boseiju/card/
legalities.rs

1/// For each format in [mtg_data::Format], the associated [mtg_data::Legality].
2#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
3pub struct Legalities {
4    pub alchemy: mtg_data::Legality,
5    pub brawl: mtg_data::Legality,
6    pub commander: mtg_data::Legality,
7    pub duel: mtg_data::Legality,
8    pub explorer: mtg_data::Legality,
9    pub future: mtg_data::Legality,
10    pub gladiator: mtg_data::Legality,
11    pub historic: mtg_data::Legality,
12    pub historicbrawl: mtg_data::Legality,
13    pub legacy: mtg_data::Legality,
14    pub modern: mtg_data::Legality,
15    pub oathbreaker: mtg_data::Legality,
16    pub pauper: mtg_data::Legality,
17    pub pauper_commander: mtg_data::Legality,
18    pub penny: mtg_data::Legality,
19    pub pionner: mtg_data::Legality,
20    pub predh: mtg_data::Legality,
21    pub premodern: mtg_data::Legality,
22    pub standard: mtg_data::Legality,
23    pub vintage: mtg_data::Legality,
24}
25
26impl Legalities {
27    pub fn display<W: std::io::Write>(&self, output: &mut W) -> std::io::Result<()> {
28        let lines: arrayvec::ArrayVec<_, 4> = mtg_data::Legality::all()
29            .map(|legality| {
30                let legals_in: arrayvec::ArrayVec<_, 20> = self.iter().filter(|(_, l)| *l == legality).map(|(f, _)| f).collect();
31                match legals_in.is_empty() {
32                    false => Some((legality, legals_in)),
33                    true => None,
34                }
35            })
36            .filter(Option::is_some)
37            .map(Option::unwrap)
38            .collect();
39        for (i, (legality, formats)) in lines.iter().enumerate() {
40            let tree_node = if i + 1 == lines.len() { '╰' } else { '├' };
41            write!(output, "│ {tree_node}─ {legality} in: ")?;
42            for (j, format) in formats.iter().enumerate() {
43                let end_str = if j + 1 == formats.len() { "\n" } else { ", " };
44                write!(output, "{format}{end_str}")?;
45            }
46        }
47        Ok(())
48    }
49
50    pub fn iter(&self) -> impl Iterator<Item = (mtg_data::Format, mtg_data::Legality)> {
51        [
52            (mtg_data::Format::Alchemy, self.alchemy),
53            (mtg_data::Format::Brawl, self.brawl),
54            (mtg_data::Format::Commander, self.commander),
55            (mtg_data::Format::Duel, self.duel),
56            (mtg_data::Format::Explorer, self.explorer),
57            (mtg_data::Format::Future, self.future),
58            (mtg_data::Format::Gladiator, self.gladiator),
59            (mtg_data::Format::Historic, self.historic),
60            (mtg_data::Format::HistoricBrawl, self.historicbrawl),
61            (mtg_data::Format::Legacy, self.legacy),
62            (mtg_data::Format::Modern, self.modern),
63            (mtg_data::Format::Oathbreaker, self.oathbreaker),
64            (mtg_data::Format::Pauper, self.pauper),
65            (mtg_data::Format::PauperCommander, self.pauper_commander),
66            (mtg_data::Format::Penny, self.penny),
67            (mtg_data::Format::Pionner, self.pionner),
68            (mtg_data::Format::Predh, self.predh),
69            (mtg_data::Format::Premodern, self.premodern),
70            (mtg_data::Format::Standard, self.standard),
71            (mtg_data::Format::Vintage, self.vintage),
72        ]
73        .into_iter()
74    }
75}
76
77impl TryFrom<&mtg_cardbase::Legalities> for Legalities {
78    type Error = String; // Fixme!
79    fn try_from(value: &mtg_cardbase::Legalities) -> Result<Self, Self::Error> {
80        use mtg_data::Legality;
81        use std::str::FromStr;
82        // Fixme: there are differences between the legailities got from the direct api and the one in the cards
83        Ok(Legalities {
84            alchemy: Legality::from_str(&value.alchemy).map_err(|e| format!("Failed to parse format alchemy: {e}"))?,
85            brawl: Legality::from_str(&value.brawl).map_err(|e| format!("Failed to parse format brawl: {e}"))?,
86            commander: Legality::from_str(&value.commander).map_err(|e| format!("Failed to parse format commander: {e}"))?,
87            duel: Legality::from_str(&value.duel).map_err(|e| format!("Failed to parse format duel: {e}"))?,
88            explorer: Legality::Notlegal,
89            future: Legality::from_str(&value.future).map_err(|e| format!("Failed to parse format future: {e}"))?,
90            gladiator: Legality::from_str(&value.gladiator).map_err(|e| format!("Failed to parse format gladiator: {e}"))?,
91            historic: Legality::from_str(&value.historic).map_err(|e| format!("Failed to parse format historic: {e}"))?,
92            historicbrawl: Legality::Notlegal,
93            legacy: Legality::from_str(&value.legacy).map_err(|e| format!("Failed to parse format legacy: {e}"))?,
94            modern: Legality::from_str(&value.modern).map_err(|e| format!("Failed to parse format modern: {e}"))?,
95            oathbreaker: Legality::from_str(&value.oathbreaker)
96                .map_err(|e| format!("Failed to parse format oathbreaker: {e}"))?,
97            pauper: Legality::from_str(&value.pauper).map_err(|e| format!("Failed to parse format pauper: {e}"))?,
98            pauper_commander: Legality::Notlegal,
99            penny: Legality::from_str(&value.penny).map_err(|e| format!("Failed to parse format penny: {e}"))?,
100            pionner: Legality::Notlegal,
101            predh: Legality::from_str(&value.predh).map_err(|e| format!("Failed to parse format predh: {e}"))?,
102            premodern: Legality::from_str(&value.premodern).map_err(|e| format!("Failed to parse format premodern: {e}"))?,
103            standard: Legality::from_str(&value.standard).map_err(|e| format!("Failed to parse format standard: {e}"))?,
104            vintage: Legality::from_str(&value.vintage).map_err(|e| format!("Failed to parse format vintage: {e}"))?,
105        })
106    }
107}