mirror of
https://github.com/Steffo99/patched-porobot.git
synced 2024-12-22 17:44:22 +00:00
Restructure again!
This commit is contained in:
parent
26c02d9c2e
commit
824d2246de
33 changed files with 486 additions and 630 deletions
|
@ -16,7 +16,7 @@ itertools = { version = "0.10.3" } # Not using this yet
|
|||
# exec
|
||||
pretty_env_logger = { version = "0.4.0", optional = true }
|
||||
glob = { version = "0.3.0", optional = true }
|
||||
# schema
|
||||
# data
|
||||
serde = { version = "1.0.140", features = ["derive"] }
|
||||
serde_json = { version = "1.0.82" }
|
||||
# search
|
||||
|
@ -29,7 +29,7 @@ tokio = { version = "1.20.1", features = ["rt-multi-thread", "macros"], optiona
|
|||
# matrix
|
||||
|
||||
[features]
|
||||
# schema = [] # Always included
|
||||
# data = [] # Always included
|
||||
exec = ["pretty_env_logger", "glob"]
|
||||
search = ["tantivy"]
|
||||
telegram = ["search", "teloxide", "reqwest", "tokio"]
|
||||
|
@ -39,7 +39,3 @@ telegram = ["search", "teloxide", "reqwest", "tokio"]
|
|||
[lib]
|
||||
name = "patched_porobot"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "patched_porobot_telegram"
|
||||
path = "src/telegram/bin.rs"
|
||||
|
|
43
src/data/anybundle/metadata.rs
Normal file
43
src/data/anybundle/metadata.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
//! This module defines [BundleMetadata], the contents of `metadata.json`.
|
||||
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use crate::data::outcomes::{LoadingError, LoadingResult};
|
||||
|
||||
/// A parsed `metadata.json` file from a Data Dragon Bundle.
|
||||
///
|
||||
/// The specification defines more fields, but they are missing from the output files.
|
||||
///
|
||||
/// > ```json
|
||||
/// > {
|
||||
/// > "locales": ["{string}", ],
|
||||
/// > "clientHash": "{string}"
|
||||
/// > "gameplayDataHash": "{string}",
|
||||
/// > "timestamp": "{YYYYMMDDhhmm}",
|
||||
/// > "patchlineRef": "{string}"
|
||||
/// > }
|
||||
/// > ```
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct BundleMetadata {
|
||||
/// [Vec] of locales included in the bundle.
|
||||
///
|
||||
/// The specification defines that there can be multiple, but currently I've never seen more (or less) than one.
|
||||
pub locales: Vec<String>
|
||||
}
|
||||
|
||||
|
||||
impl BundleMetadata {
|
||||
/// Load a `metadata.json` file to create a [LocalizedGlobalsVecs] instance.
|
||||
pub fn load(path: &Path) -> LoadingResult<Self> {
|
||||
let file = File::open(path)
|
||||
.map_err(LoadingError::Loading)?;
|
||||
let data = serde_json::de::from_reader::<File, Self>(file)
|
||||
.map_err(LoadingError::Parsing)?;
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
/// Get a reference to the first (and probably only) locale defined in BundleMetadata.
|
||||
pub fn locale(&self) -> Option<&String> {
|
||||
self.locales.get(0)
|
||||
}
|
||||
}
|
3
src/data/anybundle/mod.rs
Normal file
3
src/data/anybundle/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
//! This module defines structs common to all Data Dragon Bundles.
|
||||
|
||||
pub mod metadata;
|
216
src/data/corebundle/globals.rs
Normal file
216
src/data/corebundle/globals.rs
Normal file
|
@ -0,0 +1,216 @@
|
|||
//! This module defines [LocalizedGlobalsVecs] and [LocalizedGlobalsIndexes], structs representing the data contained in the `globals.json` files.
|
||||
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use crate::data::outcomes::{LoadingError, LoadingResult};
|
||||
use super::vocabterm::{LocalizedVocabTermVec, LocalizedVocabTermIndex};
|
||||
use super::keyword::{LocalizedCardKeywordVec, LocalizedCardKeywordIndex};
|
||||
use super::region::{LocalizedCardRegionVec, LocalizedCardRegionIndex};
|
||||
use super::speed::{LocalizedSpellSpeedVec, LocalizedSpellSpeedIndex};
|
||||
use super::rarity::{LocalizedCardRarityVec, LocalizedCardRarityIndex};
|
||||
use super::set::{LocalizedCardSetVec, LocalizedCardSetIndex};
|
||||
|
||||
/// A parsed `globals.json` file from a Legends of Runeterra Core Bundle.
|
||||
///
|
||||
/// It contains a list of all vocabulary terms, keywords, regions, spell speeds, and rarities present in Legends of Runeterra.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct LocalizedGlobalsVecs {
|
||||
#[serde(rename = "vocabTerms")]
|
||||
pub vocab_terms: LocalizedVocabTermVec,
|
||||
|
||||
pub keywords: LocalizedCardKeywordVec,
|
||||
|
||||
pub regions: LocalizedCardRegionVec,
|
||||
|
||||
#[serde(rename = "spellSpeeds")]
|
||||
pub spell_speeds: LocalizedSpellSpeedVec,
|
||||
|
||||
pub rarities: LocalizedCardRarityVec,
|
||||
|
||||
pub sets: LocalizedCardSetVec,
|
||||
}
|
||||
|
||||
/// An instance of [LocalizedGlobalsVecs] which had its own fields indexed in [HashMap]s, using the respective identifiers as map keys.
|
||||
///
|
||||
/// It contains a indexed list of all vocabulary terms, keywords, regions, spell speeds, and rarities present in Legends of Runeterra.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct LocalizedGlobalsIndexes {
|
||||
pub vocab_terms: LocalizedVocabTermIndex,
|
||||
|
||||
pub keywords: LocalizedCardKeywordIndex,
|
||||
|
||||
pub regions: LocalizedCardRegionIndex,
|
||||
|
||||
pub spell_speeds: LocalizedSpellSpeedIndex,
|
||||
|
||||
pub rarities: LocalizedCardRarityIndex,
|
||||
|
||||
pub sets: LocalizedCardSetIndex,
|
||||
}
|
||||
|
||||
|
||||
impl LocalizedGlobalsVecs {
|
||||
/// Load a `globals.json` file to create a [LocalizedGlobalsVecs] instance.
|
||||
pub fn load(path: &Path) -> LoadingResult<Self> {
|
||||
let file = File::open(path)
|
||||
.map_err(LoadingError::Loading)?;
|
||||
let data = serde_json::de::from_reader::<File, Self>(file)
|
||||
.map_err(LoadingError::Parsing)?;
|
||||
Ok(data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<LocalizedGlobalsVecs> for LocalizedGlobalsIndexes {
|
||||
fn from(o: LocalizedGlobalsVecs) -> Self {
|
||||
Self {
|
||||
vocab_terms: {
|
||||
let mut hm = LocalizedVocabTermIndex::new();
|
||||
for obj in o.vocab_terms {
|
||||
hm.insert(obj.vocabterm.clone(), obj);
|
||||
}
|
||||
hm
|
||||
},
|
||||
keywords: {
|
||||
let mut hm = LocalizedCardKeywordIndex::new();
|
||||
for obj in o.keywords {
|
||||
hm.insert(obj.keyword, obj);
|
||||
}
|
||||
hm
|
||||
},
|
||||
regions: {
|
||||
let mut hm = LocalizedCardRegionIndex::new();
|
||||
for obj in o.regions {
|
||||
hm.insert(obj.region, obj);
|
||||
}
|
||||
hm
|
||||
},
|
||||
spell_speeds: {
|
||||
let mut hm = LocalizedSpellSpeedIndex::new();
|
||||
for obj in o.spell_speeds {
|
||||
hm.insert(obj.spell_speed, obj);
|
||||
}
|
||||
hm
|
||||
},
|
||||
rarities: {
|
||||
let mut hm = LocalizedCardRarityIndex::new();
|
||||
for obj in o.rarities {
|
||||
hm.insert(obj.rarity, obj);
|
||||
}
|
||||
hm
|
||||
},
|
||||
sets: {
|
||||
let mut hm = LocalizedCardSetIndex::new();
|
||||
for obj in o.sets {
|
||||
hm.insert(obj.set, obj);
|
||||
}
|
||||
hm
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::data::setbundle::keyword::CardKeyword;
|
||||
use crate::data::setbundle::rarity::CardRarity;
|
||||
use crate::data::setbundle::region::CardRegion;
|
||||
use crate::data::setbundle::set::CardSet;
|
||||
use crate::data::setbundle::speed::SpellSpeed;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
assert_eq!(
|
||||
serde_json::de::from_str::<'static, LocalizedGlobalsVecs>(r#"
|
||||
{
|
||||
"vocabTerms": [
|
||||
{
|
||||
"description": "When you summon this, it gets its allegiance bonus if the top card of your deck matches its region.",
|
||||
"name": "Allegiance",
|
||||
"nameRef": "Allegiance"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
{
|
||||
"description": "Inflicts damage beyond what would kill the target(s) to the enemy Nexus.",
|
||||
"name": "Overwhelm",
|
||||
"nameRef": "SpellOverwhelm"
|
||||
}
|
||||
],
|
||||
"regions": [
|
||||
{
|
||||
"abbreviation": "NX",
|
||||
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-noxus.png",
|
||||
"name": "Noxus",
|
||||
"nameRef": "Noxus"
|
||||
}
|
||||
],
|
||||
"spellSpeeds": [
|
||||
{
|
||||
"name": "Slow",
|
||||
"nameRef": "Slow"
|
||||
}
|
||||
],
|
||||
"rarities": [
|
||||
{
|
||||
"name": "COMMON",
|
||||
"nameRef": "Common"
|
||||
}
|
||||
],
|
||||
"sets": [
|
||||
{
|
||||
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set3_crispmip.png",
|
||||
"name": "Call of the Mountain",
|
||||
"nameRef": "Set3"
|
||||
}
|
||||
]
|
||||
}
|
||||
"#).unwrap(),
|
||||
LocalizedGlobalsVecs {
|
||||
vocab_terms: vec![
|
||||
vocabterm::LocalizedVocabTerm {
|
||||
vocabterm: "Allegiance".to_string(),
|
||||
name: "Allegiance".to_string(),
|
||||
description: "When you summon this, it gets its allegiance bonus if the top card of your deck matches its region.".to_string(),
|
||||
}
|
||||
],
|
||||
keywords: vec![
|
||||
keyword::LocalizedCardKeyword {
|
||||
keyword: CardKeyword::SpellOverwhelm,
|
||||
name: "Overwhelm".to_string(),
|
||||
description: "Inflicts damage beyond what would kill the target(s) to the enemy Nexus.".to_string(),
|
||||
}
|
||||
],
|
||||
regions: vec![
|
||||
region::LocalizedCardRegion {
|
||||
region: CardRegion::Noxus,
|
||||
name: "Noxus".to_string(),
|
||||
abbreviation: "NX".to_string(),
|
||||
icon_png: "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-noxus.png".to_string(),
|
||||
}
|
||||
],
|
||||
spell_speeds: vec![
|
||||
speed::LocalizedSpellSpeed {
|
||||
spell_speed: SpellSpeed::Slow,
|
||||
name: "Slow".to_string(),
|
||||
}
|
||||
],
|
||||
rarities: vec![
|
||||
rarity::LocalizedCardRarity {
|
||||
rarity: CardRarity::Common,
|
||||
name: "COMMON".to_string(),
|
||||
}
|
||||
],
|
||||
sets: vec![
|
||||
set::LocalizedCardSet {
|
||||
set: CardSet::CallOfTheMountain,
|
||||
name: "Call of the Mountain".to_string(),
|
||||
icon_png: "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set3_crispmip.png".to_string(),
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
//! This module defines [CoreKeyword].
|
||||
|
||||
use crate::schema::setbundle::CardKeyword;
|
||||
use std::collections::HashMap;
|
||||
use crate::data::setbundle::keyword::CardKeyword;
|
||||
|
||||
/// A Legends of Runeterra [CardKeyword], and its associated localization.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct CoreKeyword {
|
||||
pub struct LocalizedCardKeyword {
|
||||
/// The [CardKeyword] these strings refer to.
|
||||
#[serde(rename = "nameRef")]
|
||||
pub keyword: CardKeyword,
|
||||
|
@ -16,24 +17,27 @@ pub struct CoreKeyword {
|
|||
pub description: String,
|
||||
}
|
||||
|
||||
/// How [LocalizedCardKeyword]s appear in `global.json` files.
|
||||
pub type LocalizedCardKeywordVec = Vec<LocalizedCardKeyword>;
|
||||
/// An index of [LocalizedCardKeyword]s, with [LocalizedCardKeyword::keyword]s as keys.
|
||||
pub type LocalizedCardKeywordIndex = HashMap<CardKeyword, LocalizedCardKeyword>;
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::schema::setbundle::CardKeyword;
|
||||
|
||||
use super::CoreKeyword;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
assert_eq!(
|
||||
serde_json::de::from_str::<'static, CoreKeyword>(r#"
|
||||
serde_json::de::from_str::<'static, LocalizedCardKeyword>(r#"
|
||||
{
|
||||
"description": "Inflicts damage beyond what would kill the target(s) to the enemy Nexus.",
|
||||
"name": "Overwhelm",
|
||||
"nameRef": "SpellOverwhelm"
|
||||
}
|
||||
"#).unwrap(),
|
||||
CoreKeyword {
|
||||
LocalizedCardKeyword {
|
||||
keyword: CardKeyword::SpellOverwhelm,
|
||||
name: "Overwhelm".to_string(),
|
||||
description: "Inflicts damage beyond what would kill the target(s) to the enemy Nexus.".to_string(),
|
45
src/data/corebundle/mod.rs
Normal file
45
src/data/corebundle/mod.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
//! This module defines the types used in Data Dragon [Core Bundles](https://developer.riotgames.com/docs/lor#data-dragon_core-bundles).
|
||||
|
||||
use std::path::Path;
|
||||
use super::anybundle::metadata::BundleMetadata;
|
||||
use super::outcomes::{LoadingError, LoadingResult};
|
||||
|
||||
pub mod globals;
|
||||
pub mod vocabterm;
|
||||
pub mod keyword;
|
||||
pub mod region;
|
||||
pub mod speed;
|
||||
pub mod rarity;
|
||||
pub mod set;
|
||||
|
||||
|
||||
/// A parsed [Core Bundle](https://developer.riotgames.com/docs/lor#data-dragon_core-bundles).
|
||||
pub struct CoreBundle {
|
||||
/// The contents of the `metadata.json` file.
|
||||
pub metadata: BundleMetadata,
|
||||
|
||||
/// The contents of the `[locale]/data/globals-[locale].json` file.
|
||||
pub globals: globals::LocalizedGlobalsVecs,
|
||||
}
|
||||
|
||||
|
||||
impl CoreBundle {
|
||||
/// Load a Core Bundle directory to create a [CoreBundle] instance.
|
||||
pub fn load(bundle_path: &Path) -> LoadingResult<Self> {
|
||||
let metadata = BundleMetadata::load(
|
||||
&bundle_path
|
||||
.join("metadata.json")
|
||||
)?;
|
||||
|
||||
let locale = metadata.locale().ok_or(LoadingError::Using)?;
|
||||
|
||||
let globals = globals::LocalizedGlobalsVecs::load(
|
||||
&bundle_path
|
||||
.join(&locale)
|
||||
.join("data")
|
||||
.join(format!("globals-{}.json", &locale))
|
||||
)?;
|
||||
|
||||
Ok(CoreBundle {metadata, globals})
|
||||
}
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
//! This module defines [CoreRarity].
|
||||
|
||||
use crate::schema::setbundle::CardRarity;
|
||||
use std::collections::HashMap;
|
||||
use crate::data::setbundle::rarity::CardRarity;
|
||||
|
||||
/// A Legends of Runeterra [CardRarity], and its associated localization.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct CoreRarity {
|
||||
pub struct LocalizedCardRarity {
|
||||
/// The [CardRarity] these strings refer to.
|
||||
#[serde(rename = "nameRef")]
|
||||
pub rarity: CardRarity,
|
||||
|
@ -13,23 +14,26 @@ pub struct CoreRarity {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
/// How [LocalizedCardRarity]s appear in `global.json` files.
|
||||
pub type LocalizedCardRarityVec = Vec<LocalizedCardRarity>;
|
||||
/// An index of [LocalizedCardRarity]s, with [LocalizedCardRarity::rarity]s as keys.
|
||||
pub type LocalizedCardRarityIndex = HashMap<CardRarity, LocalizedCardRarity>;
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::schema::setbundle::CardRarity;
|
||||
|
||||
use super::CoreRarity;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
assert_eq!(
|
||||
serde_json::de::from_str::<'static, CoreRarity>(r#"
|
||||
serde_json::de::from_str::<'static, LocalizedCardRarity>(r#"
|
||||
{
|
||||
"name": "COMMON",
|
||||
"nameRef": "Common"
|
||||
}
|
||||
"#).unwrap(),
|
||||
CoreRarity {
|
||||
LocalizedCardRarity {
|
||||
rarity: CardRarity::Common,
|
||||
name: "COMMON".to_string(),
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
//! This module defines [CoreRegion].
|
||||
|
||||
use crate::schema::setbundle::CardRegion;
|
||||
use std::collections::HashMap;
|
||||
use crate::data::setbundle::region::CardRegion;
|
||||
|
||||
/// A Legends of Runeterra [CardRegion], and its associated localization.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct CoreRegion {
|
||||
pub struct LocalizedCardRegion {
|
||||
/// The [CardRegion] these strings refer to.
|
||||
#[serde(rename = "nameRef")]
|
||||
pub region: CardRegion,
|
||||
|
@ -22,17 +23,20 @@ pub struct CoreRegion {
|
|||
pub icon_png: String,
|
||||
}
|
||||
|
||||
/// How [LocalizedCardRegion]s appear in `global.json` files.
|
||||
pub type LocalizedCardRegionVec = Vec<LocalizedCardRegion>;
|
||||
/// An index of [LocalizedCardRegion]s, with [LocalizedCardRegion::region]s as keys.
|
||||
pub type LocalizedCardRegionIndex = HashMap<CardRegion, LocalizedCardRegion>;
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::schema::setbundle::CardRegion;
|
||||
|
||||
use super::CoreRegion;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
assert_eq!(
|
||||
serde_json::de::from_str::<'static, CoreRegion>(r#"
|
||||
serde_json::de::from_str::<'static, LocalizedCardRegion>(r#"
|
||||
{
|
||||
"abbreviation": "NX",
|
||||
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-noxus.png",
|
||||
|
@ -40,7 +44,7 @@ mod tests {
|
|||
"nameRef": "Noxus"
|
||||
}
|
||||
"#).unwrap(),
|
||||
CoreRegion {
|
||||
LocalizedCardRegion {
|
||||
region: CardRegion::Noxus,
|
||||
name: "Noxus".to_string(),
|
||||
abbreviation: "NX".to_string(),
|
|
@ -1,10 +1,11 @@
|
|||
//! This module defines [CoreSet].
|
||||
|
||||
use crate::schema::setbundle::CardSet;
|
||||
use std::collections::HashMap;
|
||||
use crate::data::setbundle::set::CardSet;
|
||||
|
||||
/// A Legends of Runeterra [CardSet], and its associated localization.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct CoreSet {
|
||||
pub struct LocalizedCardSet {
|
||||
/// The [CardSet] these strings refer to.
|
||||
#[serde(rename = "nameRef")]
|
||||
pub set: CardSet,
|
||||
|
@ -17,24 +18,27 @@ pub struct CoreSet {
|
|||
pub icon_png: String,
|
||||
}
|
||||
|
||||
/// How [LocalizedCardSet]s appear in `global.json` files.
|
||||
pub type LocalizedCardSetVec = Vec<LocalizedCardSet>;
|
||||
/// An index of [LocalizedCardSet]s, with [LocalizedCardSet::set]s as keys.
|
||||
pub type LocalizedCardSetIndex = HashMap<CardSet, LocalizedCardSet>;
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::schema::setbundle::CardSet;
|
||||
|
||||
use super::CoreSet;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
assert_eq!(
|
||||
serde_json::de::from_str::<'static, CoreSet>(r#"
|
||||
serde_json::de::from_str::<'static, LocalizedCardSet>(r#"
|
||||
{
|
||||
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set3_crispmip.png",
|
||||
"name": "Call of the Mountain",
|
||||
"nameRef": "Set3"
|
||||
}
|
||||
"#).unwrap(),
|
||||
CoreSet {
|
||||
LocalizedCardSet {
|
||||
set: CardSet::CallOfTheMountain,
|
||||
name: "Call of the Mountain".to_string(),
|
||||
icon_png: "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set3_crispmip.png".to_string(),
|
|
@ -1,10 +1,11 @@
|
|||
//! This module defines [CoreSpellSpeed].
|
||||
|
||||
use crate::schema::setbundle::SpellSpeed;
|
||||
use std::collections::HashMap;
|
||||
use crate::data::setbundle::speed::SpellSpeed;
|
||||
|
||||
/// A Legends of Runeterra [SpellSpeed], and its associated localization.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct CoreSpellSpeed {
|
||||
pub struct LocalizedSpellSpeed {
|
||||
/// The [SpellSpeed] these strings refer to.
|
||||
#[serde(rename = "nameRef")]
|
||||
pub spell_speed: SpellSpeed,
|
||||
|
@ -13,23 +14,26 @@ pub struct CoreSpellSpeed {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
/// How [LocalizedSpellSpeed]s appear in `global.json` files.
|
||||
pub type LocalizedSpellSpeedVec = Vec<LocalizedSpellSpeed>;
|
||||
/// An index of [LocalizedSpellSpeed]s, with [LocalizedSpellSpeed::spell_speed]s as keys.
|
||||
pub type LocalizedSpellSpeedIndex = HashMap<SpellSpeed, LocalizedSpellSpeed>;
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::schema::setbundle::SpellSpeed;
|
||||
|
||||
use super::CoreSpellSpeed;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
assert_eq!(
|
||||
serde_json::de::from_str::<'static, CoreSpellSpeed>(r#"
|
||||
serde_json::de::from_str::<'static, LocalizedSpellSpeed>(r#"
|
||||
{
|
||||
"name": "Slow",
|
||||
"nameRef": "Slow"
|
||||
}
|
||||
"#).unwrap(),
|
||||
CoreSpellSpeed {
|
||||
LocalizedSpellSpeed {
|
||||
spell_speed: SpellSpeed::Slow,
|
||||
name: "Slow".to_string(),
|
||||
}
|
|
@ -1,16 +1,14 @@
|
|||
//! This module defines [CoreVocabTerm].
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
|
||||
/// A Legends of Runeterra vocabulary term, and its associated localization.
|
||||
///
|
||||
/// I'm not sure where these are used, other than in in-game tooltips.
|
||||
///
|
||||
/// TODO: Find out where these are used.
|
||||
/// Vocabulary terms are used in [XML tags of card descriptions](crate::data::setbundle::card::Card::localized_description_xml) to provide tooltips about game mechanics.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct CoreVocabTerm {
|
||||
pub struct LocalizedVocabTerm {
|
||||
/// The internal name used by the vocabulary term.
|
||||
///
|
||||
/// TODO: Map these to an enum.
|
||||
#[serde(rename = "nameRef")]
|
||||
pub vocabterm: String,
|
||||
|
||||
|
@ -21,22 +19,27 @@ pub struct CoreVocabTerm {
|
|||
pub description: String,
|
||||
}
|
||||
|
||||
/// How [LocalizedVocabTerm]s appear in `global.json` files.
|
||||
pub type LocalizedVocabTermVec = Vec<LocalizedVocabTerm>;
|
||||
/// An index of [LocalizedVocabTerm]s, with [LocalizedVocabTerm::vocabterm]s as keys.
|
||||
pub type LocalizedVocabTermIndex = HashMap<String, LocalizedVocabTerm>;
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::CoreVocabTerm;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
assert_eq!(
|
||||
serde_json::de::from_str::<'static, CoreVocabTerm>(r#"
|
||||
serde_json::de::from_str::<'static, LocalizedVocabTerm>(r#"
|
||||
{
|
||||
"description": "When you summon this, it gets its allegiance bonus if the top card of your deck matches its region.",
|
||||
"name": "Allegiance",
|
||||
"nameRef": "Allegiance"
|
||||
}
|
||||
"#).unwrap(),
|
||||
CoreVocabTerm {
|
||||
LocalizedVocabTerm {
|
||||
vocabterm: "Allegiance".to_string(),
|
||||
name: "Allegiance".to_string(),
|
||||
description: "When you summon this, it gets its allegiance bonus if the top card of your deck matches its region.".to_string(),
|
|
@ -3,3 +3,4 @@
|
|||
pub mod corebundle;
|
||||
pub mod setbundle;
|
||||
pub mod anybundle;
|
||||
pub mod outcomes;
|
8
src/data/outcomes.rs
Normal file
8
src/data/outcomes.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
pub enum LoadingError {
|
||||
Checking,
|
||||
Loading(std::io::Error),
|
||||
Parsing(serde_json::Error),
|
||||
Using,
|
||||
}
|
||||
|
||||
pub type LoadingResult<T> = Result<T, LoadingError>;
|
|
@ -1,8 +1,13 @@
|
|||
//! Module defining [Card].
|
||||
|
||||
|
||||
use std::collections::HashMap;
|
||||
use super::*;
|
||||
use super::r#type::CardType;
|
||||
use super::art::CardArt;
|
||||
use super::keyword::CardKeyword;
|
||||
use super::rarity::CardRarity;
|
||||
use super::region::CardRegion;
|
||||
use super::speed::SpellSpeed;
|
||||
use super::set::CardSet;
|
||||
|
||||
/// A single Legends of Runeterra card as represented in a `set.json` file.
|
||||
///
|
||||
|
@ -141,7 +146,6 @@ pub struct Card {
|
|||
pub supertype: String,
|
||||
}
|
||||
|
||||
|
||||
impl Card {
|
||||
/// Get references to the cards associated with this one, given an [HashMap] of cards indexed by code.
|
||||
pub fn associated_cards<'c, 'hm: 'c>(&'c self, hashmap: &'hm HashMap<String, Card>) -> impl Iterator<Item=Option<&'hm Card>> + 'c {
|
|
@ -1,9 +1,6 @@
|
|||
//! Module defining [CardKeyword].
|
||||
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::schema::corebundle::CoreKeyword;
|
||||
use crate::data::corebundle::keyword::{LocalizedCardKeyword, LocalizedCardKeywordIndex};
|
||||
|
||||
/// A keyword which cards can have.
|
||||
///
|
||||
|
@ -337,12 +334,13 @@ pub enum CardKeyword {
|
|||
Unsupported,
|
||||
}
|
||||
|
||||
|
||||
impl CardKeyword {
|
||||
/// Get localized text about the keyword from [crate::schema::corebundle] data.
|
||||
/// Get the [LocalizedCardKeyword] associated with this [CardKeyword].
|
||||
///
|
||||
/// Returns `None` if no matching [CoreKeyword] was found, for example for [CardKeyword::Unsupported] keywords.
|
||||
pub fn localized<'hm>(&self, hm: &'hm HashMap<CardKeyword, CoreKeyword>) -> Option<&'hm CoreKeyword> {
|
||||
/// Returns [Option::None] if no matching [LocalizedCardKeyword] was found, for example for [CardKeyword::Unsupported] keywords.
|
||||
///
|
||||
/// Equivalent to calling [LocalizedCardKeywordIndex::get].
|
||||
pub fn localized<'hm>(&self, hm: &'hm LocalizedCardKeywordIndex) -> Option<&'hm LocalizedCardKeyword> {
|
||||
hm.get(&self)
|
||||
}
|
||||
}
|
53
src/data/setbundle/mod.rs
Normal file
53
src/data/setbundle/mod.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
//! This module defines the types used in Data Dragon [Set Bundles](https://developer.riotgames.com/docs/lor#data-dragon_set-bundles).
|
||||
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use super::anybundle::metadata::BundleMetadata;
|
||||
use super::outcomes::{LoadingError, LoadingResult};
|
||||
|
||||
pub mod card;
|
||||
pub mod art;
|
||||
pub mod r#type;
|
||||
pub mod rarity;
|
||||
pub mod region;
|
||||
pub mod set;
|
||||
pub mod speed;
|
||||
pub mod keyword;
|
||||
|
||||
|
||||
/// A parsed [Set Bundle](https://developer.riotgames.com/docs/lor#data-dragon_set-bundles).
|
||||
pub struct SetBundle {
|
||||
/// The contents of the `metadata.json` file.
|
||||
pub metadata: BundleMetadata,
|
||||
|
||||
/// The contents of the `[locale]/data/globals-[locale].json` file.
|
||||
pub cards: Vec<card::Card>,
|
||||
}
|
||||
|
||||
|
||||
impl SetBundle {
|
||||
/// Load a Set Bundle directory to create a [SetBundle] instance.
|
||||
pub fn load(bundle_path: &Path) -> LoadingResult<Self> {
|
||||
let metadata = BundleMetadata::load(
|
||||
&bundle_path
|
||||
.join("metadata.json")
|
||||
)?;
|
||||
|
||||
let locale = metadata.locale().ok_or(LoadingError::Using)?;
|
||||
|
||||
let mut filename = bundle_path.file_name().ok_or(LoadingError::Checking)?.to_os_string();
|
||||
filename.push(".json");
|
||||
|
||||
let cards = File::open(
|
||||
&bundle_path
|
||||
.join(&locale)
|
||||
.join("data")
|
||||
.join(filename)
|
||||
).map_err(LoadingError::Loading)?;
|
||||
|
||||
let cards = serde_json::de::from_reader::<File, Vec<card::Card>>(cards)
|
||||
.map_err(LoadingError::Parsing)?;
|
||||
|
||||
Ok(SetBundle {metadata, cards})
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
//! Module defining [CardRarity].
|
||||
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::schema::corebundle::CoreRarity;
|
||||
use crate::data::corebundle::rarity::{LocalizedCardRarity, LocalizedCardRarityIndex};
|
||||
|
||||
/// A possible [super::Card] rarity.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
|
@ -24,12 +21,13 @@ pub enum CardRarity {
|
|||
Champion,
|
||||
}
|
||||
|
||||
|
||||
impl CardRarity {
|
||||
/// Get localized text about the rarity from [crate::schema::corebundle] data.
|
||||
/// Get the [LocalizedCardRarity] associated with this [CardRarity].
|
||||
///
|
||||
/// Returns `None` if no matching [CoreRarity] was found, for example if the hashmap is incomplete.
|
||||
pub fn localized<'hm>(&self, hm: &'hm HashMap<CardRarity, CoreRarity>) -> Option<&'hm CoreRarity> {
|
||||
/// Returns [Option::None] if no matching [LocalizedCardRarity] was found, for example rarities missing from the index.
|
||||
///
|
||||
/// Equivalent to calling [LocalizedCardRarityIndex::get].
|
||||
pub fn localized<'hm>(&self, hm: &'hm LocalizedCardRarityIndex) -> Option<&'hm LocalizedCardRarity> {
|
||||
hm.get(&self)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
//! Module defining [CardRegion].
|
||||
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::schema::corebundle::CoreRegion;
|
||||
use crate::data::corebundle::region::{LocalizedCardRegion, LocalizedCardRegionIndex};
|
||||
|
||||
/// A region to which [super::Card]s can belong to.
|
||||
///
|
||||
|
@ -45,12 +42,13 @@ pub enum CardRegion {
|
|||
Unsupported,
|
||||
}
|
||||
|
||||
|
||||
impl CardRegion {
|
||||
/// Get localized text about the region from [crate::schema::corebundle] data.
|
||||
/// Get the [LocalizedCardRegion] associated with this [CardRegion].
|
||||
///
|
||||
/// Returns `None` if no matching [CoreRegion] was found, for example for [CardRegion::Unsupported] regions.
|
||||
pub fn localized<'hm>(&self, hm: &'hm HashMap<CardRegion, CoreRegion>) -> Option<&'hm CoreRegion> {
|
||||
/// Returns [Option::None] if no matching [LocalizedCardRegion] was found, for example for [CardRegion::Unsupported] regions.
|
||||
///
|
||||
/// Equivalent to calling [LocalizedCardRegionIndex::get].
|
||||
pub fn localized<'hm>(&self, hm: &'hm LocalizedCardRegionIndex) -> Option<&'hm LocalizedCardRegion> {
|
||||
hm.get(&self)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
//! Module defining [CardSet].
|
||||
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::schema::corebundle::CoreSet;
|
||||
use crate::data::corebundle::set::{LocalizedCardSet, LocalizedCardSetIndex};
|
||||
|
||||
/// The release set a [super::Card] may belong to.
|
||||
///
|
||||
|
@ -44,12 +41,13 @@ pub enum CardSet {
|
|||
Unsupported,
|
||||
}
|
||||
|
||||
|
||||
impl CardSet {
|
||||
/// Get localized text about the set from [crate::schema::corebundle] data.
|
||||
/// Get the [LocalizedCardSet] associated with this [CardSet].
|
||||
///
|
||||
/// Returns `None` if no matching [CoreSet] was found, for example for [CardSet::Unsupported] sets.
|
||||
pub fn localized<'hm>(&self, hm: &'hm HashMap<CardSet, CoreSet>) -> Option<&'hm CoreSet> {
|
||||
/// Returns [Option::None] if no matching [LocalizedCardSet] was found, for example for [CardSet::Unsupported] sets.
|
||||
///
|
||||
/// Equivalent to calling [LocalizedCardSetIndex::get].
|
||||
pub fn localized<'hm>(&self, hm: &'hm LocalizedCardSetIndex) -> Option<&'hm LocalizedCardSet> {
|
||||
hm.get(&self)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
//! Module defining [SpellSpeed].
|
||||
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::schema::corebundle::CoreSpellSpeed;
|
||||
use crate::data::corebundle::speed::{LocalizedSpellSpeed, LocalizedSpellSpeedIndex};
|
||||
|
||||
/// A possible spell speed.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
|
@ -19,12 +16,13 @@ pub enum SpellSpeed {
|
|||
Burst,
|
||||
}
|
||||
|
||||
|
||||
impl SpellSpeed {
|
||||
/// Get localized text about the speed from [crate::schema::corebundle] data.
|
||||
/// Get the [LocalizedSpellSpeed] associated with this [SpellSpeed].
|
||||
///
|
||||
/// Returns `None` if no matching [CoreSpellSpeed] was found, for example if the hashmap is incomplete.
|
||||
pub fn localized<'hm>(&self, hm: &'hm HashMap<SpellSpeed, CoreSpellSpeed>) -> Option<&'hm CoreSpellSpeed> {
|
||||
/// Returns [Option::None] if no matching [LocalizedSpellSpeed] was found, for example spell speeds missing from the index.
|
||||
///
|
||||
/// Equivalent to calling [LocalizedSpellSpeedIndex::get].
|
||||
pub fn localized<'hm>(&self, hm: &'hm LocalizedSpellSpeedIndex) -> Option<&'hm LocalizedSpellSpeed> {
|
||||
hm.get(&self)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
pub mod schema;
|
||||
pub mod load;
|
||||
pub mod data;
|
||||
|
||||
#[cfg(feature = "search")]
|
||||
pub mod search;
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
//! This module provides ways to load official data files from Riot Games' [Core Bundles](https://developer.riotgames.com/docs/lor#data-dragon_core-bundles) into Rust structs.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::Read;
|
||||
|
||||
use crate::schema::corebundle::*;
|
||||
use crate::schema::setbundle::*;
|
||||
|
||||
/// Deserialize a `globals.json` file into a [CoreGlobals] struct.
|
||||
pub fn globalsjson_to_coreglobals<R>(r: R) -> serde_json::Result<CoreGlobals>
|
||||
where R: Read
|
||||
{
|
||||
serde_json::de::from_reader::<R, CoreGlobals>(r)
|
||||
}
|
||||
|
||||
|
||||
/// Convert a [Vec] of [CoreVocabTerm]s into a [HashMap] of [CoreVocabTerm]s, indexed by their [CoreVocabTerm::vocabterm].
|
||||
pub fn vocabtermvec_to_vocabtermhashmap(v: Vec<CoreVocabTerm>) -> HashMap<String, CoreVocabTerm> {
|
||||
let mut hm = HashMap::<String, CoreVocabTerm>::new();
|
||||
for vocabterm in v {
|
||||
hm.insert(vocabterm.vocabterm.clone(), vocabterm);
|
||||
}
|
||||
hm
|
||||
}
|
||||
|
||||
|
||||
/// Convert a [Vec] of [CoreKeyword]s into a [HashMap] of [CoreKeyword]s, indexed by their [CoreKeyword::keyword].
|
||||
pub fn keywordvec_to_keywordhashmap(v: Vec<CoreKeyword>) -> HashMap<CardKeyword, CoreKeyword> {
|
||||
let mut hm = HashMap::<CardKeyword, CoreKeyword>::new();
|
||||
for keyword in v {
|
||||
hm.insert(keyword.keyword, keyword);
|
||||
}
|
||||
hm
|
||||
}
|
||||
|
||||
|
||||
/// Convert a [Vec] of [CoreRegion]s into a [HashMap] of [CoreRegion]s, indexed by their [CoreRegion::region].
|
||||
pub fn regionvec_to_regionhashmap(v: Vec<CoreRegion>) -> HashMap<CardRegion, CoreRegion> {
|
||||
let mut hm = HashMap::<CardRegion, CoreRegion>::new();
|
||||
for region in v {
|
||||
hm.insert(region.region, region);
|
||||
}
|
||||
hm
|
||||
}
|
||||
|
||||
|
||||
/// Convert a [Vec] of [CoreSpellSpeed]s into a [HashMap] of [CoreSpellSpeed]s, indexed by their [CoreSpellSpeed::spell_speed].
|
||||
pub fn spellspeedvec_to_spellspeedhashmap(v: Vec<CoreSpellSpeed>) -> HashMap<SpellSpeed, CoreSpellSpeed> {
|
||||
let mut hm = HashMap::<SpellSpeed, CoreSpellSpeed>::new();
|
||||
for spell_speed in v {
|
||||
hm.insert(spell_speed.spell_speed, spell_speed);
|
||||
}
|
||||
hm
|
||||
}
|
||||
|
||||
|
||||
/// Convert a [Vec] of [CoreRarity]s into a [HashMap] of [CoreRarity]s, indexed by their [CoreRarity::spell_speed].
|
||||
pub fn rarityvec_to_rarityhashmap(v: Vec<CoreRarity>) -> HashMap<CardRarity, CoreRarity> {
|
||||
let mut hm = HashMap::<CardRarity, CoreRarity>::new();
|
||||
for rarity in v {
|
||||
hm.insert(rarity.rarity, rarity);
|
||||
}
|
||||
hm
|
||||
}
|
||||
|
||||
|
||||
/// Convert a [Vec] of [CoreSet]s into a [HashMap] of [CoreSet]s, indexed by their [CoreSet::set].
|
||||
pub fn setvec_to_sethashmap(v: Vec<CoreSet>) -> HashMap<CardSet, CoreSet> {
|
||||
let mut hm = HashMap::<CardSet, CoreSet>::new();
|
||||
for set in v {
|
||||
hm.insert(set.set, set);
|
||||
}
|
||||
hm
|
||||
}
|
||||
|
||||
|
||||
/// A [CoreGlobals] struct where items are [HashMap]s mapping identifiers to the data they belong to.
|
||||
pub struct MappedGlobals {
|
||||
pub vocab_terms: HashMap<String, CoreVocabTerm>,
|
||||
pub keywords: HashMap<CardKeyword, CoreKeyword>,
|
||||
pub regions: HashMap<CardRegion, CoreRegion>,
|
||||
pub spell_speeds: HashMap<SpellSpeed, CoreSpellSpeed>,
|
||||
pub rarities: HashMap<CardRarity, CoreRarity>,
|
||||
pub sets: HashMap<CardSet, CoreSet>,
|
||||
}
|
||||
|
||||
|
||||
/// Trait allowing easy conversion from [CoreGlobals] to [MappedGlobals].
|
||||
impl From<CoreGlobals> for MappedGlobals {
|
||||
fn from(cg: CoreGlobals) -> Self {
|
||||
MappedGlobals {
|
||||
vocab_terms: vocabtermvec_to_vocabtermhashmap(cg.vocab_terms),
|
||||
keywords: keywordvec_to_keywordhashmap(cg.keywords),
|
||||
regions: regionvec_to_regionhashmap(cg.regions),
|
||||
spell_speeds: spellspeedvec_to_spellspeedhashmap(cg.spell_speeds),
|
||||
rarities: rarityvec_to_rarityhashmap(cg.rarities),
|
||||
sets: setvec_to_sethashmap(cg.sets),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
//! This module provides ways to load official data files from Riot Games' [Data Dragon](https://developer.riotgames.com/docs/lor#data-dragon) into Rust structs.
|
||||
|
||||
pub mod corebundle;
|
||||
pub mod setbundle;
|
|
@ -1,239 +0,0 @@
|
|||
//! This module provides ways to load official data files from Riot Games' [Set Bundles](https://developer.riotgames.com/docs/lor#data-dragon_set-bundles) into Rust structs.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::Read;
|
||||
|
||||
use crate::schema::setbundle::*;
|
||||
|
||||
/// Deserialize a `set.json` file into a [Vec] of [Card]s.
|
||||
pub fn setjson_to_cardvec<R>(r: R) -> serde_json::Result<Vec<Card>>
|
||||
where R: Read
|
||||
{
|
||||
serde_json::de::from_reader::<R, Vec<Card>>(r)
|
||||
}
|
||||
|
||||
|
||||
/// Convert a [Vec] of [Card]s (probably from [setjson_to_vec]) into a [HashMap] of [Card]s, indexed by their [Card::code].
|
||||
pub fn cardvec_to_cardhashmap(v: Vec<Card>) -> HashMap<String, Card> {
|
||||
let mut hm = HashMap::<String, Card>::new();
|
||||
for card in v {
|
||||
hm.insert(card.code.clone(), card);
|
||||
}
|
||||
hm
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(deprecated)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::schema::setbundle::*;
|
||||
|
||||
use super::cardvec_to_cardhashmap;
|
||||
use super::setjson_to_cardvec;
|
||||
|
||||
const TEST_SETJSON: &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,
|
||||
],
|
||||
localized_regions: 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,
|
||||
localized_spell_speed: "Burst".to_string(),
|
||||
keywords: vec![
|
||||
CardKeyword::Burst,
|
||||
],
|
||||
localized_keywords: vec![
|
||||
"Burst".to_string(),
|
||||
],
|
||||
localized_description_xml: "Give an ally +2|+0 or +0|+3 this round.".to_string(),
|
||||
localized_description_text: "Give an ally +2|+0 or +0|+3 this round.".to_string(),
|
||||
localized_levelup_xml: "".to_string(),
|
||||
localized_levelup_text: "".to_string(),
|
||||
associated_card_codes: vec![],
|
||||
associated_card_names_localized: vec![],
|
||||
localized_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,
|
||||
],
|
||||
localized_regions: 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,
|
||||
localized_spell_speed: "Burst".to_string(),
|
||||
keywords: vec![
|
||||
CardKeyword::Burst,
|
||||
],
|
||||
localized_keywords: vec![
|
||||
"Burst".to_string(),
|
||||
],
|
||||
localized_description_xml: "Give an ally +0|+3 this round.".to_string(),
|
||||
localized_description_text: "Give an ally +0|+3 this round.".to_string(),
|
||||
localized_levelup_xml: "".to_string(),
|
||||
localized_levelup_text: "".to_string(),
|
||||
associated_card_codes: vec![],
|
||||
associated_card_names_localized: vec![],
|
||||
localized_flavor_text: "".to_string(),
|
||||
artist_name: "SIXMOREVODKA".to_string(),
|
||||
subtypes: vec![],
|
||||
supertype: "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn expected_vec() -> Vec<Card> {
|
||||
vec![expected_card_1(), expected_card_2()]
|
||||
}
|
||||
|
||||
fn expected_hashmap() -> HashMap<String, Card> {
|
||||
let mut hm = HashMap::<String, Card>::new();
|
||||
hm.insert("01IO012".to_string(), expected_card_1());
|
||||
hm.insert("01IO012T2".to_string(), expected_card_2());
|
||||
hm
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_setjson_to_cardvec() {
|
||||
assert_eq!(
|
||||
setjson_to_cardvec(TEST_SETJSON.as_bytes()).unwrap(),
|
||||
expected_vec()
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cardvec_to_cardhashmap() {
|
||||
assert_eq!(
|
||||
cardvec_to_cardhashmap(expected_vec()),
|
||||
expected_hashmap()
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
use crate::schema::corebundle::CoreSet;
|
||||
|
||||
use super::keyword::CoreKeyword;
|
||||
use super::rarity::CoreRarity;
|
||||
use super::region::CoreRegion;
|
||||
use super::speed::CoreSpellSpeed;
|
||||
use super::vocabterm::CoreVocabTerm;
|
||||
|
||||
/// A complete `globals.json` file.
|
||||
///
|
||||
/// It contains a list of all vocabulary terms, [CardKeyword]s, [CardRegion]s, [SpellSpeed]s, and [CardRarity]s present in the game.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
pub struct CoreGlobals {
|
||||
/// A [Vec] of all [CoreVocabTerm]s in the game.
|
||||
#[serde(rename = "vocabTerms")]
|
||||
pub vocab_terms: Vec<CoreVocabTerm>,
|
||||
|
||||
/// A [Vec] of all [CoreKeyword]s in the game.
|
||||
pub keywords: Vec<CoreKeyword>,
|
||||
|
||||
/// A [Vec] of all [CoreRegion]s in the game.
|
||||
pub regions: Vec<CoreRegion>,
|
||||
|
||||
/// A [Vec] of all [CoreSpellSpeed]s in the game.
|
||||
#[serde(rename = "spellSpeeds")]
|
||||
pub spell_speeds: Vec<CoreSpellSpeed>,
|
||||
|
||||
/// A [Vec] of all [CoreRarity]s in the game.
|
||||
pub rarities: Vec<CoreRarity>,
|
||||
|
||||
/// A [Vec] of all [CardSet]s in the game.
|
||||
pub sets: Vec<CoreSet>,
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::schema::corebundle::*;
|
||||
use crate::schema::setbundle::*;
|
||||
|
||||
#[test]
|
||||
fn deserialize() {
|
||||
assert_eq!(
|
||||
serde_json::de::from_str::<'static, CoreGlobals>(r#"
|
||||
{
|
||||
"vocabTerms": [
|
||||
{
|
||||
"description": "When you summon this, it gets its allegiance bonus if the top card of your deck matches its region.",
|
||||
"name": "Allegiance",
|
||||
"nameRef": "Allegiance"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
{
|
||||
"description": "Inflicts damage beyond what would kill the target(s) to the enemy Nexus.",
|
||||
"name": "Overwhelm",
|
||||
"nameRef": "SpellOverwhelm"
|
||||
}
|
||||
],
|
||||
"regions": [
|
||||
{
|
||||
"abbreviation": "NX",
|
||||
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-noxus.png",
|
||||
"name": "Noxus",
|
||||
"nameRef": "Noxus"
|
||||
}
|
||||
],
|
||||
"spellSpeeds": [
|
||||
{
|
||||
"name": "Slow",
|
||||
"nameRef": "Slow"
|
||||
}
|
||||
],
|
||||
"rarities": [
|
||||
{
|
||||
"name": "COMMON",
|
||||
"nameRef": "Common"
|
||||
}
|
||||
],
|
||||
"sets": [
|
||||
{
|
||||
"iconAbsolutePath": "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set3_crispmip.png",
|
||||
"name": "Call of the Mountain",
|
||||
"nameRef": "Set3"
|
||||
}
|
||||
]
|
||||
}
|
||||
"#).unwrap(),
|
||||
CoreGlobals {
|
||||
vocab_terms: vec![
|
||||
CoreVocabTerm {
|
||||
vocabterm: "Allegiance".to_string(),
|
||||
name: "Allegiance".to_string(),
|
||||
description: "When you summon this, it gets its allegiance bonus if the top card of your deck matches its region.".to_string(),
|
||||
}
|
||||
],
|
||||
keywords: vec![
|
||||
CoreKeyword {
|
||||
keyword: CardKeyword::SpellOverwhelm,
|
||||
name: "Overwhelm".to_string(),
|
||||
description: "Inflicts damage beyond what would kill the target(s) to the enemy Nexus.".to_string(),
|
||||
}
|
||||
],
|
||||
regions: vec![
|
||||
CoreRegion {
|
||||
region: CardRegion::Noxus,
|
||||
name: "Noxus".to_string(),
|
||||
abbreviation: "NX".to_string(),
|
||||
icon_png: "http://dd.b.pvp.net/3_11_0/core/en_us/img/regions/icon-noxus.png".to_string(),
|
||||
}
|
||||
],
|
||||
spell_speeds: vec![
|
||||
CoreSpellSpeed {
|
||||
spell_speed: SpellSpeed::Slow,
|
||||
name: "Slow".to_string(),
|
||||
}
|
||||
],
|
||||
rarities: vec![
|
||||
CoreRarity {
|
||||
rarity: CardRarity::Common,
|
||||
name: "COMMON".to_string(),
|
||||
}
|
||||
],
|
||||
sets: vec![
|
||||
CoreSet {
|
||||
set: CardSet::CallOfTheMountain,
|
||||
name: "Call of the Mountain".to_string(),
|
||||
icon_png: "http://dd.b.pvp.net/3_11_0/core/en_us/img/sets/set3_crispmip.png".to_string(),
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
//! This module defines the types used in Data Dragon's [Core Bundle](https://developer.riotgames.com/docs/lor#data-dragon_core-bundles) `globals.json` files.
|
||||
|
||||
pub use globals::CoreGlobals;
|
||||
pub use keyword::CoreKeyword;
|
||||
pub use rarity::CoreRarity;
|
||||
pub use region::CoreRegion;
|
||||
pub use set::CoreSet;
|
||||
pub use speed::CoreSpellSpeed;
|
||||
pub use vocabterm::CoreVocabTerm;
|
||||
|
||||
mod globals;
|
||||
mod vocabterm;
|
||||
mod keyword;
|
||||
mod region;
|
||||
mod speed;
|
||||
mod rarity;
|
||||
mod set;
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
//! This module defines the types used in Data Dragon's [Set Bundle](https://developer.riotgames.com/docs/lor#data-dragon_set-bundles) `set.json` files.
|
||||
|
||||
pub use art::CardArt;
|
||||
pub use card::Card;
|
||||
pub use keyword::CardKeyword;
|
||||
pub use r#type::CardType;
|
||||
pub use rarity::CardRarity;
|
||||
pub use region::CardRegion;
|
||||
pub use set::CardSet;
|
||||
pub use speed::SpellSpeed;
|
||||
|
||||
mod card;
|
||||
mod art;
|
||||
mod r#type;
|
||||
mod rarity;
|
||||
mod region;
|
||||
mod set;
|
||||
mod speed;
|
||||
mod keyword;
|
||||
|
|
@ -6,8 +6,9 @@ use tantivy::query::{QueryParser, QueryParserError};
|
|||
use tantivy::schema::{Schema, TextOptions};
|
||||
use tantivy::tokenizer::TextAnalyzer;
|
||||
use itertools::Itertools;
|
||||
use crate::load::corebundle::MappedGlobals;
|
||||
use crate::schema::setbundle::{Card, CardType};
|
||||
use crate::data::corebundle::CoreBundle;
|
||||
use crate::data::setbundle::r#type::CardType;
|
||||
use crate::data::setbundle::card::Card;
|
||||
|
||||
|
||||
/// Create a new [tantivy::tokenizer::TextAnalyzer] for card text.
|
||||
|
@ -92,7 +93,7 @@ pub fn card_schema() -> Schema {
|
|||
|
||||
|
||||
/// Create a new [tantivy::Document] using a [Card] in a specific [locale](MappedGlobals] as base.
|
||||
pub fn card_to_document(schema: &Schema, locale: &MappedGlobals, card: Card) -> Document {
|
||||
pub fn card_to_document(schema: &Schema, cb: &CoreBundle, card: Card) -> Document {
|
||||
use tantivy::*;
|
||||
|
||||
let f_code = schema.get_field("code").expect("schema to have a 'code' field");
|
||||
|
@ -129,17 +130,17 @@ pub fn card_to_document(schema: &Schema, locale: &MappedGlobals, card: Card) ->
|
|||
f_name => card.name,
|
||||
f_type => c_type,
|
||||
f_set => card.set
|
||||
.localized(&locale.sets)
|
||||
.localized(&cb.globals.sets)
|
||||
.map(|cs| cs.name.to_owned())
|
||||
.unwrap_or_else(String::new),
|
||||
f_rarity => card.rarity
|
||||
.localized(&locale.rarities)
|
||||
.localized(&cb.globals.rarities)
|
||||
.map(|cr| cr.name.to_owned())
|
||||
.unwrap_or_else(String::new),
|
||||
f_collectible => if card.collectible {1u64} else {0u64},
|
||||
f_regions => card.regions.iter()
|
||||
.map(|region| region
|
||||
.localized(&locale.regions)
|
||||
.localized(&cb.globals.regions)
|
||||
.map(|cr| cr.name.to_owned())
|
||||
.unwrap_or_else(String::new)
|
||||
).join(" "),
|
||||
|
@ -147,12 +148,12 @@ pub fn card_to_document(schema: &Schema, locale: &MappedGlobals, card: Card) ->
|
|||
f_cost => card.cost,
|
||||
f_health => card.health,
|
||||
f_spellspeed => card.spell_speed
|
||||
.localized(&locale.spell_speeds)
|
||||
.localized(&cb.globals.spell_speeds)
|
||||
.map(|ss| ss.name.to_owned())
|
||||
.unwrap_or_else(String::new),
|
||||
f_keywords => card.keywords.iter()
|
||||
.map(|keyword| keyword
|
||||
.localized(&locale.keywords)
|
||||
.localized(&cb.globals.keywords)
|
||||
.map(|ck| ck.name.to_owned())
|
||||
.unwrap_or_else(String::new))
|
||||
.join(" "),
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
use log::*;
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
pretty_env_logger::init();
|
||||
}
|
|
@ -7,13 +7,10 @@
|
|||
use std::collections::HashMap;
|
||||
use itertools::Itertools;
|
||||
use teloxide::utils::html::escape;
|
||||
use crate::load::corebundle::MappedGlobals;
|
||||
use crate::schema::corebundle::{CoreRegion, CoreSet};
|
||||
use crate::schema::setbundle::{Card, CardRegion, CardSet, CardType};
|
||||
|
||||
|
||||
/// Render a [Card] to a [String] formatted with [Telegram Bot HTML](https://core.telegram.org/bots/api#html-style).
|
||||
pub fn display_card(card: &Card, mg: &MappedGlobals) -> String {
|
||||
pub fn display_card(card: &, mg: &MappedGlobals) -> String {
|
||||
let title = format!(r#"<a href="{}"><b><i>{}</b></i></a>"#, &card.main_art().card_png, escape(&card.name));
|
||||
|
||||
let stats = match &card.r#type {
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
pub(crate) mod display;
|
||||
mod bin;
|
||||
|
|
Loading…
Reference in a new issue