diff --git a/contest/tasks.py b/contest/tasks.py new file mode 100644 index 00000000..88078001 --- /dev/null +++ b/contest/tasks.py @@ -0,0 +1,57 @@ +from celery import shared_task + +from submission.models import Submission + +import os +from django.conf import settings +from contest.models import Contest +from problem.models import Problem +from submission.models import JudgeStatus + + +@shared_task(time_limit=30) +def similiar_task(contest_id): + problems = Problem.objects.filter(contest_id=contest_id) + owner = {} + data_to_write = [] + + for problem in problems: + check_dir = os.path.join(settings.TEST_CASE_DIR, str(problem.id) + "_similiar_tmp") + if not os.path.exists(check_dir): + os.mkdir(check_dir) + os.chmod(check_dir, 0o710) + + submissions = Submission.objects.filter(problem_id=problem.id, result=JudgeStatus.ACCEPTED) + for submission in submissions: + owner[submission.id] = submission.username + file_path = os.path.join(check_dir, submission.id) + f = open(file_path, "w") + f.write(submission.code) + f.close() + + output_dir = os.path.join(check_dir, "result") + check_files = check_dir + "/*" + os.system(f"/app/sim_c -p -t40 -o {output_dir} {check_files}") + f = open(output_dir) + for line in f: + # xxxx consists for xx % of xxxx material + if "consists" in line: + splited_line = line.split() + sub1 = splited_line[0].split("/")[-1] + sub2 = splited_line[-2].split("/")[-1] + if owner[sub1] == owner[sub2]: + continue + sim = splited_line[3] + data_to_write.append("#".join([problem._id, sub1, owner[sub1], sub2, owner[sub2], sim])) + f.close() + + os.remove(output_dir) + for submission in submissions: + owner[submission.id] = submission.username + file_path = os.path.join(check_dir, submission.id) + os.remove(file_path) + os.rmdir(check_dir) + + contest = Contest.objects.get(id=contest_id) + contest.similarity_check_result = data_to_write + contest.save() diff --git a/contest/views/admin.py b/contest/views/admin.py index 95439386..232b3e60 100644 --- a/contest/views/admin.py +++ b/contest/views/admin.py @@ -20,6 +20,7 @@ from ..serializers import (ContestAnnouncementSerializer, ContestAdminSerializer EditConetestSeriaizer, EditContestAnnouncementSerializer, ACMContesHelperSerializer, ) from account.decorators import super_admin_required +from contest.tasks import similiar_task class ContestAPI(APIView): @@ -245,4 +246,6 @@ class DownloadContestSubmissions(APIView): class ContestCheckSimiliarAPI(APIView): @super_admin_required def get(self, request): + cid = request.GET.get("contest_id") + similiar_task.delay(cid) return self.success()