use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum Rarity { #[default] Bronze, Silver, Gold, RareGold, Totw, Hero, Icon, } impl Rarity { pub fn as_str(&self) -> &'static str { match self { Rarity::Bronze => "bronze", Rarity::Silver => "silver", Rarity::Gold => "gold", Rarity::RareGold => "raregold", Rarity::Totw => "totw", Rarity::Hero => "hero", Rarity::Icon => "icon", } } } /// Visual card quality tier (gold/silver/bronze). /// /// Game-independent semantic dimension, kept distinct from `Rarity` (which also /// carries special-card programs like TOTW/Hero/Icon). Derived from a card's base /// overall using FIFA 17's proven tier convention: gold >= 75, silver >= 65, /// otherwise bronze (evidence: `fifa17-recon/tools/fut_cards.py` `tier()`). #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum Quality { Bronze, Silver, Gold, } impl Quality { /// Classify a base overall rating into its quality tier. pub fn from_overall(overall: u8) -> Self { if overall >= 75 { Quality::Gold } else if overall >= 65 { Quality::Silver } else { Quality::Bronze } } } /// A card definition loaded from JSON data files. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CardDefinition { pub id: String, pub name: String, pub overall: u8, pub position: String, pub nation: String, pub league: String, pub club: String, pub pace: u8, pub shooting: u8, pub passing: u8, pub dribbling: u8, pub defending: u8, pub physical: u8, pub rarity: Rarity, pub image_path: Option, } /// A card instance owned by a club (stored in DB). #[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)] pub struct OwnedCard { pub id: String, pub club_id: String, pub card_id: String, pub is_loan: bool, pub loan_matches_remaining: Option, pub acquired_at: String, pub chemistry_style: String, pub position_override: Option, pub training_bonus: i64, }