from app.models import Event, EventType class PointsService: """Service for calculating points and penalties""" STREAK_MULTIPLIERS = { 0: 0.0, 1: 0.0, 2: 0.1, 3: 0.2, 4: 0.3, } MAX_STREAK_MULTIPLIER = 0.4 # Drop penalty as percentage of challenge points DROP_PENALTY_PERCENTAGES = { 0: 0.5, # 1st drop: 50% 1: 0.75, # 2nd drop: 75% } MAX_DROP_PENALTY_PERCENTAGE = 1.0 # 3rd+ drop: 100% # Event point multipliers EVENT_MULTIPLIERS = { EventType.GOLDEN_HOUR.value: 1.5, EventType.DOUBLE_RISK.value: 0.5, EventType.JACKPOT.value: 3.0, # GAME_CHOICE uses 1.0 multiplier (default) } def calculate_completion_points( self, base_points: int, current_streak: int, event: Event | None = None, ) -> tuple[int, int, int]: """ Calculate points earned for completing a challenge. Args: base_points: Base points for the challenge current_streak: Current streak before this completion event: Active event (optional) Returns: Tuple of (total_points, streak_bonus, event_bonus) """ # Apply event multiplier first event_multiplier = 1.0 if event: event_multiplier = self.EVENT_MULTIPLIERS.get(event.type, 1.0) adjusted_base = int(base_points * event_multiplier) event_bonus = adjusted_base - base_points # Then apply streak bonus streak_multiplier = self.STREAK_MULTIPLIERS.get( current_streak, self.MAX_STREAK_MULTIPLIER ) streak_bonus = int(adjusted_base * streak_multiplier) total_points = adjusted_base + streak_bonus return total_points, streak_bonus, event_bonus def calculate_drop_penalty( self, consecutive_drops: int, challenge_points: int, event: Event | None = None ) -> int: """ Calculate penalty for dropping a challenge. Args: consecutive_drops: Number of drops since last completion challenge_points: Base points of the challenge being dropped event: Active event (optional) Returns: Penalty points to subtract """ # Double risk event = free drops if event and event.type == EventType.DOUBLE_RISK.value: return 0 penalty_percentage = self.DROP_PENALTY_PERCENTAGES.get( consecutive_drops, self.MAX_DROP_PENALTY_PERCENTAGE ) return int(challenge_points * penalty_percentage) def apply_event_multiplier(self, base_points: int, event: Event | None) -> int: """Apply event multiplier to points""" if not event: return base_points multiplier = self.EVENT_MULTIPLIERS.get(event.type, 1.0) return int(base_points * multiplier)