109 lines
4.1 KiB
Python
109 lines
4.1 KiB
Python
from django.db.models import Prefetch, Q
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from contest.models import RatingHistory, RealtimeMatch
|
|
|
|
from .models import UserAbility, UserPet
|
|
|
|
|
|
class ProgressionProfileView(APIView):
|
|
def get(self, request):
|
|
pet, _ = UserPet.objects.get_or_create(user=request.user)
|
|
existing = {ability.dimension: ability for ability in request.user.abilities.all()}
|
|
abilities = []
|
|
for dimension, label in UserAbility.Dimension.choices:
|
|
ability = existing.get(dimension)
|
|
if ability is None:
|
|
ability = UserAbility.objects.create(user=request.user, dimension=dimension)
|
|
abilities.append(
|
|
{
|
|
"dimension": dimension,
|
|
"label": label,
|
|
"level": ability.level,
|
|
"fragments": ability.fragments,
|
|
}
|
|
)
|
|
matches = (
|
|
RealtimeMatch.objects.filter(
|
|
Q(player_one=request.user) | Q(player_two=request.user),
|
|
status=RealtimeMatch.Status.COMPLETED,
|
|
)
|
|
.select_related("contest", "player_one", "player_two", "winner")
|
|
.prefetch_related(
|
|
Prefetch(
|
|
"rating_changes",
|
|
queryset=RatingHistory.objects.filter(user=request.user),
|
|
to_attr="viewer_rating_changes",
|
|
)
|
|
)
|
|
.order_by("-completed_at")[:10]
|
|
)
|
|
recent_matches = []
|
|
for match in matches:
|
|
opponent = (
|
|
match.player_two
|
|
if match.player_one_id == request.user.id
|
|
else match.player_one
|
|
)
|
|
rating_change = (
|
|
match.viewer_rating_changes[0]
|
|
if match.viewer_rating_changes
|
|
else None
|
|
)
|
|
recent_matches.append(
|
|
{
|
|
"match_id": match.id,
|
|
"contest": match.contest.title,
|
|
"opponent": opponent.nickname if opponent else "未知对手",
|
|
"result": (
|
|
"draw"
|
|
if match.winner_id is None
|
|
else "win"
|
|
if match.winner_id == request.user.id
|
|
else "loss"
|
|
),
|
|
"rating_delta": rating_change.delta if rating_change else 0,
|
|
"rating_after": (
|
|
rating_change.rating_after
|
|
if rating_change
|
|
else request.user.rating
|
|
),
|
|
"completed_at": match.completed_at,
|
|
}
|
|
)
|
|
return Response(
|
|
{
|
|
"pet": {
|
|
"name": pet.name,
|
|
"level": pet.level,
|
|
"experience": pet.experience,
|
|
"appearance": pet.appearance,
|
|
},
|
|
"abilities": abilities,
|
|
"cards": [
|
|
{
|
|
"slug": item.card.slug,
|
|
"name": item.card.name,
|
|
"mathematician": item.card.mathematician,
|
|
"image": item.card.image,
|
|
"acquired_at": item.acquired_at,
|
|
}
|
|
for item in request.user.cards.select_related("card")
|
|
],
|
|
"recent_games": [
|
|
{
|
|
"kind": attempt.kind,
|
|
"label": attempt.get_kind_display(),
|
|
"difficulty": attempt.get_difficulty_display(),
|
|
"status": attempt.status,
|
|
"score": attempt.score,
|
|
"duration_ms": attempt.duration_ms,
|
|
"started_at": attempt.started_at,
|
|
}
|
|
for attempt in request.user.math_game_attempts.all()[:10]
|
|
],
|
|
"recent_matches": recent_matches,
|
|
}
|
|
)
|