use 5.014000;
use strict;
use warnings;
-use parent qw/Exporter/;
-our @EXPORT_OK = qw/generate header footer/;
+use Fcntl qw/:flock/;
use File::Basename qw/fileparse/;
-use File::Slurp qw/write_file/;
+use File::Path qw/make_path/;
+use File::Slurp qw/read_file write_file/;
use IO::Compress::Gzip qw/gzip/;
+use IO::File;
+use Gruntmaster::Data;
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',
+ 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><li><a href="/ct/">Contests</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];
+ my ($generator, $regex) = @_;
+ $generator = "Gruntmaster::Page::$generator";
+ eval "require $generator";
+ push @generators, [$regex, $generator];
}
{
- 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/st/index$,;
- 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 Us => qr,^us/index$,;
+ declaregen 'Us::Entry' => qr,^us/$component$,;
+ declaregen Ct => qr,^ct/index$,;
+ declaregen 'Ct::Entry' => qr,^ct/$component/index$,;
+ declaregen St => qr,^${contest}log/st$,;
+ declaregen Log => qr,^${contest}log/(?:\d+|index)$,;
+ declaregen 'Log::Entry' => qr,^${contest}log/job/$component$,;
+ declaregen Submit => qr,^${contest}submit$,;
+ declaregen Pb => qr,^${contest}pb/index$,;
+ declaregen 'Pb::Entry' => qr,^${contest}pb/$component$,;
}
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;
+ my ($path, $topic) = @_;
+ my ($path_noext, $ext) = $path =~ m/^(.*)\.(.*)$/;
+ my ($basename, $directories) = fileparse $path_noext;
+ make_path $directories;
+
+ 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";
+
+ my $fill_typemap = sub {
+ for my $lang (@{LANGUAGES()}) {
+ my $page = $_[0]->($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";
+ }
+ };
+
+ if ($topic eq 'genpage') {
+ for my $gen (@generators) {
+ my ($regex, $generator) = @$gen;
+ next unless $path_noext =~ $regex;
+ $fill_typemap->(sub { $generator->generate($path, $_[0]) });
+ last
+ }
+ } else {
+ my $get_article = sub {
+ my $article = read_file "$ENV{GRUNTMASTER_ARTICLE_ROOT}/$basename.$_[0]";
+ my $title = read_file "$ENV{GRUNTMASTER_ARTICLE_ROOT}/$basename.$_[0].title";
+ Gruntmaster::Page::Base::header($_[0], $title) . $article . Gruntmaster::Page::Base::footer($_[0])
+ };
+
+ $fill_typemap->($get_article);
+ }
+
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";
+ rename "$path_noext.$lang.$ext.new", "$path_noext.$lang.$ext";
+ rename "$path_noext.$lang.gz.$ext.new", "$path_noext.$lang.gz.$ext";
}
- }
- close $typemap;
+ rename "$path_noext.var.new", "$path_noext.var";
+ close $typemap;
+}
+
+sub gensrc{
+ my ($contest, $job) = split /\./, $_[0];
+ local $Gruntmaster::Data::contest = $contest if $contest;
+ my $ext = job_extension $job;
+ my $log = $contest ? "ct/$contest/log" : 'log';
+ make_path "$log/src/";
+ say STDERR "Writing to $log/src/$job.$ext";
+ write_file "$log/src/$job.$ext", job_inmeta($job)->{files}{prog}{content};
}
1;