Change points balance

This commit is contained in:
2025-12-16 03:06:26 +07:00
parent e32df4d95e
commit a199952383
3 changed files with 24 additions and 14 deletions

View File

@@ -182,7 +182,7 @@ async def spin_wheel(marathon_id: int, current_user: CurrentUser, db: DbSession)
await db.refresh(assignment) await db.refresh(assignment)
# Calculate drop penalty (considers active event for double_risk) # Calculate drop penalty (considers active event for double_risk)
drop_penalty = points_service.calculate_drop_penalty(participant.drop_count, active_event) drop_penalty = points_service.calculate_drop_penalty(participant.drop_count, challenge.points, active_event)
# Get challenges count (avoid lazy loading in async context) # Get challenges count (avoid lazy loading in async context)
challenges_count = 0 challenges_count = 0
@@ -238,7 +238,7 @@ async def get_current_assignment(marathon_id: int, current_user: CurrentUser, db
# Calculate drop penalty (considers active event for double_risk) # Calculate drop penalty (considers active event for double_risk)
active_event = await event_service.get_active_event(db, marathon_id) active_event = await event_service.get_active_event(db, marathon_id)
drop_penalty = points_service.calculate_drop_penalty(participant.drop_count, active_event) drop_penalty = points_service.calculate_drop_penalty(participant.drop_count, challenge.points, active_event)
return AssignmentResponse( return AssignmentResponse(
id=assignment.id, id=assignment.id,
@@ -496,7 +496,7 @@ async def drop_assignment(assignment_id: int, current_user: CurrentUser, db: DbS
active_event = await event_service.get_active_event(db, marathon_id) active_event = await event_service.get_active_event(db, marathon_id)
# Calculate penalty (0 if double_risk event is active) # Calculate penalty (0 if double_risk event is active)
penalty = points_service.calculate_drop_penalty(participant.drop_count, active_event) penalty = points_service.calculate_drop_penalty(participant.drop_count, assignment.challenge.points, active_event)
# Update assignment # Update assignment
assignment.status = AssignmentStatus.DROPPED.value assignment.status = AssignmentStatus.DROPPED.value

View File

@@ -40,7 +40,7 @@ class GPTService:
- description: что нужно сделать на русском (1-2 предложения) - description: что нужно сделать на русском (1-2 предложения)
- type: один из [completion, no_death, speedrun, collection, achievement, challenge_run] - type: один из [completion, no_death, speedrun, collection, achievement, challenge_run]
- difficulty: easy/medium/hard - difficulty: easy/medium/hard
- points: очки (easy: 30-50, medium: 60-100, hard: 120-200) - points: очки (easy: 20-40, medium: 45-75, hard: 90-150)
- estimated_time: примерное время в минутах - estimated_time: примерное время в минутах
- proof_type: screenshot/video/steam (что лучше подойдёт для проверки) - proof_type: screenshot/video/steam (что лучше подойдёт для проверки)
- proof_hint: что должно быть на скриншоте/видео для подтверждения на русском - proof_hint: что должно быть на скриншоте/видео для подтверждения на русском
@@ -77,10 +77,17 @@ class GPTService:
if proof_type not in ["screenshot", "video", "steam"]: if proof_type not in ["screenshot", "video", "steam"]:
proof_type = "screenshot" proof_type = "screenshot"
# Validate points # Validate points based on difficulty
points = ch.get("points", 50) points = ch.get("points", 30)
if not isinstance(points, int) or points < 1: if not isinstance(points, int) or points < 1:
points = 50 points = 30
# Clamp points to expected ranges
if difficulty == "easy":
points = max(20, min(40, points))
elif difficulty == "medium":
points = max(45, min(75, points))
elif difficulty == "hard":
points = max(90, min(150, points))
challenges.append(ChallengeGenerated( challenges.append(ChallengeGenerated(
title=ch.get("title", "Unnamed Challenge")[:100], title=ch.get("title", "Unnamed Challenge")[:100],

View File

@@ -13,12 +13,12 @@ class PointsService:
} }
MAX_STREAK_MULTIPLIER = 0.4 MAX_STREAK_MULTIPLIER = 0.4
DROP_PENALTIES = { # Drop penalty as percentage of challenge points
0: 0, # First drop is free DROP_PENALTY_PERCENTAGES = {
1: 10, 0: 0.5, # 1st drop: 50%
2: 25, 1: 0.75, # 2nd drop: 75%
} }
MAX_DROP_PENALTY = 50 MAX_DROP_PENALTY_PERCENTAGE = 1.0 # 3rd+ drop: 100%
# Event point multipliers # Event point multipliers
EVENT_MULTIPLIERS = { EVENT_MULTIPLIERS = {
@@ -66,6 +66,7 @@ class PointsService:
def calculate_drop_penalty( def calculate_drop_penalty(
self, self,
consecutive_drops: int, consecutive_drops: int,
challenge_points: int,
event: Event | None = None event: Event | None = None
) -> int: ) -> int:
""" """
@@ -73,6 +74,7 @@ class PointsService:
Args: Args:
consecutive_drops: Number of drops since last completion consecutive_drops: Number of drops since last completion
challenge_points: Base points of the challenge being dropped
event: Active event (optional) event: Active event (optional)
Returns: Returns:
@@ -82,10 +84,11 @@ class PointsService:
if event and event.type == EventType.DOUBLE_RISK.value: if event and event.type == EventType.DOUBLE_RISK.value:
return 0 return 0
return self.DROP_PENALTIES.get( penalty_percentage = self.DROP_PENALTY_PERCENTAGES.get(
consecutive_drops, consecutive_drops,
self.MAX_DROP_PENALTY self.MAX_DROP_PENALTY_PERCENTAGE
) )
return int(challenge_points * penalty_percentage)
def apply_event_multiplier(self, base_points: int, event: Event | None) -> int: def apply_event_multiplier(self, base_points: int, event: Event | None) -> int:
"""Apply event multiplier to points""" """Apply event multiplier to points"""