NDOJ/judge/performance_points.py

113 lines
4.3 KiB
Python
Raw Normal View History

2020-01-21 06:35:58 +00:00
from collections import namedtuple
from django.conf import settings
from django.db import connection
from judge.models import Submission
from judge.timezone import from_database_time
2022-05-14 17:57:27 +00:00
PP_WEIGHT_TABLE = [
pow(settings.DMOJ_PP_STEP, i) for i in range(settings.DMOJ_PP_ENTRIES)
]
2020-01-21 06:35:58 +00:00
2022-05-14 17:57:27 +00:00
PPBreakdown = namedtuple(
"PPBreakdown",
"points weight scaled_points problem_name problem_code "
"sub_id sub_date sub_points sub_total sub_result_class "
"sub_short_status sub_long_status sub_lang",
)
2020-01-21 06:35:58 +00:00
def get_pp_breakdown(user, start=0, end=settings.DMOJ_PP_ENTRIES):
with connection.cursor() as cursor:
2022-05-14 17:57:27 +00:00
cursor.execute(
"""
2023-02-13 23:57:27 +00:00
SELECT submission.problem_code,
submission.problem_name,
submission.max_points,
submission.sub_id,
submission.sub_date,
submission.case_points,
submission.case_total,
submission.result,
2020-01-21 06:35:58 +00:00
judge_language.short_name,
judge_language.key
2023-02-13 23:57:27 +00:00
FROM
(SELECT max_points_table.problem_code problem_code,
max_points_table.problem_name problem_name,
max_points_table.max_points max_points,
judge_submission.id sub_id,
judge_submission.date sub_date,
judge_submission.case_points case_points,
judge_submission.case_total case_total,
judge_submission.result result,
judge_submission.language_id language_id
FROM judge_submission
JOIN (
SELECT judge_problem.id problem_id,
judge_problem.name problem_name,
judge_problem.code problem_code,
MAX(judge_submission.points) AS max_points
FROM judge_problem
INNER JOIN judge_submission
ON (judge_problem.id = judge_submission.problem_id)
WHERE (judge_problem.is_public = True AND judge_problem.is_organization_private = False AND judge_submission.points IS NOT NULL AND judge_submission.user_id = %s)
GROUP BY judge_problem.id
HAVING MAX(judge_submission.points) > 0.0
) AS max_points_table
ON (judge_submission.problem_id = max_points_table.problem_id AND judge_submission.points = max_points_table.max_points AND judge_submission.user_id = %s)
GROUP BY max_points_table.problem_id
ORDER BY max_points DESC, judge_submission.date DESC
LIMIT %s
OFFSET %s
) AS submission
2020-01-21 06:35:58 +00:00
JOIN judge_language
2023-02-13 23:57:27 +00:00
ON submission.language_id = judge_language.id
ORDER BY submission.max_points DESC, submission.sub_date DESC;
2022-05-14 17:57:27 +00:00
""",
(user.id, user.id, end - start + 1, start),
)
2020-01-21 06:35:58 +00:00
data = cursor.fetchall()
breakdown = []
for weight, contrib in zip(PP_WEIGHT_TABLE[start:end], data):
2022-05-14 17:57:27 +00:00
(
code,
name,
points,
id,
date,
case_points,
case_total,
result,
lang_short_name,
lang_key,
) = contrib
2020-01-21 06:35:58 +00:00
# Replicates a lot of the logic usually done on Submission objects
lang_short_display_name = lang_short_name or lang_key
2022-05-14 17:57:27 +00:00
result_class = Submission.result_class_from_code(
result, case_points, case_total
)
long_status = Submission.USER_DISPLAY_CODES.get(result, "")
2020-01-21 06:35:58 +00:00
2022-05-14 17:57:27 +00:00
breakdown.append(
PPBreakdown(
points=points,
weight=weight * 100,
scaled_points=points * weight,
problem_name=name,
problem_code=code,
sub_id=id,
sub_date=from_database_time(date),
sub_points=case_points,
sub_total=case_total,
sub_short_status=result,
sub_long_status=long_status,
sub_result_class=result_class,
sub_lang=lang_short_display_name,
)
)
2020-01-21 06:35:58 +00:00
has_more = end < min(len(PP_WEIGHT_TABLE), start + len(data))
return breakdown, has_more