Files
dodep-simulator/upgrade.py
T

151 lines
6.1 KiB
Python

import random
import math
from datetime import datetime
from sqlalchemy import select
from sqlalchemy.orm import Session
from sqlalchemy.ext.asyncio import AsyncSession
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
async def get_upgrade_rpu_async(db: AsyncSession, user_id: int) -> UpgradeRPU:
result = await db.execute(select(UpgradeRPU).where(UpgradeRPU.user_id == user_id))
rpu = result.scalar_one_or_none()
if not rpu:
rpu = UpgradeRPU(user_id=user_id)
db.add(rpu)
from rpu import _rpu_commit_or_flush_async
await _rpu_commit_or_flush_async(db)
await 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))
async def get_adjusted_upgrade_probability_async(db: AsyncSession, user_id: int, base_probability: float) -> float:
if base_probability < 0:
return -1.0
rpu = await get_upgrade_rpu_async(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)
target_angle = random.uniform(lo, hi) if lo < hi else 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)
lo, hi = (0, max(0, 180 - half_green - 3)) if left_size >= right_size else (min(360, 180 + half_green + 3), 360)
target_angle = random.uniform(lo, hi) if lo < hi else random.uniform(min(360, 180 + half_green + 3), 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)
async def update_upgrade_stats_async(db: AsyncSession, user_id: int, success: bool, input_price: float):
rpu = await get_upgrade_rpu_async(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_async
await _rpu_commit_or_flush_async(db)