+sub rerun_problem {
+ my ($problem) = @_;
+ _query rerun_problem_sth => $problem;
+ purge '/log/';
+}
+
+sub rerun_job {
+ my ($id) = @_;
+ _query rerun_job_sth => $id;
+ purge '/log/';
+ purge "/log/$id";
+}
+
+sub take_job {
+ my ($daemon) = @_;
+ my $id = _query(take_job_sth => $daemon)->list;
+ return unless $id;
+ purge '/log/';
+ purge "/log/$id";
+ db->select(jobs => '*', {id => $id})->hash
+}
+
+sub finish_job {
+ my ($job, $private, %args) = @_;
+ db->update(jobs => \%args, {id => $job->{id}});
+ purge '/log/';
+ purge '/log/' . $job->{id};
+ return if $private;
+ my $status = {
+ problem => $job->{problem},
+ owner => $job->{owner},
+ job => $job->{id},
+ solved => ($args{result} ? 0 : 1),
+ };
+ eval {
+ db->insert(problem_status => $status)
+ } or db->update(problem_status => $status, {owner => $job->{owner}, problem => $job->{problem}});
+ purge '/us/' . $job->{owner};
+}
+
+sub open_problem {
+ my ($contest, $problem, $owner, $time) = @_;
+ my $ct = contest_entry($contest);
+ return unless $ct->{id} && $time >= $ct->{start} && $time < $ct->{stop}; ## no critic (ProhibitNegativeExpressionsInUnlessAndUntilConditions)
+ eval { db->insert(opens => { ## no critic (RequireCheckingReturnValueOfEval)
+ contest => $contest,
+ problem => $problem,
+ owner => $owner,
+ time => $time}) };
+}
+