From 9afca65ddd426f6a5066ce06eba089f52e07d0a1 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sun, 1 Jun 2014 01:40:11 +0300 Subject: [PATCH 1/1] Initial commit --- Changes | 4 + MANIFEST | 6 ++ Makefile.PL | 26 +++++ README | 30 ++++++ gruntmaster-gui | 37 +++++++ lib/Gruntmaster/GUI.pm | 230 +++++++++++++++++++++++++++++++++++++++++ t/Gruntmaster-GUI.t | 5 + 7 files changed, 338 insertions(+) create mode 100644 Changes create mode 100644 MANIFEST create mode 100644 Makefile.PL create mode 100644 README create mode 100755 gruntmaster-gui create mode 100644 lib/Gruntmaster/GUI.pm create mode 100644 t/Gruntmaster-GUI.t diff --git a/Changes b/Changes new file mode 100644 index 0000000..98e51ea --- /dev/null +++ b/Changes @@ -0,0 +1,4 @@ +Revision history for Perl extension Gruntmaster::GUI. + +5999.000_001 2014-06-01T01:40+03:00 + - Initial release diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..43c3eb1 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,6 @@ +Changes +Makefile.PL +MANIFEST +README +t/Gruntmaster-GUI.t +lib/Gruntmaster/GUI.pm diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..51ef4d9 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,26 @@ +use 5.014000; +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'Gruntmaster::GUI', + VERSION_FROM => 'lib/Gruntmaster/GUI.pm', + ABSTRACT_FROM => 'lib/Gruntmaster/GUI.pm', + AUTHOR => 'Marius Gavrilescu ', + EXE_FILES => [qw/gruntmaster-gui/], + MIN_PERL_VERSION => '5.14.0', + LICENSE => 'perl', + SIGN => 1, + PREREQ_PM => { + qw/Gruntmaster::Data 0 + Sub::Name 0 + Try::Tiny 0 + Wx 0 + Wx::Event 0/, + }, + META_MERGE => { + dynamic_config => 0, + resources => { + repository => 'https://git.ieval.ro/?p=gruntmaster-gui.git', + } + } +); diff --git a/README b/README new file mode 100644 index 0000000..07be6bb --- /dev/null +++ b/README @@ -0,0 +1,30 @@ +Gruntmaster-GUI version 5999.000_001 +==================================== + +INSTALLATION + +To install this module type the following: + + perl Makefile.PL + make + make test + make install + +DEPENDENCIES + +This module requires these other modules and libraries: + +* Gruntmaster::Data +* Sub::Name +* Try::Tiny +* Wx + +COPYRIGHT AND LICENCE + +Copyright (C) 2014 by Marius Gavrilescu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.18.2 or, +at your option, any later version of Perl 5 you may have available. + + diff --git a/gruntmaster-gui b/gruntmaster-gui new file mode 100755 index 0000000..3284301 --- /dev/null +++ b/gruntmaster-gui @@ -0,0 +1,37 @@ +#!/usr/bin/perl -w +use v5.14; + +use Gruntmaster::GUI; + +Gruntmaster::GUI->new->MainLoop; + +__END__ + +=head1 NAME + +gruntmaster-gui - Gruntmaster 6000 Online Judge -- GUI database editor + +=head1 SYNOPSIS + + gruntmaster-gui + +=head1 DESCRIPTION + +gruntmaster-gui is a GUI viewer and editor for the Gruntmaster 6000 database. + +CLI tools with the same purpose are distributed with Gruntmaster::Data. See L, L, L. + +=head1 AUTHOR + +Marius Gavrilescu Emarius@ieval.roE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2014 by Marius Gavrilescu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.18.2 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/lib/Gruntmaster/GUI.pm b/lib/Gruntmaster/GUI.pm new file mode 100644 index 0000000..60cac04 --- /dev/null +++ b/lib/Gruntmaster/GUI.pm @@ -0,0 +1,230 @@ +package Gruntmaster::GUI; + +use 5.014000; +use strict; +use warnings; +use parent qw/Wx::App/; +our $VERSION = '5999.000_001'; +$VERSION = eval $VERSION; + +use constant FORMATS => [qw/C CPP GO HASKELL JAVA PASCAL PERL PYTHON/]; + +use Gruntmaster::Data; +use Sub::Name qw/subname/; +use Try::Tiny; +use Wx qw/wxVERTICAL wxHORIZONTAL wxEXPAND wxALL wxTOP wxBOTTOM wxTE_MULTILINE wxTE_PROCESS_ENTER wxDefaultPosition wxDefaultSize wxLC_ICON/; +use Wx::Event qw/EVT_BUTTON EVT_COMBOBOX EVT_LISTBOX EVT_TEXT EVT_TEXT_ENTER/; + +my ($db, $pb, $ct); +my ($problem_list, $contest_list, $job_list); +my (%problem, %contest); + +sub problem_enable_relevant{ + $problem{genformat}->Enable($problem{generator}->GetValue eq 'Run'); + $problem{gensource}->Enable($problem{generator}->GetValue eq 'Run'); + $problem{verformat}->Enable($problem{runner}->GetValue ne 'File'); + $problem{versource}->Enable($problem{runner}->GetValue ne 'File'); + $problem{tests}->Enable($problem{runner}->GetValue eq 'File'); +} + +sub select_problem { + my $id = $problem_list->GetClientData($problem_list->GetSelection); + $pb = $db->problem($id); + $problem{id}->SetLabel("ID: $id"); + $problem{$_}->SetValue($pb->get_column($_) // '') for qw/name author writer owner tests timeout olimit level generator runner judge testcnt value statement genformat gensource verformat versource/; + $problem{private}->SetValue($pb->private); + problem_enable_relevant; +} + +sub select_contest { + my $id = $contest_list->GetClientData($contest_list->GetSelection); + $ct = $db->contest($id); + $contest{id}->SetLabel("ID: $id"); + $contest{$_}->SetValue($ct->get_column($_)) for qw/name start stop owner/; +} + +sub connect_or_disconnect { + my ($dsn, $button, $nb) = @_; + subname 'connect_or_disconnect', sub { + if (defined $db) { + undef $db; + $dsn->Enable; + $nb->Disable; + $button->SetLabel('Connect'); + $problem_list->Clear; + } else { + try { + $db = Gruntmaster::Data->connect($dsn->GetValue); + $db->problems->count({}); # Trigger database connection + } catch { + Wx::MessageBox("Cannot connect to database: $_"); + undef $db; + }; + return unless defined $db; + $dsn->Disable; + $nb->Enable; + $button->SetLabel('Disconnect'); + $problem_list->Append($_->name, $_->id) for $db->problems->search({}, {order_by => 'name'}); + $problem_list->GetParent->GetSizer->Layout; + $contest_list->Append($_->name, $_->id) for $db->contests->search({}, {order_by => 'name'}); + $contest_list->GetParent->GetSizer->Layout; + $problem_list->SetSelection(0); + $contest_list->SetSelection(0); + select_problem; + select_contest; + } + $button->GetParent->GetSizer->Layout; + } +} + +sub OnInit { + my $frame = Wx::Frame->new(undef, -1, 'Gruntmaster 6000', [-1, -1], [500, 700]); + my ($nb, $problems, $contests, $jobs); + + { + my $panel = Wx::Panel->new($frame); + my $subpanel = Wx::Panel->new($panel); + my $panel_sizer = Wx::BoxSizer->new(wxVERTICAL); + my $subpanel_sizer = Wx::BoxSizer->new(wxHORIZONTAL); + + my $dsn = Wx::TextCtrl->new($subpanel, -1, '', wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER); + my $db_button = Wx::Button->new($subpanel, -1, 'Connect'); + $nb = Wx::Notebook->new($panel); + $nb->Disable; + EVT_BUTTON($db_button, $db_button, connect_or_disconnect $dsn, $db_button, $nb); + EVT_TEXT_ENTER($dsn, $dsn, connect_or_disconnect $dsn, $db_button, $nb); + + $panel_sizer->Add($subpanel, 0, wxEXPAND | wxALL, 10); + $panel_sizer->Add($nb, 1, wxEXPAND | wxALL, 10); + $subpanel_sizer->Add($dsn, 1, wxEXPAND | wxALL, 10); + $subpanel_sizer->Add($db_button, 0, wxEXPAND | wxALL, 10); + $panel->SetSizer($panel_sizer); + $subpanel->SetSizer($subpanel_sizer); + } + + sub label { + my ($parent, $sizer, $content) = @_; + my $temp = Wx::StaticText->new($parent, -1, $content); + $sizer->Add($temp, wxEXPAND); + $temp + } + sub formsize { + my ($sizer, $item) = @_; + $sizer->Add($item, 0, wxEXPAND | wxTOP | wxBOTTOM, 5); + } + + { + $problems = Wx::Panel->new($nb); + my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); + $problem_list = Wx::ListBox->new($problems); + EVT_LISTBOX($problem_list, $problem_list, \&select_problem); + my $form1 = Wx::ScrolledWindow->new($problems); + my $form2 = Wx::ScrolledWindow->new($problems); + my $f1sizer = Wx::BoxSizer->new(wxVERTICAL); + my $f2sizer = Wx::BoxSizer->new(wxVERTICAL); + $problem{id} = label $form1, $f1sizer, 'ID'; + my %id_to_label = (timeout => 'Time limit', olimit => 'Output limit'); + for (qw/name author writer owner tests timeout olimit/) { + label $form1, $f1sizer, $id_to_label{$_} // ucfirst; + formsize $f1sizer, $problem{$_} = Wx::TextCtrl->new($form1, -1, ''); + } + $problem{private} = Wx::CheckBox->new($form2, -1, 'Private'); + $f2sizer->Add($problem{private}); + label $form2, $f2sizer, 'Level'; + formsize $f2sizer, $problem{level} = Wx::ComboBox->new($form2); + $problem{level}->Append([qw/beginner easy medium hard/]); + label $form2, $f2sizer, 'Generator'; + formsize $f2sizer, $problem{generator} = Wx::ComboBox->new($form2); + $problem{generator}->Append([qw/File Run Undef/]); + label $form2, $f2sizer, 'Runner'; + formsize $f2sizer, $problem{runner} = Wx::ComboBox->new($form2); + $problem{runner}->Append([qw/File Verifier Interactive/]); + label $form2, $f2sizer, 'Judge'; + formsize $f2sizer, $problem{judge} = Wx::ComboBox->new($form2); + $problem{judge}->Append([qw/Absolute Points/]); + label $form2, $f2sizer, 'Test count'; + formsize $f2sizer, $problem{testcnt} = Wx::SpinCtrl->new($form2); + label $form2, $f2sizer, 'Value'; + formsize $f2sizer, $problem{value} = Wx::SpinCtrl->new($form2); + label $form1, $f1sizer, 'Statement'; + formsize $f1sizer, $problem{statement} = Wx::TextCtrl->new($form1, -1, '', wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); + #$f1sizer->Add($problem{statement}, 2, wxEXPAND | wxTOP | wxBOTTOM, 5); + label $form2, $f2sizer, 'Generator program'; + formsize $f2sizer, $problem{genformat} = Wx::ComboBox->new($form2); + $problem{genformat}->Append(FORMATS); + formsize $f2sizer, $problem{gensource} = Wx::TextCtrl->new($form2, -1, '', wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); + label $form2, $f2sizer, 'Verifier program'; + formsize $f2sizer, $problem{verformat} = Wx::ComboBox->new($form2); + $problem{verformat}->Append(FORMATS); + formsize $f2sizer, $problem{versource} = Wx::TextCtrl->new($form2, -1, '', wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); + EVT_COMBOBOX($problem{$_}, $problem{$_}, \&problem_enable_relevant) for qw/generator runner/; + EVT_TEXT($problem{$_}, $problem{$_}, \&problem_enable_relevant) for qw/generator runner/; + + $sizer->Add($problem_list, 0, wxEXPAND | wxALL, 10); + $sizer->Add($form1, 1, wxALL, 10); + $sizer->Add($form2, 1, wxALL, 10); + $form1->SetSizer($f1sizer); + $form2->SetSizer($f2sizer); + $problems->SetSizer($sizer); + } + + { + $contests = Wx::Panel->new($nb); + my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); + $contest_list = Wx::ListBox->new($contests); + EVT_LISTBOX($contest_list, $contest_list, \&select_contest); + my $form = Wx::ScrolledWindow->new($contests); + my $fsizer = Wx::BoxSizer->new(wxVERTICAL); + $contest{id} = label $form, $fsizer, 'ID'; + label $form, $fsizer, 'Name'; + formsize $fsizer, $contest{name} = Wx::TextCtrl->new($form, -1, ''); + label $form, $fsizer, 'Start'; + formsize $fsizer, $contest{start} = Wx::TextCtrl->new($form, -1, ''); + label $form, $fsizer, 'Stop'; + formsize $fsizer, $contest{stop} = Wx::TextCtrl->new($form, -1, ''); + label $form, $fsizer, 'owner'; + formsize $fsizer, $contest{owner} = Wx::TextCtrl->new($form, -1, ''); + + $sizer->Add($contest_list, 0, wxEXPAND | wxALL, 10); + $sizer->Add($form, 1, wxALL, 10); + $form->SetSizer($fsizer); + $contests->SetSizer($sizer); + } + + $nb->AddPage($problems, 'Problems'); + $nb->AddPage($contests, 'Contests'); + $frame->Show(1) +} + +1; +__END__ + +=head1 NAME + +Gruntmaster::GUI - Gruntmaster 6000 Online Judge -- GUI database editor + +=head1 SYNOPSIS + + use Gruntmaster::GUI; + Gruntmaster::GUI->new->MainLoop; + +=head1 DESCRIPTION + +Gruntmaster::GUI is a GUI viewer and editor for the Gruntmaster 6000 database. + +CLI tools with the same purpose are distributed with Gruntmaster::Data. See L, L, L. + +=head1 AUTHOR + +Marius Gavrilescu Emarius@ieval.roE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2014 by Marius Gavrilescu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.18.2 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/t/Gruntmaster-GUI.t b/t/Gruntmaster-GUI.t new file mode 100644 index 0000000..a6dcd68 --- /dev/null +++ b/t/Gruntmaster-GUI.t @@ -0,0 +1,5 @@ +#!/usr/bin/perl -w +use v5.14; + +use Test::More tests => 1; +BEGIN { use_ok('Gruntmaster::GUI') }; -- 2.30.2