paper-dynasty-card-creation/rarity_thresholds.py
2025-11-08 16:57:35 -06:00

145 lines
4.3 KiB
Python

"""
Rarity threshold configurations for card creation.
This module defines OPS thresholds for assigning rarity tiers to player cards.
Different seasons may have different thresholds based on league-wide performance.
"""
from dataclasses import dataclass
@dataclass
class PitcherRarityThresholds:
"""OPS-against thresholds for pitcher rarity assignment."""
# Starter thresholds (OPS-against, lower is better)
starter_hof: float # Hall of Fame (99)
starter_diamond: float # Diamond (1)
starter_gold: float # Gold (2)
starter_silver: float # Silver (3)
starter_bronze: float # Bronze (4)
# Reliever thresholds (OPS-against, lower is better)
reliever_hof: float # Hall of Fame (99)
reliever_diamond: float # Diamond (1)
reliever_gold: float # Gold (2)
reliever_silver: float # Silver (3)
reliever_bronze: float # Bronze (4)
def get_rarity_for_starter(self, total_ops: float) -> int:
"""Returns rarity ID for a starting pitcher based on OPS-against."""
if total_ops <= self.starter_hof:
return 99
elif total_ops <= self.starter_diamond:
return 1
elif total_ops <= self.starter_gold:
return 2
elif total_ops <= self.starter_silver:
return 3
elif total_ops <= self.starter_bronze:
return 4
else:
return 5 # Common
def get_rarity_for_reliever(self, total_ops: float) -> int:
"""Returns rarity ID for a relief pitcher based on OPS-against."""
if total_ops <= self.reliever_hof:
return 99
elif total_ops <= self.reliever_diamond:
return 1
elif total_ops <= self.reliever_gold:
return 2
elif total_ops <= self.reliever_silver:
return 3
elif total_ops <= self.reliever_bronze:
return 4
else:
return 5 # Common
@dataclass
class BatterRarityThresholds:
"""OPS thresholds for batter rarity assignment."""
# Batter thresholds (OPS, higher is better)
hof: float # Hall of Fame (99)
diamond: float # Diamond (1)
gold: float # Gold (2)
silver: float # Silver (3)
bronze: float # Bronze (4)
def get_rarity(self, total_ops: float) -> int:
"""Returns rarity ID for a batter based on OPS."""
# For batters, higher OPS is better, so we check >= instead of <=
if total_ops >= self.hof:
return 99
elif total_ops >= self.diamond:
return 1
elif total_ops >= self.gold:
return 2
elif total_ops >= self.silver:
return 3
elif total_ops >= self.bronze:
return 4
else:
return 5 # Common
# 2024 Season Thresholds (Original values)
PITCHER_THRESHOLDS_2024 = PitcherRarityThresholds(
starter_hof=0.4,
starter_diamond=0.475,
starter_gold=0.53,
starter_silver=0.6,
starter_bronze=0.675,
reliever_hof=0.325,
reliever_diamond=0.4,
reliever_gold=0.475,
reliever_silver=0.55,
reliever_bronze=0.625,
)
BATTER_THRESHOLDS_2024 = BatterRarityThresholds(
hof=1.2,
diamond=1.0,
gold=0.9,
silver=0.8,
bronze=0.7,
)
# 2025 Season Thresholds (Adjusted based on data analysis)
PITCHER_THRESHOLDS_2025 = PitcherRarityThresholds(
starter_hof=0.300, # Top 5%
starter_diamond=0.354, # Top 15%
starter_gold=0.384, # Top 30%
starter_silver=0.441, # Top 50%
starter_bronze=0.487, # Top 70%
reliever_hof=0.270, # Top 5%
reliever_diamond=0.319, # Top 15%
reliever_gold=0.370, # Top 30%
reliever_silver=0.436, # Top 50%
reliever_bronze=0.503, # Top 70%
)
BATTER_THRESHOLDS_2025 = BatterRarityThresholds(
hof=1.2,
diamond=1.0,
gold=0.9,
silver=0.8,
bronze=0.7,
)
def get_pitcher_thresholds(season: int) -> PitcherRarityThresholds:
"""Get pitcher rarity thresholds for a specific season."""
if season >= 2025:
return PITCHER_THRESHOLDS_2025
else:
return PITCHER_THRESHOLDS_2024
def get_batter_thresholds(season: int) -> BatterRarityThresholds:
"""Get batter rarity thresholds for a specific season."""
if season >= 2025:
return BATTER_THRESHOLDS_2025
else:
return BATTER_THRESHOLDS_2024