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 #[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}