diff --git a/contest/views/admin.py b/contest/views/admin.py index b94acda..6cdf49a 100644 --- a/contest/views/admin.py +++ b/contest/views/admin.py @@ -6,6 +6,8 @@ from ipaddress import ip_network import dateutil.parser from django.http import FileResponse +from problem.models import Problem + from account.decorators import super_admin_required from account.models import User from submission.models import Submission, JudgeStatus @@ -15,10 +17,15 @@ from utils.constants import CacheKey from utils.shortcuts import rand_str from utils.tasks import delete_files from ..models import Contest, ContestAnnouncement, ACMContestRank -from ..serializers import (ContestAnnouncementSerializer, ContestAdminSerializer, - CreateConetestSeriaizer, CreateContestAnnouncementSerializer, - EditConetestSeriaizer, EditContestAnnouncementSerializer, - ACMContesHelperSerializer, ) +from ..serializers import ( + ContestAnnouncementSerializer, + ContestAdminSerializer, + CreateConetestSeriaizer, + CreateContestAnnouncementSerializer, + EditConetestSeriaizer, + EditContestAnnouncementSerializer, + ACMContesHelperSerializer, +) class ContestAPI(APIView): @@ -84,7 +91,9 @@ class ContestAPI(APIView): keyword = request.GET.get("keyword") if 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): @@ -138,19 +147,29 @@ class ContestAnnouncementAPI(APIView): contest_announcement_id = request.GET.get("id") if contest_announcement_id: try: - contest_announcement = ContestAnnouncement.objects.get(id=contest_announcement_id) - return self.success(ContestAnnouncementSerializer(contest_announcement).data) + contest_announcement = ContestAnnouncement.objects.get( + id=contest_announcement_id + ) + return self.success( + ContestAnnouncementSerializer(contest_announcement).data + ) except ContestAnnouncement.DoesNotExist: return self.error("Contest announcement does not exist") contest_id = request.GET.get("contest_id") if not contest_id: 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") if keyword: - contest_announcements = contest_announcements.filter(title__contains=keyword) - return self.success(ContestAnnouncementSerializer(contest_announcements, many=True).data) + contest_announcements = contest_announcements.filter( + title__contains=keyword + ) + return self.success( + ContestAnnouncementSerializer(contest_announcements, many=True).data + ) class ACMContestHelper(APIView): @@ -163,21 +182,32 @@ class ACMContestHelper(APIView): contest = Contest.objects.get(id=contest_id, visible=True) except Contest.DoesNotExist: return self.error("Contest does not exist") - - ranks = ACMContestRank.objects.filter(contest=contest, accepted_number__gt=0) \ - .values("id", "user__username", "user__userprofile__real_name", "submission_info") + + problems = Problem.objects.filter(contest=contest).values("id", "_id") + 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 = [] for rank in ranks: for problem_id, info in rank["submission_info"].items(): if info["is_ac"]: - results.append({ - "id": rank["id"], - "username": rank["user__username"], - "real_name": rank["user__userprofile__real_name"], - "problem_id": problem_id, - "ac_info": info, - "checked": info.get("checked", False) - }) + results.append( + { + "id": rank["id"], + "username": rank["user__username"], + "real_name": rank["user__userprofile__real_name"], + "problem_id": problem_id, + "problem_display_id": problem_id_map.get( + problem_id, problem_id + ), + "ac_info": info, + "checked": info.get("checked", False), + } + ) results.sort(key=lambda x: -x["ac_info"]["ac_time"]) return self.success(results) @@ -202,7 +232,9 @@ class DownloadContestSubmissions(APIView): problem_ids = contest.problem_set.all().values_list("id", "_id") id2display_id = {k[0]: k[1] 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) users = User.objects.filter(id__in=user_ids) path = f"/tmp/{rand_str()}.zip" @@ -216,11 +248,15 @@ class DownloadContestSubmissions(APIView): problem_id = submission.problem_id if user_ac_map[problem_id]: 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 - zip_file.writestr(zinfo_or_arcname=f"{file_name}", - data=submission.code, - compress_type=compression) + zip_file.writestr( + zinfo_or_arcname=f"{file_name}", + data=submission.code, + compress_type=compression, + ) user_ac_map[problem_id] = True return path @@ -239,5 +275,7 @@ class DownloadContestSubmissions(APIView): delete_files.send_with_options(args=(zip_path,), delay=300_000) resp = FileResponse(open(zip_path, "rb")) 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 diff --git a/problem/views/admin.py b/problem/views/admin.py index 414bb8d..8854a53 100644 --- a/problem/views/admin.py +++ b/problem/views/admin.py @@ -489,7 +489,6 @@ class MakeContestProblemPublicAPIView(APIView): return self.error("Already be a public problem") problem.is_public = True problem.save() - # https://docs.djangoproject.com/en/1.11/topics/db/queries/#copying-model-instances tags = problem.tags.all() problem.pk = None problem.contest = None