mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2024-09-21 00:13:18 +00:00
完善OI细则
This commit is contained in:
parent
2c5a1e42bf
commit
f5566148bc
@ -92,7 +92,8 @@ def check_contest_permission(func):
|
|||||||
if not user.is_authenticated():
|
if not user.is_authenticated():
|
||||||
return self.error("Please login in first.")
|
return self.error("Please login in first.")
|
||||||
# password error
|
# password error
|
||||||
if ("contests" not in request.session) or (self.contest.id not in request.session["contests"]):
|
if ("accessible_contests" not in request.session) or \
|
||||||
|
(self.contest.id not in request.session["accessible_contests"]):
|
||||||
return self.error("Password is required.")
|
return self.error("Password is required.")
|
||||||
|
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
@ -45,6 +45,14 @@ class Contest(models.Model):
|
|||||||
def is_contest_admin(self, user):
|
def is_contest_admin(self, user):
|
||||||
return user.is_authenticated() and (self.created_by == user or user.admin_type == AdminType.SUPER_ADMIN)
|
return user.is_authenticated() and (self.created_by == user or user.admin_type == AdminType.SUPER_ADMIN)
|
||||||
|
|
||||||
|
def check_oi_permission(self, user):
|
||||||
|
if self.status != ContestStatus.CONTEST_ENDED and self.real_time_rank == False:
|
||||||
|
if self.is_contest_admin(user):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "contest"
|
db_table = "contest"
|
||||||
ordering = ("-create_time",)
|
ordering = ("-create_time",)
|
||||||
|
@ -67,7 +67,7 @@ class ContestPasswordVerifyAPI(APIView):
|
|||||||
# password verify OK.
|
# password verify OK.
|
||||||
if "accessible_contests" not in request.session:
|
if "accessible_contests" not in request.session:
|
||||||
request.session["accessible_contests"] = []
|
request.session["accessible_contests"] = []
|
||||||
request.session["contests"].append(contest.id)
|
request.session["accessible_contests"].append(contest.id)
|
||||||
# https://docs.djangoproject.com/en/dev/topics/http/sessions/#when-sessions-are-saved
|
# https://docs.djangoproject.com/en/dev/topics/http/sessions/#when-sessions-are-saved
|
||||||
request.session.modified = True
|
request.session.modified = True
|
||||||
return self.success(True)
|
return self.success(True)
|
||||||
@ -93,10 +93,12 @@ class ContestRankAPI(APIView):
|
|||||||
|
|
||||||
@check_contest_permission
|
@check_contest_permission
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
if self.contest.rule_type == ContestRuleType.ACM:
|
if self.contest.rule_type == ContestRuleType.OI:
|
||||||
serializer = ACMContestRankSerializer
|
if not self.contest.check_oi_permission(request.user):
|
||||||
else:
|
return self.error("You have no permission for ranks now")
|
||||||
serializer = OIContestRankSerializer
|
serializer = OIContestRankSerializer
|
||||||
|
else:
|
||||||
|
serializer = ACMContestRankSerializer
|
||||||
|
|
||||||
cache_key = f"{CacheKey.contest_rank_cache}:{self.contest.id}"
|
cache_key = f"{CacheKey.contest_rank_cache}:{self.contest.id}"
|
||||||
qs = cache.get(cache_key)
|
qs = cache.get(cache_key)
|
||||||
|
@ -156,7 +156,6 @@ class JudgeDispatcher(object):
|
|||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
# prepare problem and user_profile
|
# prepare problem and user_profile
|
||||||
problem = Problem.objects.select_for_update().get(contest_id=self.contest_id, id=self.problem.id)
|
problem = Problem.objects.select_for_update().get(contest_id=self.contest_id, id=self.problem.id)
|
||||||
problem_info = problem.statistic_info
|
|
||||||
user = User.objects.select_for_update().select_for_update("userprofile").get(id=self.submission.user_id)
|
user = User.objects.select_for_update().select_for_update("userprofile").get(id=self.submission.user_id)
|
||||||
user_profile = user.userprofile
|
user_profile = user.userprofile
|
||||||
if self.contest_id:
|
if self.contest_id:
|
||||||
@ -165,25 +164,25 @@ class JudgeDispatcher(object):
|
|||||||
key = "problems"
|
key = "problems"
|
||||||
acm_problems_status = user_profile.acm_problems_status.get(key, {})
|
acm_problems_status = user_profile.acm_problems_status.get(key, {})
|
||||||
oi_problems_status = user_profile.oi_problems_status.get(key, {})
|
oi_problems_status = user_profile.oi_problems_status.get(key, {})
|
||||||
|
problem_id = str(self.problem.id)
|
||||||
|
problem_info = problem.statistic_info
|
||||||
|
|
||||||
|
# update problem info
|
||||||
|
result = str(self.submission.result)
|
||||||
|
problem_info[result] = problem_info.get(result, 0) + 1
|
||||||
|
problem.statistic_info = problem_info
|
||||||
|
|
||||||
# update submission and accepted number counter
|
# update submission and accepted number counter
|
||||||
problem.submission_number += 1
|
problem.submission_number += 1
|
||||||
if self.submission.result == JudgeStatus.ACCEPTED:
|
if self.submission.result == JudgeStatus.ACCEPTED:
|
||||||
problem.accepted_number += 1
|
problem.accepted_number += 1
|
||||||
# only when submission is not in contest, we update user profile,
|
# submission in a contest will not be counted in user profile
|
||||||
# in other words, users' submission in a contest will not be counted in user profile
|
|
||||||
if not self.contest_id:
|
if not self.contest_id:
|
||||||
user_profile.submission_number += 1
|
user_profile.submission_number += 1
|
||||||
if self.submission.result == JudgeStatus.ACCEPTED:
|
if self.submission.result == JudgeStatus.ACCEPTED:
|
||||||
user_profile.accepted_number += 1
|
user_profile.accepted_number += 1
|
||||||
|
|
||||||
problem_id = str(self.problem.id)
|
|
||||||
if self.problem.rule_type == ProblemRuleType.ACM:
|
if self.problem.rule_type == ProblemRuleType.ACM:
|
||||||
# update acm problem info
|
|
||||||
result = str(self.submission.result)
|
|
||||||
problem_info[result] = problem_info.get(result, 0) + 1
|
|
||||||
problem.statistic_info = problem_info
|
|
||||||
|
|
||||||
# update user_profile
|
# update user_profile
|
||||||
if problem_id not in acm_problems_status:
|
if problem_id not in acm_problems_status:
|
||||||
acm_problems_status[problem_id] = {"status": self.submission.result, "_id": self.problem._id}
|
acm_problems_status[problem_id] = {"status": self.submission.result, "_id": self.problem._id}
|
||||||
@ -193,12 +192,8 @@ class JudgeDispatcher(object):
|
|||||||
user_profile.acm_problems_status[key] = acm_problems_status
|
user_profile.acm_problems_status[key] = acm_problems_status
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# update oi problem info
|
|
||||||
score = self.submission.statistic_info["score"]
|
|
||||||
problem_info[score] = problem_info.get(score, 0) + 1
|
|
||||||
problem.statistic_info = problem_info
|
|
||||||
|
|
||||||
# update user_profile
|
# update user_profile
|
||||||
|
score = self.submission.statistic_info["score"]
|
||||||
if problem_id not in oi_problems_status:
|
if problem_id not in oi_problems_status:
|
||||||
user_profile.add_score(score)
|
user_profile.add_score(score)
|
||||||
oi_problems_status[problem_id] = {"status": self.submission.result,
|
oi_problems_status[problem_id] = {"status": self.submission.result,
|
||||||
@ -218,8 +213,8 @@ class JudgeDispatcher(object):
|
|||||||
def update_contest_rank(self):
|
def update_contest_rank(self):
|
||||||
if self.contest_id and self.contest.status != ContestStatus.CONTEST_UNDERWAY:
|
if self.contest_id and self.contest.status != ContestStatus.CONTEST_UNDERWAY:
|
||||||
return
|
return
|
||||||
if self.contest.real_time_rank:
|
if self.contest.rule_type == ContestRuleType.OI or self.contest.real_time_rank:
|
||||||
cache.delete(CacheKey.contest_rank_cache + str(self.contest_id))
|
cache.delete(f"{CacheKey.contest_rank_cache}:{self.contest.id}")
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
if self.contest.rule_type == ContestRuleType.ACM:
|
if self.contest.rule_type == ContestRuleType.ACM:
|
||||||
acm_rank, _ = ACMContestRank.objects.select_for_update(). \
|
acm_rank, _ = ACMContestRank.objects.select_for_update(). \
|
||||||
|
@ -95,6 +95,7 @@ class ProblemAdminSerializer(BaseProblemSerializer):
|
|||||||
class ContestProblemAdminSerializer(BaseProblemSerializer):
|
class ContestProblemAdminSerializer(BaseProblemSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Problem
|
model = Problem
|
||||||
|
fields = "__all__"
|
||||||
|
|
||||||
|
|
||||||
class ProblemSerializer(BaseProblemSerializer):
|
class ProblemSerializer(BaseProblemSerializer):
|
||||||
|
@ -21,11 +21,10 @@ class ProblemAPI(APIView):
|
|||||||
oi_problems_status = profile.oi_problems_status.get("problems", {})
|
oi_problems_status = profile.oi_problems_status.get("problems", {})
|
||||||
# paginate data
|
# paginate data
|
||||||
results = queryset_values.get("results")
|
results = queryset_values.get("results")
|
||||||
if results:
|
if results is not None:
|
||||||
problems = results
|
problems = results
|
||||||
else:
|
else:
|
||||||
problems = [queryset_values,]
|
problems = [queryset_values,]
|
||||||
|
|
||||||
for problem in problems:
|
for problem in problems:
|
||||||
if problem["rule_type"] == ProblemRuleType.ACM:
|
if problem["rule_type"] == ProblemRuleType.ACM:
|
||||||
problem["my_status"] = acm_problems_status.get(str(problem["id"]), {}).get("status")
|
problem["my_status"] = acm_problems_status.get(str(problem["id"]), {}).get("status")
|
||||||
@ -53,11 +52,7 @@ class ProblemAPI(APIView):
|
|||||||
# 按照标签筛选
|
# 按照标签筛选
|
||||||
tag_text = request.GET.get("tag")
|
tag_text = request.GET.get("tag")
|
||||||
if tag_text:
|
if tag_text:
|
||||||
try:
|
problems = problems.filter(tags__name=tag_text)
|
||||||
tag = ProblemTag.objects.get(name=tag_text)
|
|
||||||
except ProblemTag.DoesNotExist:
|
|
||||||
return self.error("The Tag does not exist.")
|
|
||||||
problems = tag.problem_set.all().filter(visible=True)
|
|
||||||
|
|
||||||
# 搜索的情况
|
# 搜索的情况
|
||||||
keyword = request.GET.get("keyword", "").strip()
|
keyword = request.GET.get("keyword", "").strip()
|
||||||
@ -76,7 +71,11 @@ class ProblemAPI(APIView):
|
|||||||
|
|
||||||
class ContestProblemAPI(APIView):
|
class ContestProblemAPI(APIView):
|
||||||
def _add_problem_status(self, request, queryset_values):
|
def _add_problem_status(self, request, queryset_values):
|
||||||
if request.user.is_authenticated() and self.contest.rule_type != ContestRuleType.OI:
|
print("checking")
|
||||||
|
if self.contest.rule_type == ContestRuleType.OI and not self.contest.check_oi_permission(request.user):
|
||||||
|
return
|
||||||
|
print('here')
|
||||||
|
if request.user.is_authenticated():
|
||||||
profile = request.user.userprofile
|
profile = request.user.userprofile
|
||||||
if self.contest.rule_type == ContestRuleType.ACM:
|
if self.contest.rule_type == ContestRuleType.ACM:
|
||||||
problems_status = profile.acm_problems_status.get("contest_problems", {})
|
problems_status = profile.acm_problems_status.get("contest_problems", {})
|
||||||
@ -96,7 +95,7 @@ class ContestProblemAPI(APIView):
|
|||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return self.error("Problem does not exist.")
|
return self.error("Problem does not exist.")
|
||||||
problem_data = ContestProblemSerializer(problem).data
|
problem_data = ContestProblemSerializer(problem).data
|
||||||
self._add_problem_status(request, problem_data)
|
self._add_problem_status(request, [problem_data,])
|
||||||
return self.success(problem_data)
|
return self.success(problem_data)
|
||||||
|
|
||||||
contest_problems = Problem.objects.select_related("created_by").filter(contest=self.contest, visible=True)
|
contest_problems = Problem.objects.select_related("created_by").filter(contest=self.contest, visible=True)
|
||||||
|
@ -84,14 +84,13 @@ class SubmissionAPI(APIView):
|
|||||||
@login_required
|
@login_required
|
||||||
def put(self, request):
|
def put(self, request):
|
||||||
try:
|
try:
|
||||||
submission = Submission.objects.select_related("problem")\
|
submission = Submission.objects.select_related("problem").get(id=request.data["id"])
|
||||||
.get(id=request.data["id"], contest__isnull=True)
|
|
||||||
except Submission.DoesNotExist:
|
except Submission.DoesNotExist:
|
||||||
return self.error("Submission doesn't exist")
|
return self.error("Submission doesn't exist")
|
||||||
if not submission.check_user_permission(request.user, check_share=False):
|
if not submission.check_user_permission(request.user, check_share=False):
|
||||||
return self.error("No permission to share the submission")
|
return self.error("No permission to share the submission")
|
||||||
if submission.contest and submission.contest.status == ContestStatus.CONTEST_UNDERWAY:
|
if submission.contest and submission.contest.status == ContestStatus.CONTEST_UNDERWAY:
|
||||||
return self.error("Can not share submission during a contest going")
|
return self.error("Can not share submission now")
|
||||||
submission.shared = request.data["shared"]
|
submission.shared = request.data["shared"]
|
||||||
submission.save(update_fields=["shared"])
|
submission.save(update_fields=["shared"])
|
||||||
return self.success()
|
return self.success()
|
||||||
@ -130,7 +129,7 @@ class ContestSubmissionListAPI(APIView):
|
|||||||
return self.error("Limit is needed")
|
return self.error("Limit is needed")
|
||||||
|
|
||||||
contest = self.contest
|
contest = self.contest
|
||||||
if contest.rule_type == ContestRuleType.OI and not contest.is_contest_admin(request.user):
|
if not contest.check_oi_permission(request.user):
|
||||||
return self.error("No permission for OI contest submissions")
|
return self.error("No permission for OI contest submissions")
|
||||||
|
|
||||||
submissions = Submission.objects.filter(contest_id=contest.id).select_related("problem__created_by")
|
submissions = Submission.objects.filter(contest_id=contest.id).select_related("problem__created_by")
|
||||||
@ -154,9 +153,11 @@ class ContestSubmissionListAPI(APIView):
|
|||||||
submissions = submissions.filter(create_time__gte=contest.start_time)
|
submissions = submissions.filter(create_time__gte=contest.start_time)
|
||||||
|
|
||||||
# 封榜的时候只能看到自己的提交
|
# 封榜的时候只能看到自己的提交
|
||||||
|
if contest.rule_type == ContestRuleType.ACM:
|
||||||
if not contest.real_time_rank and not contest.is_contest_admin(request.user):
|
if not contest.real_time_rank and not contest.is_contest_admin(request.user):
|
||||||
submissions = submissions.filter(user_id=request.user.id)
|
submissions = submissions.filter(user_id=request.user.id)
|
||||||
|
|
||||||
data = self.paginate_data(request, submissions)
|
data = self.paginate_data(request, submissions)
|
||||||
data["results"] = SubmissionListSerializer(data["results"], many=True, user=request.user).data
|
data["results"] = SubmissionListSerializer(data["results"], many=True, user=request.user).data
|
||||||
return self.success(data)
|
return self.success(data)
|
||||||
|
|
||||||
|
@ -23,6 +23,6 @@ class ContestRuleType(Choices):
|
|||||||
|
|
||||||
class CacheKey:
|
class CacheKey:
|
||||||
waiting_queue = "waiting_queue"
|
waiting_queue = "waiting_queue"
|
||||||
contest_rank_cache = "contest_rank_cache_"
|
contest_rank_cache = "contest_rank_cache"
|
||||||
website_config = "website_config"
|
website_config = "website_config"
|
||||||
option = "option"
|
option = "option"
|
||||||
|
Loading…
Reference in New Issue
Block a user