ugg_types/
overview.rs

1// Credit to https://github.com/pradishb/ugg-parser for figuring out the
2// structure of the champ overview stats data.
3
4use crate::mappings;
5use serde::de::{Deserialize, Deserializer, IgnoredAny, SeqAccess, Visitor};
6use serde::Serialize;
7use std::collections::HashMap;
8use std::fmt;
9
10pub type ChampOverview = HashMap<
11    mappings::Region,
12    HashMap<mappings::Rank, HashMap<mappings::Role, WrappedOverviewData>>,
13>;
14
15fn handle_unknown<T: Default, E>(result: Result<Option<T>, E>) -> T {
16    result.ok().flatten().unwrap_or_default()
17}
18
19#[derive(Debug, Clone, Serialize)]
20pub struct WrappedOverviewData {
21    pub data: OverviewData,
22}
23
24impl<'de> Deserialize<'de> for WrappedOverviewData {
25    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
26    where
27        D: Deserializer<'de>,
28    {
29        struct WrappedOverviewDataVisitor;
30
31        impl<'de> Visitor<'de> for WrappedOverviewDataVisitor {
32            type Value = WrappedOverviewData;
33
34            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
35                formatter.write_str("waa")
36            }
37
38            fn visit_seq<V>(self, mut visitor: V) -> Result<WrappedOverviewData, V::Error>
39            where
40                V: SeqAccess<'de>,
41            {
42                match visitor.next_element::<OverviewData>() {
43                    Ok(Some(data)) => {
44                        while let Some(IgnoredAny) = visitor.next_element()? {}
45                        Ok(WrappedOverviewData { data })
46                    }
47                    Err(e) => Err(e),
48                    _ => Err(serde::de::Error::custom("No more data left.")),
49                }
50            }
51        }
52
53        deserializer.deserialize_seq(WrappedOverviewDataVisitor)
54    }
55}
56
57#[derive(Debug, Clone, Serialize)]
58pub struct OverviewData {
59    pub runes: Runes,
60    pub summoner_spells: SummonerSpells,
61    pub starting_items: Items,
62    pub core_items: Items,
63    pub abilities: Abilities,
64    pub item_4_options: Vec<LateItem>,
65    pub item_5_options: Vec<LateItem>,
66    pub item_6_options: Vec<LateItem>,
67    pub wins: i64,
68    pub matches: i64,
69    pub low_sample_size: bool,
70    pub shards: Shards,
71}
72
73#[derive(Debug, Clone, Serialize)]
74pub struct Runes {
75    pub matches: i64,
76    pub wins: i64,
77    pub primary_style_id: i64,
78    pub secondary_style_id: i64,
79    pub rune_ids: Vec<i64>,
80}
81
82impl<'de> Deserialize<'de> for Runes {
83    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
84    where
85        D: Deserializer<'de>,
86    {
87        struct RunesVisitor;
88
89        impl<'de> Visitor<'de> for RunesVisitor {
90            type Value = Runes;
91
92            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
93                formatter.write_str("rune stats")
94            }
95
96            fn visit_seq<V>(self, mut visitor: V) -> Result<Runes, V::Error>
97            where
98                V: SeqAccess<'de>,
99            {
100                Ok(Runes {
101                    matches: handle_unknown(visitor.next_element::<i64>()),
102                    wins: handle_unknown(visitor.next_element::<i64>()),
103                    primary_style_id: handle_unknown(visitor.next_element::<i64>()),
104                    secondary_style_id: handle_unknown(visitor.next_element::<i64>()),
105                    rune_ids: handle_unknown(visitor.next_element::<Vec<i64>>()),
106                })
107            }
108        }
109
110        deserializer.deserialize_seq(RunesVisitor)
111    }
112}
113
114#[derive(Debug, Clone, Serialize)]
115pub struct SummonerSpells {
116    pub matches: i64,
117    pub wins: i64,
118    pub spell_ids: Vec<i64>,
119}
120
121impl<'de> Deserialize<'de> for SummonerSpells {
122    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
123    where
124        D: Deserializer<'de>,
125    {
126        struct SummonerSpellsVisitor;
127
128        impl<'de> Visitor<'de> for SummonerSpellsVisitor {
129            type Value = SummonerSpells;
130
131            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
132                formatter.write_str("summoner spells")
133            }
134
135            fn visit_seq<V>(self, mut visitor: V) -> Result<SummonerSpells, V::Error>
136            where
137                V: SeqAccess<'de>,
138            {
139                Ok(SummonerSpells {
140                    matches: handle_unknown(visitor.next_element::<i64>()),
141                    wins: handle_unknown(visitor.next_element::<i64>()),
142                    spell_ids: handle_unknown(visitor.next_element::<Vec<i64>>()),
143                })
144            }
145        }
146
147        deserializer.deserialize_seq(SummonerSpellsVisitor)
148    }
149}
150
151#[derive(Debug, Clone, Serialize)]
152pub struct Items {
153    pub matches: i64,
154    pub wins: i64,
155    pub item_ids: Vec<i64>,
156}
157
158impl<'de> Deserialize<'de> for Items {
159    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
160    where
161        D: Deserializer<'de>,
162    {
163        struct ItemsVisitor;
164
165        impl<'de> Visitor<'de> for ItemsVisitor {
166            type Value = Items;
167
168            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
169                formatter.write_str("items")
170            }
171
172            fn visit_seq<V>(self, mut visitor: V) -> Result<Items, V::Error>
173            where
174                V: SeqAccess<'de>,
175            {
176                Ok(Items {
177                    matches: handle_unknown(visitor.next_element::<i64>()),
178                    wins: handle_unknown(visitor.next_element::<i64>()),
179                    item_ids: handle_unknown(visitor.next_element::<Vec<i64>>()),
180                })
181            }
182        }
183
184        deserializer.deserialize_seq(ItemsVisitor)
185    }
186}
187
188#[derive(Debug, Clone, Serialize)]
189pub struct Abilities {
190    pub matches: i64,
191    pub wins: i64,
192    pub ability_order: Vec<char>,
193    pub ability_max_order: String,
194}
195
196impl<'de> Deserialize<'de> for Abilities {
197    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
198    where
199        D: Deserializer<'de>,
200    {
201        struct AbilitiesVisitor;
202
203        impl<'de> Visitor<'de> for AbilitiesVisitor {
204            type Value = Abilities;
205
206            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
207                formatter.write_str("abilities")
208            }
209
210            fn visit_seq<V>(self, mut visitor: V) -> Result<Abilities, V::Error>
211            where
212                V: SeqAccess<'de>,
213            {
214                Ok(Abilities {
215                    matches: handle_unknown(visitor.next_element::<i64>()),
216                    wins: handle_unknown(visitor.next_element::<i64>()),
217                    ability_order: handle_unknown(visitor.next_element::<Vec<char>>()),
218                    ability_max_order: handle_unknown(visitor.next_element::<String>()),
219                })
220            }
221        }
222
223        deserializer.deserialize_seq(AbilitiesVisitor)
224    }
225}
226
227#[derive(Debug, Clone, Serialize)]
228pub struct LateItem {
229    pub matches: i64,
230    pub wins: i64,
231    pub id: i64,
232}
233
234impl<'de> Deserialize<'de> for LateItem {
235    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
236    where
237        D: Deserializer<'de>,
238    {
239        struct LateItemVisitor;
240
241        impl<'de> Visitor<'de> for LateItemVisitor {
242            type Value = LateItem;
243
244            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
245                formatter.write_str("summoner spells")
246            }
247
248            fn visit_seq<V>(self, mut visitor: V) -> Result<LateItem, V::Error>
249            where
250                V: SeqAccess<'de>,
251            {
252                Ok(LateItem {
253                    id: handle_unknown(visitor.next_element::<i64>()),
254                    wins: handle_unknown(visitor.next_element::<i64>()),
255                    matches: handle_unknown(visitor.next_element::<i64>()),
256                })
257            }
258        }
259
260        deserializer.deserialize_seq(LateItemVisitor)
261    }
262}
263
264#[derive(Debug, Clone, Serialize)]
265pub struct Shards {
266    pub matches: i64,
267    pub wins: i64,
268    pub shard_ids: Vec<i64>,
269}
270
271impl<'de> Deserialize<'de> for Shards {
272    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
273    where
274        D: Deserializer<'de>,
275    {
276        struct AbilitiesVisitor;
277
278        impl<'de> Visitor<'de> for AbilitiesVisitor {
279            type Value = Shards;
280
281            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
282                formatter.write_str("shards")
283            }
284
285            fn visit_seq<V>(self, mut visitor: V) -> Result<Shards, V::Error>
286            where
287                V: SeqAccess<'de>,
288            {
289                Ok(Shards {
290                    matches: handle_unknown(visitor.next_element::<i64>()),
291                    wins: handle_unknown(visitor.next_element::<i64>()),
292                    shard_ids: handle_unknown(visitor.next_element::<Vec<String>>())
293                        .iter()
294                        .map(|x| x.parse::<i64>().unwrap_or_default())
295                        .collect::<Vec<i64>>(),
296                })
297            }
298        }
299
300        deserializer.deserialize_seq(AbilitiesVisitor)
301    }
302}
303
304impl<'de> Deserialize<'de> for OverviewData {
305    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
306    where
307        D: Deserializer<'de>,
308    {
309        struct OverviewDataVisitor;
310
311        impl<'de> Visitor<'de> for OverviewDataVisitor {
312            type Value = OverviewData;
313
314            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
315                formatter.write_str("overview data")
316            }
317
318            fn visit_seq<V>(self, mut visitor: V) -> Result<OverviewData, V::Error>
319            where
320                V: SeqAccess<'de>,
321            {
322                let runes = visitor
323                    .next_element::<Runes>()?
324                    .ok_or(serde::de::Error::custom("Could not parse runes."))?;
325                let summoner_spells = visitor
326                    .next_element::<SummonerSpells>()?
327                    .ok_or(serde::de::Error::custom("Could not parse summoner spells."))?;
328                let starting_items = visitor
329                    .next_element::<Items>()?
330                    .ok_or(serde::de::Error::custom("Could not parse starting items."))?;
331                let core_items = visitor
332                    .next_element::<Items>()?
333                    .ok_or(serde::de::Error::custom("Could not parse core items."))?;
334                let abilities = visitor
335                    .next_element::<Abilities>()?
336                    .ok_or(serde::de::Error::custom("Could not parse abilities."))?;
337                let late_items = visitor
338                    .next_element::<Vec<Vec<LateItem>>>()?
339                    .ok_or(serde::de::Error::custom("Could not parse late items."))?;
340                let match_info = visitor.next_element::<Vec<i64>>()?.unwrap_or_default();
341                let low_sample_size = match_info[1] < 1000;
342
343                // this is the original low sample size value, it's always false though, so ignore.
344                let _ = visitor.next_element::<IgnoredAny>().is_ok();
345
346                let shards = visitor
347                    .next_element::<Shards>()?
348                    .ok_or(serde::de::Error::custom("Could not parse shards."))?;
349
350                // Don't know what this is yet
351                while let Some(IgnoredAny) = visitor.next_element()? {}
352
353                let overview_data = OverviewData {
354                    runes,
355                    summoner_spells,
356                    starting_items,
357                    core_items,
358                    abilities,
359                    item_4_options: late_items[0].clone(),
360                    item_5_options: late_items[1].clone(),
361                    item_6_options: late_items[2].clone(),
362                    wins: match_info[0],
363                    matches: match_info[1],
364                    low_sample_size,
365                    shards,
366                };
367                Ok(overview_data)
368            }
369        }
370
371        deserializer.deserialize_seq(OverviewDataVisitor)
372    }
373}