1
Fork 0
mirror of https://github.com/Steffo99/patched-porobot.git synced 2024-12-22 09:34:21 +00:00

Perfect data module

This commit is contained in:
Steffo 2022-08-06 19:44:44 +02:00
parent 05a8a5c4a3
commit 0bd71f35d4
Signed by: steffo
GPG key ID: 6965406171929D01
31 changed files with 303 additions and 138 deletions

View file

@ -0,0 +1,3 @@
<component name="ProjectDictionaryState">
<dictionary name="steffo" />
</component>

View file

@ -3,8 +3,8 @@
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/data" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/card-data" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />

View file

@ -32,9 +32,9 @@ tokio = { version = "1.20.1", features = ["rt-multi-thread", "macros"], optiona
# data = [] # Always included
exec = ["pretty_env_logger", "glob"]
search = ["tantivy"]
telegram = ["search", "teloxide", "reqwest", "tokio"]
# discord = ["search"]
# matrix = ["search"]
telegram = ["exec", "search", "teloxide", "reqwest", "tokio"]
# discord = ["exec", "search"]
# matrix = ["exec", "search"]
[lib]
name = "patched_porobot"

View file

@ -1,6 +1,10 @@
# ![](icon.jpg) patched-porobot
WIP: Legends of Runeterra card bot
## Legal
patched-porobot isn't endorsed by Riot Games and doesn't reflect the views or opinions of Riot Games or anyone officially involved in producing or managing Riot Games properties. Riot Games, and all associated properties are trademarks or registered trademarks of Riot Games, Inc.
## Discord Emoji Codes

View file

@ -1,12 +1,14 @@
//! This module defines [BundleMetadata], the contents of `metadata.json`.
//! Module defining [BundleMetadata], the contents of the `metadata.json` present in all [Data Dragon] Bundles.
//!
//! [Data Dragon]: https://developer.riotgames.com/docs/lor#data-dragon
use std::fs::File;
use std::path::Path;
use crate::data::outcomes::{LoadingError, LoadingResult};
use crate::data::anybundle::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.
/// The specification defines more fields, but they are missing from the output files:
///
/// > ```json
/// > {
@ -27,17 +29,41 @@ pub struct BundleMetadata {
impl BundleMetadata {
/// Load a `metadata.json` file to create a [LocalizedGlobalsVecs] instance.
/// Load a `metadata.json` file to create a [BundleMetadata] instance.
pub fn load(path: &Path) -> LoadingResult<Self> {
let file = File::open(path)
.map_err(LoadingError::Loading)?;
.map_err(LoadingError::OpeningFile)?;
let data = serde_json::de::from_reader::<File, Self>(file)
.map_err(LoadingError::Parsing)?;
.map_err(LoadingError::Deserializing)?;
Ok(data)
}
/// Get a reference to the first (and probably only) locale defined in BundleMetadata.
///
/// Equivalent to calling [BundleMetadata].[locales](BundleMetadata::locales).[get(0)]([T]::get).
pub fn locale(&self) -> Option<&String> {
self.locales.get(0)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserialize() {
assert_eq!(
serde_json::de::from_str::<'static, BundleMetadata>(r#"
{
"locales": [
"en_us"
]
}
"#).unwrap(),
BundleMetadata {
locales: vec!["en_us".to_string()]
}
);
}
}

View file

@ -1,3 +1,6 @@
//! This module defines structs common to all Data Dragon Bundles.
//! Definitions of structs common to all [Data Dragon] Bundles.
//!
//! [Data Dragon]: https://developer.riotgames.com/docs/lor#data-dragon
pub mod metadata;
pub mod outcomes;

View file

@ -0,0 +1,22 @@
//! Module defining [Result] and [Result::Err] variants for actions related to [Data Dragon] Bundles.
//!
//! [Data Dragon]: https://developer.riotgames.com/docs/lor#data-dragon
/// An error that occoured while loading a Data Dragon Bundle.
#[derive(Debug)]
pub enum LoadingError {
/// Could not get the locale from the `metadata.json` file.
GettingLocale,
/// Could not get the bundle name from the operating system.
GettingBundleName,
/// Could not convert the bundle name from a [OsString](std::ffi::OsString) to a [String].
ConvertingBundleName,
/// Could not use [File::open](std::fs::File::open) on a data file.
OpeningFile(std::io::Error),
/// Could not deserialize a data file.
Deserializing(serde_json::Error),
}
/// The result of the loading of a Legends of Runeterra bundle.
pub type LoadingResult<T> = Result<T, LoadingError>;

View file

@ -1,8 +1,8 @@
//! This module defines [LocalizedGlobalsVecs] and [LocalizedGlobalsIndexes], structs representing the data contained in the `globals.json` files.
//! Module defining structs representing data contained in `globals.json` files.
use std::fs::File;
use std::path::Path;
use crate::data::outcomes::{LoadingError, LoadingResult};
use crate::data::anybundle::outcomes::{LoadingError, LoadingResult};
use super::vocabterm::{LocalizedVocabTermVec, LocalizedVocabTermIndex};
use super::keyword::{LocalizedCardKeywordVec, LocalizedCardKeywordIndex};
use super::region::{LocalizedCardRegionVec, LocalizedCardRegionIndex};
@ -10,41 +10,61 @@ 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.
/// A parsed `globals.json` file from a [Data Dragon] [Core Bundle].
///
/// It contains a list of all vocabulary terms, keywords, regions, spell speeds, and rarities present in Legends of Runeterra.
/// It contains [Vec]s of all vocabulary terms, keywords, regions, spell speeds, and rarities present in the game.
///
/// [Data Dragon]: https://developer.riotgames.com/docs/lor#data-dragon
/// [Core Bundle]: https://developer.riotgames.com/docs/lor#data-dragon_core-bundles
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct LocalizedGlobalsVecs {
/// Vocabulary terms.
#[serde(rename = "vocabTerms")]
pub vocab_terms: LocalizedVocabTermVec,
/// Card keywords.
pub keywords: LocalizedCardKeywordVec,
/// Card regions.
pub regions: LocalizedCardRegionVec,
/// Spell speeds.
#[serde(rename = "spellSpeeds")]
pub spell_speeds: LocalizedSpellSpeedVec,
/// Card rarities.
pub rarities: LocalizedCardRarityVec,
/// Card sets.
pub sets: LocalizedCardSetVec,
}
/// An instance of [LocalizedGlobalsVecs] which had its own fields indexed in [HashMap]s, using the respective identifiers as map keys.
/// A parsed and indexed `globals.json` file from a [Data Dragon] [Core Bundle].
///
/// It contains a indexed list of all vocabulary terms, keywords, regions, spell speeds, and rarities present in Legends of Runeterra.
/// It is an instance of [LocalizedGlobalsVecs] which had its own fields indexed in [std::collections::HashMap]s, using the respective identifiers as map keys.
///
/// It contains indexes of all vocabulary terms, keywords, regions, spell speeds, and rarities present in the game.
///
/// [Data Dragon]: https://developer.riotgames.com/docs/lor#data-dragon
/// [Core Bundle]: https://developer.riotgames.com/docs/lor#data-dragon_core-bundles
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LocalizedGlobalsIndexes {
/// Vocabulary terms.
pub vocab_terms: LocalizedVocabTermIndex,
/// Card keywords.
pub keywords: LocalizedCardKeywordIndex,
/// Card regions.
pub regions: LocalizedCardRegionIndex,
/// Spell speeds.
pub spell_speeds: LocalizedSpellSpeedIndex,
/// Card rarities.
pub rarities: LocalizedCardRarityIndex,
/// Card sets.
pub sets: LocalizedCardSetIndex,
}
@ -53,9 +73,9 @@ 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)?;
.map_err(LoadingError::OpeningFile)?;
let data = serde_json::de::from_reader::<File, Self>(file)
.map_err(LoadingError::Parsing)?;
.map_err(LoadingError::Deserializing)?;
Ok(data)
}
}
@ -113,7 +133,13 @@ impl From<LocalizedGlobalsVecs> for LocalizedGlobalsIndexes {
#[cfg(test)]
mod tests {
use super::*;
use super::LocalizedGlobalsVecs;
use crate::data::corebundle::keyword::LocalizedCardKeyword;
use crate::data::corebundle::rarity::LocalizedCardRarity;
use crate::data::corebundle::region::LocalizedCardRegion;
use crate::data::corebundle::set::LocalizedCardSet;
use crate::data::corebundle::speed::LocalizedSpellSpeed;
use crate::data::corebundle::vocabterm::LocalizedVocabTerm;
use crate::data::setbundle::keyword::CardKeyword;
use crate::data::setbundle::rarity::CardRarity;
use crate::data::setbundle::region::CardRegion;
@ -170,21 +196,21 @@ mod tests {
"#).unwrap(),
LocalizedGlobalsVecs {
vocab_terms: vec![
vocabterm::LocalizedVocabTerm {
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 {
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 {
LocalizedCardRegion {
region: CardRegion::Noxus,
name: "Noxus".to_string(),
abbreviation: "NX".to_string(),
@ -192,19 +218,19 @@ mod tests {
}
],
spell_speeds: vec![
speed::LocalizedSpellSpeed {
LocalizedSpellSpeed {
spell_speed: SpellSpeed::Slow,
name: "Slow".to_string(),
}
],
rarities: vec![
rarity::LocalizedCardRarity {
LocalizedCardRarity {
rarity: CardRarity::Common,
name: "COMMON".to_string(),
}
],
sets: vec![
set::LocalizedCardSet {
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(),

View file

@ -1,4 +1,4 @@
//! This module defines [CoreKeyword].
//! Module defining structs representing localized card keywords.
use std::collections::HashMap;
use crate::data::setbundle::keyword::CardKeyword;

View file

@ -1,8 +1,11 @@
//! This module defines the types used in Data Dragon [Core Bundles](https://developer.riotgames.com/docs/lor#data-dragon_core-bundles).
//! Module defining the types used in [Data Dragon] [Core Bundle]s.
//!
//! [Data Dragon]: https://developer.riotgames.com/docs/lor#data-dragon
//! [Core Bundle]: https://developer.riotgames.com/docs/lor#data-dragon_core-bundles
use std::path::Path;
use super::anybundle::metadata::BundleMetadata;
use super::outcomes::{LoadingError, LoadingResult};
use crate::data::anybundle::outcomes::{LoadingError, LoadingResult};
pub mod globals;
pub mod vocabterm;
@ -13,8 +16,15 @@ pub mod rarity;
pub mod set;
/// A parsed [Core Bundle](https://developer.riotgames.com/docs/lor#data-dragon_core-bundles).
/// A parsed [Data Dragon] [Core Bundle].
///
/// [Data Dragon]: https://developer.riotgames.com/docs/lor#data-dragon
/// [Core Bundle]: https://developer.riotgames.com/docs/lor#data-dragon_core-bundles
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct CoreBundle {
/// The name of the root directory of the bundle.
pub name: String,
/// The contents of the `metadata.json` file.
pub metadata: BundleMetadata,
@ -31,15 +41,22 @@ impl CoreBundle {
.join("metadata.json")
)?;
let locale = metadata.locale().ok_or(LoadingError::Using)?;
let name = bundle_path.file_name()
.ok_or(LoadingError::GettingBundleName)?
.to_str()
.ok_or(LoadingError::ConvertingBundleName)?
.to_string();
let globals = globals::LocalizedGlobalsVecs::load(
&bundle_path
.join(&locale)
.join("data")
.join(format!("globals-{}.json", &locale))
)?;
let locale = metadata.locale()
.ok_or(LoadingError::GettingLocale)?;
Ok(CoreBundle {metadata, globals})
let globals_path = &bundle_path
.join(&locale)
.join("data")
.join(format!("globals-{}.json", &locale));
let globals = globals::LocalizedGlobalsVecs::load(globals_path)?;
Ok(CoreBundle {name, metadata, globals})
}
}

View file

@ -1,4 +1,4 @@
//! This module defines [CoreRarity].
//! Module defining structs representing localized card rarities.
use std::collections::HashMap;
use crate::data::setbundle::rarity::CardRarity;

View file

@ -1,4 +1,4 @@
//! This module defines [CoreRegion].
//! Module defining structs representing localized card regions.
use std::collections::HashMap;
use crate::data::setbundle::region::CardRegion;

View file

@ -1,4 +1,4 @@
//! This module defines [CoreSet].
//! Module defining structs representing localized card sets.
use std::collections::HashMap;
use crate::data::setbundle::set::CardSet;

View file

@ -1,4 +1,4 @@
//! This module defines [CoreSpellSpeed].
//! Module defining structs representing localized spell speeds.
use std::collections::HashMap;
use crate::data::setbundle::speed::SpellSpeed;

View file

@ -1,4 +1,4 @@
//! This module defines [CoreVocabTerm].
//! Module defining structs representing localized vocabulary terms.
use std::collections::HashMap;
use std::hash::Hash;

View file

@ -1,6 +1,7 @@
//! This module contains the [corebundle] and [setbundle] submodules.
//! Module containing Rust models for [Data Dragon] bundles.
//!
//! [Data Dragon]: https://developer.riotgames.com/docs/lor#data-dragon
pub mod corebundle;
pub mod setbundle;
pub mod anybundle;
pub mod outcomes;

View file

@ -1,8 +0,0 @@
pub enum LoadingError {
Checking,
Loading(std::io::Error),
Parsing(serde_json::Error),
Using,
}
pub type LoadingResult<T> = Result<T, LoadingError>;

View file

@ -1,23 +1,27 @@
//! Module defining [CardArt].
/// An art asset associated with a [super::Card].
/// The illustration of a [Card](super::card::Card), also referred to as an *art asset*.
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct CardArt {
/// URL to the `.png` image of the rendered card.
///
/// # Example
/// ## Example
///
/// `https://dd.b.pvp.net/latest/set1/en_us/img/cards/01DE001.png`
/// ```text
/// https://dd.b.pvp.net/latest/set1/en_us/img/cards/01DE001.png
/// ```
///
#[serde(rename = "gameAbsolutePath")]
pub card_png: String,
/// URL to the `.png` image of the full card art.
///
/// # Example
/// ## Example
///
/// `https://dd.b.pvp.net/latest/set1/en_us/img/cards/01DE001-full.png`
/// ```text
/// https://dd.b.pvp.net/latest/set1/en_us/img/cards/01DE001-full.png
/// ```
///
#[serde(rename = "fullAbsolutePath")]
pub full_png: String,
@ -31,7 +35,9 @@ impl CardArt {
///
/// # Example
///
/// `https://poro.steffo.eu/set1-en_us/en_us/img/cards/01DE001.jpg`
/// ```text
/// https://poro.steffo.eu/set1-en_us/en_us/img/cards/01DE001.jpg
/// ```
///
pub fn card_jpg(&self) -> String {
self.card_png
@ -45,7 +51,9 @@ impl CardArt {
///
/// # Example
///
/// `https://poro.steffo.eu/set1-en_us/en_us/img/cards/01DE001-full.jpg`
/// ```text
/// https://poro.steffo.eu/set1-en_us/en_us/img/cards/01DE001-full.jpg
/// ```
///
pub fn full_jpg(&self) -> String {
self.full_png

View file

@ -1,6 +1,8 @@
//! Module defining [Card].
use std::collections::HashMap;
use crate::data::setbundle::subtype::CardSubtype;
use crate::data::setbundle::supertype::CardSupertype;
use super::r#type::CardType;
use super::art::CardArt;
use super::keyword::CardKeyword;
@ -9,9 +11,9 @@ 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.
/// A single Legends of Runeterra card, as represented in a `set*.json` file.
///
/// The information is represented in a developer-friendly manner, but it can be serialized and deserialized via [serde] in the exact same format used in Data Dragon.
/// The data is available in a developer-friendly interface, but nevertheless it can be serialized and deserialized via [serde] in the exact same format used in the `set*.json` files.
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct Card {
/// Unique seven-character identifier of the card.
@ -21,21 +23,23 @@ pub struct Card {
/// Localized name of the card.
pub name: String,
/// The [CardType] of the card.
/// The type of the card.
///
/// The `r#` prefix is required by the Rust syntax, since `type` is a reserved keyword.
/// Since `type` in Rust is a reserved keyword, accessing this field requires [prefixing it with `r#`](https://doc.rust-lang.org/rust-by-example/compatibility/raw_identifiers.html).
#[serde(rename = "type")]
pub r#type: CardType,
/// The [CardSet] the card belongs to.
/// The release set the card belongs to.
pub set: CardSet,
/// [CardRarity] of the card.
/// The rarity of the card.
#[serde(rename = "rarityRef")]
pub rarity: CardRarity,
/// Whether the card is collectible or not.
///
/// If `true`, the card can be found in chests, crafted, or used in decks.
/// If `false`, the card is not available for direct use, as it is probably created by another card.
/// If `false`, the card is not available for direct use, and is probably created by another card, or available only in special occasions, such as Lab matches.
pub collectible: bool,
/// Regions this card belongs to.
@ -77,17 +81,17 @@ pub struct Card {
/// Localized name of the [SpellSpeed] of the card.
///
/// For serialization purposes only, use the [method with the same name](Card::localized_spell_speed()] instead!
/// **For serialization purposes only**, use the [SpellSpeed::localized] instead!
#[serde(rename = "spellSpeed")]
pub(crate) localized_spell_speed: String,
/// [Vec] of [CardKeyword]s of the card.
/// [Vec] of [CardKeyword]s of the card, such as [*Overwhelm*](CardKeyword::Overwhelm) or [*Focus*](CardKeyword::Focus).
#[serde(rename = "keywordRefs")]
pub keywords: Vec<CardKeyword>,
/// [Vec] of localized names of [CardKeyword]s of the card.
///
/// For serialization purposes only, use the [method with the same name](Card::localized_keywords()] instead!
/// **For serialization purposes only**, use the [CardKeyword::localized] instead!
#[serde(rename = "keywords")]
pub(crate) localized_keywords: Vec<String>,
@ -120,6 +124,8 @@ pub struct Card {
/// [Vec] with [Card::name]s of other cards associated with this one.
///
/// Sometimes, it may be missing some references.
///
/// **For serialization purposes only**, use [Card::associated_cards] instead!
#[serde(rename = "associatedCards")]
pub(crate) associated_card_names_localized: Vec<String>,
@ -131,38 +137,33 @@ pub struct Card {
#[serde(rename = "artistName")]
pub artist_name: String,
/// The subtypes the card has, such as `"PORO"`.
///
/// Beware of Riot's inconsistent capitalization!
///
/// TODO: Make this a enum.
pub subtypes: Vec<String>,
/// The subtypes the card belongs to, such as *Poro* or *Yordle*.
pub subtypes: Vec<CardSubtype>,
/// The supertype the card belongs to, such as `"Champion"`.
///
/// Beware of Riot's inconsistent capitalization!
///
/// TODO: Make this a enum.
pub supertype: String,
/// The supertype the card belongs to, such as *Champion*.
pub supertype: CardSupertype,
}
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 {
self.associated_card_codes.iter().map(|r| hashmap.get(r))
pub fn associated_cards<'c, 'hm: 'c>(&'c self, index: &'hm CardIndex) -> impl Iterator<Item=Option<&'hm Card>> + 'c {
self.associated_card_codes.iter().map(|r| index.get(r))
}
/// Get a reference to the first [CardArt] of the card.
///
/// # Panics
///
/// If the card has no associated [CardArt].
pub fn main_art(&self) -> &CardArt {
self.art.get(0).expect("card to have at least one art asset")
/// Equivalent to calling [CardArt].[art](super::art::CardArt::art).[get(0)]([T]::get).
pub fn main_art(&self) -> Option<&CardArt> {
self.art.get(0)
}
}
/// An index of [Card]s, with [Card::code]s as keys.
pub type CardIndex = HashMap<String, Card>;
#[cfg(test)]
mod tests {
use super::*;

View file

@ -2,18 +2,18 @@
use crate::data::corebundle::keyword::{LocalizedCardKeyword, LocalizedCardKeywordIndex};
/// A keyword which cards can have.
/// A keyword which [Card](super::card::Card)s can have.
///
/// Since more keywords will probably be added in the future, this enum is [non_exaustive](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute).
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub enum CardKeyword {
/// Like [CardKeyword::Overwhelm], but on [super::CardType::Spell]s.
/// Like [Overwhelm](CardKeyword::Overwhelm), but on [Spell](super::type::CardType::Spell)s.
///
/// > Inflicts damage beyond what would kill the target(s) to the enemy Nexus.
SpellOverwhelm,
/// [super::SpellSpeed::Burst].
/// [Burst](super::speed::SpellSpeed::Burst).
///
/// > Can be played whenever you may act. Happens instantly and allows you to continue to play other cards.
Burst,
@ -29,7 +29,7 @@ pub enum CardKeyword {
#[serde(rename = "PlaySkillMark")]
OnPlay,
/// [super::CardType::Landmark].
/// [Landmark](super::type::CardType::Landmark).
///
/// > Landmarks take up a space on the board. They can't attack, block, or take damage.
#[serde(rename = "LandmarkVisualOnly")]
@ -59,7 +59,7 @@ pub enum CardKeyword {
/// Focus.
///
/// Used to disambiguate between Burst and Focus with [super::SpellSpeed::Burst].
/// Used to disambiguate between Burst and Focus with [SpellSpeed::Burst](super::speed::SpellSpeed::Burst).
///
/// > Can be played outside combat or when no other spells or skills are pending. Happens instantly and allows you to continue to play other cards.
Focus,
@ -101,7 +101,7 @@ pub enum CardKeyword {
/// ???
BandleCity,
/// [super::SpellSpeed::Fast].
/// [Fast](super::speed::SpellSpeed::Fast).
///
/// > Can be played whenever you may act. Happens after your opponent has a chance to react.
Fast,
@ -137,7 +137,9 @@ pub enum CardKeyword {
/// > Completely removed from the game. Doesn't cause Last Breath and can't be revived.
Obliterate,
/// Imbue, an unused keyword.
/// Imbue.
///
/// Currently unused.
///
/// > These abilities trigger when you resolve a spell.
Imbue,
@ -181,7 +183,7 @@ pub enum CardKeyword {
/// > A unit's spell-like effect that allows enemy reactions.
Skill,
/// Plunder,
/// Plunder.
///
/// > A card triggers its plunder ability when played if you damaged the enemy Nexus this round.
Plunder,

View file

@ -1,9 +1,12 @@
//! This module defines the types used in Data Dragon [Set Bundles](https://developer.riotgames.com/docs/lor#data-dragon_set-bundles).
//! Module defining the types used in [Data Dragon] [Set Bundle]s.
//!
//! [Data Dragon]: https://developer.riotgames.com/docs/lor#data-dragon
//! [Set Bundle]: 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};
use crate::data::anybundle::outcomes::{LoadingError, LoadingResult};
pub mod card;
pub mod art;
@ -13,15 +16,23 @@ pub mod region;
pub mod set;
pub mod speed;
pub mod keyword;
pub mod subtype;
pub mod supertype;
/// A parsed [Set Bundle](https://developer.riotgames.com/docs/lor#data-dragon_set-bundles).
/// A parsed [Data Dragon] [Set Bundle].
///
/// [Data Dragon]: https://developer.riotgames.com/docs/lor#data-dragon
/// [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>,
/// The name of the root directory of the bundle.
pub name: String,
}
@ -33,21 +44,32 @@ impl SetBundle {
.join("metadata.json")
)?;
let locale = metadata.locale().ok_or(LoadingError::Using)?;
let locale = metadata.locale()
.ok_or(LoadingError::GettingLocale)?;
let mut filename = bundle_path.file_name().ok_or(LoadingError::Checking)?.to_os_string();
filename.push(".json");
let name = bundle_path.file_name()
.ok_or(LoadingError::GettingBundleName)?;
let data_path = {
let mut json_filename = name.to_os_string();
json_filename.push(".json");
let cards = File::open(
&bundle_path
.join(&locale)
.join("data")
.join(filename)
).map_err(LoadingError::Loading)?;
.join(&json_filename)
};
let name = name.to_str()
.ok_or(LoadingError::ConvertingBundleName)?
.to_string();
let cards = File::open(data_path)
.map_err(LoadingError::OpeningFile)?;
let cards = serde_json::de::from_reader::<File, Vec<card::Card>>(cards)
.map_err(LoadingError::Parsing)?;
.map_err(LoadingError::Deserializing)?;
Ok(SetBundle {metadata, cards})
Ok(SetBundle {metadata, cards, name})
}
}

View file

@ -2,22 +2,22 @@
use crate::data::corebundle::rarity::{LocalizedCardRarity, LocalizedCardRarityIndex};
/// A possible [super::Card] rarity.
/// A possible [Card](super::card::Card) rarity.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub enum CardRarity {
/// The card has no rarity, as it probably is not collectible.
/// The card has no rarity, as it probably is not [collectible](super::card::Card::collectible).
None,
/// A common card.
/// A common (green triangle) card.
Common,
/// A rare card.
/// A rare (blue square) card.
Rare,
/// An epic card.
/// An epic (purple pentagon) card.
Epic,
/// A champion.
/// A champion (orange hexagon) card, sometimes referred to as *Legendary*.
Champion,
}

View file

@ -2,7 +2,7 @@
use crate::data::corebundle::region::{LocalizedCardRegion, LocalizedCardRegionIndex};
/// A region to which [super::Card]s can belong to.
/// A region to which [Card](super::card::Card)s can belong to.
///
/// Since more regions might be added in the future, especially Origin ones, this enum is [non_exaustive](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute).
#[non_exhaustive]

View file

@ -2,7 +2,7 @@
use crate::data::corebundle::set::{LocalizedCardSet, LocalizedCardSetIndex};
/// The release set a [super::Card] may belong to.
/// The release set a [Card](super::card::Card) may belong to.
///
/// Since more sets will definitely be added in the future, this enum is [non_exaustive](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute).
#[non_exhaustive]
@ -32,7 +32,7 @@ pub enum CardSet {
#[serde(rename = "Set6")]
Worldwalker,
/// Events, with cards released "outside" a set.
/// Events, cards released "outside" a set.
#[serde(rename = "SetEvent")]
Events,

View file

@ -2,7 +2,7 @@
use crate::data::corebundle::speed::{LocalizedSpellSpeed, LocalizedSpellSpeedIndex};
/// A possible spell speed.
/// A possible [Spell](super::type::CardType::Spell) speed.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub enum SpellSpeed {
/// Non-spell cards have this speed.

View file

@ -0,0 +1,8 @@
//! Module defining [CardSubtype].
/// A subtype of a [Card](super::card::Card), such as *Poro* or *Yordle*.
///
/// Capitalization of the various subtypes is inconsistent.
///
/// TODO: As soon as all subtypes are known, make this a enum.
pub type CardSubtype = String;

View file

@ -0,0 +1,8 @@
//! Module defining [CardSupertype].
/// A supertype of a [Card](super::card::Card), such as *Champion*.
///
/// Capitalization of the various supertypes is inconsistent.
///
/// TODO: As soon as all supertypes are known, make this a enum.
pub type CardSupertype = String;

View file

@ -1,7 +1,7 @@
//! Module defining [CardType].
/// A possible card type.
/// A possible [Card](super::card::Card) type.
///
/// Since more types might be added in the future, as it happened with landmarks, this enum is [non_exaustive](https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute).
#[non_exhaustive]
@ -9,14 +9,21 @@
pub enum CardType {
/// A spell.
Spell,
/// An unit: either a minion, or a champion.
/// Champions have their `supertype` set to `Champion`, and their `rarity` set to `Champion` as well.
///
/// Champions have their [supertype](super::card::Card::supertype) set to `Champion`, and their [rarity](super::card::Card::rarity) set to [CardRarity::Champion](super::rarity::CardRarity::Champion) as well.
Unit,
/// An ability triggered by an unit.
/// An ability triggered by an [Unit](CardType::Unit).
Ability,
/// A landmark.
Landmark,
/// A trap or boon.
/// An autoplaying card: either a trap or boon.
///
/// Disambiguate between the two using [CardKeyword::Trap](super::keyword::CardKeyword::Trap) and [CardKeyword::Boon](super::keyword::CardKeyword::Boon).
Trap,
/// Unsupported card type.

View file

@ -1,7 +1,21 @@
//! Crate providing parsing, indexing, and displaying utilities for Legends of Runeterra data files.
//!
//! # Features
//!
//! - `search`: Adds a search engine based on [tantivy] for Legends of Runeterra data.
//! - `telegram`: Adds a [Telegram bot](https://core.telegram.org/bots/api) based on [teloxide] for Legends of Runeterra data.
//!
//! # Legal
//!
//! [patched_porobot](self) isn't endorsed by Riot Games and doesn't reflect the views or opinions of Riot Games or anyone officially involved in producing or managing Riot Games properties. Riot Games, and all associated properties are trademarks or registered trademarks of Riot Games, Inc.
#![warn(missing_docs)]
#![doc(html_logo_url = "https://raw.githubusercontent.com/Steffo99/patched-porobot/main/icon.png")]
pub mod data;
#[cfg(feature = "search")]
pub mod search;
// #[cfg(feature = "search")]
// pub mod search;
#[cfg(feature = "telegram")]
pub mod telegram;
// #[cfg(feature = "telegram")]
// pub mod telegram;

View file

@ -6,7 +6,7 @@ use tantivy::query::{QueryParser, QueryParserError};
use tantivy::schema::{Schema, TextOptions};
use tantivy::tokenizer::TextAnalyzer;
use itertools::Itertools;
use crate::data::corebundle::CoreBundle;
use crate::data::corebundle::globals::LocalizedGlobalsIndexes;
use crate::data::setbundle::r#type::CardType;
use crate::data::setbundle::card::Card;
@ -93,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, cb: &CoreBundle, card: Card) -> Document {
pub fn card_to_document(schema: &Schema, globals: &LocalizedGlobalsIndexes, card: Card) -> Document {
use tantivy::*;
let f_code = schema.get_field("code").expect("schema to have a 'code' field");
@ -122,7 +122,7 @@ pub fn card_to_document(schema: &Schema, cb: &CoreBundle, card: Card) -> Documen
CardType::Ability => "Ability",
CardType::Landmark => "Landmark",
CardType::Trap => "Trap",
CardType::Unsupported => ""
CardType::Unsupported => "Unknown",
};
doc!(
@ -130,17 +130,17 @@ pub fn card_to_document(schema: &Schema, cb: &CoreBundle, card: Card) -> Documen
f_name => card.name,
f_type => c_type,
f_set => card.set
.localized(&cb.globals.sets)
.localized(&globals.sets)
.map(|cs| cs.name.to_owned())
.unwrap_or_else(String::new),
f_rarity => card.rarity
.localized(&cb.globals.rarities)
.localized(&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(&cb.globals.regions)
.localized(&globals.regions)
.map(|cr| cr.name.to_owned())
.unwrap_or_else(String::new)
).join(" "),
@ -148,12 +148,12 @@ pub fn card_to_document(schema: &Schema, cb: &CoreBundle, card: Card) -> Documen
f_cost => card.cost,
f_health => card.health,
f_spellspeed => card.spell_speed
.localized(&cb.globals.spell_speeds)
.localized(&globals.spell_speeds)
.map(|ss| ss.name.to_owned())
.unwrap_or_else(String::new),
f_keywords => card.keywords.iter()
.map(|keyword| keyword
.localized(&cb.globals.keywords)
.localized(&globals.keywords)
.map(|ck| ck.name.to_owned())
.unwrap_or_else(String::new))
.join(" "),
@ -169,9 +169,9 @@ pub fn card_to_document(schema: &Schema, cb: &CoreBundle, card: Card) -> Documen
/// Stage all [tantivy::Document]s generated from [Card]s contained in the passed [Vec] for write on a [tantivy::Index] via the given [tantivy::IndexWriter].
pub fn cards_to_index(writer: IndexWriter, schema: Schema, locale: MappedGlobals, cards: Vec<Card>) -> tantivy::Result<()> {
pub fn cards_to_index(writer: IndexWriter, schema: Schema, globals: &LocalizedGlobalsIndexes, cards: Vec<Card>) -> tantivy::Result<()> {
for card in cards {
writer.add_document(card_to_document(&schema, &locale, card))?;
writer.add_document(card_to_document(&schema, &globals, card))?;
};
Ok(())
}

View file

@ -7,10 +7,11 @@
use std::collections::HashMap;
use itertools::Itertools;
use teloxide::utils::html::escape;
use crate::data::setbundle::card::Card;
/// Render a [Card] to a [String] formatted with [Telegram Bot HTML](https://core.telegram.org/bots/api#html-style).
pub fn display_card(card: &, mg: &MappedGlobals) -> String {
pub fn display_card(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 {