From b1eac3fa00be45f064d067d5fdeaa40dae7a7318 Mon Sep 17 00:00:00 2001 From: kageru Date: Mon, 26 Jun 2023 14:27:53 +0200 Subject: [PATCH] =?UTF-8?q?always=20return=20false=20for=20fields=20that?= =?UTF-8?q?=20aren=E2=80=99t=20set?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This means a search for level<4 won’t return link monsters. Previously, a monster without level was considered to be level 0. --- src/data.rs | 37 +++++++++++++++++++++++++++++++++++++ src/filter.rs | 24 ++++++++++++++++++------ src/parser.rs | 7 +++++-- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/data.rs b/src/data.rs index 51b6237..b7571f8 100644 --- a/src/data.rs +++ b/src/data.rs @@ -193,6 +193,43 @@ pub mod tests { ] }"#; + pub const RAW_LINK_MONSTER: &str = r#" + { + "id": 49202162, + "name": "Black Luster Soldier - Soldier of Chaos", + "type": "Link Monster", + "frameType": "link", + "desc": "3 monsters with different names\r\nIf this card was Link Summoned using a Level 7 or higher monster(s) as material, your opponent cannot target it with card effects, also it cannot be destroyed by your opponent's card effects. When this card destroys an opponent's monster by battle: You can activate 1 of these effects;\r\n● This card gains 1500 ATK.\r\n● This card can make a second attack during the Battle Phase of your next turn.\r\n● Banish 1 card on the field.", + "atk": 3000, + "race": "Warrior", + "attribute": "EARTH", + "archetype": "Black Luster Soldier", + "linkval": 3, + "linkmarkers": [ + "Top", + "Bottom-Left", + "Bottom-Right" + ], + "card_sets": [ + { + "set_name": "OTS Tournament Pack 17", + "set_code": "OP17-EN003", + "set_rarity": "Ultimate Rare", + "set_rarity_code": "(UtR)", + "set_price": "75.77" + } + ], + "card_images": [ + { + "id": 49202162, + "image_url": "https://images.ygoprodeck.com/images/cards/49202162.jpg", + "image_url_small": "https://images.ygoprodeck.com/images/cards_small/49202162.jpg", + "image_url_cropped": "https://images.ygoprodeck.com/images/cards_cropped/49202162.jpg" + } + ] + } + "#; + #[test] fn test_spell() { let coffin: Card = serde_json::from_str(RAW_SPELL).unwrap(); diff --git a/src/filter.rs b/src/filter.rs index 877dae6..0771fe9 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -56,12 +56,12 @@ pub type CardFilter = Box bool>; fn get_field_value(card: &SearchCard, field: Field) -> Value { match field { - Field::Atk => Value::Numerical(card.atk.unwrap_or(0)), - Field::Def => Value::Numerical(card.def.unwrap_or(0)), + Field::Atk => card.atk.map(Value::Numerical).unwrap_or_default(), + Field::Def => card.def.map(Value::Numerical).unwrap_or_default(), Field::Legal => Value::Numerical(card.legal_copies), - Field::Level => Value::Numerical(card.level.unwrap_or(0)), - Field::LinkRating => Value::Numerical(card.link_rating.unwrap_or(0)), - Field::Year => Value::Numerical(card.original_year.unwrap_or(0)), + Field::Level => card.level.map(Value::Numerical).unwrap_or_default(), + Field::LinkRating => card.link_rating.map(Value::Numerical).unwrap_or_default(), + Field::Year => card.original_year.map(Value::Numerical).unwrap_or_default(), Field::Set => Value::Multiple(card.sets.clone().into_iter().map(Value::String).collect()), Field::Type => Value::String(card.r#type.clone()), Field::Attribute => Value::String(card.attribute.clone().unwrap_or_default()), @@ -73,10 +73,12 @@ fn get_field_value(card: &SearchCard, field: Field) -> Value { fn filter_value(op: &Operator, field_value: &Value, query_value: &Value) -> bool { match (field_value, query_value) { + (Value::None, _) => false, (Value::Numerical(field), Value::Numerical(query)) => op.filter_number(Some(*field), *query), (Value::String(field), Value::String(query)) => match op { Operator::Equal => field.contains(query), Operator::NotEqual => !field.contains(query), + // greater/less than aren’t supported for string fields. _ => false, }, // Currently only for sets the card was released in. @@ -105,7 +107,10 @@ pub fn build_filter(RawCardFilter(field, op, value): RawCardFilter) -> Result(RAW_LINK_MONSTER).unwrap()); + let filter = parse_filters("l<=4").unwrap().1; + assert!(!filter[0](&bls)); + } + #[test] fn set_filter_test() { let lacooda = SearchCard::from(&serde_json::from_str::(RAW_MONSTER).unwrap()); diff --git a/src/parser.rs b/src/parser.rs index 6a6a0ef..2ac3834 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -232,11 +232,13 @@ impl Display for RawCardFilter { } } -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug, PartialEq, Eq, Clone, Default)] pub enum Value { String(String), Numerical(i32), Multiple(Vec), + #[default] + None, } impl Display for Value { @@ -252,7 +254,8 @@ impl Display for Value { Self::Numerical(n) => write!(f, "{n}"), Self::Multiple(m) => { write!(f, "one of [{}]", m.iter().map(Value::to_string).join(", ")) - } + }, + Self::None => f.write_str("none"), } } }