licheszter/models/
game.rs

1use crate::models::user::{LightUser, MinimalUser, PerfType};
2use serde::{Deserialize, Serialize};
3use serde_with::{TimestampMilliSeconds, serde_as, skip_serializing_none};
4use time::PrimitiveDateTime;
5
6use super::{challenge::ChallengeSource, user::Title};
7
8#[skip_serializing_none]
9#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
10#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
11pub struct PlayerAnalysis {
12    pub inaccuracy: u16,
13    pub mistake: u16,
14    pub blunder: u16,
15    pub acpl: u16,
16    pub accuracy: Option<u16>,
17}
18
19#[skip_serializing_none]
20#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
21#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
22#[serde(rename_all = "camelCase")]
23pub struct Entity {
24    pub user: MinimalUser,
25    pub rating: u16,
26    pub rating_diff: Option<i16>,
27    pub name: Option<String>,
28    #[serde(default)]
29    pub provisional: bool,
30    pub analysis: Option<PlayerAnalysis>,
31    pub team: Option<String>,
32}
33
34#[skip_serializing_none]
35#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
36#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
37pub struct Computer {
38    #[serde(rename = "aiLevel")]
39    pub ai_level: u8,
40    pub analysis: Option<PlayerAnalysis>,
41}
42
43#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
44#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
45#[serde(untagged)]
46pub enum Player {
47    Entity(Box<Entity>),
48    Computer(Computer),
49}
50
51#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
52#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
53pub struct Players {
54    pub white: Player,
55    pub black: Player,
56}
57
58#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
59#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
60pub struct Opening {
61    pub eco: String,
62    pub name: String,
63    pub ply: u16,
64}
65
66#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
67#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
68#[serde(rename_all = "camelCase")]
69#[serde(tag = "type")]
70pub enum TimeControl {
71    Clock {
72        limit: u16,
73        increment: u16,
74        show: String,
75    },
76    Correspondence {
77        #[serde(rename = "daysPerTurn")]
78        days_per_turn: u8,
79    },
80    Unlimited,
81}
82
83#[skip_serializing_none]
84#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
85#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
86pub struct Clock {
87    pub initial: u32,
88    pub increment: u32,
89    #[serde(rename = "totalTime")]
90    pub total_time: Option<u32>,
91}
92
93#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
94#[serde(rename_all = "camelCase")]
95pub enum Speed {
96    UltraBullet,
97    Bullet,
98    Blitz,
99    Rapid,
100    Classical,
101    Correspondence,
102}
103
104#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
105#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
106pub struct Judgement {
107    pub name: JudgementTier,
108    pub comment: String,
109}
110
111#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
112#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
113pub enum JudgementTier {
114    Inaccuracy,
115    Mistake,
116    Blunder,
117}
118
119#[skip_serializing_none]
120#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
121#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
122pub struct MoveAnalysis {
123    pub mate: Option<u8>,
124    pub eval: Option<i16>,
125    pub best: Option<String>,
126    pub variation: Option<String>,
127    pub judgment: Option<Judgement>,
128}
129
130#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
131#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
132pub struct Division {
133    pub middle: u16,
134    pub end: u16,
135}
136
137#[serde_as]
138#[skip_serializing_none]
139#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
140#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
141#[serde(rename_all = "camelCase")]
142pub struct Game {
143    pub id: String,
144    pub rated: bool,
145    pub variant: VariantMode,
146    pub speed: Speed,
147    pub perf: PerfType,
148    #[serde_as(as = "TimestampMilliSeconds")]
149    pub created_at: PrimitiveDateTime,
150    #[serde_as(as = "TimestampMilliSeconds")]
151    pub last_move_at: PrimitiveDateTime,
152    pub status: GameStatus,
153    pub source: Option<String>,
154    pub players: Players,
155    pub initial_fen: Option<String>,
156    pub winner: Option<FinalColor>,
157    pub opening: Option<Opening>,
158    pub moves: Option<String>,
159    pub days_per_turn: Option<u8>,
160    #[serde(default)]
161    pub analysis: Vec<MoveAnalysis>,
162    pub tournament: Option<String>,
163    pub swiss: Option<String>,
164    pub clock: Option<Clock>,
165    #[serde(default)]
166    pub clocks: Vec<u16>,
167    pub division: Option<Division>,
168}
169
170#[skip_serializing_none]
171#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
172#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
173pub struct GameState {
174    // This field is useless and only present to prevent errors
175    #[serde(skip_serializing)]
176    r#type: Option<String>,
177    pub moves: String,
178    pub wtime: u64,
179    pub btime: u64,
180    pub winc: u32,
181    pub binc: u32,
182    #[serde(default)]
183    pub wdraw: bool,
184    #[serde(default)]
185    pub bdraw: bool,
186    #[serde(default)]
187    pub wtakeback: bool,
188    #[serde(default)]
189    pub btakeback: bool,
190    pub status: GameStatus,
191    pub winner: Option<Color>,
192}
193
194#[skip_serializing_none]
195#[serde_as]
196#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
197#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
198#[serde(rename_all = "camelCase")]
199pub struct GameFull {
200    pub id: String,
201    pub rated: bool,
202    pub variant: Variant,
203    pub clock: Option<Clock>,
204    pub days_per_turn: Option<u8>,
205    pub speed: Speed,
206    pub perf: Perf,
207    #[serde_as(as = "TimestampMilliSeconds")]
208    pub created_at: PrimitiveDateTime,
209    pub white: GameEventPlayer,
210    pub black: GameEventPlayer,
211    pub initial_fen: String,
212    pub state: GameState,
213    pub tournament_id: Option<String>,
214}
215
216#[skip_serializing_none]
217#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
218#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
219pub struct OpponentGone {
220    pub gone: bool,
221    #[serde(rename = "claimWinInSeconds")]
222    pub claim_win_in_seconds: Option<u8>,
223}
224
225#[skip_serializing_none]
226#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
227#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
228pub struct Variant {
229    pub key: VariantMode,
230    pub short: Option<String>,
231    pub name: String,
232}
233
234#[skip_serializing_none]
235#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
236#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
237pub struct Perf {
238    pub icon: Option<String>,
239    pub key: Option<String>,
240    pub name: String,
241    pub position: Option<u8>,
242}
243
244#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
245#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
246pub struct UserGames {
247    #[serde(rename = "nowPlaying")]
248    pub now_playing: Vec<UserGame>,
249}
250
251#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
252#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
253#[serde(rename_all = "camelCase")]
254pub struct UserGame {
255    pub full_id: String,
256    pub game_id: String,
257    pub fen: String,
258    pub color: Color,
259    pub last_move: String,
260    pub source: String,
261    pub variant: Variant,
262    pub speed: String,
263    pub perf: PerfType,
264    pub rated: bool,
265    pub has_moved: bool,
266    pub opponent: LightUser,
267    pub is_my_turn: bool,
268    pub seconds_left: Option<u32>,
269    pub status: FullGameStatus,
270}
271
272#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
273#[serde(rename_all = "camelCase")]
274pub enum VariantMode {
275    Standard,
276    Chess960,
277    Crazyhouse,
278    Antichess,
279    Atomic,
280    Horde,
281    KingOfTheHill,
282    RacingKings,
283    ThreeCheck,
284    FromPosition,
285}
286
287#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
288#[serde(rename_all = "camelCase")]
289pub enum Color {
290    Black,
291    Random,
292    White,
293}
294
295#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
296#[serde(rename_all = "camelCase")]
297pub enum FinalColor {
298    Black,
299    White,
300}
301
302#[skip_serializing_none]
303#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
304#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
305pub struct GameEventPlayer {
306    #[serde(rename = "aiLevel")]
307    pub ai_level: Option<u8>,
308    pub id: String,
309    pub name: String,
310    pub title: Option<Title>,
311    pub rating: u16,
312    #[serde(default)]
313    pub provisional: bool,
314}
315
316#[skip_serializing_none]
317#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
318#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
319#[serde(rename_all = "camelCase")]
320pub struct GameEventInfo {
321    pub id: String,
322    pub full_id: String,
323    pub game_id: String,
324    pub fen: String,
325    pub color: Color,
326    pub last_move: String,
327    pub source: ChallengeSource,
328    pub variant: Variant,
329    pub speed: Speed,
330    pub perf: String,
331    pub rated: bool,
332    pub has_moved: bool,
333    pub opponent: LightUser,
334    pub is_my_turn: bool,
335    pub seconds_left: Option<u32>,
336    pub status: FullGameStatus,
337    pub compat: Option<GameCompatibility>,
338}
339
340#[repr(u8)]
341#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
342#[serde(rename_all = "camelCase")]
343pub enum CorrespondenceDays {
344    One = 1,
345    Two = 2,
346    Three = 3,
347    Five = 5,
348    Seven = 7,
349    Ten = 10,
350    Fourteen = 14,
351}
352
353#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
354#[serde(rename_all = "camelCase")]
355pub enum Rules {
356    NoAbort,
357    NoRematch,
358    NoGiveTime,
359    NoClaimWin,
360    NoEarlyDraw,
361}
362
363#[repr(u8)]
364#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
365#[serde(rename_all = "camelCase")]
366pub enum AILevel {
367    One = 1,
368    Two = 2,
369    Three = 3,
370    Four = 4,
371    Five = 5,
372    Six = 6,
373    Seven = 7,
374    Eight = 8,
375}
376
377#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
378#[serde(rename_all = "camelCase")]
379pub enum GameType {
380    Casual,
381    Rated,
382}
383
384#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
385#[serde(rename_all = "camelCase")]
386pub enum GameStatus {
387    Created,
388    Started,
389    Aborted,
390    Mate,
391    Resign,
392    Stalemate,
393    Timeout,
394    Draw,
395    #[serde(rename = "outoftime")]
396    OutOfTime,
397    Cheat,
398    NoStart,
399    UnknownFinish,
400    InsufficientMaterialClaim,
401    VariantEnd,
402}
403
404#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
405#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
406pub struct FullGameStatus {
407    pub id: u8,
408    pub name: GameStatus,
409}
410
411#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
412#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
413pub struct GameCompatibility {
414    pub bot: bool,
415    pub board: bool,
416}
417
418#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
419#[cfg_attr(feature = "serde-strict", serde(deny_unknown_fields))]
420#[serde(rename_all = "camelCase")]
421pub struct GameCount {
422    pub all: u32,
423    pub rated: u32,
424    #[serde(default)]
425    pub ai: u32,
426    pub draw: u32,
427    #[serde(default)]
428    pub draw_h: u32,
429    pub loss: u32,
430    #[serde(default)]
431    pub loss_h: u32,
432    pub win: u32,
433    #[serde(default)]
434    pub win_h: u32,
435    pub bookmark: u32,
436    pub playing: u32,
437    pub import: u32,
438    pub me: u32,
439}