2020-01-21 06:35:58 +00:00
|
|
|
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):
|
2022-05-14 17:57:27 +00:00
|
|
|
return JsonResponse({"error": message}, status=422)
|
2020-01-21 06:35:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
},
|
|
|
|
// ...
|
|
|
|
]
|
|
|
|
}
|
2022-05-14 17:57:27 +00:00
|
|
|
"""
|
2020-01-21 06:35:58 +00:00
|
|
|
try:
|
2022-05-14 17:57:27 +00:00
|
|
|
username = request.GET["username"]
|
2020-01-21 06:35:58 +00:00
|
|
|
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")
|
|
|
|
|
2022-05-14 17:57:27 +00:00
|
|
|
last_rating = list(profile.ratings.order_by("-contest__end_time"))
|
2020-01-21 06:35:58 +00:00
|
|
|
|
|
|
|
resp = {
|
|
|
|
"rank": profile.display_rank,
|
2022-05-14 17:57:27 +00:00
|
|
|
"organizations": list(profile.organizations.values_list("key", flat=True)),
|
2020-01-21 06:35:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
contest_history = []
|
2022-05-14 17:57:27 +00:00
|
|
|
for participation in ContestParticipation.objects.filter(
|
|
|
|
user=profile, virtual=0, contest__is_visible=True
|
|
|
|
).order_by("-contest__end_time"):
|
2020-01-21 06:35:58 +00:00
|
|
|
contest = participation.contest
|
|
|
|
|
2022-05-14 17:57:27 +00:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
)
|
2020-01-21 06:35:58 +00:00
|
|
|
|
2022-05-14 17:57:27 +00:00
|
|
|
resp["contests"] = {
|
2020-01-21 06:35:58 +00:00
|
|
|
"current_rating": last_rating[0].rating if last_rating else None,
|
2022-05-14 17:57:27 +00:00
|
|
|
"history": contest_history,
|
2020-01-21 06:35:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
solved_problems = []
|
|
|
|
attempted_problems = []
|
|
|
|
|
2022-05-14 17:57:27 +00:00
|
|
|
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()
|
|
|
|
)
|
2020-01-21 06:35:58 +00:00
|
|
|
for awarded_pts, max_pts, problem in problem_data:
|
|
|
|
if awarded_pts == max_pts:
|
|
|
|
solved_problems.append(problem)
|
|
|
|
else:
|
2022-05-14 17:57:27 +00:00
|
|
|
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)
|
|
|
|
),
|
2020-01-21 06:35:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return JsonResponse(resp)
|