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

@ -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",

View file

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

View file

@ -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,
], ],
), ),

View file

@ -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,
], ],
), ),

View file

@ -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,
], ],
), ),

View file

@ -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,
], ],
), ),

View file

@ -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,
], ],
), ),

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

View 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",
),
),
]

View file

@ -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")
if "user" in kwargs:
self.profile = get_object_or_404(Profile, user__username=kwargs["user"]) self.profile = get_object_or_404(Profile, user__username=kwargs["user"])
self.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):

View file

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

View file

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

View file

@ -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')}}]