Skip to main content

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