chore: initial commit — CS2 Simulator

This commit is contained in:
2026-07-05 10:40:00 +00:00
commit c268557997
40 changed files with 824236 additions and 0 deletions
+192
View File
@@ -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)