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 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