Add new IOI format
This commit is contained in:
parent
af8ab310ce
commit
dbb189444d
13 changed files with 327 additions and 52 deletions
|
@ -543,7 +543,7 @@ urlpatterns = [
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
url(
|
url(
|
||||||
r"^/submissions/(?P<user>\w+)/(?P<problem>\w+)/ajax",
|
r"^/submissions/(?P<participation>\d+)/(?P<problem>\w+)/ajax",
|
||||||
paged_list_view(
|
paged_list_view(
|
||||||
submission.UserContestSubmissionsAjax,
|
submission.UserContestSubmissionsAjax,
|
||||||
"contest_user_submissions_ajax",
|
"contest_user_submissions_ajax",
|
||||||
|
|
|
@ -3,4 +3,5 @@ from judge.contest_format.default import DefaultContestFormat
|
||||||
from judge.contest_format.ecoo import ECOOContestFormat
|
from judge.contest_format.ecoo import ECOOContestFormat
|
||||||
from judge.contest_format.icpc import ICPCContestFormat
|
from judge.contest_format.icpc import ICPCContestFormat
|
||||||
from judge.contest_format.ioi import IOIContestFormat
|
from judge.contest_format.ioi import IOIContestFormat
|
||||||
|
from judge.contest_format.new_ioi import NewIOIContestFormat
|
||||||
from judge.contest_format.registry import choices, formats
|
from judge.contest_format.registry import choices, formats
|
||||||
|
|
|
@ -107,7 +107,7 @@ class AtCoderContestFormat(DefaultContestFormat):
|
||||||
|
|
||||||
self.handle_frozen_state(participation, format_data)
|
self.handle_frozen_state(participation, format_data)
|
||||||
participation.cumtime = cumtime + penalty
|
participation.cumtime = cumtime + penalty
|
||||||
participation.score = points
|
participation.score = round(points, self.contest.points_precision)
|
||||||
participation.tiebreaker = 0
|
participation.tiebreaker = 0
|
||||||
participation.format_data = format_data
|
participation.format_data = format_data
|
||||||
participation.save()
|
participation.save()
|
||||||
|
@ -141,7 +141,7 @@ class AtCoderContestFormat(DefaultContestFormat):
|
||||||
"contest_user_submissions_ajax",
|
"contest_user_submissions_ajax",
|
||||||
args=[
|
args=[
|
||||||
self.contest.key,
|
self.contest.key,
|
||||||
participation.user.user.username,
|
participation.id,
|
||||||
contest_problem.problem.code,
|
contest_problem.problem.code,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -56,7 +56,7 @@ class DefaultContestFormat(BaseContestFormat):
|
||||||
|
|
||||||
self.handle_frozen_state(participation, format_data)
|
self.handle_frozen_state(participation, format_data)
|
||||||
participation.cumtime = max(cumtime, 0)
|
participation.cumtime = max(cumtime, 0)
|
||||||
participation.score = points
|
participation.score = round(points, self.contest.points_precision)
|
||||||
participation.tiebreaker = 0
|
participation.tiebreaker = 0
|
||||||
participation.format_data = format_data
|
participation.format_data = format_data
|
||||||
participation.save()
|
participation.save()
|
||||||
|
@ -82,7 +82,7 @@ class DefaultContestFormat(BaseContestFormat):
|
||||||
"contest_user_submissions_ajax",
|
"contest_user_submissions_ajax",
|
||||||
args=[
|
args=[
|
||||||
self.contest.key,
|
self.contest.key,
|
||||||
participation.user.user.username,
|
participation.id,
|
||||||
contest_problem.problem.code,
|
contest_problem.problem.code,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -117,7 +117,7 @@ class ECOOContestFormat(DefaultContestFormat):
|
||||||
|
|
||||||
self.handle_frozen_state(participation, format_data)
|
self.handle_frozen_state(participation, format_data)
|
||||||
participation.cumtime = cumtime
|
participation.cumtime = cumtime
|
||||||
participation.score = points
|
participation.score = round(points, self.contest.points_precision)
|
||||||
participation.tiebreaker = 0
|
participation.tiebreaker = 0
|
||||||
participation.format_data = format_data
|
participation.format_data = format_data
|
||||||
participation.save()
|
participation.save()
|
||||||
|
@ -151,7 +151,7 @@ class ECOOContestFormat(DefaultContestFormat):
|
||||||
"contest_user_submissions_ajax",
|
"contest_user_submissions_ajax",
|
||||||
args=[
|
args=[
|
||||||
self.contest.key,
|
self.contest.key,
|
||||||
participation.user.user.username,
|
participation.id,
|
||||||
contest_problem.problem.code,
|
contest_problem.problem.code,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -109,7 +109,7 @@ class ICPCContestFormat(DefaultContestFormat):
|
||||||
|
|
||||||
self.handle_frozen_state(participation, format_data)
|
self.handle_frozen_state(participation, format_data)
|
||||||
participation.cumtime = max(0, cumtime + penalty)
|
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.tiebreaker = last # field is sorted from least to greatest
|
||||||
participation.format_data = format_data
|
participation.format_data = format_data
|
||||||
participation.save()
|
participation.save()
|
||||||
|
@ -143,7 +143,7 @@ class ICPCContestFormat(DefaultContestFormat):
|
||||||
"contest_user_submissions_ajax",
|
"contest_user_submissions_ajax",
|
||||||
args=[
|
args=[
|
||||||
self.contest.key,
|
self.contest.key,
|
||||||
participation.user.user.username,
|
participation.id,
|
||||||
contest_problem.problem.code,
|
contest_problem.problem.code,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -81,7 +81,7 @@ class IOIContestFormat(DefaultContestFormat):
|
||||||
|
|
||||||
self.handle_frozen_state(participation, format_data)
|
self.handle_frozen_state(participation, format_data)
|
||||||
participation.cumtime = max(cumtime, 0)
|
participation.cumtime = max(cumtime, 0)
|
||||||
participation.score = score
|
participation.score = round(score, self.contest.points_precision)
|
||||||
participation.tiebreaker = 0
|
participation.tiebreaker = 0
|
||||||
participation.format_data = format_data
|
participation.format_data = format_data
|
||||||
participation.save()
|
participation.save()
|
||||||
|
@ -107,7 +107,7 @@ class IOIContestFormat(DefaultContestFormat):
|
||||||
"contest_user_submissions_ajax",
|
"contest_user_submissions_ajax",
|
||||||
args=[
|
args=[
|
||||||
self.contest.key,
|
self.contest.key,
|
||||||
participation.user.user.username,
|
participation.id,
|
||||||
contest_problem.problem.code,
|
contest_problem.problem.code,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
127
judge/contest_format/new_ioi.py
Normal file
127
judge/contest_format/new_ioi.py
Normal 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()
|
31
judge/migrations/0140_alter_contest_format_name.py
Normal file
31
judge/migrations/0140_alter_contest_format_name.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# Generated by Django 3.2.16 on 2022-11-21 22:30
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("judge", "0139_contest_freeze_after"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="contest",
|
||||||
|
name="format_name",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[
|
||||||
|
("atcoder", "AtCoder"),
|
||||||
|
("default", "Default"),
|
||||||
|
("ecoo", "ECOO"),
|
||||||
|
("icpc", "ICPC"),
|
||||||
|
("ioi", "IOI"),
|
||||||
|
("ioi16", "New IOI"),
|
||||||
|
],
|
||||||
|
default="default",
|
||||||
|
help_text="The contest format module to use.",
|
||||||
|
max_length=32,
|
||||||
|
verbose_name="contest format",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -33,7 +33,7 @@ from django.views.generic import ListView
|
||||||
|
|
||||||
from judge import event_poster as event
|
from judge import event_poster as event
|
||||||
from judge.highlight_code import highlight_code
|
from judge.highlight_code import highlight_code
|
||||||
from judge.models import Contest
|
from judge.models import Contest, ContestParticipation
|
||||||
from judge.models import Language
|
from judge.models import Language
|
||||||
from judge.models import Problem
|
from judge.models import Problem
|
||||||
from judge.models import ProblemTestCase
|
from judge.models import ProblemTestCase
|
||||||
|
@ -472,10 +472,17 @@ class SubmissionsListBase(DiggPaginatorMixin, TitleMixin, ListView):
|
||||||
|
|
||||||
class UserMixin(object):
|
class UserMixin(object):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
if "user" not in kwargs:
|
if "user" not in kwargs and "participation" not in kwargs:
|
||||||
raise ImproperlyConfigured("Must pass a user")
|
raise ImproperlyConfigured("Must pass a user or participation")
|
||||||
self.profile = get_object_or_404(Profile, user__username=kwargs["user"])
|
if "user" in kwargs:
|
||||||
self.username = kwargs["user"]
|
self.profile = get_object_or_404(Profile, user__username=kwargs["user"])
|
||||||
|
self.username = kwargs["user"]
|
||||||
|
else:
|
||||||
|
self.participation = get_object_or_404(
|
||||||
|
ContestParticipation, id=kwargs["participation"]
|
||||||
|
)
|
||||||
|
self.profile = self.participation.user
|
||||||
|
self.username = self.profile.user.username
|
||||||
if self.profile == request.profile:
|
if self.profile == request.profile:
|
||||||
self.include_frozen = True
|
self.include_frozen = True
|
||||||
return super(UserMixin, self).get(request, *args, **kwargs)
|
return super(UserMixin, self).get(request, *args, **kwargs)
|
||||||
|
@ -828,6 +835,53 @@ class UserContestSubmissionsAjax(UserContestSubmissions):
|
||||||
return s.date - self.contest.start_time
|
return s.date - self.contest.start_time
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_best_subtask_points(self):
|
||||||
|
if self.contest.format_name == "ioi16":
|
||||||
|
contest_problem = self.contest.contest_problems.get(problem=self.problem)
|
||||||
|
best_subtasks = {}
|
||||||
|
total_points = 0
|
||||||
|
problem_points = 0
|
||||||
|
achieved_points = 0
|
||||||
|
|
||||||
|
for (
|
||||||
|
problem_id,
|
||||||
|
pp,
|
||||||
|
time,
|
||||||
|
subtask_points,
|
||||||
|
total_subtask_points,
|
||||||
|
subtask,
|
||||||
|
sub_id,
|
||||||
|
) in self.contest.format.get_results_by_subtask(
|
||||||
|
self.participation, self.include_frozen
|
||||||
|
):
|
||||||
|
if contest_problem.id != problem_id or total_subtask_points == 0:
|
||||||
|
continue
|
||||||
|
if not subtask:
|
||||||
|
subtask = 0
|
||||||
|
problem_points = pp
|
||||||
|
submission = Submission.objects.get(id=sub_id)
|
||||||
|
best_subtasks[subtask] = {
|
||||||
|
"submission": submission,
|
||||||
|
"contest_time": nice_repr(self.contest_time(submission), "noday"),
|
||||||
|
"points": subtask_points,
|
||||||
|
"total": total_subtask_points,
|
||||||
|
}
|
||||||
|
total_points += total_subtask_points
|
||||||
|
achieved_points += subtask_points
|
||||||
|
for subtask in best_subtasks.values():
|
||||||
|
subtask["points"] = floatformat(
|
||||||
|
subtask["points"] / total_points * problem_points,
|
||||||
|
-self.contest.points_precision,
|
||||||
|
)
|
||||||
|
subtask["total"] = floatformat(
|
||||||
|
subtask["total"] / total_points * problem_points,
|
||||||
|
-self.contest.points_precision,
|
||||||
|
)
|
||||||
|
achieved_points = achieved_points / total_points * problem_points
|
||||||
|
if best_subtasks:
|
||||||
|
return best_subtasks, achieved_points, problem_points
|
||||||
|
return None
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserContestSubmissionsAjax, self).get_context_data(**kwargs)
|
context = super(UserContestSubmissionsAjax, self).get_context_data(**kwargs)
|
||||||
context["contest"] = self.contest
|
context["contest"] = self.contest
|
||||||
|
@ -852,6 +906,21 @@ class UserContestSubmissionsAjax(UserContestSubmissions):
|
||||||
s.display_point = f"{points} / {total}"
|
s.display_point = f"{points} / {total}"
|
||||||
filtered_submissions.append(s)
|
filtered_submissions.append(s)
|
||||||
context["submissions"] = filtered_submissions
|
context["submissions"] = filtered_submissions
|
||||||
|
|
||||||
|
best_subtasks = self.get_best_subtask_points()
|
||||||
|
if best_subtasks:
|
||||||
|
(
|
||||||
|
context["best_subtasks"],
|
||||||
|
context["points"],
|
||||||
|
context["total"],
|
||||||
|
) = best_subtasks
|
||||||
|
context["points"] = floatformat(
|
||||||
|
context["points"], -self.contest.points_precision
|
||||||
|
)
|
||||||
|
context["total"] = floatformat(
|
||||||
|
context["total"], -self.contest.points_precision
|
||||||
|
)
|
||||||
|
context["subtasks"] = sorted(context["best_subtasks"].keys())
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
|
|
|
@ -2,7 +2,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: lqdoj2\n"
|
"Project-Id-Version: lqdoj2\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-11-20 10:42+0700\n"
|
"POT-Creation-Date: 2022-11-22 10:54+0700\n"
|
||||||
"PO-Revision-Date: 2021-07-20 03:44\n"
|
"PO-Revision-Date: 2021-07-20 03:44\n"
|
||||||
"Last-Translator: Icyene\n"
|
"Last-Translator: Icyene\n"
|
||||||
"Language-Team: Vietnamese\n"
|
"Language-Team: Vietnamese\n"
|
||||||
|
@ -214,7 +214,7 @@ msgid "Taxonomy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: judge/admin/problem.py:216 judge/admin/problem.py:434
|
#: judge/admin/problem.py:216 judge/admin/problem.py:434
|
||||||
#: templates/contest/contest.html:91 templates/problem/data.html:518
|
#: templates/contest/contest.html:91 templates/problem/data.html:520
|
||||||
#: templates/problem/list.html:20 templates/problem/list.html:44
|
#: templates/problem/list.html:20 templates/problem/list.html:44
|
||||||
#: templates/user/base-users-table.html:10 templates/user/user-about.html:36
|
#: templates/user/base-users-table.html:10 templates/user/user-about.html:36
|
||||||
#: templates/user/user-about.html:52 templates/user/user-problems.html:58
|
#: templates/user/user-about.html:52 templates/user/user-problems.html:58
|
||||||
|
@ -467,6 +467,10 @@ msgstr ""
|
||||||
msgid "IOI"
|
msgid "IOI"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: judge/contest_format/new_ioi.py:11
|
||||||
|
msgid "New IOI"
|
||||||
|
msgstr "IOI mới"
|
||||||
|
|
||||||
#: judge/forms.py:70
|
#: judge/forms.py:70
|
||||||
msgid "Subscribe to contest updates"
|
msgid "Subscribe to contest updates"
|
||||||
msgstr "Đăng ký để nhận thông báo về các kỳ thi"
|
msgstr "Đăng ký để nhận thông báo về các kỳ thi"
|
||||||
|
@ -2577,7 +2581,7 @@ msgstr "Không tìm thấy kỳ thi với mã \"%s\"."
|
||||||
|
|
||||||
#: judge/views/contests.py:139 judge/views/stats.py:178
|
#: judge/views/contests.py:139 judge/views/stats.py:178
|
||||||
#: templates/organization/org-left-sidebar.html:5 templates/stats/site.html:21
|
#: templates/organization/org-left-sidebar.html:5 templates/stats/site.html:21
|
||||||
#: templates/user/user-bookmarks.html:50
|
#: templates/user/user-bookmarks.html:54
|
||||||
msgid "Contests"
|
msgid "Contests"
|
||||||
msgstr "Kỳ thi"
|
msgstr "Kỳ thi"
|
||||||
|
|
||||||
|
@ -2944,7 +2948,7 @@ msgstr "Hướng dẫn cho <a href=\"{1}\">{0}</a>"
|
||||||
|
|
||||||
#: judge/views/problem.py:447 templates/contest/contest.html:86
|
#: judge/views/problem.py:447 templates/contest/contest.html:86
|
||||||
#: templates/organization/org-left-sidebar.html:4
|
#: templates/organization/org-left-sidebar.html:4
|
||||||
#: templates/user/user-about.html:28 templates/user/user-bookmarks.html:32
|
#: templates/user/user-about.html:28 templates/user/user-bookmarks.html:34
|
||||||
#: templates/user/user-tabs.html:5 templates/user/users-table.html:19
|
#: templates/user/user-tabs.html:5 templates/user/users-table.html:19
|
||||||
msgid "Problems"
|
msgid "Problems"
|
||||||
msgstr "Bài tập"
|
msgstr "Bài tập"
|
||||||
|
@ -3150,39 +3154,39 @@ msgstr "Bài nộp của %(user)s cho bài %(problem)s"
|
||||||
msgid "All submissions"
|
msgid "All submissions"
|
||||||
msgstr "Tất cả bài nộp"
|
msgstr "Tất cả bài nộp"
|
||||||
|
|
||||||
#: judge/views/submission.py:505
|
#: judge/views/submission.py:512
|
||||||
msgid "All my submissions"
|
msgid "All my submissions"
|
||||||
msgstr "Tất cả bài nộp của tôi"
|
msgstr "Tất cả bài nộp của tôi"
|
||||||
|
|
||||||
#: judge/views/submission.py:506
|
#: judge/views/submission.py:513
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "All submissions by %s"
|
msgid "All submissions by %s"
|
||||||
msgstr "Tất cả bài nộp của %s"
|
msgstr "Tất cả bài nộp của %s"
|
||||||
|
|
||||||
#: judge/views/submission.py:551
|
#: judge/views/submission.py:558
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "All submissions for %s"
|
msgid "All submissions for %s"
|
||||||
msgstr "Tất cả bài nộp cho %s"
|
msgstr "Tất cả bài nộp cho %s"
|
||||||
|
|
||||||
#: judge/views/submission.py:579
|
#: judge/views/submission.py:586
|
||||||
msgid "Must pass a problem"
|
msgid "Must pass a problem"
|
||||||
msgstr "Phải làm được một bài"
|
msgstr "Phải làm được một bài"
|
||||||
|
|
||||||
#: judge/views/submission.py:637
|
#: judge/views/submission.py:644
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "My submissions for %(problem)s"
|
msgid "My submissions for %(problem)s"
|
||||||
msgstr "Bài nộp của tôi cho %(problem)s"
|
msgstr "Bài nộp của tôi cho %(problem)s"
|
||||||
|
|
||||||
#: judge/views/submission.py:638
|
#: judge/views/submission.py:645
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(user)s's submissions for %(problem)s"
|
msgid "%(user)s's submissions for %(problem)s"
|
||||||
msgstr "Các bài nộp của %(user)s cho %(problem)s"
|
msgstr "Các bài nộp của %(user)s cho %(problem)s"
|
||||||
|
|
||||||
#: judge/views/submission.py:768
|
#: judge/views/submission.py:775
|
||||||
msgid "Must pass a contest"
|
msgid "Must pass a contest"
|
||||||
msgstr "Phải qua một kỳ thi"
|
msgstr "Phải qua một kỳ thi"
|
||||||
|
|
||||||
#: judge/views/submission.py:798
|
#: judge/views/submission.py:805
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<a href=\"{1}\">{0}</a>'s submissions for <a href=\"{3}\">{2}</a> in <a href="
|
"<a href=\"{1}\">{0}</a>'s submissions for <a href=\"{3}\">{2}</a> in <a href="
|
||||||
|
@ -3191,7 +3195,7 @@ msgstr ""
|
||||||
"Các bài nộp của <a href=\"{1}\">{0}</a> cho <a href=\"{3}\">{2}</a> trong <a "
|
"Các bài nộp của <a href=\"{1}\">{0}</a> cho <a href=\"{3}\">{2}</a> trong <a "
|
||||||
"href=\"{5}\">{4}</a>"
|
"href=\"{5}\">{4}</a>"
|
||||||
|
|
||||||
#: judge/views/submission.py:810
|
#: judge/views/submission.py:817
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"<a href=\"{1}\">{0}</a>'s submissions for problem {2} in <a href=\"{4}\">{3}"
|
"<a href=\"{1}\">{0}</a>'s submissions for problem {2} in <a href=\"{4}\">{3}"
|
||||||
|
@ -3200,7 +3204,7 @@ msgstr ""
|
||||||
"Các bài nộp của <a href=\"{1}\">{0}</a> cho bài {2} trong <a href=\"{4}\">{3}"
|
"Các bài nộp của <a href=\"{1}\">{0}</a> cho bài {2} trong <a href=\"{4}\">{3}"
|
||||||
"</a>"
|
"</a>"
|
||||||
|
|
||||||
#: judge/views/submission.py:861
|
#: judge/views/submission.py:927
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#| msgid "You do not have the permission to rejudge submissions."
|
#| msgid "You do not have the permission to rejudge submissions."
|
||||||
msgid "You don't have permission to access."
|
msgid "You don't have permission to access."
|
||||||
|
@ -4505,7 +4509,7 @@ msgid "There are no requests to approve."
|
||||||
msgstr "Không có đơn đăng ký."
|
msgstr "Không có đơn đăng ký."
|
||||||
|
|
||||||
#: templates/organization/requests/pending.html:17
|
#: templates/organization/requests/pending.html:17
|
||||||
#: templates/problem/data.html:521
|
#: templates/problem/data.html:523
|
||||||
msgid "Delete?"
|
msgid "Delete?"
|
||||||
msgstr "Xóa?"
|
msgstr "Xóa?"
|
||||||
|
|
||||||
|
@ -4550,54 +4554,56 @@ msgstr "Nhập mã bài mới cho bài tập được nhân bản:"
|
||||||
msgid "Instruction"
|
msgid "Instruction"
|
||||||
msgstr "Hướng dẫn"
|
msgstr "Hướng dẫn"
|
||||||
|
|
||||||
#: templates/problem/data.html:470
|
#: templates/problem/data.html:472
|
||||||
msgid "View YAML"
|
msgid "View YAML"
|
||||||
msgstr "Xem YAML"
|
msgstr "Xem YAML"
|
||||||
|
|
||||||
#: templates/problem/data.html:487
|
#: templates/problem/data.html:489
|
||||||
msgid "Autofill testcases"
|
msgid "Autofill testcases"
|
||||||
msgstr "Tự động điền test"
|
msgstr "Tự động điền test"
|
||||||
|
|
||||||
#: templates/problem/data.html:491 templates/problem/problem.html:310
|
#: templates/problem/data.html:493 templates/problem/problem.html:310
|
||||||
msgid "Problem type"
|
msgid "Problem type"
|
||||||
msgid_plural "Problem types"
|
msgid_plural "Problem types"
|
||||||
msgstr[0] "Dạng bài"
|
msgstr[0] "Dạng bài"
|
||||||
|
|
||||||
#: templates/problem/data.html:498
|
#: templates/problem/data.html:500
|
||||||
msgid "Fill testcases"
|
msgid "Fill testcases"
|
||||||
msgstr "Điền test"
|
msgstr "Điền test"
|
||||||
|
|
||||||
#: templates/problem/data.html:502
|
#: templates/problem/data.html:504
|
||||||
msgid "Batch start positions"
|
msgid "Batch start positions"
|
||||||
msgstr "Vị trí bắt đầu nhóm"
|
msgstr "Vị trí bắt đầu nhóm"
|
||||||
|
|
||||||
#: templates/problem/data.html:506
|
#: templates/problem/data.html:508
|
||||||
msgid ""
|
msgid ""
|
||||||
"Leave empty if not use batch. If you want to divide to three batches [1, 4], "
|
"Leave empty if not use batch. If you want to divide to three batches [1, 4], "
|
||||||
"[5, 8], [9, 10], enter: 1, 5, 9"
|
"[5, 8], [9, 10], enter: 1, 5, 9"
|
||||||
msgstr "Để trống nếu không dùng nhóm. Nếu muốn chia test thành các nhóm [1, 4], [5, 8], [9, 10], nhập: 1, 5, 9"
|
msgstr ""
|
||||||
|
"Để trống nếu không dùng nhóm. Nếu muốn chia test thành các nhóm [1, 4], [5, "
|
||||||
|
"8], [9, 10], nhập: 1, 5, 9"
|
||||||
|
|
||||||
#: templates/problem/data.html:510 templates/problem/data.html:561
|
#: templates/problem/data.html:512 templates/problem/data.html:563
|
||||||
msgid "Apply!"
|
msgid "Apply!"
|
||||||
msgstr "Lưu!"
|
msgstr "Lưu!"
|
||||||
|
|
||||||
#: templates/problem/data.html:515
|
#: templates/problem/data.html:517
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr "Kiểu"
|
msgstr "Kiểu"
|
||||||
|
|
||||||
#: templates/problem/data.html:516
|
#: templates/problem/data.html:518
|
||||||
msgid "Input file"
|
msgid "Input file"
|
||||||
msgstr "File Input"
|
msgstr "File Input"
|
||||||
|
|
||||||
#: templates/problem/data.html:517
|
#: templates/problem/data.html:519
|
||||||
msgid "Output file"
|
msgid "Output file"
|
||||||
msgstr "File Output"
|
msgstr "File Output"
|
||||||
|
|
||||||
#: templates/problem/data.html:519
|
#: templates/problem/data.html:521
|
||||||
msgid "Pretest?"
|
msgid "Pretest?"
|
||||||
msgstr "Pretest?"
|
msgstr "Pretest?"
|
||||||
|
|
||||||
#: templates/problem/data.html:562
|
#: templates/problem/data.html:564
|
||||||
msgid "Add new case"
|
msgid "Add new case"
|
||||||
msgstr "Thêm test mới"
|
msgstr "Thêm test mới"
|
||||||
|
|
||||||
|
@ -5418,11 +5424,19 @@ msgstr ""
|
||||||
msgid "Contest submissions of"
|
msgid "Contest submissions of"
|
||||||
msgstr "Các bài nộp của"
|
msgstr "Các bài nộp của"
|
||||||
|
|
||||||
#: templates/submission/user-ajax.html:13
|
#: templates/submission/user-ajax.html:11
|
||||||
|
msgid "Subtask"
|
||||||
|
msgstr "Subtask"
|
||||||
|
|
||||||
|
#: templates/submission/user-ajax.html:29
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Tổng điểm"
|
||||||
|
|
||||||
|
#: templates/submission/user-ajax.html:46
|
||||||
msgid "g:i a d/m/Y"
|
msgid "g:i a d/m/Y"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templates/submission/user-ajax.html:13
|
#: templates/submission/user-ajax.html:46
|
||||||
#, fuzzy, python-format
|
#, fuzzy, python-format
|
||||||
#| msgid ""
|
#| msgid ""
|
||||||
#| "\n"
|
#| "\n"
|
||||||
|
@ -5437,11 +5451,11 @@ msgstr ""
|
||||||
" vào %(time)s\n"
|
" vào %(time)s\n"
|
||||||
" "
|
" "
|
||||||
|
|
||||||
#: templates/submission/user-ajax.html:22
|
#: templates/submission/user-ajax.html:55
|
||||||
msgid "pretests"
|
msgid "pretests"
|
||||||
msgstr "pretests"
|
msgstr "pretests"
|
||||||
|
|
||||||
#: templates/submission/user-ajax.html:24
|
#: templates/submission/user-ajax.html:57
|
||||||
msgid "main tests"
|
msgid "main tests"
|
||||||
msgstr "test chính thức"
|
msgstr "test chính thức"
|
||||||
|
|
||||||
|
@ -5736,7 +5750,7 @@ msgstr "Max rating:"
|
||||||
msgid "Posts"
|
msgid "Posts"
|
||||||
msgstr "Bài đăng"
|
msgstr "Bài đăng"
|
||||||
|
|
||||||
#: templates/user/user-bookmarks.html:69
|
#: templates/user/user-bookmarks.html:75
|
||||||
msgid "Editorials"
|
msgid "Editorials"
|
||||||
msgstr "Lời giải"
|
msgstr "Lời giải"
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
{% for batch in batches %}
|
{% for batch in batches %}
|
||||||
<div style="margin-top: 0.5em;">
|
<div style="margin-top: 0.5em;">
|
||||||
{% if batch.id %}
|
{% if batch.id %}
|
||||||
<b>{{ _('Batch ') }}#{{ batch.id }}: </b>
|
<b>{{ _('Batch ') }}#{{ batch.id }} ({{batch.points|floatformat}} / {{batch.total|floatformat}}): </b>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for case in batch.cases %}
|
{% for case in batch.cases %}
|
||||||
<span class="case-{{ case.status }} case-icons">
|
<span class="case-{{ case.status }} case-icons">
|
||||||
|
|
|
@ -2,6 +2,39 @@
|
||||||
{{_('Contest submissions of')}} {{link_user(profile)}} <a href="{{url('contest_user_submissions', contest.key, profile.user.username, problem.code)}}">#</a>
|
{{_('Contest submissions of')}} {{link_user(profile)}} <a href="{{url('contest_user_submissions', contest.key, profile.user.username, problem.code)}}">#</a>
|
||||||
</h4>
|
</h4>
|
||||||
<hr>
|
<hr>
|
||||||
|
{% if best_subtasks and subtasks %}
|
||||||
|
<table class="lightbox-submissions"><tbody>
|
||||||
|
{% for subtask in subtasks %}
|
||||||
|
<tr>
|
||||||
|
{% set cur_subtask = best_subtasks[subtask] %}
|
||||||
|
<td class="lightbox-submissions-time">
|
||||||
|
<b>{{_('Subtask')}} {{subtask}}:</b>
|
||||||
|
</td>
|
||||||
|
<td class="lightbox-submissions-time case-{{'AC' if cur_subtask.points == cur_subtask.total else 'WA'}}">
|
||||||
|
{{ cur_subtask.points }} / {{ cur_subtask.total }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
({{ cur_subtask.contest_time }})
|
||||||
|
</td>
|
||||||
|
{% set can_view = submission_layout(cur_subtask.submission, profile_id, request.user, editable_problem_ids, completed_problem_ids) %}
|
||||||
|
{% if can_view %}
|
||||||
|
<td>
|
||||||
|
→ <a href="{{url('submission_status', cur_subtask.submission.id)}}">{{ cur_subtask.submission.id }}</a>
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
<tr>
|
||||||
|
<td class="lightbox-submissions-time">
|
||||||
|
<b>{{_('Total')}}:</b>
|
||||||
|
</td>
|
||||||
|
<td style="border-top: 1px black solid" class="case-{{'AC' if points == total else 'WA'}}">
|
||||||
|
{{ points }} / {{ total }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>
|
||||||
|
<hr>
|
||||||
|
{% endif %}
|
||||||
<table class="lightbox-submissions"><tbody>
|
<table class="lightbox-submissions"><tbody>
|
||||||
{% for submission in submissions %}
|
{% for submission in submissions %}
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -15,8 +48,8 @@
|
||||||
{% endtrans %}
|
{% endtrans %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="case-{{submission.result}}" style="margin-left: 1em">{{submission.display_point}}</td>
|
<td class="case-{{submission.result}}">{{submission.display_point}}</td>
|
||||||
<td class="case-{{submission.result}}" style="margin-left: 1em">({{submission.short_status}})</td>
|
<td class="case-{{submission.result}}">({{submission.short_status}})</td>
|
||||||
<td>
|
<td>
|
||||||
{% if submission.contest.is_pretest %}
|
{% if submission.contest.is_pretest %}
|
||||||
[{{_('pretests')}}]
|
[{{_('pretests')}}]
|
||||||
|
|
Loading…
Reference in a new issue