mirror of
https://github.com/Steffo99/patched-porobot.git
synced 2024-12-23 01:54:22 +00:00
Add CardType::Equipment and rewrite Telegram rendering code
This commit is contained in:
parent
933907cd5f
commit
140a35e6a4
2 changed files with 198 additions and 98 deletions
|
@ -9,6 +9,9 @@ pub enum CardType {
|
||||||
/// A spell.
|
/// A spell.
|
||||||
Spell,
|
Spell,
|
||||||
|
|
||||||
|
/// A equipment.
|
||||||
|
Equipment,
|
||||||
|
|
||||||
/// An unit: either a minion, or a champion.
|
/// An unit: either a minion, or a champion.
|
||||||
///
|
///
|
||||||
/// 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.
|
/// 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.
|
||||||
|
@ -33,6 +36,7 @@ pub enum CardType {
|
||||||
impl From<&CardType> for &'static str {
|
impl From<&CardType> for &'static str {
|
||||||
fn from(r#type: &CardType) -> Self {
|
fn from(r#type: &CardType) -> Self {
|
||||||
match r#type {
|
match r#type {
|
||||||
|
CardType::Equipment => "Equipment",
|
||||||
CardType::Spell => "Spell",
|
CardType::Spell => "Spell",
|
||||||
CardType::Unit => "Unit",
|
CardType::Unit => "Unit",
|
||||||
CardType::Ability => "Ability",
|
CardType::Ability => "Ability",
|
||||||
|
|
|
@ -23,118 +23,163 @@ use teloxide::utils::html::escape;
|
||||||
///
|
///
|
||||||
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
pub fn display_card(globals: &LocalizedGlobalsIndexes, card: &Card) -> String {
|
pub fn display_card(globals: &LocalizedGlobalsIndexes, card: &Card) -> String {
|
||||||
let title = format!("<b><u>{}</u></b>\n", escape(&card.name),);
|
|
||||||
|
|
||||||
let stats = match &card.r#type {
|
let title: String = display_title(&card.name);
|
||||||
CardType::Spell => format!("{} mana\n\n", escape(&card.cost.to_string()),),
|
let r#type: String = display_type(globals, card);
|
||||||
|
let stats = display_stats(card);
|
||||||
|
let subtypes: String = display_subtypes(&card.subtypes);
|
||||||
|
|
||||||
|
let header = format!("{} ({})\n{}\n{}\n", &title, &r#type, &stats, &subtypes);
|
||||||
|
|
||||||
|
let keywords = display_keywords(&card.keywords, &globals.keywords);
|
||||||
|
let description = display_description(&card.localized_description_text);
|
||||||
|
let levelup = display_levelup(&card.localized_levelup_text);
|
||||||
|
|
||||||
|
let body = format!("{}{}{}", &keywords, &description, &levelup);
|
||||||
|
|
||||||
|
let set = display_set(&card.set, &globals.sets);
|
||||||
|
let regions = display_regions(&card.regions, &globals.regions);
|
||||||
|
let flavor = display_flavor(&card.main_art().expect("Card to have at least one illustration").full_png, &card.localized_flavor_text);
|
||||||
|
|
||||||
|
let footer = format!("{}{}\n{}", &set, ®ions, &flavor);
|
||||||
|
|
||||||
|
format!("{}⸻\n\n{}⸻\n\n{}", &header, &body, &footer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render a [Card]'s title in [Telegram Bot HTML].
|
||||||
|
///
|
||||||
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
|
fn display_title(name: &str) -> String {
|
||||||
|
format!("<b><u>{}</u></b>", escape(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the [Card]'s in-game type in [Telegram Bot HTML].
|
||||||
|
///
|
||||||
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
|
fn display_type(globals: &LocalizedGlobalsIndexes, card: &Card) -> String {
|
||||||
|
match card.r#type {
|
||||||
|
CardType::Spell => {
|
||||||
|
"Spell".to_string()
|
||||||
|
}
|
||||||
|
CardType::Equipment => {
|
||||||
|
CardKeyword::Equipment.localized(&globals.keywords).map(|l| l.name.clone()).unwrap_or_else(|| "EQUIPMENT".to_string())
|
||||||
|
}
|
||||||
|
CardType::Unit => {
|
||||||
|
if card.supertype.eq(&CardSupertype::Champion) {
|
||||||
|
"Champion".to_string()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
"Unit".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CardType::Ability => {
|
||||||
|
if card.keywords.contains(&CardKeyword::Skill) {
|
||||||
|
CardKeyword::Skill.localized(&globals.keywords).map(|l| l.name.clone()).unwrap_or_else(|| "SKILL".to_string())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
"Ability".to_string() // Does this exist?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CardType::Landmark => {
|
||||||
|
CardKeyword::Landmark.localized(&globals.keywords).map(|l| l.name.clone()).unwrap_or_else(|| "LANDMARK".to_string())
|
||||||
|
}
|
||||||
|
CardType::Trap => {
|
||||||
|
if card.keywords.contains(&CardKeyword::Trap) {
|
||||||
|
CardKeyword::Trap.localized(&globals.keywords).map(|l| l.name.clone()).unwrap_or_else(|| "TRAP".to_string())
|
||||||
|
}
|
||||||
|
else if card.keywords.contains(&CardKeyword::Boon) {
|
||||||
|
CardKeyword::Boon.localized(&globals.keywords).map(|l| l.name.clone()).unwrap_or_else(|| "Boon".to_string())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
"Trigger".to_string() // Does this exist?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CardType::Unsupported => {
|
||||||
|
"UNKNOWN?".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display_stats(card: &Card) -> String {
|
||||||
|
match &card.r#type {
|
||||||
|
CardType::Spell => format!("{} mana", escape(&card.cost.to_string())),
|
||||||
CardType::Unit => format!(
|
CardType::Unit => format!(
|
||||||
"{} mana {}|{}\n\n",
|
"{} mana · {}|{}",
|
||||||
escape(&card.cost.to_string()),
|
escape(&card.cost.to_string()),
|
||||||
escape(&card.attack.to_string()),
|
escape(&card.attack.to_string()),
|
||||||
escape(&card.health.to_string()),
|
escape(&card.health.to_string()),
|
||||||
),
|
),
|
||||||
CardType::Landmark => format!("{} mana\n\n", &card.cost),
|
CardType::Landmark => format!("{} mana", &card.cost),
|
||||||
_ => "".to_string(),
|
_ => "".to_string(),
|
||||||
};
|
}
|
||||||
|
|
||||||
let set = display_set(&card.set, &globals.sets);
|
|
||||||
let regions = display_regions(&card.regions, &globals.regions);
|
|
||||||
let r#type = display_types(&card.r#type, &card.supertype, &card.subtypes);
|
|
||||||
|
|
||||||
let breadcrumbs = format!("{} › {} › {}\n\n", &set, ®ions, &r#type);
|
|
||||||
|
|
||||||
let keywords = display_keywords(&card.keywords, &globals.keywords);
|
|
||||||
|
|
||||||
let description = display_description(&card.localized_description_text);
|
|
||||||
let levelup = display_levelup(&card.localized_levelup_text);
|
|
||||||
|
|
||||||
let flavor = format!("<i>{}</i>\n", escape(&card.localized_flavor_text));
|
|
||||||
|
|
||||||
let artist = format!(
|
|
||||||
r#"<a href="{}">Illustration</a> by {}"#,
|
|
||||||
&card
|
|
||||||
.main_art()
|
|
||||||
.expect("Card to have at least one illustration")
|
|
||||||
.full_png,
|
|
||||||
escape(&card.artist_name)
|
|
||||||
);
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"{}{}{}{}{}{}-----\n{}{}",
|
|
||||||
&title, &breadcrumbs, &keywords, &stats, &description, &levelup, &flavor, &artist,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render a [CardSet] in [Telegram Bot HTML].
|
/// Render the [CardSubtype]s in [Telegram Bot HTML].
|
||||||
///
|
///
|
||||||
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
fn display_set(set: &CardSet, hm: &LocalizedCardSetIndex) -> String {
|
fn display_subtypes(subtypes: &[CardSubtype]) -> String {
|
||||||
format!(
|
let result = subtypes
|
||||||
"<i>{}</i>",
|
|
||||||
set.localized(hm)
|
|
||||||
.map(|o| format!("<i>{}</i>", escape(&o.name)))
|
|
||||||
.unwrap_or_else(|| "Unknown".to_string())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render a slice of [CardRegion]s in [Telegram Bot HTML].
|
|
||||||
///
|
|
||||||
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
|
||||||
fn display_regions(regions: &[CardRegion], hm: &LocalizedCardRegionIndex) -> String {
|
|
||||||
regions
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|region| {
|
.map(|s| titlecase(&s))
|
||||||
region
|
.map(|s| escape(&s))
|
||||||
.localized(hm)
|
.map(|s| format!("<i>{s}</i>"))
|
||||||
.map(|o| format!("<i>{}</i>", escape(&o.name)))
|
.join(", ");
|
||||||
.unwrap_or_else(|| "Unknown".to_string())
|
|
||||||
})
|
|
||||||
.join(", ")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render the [CardType], the [CardSupertype] and the [CardSubtype]s in [Telegram Bot HTML].
|
|
||||||
///
|
|
||||||
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
|
||||||
fn display_types(r#type: &CardType, supertype: &CardSupertype, subtypes: &[CardSubtype]) -> String {
|
|
||||||
let mut result = String::new();
|
|
||||||
|
|
||||||
result.push_str(
|
|
||||||
match supertype {
|
|
||||||
CardSupertype::Champion => "<i>Champion</i> › ",
|
|
||||||
CardSupertype::Unsupported => "<i>Unknown</i> › ",
|
|
||||||
_ => "",
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
result.push_str(&format!("<i>{}</i>", escape(&String::from(r#type)),));
|
|
||||||
|
|
||||||
if !subtypes.is_empty() {
|
|
||||||
result.push_str(&format!(
|
|
||||||
" › {}",
|
|
||||||
subtypes
|
|
||||||
.iter()
|
|
||||||
.map(|subtype| format!("<i>{}</i>", escape(subtype)))
|
|
||||||
.join(", ")
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if result.is_empty() {
|
||||||
result
|
result
|
||||||
|
} else {
|
||||||
|
result + "\n"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render a slice of [CardKeyword]s in [Telegram Bot HTML].
|
/// Render a slice of [CardKeyword]s in [Telegram Bot HTML].
|
||||||
///
|
///
|
||||||
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
fn display_keywords(keywords: &[CardKeyword], hm: &LocalizedCardKeywordIndex) -> String {
|
fn display_keywords(keywords: &[CardKeyword], hm: &LocalizedCardKeywordIndex) -> String {
|
||||||
format!(
|
let result = keywords
|
||||||
"{}\n",
|
|
||||||
keywords
|
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter(|keyword| match keyword {
|
||||||
|
CardKeyword::Countdown => false,
|
||||||
|
CardKeyword::OnPlay => false,
|
||||||
|
CardKeyword::Landmark => false,
|
||||||
|
CardKeyword::Shurima => false,
|
||||||
|
CardKeyword::Noxus => false,
|
||||||
|
CardKeyword::ClobberNoEmptySlotRequirement => false,
|
||||||
|
CardKeyword::Nab => false,
|
||||||
|
CardKeyword::Enlightened => false,
|
||||||
|
CardKeyword::Invoke => false,
|
||||||
|
CardKeyword::Drain => false,
|
||||||
|
CardKeyword::LastBreath => false,
|
||||||
|
CardKeyword::Demacia => false,
|
||||||
|
CardKeyword::BandleCity => false,
|
||||||
|
CardKeyword::Bilgewater => false,
|
||||||
|
CardKeyword::Runeterra => false,
|
||||||
|
CardKeyword::Recall => false,
|
||||||
|
CardKeyword::Weakest => false,
|
||||||
|
CardKeyword::Support => false,
|
||||||
|
CardKeyword::Obliterate => false,
|
||||||
|
CardKeyword::Imbue => false,
|
||||||
|
CardKeyword::Targon => false,
|
||||||
|
CardKeyword::ShadowIsles => false,
|
||||||
|
CardKeyword::AuraVisualFakeKeyword => false,
|
||||||
|
CardKeyword::Ionia => false,
|
||||||
|
CardKeyword::PiltoverZaun => false,
|
||||||
|
CardKeyword::SilenceIndividualKeyword => false,
|
||||||
|
CardKeyword::Plunder => false,
|
||||||
|
CardKeyword::Silenced => false,
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
.map(|keyword| keyword
|
.map(|keyword| keyword
|
||||||
.localized(hm)
|
.localized(hm)
|
||||||
.map(|o| format!("[<b>{}</b>]", escape(&o.name)))
|
.map(|o| format!("[<b>{}</b>: {}]\n", escape(&o.name), escape(&o.description)))
|
||||||
.unwrap_or_else(|| "Unknown".to_string()))
|
.unwrap_or_else(|| "[<b>UNKNOWN?</b>]\n".to_string()))
|
||||||
.join(" ")
|
.join("");
|
||||||
)
|
|
||||||
|
if result.is_empty() {
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
result + "\n"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render a [Card::localized_description_text] in [Telegram Bot HTML].
|
/// Render a [Card::localized_description_text] in [Telegram Bot HTML].
|
||||||
|
@ -159,6 +204,46 @@ fn display_levelup(levelup: &String) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Render a [CardSet] in [Telegram Bot HTML].
|
||||||
|
///
|
||||||
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
|
fn display_set(set: &CardSet, hm: &LocalizedCardSetIndex) -> String {
|
||||||
|
format!(
|
||||||
|
"<i>{}</i>",
|
||||||
|
set.localized(hm)
|
||||||
|
.map(|o| format!("<i>{}</i>", escape(&o.name)))
|
||||||
|
.unwrap_or_else(|| "UNKNOWN?".to_string())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render a slice of [CardRegion]s in [Telegram Bot HTML].
|
||||||
|
///
|
||||||
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
|
fn display_regions(regions: &[CardRegion], hm: &LocalizedCardRegionIndex) -> String {
|
||||||
|
let result = regions
|
||||||
|
.iter()
|
||||||
|
.map(|region| {
|
||||||
|
region
|
||||||
|
.localized(hm)
|
||||||
|
.map(|o| format!("<u>{}</u>", escape(&o.name)))
|
||||||
|
.unwrap_or_else(|| "UNKNOWN?".to_string())
|
||||||
|
})
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
|
if result.is_empty() {
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
format!(" · {}", &result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the flavor text of a [Card] in [Telegram Bot HTML], linking to the given art.
|
||||||
|
///
|
||||||
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
|
fn display_flavor(art_url: &str, localized_flavor_text: &str) -> String {
|
||||||
|
format!("<a href=\"{}\"><i>{}</i></a>", &art_url, escape(localized_flavor_text))
|
||||||
|
}
|
||||||
|
|
||||||
/// Render a [Deck] in [Telegram Bot HTML], with an optional `name`.
|
/// Render a [Deck] in [Telegram Bot HTML], with an optional `name`.
|
||||||
///
|
///
|
||||||
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
/// [Telegram Bot HTML]: https://core.telegram.org/bots/api#html-style
|
||||||
|
@ -205,7 +290,7 @@ pub fn display_deck(index: &CardIndex, deck: &Deck, code: &str, name: &Option<&s
|
||||||
let mut tags: Vec<&'static str> = vec![];
|
let mut tags: Vec<&'static str> = vec![];
|
||||||
|
|
||||||
let regions = if let Some(regions) = deck.standard(index) {
|
let regions = if let Some(regions) = deck.standard(index) {
|
||||||
tags.push("#Standard_4_3");
|
tags.push("#Standard_4_5");
|
||||||
regions
|
regions
|
||||||
} else if let Some(regions) = deck.eternal(index) {
|
} else if let Some(regions) = deck.eternal(index) {
|
||||||
tags.push("#Eternal");
|
tags.push("#Eternal");
|
||||||
|
@ -245,3 +330,14 @@ pub fn display_deck(index: &CardIndex, deck: &Deck, code: &str, name: &Option<&s
|
||||||
None => format!("<code>{}</code>\n{}\n{}", &code, &tags, &cards),
|
None => format!("<code>{}</code>\n{}\n{}", &code, &tags, &cards),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/38406885/4334568
|
||||||
|
fn titlecase(s: &str) -> String {
|
||||||
|
let s = s.to_lowercase();
|
||||||
|
let mut c = s.chars();
|
||||||
|
match c.next() {
|
||||||
|
None => String::new(),
|
||||||
|
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue