2 package Gruntmaster
::Data
;
4 # Created by DBIx::Class::Schema::Loader
5 # DO NOT MODIFY THE FIRST PART OF THIS FILE
10 use base
'DBIx::Class::Schema';
12 __PACKAGE__
->load_namespaces;
15 # Created by DBIx::Class::Schema::Loader v0.07039 @ 2014-03-05 13:11:39
16 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dAEmtAexvUaNXLgYz2rNEg
18 our $VERSION = '5999.000_011';
20 use Lingua
::EN
::Inflect qw
/PL_N/;
21 use JSON
::MaybeXS qw
/decode_json/;
22 use PerlX
::Maybe qw
/maybe/;
23 use Sub
::Name qw
/subname/;
25 use constant PROBLEM_PUBLIC_COLUMNS
=> [qw
/id author writer level name owner private statement timeout olimit value/];
26 use constant USER_PUBLIC_COLUMNS
=> [qw
/id admin name town university level/];
27 use constant JOBS_PER_PAGE
=> 10;
30 our ($name, $sub) = @_;
31 no strict
'refs'; ## no critic (Strict)
32 *$name = subname
$name => $sub
36 for my $rs (qw
/contest contest_problem job open problem user problem_status contest_status/) {
37 my $rsname = ucfirst $rs;
38 $rsname =~ s/_([a-z])/\u$1/gs;
39 dynsub PL_N
($rs) => sub { $_[0]->resultset($rsname) };
40 dynsub
$rs => sub { $_[0]->resultset($rsname)->find($_[1]) };
45 my $rs = $_[0]->users->search(undef, {order_by
=> 'name', columns
=> USER_PUBLIC_COLUMNS
});
46 [ map { { $_->get_columns } } $rs->all ]
51 my $user = $self->users->find($id, {columns
=> USER_PUBLIC_COLUMNS
, prefetch
=> [qw
/problem_statuses contest_statuses/]});
52 my @problems = map { {problem
=> $_->get_column('problem'), solved
=> $_->solved} } $user->problem_statuses;
53 my @contests = map { {contest
=> $_->contest->id, contest_name
=> $_->contest->name, rank
=> $_->rank, score
=> $_->score} } $user->contest_statuses->search(undef, {prefetch
=> 'contest'});
54 +{ $user->get_columns, problems
=> \
@problems, contests
=> \
@contests }
58 my ($self, %args) = @_;
59 my $rs = $self->problems->search(undef, {order_by
=> 'me.name', columns
=> PROBLEM_PUBLIC_COLUMNS
, prefetch
=> 'owner'});
60 $rs = $rs->search({-or => ['contest_problems.contest' => undef, 'contest.stop' => {'<=', time}], 'me.private' => 0}, {join => {'contest_problems' => 'contest'}, distinct
=> 1}) unless $args{contest
};
61 $rs = $rs->search({'contest_problems.contest' => $args{contest
}}, {join => 'contest_problems'}) if $args{contest
};
62 $rs = $rs->search({'me.owner' => $args{owner
}}) if $args{owner
};
64 $params{contest
} = $args{contest
} if $args{contest
};
66 $params{$_->level} //= [];
67 push @
{$params{$_->level}}, {$_->get_columns, owner_name
=> $_->owner->name} ;
73 my ($self, $id, $contest, $user) = @_;
74 my $running = $contest && $self->contest($contest)->is_running;
75 my $columns = PROBLEM_PUBLIC_COLUMNS
;
76 push @
$columns, 'solution' unless $running;
77 my $pb = $self->problems->find($id, {columns
=> $columns, prefetch
=> 'owner'});
78 eval { ## no critic (RequireCheckingReturnValueOfEval)
79 $self->opens->create({
86 $contest &&= $self->contest($contest);
87 +{ $pb->get_columns, owner_name
=> $pb->owner->name, cansubmit
=> $contest ?
$running : 1, $running ?
(contest_start
=> $contest->start, contest_stop
=> $contest->stop) : () }
91 my ($self, %args) = @_;
92 my $rs = $self->contests->search(undef, {order_by
=> {-desc
=> 'start'}, prefetch
=> 'owner'});
93 $rs = $rs->search({owner
=> $args{owner
}}) if $args{owner
};
96 my $state = $_->is_pending ?
'pending' : $_->is_running ?
'running' : 'finished';
97 $params{$state} //= [];
98 push @
{$params{$state}}, { $_->get_columns, started
=> !$_->is_pending, owner_name
=> $_->owner->name };
104 my ($self, $id) = @_;
105 my $ct = $self->contest($id);
106 +{ $ct->get_columns, started
=> !$ct->is_pending, owner_name
=> $ct->owner->name }
110 my ($self, %args) = @_;
112 my $rs = $self->jobs->search(undef, {order_by
=> {-desc
=> 'me.id'}, prefetch
=> ['problem', 'owner'], rows
=> JOBS_PER_PAGE
, page
=> $args{page
}});
113 $rs = $rs->search({'me.owner' => $args{owner
}}) if $args{owner
};
114 $rs = $rs->search({contest
=> $args{contest
}}) if $args{contest
};
115 $rs = $rs->search({problem
=> $args{problem
}}) if $args{problem
};
118 my %params = $_->get_columns;
119 $params{owner_name
} = $_->owner->name;
120 $params{problem_name
} = $_->problem->name;
121 $params{results
} &&= decode_json
$params{results
};
122 $params{size
} = length $params{source
};
123 delete $params{source
};
126 current_page
=> $rs->pager->current_page,
127 maybe previous_page
=> $rs->pager->previous_page,
128 maybe next_page
=> $rs->pager->next_page,
129 maybe last_page
=> $rs->pager->last_page,
134 my ($self, $id) = @_;
135 my $job = $self->jobs->find($id, {prefetch
=> ['problem', 'owner']});
136 my %params = $job->get_columns;
137 $params{owner_name
} = $job->owner->name;
138 $params{problem_name
} = $job->problem->name;
139 $params{results
} &&= decode_json
$params{results
};
140 $params{size
} = length $params{source
};
141 delete $params{source
};
147 my @jobs = $self->jobs->search(undef, {cache
=> 1})->all;
150 $hash{$_->get_column('problem'), $_->get_column('owner')} = [$_->id, $_->result ?
0 : 1] for @jobs;
151 my @problem_statuses = map { [split ($;), @
{$hash{$_}} ] } keys %hash;
153 my @contest_statuses = map {
154 my $contest = $_->id;
155 map { [$contest, $_->{user
}, $_->{score
}, $_->{rank
}] } $_->standings
156 } $self->contests->all;
159 $self->problem_statuses->delete;
160 $self->problem_statuses->populate([[qw
/problem owner job solved/], @problem_statuses]);
161 $self->contest_statuses->delete;
162 $self->contest_statuses->populate([[qw
/contest owner score rank/], @contest_statuses]);
176 Gruntmaster::Data - Gruntmaster 6000 Online Judge -- database interface and tools
180 my $db = Gruntmaster::Data->connect('dbi:Pg:');
182 my $problem = $db->problem('my_problem');
183 $problem->update({timeout => 2.5}); # Set time limit to 2.5 seconds
184 $problem->rerun; # And rerun all jobs for this problem
188 my $contest = $db->contests->create({ # Create a new contest
190 name => 'My Awesome Contest',
194 $db->contest_problems->create({ # Add a problem to the contest
195 contest => 'my_contest',
196 problem => 'my_problem',
199 say 'The contest has not started yet' if $contest->is_pending;
203 my @jobs = $db->jobs->search({contest => 'my_contest', owner => 'MGV'})->all;
204 $_->rerun for @jobs; # Rerun all jobs sent by MGV in my_contest
208 Gruntmaster::Data is the interface to the Gruntmaster 6000 database. Read the L<DBIx::Class> documentation for usage information.
210 In addition to the typical DBIx::Class::Schema methods, this module contains several convenience methods:
216 Equivalent to C<< $schema->resultset('Contest') >>
218 =item contest_problems
220 Equivalent to C<< $schema->resultset('ContestProblem') >>
224 Equivalent to C<< $schema->resultset('Job') >>
228 Equivalent to C<< $schema->resultset('Problem') >>
232 Equivalent to C<< $schema->resultset('User') >>
236 Equivalent to C<< $schema->resultset('Contest')->find($id) >>
240 Equivalent to C<< $schema->resultset('Job')->find($id) >>
244 Equivalent to C<< $schema->resultset('Problem')->find($id) >>
248 Equivalent to C<< $schema->resultset('User')->find($id) >>
252 Returns a list of users as an arrayref containing hashrefs.
254 =item user_entry($id)
256 Returns a hashref with information about the user $id.
258 =item problem_list([%args])
260 Returns a list of problems grouped by level. A hashref with levels as keys.
262 Takes the following arguments:
268 Only show problems owned by this user
272 Only show problems in this contest
276 =item problem_entry($id, [$contest, $user])
278 Returns a hashref with information about the problem $id. If $contest and $user are present, problem open data is updated.
280 =item contest_list([%args])
282 Returns a list of contests grouped by state. A hashref with the following keys:
288 An arrayref of hashrefs representing pending contests
292 An arrayref of hashrefs representing running contests
296 An arrayref of hashrefs representing finished contests
300 Takes the following arguments:
306 Only show contests owned by this user.
310 =item contest_entry($id)
312 Returns a hashref with information about the contest $id.
314 =item job_list([%args])
316 Returns a list of jobs as an arrayref containing hashrefs. Takes the following arguments:
322 Only show jobs submitted by this user.
326 Only show jobs submitted in this contest.
330 Only show jobs submitted for this problem.
334 Show this page of results. Defaults to 1. Pages have 10 entries, and the first page has the most recent jobs.
340 Returns a hashref with information about the job $id.
346 Marius Gavrilescu E<lt>marius@ieval.roE<gt>
348 =head1 COPYRIGHT AND LICENSE
350 Copyright (C) 2014 by Marius Gavrilescu
352 This library is free software; you can redistribute it and/or modify
353 it under the same terms as Perl itself, either Perl version 5.18.1 or,
354 at your option, any later version of Perl 5 you may have available.