diff --git a/account/migrations/0004_remove_userprofile_time_zone.py b/account/migrations/0004_remove_userprofile_time_zone.py new file mode 100644 index 00000000..97345a40 --- /dev/null +++ b/account/migrations/0004_remove_userprofile_time_zone.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2017-08-23 09:04 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0003_userprofile_total_score'), + ] + + operations = [ + migrations.RemoveField( + model_name='userprofile', + name='time_zone', + ), + ] diff --git a/contest/migrations/0005_auto_20170823_0918.py b/contest/migrations/0005_auto_20170823_0918.py new file mode 100644 index 00000000..dbf12c66 --- /dev/null +++ b/contest/migrations/0005_auto_20170823_0918.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2017-08-23 09:18 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('contest', '0004_auto_20170717_1324'), + ] + + operations = [ + migrations.RenameField( + model_name='acmcontestrank', + old_name='total_ac_number', + new_name='accepted_number', + ), + migrations.RenameField( + model_name='acmcontestrank', + old_name='total_submission_number', + new_name='submission_number', + ), + migrations.RenameField( + model_name='oicontestrank', + old_name='total_submission_number', + new_name='submission_number', + ), + ] diff --git a/contest/models.py b/contest/models.py index ca991423..bda6c6c0 100644 --- a/contest/models.py +++ b/contest/models.py @@ -64,14 +64,14 @@ class Contest(models.Model): class ContestRank(models.Model): user = models.ForeignKey(User) contest = models.ForeignKey(Contest) - total_submission_number = models.IntegerField(default=0) + submission_number = models.IntegerField(default=0) class Meta: abstract = True class ACMContestRank(ContestRank): - total_ac_number = models.IntegerField(default=0) + accepted_number = models.IntegerField(default=0) # total_time is only for ACM contest total_time = ac time + none-ac times * 20 * 60 total_time = models.IntegerField(default=0) # {23: {"is_ac": True, "ac_time": 8999, "error_number": 2, "is_first_ac": True}} @@ -92,7 +92,7 @@ class OIContestRank(ContestRank): db_table = "oi_contest_rank" def update_rank(self, submission): - self.total_submission_number += 1 + self.submission_number += 1 class ContestAnnouncement(models.Model): diff --git a/contest/views/oj.py b/contest/views/oj.py index 5e2b72a2..28ee1bc2 100644 --- a/contest/views/oj.py +++ b/contest/views/oj.py @@ -1,7 +1,9 @@ +import pickle from django.utils.timezone import now from django.db.models import Q -from django.core.cache import cache from utils.api import APIView, validate_serializer +from utils.cache import default_cache +from utils.constants import CacheKey from account.decorators import login_required, check_contest_permission from ..models import ContestAnnouncement, Contest, ContestStatus, ContestRuleType @@ -90,20 +92,25 @@ class ContestAccessAPI(APIView): class ContestRankAPI(APIView): def get_rank(self): if self.contest.rule_type == ContestRuleType.ACM: - rank = ACMContestRank.objects.filter(contest=self.contest). \ - select_related("user").order_by("-total_ac_number", "total_time") - print(rank) - return ACMContestRankSerializer(rank, many=True).data + return ACMContestRank.objects.filter(contest=self.contest). \ + select_related("user").order_by("-accepted_number", "total_time") else: - rank = OIContestRank.objects.filter(contest=self.contest). \ + return OIContestRank.objects.filter(contest=self.contest). \ select_related("user").order_by("-total_score") - return OIContestRankSerializer(rank, many=True).data @check_contest_permission def get(self, request): - cache_key = str(self.contest.id) + "_rank_cache" - rank = cache.get(cache_key) - if not rank: - rank = self.get_rank() - cache.set(cache_key, rank) - return self.success(rank) + if self.contest.rule_type == ContestRuleType.ACM: + model, serializer = ACMContestRank, ACMContestRankSerializer + else: + model, serializer = OIContestRank, OIContestRankSerializer + + cache_key = CacheKey.contest_rank_cache + str(self.contest.id) + qs = default_cache.get(cache_key) + if not qs: + ranks = self.get_rank() + default_cache.set(cache_key, pickle.dumps(ranks)) + else: + ranks = pickle.loads(qs) + + return self.success(self.paginate_data(request, ranks, serializer)) diff --git a/judge/dispatcher.py b/judge/dispatcher.py index 9b4339df..e21ecb40 100644 --- a/judge/dispatcher.py +++ b/judge/dispatcher.py @@ -210,29 +210,29 @@ class JudgeDispatcher(object): if info["is_ac"]: return - rank.total_submission_number += 1 + rank.submission_number += 1 if self.submission.result == JudgeStatus.ACCEPTED: - rank.total_ac_number += 1 + rank.accepted_number += 1 info["is_ac"] = True info["ac_time"] = (self.submission.create_time - self.contest.start_time).total_seconds() rank.total_time += info["ac_time"] + info["error_number"] * 20 * 60 - if problem.total_accepted_number == 1: + if problem.accepted_number == 1: info["is_first_ac"] = True else: info["error_number"] += 1 # 第一次提交 else: - rank.total_submission_number += 1 + rank.submission_number += 1 info = {"is_ac": False, "ac_time": 0, "error_number": 0, "is_first_ac": False} if self.submission.result == JudgeStatus.ACCEPTED: - rank.total_ac_number += 1 + rank.accepted_number += 1 info["is_ac"] = True info["ac_time"] = (self.submission.create_time - self.contest.start_time).total_seconds() rank.total_time += info["ac_time"] - if problem.total_accepted_number == 1: + if problem.accepted_number == 1: info["is_first_ac"] = True else: diff --git a/problem/migrations/0006_auto_20170823_0918.py b/problem/migrations/0006_auto_20170823_0918.py new file mode 100644 index 00000000..933070f8 --- /dev/null +++ b/problem/migrations/0006_auto_20170823_0918.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2017-08-23 09:18 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('problem', '0005_auto_20170815_1258'), + ] + + operations = [ + migrations.RenameField( + model_name='contestproblem', + old_name='total_accepted_number', + new_name='accepted_number', + ), + migrations.RenameField( + model_name='contestproblem', + old_name='total_submit_number', + new_name='submission_number', + ), + migrations.RenameField( + model_name='problem', + old_name='total_accepted_number', + new_name='accepted_number', + ), + migrations.RenameField( + model_name='problem', + old_name='total_submit_number', + new_name='submission_number', + ), + ] diff --git a/problem/models.py b/problem/models.py index 6915ee08..c6da0001 100644 --- a/problem/models.py +++ b/problem/models.py @@ -55,8 +55,8 @@ class AbstractProblem(models.Model): difficulty = models.CharField(max_length=32) tags = models.ManyToManyField(ProblemTag) source = models.CharField(max_length=200, blank=True, null=True) - total_submit_number = models.BigIntegerField(default=0) - total_accepted_number = models.BigIntegerField(default=0) + submission_number = models.BigIntegerField(default=0) + 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={}) @@ -66,12 +66,12 @@ class AbstractProblem(models.Model): abstract = True def add_submission_number(self): - self.total_submit_number = models.F("total_submit_number") + 1 - self.save(update_fields=["total_submit_number"]) + self.submission_number = models.F("submission_number") + 1 + self.save(update_fields=["submission_number"]) def add_ac_number(self): - self.total_accepted_number = models.F("total_accepted_number") + 1 - self.save(update_fields=["total_accepted_number"]) + self.accepted_number = models.F("accepted_number") + 1 + self.save(update_fields=["accepted_number"]) class Problem(AbstractProblem): diff --git a/utils/constants.py b/utils/constants.py index 66ef1696..86181b6c 100644 --- a/utils/constants.py +++ b/utils/constants.py @@ -1,2 +1,3 @@ class CacheKey: waiting_queue = "waiting_queue" + contest_rank_cache = "contest_rank_cache_"