initial commit
This commit is contained in:
commit
a2f8f404af
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "aro"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde_json = "1.0"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
1
cardinfo.php
Normal file
1
cardinfo.php
Normal file
File diff suppressed because one or more lines are too long
247
src/main.rs
Normal file
247
src/main.rs
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tui_realm_stdlib::List;
|
||||||
|
use tuirealm::{
|
||||||
|
event::{Key, KeyEvent},
|
||||||
|
props::TextSpan,
|
||||||
|
terminal::TerminalBridge,
|
||||||
|
tui::layout::{Constraint, Layout},
|
||||||
|
Application, Component, Event, EventListenerCfg, MockComponent, NoUserEvent, PollStrategy,
|
||||||
|
Update,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut app: Application<Id, Msg, NoUserEvent> = Application::init(
|
||||||
|
EventListenerCfg::default()
|
||||||
|
.default_input_listener(Duration::from_millis(20))
|
||||||
|
.poll_timeout(Duration::from_millis(10)),
|
||||||
|
);
|
||||||
|
app.mount(Id::MainList, Box::new(MyList {
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
..Default::default()
|
||||||
|
}), vec![])
|
||||||
|
.unwrap();
|
||||||
|
app.active(&Id::MainList).unwrap();
|
||||||
|
let model = Model {
|
||||||
|
app,
|
||||||
|
quit: false,
|
||||||
|
redraw: true,
|
||||||
|
terminal: TerminalBridge::new().unwrap(),
|
||||||
|
state: State::default(),
|
||||||
|
};
|
||||||
|
model.terminal.enter_alternate_screen();
|
||||||
|
model.terminal.enable_raw_mode();
|
||||||
|
|
||||||
|
while !model.quit {
|
||||||
|
match app.tick(PollStrategy::Once) {
|
||||||
|
Ok(messages) if messages.len() > 0 => {
|
||||||
|
model.redraw = true;
|
||||||
|
for msg in messages.into_iter() {
|
||||||
|
model.update(Some(msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if model.redraw {
|
||||||
|
model.view(&mut app);
|
||||||
|
model.redraw = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model.terminal.leave_alternate_screen();
|
||||||
|
model.terminal.disable_raw_mode();
|
||||||
|
model.terminal.clear_screen();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum Msg {
|
||||||
|
Quit,
|
||||||
|
SearchInput(char),
|
||||||
|
SearchClear,
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
Increment,
|
||||||
|
Decrement,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Hash, Clone, Copy, Eq)]
|
||||||
|
enum Id {
|
||||||
|
MainList,
|
||||||
|
SearchField,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(MockComponent, Default)]
|
||||||
|
struct MyList {
|
||||||
|
component: List,
|
||||||
|
cards: Vec<Card>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component<Msg, NoUserEvent> for MyList {
|
||||||
|
fn on(&mut self, ev: tuirealm::Event<NoUserEvent>) -> Option<Msg> {
|
||||||
|
match ev {
|
||||||
|
Event::Keyboard(KeyEvent {
|
||||||
|
code: Key::Char(ch),
|
||||||
|
..
|
||||||
|
}) => match ch {
|
||||||
|
'+' => Some(Msg::Increment),
|
||||||
|
'-' => Some(Msg::Decrement),
|
||||||
|
ch => {
|
||||||
|
self.component = self.component
|
||||||
|
.rows(
|
||||||
|
self.cards
|
||||||
|
.iter()
|
||||||
|
.map(|c| {
|
||||||
|
vec![TextSpan::new(match c {
|
||||||
|
Card::SpellCard { name, .. } => name,
|
||||||
|
Card::EffectMonster { name, .. } => name,
|
||||||
|
})]
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
Some(Msg::SearchInput(ch))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => Some(Msg::Quit),
|
||||||
|
Event::Keyboard(KeyEvent {
|
||||||
|
code: Key::Backspace,
|
||||||
|
..
|
||||||
|
}) => Some(Msg::SearchClear),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Model {
|
||||||
|
state: State,
|
||||||
|
app: Application<Id, Msg, NoUserEvent>,
|
||||||
|
terminal: TerminalBridge,
|
||||||
|
quit: bool,
|
||||||
|
redraw: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Model {
|
||||||
|
pub fn view(&mut self, app: &mut Application<Id, Msg, NoUserEvent>) {
|
||||||
|
self.terminal
|
||||||
|
.raw_mut()
|
||||||
|
.draw(|f| {
|
||||||
|
let chunks = Layout::default()
|
||||||
|
.constraints([Constraint::Percentage(100)])
|
||||||
|
.split(f.size());
|
||||||
|
app.view(&Id::MainList, f, chunks[0]);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Update<Msg> for Model {
|
||||||
|
fn update(&mut self, msg: Option<Msg>) -> Option<Msg> {
|
||||||
|
self.redraw = true;
|
||||||
|
match msg {
|
||||||
|
Some(Msg::SearchInput(c)) => self.state.filter.push(c),
|
||||||
|
Some(Msg::SearchClear) => self.state.filter.clear(),
|
||||||
|
Some(Msg::Quit) => self.quit = true,
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Default, Debug)]
|
||||||
|
struct State {
|
||||||
|
filter: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ApiResponse {
|
||||||
|
data: Vec<Card>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq, Eq)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
enum Card {
|
||||||
|
#[serde(rename = "Spell Card")]
|
||||||
|
SpellCard {
|
||||||
|
name: String,
|
||||||
|
#[serde(rename = "desc")]
|
||||||
|
text: String,
|
||||||
|
},
|
||||||
|
#[serde(
|
||||||
|
rename = "Effect Monster",
|
||||||
|
alias = "Flip Effect Monster",
|
||||||
|
alias = "Union Effect Monster"
|
||||||
|
)]
|
||||||
|
EffectMonster {
|
||||||
|
name: String,
|
||||||
|
#[serde(rename = "desc")]
|
||||||
|
effect: String,
|
||||||
|
atk: i32,
|
||||||
|
def: i32,
|
||||||
|
level: i32,
|
||||||
|
attribute: String,
|
||||||
|
#[serde(rename = "race")]
|
||||||
|
r#type: 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()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user