forge-foundation 0.3.1

Core Magic types for the manabrew engine: colors, mana, card types, zones, phases
Documentation
use std::collections::HashMap;

use serde::{Deserialize, Serialize};

use crate::sealed_product::foil_type::FoilType;
use crate::sealed_product::rarity::Rarity;
use crate::sealed_product::sealed_template::SealedTemplate;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub enum EditionType {
    Core,
    Expansion,
    Reprint,
    Online,
    Starter,
    Commander,
    Planechase,
    Archenemy,
    Promo,
    Token,
    Other,
    #[default]
    Unknown,
}

impl EditionType {
    pub fn parse(s: &str) -> Self {
        match s.trim().to_ascii_lowercase().as_str() {
            "core" => Self::Core,
            "expansion" => Self::Expansion,
            "reprint" | "masters" | "anthology" | "draft_innovation" => Self::Reprint,
            "online" | "digital" => Self::Online,
            "starter" => Self::Starter,
            "commander" => Self::Commander,
            "planechase" => Self::Planechase,
            "archenemy" => Self::Archenemy,
            "promo" => Self::Promo,
            "token" => Self::Token,
            _ if s.is_empty() => Self::Unknown,
            _ => Self::Other,
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EditionEntry {
    pub collector_number: String,
    pub rarity: Rarity,
    pub name: String,
    pub artist: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct CardEdition {
    pub code: String,
    pub code2: Option<String>,
    pub scryfall_code: Option<String>,
    pub name: String,
    pub date: Option<String>,
    pub edition_type: EditionType,

    pub foil_type: FoilType,
    pub foil_chance_in_booster: f64,
    pub foil_always_in_common_slot: bool,
    pub additional_sheet_for_foils: Option<String>,
    pub chance_replace_common_with: f64,
    pub slot_replace_common_with: Option<String>,
    pub booster_must_contain: Option<String>,
    pub booster_replace_slot_from_print_sheet: Option<String>,
    pub sheet_replace_card_from_sheet: Option<String>,
    pub sheet_replace_card_from_sheet2: Option<String>,

    pub alias: Option<String>,
    pub booster_covers: u32,
    pub booster_box_count: u32,
    pub fat_pack_count: u32,
    pub prerelease: Option<String>,
    pub additional_unlock_set: Option<String>,
    pub small_set_override: bool,

    pub booster: Option<String>,
    pub draft_booster: Option<String>,
    pub extra_boosters: HashMap<String, String>,
    pub custom_sheets: HashMap<String, Vec<String>>,

    pub cards: Vec<EditionEntry>,
}

impl CardEdition {
    pub fn to_sealed_template(&self) -> Option<SealedTemplate> {
        self.to_sealed_template_named(None)
    }

    pub fn to_sealed_template_named(&self, variant: Option<&str>) -> Option<SealedTemplate> {
        let primary = self.booster.as_ref().or(self.draft_booster.as_ref());
        let line = match variant {
            Some(v) if !v.is_empty() => self.extra_boosters.get(v).or(primary)?.as_str(),
            _ => primary?.as_str(),
        };
        let slots = crate::sealed_product::sealed_template::parse_slots(line);
        if slots.is_empty() {
            return None;
        }
        let label = match variant {
            Some(v) if !v.is_empty() => format!("{} {v}", self.code),
            _ => self.code.clone(),
        };
        let mut tpl = SealedTemplate::new(Some(label), slots);
        tpl.foil_type = self.foil_type;
        tpl.foil_chance = self.foil_chance_in_booster;
        tpl.foil_always_in_common_slot = self.foil_always_in_common_slot;
        tpl.additional_sheet_for_foils = self.additional_sheet_for_foils.clone();
        tpl.chance_replace_common_with = self.chance_replace_common_with;
        tpl.slot_replace_common_with = self.slot_replace_common_with.clone();
        tpl.booster_must_contain = self.booster_must_contain.clone();
        tpl.booster_replace_slot_from_print_sheet =
            self.booster_replace_slot_from_print_sheet.clone();
        tpl.sheet_replace_card_from_sheet = self.sheet_replace_card_from_sheet.clone();
        tpl.sheet_replace_card_from_sheet2 = self.sheet_replace_card_from_sheet2.clone();
        Some(tpl)
    }

    pub fn variant_names(&self) -> Vec<String> {
        let mut names: Vec<String> = self.extra_boosters.keys().cloned().collect();
        names.sort();
        names
    }
}