出题人

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,
ContestProblemAPI,
PickOneAPI,
ProblemAuthorAPI,
)
urlpatterns = [
path("problem/tags", ProblemTagAPI.as_view()),
path("problem", ProblemAPI.as_view()),
path("problem/beat_count", ProblemSolvedPeopleCount.as_view()),
path("problem/author", ProblemAuthorAPI.as_view()),
path("pickone", PickOneAPI.as_view()),
path("contest/problem", ContestProblemAPI.as_view()),
]

View File

@@ -1,10 +1,12 @@
from datetime import datetime
import random
from django.db.models import Q, Count
from django.core.cache import cache
from account.models import User
from submission.models import Submission, JudgeStatus
from utils.api import APIView
from account.decorators import check_contest_permission
from utils.constants import CacheKey
from ..models import ProblemTag, Problem, ProblemRuleType
from ..serializers import (
ProblemSerializer,
@@ -82,6 +84,11 @@ class ProblemAPI(APIView):
.filter(contest_id__isnull=True, visible=True)
.order_by("-create_time")
)
author = request.GET.get("author")
if author:
problems = problems.filter(created_by__username=author)
# 按照标签筛选
tag_text = request.GET.get("tag")
if tag_text:
@@ -98,6 +105,7 @@ class ProblemAPI(APIView):
difficulty = request.GET.get("difficulty")
if difficulty:
problems = problems.filter(difficulty=difficulty)
# 根据profile 为做过的题目添加标记
data = self.paginate_data(request, problems, ProblemListSerializer)
self._add_problem_status(request, data)
@@ -166,17 +174,44 @@ class ProblemSolvedPeopleCount(APIView):
if submission_count == 0:
return self.success(rate)
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(
is_disabled=False, last_login__gte=twoYearAge
is_disabled=False, last_login__gte=years_ago
).count()
accepted_count = Submission.objects.filter(
problem_id=problem_id,
result=JudgeStatus.ACCEPTED,
create_time__gte=twoYearAge,
create_time__gte=years_ago,
).aggregate(user_count=Count("user_id", distinct=True))["user_count"]
if accepted_count < total_count:
rate = "%.2f" % ((total_count - accepted_count) / total_count * 100)
else:
rate = "0"
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"
contest_rank_cache = "contest_rank_cache"
website_config = "website_config"
problem_authors = "problem_authors"
class Difficulty(Choices):

View File

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