r6stats/types/
search_data.rs

1pub mod generic_stats;
2
3pub use self::generic_stats::GenericStats;
4use std::collections::HashMap;
5use time::OffsetDateTime;
6use url::Url;
7
8/// Api Response
9#[derive(Debug, serde::Deserialize, serde::Serialize)]
10pub struct ApiResponse<T> {
11    pub data: T,
12}
13
14/// User Data
15#[derive(Debug, serde::Deserialize, serde::Serialize)]
16pub struct UserData {
17    pub avatar_banned: bool,
18    pub avatar_url_146: Url,
19    pub avatar_url_256: Url,
20    pub claimed: bool,
21
22    #[serde(rename = "genericStats")]
23    pub generic_stats: Option<GenericStats>,
24
25    #[serde(
26        deserialize_with = "time::serde::rfc3339::deserialize",
27        serialize_with = "time::serde::rfc3339::serialize"
28    )]
29    pub last_updated: OffsetDateTime,
30    pub platform: String,
31
32    #[serde(rename = "progressionStats")]
33    pub progression_stats: Option<ProgressionStats>,
34
35    #[serde(rename = "seasonalStats")]
36    pub seasonal_stats: Option<SeasonalStats>,
37
38    pub ubisoft_id: String,
39    pub uplay_id: String,
40
41    pub username: String,
42
43    #[serde(flatten)]
44    pub unknown: HashMap<String, serde_json::Value>,
45}
46
47impl UserData {
48    pub fn kd(&self) -> Option<f64> {
49        Some(self.generic_stats.as_ref()?.general.kd)
50    }
51
52    pub fn wl(&self) -> Option<f64> {
53        Some(self.generic_stats.as_ref()?.general.wl)
54    }
55
56    pub fn mmr(&self) -> Option<u32> {
57        Some(self.seasonal_stats.as_ref()?.mmr as u32)
58    }
59}
60
61#[derive(Debug, serde::Deserialize, serde::Serialize)]
62pub struct ProgressionStats {
63    pub level: u32,
64    pub lootbox_probability: u32,
65    pub total_xp: u64,
66
67    #[serde(flatten)]
68    pub unknown: HashMap<String, serde_json::Value>,
69}
70
71#[derive(Debug, serde::Deserialize, serde::Serialize)]
72pub struct SeasonalStats {
73    pub abandons: u32,
74    pub champions_rank_position: Option<u32>,
75    #[serde(
76        deserialize_with = "time::serde::rfc3339::deserialize",
77        serialize_with = "time::serde::rfc3339::serialize"
78    )]
79    pub created_at: OffsetDateTime,
80    #[serde(
81        deserialize_with = "time::serde::rfc3339::deserialize",
82        serialize_with = "time::serde::rfc3339::serialize"
83    )]
84    pub created_for_date: OffsetDateTime,
85    pub deaths: Option<u32>,
86    pub kills: Option<u32>,
87    pub last_match_mmr_change: Option<i32>,
88    pub last_match_skill_mean_change: Option<f64>,
89    pub last_match_skill_standard_deviation_change: Option<f64>,
90    pub losses: u32,
91    pub max_mmr: f64,
92    pub max_rank: u32,
93    pub mmr: f64,
94    pub next_rank_mmr: u32,
95    pub prev_rank_mmr: u32,
96    pub rank: u32,
97    pub region: String,
98    pub skill_mean: f64,
99    pub skill_standard_deviation: f64,
100    #[serde(
101        deserialize_with = "time::serde::rfc3339::deserialize",
102        serialize_with = "time::serde::rfc3339::serialize"
103    )]
104    pub updated_at: OffsetDateTime,
105    pub wins: u32,
106
107    #[serde(flatten)]
108    pub unknown: HashMap<String, serde_json::Value>,
109}
110
111#[cfg(test)]
112mod test {
113    use super::*;
114
115    const VALID_DATA: &str = include_str!("../../test_data/search_data_valid.json");
116    const SEARCH_ASDF_DATA: &str = include_str!("../../test_data/search_asdf.json");
117
118    #[tokio::test]
119    async fn parse_valid() {
120        let valid = serde_json::from_str::<Vec<UserData>>(VALID_DATA)
121            .expect("failed to parse valid search data");
122        dbg!(&valid);
123    }
124
125    #[tokio::test]
126    async fn parse_asdf() {
127        let valid = serde_json::from_str::<Vec<UserData>>(SEARCH_ASDF_DATA).unwrap();
128        dbg!(&valid);
129    }
130}