use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LichessPerf {
pub games: u32,
pub rating: u32,
pub rd: u32,
pub prog: i32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prov: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rank: Option<u32>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct LichessPuzzleModePerf {
pub runs: u32,
pub score: u32,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct LichessPerfs {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub chess960: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub atomic: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub racing_kings: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ultra_bullet: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub blitz: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub king_of_the_hill: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub three_check: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub antichess: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub crazyhouse: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub bullet: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub correspondence: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub horde: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub puzzle: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub classical: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rapid: Option<LichessPerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub storm: Option<LichessPuzzleModePerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub racer: Option<LichessPuzzleModePerf>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub streak: Option<LichessPuzzleModePerf>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserializes_perf_with_optional_fields() {
let json = r#"{"games":109,"rating":1814,"rd":55,"prog":-19,"prov":true}"#;
let perf: LichessPerf = serde_json::from_str(json).unwrap();
assert_eq!(perf.rating, 1814);
assert_eq!(perf.prog, -19);
assert_eq!(perf.prov, Some(true));
assert_eq!(perf.rank, None);
}
#[test]
fn maps_camel_case_perf_keys() {
let json = r#"{"ultraBullet":{"games":1,"rating":1500,"rd":100,"prog":0},
"racingKings":{"games":2,"rating":1490,"rd":90,"prog":3}}"#;
let perfs: LichessPerfs = serde_json::from_str(json).unwrap();
assert!(perfs.ultra_bullet.is_some());
assert_eq!(perfs.racing_kings.unwrap().rating, 1490);
assert!(perfs.bullet.is_none());
}
}