Bump version and update Changes
[gruntmaster-data.git] / lib / Gruntmaster / Data.pm
1 use utf8;
2 package Gruntmaster::Data;
3
4 # Created by DBIx::Class::Schema::Loader
5 # DO NOT MODIFY THE FIRST PART OF THIS FILE
6
7 use strict;
8 use warnings;
9
10 use base 'DBIx::Class::Schema';
11
12 __PACKAGE__->load_namespaces;
13
14
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
17
18 our $VERSION = '5999.000_007';
19
20 use Lingua::EN::Inflect qw/PL_N/;
21 use JSON qw/decode_json/;
22 use Sub::Name qw/subname/;
23
24 use constant PROBLEM_PUBLIC_COLUMNS => [qw/id author writer level name owner private statement timeout olimit value/];
25 use constant USER_PUBLIC_COLUMNS => [qw/id admin name town university level/];
26 use constant JOBS_PER_PAGE => 10;
27
28 sub dynsub{
29 our ($name, $sub) = @_;
30 no strict 'refs';
31 *$name = subname $name => $sub
32 }
33
34 BEGIN {
35 for my $rs (qw/contest contest_problem job open problem user/) {
36 my $rsname = ucfirst $rs;
37 $rsname =~ s/_([a-z])/\u$1/g;
38 dynsub PL_N($rs) => sub { $_[0]->resultset($rsname) };
39 dynsub $rs => sub { $_[0]->resultset($rsname)->find($_[1]) };
40 }
41 }
42
43 sub user_list {
44 my $rs = $_[0]->users->search(undef, {order_by => 'name', columns => USER_PUBLIC_COLUMNS});
45 [ map +{ $_->get_columns }, $rs->all ]
46 }
47
48 sub user_entry {
49 my ($self, $id) = @_;
50 +{ $self->users->find($id, {columns => USER_PUBLIC_COLUMNS})->get_columns }
51 }
52
53 sub problem_list {
54 my ($self, %args) = @_;
55 my $rs = $self->problems->search(undef, {order_by => 'me.name', columns => PROBLEM_PUBLIC_COLUMNS, prefetch => 'owner'});
56 $rs = $rs->search({-or => ['contest_problems.contest' => undef, 'contest.stop' => {'<=', time}], 'me.private' => 0}, {join => {'contest_problems' => 'contest'}, distinct => 1}) unless $args{contest};
57 $rs = $rs->search({'contest_problems.contest' => $args{contest}}, {join => 'contest_problems'}) if $args{contest};
58 $rs = $rs->search({'me.owner' => $args{owner}}) if $args{owner};
59 my %params;
60 $params{contest} = $args{contest} if $args{contest};
61 for ($rs->all) {
62 $params{$_->level} //= [];
63 push $params{$_->level}, {$_->get_columns, owner_name => $_->owner->name} ;
64 }
65 \%params
66 }
67
68 sub problem_entry {
69 my ($self, $id, $contest, $user) = @_;
70 my $pb = $self->problems->find($id, {columns => PROBLEM_PUBLIC_COLUMNS, prefetch => 'owner'});
71 my $running = $contest && $self->contest($contest)->is_running;
72 eval {
73 $self->opens->create({
74 contest => $contest,
75 problem => $id,
76 owner => $user,
77 time => time,
78 })
79 } if $running;
80 +{ $pb->get_columns, owner_name => $pb->owner->name, cansubmit => $contest ? $running : 1 }
81 }
82
83 sub contest_list {
84 my ($self, %args) = @_;
85 my $rs = $self->contests->search(undef, {order_by => {-desc => 'start'}, prefetch => 'owner'});
86 $rs = $rs->search({owner => $args{owner}}) if $args{owner};
87 my %params;
88 for ($rs->all) {
89 my $state = $_->is_pending ? 'pending' : $_->is_running ? 'running' : 'finished';
90 $params{$state} //= [];
91 push $params{$state}, { $_->get_columns, started => !$_->is_pending, owner_name => $_->owner->name };
92 }
93 \%params
94 }
95
96 sub contest_entry {
97 my ($self, $id) = @_;
98 my $ct = $self->contest($id);
99 +{ $ct->get_columns, started => !$ct->is_pending, owner_name => $ct->owner->name }
100 }
101
102 sub job_list {
103 my ($self, %args) = @_;
104 $args{page} //= 1;
105 my $rs = $self->jobs->search(undef, {order_by => {-desc => 'me.id'}, prefetch => ['problem', 'owner'], rows => JOBS_PER_PAGE, offset => ($args{page} - 1) * JOBS_PER_PAGE});
106 $rs = $rs->search({owner => $args{owner}}) if $args{owner};
107 $rs = $rs->search({contest => $args{contest}}) if $args{contest};
108 $rs = $rs->search({problem => $args{problem}}) if $args{problem};
109 [map {
110 my %params = $_->get_columns;
111 $params{owner_name} = $_->owner->name;
112 $params{problem_name} = $_->problem->name;
113 $params{results} &&= decode_json $params{results};
114 $params{size} = length $params{source};
115 delete $params{source};
116 \%params
117 } $rs->all]
118 }
119
120 sub job_entry {
121 my ($self, $id) = @_;
122 my $job = $self->jobs->find($id, {prefetch => ['problem', 'owner']});
123 my %params = $job->get_columns;
124 $params{owner_name} = $job->owner->name;
125 $params{problem_name} = $job->problem->name;
126 $params{results} &&= decode_json $params{results};
127 $params{size} = length $params{source};
128 delete $params{source};
129 \%params
130 }
131
132 1;
133
134 __END__
135
136 =encoding utf-8
137
138 =head1 NAME
139
140 Gruntmaster::Data - Gruntmaster 6000 Online Judge -- database interface and tools
141
142 =head1 SYNOPSIS
143
144 my $db = Gruntmaster::Data->connect('dbi:Pg:');
145
146 my $problem = $db->problem('my_problem');
147 $problem->update({timeout => 2.5}); # Set time limit to 2.5 seconds
148 $problem->rerun; # And rerun all jobs for this problem
149
150 # ...
151
152 my $contest = $db->contests->create({ # Create a new contest
153 id => 'my_contest',
154 name => 'My Awesome Contest',
155 start => time + 100,
156 end => time + 1900,
157 });
158 $db->contest_problems->create({ # Add a problem to the contest
159 contest => 'my_contest',
160 problem => 'my_problem',
161 });
162
163 say 'The contest has not started yet' if $contest->is_pending;
164
165 # ...
166
167 my @jobs = $db->jobs->search({contest => 'my_contest', owner => 'MGV'})->all;
168 $_->rerun for @jobs; # Rerun all jobs sent by MGV in my_contest
169
170 =head1 DESCRIPTION
171
172 Gruntmaster::Data is the interface to the Gruntmaster 6000 database. Read the L<DBIx::Class> documentation for usage information.
173
174 In addition to the typical DBIx::Class::Schema methods, this module contains several convenience methods:
175
176 =over
177
178 =item contests
179
180 Equivalent to C<< $schema->resultset('Contest') >>
181
182 =item contest_problems
183
184 Equivalent to C<< $schema->resultset('ContestProblem') >>
185
186 =item jobs
187
188 Equivalent to C<< $schema->resultset('Job') >>
189
190 =item problems
191
192 Equivalent to C<< $schema->resultset('Problem') >>
193
194 =item users
195
196 Equivalent to C<< $schema->resultset('User') >>
197
198 =item contest($id)
199
200 Equivalent to C<< $schema->resultset('Contest')->find($id) >>
201
202 =item job($id)
203
204 Equivalent to C<< $schema->resultset('Job')->find($id) >>
205
206 =item problem($id)
207
208 Equivalent to C<< $schema->resultset('Problem')->find($id) >>
209
210 =item user($id)
211
212 Equivalent to C<< $schema->resultset('User')->find($id) >>
213
214 =item user_list
215
216 Returns a list of users as an arrayref containing hashrefs.
217
218 =item user_entry($id)
219
220 Returns a hashref with information about the user $id.
221
222 =item problem_list([%args])
223
224 Returns a list of problems grouped by level. A hashref with levels as keys.
225
226 Takes the following arguments:
227
228 =over
229
230 =item owner
231
232 Only show problems owned by this user
233
234 =item contest
235
236 Only show problems in this contest
237
238 =back
239
240 =item problem_entry($id, [$contest, $user])
241
242 Returns a hashref with information about the problem $id. If $contest and $user are present, problem open data is updated.
243
244 =item contest_list([%args])
245
246 Returns a list of contests grouped by state. A hashref with the following keys:
247
248 =over
249
250 =item pending
251
252 An arrayref of hashrefs representing pending contests
253
254 =item running
255
256 An arrayref of hashrefs representing running contests
257
258 =item finished
259
260 An arrayref of hashrefs representing finished contests
261
262 =back
263
264 Takes the following arguments:
265
266 =over
267
268 =item owner
269
270 Only show contests owned by this user.
271
272 =back
273
274 =item contest_entry($id)
275
276 Returns a hashref with information about the contest $id.
277
278 =item job_list([%args])
279
280 Returns a list of jobs as an arrayref containing hashrefs. Takes the following arguments:
281
282 =over
283
284 =item owner
285
286 Only show jobs submitted by this user.
287
288 =item contest
289
290 Only show jobs submitted in this contest.
291
292 =item problem
293
294 Only show jobs submitted for this problem.
295
296 =item page
297
298 Show this page of results. Defaults to 1. Pages have 10 entries, and the first page has the most recent jobs.
299
300 =back
301
302 =item job_entry($id)
303
304 Returns a hashref with information about the job $id.
305
306 =back
307
308 =head1 AUTHOR
309
310 Marius Gavrilescu E<lt>marius@ieval.roE<gt>
311
312 =head1 COPYRIGHT AND LICENSE
313
314 Copyright (C) 2014 by Marius Gavrilescu
315
316 This library is free software; you can redistribute it and/or modify
317 it under the same terms as Perl itself, either Perl version 5.18.1 or,
318 at your option, any later version of Perl 5 you may have available.
319
320
321 =cut
This page took 0.037541 seconds and 4 git commands to generate.