1use crate::mappings;
5use serde::Serialize;
6use serde::de::{Deserialize, Deserializer, IgnoredAny, SeqAccess, Visitor};
7use std::collections::HashMap;
8use std::fmt;
9
10pub type Matchups =
11 HashMap<mappings::Region, HashMap<mappings::Rank, HashMap<mappings::Role, WrappedMatchupData>>>;
12
13#[derive(Debug, Clone, Serialize)]
14pub struct WrappedMatchupData {
15 pub data: MatchupData,
16}
17
18impl<'de> Deserialize<'de> for WrappedMatchupData {
19 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
20 where
21 D: Deserializer<'de>,
22 {
23 struct WrappedMatchupDataVisitor;
24
25 impl<'de> Visitor<'de> for WrappedMatchupDataVisitor {
26 type Value = WrappedMatchupData;
27
28 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
29 formatter.write_str("waa")
30 }
31
32 fn visit_seq<V>(self, mut visitor: V) -> Result<WrappedMatchupData, V::Error>
33 where
34 V: SeqAccess<'de>,
35 {
36 match visitor.next_element::<MatchupData>() {
37 Ok(Some(data)) => {
38 while let Some(IgnoredAny) = visitor.next_element()? {}
39 Ok(WrappedMatchupData { data })
40 }
41 _ => Err(serde::de::Error::missing_field("top-level element")),
42 }
43 }
44 }
45
46 deserializer.deserialize_seq(WrappedMatchupDataVisitor)
47 }
48}
49
50#[derive(Debug, Clone, Serialize)]
51pub struct MatchupData {
52 pub best_matchups: Vec<Matchup>,
53 pub worst_matchups: Vec<Matchup>,
54 pub total_matches: i32,
55}
56
57#[derive(Debug, Clone, Serialize)]
58pub struct Matchup {
59 pub champion_id: i64,
60 pub wins: i32,
61 pub matches: i32,
62 pub winrate: f64,
63}
64
65impl<'de> Deserialize<'de> for MatchupData {
66 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
67 where
68 D: Deserializer<'de>,
69 {
70 struct MatchupDataVisitor;
71
72 impl<'de> Visitor<'de> for MatchupDataVisitor {
73 type Value = MatchupData;
74
75 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
76 formatter.write_str("overview data")
77 }
78
79 fn visit_seq<V>(self, mut visitor: V) -> Result<MatchupData, V::Error>
80 where
81 V: SeqAccess<'de>,
82 {
83 let mut all_matchups: Vec<Matchup> = vec![];
84 let mut total_matches: i32 = 0;
85
86 while let Ok(data_opt) = visitor.next_element::<InnerData>() {
87 match data_opt {
88 Some(data) => {
89 let wins = data.2 - data.1;
90 let winrate = f64::from(wins) / f64::from(data.2);
91 all_matchups.push(Matchup {
92 champion_id: data.0,
93 wins,
94 matches: data.2,
95 winrate,
96 });
97 total_matches += data.2;
98 }
99 None => {
100 break;
101 }
102 }
103 }
104
105 all_matchups = all_matchups
107 .into_iter()
108 .filter(|a| f64::from(a.matches) >= (f64::from(total_matches) / 200.0))
109 .collect::<Vec<Matchup>>();
110 all_matchups.sort_by(|a, b| b.winrate.partial_cmp(&a.winrate).unwrap());
111
112 if all_matchups.len() >= 5 {
113 let best_matchups: Vec<Matchup> = all_matchups.clone()[..5].to_vec();
114 let mut worst_matchups: Vec<Matchup> =
115 all_matchups.clone()[all_matchups.len() - 5..].to_vec();
116 worst_matchups.reverse();
117
118 let matchup_data = MatchupData {
119 best_matchups,
120 worst_matchups,
121 total_matches,
122 };
123 Ok(matchup_data)
124 } else {
125 Ok(MatchupData {
126 best_matchups: vec![],
127 worst_matchups: vec![],
128 total_matches: 0,
129 })
130 }
131 }
132 }
133
134 deserializer.deserialize_seq(MatchupDataVisitor)
135 }
136}
137
138struct InnerData(i64, i32, i32);
139
140impl<'de> Deserialize<'de> for InnerData {
141 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
142 where
143 D: Deserializer<'de>,
144 {
145 struct InnerSeqVisitor;
146
147 impl<'de> Visitor<'de> for InnerSeqVisitor {
148 type Value = InnerData;
149
150 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
151 formatter.write_str("a sequence with at least 3 elements")
152 }
153
154 fn visit_seq<A>(self, mut visitor: A) -> Result<Self::Value, A::Error>
155 where
156 A: SeqAccess<'de>,
157 {
158 let champion_id = visitor
159 .next_element()?
160 .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
161
162 let losses = visitor
163 .next_element()?
164 .ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
165
166 let matches = visitor
167 .next_element()?
168 .ok_or_else(|| serde::de::Error::invalid_length(2, &self))?;
169
170 while let Some(IgnoredAny) = visitor.next_element()? {}
171
172 Ok(InnerData(champion_id, losses, matches))
173 }
174 }
175
176 deserializer.deserialize_seq(InnerSeqVisitor)
177 }
178}