def run(self): for sub in self.submissions: if self.skip: submission = OldSubmission.objects.get(pk=sub) if SubmissionStatus.is_judged(submission.status): continue DispatcherThread(sub).start()
def status_detail_display(self): r, l = [], self.status_detail_list status_dictionary = dict(STATUS_CHOICE) count = len(l) re_count, last_group = 1, 0 for index, s in enumerate(l, start=1): u, v = -233, '%d/%d' % (index, count ) # Magic number: display nothing if 'verdict' in s: if 'group' in s: if s['group'] != last_group: re_count = 1 last_group = s['group'] u = s['verdict'] v = '%d-%d' % (s['group'], re_count) re_count += 1 if SubmissionStatus.is_judged(s['verdict']): u = s['verdict'] t = status_dictionary[u] if s['verdict'] in ( SubmissionStatus.ACCEPTED, SubmissionStatus.SCORED, ): t += ', %.3fs' % s.get('time', 0.0) elif s['verdict'] == SubmissionStatus.RUNTIME_ERROR: t += ', %s' % s.get('message', 'NaN') v += ': ' + t elif 'group' in s: v += ": Skipped" if 'point' in s: v += ' (%.1f)' % s['point'] r.append((u, v)) return r
def get(self, request, pk, sid): submission = get_object_or_404(Submission, problem_id=pk, author=self.request.user, pk=sid) if submission.is_judged: if is_case_download_available(self.request.user, pk): submission.allow_case_download = True if SubmissionStatus.is_accepted(submission.status): recommended_problems = recommendation.coming_up_magic_problems(submission.author_id) if recommended_problems: submission.next_problem = recommended_problems[0] return HttpResponse(render_submission(submission, permission=get_permission_for_submission(request.user, submission), hide_problem=True, rejudge_available=False, hide_reward=True))
def calculate_problems(contest: Contest, problems: list, snapshot: timedelta=None): """ :param contest: :param problems: list of ContestProblems :param snapshot: :return: { <problem_id>: { user_ac: int, user_tot: int, ac: int, tot: int, first_yes: None/int } } """ problem_ids = list(map(lambda p: p.problem_id, problems)) ans = {problem_id: dict(user_ac=set(), user_tot=dict(), ac=0, tot=0, first_yes_time=None, first_yes_by=None) for problem_id in problem_ids} for submission in get_submission_filter(contest, snapshot, problem_id__in=problem_ids): pstat = ans[submission.problem_id] status = submission.status if SubmissionStatus.is_accepted(status): pstat["user_ac"].add(submission.author_id) pstat["ac"] += 1 if submission.contest_time is not None and pstat["first_yes_time"] is None: pstat["first_yes_time"] = submission.contest_time pstat["first_yes_by"] = submission.author_id if (submission.author_id in pstat["user_tot"] and pstat["user_tot"][submission.author_id] < submission.status_percent) or \ submission.author_id not in pstat["user_tot"]: pstat["user_tot"][submission.author_id] = submission.status_percent pstat["tot"] += 1 for p in problems: pstat = ans[p.problem_id] p.ac_user_count = len(pstat["user_ac"]) p.total_user_count = len(pstat["user_tot"]) p.ac_count = pstat["ac"] p.total_count = pstat["tot"] p.first_yes_time = pstat["first_yes_time"] p.first_yes_by = pstat["first_yes_by"] p.max_score = max(pstat["user_tot"].values()) if p.total_user_count > 0 else 0.0 p.avg_score = sum(pstat["user_tot"].values()) / p.total_user_count if p.total_user_count > 0 else 0.0 return ans
def get(self, request, pk, sid): submission = get_object_or_404(Submission, problem_id=pk, author=self.request.user, pk=sid) if submission.is_judged: if is_case_download_available(self.request.user, pk): submission.allow_case_download = True if SubmissionStatus.is_accepted(submission.status): try: user_status = UserStatus.objects.get(user_id=submission.author_id, contest_id=0) for problem_id in filter(lambda x: x, map(int, user_status.predict_list.split(","))): problem = Problem.objects.get(id=problem_id) if problem.visible: submission.next_problem = problem break except: pass return HttpResponse(render_submission(submission, permission=get_permission_for_submission(request.user, submission), hide_problem=True, rejudge_available=False))
def get(self, request, cid, sid): if not request.user.is_authenticated: raise PermissionDenied submission = get_contest_submission(sid, cid, author_id=request.user.pk) if self.contest.case_public and submission.is_judged and \ is_case_download_available(self.request.user, submission.problem_id, submission.contest_id): submission.allow_case_download = True if SubmissionStatus.is_accepted(submission.status): recommended_problems = self.get_recommended_problem_list() if recommended_problems: submission.next_problem = recommended_problems[0] return HttpResponse( render_submission(submission, permission=get_permission_for_submission( request.user, submission), hide_problem=True, rejudge_available=False))
def is_judged(self): return SubmissionStatus.is_judged(self.status)
def calculate_participants(contest: Contest, participants: list, snapshot: timedelta=None): """ :param contest :param participants: list of ContestParticipants :param snapshot: submissions in the first `snapshot` seconds will be effective :return { <user_id>: { penalty: int (seconds), score: int, is_confirmed: boolean detail: { <problem_id>: { solved: boolean attempt: int (submission count including the first accepted one), score: int (individual score for each problem), time: int (first accept solution time, in seconds), partial: boolean upsolve: int (positive for accepted, negative for unaccepted, score if partial) } } } } This will be saved to participants without writing to database (can do that outside) Penalty is the same for all rules: Every failed submission till the accepted one will add `penalty_counts` (default 1200) to it. And the accepted one will add the time (seconds) to it Score methods depend on the contest rule: 1. ACM rule: individual score is all one, total score is solved problem number. 2. OI rule: individual score is problem weight times the weight of cases passed (round to integer). 3. CF rule: individual score is problem weight, but will only be available if the solution is by all means correct. How much percent one can get is a bit complicated: 1) The total percent will decrease from contest beginning to contest end from 100% to 50%. 2) Every failed submission will induce a 50-point loss to the score 3) The final score, once accepted will not be lower than 30% of the total score. """ user_ids = list(map(lambda p: p.user_id, participants)) ans = {author_id: dict(detail=dict(), is_confirmed=False) for author_id in user_ids} contest_length = contest.length if contest_length is not None: contest_length = contest_length.total_seconds() for submission in get_submission_filter(contest, snapshot, author_id__in=user_ids): status = submission.status detail = ans[submission.author_id]['detail'] author_id = submission.author_id ans[author_id]['is_confirmed'] = True detail.setdefault(submission.problem_id, {'solved': False, 'attempt': 0, 'score': 0, 'time': 0, 'waiting': False, 'pass_time': '', 'partial': False, 'upsolve': 0}) d = detail[submission.problem_id] if not SubmissionStatus.is_judged(submission.status): d['waiting'] = True continue if SubmissionStatus.is_scored(submission.status): d['partial'] = True if not SubmissionStatus.is_penalty(status): continue # This is probably CE or SE ... contest_problem = contest.get_contest_problem(submission.problem_id) if not contest_problem: # This problem has been probably deleted continue pass_time = str(submission.create_time.strftime('%Y-%m-%d %H:%M:%S')) time = int(submission.contest_time.total_seconds()) if submission.contest_time is not None else 0 score = 0 EPS = 1E-2 if contest.scoring_method == 'oi' or contest.scoring_method == "subtask": submission.contest_problem = contest_problem score = submission.status_score elif contest.scoring_method == 'acm' and SubmissionStatus.is_accepted(status): score = 1 elif contest.scoring_method == 'cf' and SubmissionStatus.is_accepted(status): score = int(max(contest_problem.weight * 0.3, contest_problem.weight * (1 - 0.5 * time / contest_length) - d['attempt'] * 50) + EPS) elif contest.scoring_method == 'tcmtime' and SubmissionStatus.is_accepted(status): score = contest_problem.weight # upsolve submission if d['partial']: d['upsolve'] = max(d['upsolve'], score) elif d['upsolve'] <= 0: d['upsolve'] -= 1 if SubmissionStatus.is_accepted(status): d['upsolve'] = abs(d['upsolve']) if contest.contest_type == 0 and submission.contest_time is None: d['upsolve_enable'] = True continue if contest.last_counts or not \ (d['solved'] or (contest.scoring_method != 'oi' and d['score'] > 0 and d['score'] >= score)): # every submission has to be calculated in OI # We have to tell whether this is the best if not contest.last_counts: d['score'] = max(d['score'], score) else: d['score'] = score d['attempt'] += 1 d.update(solved=SubmissionStatus.is_accepted(status), time=time, pass_time=pass_time) for v in ans.values(): for p in v['detail']: d = v['detail'][p] if 'upsolve_enable' not in d: d['upsolve'] = 0 else: d.pop('upsolve_enable', None) if contest.start_time is None: penalty = 0 elif contest.scoring_method == 'oi': penalty = sum(map(lambda x: max(x['attempt'], 0) * contest.penalty_counts + x['time'], v['detail'].values())) else: penalty = sum(map(lambda x: max(x['attempt'] - 1, 0) * contest.penalty_counts + x['time'], filter(lambda x: x['solved'], v['detail'].values()))) v.update(penalty=penalty, score=sum(map(lambda x: x['score'], v['detail'].values()))) for p in participants: p.detail = ans[p.user_id]["detail"] p.score = ans[p.user_id]["score"] p.penalty = ans[p.user_id]["penalty"] p.is_confirmed = ans[p.user_id]["is_confirmed"] return ans
def on_receive_data(data): judge_time = datetime.fromtimestamp(data['timestamp']) if submission.judge_end_time and judge_time < submission.judge_end_time: return True if data.get('status') == 'received': if 'message' in data: submission.status_message = data['message'] else: submission.status_message = '' submission.status = process_accepted(data.get('verdict', SubmissionStatus.JUDGING)) details = data.get('detail', []) if not group_config["on"]: # Add points to details score = 0 try: for index, detail in enumerate(details): if 'point' not in detail: if detail.get('verdict') == 0: detail['point'] = point_query.get(case_list[index], 10) / total_score * 100 score += detail.get('point', 0) except: pass submission.status_percent = score display_details = details + [{}] * max(0, len(case_list) - len(details)) submission.status_detail_list = display_details submission.status_test = process_failed_test(display_details) submission.judge_server = data.get('server', 0) submission.save(update_fields=['status_message', 'status_detail','status', 'status_percent', 'status_test', 'judge_server']) if SubmissionStatus.is_judged(data.get('verdict')): if group_config["on"] and data.get('verdict') != SubmissionStatus.COMPILE_ERROR: score = 0 records = [] accept_case_counter, total_case_counter = Counter(), Counter() for index, detail in enumerate(details): group_id = group_config["group_list"][index] if detail.get('verdict') == 0: accept_case_counter[group_id] += 1 total_case_counter[group_id] += 1 for group_id in range(1, group_config["group_count"] + 1): get_score = 0 if accept_case_counter[group_id] == total_case_counter[group_id] and \ total_case_counter[group_id] > 0: get_score = point_query[group_id - 1] score += get_score records.append("Subtask #%d: " % group_id + "%d/%d cases passed. %d points." % (accept_case_counter[group_id], total_case_counter[group_id], get_score)) records.append("Total: %d/%d" % (score, total_score)) submission.status_message = "\n".join(records) submission.status_percent = score / total_score * 100 try: submission.status_time = max(map(lambda d: d.get('time', 0.0), submission.status_detail_list)) except ValueError: pass submission.judge_end_time = judge_time submission.save(update_fields=['status_time', 'judge_end_time', 'status_message', 'status_percent']) if submission.status == SubmissionStatus.ACCEPTED: # Add reward _, created = ProblemRewardStatus.objects.get_or_create(problem_id=submission.problem_id, user_id=submission.author_id) if created: if submission.contest_time is not None: reward_contest_ac(submission.author, 4 * problem.level ** 2, submission.contest_id) else: reward_problem_ac(submission.author, problem.reward, submission.problem_id) invalidate_user(submission.author_id, submission.contest_id) invalidate_problem(submission.problem) if callback: callback() return True return False else: submission.status = SubmissionStatus.SYSTEM_ERROR submission.status_message = data['message'] submission.save(update_fields=['status', 'status_message']) return True