--- /dev/null
+Revision history for Perl extension Gruntmaster::Page.
+
+0.001 Thu Oct 24 14:32:13 2013
+ - original version; created by h2xs 1.23 with options
+ -AX -b 5.14.0 -v 0.001 Gruntmaster::Page
+
--- /dev/null
+
+Changes
+gruntmaster-genpage
+lib/Gruntmaster/Page/Index.pm
+lib/Gruntmaster/Page/Log/Entry.pm
+lib/Gruntmaster/Page/Log.pm
+lib/Gruntmaster/Page/Pb/Entry.pm
+lib/Gruntmaster/Page/Pb.pm
+lib/Gruntmaster/Page.pm
+lib/Gruntmaster/Page/Submit.pm
+Makefile.PL
+MANIFEST
+README
+t/Gruntmaster-Page.t
--- /dev/null
+use 5.014000;
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+ NAME => 'Gruntmaster::Page',
+ VERSION_FROM => 'lib/Gruntmaster/Page.pm', # finds $VERSION
+ PREREQ_PM => {}, # e.g., Module::Name => 1.1
+ ($] >= 5.005 ? ## Add these new keywords supported since 5.005
+ (ABSTRACT_FROM => 'lib/Gruntmaster/Page.pm', # retrieve abstract from module
+ AUTHOR => 'Marius Gavrilescu <marius@ieval.ro>') : ()),
+ EXE_FILES => [ qw/gruntmaster-genpage/ ]
+);
--- /dev/null
+Gruntmaster-Page version 0.001
+==============================
+
+The README is used to introduce the module and provide instructions on
+how to install the module, any machine dependencies it may have (for
+example C compilers and installed libraries) and any other information
+that should be provided before the module is installed.
+
+A README file is required for CPAN modules since CPAN extracts the
+README file from a module distribution so that people browsing the
+archive can use it get an idea of the modules uses. It is usually a
+good idea to provide version information here so that people can
+decide whether fixes for the module are worth downloading.
+
+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:
+
+ blah blah blah
+
+COPYRIGHT AND LICENCE
+
+Put the correct copyright and licence information here.
+
+Copyright (C) 2013 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.1 or,
+at your option, any later version of Perl 5 you may have available.
+
+
--- /dev/null
+#!/usr/bin/perl -w
+use v5.14;
+
+use Gruntmaster::Page qw/generate/;
+
+generate $_ for @ARGV;
--- /dev/null
+package Gruntmaster::Page;
+
+use 5.014000;
+use strict;
+use warnings;
+use parent qw/Exporter/;
+our @EXPORT_OK = qw/generate header footer/;
+
+use File::Basename qw/fileparse/;
+use File::Slurp qw/write_file/;
+use IO::Compress::Gzip qw/gzip/;
+
+our $VERSION = '0.001';
+our @generators;
+
+use constant LANGUAGES => [ 'en' ];
+use constant CONTENT_TYPES => {
+ html => 'text/html; charset=UTF-8',
+ txt => 'text/plain; charset=UTF-8',
+};
+
+my %header_templates = (
+ en => <<'HTML',
+<!DOCTYPE html>
+<title>TITLE_GOES_HERE</title>
+<link rel="stylesheet" href="/gm.css">
+<script src="/jquery-2.0.3.min.js"></script>
+<script src="/view.js"></script>
+<meta charset="utf-8">
+
+<span id="admin"></span>
+<div id="title"><span class="i">i</span><span class="Eval">Eval</span></div>
+<div id="subtitle">TITLE_GOES_HERE</div>
+
+<nav><ul><li><a href="/">Home</a><li><a href="/log/">View job log</a><li><a href="/submit.var">Submit job</a><li><a href="/pb/">Problem list</a></ul></nav>
+
+HTML
+);
+
+my %footer_templates = (
+ en => <<'HTML',
+
+<footer>
+Dilmom: Why don't you call your product the Gruntmaster 6000?
+Dilbert: What kind of product do you see when you imagine a Gruntmaster 6000?
+Dilmom: Well, it's a stripped-down version of the Gruntmaster 9000, of course. But it's software-upgradeable.
+</footer>
+HTML
+);
+
+sub header{
+ my ($language, $title) = @_;
+ $header_templates{$language} =~ s/TITLE_GOES_HERE/$title/ger;
+}
+
+sub footer{
+ $footer_templates{$_[0]};
+}
+
+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];
+}
+
+declaregen Index => qr'^index$';
+declaregen Log => qr'^log/index$';
+declaregen 'Log::Entry' => qr'^log/.*/index$';
+declaregen Submit => qr'^submit$';
+declaregen Pb => qr'^pb/index$';
+declaregen 'Pb::Entry' => qr'^pb/.*/index$';
+
+sub generate{
+ my ($path) = @_;
+ my ($path_noext, $ext) = $path =~ m/^(.*)\.(.*)$/;
+ my $basename = fileparse $path_noext;
+
+ open my $typemap, ">$path_noext.var";
+ 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", $page;
+ say $typemap "URI: $basename.$lang.$ext\nContent-Language: $lang\nContent-Type: " . CONTENT_TYPES->{$ext} . "\n";
+ gzip \$page => "$path_noext.$lang.gz.$ext", Minimal => 1;
+ say $typemap "URI: $basename.$lang.gz.$ext\nContent-Language: $lang\nContent-Encoding: gzip\nContent-Type: " . CONTENT_TYPES->{$ext} . "\n";
+ }
+ }
+ close $typemap;
+}
+
+1;
+__END__
+# Below is stub documentation for your module. You'd better edit it!
+
+=head1 NAME
+
+Gruntmaster::Page - Perl extension for blah blah blah
+
+=head1 SYNOPSIS
+
+ use Gruntmaster::Page;
+ blah blah blah
+
+=head1 DESCRIPTION
+
+Stub documentation for Gruntmaster::Page, created by h2xs. It looks like the
+author of the extension was negligent enough to leave the stub
+unedited.
+
+Blah blah blah.
+
+=head2 EXPORT
+
+None by default.
+
+
+
+=head1 SEE ALSO
+
+Mention other useful documentation such as the documentation of
+related modules or operating system documentation (such as man pages
+in UNIX), or any relevant external documentation such as RFCs or
+standards.
+
+If you have a mailing list set up for your module, mention it here.
+
+If you have a web site set up for your module, mention it here.
+
+=head1 AUTHOR
+
+Marius Gavrilescu, E<lt>marius@E<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2013 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.1 or,
+at your option, any later version of Perl 5 you may have available.
+
+
+=cut
--- /dev/null
+package Gruntmaster::Page::Index;
+
+use 5.014000;
+use strict;
+use warnings;
+use parent qw/Exporter/;
+our @EXPORT_OK = qw/generate/;
+our $VERSION = '0.001';
+
+use constant TITLE => 'Gruntmaster 6000';
+
+use Fcntl qw/:flock/;
+use HTML::Template::Compiled;
+use IO::File;
+use Gruntmaster::Page qw/header footer/;
+
+my %templates = (
+ en => <<'HTML',
+HTML
+);
+
+$templates{$_} = header($_, TITLE) . $templates{$_} for keys %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
+}
+
+1
--- /dev/null
+package Gruntmaster::Page::Log;
+
+use 5.014000;
+use strict;
+use warnings;
+use parent qw/Exporter/;
+our @EXPORT_OK = qw/generate/;
+our $VERSION = '0.001';
+
+use constant TITLE => 'Job log';
+
+use Fcntl qw/:flock/;
+use HTML::Template::Compiled;
+use IO::File;
+use POSIX qw/strftime/;
+use YAML::Any qw/LoadFile/;
+use Gruntmaster::Page qw/header footer/;
+
+my %templates = (
+ en => <<'HTML',
+<table border>
+<thead>
+<tr><th>ID<th>Problem<th>Date<th>Size<th>User<th>Result
+<tbody>
+<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 user><td class="r<tmpl_var result>"><tmpl_var result_text>
+</tmpl_loop>
+</table>
+HTML
+);
+
+$templates{$_} = header($_, TITLE) . $templates{$_} for keys %templates;
+$templates{$_} .= footer $_ for keys %templates;
+
+sub generate{
+ my $template = $templates{$_[1]};
+ my $htc = HTML::Template::Compiled->new(scalarref => \$template);
+ IO::File->new('>log/meta.yml')->close unless -f 'log/meta.yml';
+ flock my $metafh = IO::File->new('<log/meta.yml'), LOCK_SH;
+ my $meta = LoadFile 'log/meta.yml';
+ my @log = sort { $b->{id} <=> $a->{id} } map {
+ my $meta = LoadFile "log/$_/meta.yml";
+ +{ id => $_,
+ 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 "log/$_/in/" . $meta->{files}{prog}{name}) / 1024),
+ result_text => $meta->{result_text}} } 1 .. $meta->{last};
+ $htc->param(log => \@log);
+ $htc->output
+}
+
+1
--- /dev/null
+package Gruntmaster::Page::Log::Entry;
+
+use 5.014000;
+use strict;
+use warnings;
+use parent qw/Exporter/;
+our @EXPORT_OK = qw/generate/;
+our $VERSION = '0.001';
+
+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 qw/header footer/;
+
+my %templates = (
+ en => <<'HTML',
+<table border>
+<thead>
+<tr><th>Test number<th>Result<th>Time
+<tbody>
+<tmpl_loop tests><tr><td><tmpl_var id><td class="r<tmpl_var result>"><tmpl_var result_text><td><tmpl_var time>
+</tmpl_loop>
+</table>
+HTML
+);
+
+$templates{$_} = header($_, TITLE) . $templates{$_} for keys %templates;
+$templates{$_} .= footer $_ for keys %templates;
+
+sub generate{
+ my ($path, $lang) = @_;
+ $path = ($path =~ m,log/(.*)/index,)[0];
+ my $template = $templates{$lang};
+
+ my $htc = HTML::Template::Compiled->new(scalarref => \$template);
+ flock my $metafh = IO::File->new("<log/$path/meta.yml"), LOCK_SH;
+ my $meta = LoadFile "log/$path/meta.yml";
+
+ my @tests = map {
+ $_->{time} = sprintf "%.4fs", $_->{time};
+ $_
+ } @{$meta->{results}};
+
+ $htc->param(id => $path);
+ $htc->param(tests => \@tests);
+ $htc->output
+}
+
+1
--- /dev/null
+package Gruntmaster::Page::Pb;
+
+use 5.014000;
+use strict;
+use warnings;
+use parent qw/Exporter/;
+our @EXPORT_OK = qw/generate/;
+our $VERSION = '0.001';
+
+use constant TITLE => 'Problems';
+
+use Fcntl qw/:flock/;
+use HTML::Template::Compiled;
+use IO::File;
+use POSIX qw/strftime/;
+use YAML::Any qw/LoadFile/;
+use Gruntmaster::Page qw/header footer/;
+
+my %templates = (
+ en => <<'HTML',
+<ul>
+<tmpl_loop problems><li><a href="<tmpl_var id>"><tmpl_var name></a>
+</tmpl_loop></ul>
+HTML
+);
+
+$templates{$_} = header($_, TITLE) . $templates{$_} for keys %templates;
+$templates{$_} .= footer $_ for keys %templates;
+
+sub generate{
+ my $template = $templates{$_[1]};
+ my $htc = HTML::Template::Compiled->new(scalarref => \$template);
+ IO::File->new('>pb/meta.yml')->close unless -f 'pb/meta.yml';
+ flock my $metafh = IO::File->new('<pb/meta.yml'), LOCK_SH;
+ my @problems = sort { $b->{name} cmp $a->{name} } map {
+ my $meta = LoadFile $_;
+ my $id = (m,^pb/(.*)/meta.yml$,)[0];
+ +{ id => $id, name => $meta->{name} } } <pb/*/meta.yml>;
+ $htc->param(problems => \@problems);
+ $htc->output
+}
+
+1
--- /dev/null
+package Gruntmaster::Page::Pb::Entry;
+
+use 5.014000;
+use strict;
+use warnings;
+use parent qw/Exporter/;
+our @EXPORT_OK = qw/generate/;
+our $VERSION = '0.001';
+
+use Fcntl qw/:flock/;
+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 qw/header footer/;
+
+use constant FORMATS => [qw/CPP/];
+use constant TITLE => '<tmpl_var name>';
+
+my %templates = (
+ en => <<'HTML',
+<tmpl_var statement>
+
+<h1>Submit solution</h1>
+<form action="https://gm.ieval.ro/action/submit" method="POST" enctype="multipart/form-data">
+<input type="hidden" name="problem" value="<tmpl_var id>">
+<label>File: <input name="prog" required type="file"></label>
+
+<label>File format: <select name="prog_format" required>
+<tmpl_loop formats><option value="<tmpl_var _>"><tmpl_var _></option>
+</tmpl_loop></select></label>
+
+<input type="submit" value="Submit job">
+HTML
+);
+
+$templates{$_} = header($_, TITLE) . $templates{$_} for keys %templates;
+$templates{$_} .= footer $_ for keys %templates;
+
+sub generate{
+ my ($path, $lang) = @_;
+ $path = ($path =~ m,pb/(.*)/index,)[0];
+ my $template = $templates{$_[1]};
+ my $htc = HTML::Template::Compiled->new(scalarref => \$template);
+ flock my $metafh = IO::File->new("<pb/$path/meta.yml"), LOCK_SH;
+ my $meta = LoadFile "pb/$path/meta.yml";
+
+ $htc->param(formats => FORMATS);
+ $htc->param(id => $path);
+ $htc->param(name => $meta->{name});
+ $htc->param(statement => scalar slurp "pb/$path/statement.$lang");
+ $htc->output
+}
+
+1
--- /dev/null
+package Gruntmaster::Page::Submit;
+
+use 5.014000;
+use strict;
+use warnings;
+use parent qw/Exporter/;
+our @EXPORT_OK = qw/generate/;
+our $VERSION = '0.001';
+
+use constant FORMATS => [qw/CPP/];
+use constant TITLE => 'Submit job';
+
+use Fcntl qw/:flock/;
+use HTML::Template::Compiled;
+use IO::File;
+use YAML::Any qw/LoadFile/;
+use Gruntmaster::Page qw/header footer/;
+
+my %templates = (
+ en => <<'HTML',
+<form action="https://gm.ieval.ro/action/submit" method="POST" enctype="multipart/form-data">
+<label>Problem:<br>
+<select name="problem" required>
+<tmpl_loop problems><option value="<tmpl_var id>"><tmpl_var name></option>
+</tmpl_loop></select></label><p>
+
+<label>File:<br>
+<input name="prog" required type="file"></label><p>
+
+<label>File format:<br>
+<select name="prog_format" required>
+<tmpl_loop formats><option value="<tmpl_var _>"><tmpl_var _></option>
+</tmpl_loop></select></label><p>
+
+<input type="submit" value="Submit job">
+HTML
+);
+
+$templates{$_} = header($_, TITLE) . $templates{$_} for keys %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;
+ 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
+}
+
+1
--- /dev/null
+# Before 'make install' is performed this script should be runnable with
+# 'make test'. After 'make install' it should work as 'perl Gruntmaster-Page.t'
+
+#########################
+
+# change 'tests => 1' to 'tests => last_test_to_print';
+
+use strict;
+use warnings;
+
+use Test::More tests => 1;
+BEGIN { use_ok('Gruntmaster::Page') };
+
+#########################
+
+# Insert your test code below, the Test::More module is use()ed here so read
+# its man page ( perldoc Test::More ) for help writing this test script.
+