use serde::{Deserialize, Serialize};
use serde_json::Number;
#[derive(Debug, Serialize, Deserialize)]
pub struct Ttrm<'a> {
#[serde(rename = "_id")]
pub id: &'a str,
pub back: &'a str,
pub data: Vec<ReplaySet<'a>>,
#[serde(rename = "forcestyle")]
pub force_style: &'a str,
pub gametype: &'a str,
#[serde(rename = "ismulti")]
pub is_multi: bool,
#[serde(rename = "shortid")]
pub short_id: &'a str,
#[serde(rename = "ts")]
pub timestamp: &'a str,
pub verified: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ReplaySet<'a> {
#[serde(rename = "board", borrow)]
pub boards: Vec<Board<'a>>,
pub replays: Vec<Replay<'a>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Board<'a> {
pub active: bool,
pub success: bool,
#[serde(borrow)]
pub user: User<'a>,
pub winning: Number,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct User<'a> {
#[serde(rename = "_id")]
pub user_id: &'a str,
pub username: &'a str,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Replay<'a> {
#[serde(borrow)]
pub events: Vec<event::Event<'a>>,
pub frames: Number,
}
pub mod event {
use serde::{Deserialize, Serialize};
use serde_json::{Number, Value};
use tagged_hybrid::hybrid_tagged;
#[hybrid_tagged(
fields = {frame: u64},
tag = "type",
struct_attrs = { #[derive(Debug)]}
)]
#[serde(rename_all = "lowercase")]
pub enum Event<'a> {
Start,
Full {
#[serde(rename = "aggregatestats")]
aggregate_stats: AggregateStats,
assumptions: Value,
fire: Number,
game: Game<'a>,
#[serde(rename = "gameoverreason")]
game_over_reason: Option<&'a str>,
killer: Killer<'a>,
options: GameOptions<'a>,
replay: Value, source: Value,
stats: Value,
successful: bool,
targets: Vec<Value>, },
Targets,
KeyDown {
#[serde(flatten)]
key_event: KeyEvent,
},
KeyUp {
#[serde(flatten)]
key_event: KeyEvent,
},
#[serde(rename = "ige")]
InGameEvent {
#[serde(flatten)]
event: InteractionContainer,
},
End,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct InteractionContainer {
pub id: Number,
pub frame: Number,
pub data: Interaction,
}
#[hybrid_tagged(
fields = {
sender: String,
sent_frame: Number,
cid: Number,
},
tag = "type",
struct_attrs = { #[derive(Debug)]}
)]
#[serde(rename_all = "snake_case")]
pub enum Interaction {
#[serde(rename = "interaction")]
InteractionDo {
#[serde(flatten)]
data: Garbage,
},
InteractionConfirm {
#[serde(flatten)]
data: Garbage,
},
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Garbage {
pub amt: Number,
pub x: Number,
pub y: Number,
pub column: Number,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KeyEvent {
pub key: Key,
pub subframe: Number,
pub hoisted: Option<bool>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Key {
#[serde(rename = "hold")]
Hold,
#[serde(rename = "moveLeft")]
Left,
#[serde(rename = "moveRight")]
Right,
#[serde(rename = "rotateCW")]
Clockwise,
#[serde(rename = "rotate180")]
Flip,
#[serde(rename = "rotateCCW")]
CounterClockwise,
#[serde(rename = "softDrop")]
SoftDrop,
#[serde(rename = "hardDrop")]
HardDrop,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct GameOptions<'a> {
#[serde(rename = "allow180")]
pub allow_180: bool,
pub allow_harddrop: bool,
pub are: Number,
#[serde(rename = "b2bchaining")]
pub b2b_chaining: bool,
#[serde(rename = "bagtype")]
pub bag_type: &'a str, #[serde(rename = "boardbuffer")]
pub board_buffer: Number,
#[serde(rename = "boardheight")]
pub board_height: Number,
#[serde(rename = "boardskin")]
pub board_skin: &'a str,
#[serde(rename = "boardwidth")]
pub board_width: Number,
pub clutch: bool,
pub countdown: bool,
pub countdown_count: Number,
pub countdown_interval: Number,
pub display_fire: bool,
pub display_hold: bool,
pub display_next: bool,
pub display_shadow: bool,
pub display_username: bool,
pub forfeit_time: Number,
#[serde(rename = "fullinterval")]
pub full_interval: Number,
#[serde(rename = "fulloffset")]
pub full_offset: Number,
#[serde(rename = "g")]
pub gravity: f64,
#[serde(rename = "garbagecap")]
pub garbage_cap: Number,
#[serde(rename = "garbagecapincrease")]
pub garbage_cap_increase: Number,
#[serde(rename = "garbagecapmax")]
pub garbage_cap_max: Number,
#[serde(rename = "garbageincrease")]
pub garbage_increase: Number,
#[serde(rename = "garbagemargin")]
pub garbage_margin: Number,
#[serde(rename = "garbagemultiplier")]
pub garbage_multiplier: Number,
#[serde(rename = "garbagespeed")]
pub garbage_speed: Number,
#[serde(rename = "ghostskin")]
pub ghost_skin: &'a str,
#[serde(rename = "gincrease")]
pub gravity_increase: f64,
#[serde(rename = "gmargin")]
pub gravity_margin: Number,
pub handling: Handling,
#[serde(rename = "hasgarbage")]
pub has_garbage: bool,
#[serde(rename = "infinitemovement")]
pub infinite_movement: bool,
pub kickset: &'a str,
#[serde(rename = "latencypreference")]
pub latency_preference: &'a str, pub lineclear_are: Number,
#[serde(rename = "lockresets")]
pub lock_resets: Number,
#[serde(rename = "locktime")]
pub lock_time: Number,
pub manual_allowed: bool,
#[serde(rename = "minoskin")]
pub tetromino_skin: TetrominoSkin<'a>,
pub mission: Option<&'a str>,
pub mission_type: &'a str,
#[serde(rename = "neverstopbgm")]
pub loop_bgm: bool,
#[serde(rename = "nextcount")]
pub next_count: Number,
pub objective: Value, #[serde(rename = "onfail")]
pub on_fail: Value, #[serde(rename = "onfinish")]
pub on_finish: Value,
#[serde(rename = "oninteraction")]
pub on_interaction: Value,
pub passthrough: bool,
pub physical: bool,
#[serde(rename = "precountdown")]
pub pre_countdown: Number,
#[serde(rename = "prestart")]
pub pre_start: Number,
pub room_handling: bool,
pub room_handling_arr: Number,
pub room_handling_das: Number,
pub room_handling_sdf: Number,
pub seed: u64,
pub seed_random: bool,
pub slot_bar1: &'a str,
pub slot_counter1: Option<&'a str>,
pub slot_counter2: Option<&'a str>,
pub slot_counter3: Option<&'a str>,
pub slot_counter4: Option<&'a str>,
pub slot_counter5: Option<&'a str>,
#[serde(rename = "spinbonuses")]
pub spin_bonuses: &'a str,
pub stock: Number,
pub username: &'a str,
pub version: Number,
#[serde(rename = "zoominto")]
pub zoom_into: &'a str,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TetrominoSkin<'a> {
i: &'a str,
j: &'a str,
l: &'a str,
o: &'a str,
s: &'a str,
t: &'a str,
z: &'a str,
other: &'a str,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Killer<'a> {
pub name: Option<&'a str>,
#[serde(rename = "type")]
pub kind: &'a str,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AggregateStats {
pub apm: Number,
pub pps: Number,
pub vsscore: Number,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Game<'a> {
pub bag: Vec<&'a str>,
#[serde(borrow)]
pub board: Vec<Vec<Option<&'a str>>>,
pub controlling: Controlling,
#[serde(rename = "g")]
pub gravity: Number,
pub handling: Handling,
pub hold: Hold<'a>,
pub playing: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Hold<'a> {
pub locked: bool,
pub piece: Option<&'a str>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Handling {
pub arr: f64,
pub cancel: bool,
pub das: f64,
pub dcd: f64,
pub safelock: bool,
pub sdf: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Controlling {
#[serde(rename = "lastshift")]
pub last_shift: Number,
pub ldas: Number,
pub ldasiter: Number, pub lshift: bool,
pub rdas: Number,
pub rdasiter: Number, pub rshift: bool,
pub softdrop: bool,
}
}