151 lines
6.1 KiB
Python
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)
|