import random from django.db.models import Q, Count from utils.api import APIView from account.decorators import check_contest_permission from ..models import ProblemTag, Problem, ProblemRuleType from ..serializers import ProblemSerializer, TagSerializer, ProblemSafeSerializer from contest.models import ContestRuleType class ProblemTagAPI(APIView): def get(self, request): tags = ProblemTag.objects.annotate(problem_count=Count("problem")).filter(problem_count__gt=0) return self.success(TagSerializer(tags, many=True).data) class PickOneAPI(APIView): def get(self, request): problems = Problem.objects.filter(contest_id__isnull=True, visible=True) count = problems.count() if count == 0: return self.error("No problem to pick") return self.success(problems[random.randint(0, count - 1)]._id) class ProblemAPI(APIView): @staticmethod def _add_problem_status(request, queryset_values): if request.user.is_authenticated: profile = request.user.userprofile acm_problems_status = profile.acm_problems_status.get("problems", {}) oi_problems_status = profile.oi_problems_status.get("problems", {}) # paginate data results = queryset_values.get("results") if results is not None: problems = results else: problems = [queryset_values, ] for problem in problems: if problem["rule_type"] == ProblemRuleType.ACM: problem["my_status"] = acm_problems_status.get(str(problem["id"]), {}).get("status") else: problem["my_status"] = oi_problems_status.get(str(problem["id"]), {}).get("status") def get(self, request): # 问题详情页 problem_id = request.GET.get("problem_id") if problem_id: try: problem = Problem.objects.select_related("created_by") \ .get(_id=problem_id, contest_id__isnull=True, visible=True) problem_data = ProblemSerializer(problem).data self._add_problem_status(request, problem_data) return self.success(problem_data) except Problem.DoesNotExist: return self.error("Problem does not exist") limit = request.GET.get("limit") if not limit: return self.error("Limit is needed") problems = Problem.objects.select_related("created_by").filter(contest_id__isnull=True, visible=True) # 按照标签筛选 tag_text = request.GET.get("tag") if tag_text: problems = problems.filter(tags__name=tag_text) # 搜索的情况 keyword = request.GET.get("keyword", "").strip() if keyword: problems = problems.filter(Q(title__icontains=keyword) | Q(_id__icontains=keyword)) # 难度筛选 difficulty = request.GET.get("difficulty") if difficulty: problems = problems.filter(difficulty=difficulty) # 根据profile 为做过的题目添加标记 data = self.paginate_data(request, problems, ProblemSerializer) self._add_problem_status(request, data) return self.success(data) class ContestProblemAPI(APIView): def _add_problem_status(self, request, queryset_values): if request.user.is_authenticated: profile = request.user.userprofile if self.contest.rule_type == ContestRuleType.ACM: problems_status = profile.acm_problems_status.get("contest_problems", {}) else: problems_status = profile.oi_problems_status.get("contest_problems", {}) for problem in queryset_values: problem["my_status"] = problems_status.get(str(problem["id"]), {}).get("status") @check_contest_permission(check_type="problems") def get(self, request): problem_id = request.GET.get("problem_id") if problem_id: try: problem = Problem.objects.select_related("created_by").get(_id=problem_id, contest=self.contest, visible=True) except Problem.DoesNotExist: return self.error("Problem does not exist.") if self.contest.problem_details_permission(request.user): problem_data = ProblemSerializer(problem).data self._add_problem_status(request, [problem_data, ]) else: problem_data = ProblemSafeSerializer(problem).data return self.success(problem_data) random.seed(request.user.id + request.contest.id) # Random problems for every students in contest def random_contest_problems(self, difficulty='Low', count=3): contest_problem_set = Problem.objects.select_related("created_by").filter(contest=self.contest, visible=True, difficulty=difficulty).all() contest_problem_id = [] for i in contest_problem_set: contest_problem_id.append(i._id) contest_problem_id = random.sample(contest_problem_id, count) contest_problems = Problem.objects.select_related("created_by").filter(contest=self.contest, visible=True, _id__in=contest_problem_id) return contest_problems contest_low_problems = random_contest_problems(difficulty='Low', count=3) contest_mid_problems = random_contest_problems(difficulty='Mid', count=2) contest_high_problems = random_contest_problems(difficulty='High', count=0) contest_problems = (contest_low_problems | contest_mid_problems | contest_high_problems).order_by("_id") # self.contest_problem_list = random.sample(contest_low_problem_set, 3) # self.contest_problem_list.extend(random.sample(contest_mid_problem_set, 2)) # self.contest_problem_list.extend(random.sample(contest_high_problem_set, 0)) # # contest_problems = Problem.objects.select_related("created_by").filter(contest=self.contest, visible=True, _id__in=self.probelm_list).order_by('_id') if self.contest.problem_details_permission(request.user): data = ProblemSerializer(contest_problems, many=True).data self._add_problem_status(request, data) else: data = ProblemSafeSerializer(contest_problems, many=True).data return self.success(data)