add problem_statistic_info

This commit is contained in:
zemal 2017-08-15 21:05:41 +08:00
parent df185a233f
commit 1587192ff9
5 changed files with 58 additions and 27 deletions

View File

@ -14,7 +14,7 @@ from contest.models import ContestRuleType, ACMContestRank, OIContestRank
from judge.languages import languages
from problem.models import Problem, ProblemRuleType, ContestProblem
from submission.models import JudgeStatus, Submission
from utils.cache import judge_queue_cache
from utils.cache import judge_cache
from utils.constants import CacheKey
logger = logging.getLogger(__name__)
@ -22,10 +22,10 @@ logger = logging.getLogger(__name__)
# 继续处理在队列中的问题
def process_pending_task():
if judge_queue_cache.llen(CacheKey.waiting_queue):
if judge_cache.llen(CacheKey.waiting_queue):
# 防止循环引入
from judge.tasks import judge_task
data = json.loads(judge_queue_cache.rpop(CacheKey.waiting_queue))
data = json.loads(judge_cache.rpop(CacheKey.waiting_queue))
judge_task.delay(**data)
@ -33,7 +33,7 @@ class JudgeDispatcher(object):
def __init__(self, submission_id, problem_id):
token = JudgeServerToken.objects.first().token
self.token = hashlib.sha256(token.encode("utf-8")).hexdigest()
self.redis_conn = judge_queue_cache
self.redis_conn = judge_cache
self.submission = Submission.objects.get(pk=submission_id)
if self.submission.contest_id:
self.problem = ContestProblem.objects.select_related("contest")\
@ -98,8 +98,8 @@ class JudgeDispatcher(object):
"spj_compile_config": spj_config.get("compile"),
"spj_src": self.problem.spj_code
}
self.submission.result = JudgeStatus.JUDGING
self.submission.save()
Submission.objects.filter(id=self.submission.id).update(result=JudgeStatus.JUDGING)
# TODO: try catch
resp = self._request(urljoin(server.service_url, "/judge"), data=data)
@ -123,11 +123,12 @@ class JudgeDispatcher(object):
self.submission.save()
self.release_judge_res(server.id)
self.update_problem_status()
if self.submission.contest_id:
self.update_contest_problem_status()
self.update_contest_rank()
else:
self.update_problem_status()
self.update_user_profile()
# 至此判题结束,尝试处理任务队列中剩余的任务
process_pending_task()
@ -138,13 +139,21 @@ class JudgeDispatcher(object):
return self._request(urljoin(service_url, "compile_spj"), data=data)
def update_problem_status(self):
with transaction.atomic():
# 更新problem计数器
self.problem = Problem.objects.select_for_update().get(id=self.problem.id)
self.problem.add_submission_number()
if self.submission.result == JudgeStatus.ACCEPTED:
self.problem.add_ac_number()
with transaction.atomic():
if self.submission.contest_id:
problem = ContestProblem.objects.select_for_update().get(_id=self.problem.id, contest_id=self.contest.id)
else:
problem = Problem.objects.select_related().get(_id=self.problem.id)
info = problem.statistic_info
info[self.submission.result] = info.get(self.submission.result, 0) + 1
problem.statistic_info = info
problem.save(update_fields=["statistic_info"])
def update_user_profile(self):
with transaction.atomic():
# 更新user profile
user = User.objects.select_for_update().get(id=self.submission.user_id)
user_profile = user.userprofile
@ -163,13 +172,6 @@ class JudgeDispatcher(object):
user_profile.problems_status = problems_status
user_profile.save(update_fields=["problems_status"])
def update_contest_problem_status(self):
with transaction.atomic():
problem = ContestProblem.objects.select_for_update().get(id=self.problem.id)
problem.add_submission_number()
if self.submission.result == JudgeStatus.ACCEPTED:
problem.add_ac_number()
def update_contest_rank(self):
if self.contest.real_time_rank:
cache.delete(str(self.contest.id) + "_rank_cache")

View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2017-08-15 12:58
from __future__ import unicode_literals
from django.db import migrations
import jsonfield.fields
class Migration(migrations.Migration):
dependencies = [
('problem', '0004_auto_20170501_0637'),
]
operations = [
migrations.AddField(
model_name='contestproblem',
name='statistic_info',
field=jsonfield.fields.JSONField(default={}),
),
migrations.AddField(
model_name='problem',
name='statistic_info',
field=jsonfield.fields.JSONField(default={}),
),
]

View File

@ -57,6 +57,9 @@ class AbstractProblem(models.Model):
source = models.CharField(max_length=200, blank=True, null=True)
total_submit_number = models.BigIntegerField(default=0)
total_accepted_number = models.BigIntegerField(default=0)
# {0: 0, 1: 0, 2: 0, 3: 0 ...}
# the first number means JudgeStatus, the second number present count
statistic_info = JSONField(default={})
class Meta:
db_table = "problem"

View File

@ -95,21 +95,21 @@ class SubmissionListAPI(APIView):
if request.GET.get("contest_id"):
return self._get_contest_submission_list(request)
subs = Submission.objects.filter(contest_id__isnull=True)
return self.process_submissions(request, subs)
submissions = Submission.objects.filter(contest_id__isnull=True)
return self.process_submissions(request, submissions)
@check_contest_permission
def _get_contest_submission_list(self, request):
subs = Submission.objects.filter(contest_id=self.contest.id)
return self.process_submissions(request, subs)
def process_submissions(self, request, subs):
def process_submissions(self, request, submissions):
problem_id = request.GET.get("problem_id")
if problem_id:
subs = subs.filter(problem_id=problem_id)
submissions = submissions.filter(problem_id=problem_id)
if request.GET.get("myself") and request.GET["myself"] == "1":
subs = subs.filter(user_id=request.user.id)
data = self.paginate_data(request, subs)
submissions = submissions.filter(user_id=request.user.id)
data = self.paginate_data(request, submissions)
data["results"] = SubmissionListSerializer(data["results"], many=True, user=request.user).data
return self.success(data)

View File

@ -1,6 +1,6 @@
from django.conf import settings
from django_redis import get_redis_connection
judge_queue_cache = get_redis_connection(settings.CACHE_JUDGE_QUEUE)
judge_cache = get_redis_connection(settings.CACHE_JUDGE_QUEUE)
throttling_cache = get_redis_connection(settings.CACHE_THROTTLING)
default_cache = get_redis_connection("default")