import random from datetime import datetime from typing import Dict, Optional from sqlalchemy.orm import Session from database import User, UserRPU # Стандартные веса редкостей BASE_RARITY_WEIGHTS = { "Consumer Grade": 10000, "Industrial Grade": 5000, "Mil-Spec": 2500, "Mil-Spec Grade": 2500, "Restricted": 625, "Classified": 125, "Covert": 25, "Rare Special Item": 5, "Extraordinary": 5 } # Маппинг редкостей на поля в UserRPU RARITY_TO_FIELD = { "Consumer Grade": "consumer_multiplier", "Industrial Grade": "industrial_multiplier", "Mil-Spec": "mil_spec_multiplier", "Mil-Spec Grade": "mil_spec_multiplier", "Restricted": "restricted_multiplier", "Classified": "classified_multiplier", "Covert": "covert_multiplier", "Rare Special Item": "rare_special_multiplier", "Extraordinary": "rare_special_multiplier" } def get_user_rpu(db: Session, user_id: int) -> UserRPU: """Получает или создает настройки РПУ для пользователя""" rpu = db.query(UserRPU).filter(UserRPU.user_id == user_id).first() if not rpu: rpu = UserRPU(user_id=user_id) db.add(rpu) db.commit() db.refresh(rpu) return rpu def get_adjusted_weights(db: Session, user_id: int) -> Dict[str, float]: """ Получает веса редкостей с учетом РПУ пользователя. НИЗКИЙ % РПУ = ПОВЫШЕННЫЕ шансы на редкое (везёт) ВЫСОКИЙ % РПУ = ПОНИЖЕННЫЕ шансы на редкое (не везёт) """ rpu = get_user_rpu(db, user_id) # Вычисляем общий уровень РПУ (0-100%) rpu_level = calculate_rpu_level(rpu) # Переворачиваем: низкий РПУ = высокий множитель для редких # При 0% РПУ множитель для редких = 2.0 (очень везёт) # При 50% РПУ множитель = 1.0 (обычно) # При 100% РПУ множитель = 0.1 (совсем не везёт) adjusted = {} for rarity, base_weight in BASE_RARITY_WEIGHTS.items(): field = RARITY_TO_FIELD.get(rarity) base_multiplier = getattr(rpu, field, 1.0) if field else 1.0 # Определяем "редкость" предмета (чем реже, тем больше индекс) rarity_index = 0 if "Industrial" in rarity: rarity_index = 1 elif "Mil-Spec" in rarity: rarity_index = 2 elif "Restricted" in rarity: rarity_index = 3 elif "Classified" in rarity: rarity_index = 4 elif "Covert" in rarity: rarity_index = 5 elif "Rare Special" in rarity or "Extraordinary" in rarity: rarity_index = 6 # Чем выше РПУ, тем сильнее режем шансы на редкое # Чем ниже РПУ, тем сильнее повышаем шансы на редкое if rpu_level < 50: # Везёт: повышаем шансы на редкое luck_factor = 1.0 + ((50 - rpu_level) / 50) * rarity_index * 0.3 else: # Не везёт: понижаем шансы на редкое luck_factor = 1.0 - ((rpu_level - 50) / 50) * rarity_index * 0.2 luck_factor = max(0.1, min(3.0, luck_factor)) final_multiplier = base_multiplier * rpu.luck_multiplier * luck_factor adjusted[rarity] = base_weight * final_multiplier return adjusted def calculate_rpu_level(rpu: UserRPU) -> float: """ Вычисляет общий уровень РПУ (0-100%). 0% = максимальное везение 100% = максимальное невезение """ multipliers = [ rpu.consumer_multiplier, rpu.industrial_multiplier, rpu.mil_spec_multiplier, rpu.restricted_multiplier, rpu.classified_multiplier, rpu.covert_multiplier, rpu.rare_special_multiplier ] # Средний множитель avg = sum(multipliers) / len(multipliers) # Преобразуем в проценты: 0.1x = 100% РПУ (не везёт), 3.0x = 0% РПУ (везёт) # 1.0x = 50% РПУ if avg >= 1.0: level = 50 - ((avg - 1.0) / 2.0) * 100 else: level = 50 + ((1.0 - avg) / 0.9) * 50 return max(0, min(100, level)) def get_rpu_description(level: float) -> str: """Возвращает текстовое описание уровня РПУ""" if level < 20: return "🍀 Очень везучий" elif level < 35: return "😊 Везучий" elif level < 45: return "🙂 Немного везучий" elif level < 55: return "😐 Обычный" elif level < 70: return "🙁 Немного невезучий" elif level < 85: return "😟 Невезучий" else: return "💀 Проклятый" def auto_adjust_rpu(db: Session, user_id: int): """Автоматическая подкрутка РПУ на основе статистики""" rpu = get_user_rpu(db, user_id) if not rpu.auto_adjust: return user = db.query(User).filter(User.id == user_id).first() if not user: return # Анализируем статистику if rpu.total_opened > 0: avg_spent_per_case = rpu.total_spent / rpu.total_opened # Если пользователь много тратит и мало получает - снижаем РПУ (даём везение) if rpu.total_spent > 10000 and rpu.total_opened > 20: # Снижаем РПУ на 5-15% reduction = min(0.15, rpu.total_spent / 100000) rpu.luck_multiplier = min(2.0, rpu.luck_multiplier + reduction) # Если пользователь часто открывает кейсы - немного снижаем РПУ if rpu.total_opened > 50: rpu.classified_multiplier = min(1.5, rpu.classified_multiplier + 0.05) rpu.covert_multiplier = min(1.3, rpu.covert_multiplier + 0.03) # Ограничиваем множители for field in ['consumer_multiplier', 'industrial_multiplier', 'mil_spec_multiplier', 'restricted_multiplier', 'classified_multiplier', 'covert_multiplier', 'rare_special_multiplier']: value = getattr(rpu, field) setattr(rpu, field, max(0.1, min(3.0, value))) rpu.luck_multiplier = max(0.1, min(3.0, rpu.luck_multiplier)) rpu.last_adjustment = datetime.utcnow() db.commit() def update_rpu_stats(db: Session, user_id: int, spent: float, opened: int = 1): """Обновляет статистику РПУ после открытия кейсов""" rpu = get_user_rpu(db, user_id) rpu.total_spent += spent rpu.total_opened += opened db.commit() # Авто-подкрутка если включена if rpu.auto_adjust: auto_adjust_rpu(db, user_id)