r6stats/types/
search_data.rs1pub mod generic_stats;
2
3pub use self::generic_stats::GenericStats;
4use std::collections::HashMap;
5use time::OffsetDateTime;
6use url::Url;
7
8#[derive(Debug, serde::Deserialize, serde::Serialize)]
10pub struct ApiResponse<T> {
11 pub data: T,
12}
13
14#[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}