--- /dev/null
+package Gruntmaster::Page::Ct;
+
+use 5.014000;
+use strict;
+use warnings;
+use parent qw/Exporter/;
+our @EXPORT_OK = qw/generate/;
+our $VERSION = '0.001';
+
+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 qw/header footer/;
+
+my %templates = (
+ en => <<'HTML',
+<tmpl_if runningn>
+<h1>Running contests</h1>
+<table border>
+<thead>
+<tr><th>Name<th>Start date<th>End date<th>Owner
+<tbody>
+<tmpl_loop running><tr><td><a href="<tmpl_var id>"><tmpl_var name></a>
+<td><tmpl_var start>
+<td><tmpl_var end>
+<td><tmpl_var owner>
+</tmpl_loop>
+</table>
+</tmpl_if>
+
+<tmpl_if pendingn>
+<h1>Pending contests</h1>
+<table border>
+<thead>
+<tr><th>Name<th>Start date<th>End date<th>Owner
+<tbody>
+<tmpl_loop pending><tr><td><a href="<tmpl_var id>"><tmpl_var name></a>
+<td><tmpl_var start>
+<td><tmpl_var end>
+<td><tmpl_var owner>
+</tmpl_loop>
+</table>
+</tmpl_if>
+
+<tmpl_if finishedn>
+<h1>Finished contests</h1>
+<table border>
+<thead>
+<tr><th>Name<th>Start date<th>End date<th>Owner
+<tbody>
+<tmpl_loop finished><tr><td><a href="<tmpl_var id>"><tmpl_var name></a>
+<td><tmpl_var start>
+<td><tmpl_var end>
+<td><tmpl_var owner>
+</tmpl_loop>
+</table>
+</tmpl_if>
+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('>ct/meta.yml')->close unless -f 'ct/meta.yml';
+ flock my $metafh = IO::File->new('<ct/meta.yml'), LOCK_SH;
+
+ 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 $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};
+ }
+
+ $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
+}
+
+1