Bump version number and update Changes
[gruntmaster-data.git] / lib / Gruntmaster / Data.pm
CommitLineData
bbf8209c 1package Gruntmaster::Data;
014ee8a6 2use v5.14;
bbf8209c 3use warnings;
014ee8a6
MG
4use parent qw/Exporter/;
5
6use JSON qw/encode_json decode_json/;
014ee8a6 7use Redis;
fb6a4e3d 8use Sub::Name qw/subname/;
014ee8a6 9
7625bb86 10our $VERSION = '5999.000_002';
f7386aab 11
014ee8a6
MG
12our $contest;
13my $redis = Redis->new;
14my $pubsub = Redis->new;
15
16sub dynsub{
fb6a4e3d 17 our ($name, $sub) = @_;
014ee8a6 18 no strict 'refs';
fb6a4e3d 19 *$name = subname $name => $sub
014ee8a6
MG
20}
21
22BEGIN {
ddf4c742 23 for my $cmd (qw/multi exec smembers get hget hgetall hdel hset sadd srem incr hmset hsetnx publish del/) {
014ee8a6
MG
24 dynsub uc $cmd, sub { $redis->$cmd(@_) };
25 }
26
27 for my $cmd (qw/subscribe wait_for_messages/) {
28 dynsub uc $cmd, sub { $pubsub->$cmd(@_) };
29 }
30}
31
32sub cp { defined $contest ? "contest.$contest." : '' }
33
014ee8a6
MG
34sub problems () { SMEMBERS cp . 'problem' }
35sub contests () { SMEMBERS cp . 'contest' }
36sub users () { SMEMBERS cp . 'user' }
37sub jobcard () { GET cp . 'job' }
38
39sub job_results (_) { decode_json HGET cp . "job.$_[0]", 'results' }
40sub set_job_results ($+) { HSET cp . "job.$_[0]", 'results', encode_json $_[1] }
41sub job_inmeta (_) { decode_json HGET cp . "job.$_[0]", 'inmeta' }
42sub set_job_inmeta ($+) { HSET cp . "job.$_[0]", 'inmeta', encode_json $_[1] }
43sub problem_meta (_) { decode_json HGET cp . "problem.$_[0]", 'meta' }
44sub set_problem_meta ($+) { HSET cp . "problem.$_[0]", 'meta', encode_json $_[1] }
45sub job_daemon (_) { HGET cp . "job.$_[0]", 'daemon' }
46sub set_job_daemon ($$) { HSETNX cp . "job.$_[0]", 'daemon', $_[1] };
47
48sub defhash{
49 my ($name, @keys) = @_;
50 for my $key (@keys) {
51 dynsub "${name}_$key", sub (_) { HGET cp . "$name.$_[0]", $key };
52 dynsub "set_${name}_$key", sub ($$) { HSET cp . "$name.$_[0]", $key, $_[1] };
53 }
54
55 dynsub "edit_$name", sub {
56 my ($key, %values) = @_;
57 HMSET cp . "$name.$key", %values;
58 };
59
60 dynsub "insert_$name", sub {
61 my ($key, %values) = @_;
62 SADD cp . $name, $key or return;
63 HMSET cp . "$name.$key", %values;
64 };
65 dynsub "remove_$name", sub (_) {
66 my $key = shift;
67 SREM cp . $name, $key;
68 DEL cp . "$name.$key";
69 };
70
71 dynsub "push_$name", sub {
72 my $nr = INCR cp . $name;
73 HMSET cp . "$name.$nr", @_;
74 $nr
75 };
76}
77
a10ce53b 78defhash problem => qw/name level difficulty statement owner author private generator runner judge testcnt timeout olimit/;
014ee8a6
MG
79defhash contest => qw/start end name owner/;
80defhash job => qw/date errors extension filesize private problem result result_text user/;
db5da8ea 81defhash user => qw/name email lastjob town university level/;
014ee8a6
MG
82
83sub clean_job (_){
84 HDEL cp . "job.$_[0]", qw/result result_text results daemon/
85}
86
87sub mark_open {
88 my ($problem, $user) = @_;
89 HSETNX cp . 'open', "$problem.$user", time;
90}
91
92sub get_open {
93 my ($problem, $user) = @_;
94 HGET cp . 'open', "$problem.$user";
95}
96
97our @EXPORT = do {
98 no strict 'refs';
99 grep { $_ =~ /^[a-zA-Z]/ and exists &$_ } keys %{__PACKAGE__ . '::'};
100};
101
f7386aab
MG
1021;
103__END__
104
105=encoding utf-8
106
107=head1 NAME
108
109Gruntmaster::Data - Gruntmaster 6000 Online Judge -- database interface and tools
110
111=head1 SYNOPSIS
112
113 for my $problem (problems) {
114 say "Problem name: " . problem_name $problem;
115 say "Problem level: " . problem_level $problem;
116 ...
117 }
118
119=head1 DESCRIPTION
120
121Gruntmaster::Data is the Redis interface used by the Gruntmaster 6000 Online Judge. It exports many functions for talking to the database. All functions are exported by default.
122
123The current contest is selected by setting the C<< $Gruntmaster::Data::contest >> variable.
124
125 local $Gruntmaster::Data::contest = 'mycontest';
126 say 'There are' . jobcard . ' jobs in my contest';
127
128=head1 FUNCTIONS
129
130=head2 Redis
131
132Gruntmaster::Data exports some functions for talking directly to the Redis server. These functions should not normally be used, except for B<MULTI>, B<EXEC>, B<PUBLISH>, B<SUBSCRIBE> and B<WAIT_FOR_MESSAGES>.
133
d923d4bf 134These functions correspond to Redis commands. The current list is: B<< MULTI EXEC SMEMBERS GET HGET HGETALL HDEL HSET SADD SREM INCR HMSET HSETNX DEL PUBLISH SUBSCRIBE WAIT_FOR_MESSAGES >>.
f7386aab
MG
135
136=head2 Problems
137
138=over
139
140=item B<problems>
141
142Returns a list of problems in the current contest.
143
144=item B<problem_meta> I<$problem>
145
146Returns a problem's meta.
147
148=item B<set_problem_meta> I<$problem>, I<$meta>
149
150Sets a problem's meta.
151
152=item B<problem_name> I<$problem>
153
154Returns a problem's name.
155
156=item B<set_problem_name> I<$problem>, I<$name>
157
158Sets a problem's name.
159
160=item B<problem_level> I<$problem>
161
162Returns a problem's level. The levels are beginner, easy, medium, hard.
163
164=item B<set_problem_level> I<$problem>, I<$level>
165
166Sets a problem's level. The levels are beginner, easy, medium, hard.
167
d923d4bf
MG
168=item B<problem_difficulty> I<$problem>
169
170Returns a problem's difficulty.
171
172=item B<set_problem_difficulty> I<$problem>, I<$name>
173
174Sets a problem's difficulty.
175
f7386aab
MG
176=item B<problem_statement> I<$problem>
177
178Returns a problem's statement.
179
180=item B<set_problem_statement> I<$problem>, I<$statement>
181
182Sets a problem's statement.
183
184=item B<problem_owner> I<$problem>
185
186Returns a problem's owner.
187
188=item B<set_problem_owner> I<$problem>, I<$owner>
189
190Sets a problem's owner.
191
192=item B<problem_author> I<$problem>
193
194Returns a problem's author.
195
196=item B<set_problem_author> I<$problem>, I<$author>
197
198Sets a problem's author.
199
d923d4bf
MG
200=item B<problem_private> I<$problem>
201
202Returns a problem's private flag (true if the problem is private, false otherwise).
203
204=item B<set_problem_private> I<$problem>, I<$private>
205
206Sets a problem's private flag.
207
208=item B<problem_generator> I<$problem>
209
210Returns a problem's generator. The generators are File, Run and Undef. More might be added in the future.
211
212=item B<set_problem_generator> I<$problem>, I<$generator>
213
214Sets a problem's generator.
215
216=item B<problem_runner> I<$problem>
217
218Returns a problem's runner. The runners are File, Verifier and Interactive. More might be added in the future.
219
220=item B<set_problem_runner> I<$problem>, I<$runner>
221
222Sets a problem's runner.
223
224=item B<problem_judge> I<$problem>
225
226Returns a problem's judge. The judges are Absolute and Points. More might be added in the future.
227
228=item B<set_problem_judge> I<$problem>, I<$judge>
229
230Sets a problem's judge.
231
232=item B<problem_testcnt> I<$problem>
233
234Returns a problem's test count.
235
236=item B<set_problem_testcnt> I<$problem>, I<$testcnt>
237
238Sets a problem's test count.
239
240=item B<problem_timeout> I<$problem>
241
242Returns a problem's time limit, in seconds.
243
244=item B<set_problem_timeout> I<$problem>, I<$timeout>
245
246Sets a problem's time limit, in seconds.
247
248=item B<problem_olimit> I<$problem>
249
250Returns a problem's output limit, in bytes.
251
252=item B<set_problem_olimit> I<$problem>, I<$olimit>
253
254Sets a problem's output limit, in bytes.
255
f7386aab
MG
256=item B<get_open> I<$problem>, I<$user>
257
258Returns the time when I<$user> opened I<$problem>.
259
260=item B<mark_open> I<$problem>, I<$user>
261
262Sets the time when I<$user> opened I<$problem> to the current time. Does nothing if I<$user> has already opened I<$problem>.
263
264=item B<insert_problem> I<$id>, I<$key> => I<$value>, ...
265
266Inserts a problem with id I<$id> and the given initial configuration. Does nothing if a problem with id I<$id> already exists. Returns true if the problem was added, false otherwise.
267
268=item B<edit_problem> I<$id>, I<$key> => I<$value>, ...
269
270Updates the configuration of a problem. The values of the given keys are updated. All other keys/values are left intact.
271
272=item B<remove_problem> I<$id>
273
274Removes a problem.
275
276=back
277
278=head2 Contests
279
280B<<< WARNING: these functions only work correctly when C<< $Gruntmaster::Data::contest >> is undef >>>
281
282=over
283
284=item B<contests>
285
286Returns a list of contests.
287
288=item B<contest_start> I<$contest>
289
290Returns a contest's start time.
291
292=item B<set_contest_start> I<$contest>, I<$start>
293
294Sets a contest's start time.
295
296=item B<contest_end> I<$contest>
297
298Returns a contest's end time.
299
300=item B<set_contest_end> I<$contest>, I<$end>
301
302Sets a contest's end time.
303
304=item B<contest_name> I<$contest>
305
306Returns a contest's name.
307
308=item B<set_contest_name> I<$contest>, I<$name>
309
310Sets a contest's name.
311
312=item B<contest_owner> I<$contest>
313
314Returns a contest's owner.
315
316=item B<set_contest_owner> I<$contest>, I<$owner>
317
318Sets a contest's owner.
319
320=item B<insert_contest> I<$id>, I<$key> => I<$value>, ...
321
322Inserts a contest with id I<$id> and the given initial configuration. Does nothing if a contest with id I<$id> already exists. Returns true if the contest was added, false otherwise.
323
324=item B<edit_contest> I<$id>, I<$key> => I<$value>, ...
325
326Updates the configuration of a contest. The values of the given keys are updated. All other keys/values are left intact.
327
328=item B<remove_contest> I<$id>
329
330Removes a contest.
331
332=back
333
334=head2 Jobs
335
336=over
337
338=item B<jobcard>
339
340Returns the number of jobs in the database.
341
342=item B<job_results> I<$job>
343
344Returns an array of job results. Each element corresponds to a test and is a hashref with keys B<id> (test number), B<result> (result code, see L<Gruntmaster::Daemon::Constants>), B<result_text> (result description) and B<time> (time taken).
345
346=item B<set_job_results> I<$job>, I<$results>
347
348Sets a job's results.
349
350=item B<job_inmeta> I<$job>
351
352Returns a job's meta.
353
354=item B<set_job_inmeta> I<$job>, I<$meta>
355
356Sets a job's meta.
357
358=item B<job_daemon> I<$job>
359
360Returns the hostname:pid of the daemon which ran this job.
361
362=item B<set_job_daemon> I<$job>, I<$hostname_and_pid>
363
364If the job has no associated daemon, it sets the daemon and returns true. Otherwise it returns false without setting the daemon.
365
366=item B<job_date> I<$job>
367
368Returns a job's submit date.
369
370=item B<set_job_date> I<$job>, I<$date>
371
372Sets a job's submit date.
373
374=item B<job_errors> I<$job>
375
376Returns a job's compile errors.
377
378=item B<set_job_errors> I<$job>, I<$errors>
379
380Sets a job's compile errors.
381
382=item B<job_extension> I<$job>
383
384Returns a job's file name extension (e.g. "cpp", "pl", "java").
385
386=item B<set_job_extension> I<$job>, I<$extension>
387
388Sets a job's file name extension.
389
390=item B<job_filesize> I<$job>
391
392Returns a job's source file size, in bytes.
393
394=item B<set_job_filesize> I<$job>, I<$filesize>
395
396Sets a job's source file size, in bytes.
397
398=item B<job_private> I<$job>
399
400Returns the value of a job's private flag.
401
402=item B<set_job_private> I<$job>, I<$private>
403
404Sets the value of a job's private flag.
405
406=item B<job_problem> I<$job>
407
408Returns a job's problem.
409
410=item B<set_job_problem> I<$job>, I<$problem>
411
412Sets a job's problem.
413
414=item B<job_result> I<$job>
415
416Returns a job's result code. Possible result codes are described in L<Gruntmaster::Daemon::Constants>
417
418=item B<set_job_result> I<$job>, I<$result>
419
420Sets a job's result code.
421
422=item B<job_result_text> I<$job>
423
424Returns a job's result text.
425
426=item B<set_job_result_text> I<$job>, I<$result_text>
427
428Sets a job's result text.
429
430=item B<job_user> I<$job>
431
432Returns the user who submitted a job.
433
434=item B<set_job_user> I<$job>, I<$user>
435
436Sets the suer who submitted a job.
437
438=item B<clean_job> I<$job>
439
440Removes a job's daemon, result code, result text and result array.
441
442=item B<push_job> I<$key> => I<$value>, ...
443
444Inserts a job with a given initial configuration. Returns the id of the newly-added job.
445
446=item B<edit_job> I<$id>, I<$key> => I<$value>, ...
447
448Updates the configuration of a job. The values of the given keys are updated. All other keys/values are left intact.
449
450=item B<remove_job> I<$id>
451
452Removes a job.
453
454=back
455
456=head2 Users
457
458B<<< WARNING: these functions only work correctly when C<< $Gruntmaster::Data::contest >> is undef >>>
459
460=over
461
462=item B<users>
463
464Returns a list of users.
465
466=item B<user_name> I<$user>
467
468Returns a user's full name.
469
470=item B<set_user_name> I<$user>, I<$name>
471
472Sets a user's full name.
473
474=item B<user_email> I<$user>
475
476Returns a user's email address.
477
478=item B<set_user_email> I<$user>, I<$email>
479
480Sets a user's email address.
481
d923d4bf
MG
482=item B<user_lastjob> I<$user>
483
484Returns the time (seconds since epoch) when the user last submitted a solution.
485
486=item B<set_user_lastjob> I<$user>, I<$lastjob>
487
488Sets the time (seconds since epoch) when the user last submitted a solution.
489
f7386aab
MG
490=item B<user_town> I<$user>
491
492Returns a user's town.
493
494=item B<set_user_town> I<$user>, I<$town>
495
496Sets a user's town.
497
498=item B<user_university> I<$user>
499
500Returns a user's university/highschool/place of work/etc.
501
502=item B<set_user_university> I<$user>, I<$university>
503
504Sets a user's university, highschool/place of work/etc.
505
506=item B<user_level> I<$user>
507
508Returns a user's current level of study. One of 'Highschool', 'Undergraduate', 'Master', 'Doctorate' or 'Other'.
509
510=item B<set_user_level> I<$user>, I<$level>
511
512Sets a user's current level of study.
513
514=item B<insert_user> I<$id>, I<$key> => I<$value>, ...
515
516Inserts a user with id I<$id> and the given initial configuration. Does nothing if a user with id I<$id> already exists. Returns true if the user was added, false otherwise.
517
518=item B<edit_user> I<$id>, I<$key> => I<$value>, ...
519
520Updates the configuration of a user. The values of the given keys are updated. All other keys/values are left intact.
521
522=item B<remove_user> I<$id>
523
524Removes a user.
525
526=back
527
528=head1 AUTHOR
529
530Marius Gavrilescu E<lt>marius@ieval.roE<gt>
531
532=head1 COPYRIGHT AND LICENSE
533
534Copyright (C) 2014 by Marius Gavrilescu
535
536This library is free software: you can redistribute it and/or modify
537it under the terms of the GNU Affero General Public License as published by
538the Free Software Foundation, either version 3 of the License, or
539(at your option) any later version.
540
541
542=cut
This page took 0.039426 seconds and 4 git commands to generate.