import random import math from datetime import datetime from sqlalchemy.orm import Session from database import User, UpgradeRPU, Upgrade MAX_WIN_STREAK = 3 MAX_LOSE_STREAK = 5 def get_upgrade_rpu(db: Session, user_id: int) -> UpgradeRPU: """Получает или создает настройки РПУ апгрейдов""" rpu = db.query(UpgradeRPU).filter(UpgradeRPU.user_id == user_id).first() if not rpu: rpu = UpgradeRPU(user_id=user_id) db.add(rpu) from rpu import _rpu_commit_or_flush _rpu_commit_or_flush(db) db.refresh(rpu) return rpu def calculate_upgrade_probability(input_price: float, target_price: float) -> float: if input_price <= 0 or target_price <= 0: return 50.0 if target_price <= input_price: return -1.0 probability = (input_price / target_price) * 100 return max(1.0, min(75.0, probability)) def get_adjusted_upgrade_probability(db: Session, user_id: int, base_probability: float) -> float: if base_probability < 0: return -1.0 rpu = get_upgrade_rpu(db, user_id) # Базовая корректировка от множителя adjusted = base_probability * rpu.upgrade_multiplier # Корректировка на серии if rpu.current_win_streak >= MAX_WIN_STREAK: # Слишком много побед подряд — режем шанс penalty = (rpu.current_win_streak - MAX_WIN_STREAK + 1) * 0.15 adjusted *= (1.0 - penalty) elif rpu.current_lose_streak >= MAX_LOSE_STREAK: # Слишком много поражений подряд — повышаем шанс boost = (rpu.current_lose_streak - MAX_LOSE_STREAK + 1) * 0.2 adjusted *= (1.0 + boost) return max(1.0, min(75.0, adjusted)) def spin_upgrade_wheel(success_probability: float) -> tuple[bool, float, int, float]: raw_angle = random.uniform(0, 360) half_green = (success_probability / 100) * 180 success = 180 - half_green <= raw_angle <= 180 + half_green margin = max(3, half_green * 0.12) if success: rotations = random.randint(7, 9) lo = max(0, 180 - half_green + margin) hi = min(360, 180 + half_green - margin) if lo < hi: target_angle = random.uniform(lo, hi) else: target_angle = random.uniform(max(0, 180 - half_green + 1), min(360, 180 + half_green - 1)) else: rotations = random.randint(6, 8) left_size = max(0, 180 - half_green - 3) right_start = min(360, 180 + half_green + 3) right_size = max(0, 360 - right_start) if left_size >= right_size: lo = 0 hi = max(0, 180 - half_green - 3) else: lo = min(360, 180 + half_green + 3) hi = 360 if lo < hi: target_angle = random.uniform(lo, hi) else: target_angle = random.uniform(0, 360) final_angle = target_angle + rotations * 360 return success, final_angle, rotations, raw_angle def update_upgrade_stats(db: Session, user_id: int, success: bool, input_price: float): rpu = get_upgrade_rpu(db, user_id) rpu.total_attempts += 1 if success: rpu.total_success += 1 rpu.current_win_streak += 1 rpu.current_lose_streak = 0 if rpu.current_win_streak > rpu.best_win_streak: rpu.best_win_streak = rpu.current_win_streak else: rpu.total_spent_value += input_price rpu.current_lose_streak += 1 rpu.current_win_streak = 0 if rpu.current_lose_streak > rpu.worst_lose_streak: rpu.worst_lose_streak = rpu.current_lose_streak # Авто-подкрутка if rpu.auto_adjust and rpu.total_attempts >= 10: # Анализ серии побед if rpu.current_win_streak >= MAX_WIN_STREAK: rpu.upgrade_multiplier = max(0.3, rpu.upgrade_multiplier - 0.15) # Анализ серии поражений if rpu.current_lose_streak >= MAX_LOSE_STREAK: rpu.upgrade_multiplier = min(2.5, rpu.upgrade_multiplier + 0.2) # Общий процент побед rate = rpu.total_success / rpu.total_attempts if rate < 0.2: rpu.upgrade_multiplier = min(2.5, rpu.upgrade_multiplier + 0.1) elif rate > 0.6: rpu.upgrade_multiplier = max(0.3, rpu.upgrade_multiplier - 0.1) from rpu import _rpu_commit_or_flush _rpu_commit_or_flush(db)