Add new IOI format

This commit is contained in:
cuom1999 2022-11-21 22:05:35 -06:00
parent af8ab310ce
commit dbb189444d
13 changed files with 327 additions and 52 deletions

View file

@ -3,4 +3,5 @@ from judge.contest_format.default import DefaultContestFormat
from judge.contest_format.ecoo import ECOOContestFormat
from judge.contest_format.icpc import ICPCContestFormat
from judge.contest_format.ioi import IOIContestFormat
from judge.contest_format.new_ioi import NewIOIContestFormat
from judge.contest_format.registry import choices, formats

View file

@ -107,7 +107,7 @@ class AtCoderContestFormat(DefaultContestFormat):
self.handle_frozen_state(participation, format_data)
participation.cumtime = cumtime + penalty
participation.score = points
participation.score = round(points, self.contest.points_precision)
participation.tiebreaker = 0
participation.format_data = format_data
participation.save()
@ -141,7 +141,7 @@ class AtCoderContestFormat(DefaultContestFormat):
"contest_user_submissions_ajax",
args=[
self.contest.key,
participation.user.user.username,
participation.id,
contest_problem.problem.code,
],
),

View file

@ -56,7 +56,7 @@ class DefaultContestFormat(BaseContestFormat):
self.handle_frozen_state(participation, format_data)
participation.cumtime = max(cumtime, 0)
participation.score = points
participation.score = round(points, self.contest.points_precision)
participation.tiebreaker = 0
participation.format_data = format_data
participation.save()
@ -82,7 +82,7 @@ class DefaultContestFormat(BaseContestFormat):
"contest_user_submissions_ajax",
args=[
self.contest.key,
participation.user.user.username,
participation.id,
contest_problem.problem.code,
],
),

View file

@ -117,7 +117,7 @@ class ECOOContestFormat(DefaultContestFormat):
self.handle_frozen_state(participation, format_data)
participation.cumtime = cumtime
participation.score = points
participation.score = round(points, self.contest.points_precision)
participation.tiebreaker = 0
participation.format_data = format_data
participation.save()
@ -151,7 +151,7 @@ class ECOOContestFormat(DefaultContestFormat):
"contest_user_submissions_ajax",
args=[
self.contest.key,
participation.user.user.username,
participation.id,
contest_problem.problem.code,
],
),

View file

@ -109,7 +109,7 @@ class ICPCContestFormat(DefaultContestFormat):
self.handle_frozen_state(participation, format_data)
participation.cumtime = max(0, cumtime + penalty)
participation.score = score
participation.score = round(score, self.contest.points_precision)
participation.tiebreaker = last # field is sorted from least to greatest
participation.format_data = format_data
participation.save()
@ -143,7 +143,7 @@ class ICPCContestFormat(DefaultContestFormat):
"contest_user_submissions_ajax",
args=[
self.contest.key,
participation.user.user.username,
participation.id,
contest_problem.problem.code,
],
),

View file

@ -81,7 +81,7 @@ class IOIContestFormat(DefaultContestFormat):
self.handle_frozen_state(participation, format_data)
participation.cumtime = max(cumtime, 0)
participation.score = score
participation.score = round(score, self.contest.points_precision)
participation.tiebreaker = 0
participation.format_data = format_data
participation.save()
@ -107,7 +107,7 @@ class IOIContestFormat(DefaultContestFormat):
"contest_user_submissions_ajax",
args=[
self.contest.key,
participation.user.user.username,
participation.id,
contest_problem.problem.code,
],
),

View file

@ -0,0 +1,127 @@
from django.db import connection
from django.utils.translation import gettext as _, gettext_lazy
from judge.contest_format.ioi import IOIContestFormat
from judge.contest_format.registry import register_contest_format
from judge.timezone import from_database_time, to_database_time
@register_contest_format("ioi16")
class NewIOIContestFormat(IOIContestFormat):
name = gettext_lazy("New IOI")
config_defaults = {"cumtime": False}
"""
cumtime: Specify True if time penalties are to be computed. Defaults to False.
"""
def get_results_by_subtask(self, participation, include_frozen=False):
frozen_time = self.contest.end_time
if self.contest.freeze_after and not include_frozen:
frozen_time = participation.start + self.contest.freeze_after
with connection.cursor() as cursor:
cursor.execute(
"""
SELECT q.prob,
q.prob_points,
MIN(q.date) as `date`,
q.batch_points,
q.total_batch_points,
q.batch,
q.subid
FROM (
SELECT cp.id as `prob`,
cp.points as `prob_points`,
sub.id as `subid`,
sub.date as `date`,
tc.points as `points`,
tc.batch as `batch`,
SUM(tc.points) as `batch_points`,
SUM(tc.total) as `total_batch_points`
FROM judge_contestproblem cp
INNER JOIN
judge_contestsubmission cs
ON (cs.problem_id = cp.id AND cs.participation_id = %s)
LEFT OUTER JOIN
judge_submission sub
ON (sub.id = cs.submission_id AND sub.status = 'D')
INNER JOIN judge_submissiontestcase tc
ON sub.id = tc.submission_id
WHERE sub.date < %s
GROUP BY cp.id, tc.batch, sub.id
) q
INNER JOIN (
SELECT prob, batch, MAX(r.batch_points) as max_batch_points
FROM (
SELECT cp.id as `prob`,
tc.batch as `batch`,
SUM(tc.points) as `batch_points`
FROM judge_contestproblem cp
INNER JOIN
judge_contestsubmission cs
ON (cs.problem_id = cp.id AND cs.participation_id = %s)
LEFT OUTER JOIN
judge_submission sub
ON (sub.id = cs.submission_id AND sub.status = 'D')
INNER JOIN judge_submissiontestcase tc
ON sub.id = tc.submission_id
GROUP BY cp.id, tc.batch, sub.id
) r
GROUP BY prob, batch
) p
ON p.prob = q.prob AND (p.batch = q.batch OR p.batch is NULL AND q.batch is NULL)
WHERE p.max_batch_points = q.batch_points
GROUP BY q.prob, q.batch
""",
(participation.id, to_database_time(frozen_time), participation.id),
)
return cursor.fetchall()
def update_participation(self, participation):
cumtime = 0
score = 0
format_data = {}
for (
problem_id,
problem_points,
time,
subtask_points,
total_subtask_points,
subtask,
sub_id,
) in self.get_results_by_subtask(participation):
problem_id = str(problem_id)
time = from_database_time(time)
if self.config["cumtime"]:
dt = (time - participation.start).total_seconds()
else:
dt = 0
if format_data.get(problem_id) is None:
format_data[problem_id] = {"points": 0, "time": 0, "total_points": 0}
format_data[problem_id]["points"] += subtask_points
format_data[problem_id]["time"] = max(dt, format_data[problem_id]["time"])
format_data[problem_id]["problem_points"] = problem_points
format_data[problem_id]["total_points"] += total_subtask_points
for problem_data in format_data.values():
if not problem_data["total_points"]:
continue
penalty = problem_data["time"]
problem_data["points"] = (
problem_data["points"]
/ problem_data["total_points"]
* problem_data["problem_points"]
)
if self.config["cumtime"] and points:
cumtime += penalty
score += problem_data["points"]
self.handle_frozen_state(participation, format_data)
participation.cumtime = max(cumtime, 0)
participation.score = round(score, self.contest.points_precision)
participation.tiebreaker = 0
participation.format_data = format_data
participation.save()