chore: initial commit — CS2 Simulator
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user