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::arena_overview::ArenaOverviewData;
5use crate::default_overview::{Abilities, OverviewData};
6use crate::mappings;
7use serde::de::{Deserialize, Deserializer, IgnoredAny, SeqAccess, Visitor};
8use serde::{Deserialize as DeserializeDerive, Serialize};
9use std::collections::HashMap;
10use std::fmt;
11
12pub type ChampOverview = HashMap<
13    mappings::Region,
14    HashMap<mappings::Rank, HashMap<mappings::Role, WrappedOverviewData>>,
15>;
16
17pub fn handle_unknown<T: Default, E>(result: Result<Option<T>, E>) -> T {
18    result.ok().flatten().unwrap_or_default()
19}
20
21#[derive(Debug, Clone, Serialize, DeserializeDerive)]
22#[serde(untagged)]
23pub enum Overview {
24    Default(OverviewData),
25    Arena(ArenaOverviewData),
26}
27
28impl Overview {
29    #[must_use]
30    pub fn matches(&self) -> i64 {
31        match self {
32            Overview::Arena(a) => a.matches,
33            Overview::Default(d) => d.matches,
34        }
35    }
36
37    #[must_use]
38    pub fn abilities(&self) -> Abilities {
39        match self {
40            Overview::Arena(a) => a.abilities.clone(),
41            Overview::Default(d) => d.abilities.clone(),
42        }
43    }
44
45    #[must_use]
46    pub fn low_sample_size(&self) -> bool {
47        match self {
48            Overview::Arena(a) => a.low_sample_size,
49            Overview::Default(d) => d.low_sample_size,
50        }
51    }
52}
53
54#[derive(Debug, Clone, Serialize)]
55pub struct WrappedOverviewData {
56    pub data: Overview,
57}
58
59impl<'de> Deserialize<'de> for WrappedOverviewData {
60    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
61    where
62        D: Deserializer<'de>,
63    {
64        struct WrappedOverviewDataVisitor;
65
66        impl<'de> Visitor<'de> for WrappedOverviewDataVisitor {
67            type Value = WrappedOverviewData;
68
69            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
70                formatter.write_str("waa")
71            }
72
73            fn visit_seq<V>(self, mut visitor: V) -> Result<WrappedOverviewData, V::Error>
74            where
75                V: SeqAccess<'de>,
76            {
77                match visitor.next_element::<Overview>() {
78                    Ok(Some(data)) => {
79                        while let Some(IgnoredAny) = visitor.next_element()? {}
80                        Ok(WrappedOverviewData { data })
81                    }
82                    Err(e) => Err(e),
83                    _ => Err(serde::de::Error::custom("No more data left.")),
84                }
85            }
86        }
87
88        deserializer.deserialize_seq(WrappedOverviewDataVisitor)
89    }
90}