update acm helper

This commit is contained in:
2025-10-06 00:06:59 +08:00
parent 6d32e5de1e
commit cbe0e297fd
2 changed files with 65 additions and 28 deletions

View File

@@ -6,6 +6,8 @@ from ipaddress import ip_network
import dateutil.parser import dateutil.parser
from django.http import FileResponse from django.http import FileResponse
from problem.models import Problem
from account.decorators import super_admin_required from account.decorators import super_admin_required
from account.models import User from account.models import User
from submission.models import Submission, JudgeStatus from submission.models import Submission, JudgeStatus
@@ -15,10 +17,15 @@ from utils.constants import CacheKey
from utils.shortcuts import rand_str from utils.shortcuts import rand_str
from utils.tasks import delete_files from utils.tasks import delete_files
from ..models import Contest, ContestAnnouncement, ACMContestRank from ..models import Contest, ContestAnnouncement, ACMContestRank
from ..serializers import (ContestAnnouncementSerializer, ContestAdminSerializer, from ..serializers import (
CreateConetestSeriaizer, CreateContestAnnouncementSerializer, ContestAnnouncementSerializer,
EditConetestSeriaizer, EditContestAnnouncementSerializer, ContestAdminSerializer,
ACMContesHelperSerializer, ) CreateConetestSeriaizer,
CreateContestAnnouncementSerializer,
EditConetestSeriaizer,
EditContestAnnouncementSerializer,
ACMContesHelperSerializer,
)
class ContestAPI(APIView): class ContestAPI(APIView):
@@ -84,7 +91,9 @@ class ContestAPI(APIView):
keyword = request.GET.get("keyword") keyword = request.GET.get("keyword")
if keyword: if keyword:
contests = contests.filter(title__contains=keyword) contests = contests.filter(title__contains=keyword)
return self.success(self.paginate_data(request, contests, ContestAdminSerializer)) return self.success(
self.paginate_data(request, contests, ContestAdminSerializer)
)
class ContestAnnouncementAPI(APIView): class ContestAnnouncementAPI(APIView):
@@ -138,19 +147,29 @@ class ContestAnnouncementAPI(APIView):
contest_announcement_id = request.GET.get("id") contest_announcement_id = request.GET.get("id")
if contest_announcement_id: if contest_announcement_id:
try: try:
contest_announcement = ContestAnnouncement.objects.get(id=contest_announcement_id) contest_announcement = ContestAnnouncement.objects.get(
return self.success(ContestAnnouncementSerializer(contest_announcement).data) id=contest_announcement_id
)
return self.success(
ContestAnnouncementSerializer(contest_announcement).data
)
except ContestAnnouncement.DoesNotExist: except ContestAnnouncement.DoesNotExist:
return self.error("Contest announcement does not exist") return self.error("Contest announcement does not exist")
contest_id = request.GET.get("contest_id") contest_id = request.GET.get("contest_id")
if not contest_id: if not contest_id:
return self.error("Parameter error") return self.error("Parameter error")
contest_announcements = ContestAnnouncement.objects.filter(contest_id=contest_id) contest_announcements = ContestAnnouncement.objects.filter(
contest_id=contest_id
)
keyword = request.GET.get("keyword") keyword = request.GET.get("keyword")
if keyword: if keyword:
contest_announcements = contest_announcements.filter(title__contains=keyword) contest_announcements = contest_announcements.filter(
return self.success(ContestAnnouncementSerializer(contest_announcements, many=True).data) title__contains=keyword
)
return self.success(
ContestAnnouncementSerializer(contest_announcements, many=True).data
)
class ACMContestHelper(APIView): class ACMContestHelper(APIView):
@@ -164,20 +183,31 @@ class ACMContestHelper(APIView):
except Contest.DoesNotExist: except Contest.DoesNotExist:
return self.error("Contest does not exist") return self.error("Contest does not exist")
ranks = ACMContestRank.objects.filter(contest=contest, accepted_number__gt=0) \ problems = Problem.objects.filter(contest=contest).values("id", "_id")
.values("id", "user__username", "user__userprofile__real_name", "submission_info") problem_id_map = {str(p["id"]): p["_id"] for p in problems}
ranks = ACMContestRank.objects.filter(
contest=contest, accepted_number__gt=0
).values(
"id", "user__username", "user__userprofile__real_name", "submission_info"
)
results = [] results = []
for rank in ranks: for rank in ranks:
for problem_id, info in rank["submission_info"].items(): for problem_id, info in rank["submission_info"].items():
if info["is_ac"]: if info["is_ac"]:
results.append({ results.append(
{
"id": rank["id"], "id": rank["id"],
"username": rank["user__username"], "username": rank["user__username"],
"real_name": rank["user__userprofile__real_name"], "real_name": rank["user__userprofile__real_name"],
"problem_id": problem_id, "problem_id": problem_id,
"problem_display_id": problem_id_map.get(
problem_id, problem_id
),
"ac_info": info, "ac_info": info,
"checked": info.get("checked", False) "checked": info.get("checked", False),
}) }
)
results.sort(key=lambda x: -x["ac_info"]["ac_time"]) results.sort(key=lambda x: -x["ac_info"]["ac_time"])
return self.success(results) return self.success(results)
@@ -202,7 +232,9 @@ class DownloadContestSubmissions(APIView):
problem_ids = contest.problem_set.all().values_list("id", "_id") problem_ids = contest.problem_set.all().values_list("id", "_id")
id2display_id = {k[0]: k[1] for k in problem_ids} id2display_id = {k[0]: k[1] for k in problem_ids}
ac_map = {k[0]: False for k in problem_ids} ac_map = {k[0]: False for k in problem_ids}
submissions = Submission.objects.filter(contest=contest, result=JudgeStatus.ACCEPTED).order_by("-create_time") submissions = Submission.objects.filter(
contest=contest, result=JudgeStatus.ACCEPTED
).order_by("-create_time")
user_ids = submissions.values_list("user_id", flat=True) user_ids = submissions.values_list("user_id", flat=True)
users = User.objects.filter(id__in=user_ids) users = User.objects.filter(id__in=user_ids)
path = f"/tmp/{rand_str()}.zip" path = f"/tmp/{rand_str()}.zip"
@@ -216,11 +248,15 @@ class DownloadContestSubmissions(APIView):
problem_id = submission.problem_id problem_id = submission.problem_id
if user_ac_map[problem_id]: if user_ac_map[problem_id]:
continue continue
file_name = f"{user.username}_{id2display_id[submission.problem_id]}.txt" file_name = (
f"{user.username}_{id2display_id[submission.problem_id]}.txt"
)
compression = zipfile.ZIP_DEFLATED compression = zipfile.ZIP_DEFLATED
zip_file.writestr(zinfo_or_arcname=f"{file_name}", zip_file.writestr(
zinfo_or_arcname=f"{file_name}",
data=submission.code, data=submission.code,
compress_type=compression) compress_type=compression,
)
user_ac_map[problem_id] = True user_ac_map[problem_id] = True
return path return path
@@ -239,5 +275,7 @@ class DownloadContestSubmissions(APIView):
delete_files.send_with_options(args=(zip_path,), delay=300_000) delete_files.send_with_options(args=(zip_path,), delay=300_000)
resp = FileResponse(open(zip_path, "rb")) resp = FileResponse(open(zip_path, "rb"))
resp["Content-Type"] = "application/zip" resp["Content-Type"] = "application/zip"
resp["Content-Disposition"] = f"attachment;filename={os.path.basename(zip_path)}" resp["Content-Disposition"] = (
f"attachment;filename={os.path.basename(zip_path)}"
)
return resp return resp

View File

@@ -489,7 +489,6 @@ class MakeContestProblemPublicAPIView(APIView):
return self.error("Already be a public problem") return self.error("Already be a public problem")
problem.is_public = True problem.is_public = True
problem.save() problem.save()
# https://docs.djangoproject.com/en/1.11/topics/db/queries/#copying-model-instances
tags = problem.tags.all() tags = problem.tags.all()
problem.pk = None problem.pk = None
problem.contest = None problem.contest = None