From f34c7f152ea3012acec9e3a0cc91686fbd24c15a Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Thu, 4 Aug 2022 10:16:30 +0200 Subject: [PATCH] Create the `load` module, plus various fixes detected in tests --- src/data/mod.rs | 2 - src/lib.rs | 1 + src/load/mod.rs | 237 +++++++++++++++++++++++++++++++++++++++++++ src/schema/card.rs | 8 +- src/schema/rarity.rs | 6 +- 5 files changed, 248 insertions(+), 6 deletions(-) delete mode 100644 src/data/mod.rs create mode 100644 src/load/mod.rs diff --git a/src/data/mod.rs b/src/data/mod.rs deleted file mode 100644 index 259a888..0000000 --- a/src/data/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -//! This module contains ways to download the latest and official data from Riot Games' [Data Dragon](https://developer.riotgames.com/docs/lor#data-dragon). - diff --git a/src/lib.rs b/src/lib.rs index 1ce7e17..2de4b23 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,2 @@ pub mod schema; +pub mod load; diff --git a/src/load/mod.rs b/src/load/mod.rs new file mode 100644 index 0000000..c7fadf4 --- /dev/null +++ b/src/load/mod.rs @@ -0,0 +1,237 @@ +//! This module offers ways to load official data files from Riot Games' [Data Dragon](https://developer.riotgames.com/docs/lor#data-dragon) into [Card] objects. +//! +//! Since [Card] implements both [serde::Serialize] and [serde::Deserialize], both operations can be performed manually; this module just provides shortcuts and useful utility functions. + + +use std::io::Read; +use std::collections::HashMap; +use crate::schema::Card; + + +/// Deserialize Data Dragon [Set Bundle](https://developer.riotgames.com/docs/lor#data-dragon_set-bundles) JSON data into a [Card] [Vec]. +pub fn vec_from_reader(r: R) -> serde_json::Result> + where R: Read +{ + serde_json::de::from_reader::>(r) +} + + +/// Deserialize Data Dragon [Set Bundle](https://developer.riotgames.com/docs/lor#data-dragon_set-bundles) JSON data into a [Card] [HashMap], with card codes as keys. +pub fn hashmap_from_reader(r: R) -> serde_json::Result> + where R: Read +{ + let vec = vec_from_reader(r)?; + let mut hm = HashMap::::new(); + for card in vec { + hm.insert(card.code.clone(), card); + } + Ok(hm) +} + + +#[cfg(test)] +#[allow(deprecated)] +mod tests { + use super::*; + use crate::schema::*; + + const TEST_DATA: &'static str = r#" + [ + { + "associatedCards": [], + "associatedCardRefs": [], + "assets": [ + { + "gameAbsolutePath": "http://dd.b.pvp.net/3_11_0/set1/en_us/img/cards/01IO012.png", + "fullAbsolutePath": "http://dd.b.pvp.net/3_11_0/set1/en_us/img/cards/01IO012-full.png" + } + ], + "regions": [ + "Ionia" + ], + "regionRefs": [ + "Ionia" + ], + "attack": 0, + "cost": 2, + "health": 0, + "description": "Give an ally +2|+0 or +0|+3 this round.", + "descriptionRaw": "Give an ally +2|+0 or +0|+3 this round.", + "levelupDescription": "", + "levelupDescriptionRaw": "", + "flavorText": "\"Never fear change. It will question you, test your limits. It is our greatest teacher.\" - Karma", + "artistName": "SIXMOREVODKA", + "name": "Twin Disciplines", + "cardCode": "01IO012", + "keywords": [ + "Burst" + ], + "keywordRefs": [ + "Burst" + ], + "spellSpeed": "Burst", + "spellSpeedRef": "Burst", + "rarity": "COMMON", + "rarityRef": "Common", + "subtypes": [], + "supertype": "", + "type": "Spell", + "collectible": true, + "set": "Set1" + }, + { + "associatedCards": [], + "associatedCardRefs": [], + "assets": [ + { + "gameAbsolutePath": "http://dd.b.pvp.net/3_11_0/set1/en_us/img/cards/01IO012T2.png", + "fullAbsolutePath": "http://dd.b.pvp.net/3_11_0/set1/en_us/img/cards/01IO012T2-full.png" + } + ], + "regions": [ + "Ionia" + ], + "regionRefs": [ + "Ionia" + ], + "attack": 0, + "cost": 2, + "health": 0, + "description": "Give an ally +0|+3 this round.", + "descriptionRaw": "Give an ally +0|+3 this round.", + "levelupDescription": "", + "levelupDescriptionRaw": "", + "flavorText": "", + "artistName": "SIXMOREVODKA", + "name": "Discipline of Fortitude", + "cardCode": "01IO012T2", + "keywords": [ + "Burst" + ], + "keywordRefs": [ + "Burst" + ], + "spellSpeed": "Burst", + "spellSpeedRef": "Burst", + "rarity": "None", + "rarityRef": "None", + "subtypes": [], + "supertype": "", + "type": "Spell", + "collectible": false, + "set": "Set1" + } + ] + "#; + + fn expected_card_1() -> Card { + Card { + code: "01IO012".to_string(), + name: "Twin Disciplines".to_string(), + r#type: CardType::Spell, + set: CardSet::Foundations, + rarity: CardRarity::Common, + collectible: true, + regions: vec![ + CardRegion::Ionia, + ], + regions_localized: vec![ + "Ionia".to_string(), + ], + art: vec![ + CardArt { + card_png: "http://dd.b.pvp.net/3_11_0/set1/en_us/img/cards/01IO012.png".to_string(), + full_png: "http://dd.b.pvp.net/3_11_0/set1/en_us/img/cards/01IO012-full.png".to_string(), + } + ], + attack: 0, + cost: 2, + health: 0, + spell_speed: SpellSpeed::Burst, + spell_speed_localized: "Burst".to_string(), + keywords: vec![ + CardKeyword::Burst, + ], + keywords_localized: vec![ + "Burst".to_string(), + ], + description: "Give an ally +2|+0 or +0|+3 this round.".to_string(), + description_raw: "Give an ally +2|+0 or +0|+3 this round.".to_string(), + levelup_description: "".to_string(), + levelup_description_raw: "".to_string(), + associated_card_codes: vec![], + associated_card_names_localized: vec![], + flavor_text: r#""Never fear change. It will question you, test your limits. It is our greatest teacher." - Karma"#.to_string(), + artist_name: "SIXMOREVODKA".to_string(), + subtypes: vec![], + supertype: "".to_string() + } + } + + fn expected_card_2() -> Card { + Card { + code: "01IO012T2".to_string(), + name: "Discipline of Fortitude".to_string(), + r#type: CardType::Spell, + set: CardSet::Foundations, + rarity: CardRarity::None, + collectible: false, + regions: vec![ + CardRegion::Ionia, + ], + regions_localized: vec![ + "Ionia".to_string(), + ], + art: vec![ + CardArt { + card_png: "http://dd.b.pvp.net/3_11_0/set1/en_us/img/cards/01IO012T2.png".to_string(), + full_png: "http://dd.b.pvp.net/3_11_0/set1/en_us/img/cards/01IO012T2-full.png".to_string() + } + ], + attack: 0, + cost: 2, + health: 0, + spell_speed: SpellSpeed::Burst, + spell_speed_localized: "Burst".to_string(), + keywords: vec![ + CardKeyword::Burst, + ], + keywords_localized: vec![ + "Burst".to_string(), + ], + description: "Give an ally +0|+3 this round.".to_string(), + description_raw: "Give an ally +0|+3 this round.".to_string(), + levelup_description: "".to_string(), + levelup_description_raw: "".to_string(), + associated_card_codes: vec![], + associated_card_names_localized: vec![], + flavor_text: "".to_string(), + artist_name: "SIXMOREVODKA".to_string(), + subtypes: vec![], + supertype: "".to_string() + } + } + + fn expected_hashmap() -> HashMap { + let mut hm = HashMap::::new(); + hm.insert("01IO012".to_string(), expected_card_1()); + hm.insert("01IO012T2".to_string(), expected_card_2()); + hm + } + + #[test] + fn test_vec_from_reader() { + assert_eq!( + vec_from_reader(TEST_DATA.as_bytes()).unwrap(), + vec![expected_card_1(), expected_card_2()] + ) + } + + #[test] + fn test_hashmap_from_reader() { + assert_eq!( + hashmap_from_reader(TEST_DATA.as_bytes()).unwrap(), + expected_hashmap() + ) + } +} \ No newline at end of file diff --git a/src/schema/card.rs b/src/schema/card.rs index 8db0eea..211e014 100644 --- a/src/schema/card.rs +++ b/src/schema/card.rs @@ -58,12 +58,18 @@ pub struct Card { pub art: Vec, /// Base attack of the card. + /// + /// Cards with no attack, such as [CardType::Spell]s, have a value of `0` attack. pub attack: u64, - /// Base cost of the card. + /// Base mana cost of the card. + /// + /// Cards with no health, such as [CardType::Ability]s, have a value of `0` cost. pub cost: u64, /// Base health of the card. + /// + /// Cards with no health, such as [CardType::Spell]s, have a value of `0` health. pub health: u64, /// [SpellSpeed] of the card. diff --git a/src/schema/rarity.rs b/src/schema/rarity.rs index 30c88c2..ef5560f 100644 --- a/src/schema/rarity.rs +++ b/src/schema/rarity.rs @@ -8,13 +8,13 @@ pub enum CardRarity { #[serde(alias = "NONE")] None, /// A common card. - #[serde(rename = "COMMON")] + #[serde(alias = "COMMON")] Common, /// A rare card. - #[serde(rename = "RARE")] + #[serde(alias = "RARE")] Rare, /// An epic card. - #[serde(rename = "EPIC")] + #[serde(alias = "EPIC")] Epic, /// A champion. #[serde(alias = "CHAMPION")]