deserlize all cards

This commit is contained in:
kageru 2023-01-26 15:04:39 +01:00
parent 97aa161166
commit 91a56a77dc
5 changed files with 609831 additions and 403 deletions

272
Cargo.lock generated
View File

@ -6,59 +6,8 @@ version = 3
name = "aro"
version = "0.1.0"
dependencies = [
"crossterm",
"serde",
"serde_json",
"tui",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cassowary"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossterm"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
dependencies = [
"bitflags",
"crossterm_winapi",
"libc",
"mio",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c"
dependencies = [
"winapi",
]
[[package]]
@ -67,66 +16,6 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
[[package]]
name = "libc"
version = "0.2.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "mio"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
]
[[package]]
name = "proc-macro2"
version = "1.0.47"
@ -145,27 +34,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.147"
@ -197,42 +71,6 @@ dependencies = [
"serde",
]
[[package]]
name = "signal-hook"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "syn"
version = "1.0.103"
@ -244,118 +82,8 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "tui"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccdd26cbd674007e649a272da4475fb666d3aa0ad0531da7136db6fab0e5bad1"
dependencies = [
"bitflags",
"cassowary",
"crossterm",
"unicode-segmentation",
"unicode-width",
]
[[package]]
name = "unicode-ident"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "unicode-segmentation"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
[[package]]
name = "unicode-width"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"

View File

@ -6,5 +6,3 @@ edition = "2021"
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tui = "0.19.0"
crossterm = "0.25.0"

File diff suppressed because one or more lines are too long

609680
cards.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,149 +1,172 @@
use crossterm::terminal::enable_raw_mode;
use serde::Deserialize;
use std::{io, iter, time::Duration};
use tui::{
backend::CrosstermBackend,
layout,
style::{Color, Style},
text::Text,
widgets::{Block, Borders, List, ListItem, Paragraph, Widget},
};
type Terminal = tui::Terminal<CrosstermBackend<io::Stdout>>;
use serde::{de::Visitor, Deserialize, Deserializer};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let stdout = io::stdout();
enable_raw_mode()?;
let mut backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
terminal.hide_cursor()?;
terminal.clear()?;
let all_cards= vec![
Card::SpellCard {
name: "The Cheerful Coffin".to_owned(),
text: "Discard up to 3 Monster Cards from your hand to the Graveyard.".to_owned()
},
Card::EffectMonster {
name: "Des Lacooda".to_owned(),
effect: "Once per turn: You can change this card to face-down Defense Position. When this card is Flip Summoned: Draw 1 card.".to_owned(),
atk: 500,
def: 600,
level: 3,
r#type: "Zombie".to_owned(),
attribute: "EARTH".to_owned(),
let cards: CardInfo =
serde_json::from_reader(std::io::BufReader::new(std::fs::File::open("cards.json")?))?;
println!("{} cards read", cards.data.len());
Ok(())
}
#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
struct CardInfo {
data: Vec<Card>,
}
#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
struct CardBase {
//#[serde(rename = "type", deserialize_with = "split_types")]
//card_type: Vec<String>,
name: String,
#[serde(rename = "desc")]
text: String,
}
fn split_types<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<String>, D::Error> {
struct SplittingVisitor;
impl<'de> Visitor<'de> for SplittingVisitor {
type Value = Vec<String>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a string")
}
];
let mut cards = all_cards.clone();
let mut search_text = String::new();
loop {
refresh(&mut terminal, &cards, &search_text);
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
Ok(v.split_whitespace()
.filter(|t| t != &"Card")
.map(str::to_owned)
.collect())
}
}
Ok(())
deserializer.deserialize_any(SplittingVisitor)
}
fn refresh(term: &mut Terminal, cards: &Vec<Card>, search_text: &str) -> Result<(), io::Error> {
let mut list = selectable_list(
search_text,
cards
.iter()
.map(|c| ListItem::new(format!("{c:?}")))
.collect::<Vec<_>>(),
None,
);
term.draw(|mut frame| {
frame.render_widget(list, frame.size());
})?;
Ok(())
}
pub fn selectable_list<'a>(
title: &'a str,
content: Vec<ListItem<'a>>,
selected: Option<usize>,
) -> List<'a> {
List::new(content)
.block(
Block::default()
.title(title)
.borders(Borders::TOP | Borders::RIGHT | Borders::LEFT),
)
.highlight_style(Style::default().fg(Color::LightGreen))
.highlight_symbol(">")
#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
struct Monster {
// None for ?
atk: Option<i32>,
attribute: String,
#[serde(rename = "race")]
r#type: String,
// None for ? or link monsters
def: Option<i32>,
// also includes rank
level: Option<u8>,
}
#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
#[serde(tag = "type")]
enum Card {
#[serde(rename = "Spell Card")]
SpellCard {
name: String,
#[serde(rename = "desc")]
text: String,
#[serde(alias = "Spell Card", alias = "Trap Card")]
Backrow {
#[serde(flatten)]
base: CardBase,
},
#[serde(rename = "Skill Card")]
Skill {
#[serde(flatten)]
base: CardBase,
},
#[serde(
rename = "Effect Monster",
alias = "Effect Monster",
alias = "Flip Effect Monster",
alias = "Union Effect Monster"
alias = "Fusion Monster",
alias = "Gemini Monster",
alias = "Link Monster",
alias = "Normal Monster",
alias = "Normal Tuner Monster",
alias = "Pendulum Effect Fusion Monster",
alias = "Pendulum Effect Monster",
alias = "Pendulum Effect Ritual Monster",
alias = "Pendulum Flip Effect Monster",
alias = "Pendulum Normal Monster",
alias = "Pendulum Tuner Effect Monster",
alias = "Ritual Effect Monster",
alias = "Ritual Monster",
alias = "Spirit Monster",
alias = "Synchro Monster",
alias = "Synchro Pendulum Effect Monster",
alias = "Synchro Tuner Monster",
alias = "Token",
alias = "Toon Monster",
alias = "Tuner Monster",
alias = "Union Effect Monster",
alias = "XYZ Monster",
alias = "XYZ Pendulum Effect Monster"
)]
EffectMonster {
name: String,
#[serde(rename = "desc")]
effect: String,
atk: i32,
def: i32,
level: i32,
attribute: String,
#[serde(rename = "race")]
r#type: String,
Monster {
#[serde(flatten)]
base: CardBase,
#[serde(flatten)]
monster: Monster,
#[serde(default, rename = "linkval")]
link_rating: u8,
#[serde(default)]
linkmarkers: Vec<String>,
},
}
#[test]
fn test_spell() {
let s = r#"
{
"id": 41142615,
"name": "The Cheerful Coffin",
"type": "Spell Card",
"desc": "Discard up to 3 Monster Cards from your hand to the Graveyard.",
"race": "Normal"
}"#;
let coffin: Card = serde_json::from_str(s).unwrap();
assert_eq!(
coffin,
Card::SpellCard {
name: "The Cheerful Coffin".to_owned(),
text: "Discard up to 3 Monster Cards from your hand to the Graveyard.".to_owned()
}
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_monster() {
let s = r#"
{
"id": 2326738,
"name": "Des Lacooda",
"type": "Effect Monster",
"desc": "Once per turn: You can change this card to face-down Defense Position. When this card is Flip Summoned: Draw 1 card.",
"atk": 500,
"def": 600,
"level": 3,
"race": "Zombie",
"attribute": "EARTH"
}"#;
let munch: Card = serde_json::from_str(s).unwrap();
assert_eq!(
munch,
Card::EffectMonster {
name: "Des Lacooda".to_owned(),
effect: "Once per turn: You can change this card to face-down Defense Position. When this card is Flip Summoned: Draw 1 card.".to_owned(),
atk: 500,
def: 600,
level: 3,
r#type: "Zombie".to_owned(),
attribute: "EARTH".to_owned(),
}
)
#[test]
fn test_spell() {
let s = r#"
{
"id": 41142615,
"name": "The Cheerful Coffin",
"type": "Spell Card",
"desc": "Discard up to 3 Monster Cards from your hand to the Graveyard.",
"race": "Normal"
}"#;
let coffin: Card = serde_json::from_str(s).unwrap();
assert_eq!(
coffin,
Card::Backrow {
base: CardBase {
card_type: vec!["Spell".to_owned()],
name: "The Cheerful Coffin".to_owned(),
text: "Discard up to 3 Monster Cards from your hand to the Graveyard."
.to_owned()
}
}
)
}
#[test]
fn test_monster() {
let s = r#"
{
"id": 2326738,
"name": "Des Lacooda",
"type": "Effect Monster",
"desc": "Once per turn: You can change this card to face-down Defense Position. When this card is Flip Summoned: Draw 1 card.",
"atk": 500,
"def": 600,
"level": 3,
"race": "Zombie",
"attribute": "EARTH"
}"#;
let munch: Card = serde_json::from_str(s).unwrap();
assert_eq!(
munch,
Card::Monster {
base: CardBase {
card_type: vec!["Effect".to_owned(), "Monster".to_owned()],
name: "Des Lacooda".to_owned(),
text: "Once per turn: You can change this card to face-down Defense Position. When this card is Flip Summoned: Draw 1 card.".to_owned(),
},
monster: Monster {
atk: Some(500),
def: Some(600),
level: Some(3),
r#type: "Zombie".to_owned(),
attribute: "EARTH".to_owned(),
},
link_rating: 0,
linkmarkers: vec![]
},
)
}
}