From: Marius Gavrilescu Date: Fri, 28 Feb 2014 10:10:51 +0000 (+0200) Subject: Merge branch 'master' into mindcoding X-Git-Url: http://git.ieval.ro/?a=commitdiff_plain;h=fd7ea993642eacb1f0a6beb2a2a8464fcf8480c4;hp=4fffff7c5a0669e2860cf1428f8f4c4f9fddabea;p=gruntmaster-page.git Merge branch 'master' into mindcoding Conflicts: css/custom.css lib/Gruntmaster/Page/St.pm tmpl/log.en --- diff --git a/MANIFEST b/MANIFEST index 80ce6d4..61687ff 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,17 +1,51 @@ +a/account.en +a/account.en.title +a/index.en +a/index.en.title +app.psgi Changes -gruntmaster-genallpages -gruntmaster-genpage -lib/Gruntmaster/Page/Common.pm -lib/Gruntmaster/Page/Ct/Entry.pm -lib/Gruntmaster/Page/Ct.pm -lib/Gruntmaster/Page/Index.pm -lib/Gruntmaster/Page/Log/Entry.pm +css/custom.css +css/orig/cerulean.css +css/orig/cosmo.css +css/orig/cyborg.css +css/orig/slate.css +css/themes/cerulean.css +css/themes/cosmo.css +css/themes/cyborg.css +css/themes/slate.css +js/00-zepto.js +js/10-bootstrap-dropdown.js +js/90-custom.js +js/90-form.js +lib/Gruntmaster/Page/Base.pm +lib/Gruntmaster/Page/CSS.pm +lib/Gruntmaster/Page/Generic.pm +lib/Gruntmaster/Page/JS.pm lib/Gruntmaster/Page/Log.pm +lib/Gruntmaster/Page/Passwd.pm lib/Gruntmaster/Page/Pb/Entry.pm -lib/Gruntmaster/Page/Pb.pm -lib/Gruntmaster/Page.pm +lib/Gruntmaster/Page/Register.pm +lib/Gruntmaster/Page/Src.pm +lib/Gruntmaster/Page/St.pm lib/Gruntmaster/Page/Submit.pm +lib/Plack/App/Gruntmaster.pm +log.conf Makefile.PL MANIFEST README +run +static/gm.css t/Gruntmaster-Page.t +t/mech.t +tmpl/ct.en +tmpl/ct_entry.en +tmpl/footer.en +tmpl/header.en +tmpl/log.en +tmpl/log_entry.en +tmpl/pb.en +tmpl/pb_entry.en +tmpl/st.en +tmpl/us.en +tmpl/us_entry.en + diff --git a/Makefile.PL b/Makefile.PL index dfb2291..0c47a00 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -2,25 +2,43 @@ use 5.014000; use ExtUtils::MakeMaker; WriteMakefile( - NAME => 'Gruntmaster::Page', - VERSION_FROM => 'lib/Gruntmaster/Page.pm', - ABSTRACT_FROM => 'lib/Gruntmaster/Page.pm', - AUTHOR => 'Marius Gavrilescu ', - MIN_PERL_VERSION => '5.14.0', - LICENSE => 'perl', - SIGN => 1, - PREREQ_PM => { - qw/Fcntl 0 - File::Basename 0 - IO::File 0 - POSIX 0 + NAME => 'Gruntmaster::Page', + VERSION_FROM => 'lib/Plack/App/Gruntmaster.pm', + ABSTRACT_FROM => 'lib/Plack/App/Gruntmaster.pm', + AUTHOR => 'Marius Gavrilescu ', + MIN_PERL_VERSION => '5.14.0', + LICENSE => 'perl', + SIGN => 1, + BUILD_REQUIRES => { + qw/Test::More 0 + Test::WWW::Mechanize::PSGI 0/, + }, + PREREQ_PM => { + qw/Carp 0 + Digest::SHA 0 + List::Util 0 + POSIX 0 + constant 0 + feature 0 + parent 0 + strict 0 + warnings 0 - File::Slurp 0 - HTML::Template::Compiled 0 - IO::Compress::Gzip 0 - YAML::Any 0/, - }, - META_MERGE => { - dynamic_config => 0, - } -); + Apache2::Authen::Passphrase 0 + Apache2::AuthzCaps 0 + CSS::Minifier::XS 0 + File::Slurp 0 + Gruntmaster::Data 0 + HTML::Template::Compiled 0 + HTTP::Negotiate 0 + JavaScript::Minifier::XS 0 + JSON 0 + Log::Log4perl 0 + LWP::UserAgent 0 + Plack::Builder 0 + Plack::Request 0/, + }, + META_MERGE => { + dynamic_config => 0, + } +) diff --git a/css/custom.css b/css/custom.css index 9bc0cbd..1e5d955 100644 --- a/css/custom.css +++ b/css/custom.css @@ -51,3 +51,7 @@ a.dropdown-toggle{ #sponsors a.logo{ margin-bottom: 1em; } + +.table-fixed{ + table-layout: fixed; +} diff --git a/lib/Gruntmaster/Page/Base.pm b/lib/Gruntmaster/Page/Base.pm index 9e2d030..84d7451 100644 --- a/lib/Gruntmaster/Page/Base.pm +++ b/lib/Gruntmaster/Page/Base.pm @@ -3,6 +3,7 @@ package Gruntmaster::Page::Base; use 5.014000; use strict; use warnings; +our $VERSION = '0.001'; use File::Slurp qw/read_file/; use HTML::Template::Compiled; @@ -34,18 +35,27 @@ use POSIX (); use Gruntmaster::Data (); use List::Util (); use LWP::UserAgent; +use Plack::Request (); +use feature (); my $ua = LWP::UserAgent->new; my %templates; -sub import { - my $caller = caller; - my ($self, $name, $title) = @_; +use Carp qw/cluck/; + +sub import_to { + my ($self, $caller, $name, $title) = @_; + strict->import; + feature->import(':5.14'); + warnings->import; + File::Slurp->export_to_level(1, $caller, qw/read_file/); Gruntmaster::Data->export_to_level(1, $caller); List::Util->export_to_level(1, $caller, qw/sum/); no strict 'refs'; + *{"${caller}::ISA"} = [__PACKAGE__]; + *{"${caller}::VERSION"} = $VERSION; *{"${caller}::strftime"} = \&POSIX::strftime; *{"${caller}::debug"} = sub { local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 1; @@ -65,12 +75,18 @@ sub import { } } +sub import { + return unless $_[0] eq __PACKAGE__; + splice @_, 1, 0, scalar caller; + goto &import_to +} + ################################################## sub generate{ my ($self, $lang, @args) = @_; - my $htc = HTML::Template::Compiled->new(scalarref => \$templates{$self}{$lang}, default_escape => 'HTML',); + my $htc = HTML::Template::Compiled->new(scalarref => \$templates{$self}{$lang}, default_escape => 'HTML', use_perl => 1); $self->_generate($htc, $lang, @args); my $out = $htc->output; utf8::downgrade($out); @@ -80,11 +96,12 @@ sub generate{ sub _generate {} -sub vary {} +sub vary { '' } sub max_age { 60 } sub variants { + return [] unless exists $templates{$_[0]}; [ map { [ $_, 1, 'text/html', undef, undef, $_, undef ]} keys $templates{$_[0]} ] } diff --git a/lib/Gruntmaster/Page/CSS.pm b/lib/Gruntmaster/Page/CSS.pm index 2553ab6..912e948 100644 --- a/lib/Gruntmaster/Page/CSS.pm +++ b/lib/Gruntmaster/Page/CSS.pm @@ -1,13 +1,6 @@ package Gruntmaster::Page::CSS; -use 5.014000; -use strict; -use warnings; use Gruntmaster::Page::Base; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - -use File::Slurp qw/read_file/; use CSS::Minifier::XS qw/minify/; sub generate{ @@ -19,6 +12,4 @@ sub generate{ [200, ['Content-Type' => 'text/css', 'Cache-Control' => 'public, max-age=604800', 'X-Forever' => 1], [minify $css] ] } -sub variants{ [[css => 1, 'text/css', undef, undef, undef, undef]] } - 1 diff --git a/lib/Gruntmaster/Page/Ct.pm b/lib/Gruntmaster/Page/Ct.pm deleted file mode 100644 index a21bf77..0000000 --- a/lib/Gruntmaster/Page/Ct.pm +++ /dev/null @@ -1,33 +0,0 @@ -package Gruntmaster::Page::Ct; - -use 5.014000; -use strict; -use warnings; -use Gruntmaster::Page::Base ct => 'Contests'; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - -sub _generate{ - my ($self, $htc, $lang, $env) = @_; - debug $env => "language is '$lang'"; - - my (@running, @pending, @finished); - for (sort {contest_start $a <=> contest_start $b}contests) { - my $ct = { id => $_, - name => contest_name, - start => strftime ('%c', localtime contest_start), - end => strftime ('%c', localtime contest_end), - owner => contest_owner }; - - my $time = time; - push @pending, $ct if time < contest_start; - push @running, $ct if time >= contest_start && time < contest_end; - push @finished, $ct if time > contest_end; - } - - $htc->param(running => \@running) if @running; - $htc->param(pending => \@pending) if @pending; - $htc->param(finished => \@finished) if @finished; -} - -1 diff --git a/lib/Gruntmaster/Page/Ct/Entry.pm b/lib/Gruntmaster/Page/Ct/Entry.pm deleted file mode 100644 index acc076e..0000000 --- a/lib/Gruntmaster/Page/Ct/Entry.pm +++ /dev/null @@ -1,21 +0,0 @@ -package Gruntmaster::Page::Ct::Entry; - -use 5.014000; -use strict; -use warnings; -use Gruntmaster::Page::Base ct_entry => ''; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - -sub _generate{ - my ($self, $htc, $lang, $env, $id) = @_; - debug $env => "language is '$lang' and id is '$id'"; - - $htc->param(id => $id); - $htc->param(name => contest_name $id); - $htc->param(start => strftime '%c', localtime contest_start $id); - $htc->param(end => strftime '%c', localtime contest_end $id); - $htc->param(started => time >= contest_start $id); -} - -1 diff --git a/lib/Gruntmaster/Page/Generic.pm b/lib/Gruntmaster/Page/Generic.pm new file mode 100644 index 0000000..3fdd47c --- /dev/null +++ b/lib/Gruntmaster/Page/Generic.pm @@ -0,0 +1,128 @@ +package Gruntmaster::Page::Generic; + +use 5.014000; +use strict; +use warnings; +our $VERSION = '0.001'; + +use Gruntmaster::Data; +use Gruntmaster::Page::Base; +use JSON qw/encode_json decode_json/; + +sub hgetall { + my $hash = shift; + my $cp = $Gruntmaster::Data::contest ? "contest.$Gruntmaster::Data::contest." : ''; + map { { id => $_, HGETALL "$cp$hash.$_" } } SMEMBERS "$cp$hash" +} + +sub putsym { + my ($key, $value) = @_; + no strict 'refs'; + *{"$key"} = $value; +} + +sub makepkg { + my ($pkg, $id, $title) = @_; + my $fn = $pkg =~ s,::,/,gr; + return if $INC{"$fn.pm"}; + $INC{"$fn.pm"} = 1; + Gruntmaster::Page::Base->import_to($pkg, $id, $title); + 1 +} + +sub list { + my ($thing, $lang, $env, $ct) = @_; + my %thing = %$thing; + undef $ct unless $thing{contest}; + debug $env => "Contest is $ct"; + local $Gruntmaster::Data::contest = $ct if $ct; + my @thing = hgetall $thing{hash}; + @thing = map { $thing{mangle}->(); $_ } @thing if exists $thing{mangle}; + @thing = grep { $thing{choose}->() } @thing if exists $thing{choose}; + @thing = sort { $thing{sortby}->() } @thing if exists $thing{sortby}; + my %params; + $thing{group} //= sub { $thing{id} }; + for (@thing) { + my $group = $thing{group}->(); + $params{$group} //= []; + push $params{$group}, $_ + } + wantarray ? %params : \%params +} + +sub entry { + my ($thing, $lang, $env, $id, $ct) = @_; + my %thing = %$thing; + ($id, $ct) = ($ct, $id) if $thing{contest}; + local $Gruntmaster::Data::contest = $ct if $ct; + debug $env => "Hash is $thing{hash} and id is $id"; + my %params = HGETALL "$thing{hash}.$id"; + $thing{mangle}->(local $_ = \%params) if exists $thing{mangle}; + wantarray ? %params : \%params +} + +sub headers ($) { ['Content-Type' => 'application/json', 'Cache-Control' => 'max-age=' . $_[0]->max_age] } + +sub create_thing { + my %thing = @_; + my $ucid = ucfirst $thing{id}; + my $pkg = "Gruntmaster::Page::$ucid"; + + putsym "${pkg}::_generate", sub { $_[1]->param(list \%thing, @_[2..$#_]) } if makepkg $pkg, @thing{qw/id title/}; + putsym "${pkg}::Entry::_generate", sub { $_[1]->param(entry \%thing, @_[2..$#_]) } if makepkg "${pkg}::Entry", "$thing{id}_entry", ''; + putsym "${pkg}::Read::generate", sub { [200, headers shift, [encode_json list \%thing, @_]] } if makepkg "${pkg}::Read"; + putsym "${pkg}::Entry::Read::generate", sub { [200, headers shift, [encode_json entry \%thing, @_]] } if makepkg "${pkg}::Entry::Read"; +} + +sub params; +sub contest; +sub choose (&); +sub sortby (&); +sub group (&); +sub mangle (&); + +sub thing (&){ + my %thing; + no strict 'refs'; + local *{"params"} = sub { @thing{qw/id hash title/} = @_ }; + local *{"choose"} = sub { $thing{choose} = shift }; + local *{"sortby"} = sub { $thing{sortby} = shift }; + local *{"mangle"} = sub { $thing{mangle} = shift }; + local *{"group"} = sub { $thing{group} = shift }; + local *{"contest"} = sub { $thing{contest} = 1 }; + use strict 'refs'; + + shift->(); + create_thing %thing +} + +################################################## + +thing { + params qw/us user Users/; + choose { $_->{name} =~ /\w/ }; + sortby { lc $a->{name} cmp lc $b->{name} }; +}; + +thing { + params qw/pb problem Problems/; + contest; + sortby { $a->{name} cmp $b->{name} }; + group { $_->{level} }; + mangle { $_->{owner_name} = do { local $Gruntmaster::Data::contest; user_name $_->{owner} } } +}; + +thing { + params qw/ct contest Contests/; + sortby { $a->{start} <=> $b->{start} }; + group { time < $_->{start} ? 'pending' : time > $_->{end} ? 'finished' : 'running' }; + mangle { $_->{started} = time >= $_->{start}; $_->{owner_name} = do { local $Gruntmaster::Data::contest; user_name $_->{owner} } }; +}; + +thing { + params qw/log job/, 'Job log'; + contest; + mangle { $_->{results} &&= decode_json $_->{results}; $_->{user_name} = do { local $Gruntmaster::Data::contest; user_name $_->{user} } } +}; + +1 diff --git a/lib/Gruntmaster/Page/JS.pm b/lib/Gruntmaster/Page/JS.pm index b8ddafb..f51000e 100644 --- a/lib/Gruntmaster/Page/JS.pm +++ b/lib/Gruntmaster/Page/JS.pm @@ -1,13 +1,6 @@ package Gruntmaster::Page::JS; -use 5.014000; -use strict; -use warnings; use Gruntmaster::Page::Base; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - -use File::Slurp qw/read_file/; use JavaScript::Minifier::XS qw/minify/; sub generate{ @@ -18,6 +11,4 @@ sub generate{ [200, ['Content-Type' => 'application/javascript', 'Cache-Control' => 'public, max-age=604800', 'X-Forever' => 1], [minify $js] ] } -sub variants{ [[js => 1, 'application/javascript', undef, undef, undef, undef]] } - 1 diff --git a/lib/Gruntmaster/Page/Log.pm b/lib/Gruntmaster/Page/Log.pm index 68f45fd..f63f832 100644 --- a/lib/Gruntmaster/Page/Log.pm +++ b/lib/Gruntmaster/Page/Log.pm @@ -1,11 +1,6 @@ package Gruntmaster::Page::Log; -use 5.014000; -use strict; -use warnings; use Gruntmaster::Page::Base log => 'Job log'; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; use constant PAGE_SIZE => 10; @@ -24,6 +19,7 @@ sub _generate{ date => (job_date() ? strftime ('%c' => localtime job_date) : '?'), extension => job_extension, name => problem_name job_problem, + user_name => do { local $Gruntmaster::Data::contest; user_name job_user }, problem => job_problem, result => job_result, result_text => job_result_text, diff --git a/lib/Gruntmaster/Page/Log/Entry.pm b/lib/Gruntmaster/Page/Log/Entry.pm deleted file mode 100644 index 57591b5..0000000 --- a/lib/Gruntmaster/Page/Log/Entry.pm +++ /dev/null @@ -1,29 +0,0 @@ -package Gruntmaster::Page::Log::Entry; - -use 5.014000; -use strict; -use warnings; -use Gruntmaster::Page::Base log_entry => 'Job '; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - -sub _generate{ - my ($self, $htc, $lang, $env, $ct, $id) = @_; - debug $env => "language is '$lang', contest is '$ct' and id is '$id'"; - local $Gruntmaster::Data::contest = $ct if $ct; - - my @tests = (); - - eval { - @tests = map { - $_->{time} = sprintf "%.4fs", $_->{time}; - $_ - } @{job_results $id}; - }; - - $htc->param(id => $id); - $htc->param(tests => \@tests); - $htc->param(errors => job_errors $id) -} - -1 diff --git a/lib/Gruntmaster/Page/Passwd.pm b/lib/Gruntmaster/Page/Passwd.pm index 86689ac..3a7522e 100644 --- a/lib/Gruntmaster/Page/Passwd.pm +++ b/lib/Gruntmaster/Page/Passwd.pm @@ -1,14 +1,7 @@ package Gruntmaster::Page::Passwd; -use 5.014000; -use strict; -use warnings; use Gruntmaster::Page::Base; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - use Apache2::Authen::Passphrase qw/pwcheck pwset/; -use Plack::Request; sub generate{ my ($self, $format, $env) = @_; @@ -22,6 +15,4 @@ sub generate{ reply 'Password changed successfully'; } -sub variants{ [[reply => 1, undef, undef, undef, undef, undef]] } - 1 diff --git a/lib/Gruntmaster/Page/Pb.pm b/lib/Gruntmaster/Page/Pb.pm deleted file mode 100644 index ba78869..0000000 --- a/lib/Gruntmaster/Page/Pb.pm +++ /dev/null @@ -1,27 +0,0 @@ -package Gruntmaster::Page::Pb; - -use 5.014000; -use strict; -use warnings; -use Gruntmaster::Page::Base pb => 'Problems'; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - -sub _generate{ - my ($self, $htc, $lang, $env, $ct) = @_; - debug $env => "language is '$lang' and contest is '$ct'"; - local $Gruntmaster::Data::contest = $ct if $ct; - - my @problems = sort { $b->{name} cmp $a->{name} } map +{ - id => $_, - name => problem_name, - level => problem_level}, problems; - - for my $d (qw/beginner easy medium advanced hard/) { - $htc->param($d => [grep {$_->{level} and $_->{level} eq $d} @problems]); - } - $htc->param(levels => grep { $_->{level} } @problems); - $htc->param(problems => \@problems); -} - -1 diff --git a/lib/Gruntmaster/Page/Pb/Entry.pm b/lib/Gruntmaster/Page/Pb/Entry.pm index 5dbeb92..9f3fc6b 100644 --- a/lib/Gruntmaster/Page/Pb/Entry.pm +++ b/lib/Gruntmaster/Page/Pb/Entry.pm @@ -1,11 +1,6 @@ package Gruntmaster::Page::Pb::Entry; -use 5.014000; -use strict; -use warnings; use Gruntmaster::Page::Base pb_entry => ''; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; use constant FORMATS => [qw/C CPP JAVA PASCAL PERL PYTHON/]; diff --git a/lib/Gruntmaster/Page/Register.pm b/lib/Gruntmaster/Page/Register.pm index dcb9451..be1d4be 100644 --- a/lib/Gruntmaster/Page/Register.pm +++ b/lib/Gruntmaster/Page/Register.pm @@ -1,14 +1,7 @@ package Gruntmaster::Page::Register; -use 5.014000; -use strict; -use warnings; use Gruntmaster::Page::Base; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - use Apache2::Authen::Passphrase qw/pwcheck pwset USER_REGEX/; -use Plack::Request; sub generate{ my ($self, $format, $env) = @_; @@ -27,6 +20,4 @@ sub generate{ reply 'Registered successfully'; } -sub variants{ [[reply => 1, undef, undef, undef, undef, undef]] } - 1 diff --git a/lib/Gruntmaster/Page/Src.pm b/lib/Gruntmaster/Page/Src.pm index 8e51d8b..8f9ab1b 100644 --- a/lib/Gruntmaster/Page/Src.pm +++ b/lib/Gruntmaster/Page/Src.pm @@ -1,11 +1,6 @@ package Gruntmaster::Page::Src; -use 5.014000; -use strict; -use warnings; use Gruntmaster::Page::Base; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; use constant CONTENT_TYPES => +{ c => 'text/x-csrc', @@ -25,6 +20,4 @@ sub generate{ [200, ['Content-Type' => CONTENT_TYPES->{$ext}, 'Cache-Control' => 'max-age=604800', 'X-Forever' => 1], [job_inmeta($job)->{files}{prog}{content}] ] } -sub variants{ [[file => 1, undef, undef, undef, undef, undef]] } - 1 diff --git a/lib/Gruntmaster/Page/St.pm b/lib/Gruntmaster/Page/St.pm index 562e467..22d6e30 100644 --- a/lib/Gruntmaster/Page/St.pm +++ b/lib/Gruntmaster/Page/St.pm @@ -1,11 +1,6 @@ package Gruntmaster::Page::St; -use 5.014000; -use strict; -use warnings; use Gruntmaster::Page::Base st => 'Standings'; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; use constant LEVEL_VALUES => { beginner => 100, @@ -27,14 +22,6 @@ sub calc_score{ int $score + 0.5 } -sub usname ($) { - local $Gruntmaster::Data::contest; - my $user = shift; - my $name = user_name $user; - "$name ($user)" -} - - sub _generate{ my ($self, $htc, $lang, $env, $ct) = @_; debug $env => "language is '$lang' and contest is '$ct'"; @@ -66,7 +53,8 @@ sub _generate{ my @st = sort { $b->{score} <=> $a->{score} or $a->{user} cmp $b->{user}} map { my $user = $_; +{ - user => usname $user, + user => $user, + name => do {local $Gruntmaster::Data::contest; user_name $user}, score => sum (values $scores{$user}), scores => [map { $scores{$user}{$_} // '-'} @problems], problems => $Gruntmaster::Data::contest, diff --git a/lib/Gruntmaster/Page/Submit.pm b/lib/Gruntmaster/Page/Submit.pm index aeffb08..ea67c2b 100644 --- a/lib/Gruntmaster/Page/Submit.pm +++ b/lib/Gruntmaster/Page/Submit.pm @@ -1,15 +1,6 @@ package Gruntmaster::Page::Submit; -use 5.014000; -use strict; -use warnings; use Gruntmaster::Page::Base; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - -use Apache2::Authen::Passphrase qw/pwcheck pwset USER_REGEX/; -use File::Slurp qw/read_file/; -use Plack::Request; use constant FORMAT_EXTENSION => { C => 'c', @@ -64,6 +55,4 @@ sub generate{ [303, [Location => $r->path =~ s,/pb/\w+/submit$,/log/,r], ['']] } -sub variants{ [[reply => 1, undef, undef, undef, undef, undef]] } - 1 diff --git a/lib/Gruntmaster/Page/Us.pm b/lib/Gruntmaster/Page/Us.pm deleted file mode 100644 index 915ee50..0000000 --- a/lib/Gruntmaster/Page/Us.pm +++ /dev/null @@ -1,19 +0,0 @@ -package Gruntmaster::Page::Us; - -use 5.014000; -use strict; -use warnings; -use Gruntmaster::Page::Base us => 'Users'; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - -sub _generate{ - my ($self, $htc, $lang, $env) = @_; - debug $env => "language is '$lang'"; - - $htc->param(users => [ sort { lc $a->{name} cmp lc $b->{name} } - map { {id => $_, name => user_name} } - grep { user_name =~ /\w/ } users ]); -} - -1 diff --git a/lib/Gruntmaster/Page/Us/Entry.pm b/lib/Gruntmaster/Page/Us/Entry.pm deleted file mode 100644 index 628f9fa..0000000 --- a/lib/Gruntmaster/Page/Us/Entry.pm +++ /dev/null @@ -1,21 +0,0 @@ -package Gruntmaster::Page::Us::Entry; - -use 5.014000; -use strict; -use warnings; -use Gruntmaster::Page::Base us_entry => ''; -our @ISA = qw/Gruntmaster::Page::Base/; -our $VERSION = '0.001'; - -sub _generate{ - my ($self, $htc, $lang, $env, $us) = @_; - debug $env => "language is '$lang', user is '$us'"; - local $_ = $us; - - $htc->param(name => user_name); - $htc->param(town => user_town); - $htc->param(university => user_university); - $htc->param(level => user_level); -} - -1 diff --git a/lib/Plack/App/Gruntmaster.pm b/lib/Plack/App/Gruntmaster.pm index a071101..f3da571 100644 --- a/lib/Plack/App/Gruntmaster.pm +++ b/lib/Plack/App/Gruntmaster.pm @@ -10,6 +10,9 @@ our $VERSION = '5999.000_001'; use File::Slurp qw/read_file/; use HTTP::Negotiate qw/choose/; use Plack::Request; +use Gruntmaster::Page::Log; +use Gruntmaster::Page::Pb::Entry; +use Gruntmaster::Page::Generic; my %handlers; @@ -58,20 +61,33 @@ BEGIN{ my $word = qr,(\w+),a; my $ct = qr,(?:\/ct/$word)?,a; + sub generic { + my ($thing, $ct, $fs) = @_; + $ct //= '', $fs //= ''; + my $pkg = ucfirst $thing; + get qr,$ct/$thing/, => $pkg; + get qr,$ct/$thing/$word$fs, => "${pkg}::Entry"; + + get qr,$ct/$thing/read, => "${pkg}::Read"; +# post qr,$ct/$thing/$word/create, => "${pkg}::Entry::Create"; + get qr,$ct/$thing/$word/read, => "${pkg}::Entry::Read"; +# post qr,$ct/$thing/$word/update, => "${pkg}::Entry::Update"; +# post qr,$ct/$thing/$word/delete, => "${pkg}::Entry::Delete"; + } + get qr,/css/$word\.css, => 'CSS'; get qr,/js\.js, => 'JS'; - get qr,/ct/, => 'Ct'; - get qr,/ct/$word/, => 'Ct::Entry'; - get qr,/us/, => 'Us'; - get qr,/us/$word, => 'Us::Entry'; + generic 'us'; + generic ct => '', '/'; + generic pb => $ct; + #generic log => $ct; get qr,$ct/log/(\d+)?, => 'Log'; get qr,$ct/log/st, => 'St'; get qr,$ct/log/job/$word, => 'Log::Entry'; + get qr,$ct/log/job/$word/read, => 'Log::Entry::Read'; get qr,$ct/log/src/$word\.$word, => 'Src'; - get qr,$ct/pb/, => 'Pb'; - get qr,$ct/pb/$word, => 'Pb::Entry'; post qr,$ct/pb/$word/submit, => 'Submit'; post qr,/action/register, => 'Register'; diff --git a/t/mech.t b/t/mech.t new file mode 100644 index 0000000..5ea673b --- /dev/null +++ b/t/mech.t @@ -0,0 +1,14 @@ +#!/usr/bin/perl -w +use strict; +use warnings; + +use Test::More tests => 5; +use Test::WWW::Mechanize::PSGI; + +my $mech = Test::WWW::Mechanize::PSGI->new(app => do 'app.psgi'); +$mech->get_ok('/'); +$mech->title_is('Gruntmaster 6000'); + +$mech->get_ok('/pb/'); +$mech->title_is('Problems'); +$mech->content_contains('Spell'); diff --git a/tmpl/ct.en b/tmpl/ct.en index ab10185..d39bbcb 100644 --- a/tmpl/ct.en +++ b/tmpl/ct.en @@ -5,9 +5,9 @@ NameStart dateEnd dateOwner - - - +<%perl __OUT__ POSIX::strftime '%c', localtime __CURRENT__->{start}; %> +<%perl __OUT__ POSIX::strftime '%c', localtime __CURRENT__->{end}; %> + () @@ -19,9 +19,9 @@ NameStart dateEnd dateOwner - - - +<%perl __OUT__ POSIX::strftime '%c', localtime __CURRENT__->{start}; %> +<%perl __OUT__ POSIX::strftime '%c', localtime __CURRENT__->{end}; %> + () @@ -33,9 +33,9 @@ NameStart dateEnd dateOwner - - - +<%perl __OUT__ POSIX::strftime '%c', localtime __CURRENT__->{start}; %> +<%perl __OUT__ POSIX::strftime '%c', localtime __CURRENT__->{end}; %> + () diff --git a/tmpl/ct_entry.en b/tmpl/ct_entry.en index 14ac48e..f95f345 100644 --- a/tmpl/ct_entry.en +++ b/tmpl/ct_entry.en @@ -1,5 +1,5 @@ -Contest start time:
-Contest end time:

+Contest start time: <%perl __OUT__ POSIX::strftime '%c', localtime __CURRENT__->{start}; %>
+Contest end time: <%perl __OUT__ POSIX::strftime '%c', localtime __CURRENT__->{end}; %>

Problems
Job log
diff --git a/tmpl/log.en b/tmpl/log.en index dc87171..de918a2 100644 --- a/tmpl/log.en +++ b/tmpl/log.en @@ -6,7 +6,7 @@ data-private
> - + () diff --git a/tmpl/log_entry.en b/tmpl/log_entry.en index 45cd405..adf6bfd 100644 --- a/tmpl/log_entry.en +++ b/tmpl/log_entry.en @@ -1,11 +1,15 @@ -Compiler output: + +

Compiler output

+ -Results: + +

Results

-
Test numberResultTime
+
<%perl __OUT__ sprintf "%.4fs", __CURRENT__->{time}; %>
+
\ No newline at end of file diff --git a/tmpl/pb.en b/tmpl/pb.en index 3a8194f..341ffbe 100644 --- a/tmpl/pb.en +++ b/tmpl/pb.en @@ -1,26 +1,39 @@ - +

Beginner

-
- -
+ + +
NameAuthorOwner +
() + +
+
+

Easy

-
- -
+ + +
NameAuthorOwner +
() + +
+
+

Medium

-
- -
+ + +
NameAuthorOwner +
() + +
+
+

Hard

-
- -
- - -
- -
+ + +
NameAuthorOwner +
() + +
diff --git a/tmpl/st.en b/tmpl/st.en index 0c9893b..4bb3f04 100644 --- a/tmpl/st.en +++ b/tmpl/st.en @@ -1,11 +1,11 @@ - -
RankUsernameTotal -
RankUsernameScore +
RankUserTotal +
RankUserScore
+
() diff --git a/tmpl/us.en b/tmpl/us.en index 174bc80..72c72c3 100644 --- a/tmpl/us.en +++ b/tmpl/us.en @@ -1,2 +1,2 @@ -
+