mirror of
https://github.com/Steffo99/patched-porobot.git
synced 2024-12-22 17:44:22 +00:00
Run cargo fmt
This commit is contained in:
parent
54fc192b6e
commit
30a94754cd
19 changed files with 232 additions and 155 deletions
|
@ -1,7 +1,7 @@
|
|||
//! Module defining structs representing localized card keywords.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use crate::data::setbundle::keyword::CardKeyword;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// A Legends of Runeterra [CardKeyword], and its associated localization.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
|
@ -22,7 +22,6 @@ 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 super::*;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Module defining structs representing localized card rarities.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use crate::data::setbundle::rarity::CardRarity;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// A Legends of Runeterra [CardRarity], and its associated localization.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
|
@ -19,7 +19,6 @@ 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 super::*;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Module defining structs representing localized card sets.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use crate::data::setbundle::set::CardSet;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// A Legends of Runeterra [CardSet], and its associated localization.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
|
||||
|
@ -23,7 +23,6 @@ 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 super::*;
|
||||
|
|
|
@ -24,7 +24,6 @@ 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::*;
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
//! Module defining the [`Deck`] struct and its serialization methods and results.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::io::{Cursor, Read, Write};
|
||||
use itertools::Itertools;
|
||||
use varint_rs::{VarintReader, VarintWriter};
|
||||
use super::format::DeckCodeFormat;
|
||||
use crate::data::deckcode::version::{DeckCodeVersion, DeckCodeVersioned};
|
||||
use crate::data::setbundle::code::CardCode;
|
||||
use crate::data::setbundle::region::CardRegion;
|
||||
use crate::data::setbundle::set::CardSet;
|
||||
use super::format::DeckCodeFormat;
|
||||
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{Cursor, Read, Write};
|
||||
use varint_rs::{VarintReader, VarintWriter};
|
||||
|
||||
/// A unshuffled Legends of Runeterra card deck.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -18,7 +17,6 @@ pub struct Deck {
|
|||
pub contents: HashMap<CardCode, u32>,
|
||||
}
|
||||
|
||||
|
||||
impl Deck {
|
||||
/// Decode a deck code into a [`Vec`] of [bytes](u8).
|
||||
fn decode_code(code: &str) -> DeckDecodingResult<Vec<u8>> {
|
||||
|
@ -29,23 +27,32 @@ impl Deck {
|
|||
|
||||
/// Encode a slice of [bytes](u8) into a deck code.
|
||||
fn encode_code(bytes: &[u8]) -> String {
|
||||
data_encoding::BASE32_NOPAD
|
||||
.encode(bytes)
|
||||
data_encoding::BASE32_NOPAD.encode(bytes)
|
||||
}
|
||||
|
||||
/// [Read] the header byte into a [format](DeckCodeFormat) and [version](DeckCodeVersion) tuple.
|
||||
fn read_header<R: Read>(reader: &mut R) -> DeckDecodingResult<(DeckCodeFormat, DeckCodeVersion)> {
|
||||
fn read_header<R: Read>(
|
||||
reader: &mut R,
|
||||
) -> DeckDecodingResult<(DeckCodeFormat, DeckCodeVersion)> {
|
||||
let mut format_version: [u8; 1] = [0; 1];
|
||||
reader.read_exact(&mut format_version).map_err(DeckDecodingError::Read)?;
|
||||
reader
|
||||
.read_exact(&mut format_version)
|
||||
.map_err(DeckDecodingError::Read)?;
|
||||
|
||||
let format = DeckCodeFormat::try_from(format_version[0] >> 4).map_err(|_| DeckDecodingError::UnknownFormat)?;
|
||||
let version = DeckCodeVersion::try_from(format_version[0] & 0xF).map_err(|_| DeckDecodingError::UnknownVersion)?;
|
||||
let format = DeckCodeFormat::try_from(format_version[0] >> 4)
|
||||
.map_err(|_| DeckDecodingError::UnknownFormat)?;
|
||||
let version = DeckCodeVersion::try_from(format_version[0] & 0xF)
|
||||
.map_err(|_| DeckDecodingError::UnknownVersion)?;
|
||||
|
||||
Ok((format, version))
|
||||
}
|
||||
|
||||
/// [Write] the header byte with the given [format](DeckCodeFormat) and [version](DeckCodeVersion).
|
||||
fn write_header<W: Write>(writer: &mut W, format: DeckCodeFormat, version: DeckCodeVersion) -> DeckEncodingResult<()> {
|
||||
fn write_header<W: Write>(
|
||||
writer: &mut W,
|
||||
format: DeckCodeFormat,
|
||||
version: DeckCodeVersion,
|
||||
) -> DeckEncodingResult<()> {
|
||||
let format: u8 = format.into();
|
||||
let version: u8 = version.into();
|
||||
|
||||
|
@ -103,7 +110,11 @@ impl Deck {
|
|||
}
|
||||
|
||||
/// [Read] the **groups** of a single supergroup.
|
||||
fn read_f1_supergroup<R: Read>(reader: &mut R, contents: &mut HashMap<CardCode, u32>, quantity: u32) -> DeckDecodingResult<()> {
|
||||
fn read_f1_supergroup<R: Read>(
|
||||
reader: &mut R,
|
||||
contents: &mut HashMap<CardCode, u32>,
|
||||
quantity: u32,
|
||||
) -> DeckDecodingResult<()> {
|
||||
// Read the number of groups in the supergroup
|
||||
let len = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
|
||||
|
||||
|
@ -116,7 +127,9 @@ impl Deck {
|
|||
}
|
||||
|
||||
/// Given a slice of [`CardCode`]s, group them by set and region.
|
||||
fn f1_group_cards<'cc>(codes: &[&'cc CardCode]) -> HashMap<(&'cc str, &'cc str), Vec<&'cc CardCode>> {
|
||||
fn f1_group_cards<'cc>(
|
||||
codes: &[&'cc CardCode],
|
||||
) -> HashMap<(&'cc str, &'cc str), Vec<&'cc CardCode>> {
|
||||
// Create the hashmap accumulating groups of cards
|
||||
// It has the tuple (set, region) as key
|
||||
let mut groups = HashMap::new();
|
||||
|
@ -145,22 +158,28 @@ impl Deck {
|
|||
}
|
||||
|
||||
/// [Write] the **groups** of a single supergroup.
|
||||
fn write_f1_supergroup<W: Write>(writer: &mut W, supergroup: &[&CardCode]) -> DeckEncodingResult<()> {
|
||||
fn write_f1_supergroup<W: Write>(
|
||||
writer: &mut W,
|
||||
supergroup: &[&CardCode],
|
||||
) -> DeckEncodingResult<()> {
|
||||
// Arrange cards into groups
|
||||
let groups = Self::f1_group_cards(supergroup);
|
||||
|
||||
// Determine the number of groups in the supergroup
|
||||
let len: u32 = groups.len().try_into().expect("groups length to be smaller than usize");
|
||||
writer.write_u32_varint(len).map_err(DeckEncodingError::Write)?;
|
||||
let len: u32 = groups
|
||||
.len()
|
||||
.try_into()
|
||||
.expect("groups length to be smaller than usize");
|
||||
writer
|
||||
.write_u32_varint(len)
|
||||
.map_err(DeckEncodingError::Write)?;
|
||||
|
||||
// Sort first by ascending group length, then by key
|
||||
let groups = groups
|
||||
.into_iter()
|
||||
.sorted_by(|(a_key, a_group), (b_key, b_group)|
|
||||
a_group.len().cmp(&b_group.len())
|
||||
.then(
|
||||
a_key.cmp(b_key))
|
||||
);
|
||||
.sorted_by(|(a_key, a_group), (b_key, b_group)| {
|
||||
a_group.len().cmp(&b_group.len()).then(a_key.cmp(b_key))
|
||||
});
|
||||
|
||||
// Write all groups
|
||||
for ((set, region), group) in groups {
|
||||
|
@ -171,14 +190,22 @@ impl Deck {
|
|||
}
|
||||
|
||||
/// [Read] the **cards** of a single group.
|
||||
fn read_f1_group<R: Read>(reader: &mut R, contents: &mut HashMap<CardCode, u32>, quantity: u32) -> DeckDecodingResult<()> {
|
||||
fn read_f1_group<R: Read>(
|
||||
reader: &mut R,
|
||||
contents: &mut HashMap<CardCode, u32>,
|
||||
quantity: u32,
|
||||
) -> DeckDecodingResult<()> {
|
||||
let card_count = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
|
||||
|
||||
let set = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
|
||||
let set = CardSet::from(set).to_code().ok_or(DeckDecodingError::UnknownSet)?;
|
||||
let set = CardSet::from(set)
|
||||
.to_code()
|
||||
.ok_or(DeckDecodingError::UnknownSet)?;
|
||||
|
||||
let region = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
|
||||
let region = CardRegion::from(region).to_code().ok_or(DeckDecodingError::UnknownRegion)?;
|
||||
let region = CardRegion::from(region)
|
||||
.to_code()
|
||||
.ok_or(DeckDecodingError::UnknownRegion)?;
|
||||
|
||||
for _card in 0..card_count {
|
||||
Self::read_f1_standard_card(reader, contents, quantity, &set, ®ion)?;
|
||||
|
@ -188,15 +215,33 @@ impl Deck {
|
|||
}
|
||||
|
||||
/// [Write] the **cards** of a single group.
|
||||
fn write_f1_group<W: Write>(writer: &mut W, group: &[&CardCode], set: &str, region: &str) -> DeckEncodingResult<()> {
|
||||
let len: u32 = group.len().try_into().expect("cards length to be smaller than usize");
|
||||
writer.write_u32_varint(len).map_err(DeckEncodingError::Write)?;
|
||||
fn write_f1_group<W: Write>(
|
||||
writer: &mut W,
|
||||
group: &[&CardCode],
|
||||
set: &str,
|
||||
region: &str,
|
||||
) -> DeckEncodingResult<()> {
|
||||
let len: u32 = group
|
||||
.len()
|
||||
.try_into()
|
||||
.expect("cards length to be smaller than usize");
|
||||
writer
|
||||
.write_u32_varint(len)
|
||||
.map_err(DeckEncodingError::Write)?;
|
||||
|
||||
let set: u32 = CardSet::from_code(set).try_into().map_err(|_| DeckEncodingError::UnknownSet)?;
|
||||
writer.write_u32_varint(set).map_err(DeckEncodingError::Write)?;
|
||||
let set: u32 = CardSet::from_code(set)
|
||||
.try_into()
|
||||
.map_err(|_| DeckEncodingError::UnknownSet)?;
|
||||
writer
|
||||
.write_u32_varint(set)
|
||||
.map_err(DeckEncodingError::Write)?;
|
||||
|
||||
let region: u32 = CardRegion::from_code(region).try_into().map_err(|_| DeckEncodingError::UnknownRegion)?;
|
||||
writer.write_u32_varint(region).map_err(DeckEncodingError::Write)?;
|
||||
let region: u32 = CardRegion::from_code(region)
|
||||
.try_into()
|
||||
.map_err(|_| DeckEncodingError::UnknownRegion)?;
|
||||
writer
|
||||
.write_u32_varint(region)
|
||||
.map_err(DeckEncodingError::Write)?;
|
||||
|
||||
for card in group.iter().sorted() {
|
||||
Self::write_f1_standard_card(writer, card.card())?;
|
||||
|
@ -206,7 +251,13 @@ impl Deck {
|
|||
}
|
||||
|
||||
/// [Read] **a single card**.
|
||||
fn read_f1_standard_card<R: Read>(reader: &mut R, contents: &mut HashMap<CardCode, u32>, quantity: u32, set: &str, region: &str) -> DeckDecodingResult<()> {
|
||||
fn read_f1_standard_card<R: Read>(
|
||||
reader: &mut R,
|
||||
contents: &mut HashMap<CardCode, u32>,
|
||||
quantity: u32,
|
||||
set: &str,
|
||||
region: &str,
|
||||
) -> DeckDecodingResult<()> {
|
||||
let card = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
|
||||
|
||||
let code = CardCode::from_s_r_c(set, region, card);
|
||||
|
@ -217,15 +268,21 @@ impl Deck {
|
|||
|
||||
/// [Write] **a single card**.
|
||||
fn write_f1_standard_card<W: Write>(writer: &mut W, card: &str) -> DeckEncodingResult<()> {
|
||||
let card = card.parse::<u32>().map_err(DeckEncodingError::InvalidCardNumber)?;
|
||||
writer.write_u32_varint(card).map_err(DeckEncodingError::Write)?;
|
||||
let card = card
|
||||
.parse::<u32>()
|
||||
.map_err(DeckEncodingError::InvalidCardNumber)?;
|
||||
writer
|
||||
.write_u32_varint(card)
|
||||
.map_err(DeckEncodingError::Write)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// [Read] the **extra segment** of the deck code.
|
||||
fn read_f1_extra<R: Read>(reader: &mut R, contents: &mut HashMap<CardCode, u32>) -> DeckDecodingResult<()> {
|
||||
|
||||
fn read_f1_extra<R: Read>(
|
||||
reader: &mut R,
|
||||
contents: &mut HashMap<CardCode, u32>,
|
||||
) -> DeckDecodingResult<()> {
|
||||
// While the cursor has still some bytes left...
|
||||
while Self::read_f1_extra_card(reader, contents).is_ok() {}
|
||||
|
||||
|
@ -233,7 +290,10 @@ impl Deck {
|
|||
}
|
||||
|
||||
/// [Write] the **extra segment** of the deck code.
|
||||
fn write_f1_extra<W: Write>(writer: &mut W, codes: Vec<(&CardCode, u32)>) -> DeckEncodingResult<()> {
|
||||
fn write_f1_extra<W: Write>(
|
||||
writer: &mut W,
|
||||
codes: Vec<(&CardCode, u32)>,
|
||||
) -> DeckEncodingResult<()> {
|
||||
for (code, quantity) in codes.iter().sorted() {
|
||||
Self::write_f1_extra_card(writer, code, *quantity)?;
|
||||
}
|
||||
|
@ -242,14 +302,21 @@ impl Deck {
|
|||
}
|
||||
|
||||
/// [Read] **a single card** with a **non-standard quantity**.
|
||||
fn read_f1_extra_card<R: Read>(reader: &mut R, contents: &mut HashMap<CardCode, u32>) -> DeckDecodingResult<()> {
|
||||
fn read_f1_extra_card<R: Read>(
|
||||
reader: &mut R,
|
||||
contents: &mut HashMap<CardCode, u32>,
|
||||
) -> DeckDecodingResult<()> {
|
||||
let quantity = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
|
||||
|
||||
let set = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
|
||||
let set = CardSet::from(set).to_code().ok_or(DeckDecodingError::UnknownSet)?;
|
||||
let set = CardSet::from(set)
|
||||
.to_code()
|
||||
.ok_or(DeckDecodingError::UnknownSet)?;
|
||||
|
||||
let region = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
|
||||
let region = CardRegion::from(region).to_code().ok_or(DeckDecodingError::UnknownRegion)?;
|
||||
let region = CardRegion::from(region)
|
||||
.to_code()
|
||||
.ok_or(DeckDecodingError::UnknownRegion)?;
|
||||
|
||||
let card = reader.read_u32_varint().map_err(DeckDecodingError::Read)?;
|
||||
|
||||
|
@ -260,19 +327,36 @@ impl Deck {
|
|||
}
|
||||
|
||||
/// [Write] **a single card** with a **non-standard quantity**.
|
||||
fn write_f1_extra_card<W: Write>(writer: &mut W, code: &CardCode, quantity: u32) -> DeckEncodingResult<()> {
|
||||
writer.write_u32_varint(quantity).map_err(DeckEncodingError::Write)?;
|
||||
fn write_f1_extra_card<W: Write>(
|
||||
writer: &mut W,
|
||||
code: &CardCode,
|
||||
quantity: u32,
|
||||
) -> DeckEncodingResult<()> {
|
||||
writer
|
||||
.write_u32_varint(quantity)
|
||||
.map_err(DeckEncodingError::Write)?;
|
||||
|
||||
let set = CardSet::from_code(code.set());
|
||||
let set: u32 = set.try_into().map_err(|_| DeckEncodingError::UnknownSet)?;
|
||||
writer.write_u32_varint(set).map_err(DeckEncodingError::Write)?;
|
||||
writer
|
||||
.write_u32_varint(set)
|
||||
.map_err(DeckEncodingError::Write)?;
|
||||
|
||||
let region = CardRegion::from_code(code.region());
|
||||
let region: u32 = region.try_into().map_err(|_| DeckEncodingError::UnknownRegion)?;
|
||||
writer.write_u32_varint(region).map_err(DeckEncodingError::Write)?;
|
||||
let region: u32 = region
|
||||
.try_into()
|
||||
.map_err(|_| DeckEncodingError::UnknownRegion)?;
|
||||
writer
|
||||
.write_u32_varint(region)
|
||||
.map_err(DeckEncodingError::Write)?;
|
||||
|
||||
let card = code.card().parse::<u32>().map_err(DeckEncodingError::InvalidCardNumber)?;
|
||||
writer.write_u32_varint(card).map_err(DeckEncodingError::Write)?;
|
||||
let card = code
|
||||
.card()
|
||||
.parse::<u32>()
|
||||
.map_err(DeckEncodingError::InvalidCardNumber)?;
|
||||
writer
|
||||
.write_u32_varint(card)
|
||||
.map_err(DeckEncodingError::Write)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -293,7 +377,7 @@ impl Deck {
|
|||
let (format, _version) = Self::read_header(&mut cursor)?;
|
||||
|
||||
match format {
|
||||
DeckCodeFormat::F1 => Self::read_f1_body(&mut cursor)
|
||||
DeckCodeFormat::F1 => Self::read_f1_body(&mut cursor),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,7 +399,9 @@ impl Deck {
|
|||
pub fn to_code(&self, format: DeckCodeFormat) -> DeckEncodingResult<String> {
|
||||
let mut cursor = Cursor::new(Vec::new());
|
||||
|
||||
let version = self.min_deckcode_version().ok_or(DeckEncodingError::UnknownVersion)?;
|
||||
let version = self
|
||||
.min_deckcode_version()
|
||||
.ok_or(DeckEncodingError::UnknownVersion)?;
|
||||
|
||||
Self::write_header(&mut cursor, format, version)?;
|
||||
|
||||
|
@ -327,7 +413,6 @@ impl Deck {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// An error occoured while decoding a [`Deck`] from a code.
|
||||
#[derive(Debug)]
|
||||
pub enum DeckDecodingError {
|
||||
|
@ -366,7 +451,6 @@ pub type DeckDecodingResult<T> = Result<T, DeckDecodingError>;
|
|||
/// The [`Result`] of a [`Deck`] **encoding** operation, for example [`Deck::to_code`].
|
||||
pub type DeckEncodingResult<T> = Result<T, DeckEncodingError>;
|
||||
|
||||
|
||||
/// Macro to build a deck from card code strings and quantities.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -408,7 +492,7 @@ macro_rules! deck {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[rustfmt::skip::macros(test_de_ser, test_ser_de)]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -457,12 +541,14 @@ mod tests {
|
|||
fn $id() {
|
||||
use patched_porobot::data::deckcode::deck::Deck;
|
||||
let deck1 = $deck;
|
||||
let code = deck1.to_code(DeckCodeFormat::F1).expect("deck to serialize successfully");
|
||||
let code = deck1
|
||||
.to_code(DeckCodeFormat::F1)
|
||||
.expect("deck to serialize successfully");
|
||||
println!("Serialized deck code (for science, obviously): {}", &code);
|
||||
let deck2 = Deck::from_code(&code).expect("deck to deserialize successfully");
|
||||
assert_eq!(deck1, deck2);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Some tests from https://github.com/RiotGames/LoRDeckCodes/blob/main/LoRDeckCodes_Tests/UnitTest1.cs
|
||||
|
@ -571,5 +657,4 @@ mod tests {
|
|||
]);
|
||||
|
||||
//test_ser_de!(test_ser_de_, deck![]);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
//! Module defining [`DeckCodeFormat`].
|
||||
|
||||
|
||||
/// The format of a deck code.
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
@ -9,14 +8,13 @@ pub enum DeckCodeFormat {
|
|||
F1,
|
||||
}
|
||||
|
||||
|
||||
impl TryFrom<u8> for DeckCodeFormat {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
1 => Ok(Self::F1),
|
||||
_ => Err(())
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,4 +25,4 @@ impl From<DeckCodeFormat> for u8 {
|
|||
DeckCodeFormat::F1 => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Module defining the types used to deserialize deck codes.
|
||||
//!
|
||||
//!
|
||||
//! Adapted from [RiotGames/LoRDeckCodes](https://github.com/RiotGames/LoRDeckCodes) and from [iulianR/lordeckcodes-rs](https://github.com/iulianR/lordeckcodes-rs).
|
||||
|
||||
pub mod deck;
|
||||
pub mod version;
|
||||
pub mod format;
|
||||
pub mod version;
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::data::deckcode::deck::Deck;
|
|||
use crate::data::setbundle::code::CardCode;
|
||||
use crate::data::setbundle::region::CardRegion;
|
||||
|
||||
|
||||
/// The version of a deck code.
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
@ -27,7 +26,6 @@ pub enum DeckCodeVersion {
|
|||
V5,
|
||||
}
|
||||
|
||||
|
||||
impl TryFrom<u8> for DeckCodeVersion {
|
||||
type Error = ();
|
||||
|
||||
|
@ -38,7 +36,7 @@ impl TryFrom<u8> for DeckCodeVersion {
|
|||
3 => Ok(Self::V3),
|
||||
4 => Ok(Self::V4),
|
||||
5 => Ok(Self::V5),
|
||||
_ => Err(())
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,15 +53,12 @@ impl From<DeckCodeVersion> for u8 {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Indicates that a given type is versioned in the [specs for deck codes](https://github.com/RiotGames/LoRDeckCodes).
|
||||
pub trait DeckCodeVersioned {
|
||||
/// Get the minimum deck version required to encode the deck in "code" format.
|
||||
fn min_deckcode_version(&self) -> Option<DeckCodeVersion>;
|
||||
}
|
||||
|
||||
|
||||
impl DeckCodeVersioned for CardRegion {
|
||||
fn min_deckcode_version(&self) -> Option<DeckCodeVersion> {
|
||||
match self {
|
||||
|
@ -91,7 +86,6 @@ impl DeckCodeVersioned for CardRegion {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// [`CardCode`]'s version is the maximum version of its components.
|
||||
impl DeckCodeVersioned for CardCode {
|
||||
fn min_deckcode_version(&self) -> Option<DeckCodeVersion> {
|
||||
|
@ -99,7 +93,6 @@ impl DeckCodeVersioned for CardCode {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// [`Deck`]'s version is the maximum version of all its [`CardCode`]s.
|
||||
impl DeckCodeVersioned for Deck {
|
||||
fn min_deckcode_version(&self) -> Option<DeckCodeVersion> {
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
|
||||
pub mod anybundle;
|
||||
pub mod corebundle;
|
||||
pub mod setbundle;
|
||||
pub mod deckcode;
|
||||
pub mod setbundle;
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
//! Module defining [Card].
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use crate::data::setbundle::subtype::CardSubtype;
|
||||
use crate::data::setbundle::supertype::CardSupertype;
|
||||
use super::r#type::CardType;
|
||||
use super::art::CardArt;
|
||||
use super::code::CardCode;
|
||||
use super::keyword::CardKeyword;
|
||||
use super::r#type::CardType;
|
||||
use super::rarity::CardRarity;
|
||||
use super::region::CardRegion;
|
||||
use super::speed::SpellSpeed;
|
||||
use super::set::CardSet;
|
||||
use super::code::CardCode;
|
||||
use super::speed::SpellSpeed;
|
||||
use crate::data::setbundle::subtype::CardSubtype;
|
||||
use crate::data::setbundle::supertype::CardSupertype;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
/// A single Legends of Runeterra card, as represented in a `set*.json` file.
|
||||
///
|
||||
|
@ -146,10 +146,12 @@ pub struct Card {
|
|||
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, index: &'hm CardIndex) -> impl Iterator<Item=Option<&'hm Card>> + 'c {
|
||||
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))
|
||||
}
|
||||
|
||||
|
@ -161,7 +163,6 @@ impl Card {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Two [`Card`]s are equal if they have the same [`Card::code`].
|
||||
impl PartialEq for Card {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
|
@ -169,7 +170,6 @@ impl PartialEq for Card {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// [`Card`] [`Hash`]es are equal to hashes of their [`Card::code`].
|
||||
impl Hash for Card {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
|
@ -177,11 +177,9 @@ impl Hash for Card {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// An index of [Card]s, with [CardCode]s as keys.
|
||||
pub type CardIndex = HashMap<CardCode, Card>;
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -277,4 +275,4 @@ mod tests {
|
|||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
//! Module defining [CardCode].
|
||||
|
||||
|
||||
use crate::data::setbundle::card::{Card, CardIndex};
|
||||
|
||||
/// The internal code of a [Card](super::card::Card).
|
||||
///
|
||||
///
|
||||
/// It is a ASCII string composed of the following segments:
|
||||
/// - `0..2`: set;
|
||||
/// - `2..4`: region;
|
||||
|
@ -22,17 +21,18 @@ use crate::data::setbundle::card::{Card, CardIndex};
|
|||
/// # Warning
|
||||
///
|
||||
/// The way this is built is pretty... unsafe, so beware to not construct this with invalid codes.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(
|
||||
Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct CardCode {
|
||||
/// The card code as a [`String`].
|
||||
pub full: String
|
||||
pub full: String,
|
||||
}
|
||||
|
||||
|
||||
impl CardCode {
|
||||
/// Determines whether the card code is valid or not by checking the following:
|
||||
///
|
||||
///
|
||||
/// - that the full string [is ascii](str::is_ascii);
|
||||
/// - that it is either 7 or 9 characters long.
|
||||
pub fn is_valid(&self) -> bool {
|
||||
|
@ -44,28 +44,28 @@ impl CardCode {
|
|||
}
|
||||
|
||||
/// The set segment of the code.
|
||||
///
|
||||
///
|
||||
/// In valid codes, it is always 2-ASCII-characters long.
|
||||
pub fn set(&self) -> &str {
|
||||
&self.full[0..2]
|
||||
}
|
||||
|
||||
/// The region segment of the code.
|
||||
///
|
||||
///
|
||||
/// In valid codes, it is always 2-ASCII-characters long.
|
||||
pub fn region(&self) -> &str {
|
||||
&self.full[2..4]
|
||||
}
|
||||
|
||||
/// The card segment of the code.
|
||||
///
|
||||
///
|
||||
/// In valid codes, it is always 3-ASCII-characters long.
|
||||
pub fn card(&self) -> &str {
|
||||
&self.full[4..7]
|
||||
}
|
||||
|
||||
/// The token segment of the code.
|
||||
///
|
||||
///
|
||||
/// In valid codes, it may either be an empty string, or 2-ASCII-characters long.
|
||||
pub fn token(&self) -> &str {
|
||||
&self.full[7..9]
|
||||
|
|
|
@ -10,6 +10,7 @@ use std::path::Path;
|
|||
|
||||
pub mod art;
|
||||
pub mod card;
|
||||
pub mod code;
|
||||
pub mod keyword;
|
||||
pub mod rarity;
|
||||
pub mod region;
|
||||
|
@ -18,7 +19,6 @@ pub mod speed;
|
|||
pub mod subtype;
|
||||
pub mod supertype;
|
||||
pub mod r#type;
|
||||
pub mod code;
|
||||
|
||||
/// A parsed [Data Dragon] [Set Bundle].
|
||||
///
|
||||
|
|
|
@ -50,7 +50,10 @@ impl CardRegion {
|
|||
/// 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> {
|
||||
pub fn localized<'hm>(
|
||||
&self,
|
||||
hm: &'hm LocalizedCardRegionIndex,
|
||||
) -> Option<&'hm LocalizedCardRegion> {
|
||||
hm.get(self)
|
||||
}
|
||||
|
||||
|
@ -101,18 +104,18 @@ impl CardRegion {
|
|||
impl From<u32> for CardRegion {
|
||||
fn from(value: u32) -> Self {
|
||||
match value {
|
||||
0 => CardRegion::Demacia,
|
||||
1 => CardRegion::Freljord,
|
||||
2 => CardRegion::Ionia,
|
||||
3 => CardRegion::Noxus,
|
||||
4 => CardRegion::PiltoverZaun,
|
||||
5 => CardRegion::ShadowIsles,
|
||||
6 => CardRegion::Bilgewater,
|
||||
7 => CardRegion::Shurima,
|
||||
9 => CardRegion::Targon,
|
||||
0 => CardRegion::Demacia,
|
||||
1 => CardRegion::Freljord,
|
||||
2 => CardRegion::Ionia,
|
||||
3 => CardRegion::Noxus,
|
||||
4 => CardRegion::PiltoverZaun,
|
||||
5 => CardRegion::ShadowIsles,
|
||||
6 => CardRegion::Bilgewater,
|
||||
7 => CardRegion::Shurima,
|
||||
9 => CardRegion::Targon,
|
||||
10 => CardRegion::BandleCity,
|
||||
12 => CardRegion::Runeterra,
|
||||
_ => CardRegion::Unsupported,
|
||||
_ => CardRegion::Unsupported,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,23 +128,22 @@ impl TryFrom<CardRegion> for u32 {
|
|||
|
||||
fn try_from(value: CardRegion) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
CardRegion::Demacia => Ok(0),
|
||||
CardRegion::Freljord => Ok(1),
|
||||
CardRegion::Ionia => Ok(2),
|
||||
CardRegion::Noxus => Ok(3),
|
||||
CardRegion::Demacia => Ok(0),
|
||||
CardRegion::Freljord => Ok(1),
|
||||
CardRegion::Ionia => Ok(2),
|
||||
CardRegion::Noxus => Ok(3),
|
||||
CardRegion::PiltoverZaun => Ok(4),
|
||||
CardRegion::ShadowIsles => Ok(5),
|
||||
CardRegion::Bilgewater => Ok(6),
|
||||
CardRegion::Shurima => Ok(7),
|
||||
CardRegion::Targon => Ok(9),
|
||||
CardRegion::BandleCity => Ok(10),
|
||||
CardRegion::Runeterra => Ok(12),
|
||||
_ => Err(()),
|
||||
CardRegion::ShadowIsles => Ok(5),
|
||||
CardRegion::Bilgewater => Ok(6),
|
||||
CardRegion::Shurima => Ok(7),
|
||||
CardRegion::Targon => Ok(9),
|
||||
CardRegion::BandleCity => Ok(10),
|
||||
CardRegion::Runeterra => Ok(12),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
#[rustfmt::skip]
|
||||
mod tests {
|
||||
|
|
|
@ -86,7 +86,6 @@ impl CardSet {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Get the [`CardSet`] from its internal id.
|
||||
///
|
||||
/// [`CardSet::Events`] cards have the id of the set they were released in, so it is impossible to determine if a card belongs to that set from its id.
|
||||
|
@ -123,7 +122,6 @@ impl TryFrom<CardSet> for u32 {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::CardSet;
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
use crate::data::corebundle::globals::LocalizedGlobalsIndexes;
|
||||
use crate::data::setbundle::card::{Card, CardIndex};
|
||||
use crate::data::setbundle::code::CardCode;
|
||||
use itertools::Itertools;
|
||||
use tantivy::collector::TopDocs;
|
||||
use tantivy::query::{QueryParser, QueryParserError};
|
||||
use tantivy::schema::{Field, NumericOptions, Schema, TextOptions};
|
||||
use tantivy::tokenizer::TextAnalyzer;
|
||||
use tantivy::{Document, Index, IndexReader, IndexWriter};
|
||||
use crate::data::setbundle::code::CardCode;
|
||||
|
||||
/// The search engine.
|
||||
///
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::data::corebundle::globals::LocalizedGlobalsIndexes;
|
|||
use crate::data::corebundle::keyword::LocalizedCardKeywordIndex;
|
||||
use crate::data::corebundle::region::LocalizedCardRegionIndex;
|
||||
use crate::data::corebundle::set::LocalizedCardSetIndex;
|
||||
use crate::data::deckcode::deck::Deck;
|
||||
use crate::data::setbundle::card::{Card, CardIndex};
|
||||
use crate::data::setbundle::keyword::CardKeyword;
|
||||
use crate::data::setbundle::r#type::CardType;
|
||||
|
@ -13,7 +14,6 @@ use crate::data::setbundle::region::CardRegion;
|
|||
use crate::data::setbundle::set::CardSet;
|
||||
use crate::data::setbundle::subtype::CardSubtype;
|
||||
use crate::data::setbundle::supertype::CardSupertype;
|
||||
use crate::data::deckcode::deck::Deck;
|
||||
use itertools::Itertools;
|
||||
use teloxide::utils::html::escape;
|
||||
|
||||
|
@ -158,13 +158,17 @@ fn display_levelup(levelup: &String) -> String {
|
|||
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||
pub fn display_deck(index: &CardIndex, deck: &Deck, code: String) -> String {
|
||||
// TODO: optimize this
|
||||
let cards = deck.contents
|
||||
let cards = deck
|
||||
.contents
|
||||
.keys()
|
||||
.sorted_by(|a, b| {
|
||||
let card_a = index.get(a).expect("card to exist in the index");
|
||||
let card_b = index.get(b).expect("card to exist in the index");
|
||||
|
||||
card_a.cost.cmp(&card_b.cost).then(card_a.name.cmp(&card_b.name))
|
||||
card_a
|
||||
.cost
|
||||
.cmp(&card_b.cost)
|
||||
.then(card_a.name.cmp(&card_b.name))
|
||||
})
|
||||
.map(|k| {
|
||||
let card = index.get(k).expect("card to exist in the index");
|
||||
|
@ -172,8 +176,7 @@ pub fn display_deck(index: &CardIndex, deck: &Deck, code: String) -> String {
|
|||
|
||||
if card.supertype == "Champion" {
|
||||
format!("<b>{}×</b> <u>{}</u>", &quantity, &card.name)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
format!("<b>{}×</b> {}", &quantity, &card.name)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Module providing handlers for @patchedporobot on Telegram.
|
||||
|
||||
use crate::data::deckcode::deck::Deck;
|
||||
use crate::search::cardsearch::CardSearchEngine;
|
||||
use crate::telegram::inline::{card_to_inlinequeryresult, deck_to_inlinequeryresult};
|
||||
use itertools::Itertools;
|
||||
|
@ -9,7 +10,6 @@ use teloxide::payloads::{AnswerInlineQuery, SendMessage};
|
|||
use teloxide::prelude::*;
|
||||
use teloxide::requests::{JsonRequest, ResponseResult};
|
||||
use teloxide::types::{ParseMode, Recipient};
|
||||
use crate::data::deckcode::deck::Deck;
|
||||
|
||||
/// Handle inline queries by searching cards on the [CardSearchEngine].
|
||||
pub fn inline_query_handler(
|
||||
|
@ -37,15 +37,13 @@ pub fn inline_query_handler(
|
|||
debug!("Parsed deck successfully!");
|
||||
break AnswerInlineQuery {
|
||||
inline_query_id: query.id.clone(),
|
||||
results: vec![
|
||||
deck_to_inlinequeryresult(&engine.cards, &deck)
|
||||
],
|
||||
results: vec![deck_to_inlinequeryresult(&engine.cards, &deck)],
|
||||
cache_time: None,
|
||||
is_personal: Some(false),
|
||||
next_offset: None,
|
||||
switch_pm_text: None,
|
||||
switch_pm_parameter: None,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
debug!("Querying the card search engine...");
|
||||
|
|
|
@ -2,15 +2,18 @@
|
|||
//!
|
||||
//! [inline mode]: https://core.telegram.org/bots/api#inline-mode
|
||||
|
||||
use crate::data::corebundle::globals::LocalizedGlobalsIndexes;
|
||||
use crate::data::deckcode::deck::Deck;
|
||||
use crate::data::deckcode::format::DeckCodeFormat;
|
||||
use crate::data::setbundle::card::{Card, CardIndex};
|
||||
use crate::telegram::display::{display_card, display_deck};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::Hash;
|
||||
use std::ptr::hash;
|
||||
use crate::data::corebundle::globals::LocalizedGlobalsIndexes;
|
||||
use crate::data::setbundle::card::{Card, CardIndex};
|
||||
use crate::telegram::display::{display_card, display_deck};
|
||||
use teloxide::types::{InlineQueryResult, InlineQueryResultArticle, InlineQueryResultPhoto, InputMessageContent, InputMessageContentText, ParseMode};
|
||||
use crate::data::deckcode::deck::Deck;
|
||||
use crate::data::deckcode::format::DeckCodeFormat;
|
||||
use teloxide::types::{
|
||||
InlineQueryResult, InlineQueryResultArticle, InlineQueryResultPhoto, InputMessageContent,
|
||||
InputMessageContentText, ParseMode,
|
||||
};
|
||||
|
||||
/// Converts a [Card] into a [InlineQueryResult].
|
||||
pub fn card_to_inlinequeryresult(
|
||||
|
@ -43,9 +46,10 @@ pub fn card_to_inlinequeryresult(
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
pub fn deck_to_inlinequeryresult(index: &CardIndex, deck: &Deck) -> InlineQueryResult {
|
||||
let code = deck.to_code(DeckCodeFormat::F1).expect("serialized deck to deserialize properly");
|
||||
let code = deck
|
||||
.to_code(DeckCodeFormat::F1)
|
||||
.expect("serialized deck to deserialize properly");
|
||||
|
||||
InlineQueryResult::Article(InlineQueryResultArticle {
|
||||
id: format!("{:x}", md5::compute(&code)),
|
||||
|
@ -54,7 +58,7 @@ pub fn deck_to_inlinequeryresult(index: &CardIndex, deck: &Deck) -> InlineQueryR
|
|||
message_text: display_deck(index, deck, code),
|
||||
parse_mode: Some(ParseMode::Html),
|
||||
entities: None,
|
||||
disable_web_page_preview: Some(true)
|
||||
disable_web_page_preview: Some(true),
|
||||
}),
|
||||
reply_markup: None,
|
||||
url: None,
|
||||
|
@ -62,6 +66,6 @@ pub fn deck_to_inlinequeryresult(index: &CardIndex, deck: &Deck) -> InlineQueryR
|
|||
description: None,
|
||||
thumb_url: None,
|
||||
thumb_width: None,
|
||||
thumb_height: None
|
||||
thumb_height: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,10 @@ pub async fn main() {
|
|||
let mut cards: Vec<Card> = vec![];
|
||||
for setpath in setpaths {
|
||||
debug!("Loading {:?}...", &setpath);
|
||||
let set = SetBundle::load(&setpath)
|
||||
.expect(&*format!("to be able to load {:?} as a set bundle", &setpath));
|
||||
let set = SetBundle::load(&setpath).expect(&*format!(
|
||||
"to be able to load {:?} as a set bundle",
|
||||
&setpath
|
||||
));
|
||||
let mut setcards = set.cards;
|
||||
cards.append(&mut setcards);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue