--- /dev/null
+package Gruntmaster::Data;
+use v5.14;
+use warnings;
+use parent qw/Exporter/;
+
+use JSON qw/encode_json decode_json/;
+
+use Redis;
+
+our $contest;
+my $redis = Redis->new;
+
+sub dynsub{
+ no strict 'refs';
+ *{$_[0]} = $_[1];
+}
+
+BEGIN {
+ for my $cmd (qw/multi exec smembers get hget hset sadd incr hmset/) {
+ dynsub uc $cmd, sub { say $cmd;exit;$redis->$cmd(@_) };
+ }
+}
+
+sub cp { defined $contest ? "contest.$contest." : '' }
+
+sub multi () { MULTI }
+sub rexec () { EXEC }
+
+sub problems () { SMEMBERS cp . 'problem' }
+sub contests () { SMEMBERS cp . 'contest' }
+sub jobcard () { GET cp . 'job' }
+
+sub job_results (_) { decode_json HGET cp . "job.$_[0]", 'results' }
+sub set_job_results ($+) { HSET cp . "job.$_[0]", 'results', encode_json $_[1] }
+sub problem_meta (_) { decode_json HGET cp . "pb.$_[0]", 'meta' }
+sub set_problem_meta ($+) { HSET cp . "pb.$_[0]", 'meta', encode_json $_[1] }
+
+sub defhash{
+ my ($name, @keys) = @_;
+ for my $key (@keys) {
+ dynsub "${name}_$key", sub (_) { HGET cp . "$name.$_[0]", $key };
+ dynsub "set_${name}_$key", sub ($$) { HSET cp . "$name.$_[0]", $key, $_[1] };
+ }
+
+ dynsub "insert_$name", sub {
+ my ($key, %values) = @_;
+ SADD cp . $name, $key or return;
+ HMSET cp . "$name.$key", %values;
+ };
+ dynsub "push_$name", sub {
+ my $nr = INCR cp . $name;
+ HMSET cp . "$name.$nr", @_;
+ };
+}
+
+defhash problem => qw/name level statement/;
+defhash contest => qw/start end name owner/;
+defhash job => qw/date file name private problem result result_text user/;
+
+our @EXPORT_OK = do {
+ no strict 'refs';
+ grep { $_ =~ /^[a-z]/ and exists &$_ } keys %{__PACKAGE__ . '::'};
+};
+
+1
use constant LANGUAGES => [ 'en' ];
use constant CONTENT_TYPES => {
- html => 'text/html; charset=UTF-8',
- txt => 'text/plain; charset=UTF-8',
+ html => 'text/html; charset=UTF-8',
+ txt => 'text/plain; charset=UTF-8',
};
sub declaregen{
- my ($generator, $regex) = @_;
- $generator = "Gruntmaster::Page::$generator";
- eval "require $generator";
- my $gensub = $generator->can('generate') or die "No such generator: $generator";
- push @generators, [$regex, $gensub];
+ my ($generator, $regex) = @_;
+ $generator = "Gruntmaster::Page::$generator";
+ eval "require $generator";
+ my $gensub = $generator->can('generate') or die "No such generator: $generator";
+ push @generators, [$regex, $gensub];
}
{
- my $component = qr'[^/]+';
- my $contest = qr,(?:ct/$component/)?,;
- declaregen Index => qr,^index$,;
- declaregen Ct => qr,^ct/index$,;
- declaregen 'Ct::Entry' => qr,^ct/$component/index$,;
- declaregen St => qr,^ct/$component/log/st$,;
- declaregen Learn => qr,^learn$,;
- declaregen Log => qr,^${contest}log/index$,;
- declaregen 'Log::Entry' => qr,^${contest}log/$component/index$,;
- declaregen Submit => qr,^${contest}submit$,;
- declaregen Pb => qr,^${contest}pb/index$,;
- declaregen 'Pb::Entry' => qr,^${contest}pb/$component/index$,;
+ my $component = qr'[^/]+';
+ my $contest = qr,(?:ct/$component/)?,;
+ declaregen Index => qr,^index$,;
+ declaregen Learn => qr,^learn$,;
+ declaregen Ct => qr,^ct/index$,;
+ declaregen 'Ct::Entry' => qr,^ct/$component/index$,;
+ declaregen St => qr,^ct/$component/log/st$,;
+ declaregen Log => qr,^${contest}log/(?:\d+|index)$,;
+ declaregen 'Log::Entry' => qr,^${contest}log/$component/index$,;
+ declaregen Submit => qr,^${contest}submit$,;
+ declaregen Pb => qr,^${contest}pb/index$,;
+ declaregen 'Pb::Entry' => qr,^${contest}pb/$component/index$,;
}
sub generate{
- my ($path) = @_;
- my ($path_noext, $ext) = $path =~ m/^(.*)\.(.*)$/;
- my $basename = fileparse $path_noext;
-
- IO::File->new(">$path_noext.var")->close unless -f "$path_noext.var";
- flock my $lockfh = IO::File->new("<$path_noext.var"), LOCK_EX;
- open my $typemap, ">$path_noext.var.new";
- say $typemap "URI: $basename\n";
- for my $gen(@generators) {
- my ($regex, $generator) = @$gen;
- next unless $path_noext =~ $regex;
+ my ($path) = @_;
+ my ($path_noext, $ext) = $path =~ m/^(.*)\.(.*)$/;
+ my $basename = fileparse $path_noext;
+
+ IO::File->new(">$path_noext.var")->close unless -f "$path_noext.var";
+ flock my $lockfh = IO::File->new("<$path_noext.var"), LOCK_EX;
+ open my $typemap, ">$path_noext.var.new";
+ say $typemap "URI: $basename\n";
+ for my $gen (@generators) {
+ my ($regex, $generator) = @$gen;
+ next unless $path_noext =~ $regex;
+ for my $lang (@{LANGUAGES()}) {
+ my $page = $generator->($path, $lang);
+ write_file "$path_noext.$lang.$ext.new", $page;
+ say $typemap "URI: $basename.$lang.$ext\nContent-Language: $lang\nContent-Type: " . CONTENT_TYPES->{$ext} . "\n";
+ gzip \$page => "$path_noext.$lang.gz.$ext.new", Minimal => 1;
+ say $typemap "URI: $basename.$lang.gz.$ext\nContent-Language: $lang\nContent-Encoding: gzip\nContent-Type: " . CONTENT_TYPES->{$ext} . "\n";
+ }
+ }
+
for my $lang (@{LANGUAGES()}) {
- my $page = $generator->($path, $lang);
- write_file "$path_noext.$lang.$ext.new", $page;
- say $typemap "URI: $basename.$lang.$ext\nContent-Language: $lang\nContent-Type: " . CONTENT_TYPES->{$ext} . "\n";
- gzip \$page => "$path_noext.$lang.gz.$ext.new", Minimal => 1;
- say $typemap "URI: $basename.$lang.gz.$ext\nContent-Language: $lang\nContent-Encoding: gzip\nContent-Type: " . CONTENT_TYPES->{$ext} . "\n";
+ rename "$path_noext.$lang.$ext.new", "$path_noext.$lang.$ext";
+ rename "$path_noext.$lang.gz.$ext.new", "$path_noext.$lang.gz.$ext";
}
- }
-
- for my $lang(@{LANGUAGES()}) {
- rename "$path_noext.$lang.$ext.new", "$path_noext.$lang.$ext";
- rename "$path_noext.$lang.gz.$ext.new", "$path_noext.$lang.gz.$ext";
- }
- rename "$path_noext.var.new", "$path_noext.var";
- close $typemap;
+ rename "$path_noext.var.new", "$path_noext.var";
+ close $typemap;
}
1;
use constant TITLE => 'Contests';
-use Fcntl qw/:flock/;
use HTML::Template::Compiled;
-use IO::File;
use POSIX qw/strftime/;
-use YAML::Any qw/LoadFile/;
use Gruntmaster::Page::Common qw/header footer/;
+use Gruntmaster::Data qw/contest_name contest_start contest_end contest_owner/;
my %templates = (
- en => <<'HTML',
-<tmpl_if runningn>
+ en => <<'HTML',
+<tmpl_if running>
<h1>Running contests</h1>
<table border>
<thead>
</table>
</tmpl_if>
-<tmpl_if pendingn>
+<tmpl_if pending>
<h1>Pending contests</h1>
<table border>
<thead>
</table>
</tmpl_if>
-<tmpl_if finishedn>
+<tmpl_if finished>
<h1>Finished contests</h1>
<table border>
<thead>
$templates{$_} .= footer $_ for keys %templates;
sub generate{
- my $template = $templates{$_[1]};
- my $htc = HTML::Template::Compiled->new(scalarref => \$template);
- IO::File->new('>ct/meta.yml')->close unless -f 'ct/meta.yml';
- flock my $metafh = IO::File->new('<ct/meta.yml'), LOCK_SH;
+ my $htc = HTML::Template::Compiled->new(scalarref => \$templates{$_[1]});
- my (@running, @pending, @finished);
- for (<ct/*/meta.yml>) {
- my $meta = LoadFile $_;
- my $id = (m,^ct/(.*)/meta.yml$,)[0];
- my $ct = { id => $id,
- name => $meta->{name},
- start => strftime ('%c', localtime $meta->{start}),
- end => strftime ('%c', localtime $meta->{end}),
- owner => $meta->{owner}};
+ my (@running, @pending, @finished);
+ for (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 < $meta->{start};
- push @running, $ct if time >= $meta->{start} && time < $meta->{end};
- push @finished, $ct if time > $meta->{end};
- }
+ 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(runningn => scalar @running);
- $htc->param(pendingn => scalar @pending);
- $htc->param(finishedn => scalar @finished);
- $htc->param(running => \@running);
- $htc->param(pending => \@pending);
- $htc->param(finished => \@finished);
- $htc->output
+ $htc->param(running => \@running);
+ $htc->param(pending => \@pending);
+ $htc->param(finished => \@finished);
+ $htc->output
}
1
our @EXPORT_OK = qw/generate/;
our $VERSION = '0.001';
-use Fcntl qw/:flock/;
+use constant TITLE => '<tmpl_var name>';
+
use HTML::Template::Compiled;
-use IO::File;
use POSIX qw/strftime/;
-use YAML::Any qw/LoadFile/;
-use File::Basename qw/fileparse/;
-use File::Slurp qw/slurp/;
use Gruntmaster::Page::Common qw/header footer/;
-
-use constant TITLE => '<tmpl_var name>';
+use Gruntmaster::Data qw/contest_name contest_start contest_end/;
my %templates = (
- en => <<'HTML',
+ en => <<'HTML',
Contest start time: <tmpl_var start><br>
Contest end time: <tmpl_var end><p>
$templates{$_} .= footer $_ for keys %templates;
sub generate{
- my ($path, $lang) = @_;
- $path = ($path =~ m,ct/(.*)/index,)[0];
- my $template = $templates{$lang};
- my $htc = HTML::Template::Compiled->new(scalarref => \$template);
- flock my $metafh = IO::File->new("<ct/$path/meta.yml"), LOCK_SH;
- my $meta = LoadFile "ct/$path/meta.yml";
-
- $htc->param(id => $path);
- $htc->param(name => $meta->{name});
- $htc->param(start => strftime '%c', localtime $meta->{start});
- $htc->param(end => strftime '%c', localtime $meta->{end});
- $htc->param(started => time >= $meta->{start});
- $htc->output
+ my ($path, $lang) = @_;
+ $path = ($path =~ m,ct/(.*)/index,)[0];
+ my $template = $templates{$lang};
+ my $htc = HTML::Template::Compiled->new(scalarref => \$template);
+
+ $htc->param(id => $path);
+ $htc->param(name => contest_name $path);
+ $htc->param(start => strftime '%c', contest_start);
+ $htc->param(end => strftime '%c', contest_end);
+ $htc->param(started => time >= contest_start);
+ $htc->output
}
1
use constant TITLE => 'Gruntmaster 6000';
-use Fcntl qw/:flock/;
use HTML::Template::Compiled;
-use IO::File;
use Gruntmaster::Page::Common qw/header footer/;
my %templates = (
$templates{$_} .= footer $_ for keys %templates;
sub generate{
- my $template = $templates{$_[1]};
- my $htc = HTML::Template::Compiled->new(scalarref => \$template);
- IO::File->new('>meta.yml')->close unless -f 'meta.yml';
- flock my $metafh = IO::File->new('<meta.yml'), LOCK_SH;
- $htc->output
+ HTML::Template::Compiled->new(scalarref => \$templates{$_[1]})->output
}
1
our @EXPORT_OK = qw/generate/;
our $VERSION = '0.001';
-use constant FORMATS => [qw/CPP/];
-use constant TITLE => 'Learn Perl';
+use constant TITLE => 'Learn';
-use Fcntl qw/:flock/;
use HTML::Template::Compiled;
-use IO::File;
-use YAML::Any qw/LoadFile/;
use Gruntmaster::Page::Common qw/header footer/;
my %templates = (
en => <<'HTML',
-Download interactive-perl-tutorial for <a href="ipt-linux">Linux</a> | <a href="ipt-windows.exe">Windows</a> | <a href="ipt-mac">Mac OS X</a>.
-<p>Get the source from <a href="http://example.org/">meta::cpan</a>
+Install interactive-perl-tutorial from your nearest CPAN mirror. Run <code>cpan App::InteractivePerlTutorial</code>.
+<p>You can also get the source from <a href="http://git.ieval.ro/?p=app-interactiveperltutorial.git">git.ieval.ro</a>
HTML
);
$templates{$_} .= footer $_ for keys %templates;
sub generate{
- my $template = $templates{$_[1]};
- my $htc = HTML::Template::Compiled->new(scalarref => \$template);
- $htc->output
+ HTML::Template::Compiled->new(scalarref => \$templates{$_[1]})->output;
}
1
our $VERSION = '0.001';
use constant TITLE => 'Job log';
+use constant PAGE_SIZE => 10;
-use Fcntl qw/:flock/;
use HTML::Template::Compiled;
-use IO::File;
use POSIX qw/strftime/;
-use YAML::Any qw/LoadFile/;
use Gruntmaster::Page::Common qw/header footer/;
+use Gruntmaster::Data qw/job_date job_file job_name job_private job_problem job_result job_result_text job_user/;
my %templates = (
- en => <<'HTML',
+ en => <<'HTML',
<table border>
<thead>
<tr><th>ID<th>Problem<th>Date<th>Size<th>User<th>Result
<tmpl_loop log><tr><td><a href="<tmpl_var id>"><tmpl_var id></a>
<td><a href="/pb/<tmpl_var problem>"><tmpl_var name></a>
<td><tmpl_var date>
-<td><a href="<tmpl_var id>/in/<tmpl_var filename>"<tmpl_if private> data-private</tmpl_if>><tmpl_var size></a>
+<td><tmpl_var size></a>
<td><tmpl_var user><td class="r<tmpl_var result>"><tmpl_var result_text>
</tmpl_loop>
</table>
$templates{$_} .= footer $_ for keys %templates;
sub generate{
- my ($path, $lang) = @_;
- $path =~ s,/index\.html$,,;
- my $template = $templates{$lang};
- my $htc = HTML::Template::Compiled->new(scalarref => \$template);
- IO::File->new(">$path/meta.yml")->close unless -f "$path/meta.yml";
- flock my $metafh = IO::File->new("<$path/meta.yml"), LOCK_SH;
- my $meta = LoadFile "$path/meta.yml";
- my @log = sort { $b->{id} <=> $a->{id} } map {
- my $meta = LoadFile "$path/$_/meta.yml";
- +{ id => $_,
- date => (exists $meta->{date} ? strftime ('%c' => localtime $meta->{date}) : '?'),
- user => $meta->{user},
- result => $meta->{result},
- name => $meta->{name},
- problem => $meta->{problem},
- filename => $meta->{files}{prog}{name},
- (defined $meta->{private} ? (private => $meta->{private}) : ()),
- size => sprintf ("%.2f KiB", (-s "$path/$_/in/" . $meta->{files}{prog}{name}) / 1024),
- result_text => $meta->{result_text}} } 1 .. $meta->{last};
- $htc->param(log => \@log);
- $htc->output
+ $_[0] =~ m,^(?:ct/([^/]+)/)?log/(\w+)\.html$,;
+ local $Gruntmaster::Data::contest = $1;
+ my $page = $2 eq 'index' ? 0 : $2;
+
+ my $htc = HTML::Template::Compiled->new(scalarref => \$templates{$_[1]});
+ my @log = sort { $b->{id} <=> $a->{id} } map +{
+ id => $_,
+ (job_private() ? (private => job_private) : ()),
+ date => (job_date() ? strftime ('%c' => localtime job_date) : '?'),
+ name => job_name,
+ problem => job_problem,
+ result => job_result,
+ result_text => job_result_text,
+ size => sprintf ("%.2f KiB", (length job_file) / 1024),
+ user => job_user}, ($page - 1) * PAGE_SIZE + 1 .. $page * PAGE_SIZE;
+ $htc->param(log => \@log);
+ $htc->output
}
1
use constant TITLE => 'Job <tmpl_var id>';
-use Fcntl qw/:flock/;
use HTML::Template::Compiled;
-use IO::File;
use POSIX qw/strftime/;
-use YAML::Any qw/LoadFile/;
use Gruntmaster::Page::Common qw/header footer/;
+use Gruntmaster::Data qw/job_results/;
my %templates = (
- en => <<'HTML',
+ en => <<'HTML',
<table border>
<thead>
<tr><th>Test number<th>Result<th>Time
$templates{$_} .= footer $_ for keys %templates;
sub generate{
- my ($path, $lang) = @_;
- my $id = ($path =~ m,log/(.*)/index,)[0];
- $path =~ s,/index\.html,,;
- my $template = $templates{$lang};
-
- my $htc = HTML::Template::Compiled->new(scalarref => \$template);
- flock my $metafh = IO::File->new("<$path/meta.yml"), LOCK_SH;
- my $meta = LoadFile "$path/meta.yml";
-
- my @tests = map {
- $_->{time} = sprintf "%.4fs", $_->{time};
- $_
- } @{$meta->{results}};
-
- $htc->param(id => $id);
- $htc->param(tests => \@tests);
- $htc->output
+ $_[0] =~ m,^(?:ct/([^/]+)/)?log/([^/]+)/index\.html$,;
+ local $Gruntmaster::Data::contest = $1;
+ my $id = $2;
+
+ my $htc = HTML::Template::Compiled->new(scalarref => \$templates{$_[1]});
+
+ my @tests = map {
+ $_->{time} = sprintf "%.4fs", $_->{time};
+ $_
+ } @{job_results $id};
+
+ $htc->param(id => $id);
+ $htc->param(tests => \@tests);
+ $htc->output
}
1
use HTML::Template::Compiled;
use IO::File;
use POSIX qw/strftime/;
-use YAML::Any qw/LoadFile/;
use Gruntmaster::Page::Common qw/header footer/;
+use Gruntmaster::Data qw/problem_name problem_level problems/;
my %templates = (
en => <<'HTML',
$templates{$_} .= footer $_ for keys %templates;
sub generate{
- my ($path, $lang) = @_;
- $path =~ s,/index\.html$,,;
- my $template = $templates{$lang};
- my $htc = HTML::Template::Compiled->new(scalarref => \$template);
- IO::File->new(">$path/meta.yml")->close unless -f "$path/meta.yml";
- flock my $metafh = IO::File->new("<$path/meta.yml"), LOCK_SH;
- my @problems = sort { $b->{name} cmp $a->{name} } map {
- my $meta = LoadFile $_;
- my $id = (m,^$path/(.*)/meta.yml$,)[0];
- +{ id => $id, name => $meta->{name}, level => $meta->{level} } } <$path/*/meta.yml>;
- 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);
- $htc->output
+ $_[0] =~ m,^(?:ct/([^/]+)/)?pb/index.html$,;
+ local $Gruntmaster::Data::contest = $1;
+
+ my $htc = HTML::Template::Compiled->new(scalarref => \$templates{$_[1]});
+ 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);
+ $htc->output
}
1
use HTML::Template::Compiled;
use IO::File;
use POSIX qw/strftime/;
-use YAML::Any qw/LoadFile/;
use File::Basename qw/fileparse/;
-use File::Slurp qw/slurp/;
use Gruntmaster::Page::Common qw/header footer/;
+use Gruntmaster::Data qw/contest_start contest_end problem_name problem_statement/;
use constant FORMATS => [qw/CPP/];
use constant TITLE => '<tmpl_var name>';
my %templates = (
- en => <<'HTML',
+ en => <<'HTML',
<tmpl_var statement>
<tmpl_if cansubmit>
$templates{$_} .= footer $_ for keys %templates;
sub generate{
- my ($path, $lang) = @_;
- my $contest;
- $contest = $1 if $path =~ m,ct/([^/]*)/,;
- my $id = ($path =~ m,pb/([^/]*)/index,)[0];
- $path =~ s,/index\.html$,,;
- my $template = $templates{$_[1]};
- my $htc = HTML::Template::Compiled->new(scalarref => \$template);
- flock my $metafh = IO::File->new("<$path/meta.yml"), LOCK_SH;
- my $meta = LoadFile "$path/meta.yml";
+ $_[0] =~ m,(?:ct/([^/])+/)?log/(\w+)\.html$,;
- $htc->param(cansubmit => 1);
- if (defined $contest) {
- my $meta = LoadFile "ct/$contest/meta.yml";
- $htc->param(cansubmit => time >= $meta->{start} && time <= $meta->{end});
- $htc->param(contest => $contest);
- }
- $htc->param(formats => FORMATS);
- $htc->param(id => $id);
- $htc->param(name => $meta->{name});
- $htc->param(statement => scalar slurp "$path/statement.$lang");
- $htc->output
+ my ($contest, $id) = ($1, $2);
+ my $htc = HTML::Template::Compiled->new(scalarref => \$templates{$_[1]});
+
+ $htc->param(cansubmit => 1);
+ if (defined $contest) {
+ $htc->param(cansubmit => time >= contest_start $contest && time <= contest_end $contest);
+ $htc->param(contest => $contest);
+ }
+ $htc->param(formats => FORMATS);
+ $htc->param(id => $id);
+ local $Gruntmaster::Data::contest = ($_[0] =~ m,(?:ct/([^/])+/)?,)[0];
+ $htc->param(name => problem_name $id);
+ $htc->param(statement => problem_statement $id, $_[2]);
+ $htc->output
}
1
use constant TITLE => 'Standings';
-use Fcntl qw/:flock/;
use HTML::Template::Compiled;
-use IO::File;
use List::Util qw/sum/;
use POSIX qw/strftime/;
-use YAML::Any qw/LoadFile/;
use Gruntmaster::Page::Common qw/header footer/;
+use Gruntmaster::Data qw/problems jobcard job_result_text job_result job_problem job_user/;
my %templates = (
- en => <<'HTML',
+ en => <<'HTML',
<table border>
<thead>
<tr><th>Username<tmpl_loop problems><th><tmpl_var _></tmpl_loop><th>Total
$templates{$_} .= footer $_ for keys %templates;
sub generate{
- my ($path, $lang) = @_;
- $path =~ s,/st\.html$,,;
- my $template = $templates{$lang};
- my $htc = HTML::Template::Compiled->new(scalarref => \$template);
- IO::File->new(">$path/meta.yml")->close unless -f "$path/meta.yml";
- flock my $metafh = IO::File->new("<$path/meta.yml"), LOCK_SH;
- my $meta = LoadFile "$path/meta.yml";
- my @problems = sort grep { /^\w+$/ } map { s,.*/,,r } <$path/../pb/*>;
- my %scores;
- for (1 .. $meta->{last}) {
- my $meta = LoadFile "$path/$_/meta.yml";
- if ($meta->{result_text} =~ m/^(\d+)/) {
- $scores{$meta->{user}}{$meta->{problem}} = $1;
- } else {
- $scores{$meta->{user}}{$meta->{problem}} = $meta->{result} ? 0 : 100;
+ local $Gruntmaster::Data::contest = ($_[0] =~ m,^ct/([^/]+)/,)[0];
+ my $htc = HTML::Template::Compiled->new(scalarref => \$templates{$_[1]});
+
+ my @problems = sort problems;
+ my %scores;
+ for (1 .. jobcard) {
+ if (job_result_text =~ m/^(\d+)/) {
+ $scores{job_user()}{job_problem()} = $1;
+ } else {
+ $scores{job_user()}{job_problem()} = job_result() ? 0 : 100;
+ }
}
- }
- my @st = sort { $b->{score} <=> $a->{score} } map {
- my $user = $_;
- +{
- user => $user,
- score => sum (values $scores{$user}),
- scores => [map { $scores{$user}{$_} // '-'} @problems],
- }
- } keys %scores;
- $htc->param(problems => \@problems);
- $htc->param(st => \@st);
- $htc->output
+ my @st = sort { $b->{score} <=> $a->{score} } map {
+ my $user = $_;
+ +{
+ user => $user,
+ score => sum (values $scores{$user}),
+ scores => [map { $scores{$user}{$_} // '-'} @problems],
+ }
+ } keys %scores;
+ $htc->param(problems => \@problems);
+ $htc->param(st => \@st);
+ $htc->output
}
1
use Fcntl qw/:flock/;
use HTML::Template::Compiled;
-use IO::File;
use YAML::Any qw/LoadFile/;
use Gruntmaster::Page::Common qw/header footer/;
+use Gruntmaster::Data qw//;
my %templates = (
- en => <<'HTML',
+ en => <<'HTML',
<form action="https://gm.ieval.ro/action/submit" method="POST" enctype="multipart/form-data">
<label>Problem:<br>
<select name="problem" required>
$templates{$_} .= footer $_ for keys %templates;
sub generate{
- my $template = $templates{$_[1]};
- my $htc = HTML::Template::Compiled->new(scalarref => \$template);
- IO::File->new('>meta.yml')->close unless -f 'meta.yml';
- flock my $metafh = IO::File->new('<meta.yml'), LOCK_SH;
- my @problems = map {
- my $meta = LoadFile $_;
- my $id = (m,^pb/(.*)/meta.yml$,)[0];
- +{ id => $id, name => $meta->{name} } } <pb/*/meta.yml>;
- $htc->param(problems => \@problems);
- $htc->param(formats => FORMATS);
- $htc->output
+ my $htc = HTML::Template::Compiled->new(scalarref => \$templates{$_[1]});
+ my @problems = map +{ id => $_, name => problem_name }, problems;
+ $htc->param(problems => \@problems);
+ $htc->param(formats => FORMATS);
+ $htc->output
}
1