Exemplo n.º 1
0
 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))
Exemplo n.º 2
0
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
Exemplo n.º 3
0
 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))
Exemplo n.º 4
0
 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))
Exemplo n.º 5
0
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