出题人

This commit is contained in:
2025-10-03 02:03:19 +08:00
parent 893b2aba79
commit ce2a4629da
4 changed files with 41 additions and 8 deletions

View File

@@ -6,12 +6,14 @@ from ..views.oj import (
ProblemAPI, ProblemAPI,
ContestProblemAPI, ContestProblemAPI,
PickOneAPI, PickOneAPI,
ProblemAuthorAPI,
) )
urlpatterns = [ urlpatterns = [
path("problem/tags", ProblemTagAPI.as_view()), path("problem/tags", ProblemTagAPI.as_view()),
path("problem", ProblemAPI.as_view()), path("problem", ProblemAPI.as_view()),
path("problem/beat_count", ProblemSolvedPeopleCount.as_view()), path("problem/beat_count", ProblemSolvedPeopleCount.as_view()),
path("problem/author", ProblemAuthorAPI.as_view()),
path("pickone", PickOneAPI.as_view()), path("pickone", PickOneAPI.as_view()),
path("contest/problem", ContestProblemAPI.as_view()), path("contest/problem", ContestProblemAPI.as_view()),
] ]

View File

@@ -1,10 +1,12 @@
from datetime import datetime from datetime import datetime
import random import random
from django.db.models import Q, Count from django.db.models import Q, Count
from django.core.cache import cache
from account.models import User from account.models import User
from submission.models import Submission, JudgeStatus from submission.models import Submission, JudgeStatus
from utils.api import APIView from utils.api import APIView
from account.decorators import check_contest_permission from account.decorators import check_contest_permission
from utils.constants import CacheKey
from ..models import ProblemTag, Problem, ProblemRuleType from ..models import ProblemTag, Problem, ProblemRuleType
from ..serializers import ( from ..serializers import (
ProblemSerializer, ProblemSerializer,
@@ -82,6 +84,11 @@ class ProblemAPI(APIView):
.filter(contest_id__isnull=True, visible=True) .filter(contest_id__isnull=True, visible=True)
.order_by("-create_time") .order_by("-create_time")
) )
author = request.GET.get("author")
if author:
problems = problems.filter(created_by__username=author)
# 按照标签筛选 # 按照标签筛选
tag_text = request.GET.get("tag") tag_text = request.GET.get("tag")
if tag_text: if tag_text:
@@ -98,6 +105,7 @@ class ProblemAPI(APIView):
difficulty = request.GET.get("difficulty") difficulty = request.GET.get("difficulty")
if difficulty: if difficulty:
problems = problems.filter(difficulty=difficulty) problems = problems.filter(difficulty=difficulty)
# 根据profile 为做过的题目添加标记 # 根据profile 为做过的题目添加标记
data = self.paginate_data(request, problems, ProblemListSerializer) data = self.paginate_data(request, problems, ProblemListSerializer)
self._add_problem_status(request, data) self._add_problem_status(request, data)
@@ -166,17 +174,44 @@ class ProblemSolvedPeopleCount(APIView):
if submission_count == 0: if submission_count == 0:
return self.success(rate) return self.success(rate)
today = datetime.today() today = datetime.today()
twoYearAge = datetime(today.year - 2, today.month, today.day, 0, 0) years_ago = datetime(today.year - 2, today.month, today.day, 0, 0)
total_count = User.objects.filter( total_count = User.objects.filter(
is_disabled=False, last_login__gte=twoYearAge is_disabled=False, last_login__gte=years_ago
).count() ).count()
accepted_count = Submission.objects.filter( accepted_count = Submission.objects.filter(
problem_id=problem_id, problem_id=problem_id,
result=JudgeStatus.ACCEPTED, result=JudgeStatus.ACCEPTED,
create_time__gte=twoYearAge, create_time__gte=years_ago,
).aggregate(user_count=Count("user_id", distinct=True))["user_count"] ).aggregate(user_count=Count("user_id", distinct=True))["user_count"]
if accepted_count < total_count: if accepted_count < total_count:
rate = "%.2f" % ((total_count - accepted_count) / total_count * 100) rate = "%.2f" % ((total_count - accepted_count) / total_count * 100)
else: else:
rate = "0" rate = "0"
return self.success(rate) return self.success(rate)
class ProblemAuthorAPI(APIView):
def get(self, request):
# 统计出题用户
cached_data = cache.get(CacheKey.problem_authors)
if cached_data:
return self.success(cached_data)
authors = (
Problem.objects.filter(
visible=True, contest_id__isnull=True, created_by__is_disabled=False
)
.values("created_by__username")
.annotate(problem_count=Count("id"))
.order_by("-problem_count")
)
result = [
{
"username": author["created_by__username"],
"problem_count": author["problem_count"],
}
for author in authors
]
cache.set(CacheKey.problem_authors, result, 3600)
return self.success(result)

View File

@@ -25,6 +25,7 @@ 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"
problem_authors = "problem_authors"
class Difficulty(Choices): class Difficulty(Choices):

View File

@@ -57,11 +57,6 @@ def datetime2str(value, format="iso-8601"):
return value return value
return value.strftime(format) return value.strftime(format)
def timestamp2utcstr(value):
return datetime.datetime.utcfromtimestamp(value).isoformat()
def natural_sort_key(s, _nsre=re.compile(r"(\d+)")): def natural_sort_key(s, _nsre=re.compile(r"(\d+)")):
return [int(text) if text.isdigit() else text.lower() return [int(text) if text.isdigit() else text.lower()
for text in re.split(_nsre, s)] for text in re.split(_nsre, s)]