from operator import attrgetter from django.db.models import Max from django.http import JsonResponse from judge.models import ContestParticipation, Problem, Profile, Submission from judge.utils.ranker import ranker from judge.views.contests import contest_ranking_list def error(message): return JsonResponse({"error": message}, status=422) def api_v2_user_info(request): """ { "points": 100.0, "rating": 2452, "rank": "user", "organizations": [], "solved_problems": ["ccc14s4", ...], "attempted_problems": [ { "code": "Hello, World!", "points": 1.0, "max_points": 2.0 } ], "authored_problems": ["dmpg16s4"], "contest_history": [ { "contest": { "code": "halloween14", "name": "Kemonomimi Party", "tags": ["seasonal"], "time_limit": null, "start_time": "2014-10-31T04:00:00+00:00", "end_time": "2014-11-10T05:00:00+00:00" }, "rank": 1, "rating:": 1800 }, // ... ] } """ try: username = request.GET["username"] except KeyError: return error("no username passed") if not username: return error("username argument not provided") try: profile = Profile.objects.get(user__username=username) except Profile.DoesNotExist: return error("no such user") last_rating = list(profile.ratings.order_by("-contest__end_time")) resp = { "rank": profile.display_rank, "organizations": list(profile.organizations.values_list("key", flat=True)), } contest_history = [] for participation in ContestParticipation.objects.filter( user=profile, virtual=0, contest__is_visible=True ).order_by("-contest__end_time"): contest = participation.contest problems = list( contest.contest_problems.select_related("problem") .defer("problem__description") .order_by("order") ) rank, result = next( filter( lambda data: data[1].user == profile.user, ranker( contest_ranking_list(contest, problems), key=attrgetter("points", "cumtime"), ), ) ) contest_history.append( { "contest": { "code": contest.key, "name": contest.name, "tags": list(contest.tags.values_list("name", flat=True)), "time_limit": contest.time_limit and contest.time_limit.total_seconds(), "start_time": contest.start_time.isoformat(), "end_time": contest.end_time.isoformat(), }, "rank": rank, "rating": result.participation_rating, } ) resp["contests"] = { "current_rating": last_rating[0].rating if last_rating else None, "history": contest_history, } solved_problems = [] attempted_problems = [] problem_data = ( Submission.objects.filter( points__gt=0, user=profile, problem__is_public=True, problem__is_organization_private=False, ) .annotate(max_pts=Max("points")) .values_list("max_pts", "problem__points", "problem__code") .distinct() ) for awarded_pts, max_pts, problem in problem_data: if awarded_pts == max_pts: solved_problems.append(problem) else: attempted_problems.append( { "awarded": awarded_pts, "max": max_pts, "problem": problem, } ) resp["problems"] = { "points": profile.points, "solved": solved_problems, "attempted": attempted_problems, "authored": list( Problem.objects.filter( is_public=True, is_organization_private=False, authors=profile ).values_list("code", flat=True) ), } return JsonResponse(resp)