ddapi_rs/scheme/
ddnet.rs

1use serde::{Deserialize as SerdeDeserialize, Deserializer};
2use serde_derive::Deserialize;
3use serde_derive::Serialize;
4use std::collections::{HashMap, HashSet};
5
6fn deserialize_timestamp<'de, D>(deserializer: D) -> Result<u64, D::Error>
7where
8    D: Deserializer<'de>,
9{
10    let value: f64 = SerdeDeserialize::deserialize(deserializer)?;
11    Ok(value as u64)
12}
13
14fn default_location() -> String {
15    "unknown".to_string()
16}
17
18#[allow(dead_code)]
19pub type Query = Vec<QueryPlayer>;
20
21#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct QueryPlayer {
24    pub points: i64,
25    pub name: String,
26}
27
28#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
29#[serde(rename_all = "camelCase")]
30pub struct Master {
31    pub servers: Vec<Server>,
32}
33
34impl Master {
35    #[allow(dead_code)]
36    pub fn count_clients(&self) -> usize {
37        self.servers.iter().map(Server::count_client).sum()
38    }
39
40    #[allow(dead_code)]
41    pub fn get_clans(&self, rm: Option<Vec<&str>>) -> Vec<(String, usize)> {
42        let remove_list: HashSet<&str> = rm
43            .unwrap_or_else(|| vec!["DD-Persian", "/vDQMHSss8W"])
44            .into_iter()
45            .collect();
46
47        if self.servers.is_empty() {
48            return vec![];
49        }
50
51        let mut dat: HashMap<String, usize> = HashMap::new();
52
53        self.servers.iter().for_each(|server| {
54            if let Some(clients) = &server.info.clients {
55                clients
56                    .iter()
57                    .filter(|client| !client.clan.is_empty())
58                    .for_each(|client| {
59                        *dat.entry(client.clan.clone()).or_insert(0) += 1;
60                    });
61            }
62        });
63
64        for clan in remove_list {
65            dat.remove(clan);
66        }
67
68        let mut sorted_dat: Vec<_> = dat.into_iter().collect();
69        sorted_dat.sort_by(|&(_, count1), &(_, count2)| count2.cmp(&count1));
70        sorted_dat
71    }
72}
73
74#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct Server {
77    pub addresses: Vec<String>,
78    #[serde(default = "default_location")]
79    pub location: String,
80    pub info: Info,
81}
82
83impl Server {
84    #[allow(dead_code)]
85    pub fn count_client(&self) -> usize {
86        self.info
87            .clients
88            .as_ref()
89            .map_or(0, |clients| clients.len())
90    }
91}
92
93#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
94#[serde(rename_all = "camelCase")]
95pub struct Info {
96    #[serde(rename = "max_clients")]
97    pub max_clients: i64,
98    #[serde(rename = "max_players")]
99    pub max_players: i64,
100    pub passworded: bool,
101    #[serde(rename = "game_type")]
102    pub game_type: String,
103    pub name: String,
104    pub map: Map,
105    pub version: String,
106    pub clients: Option<Vec<Client>>,
107    #[serde(rename = "requires_login")]
108    pub requires_login: Option<bool>,
109    pub community: Option<Community>,
110}
111
112#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
113#[serde(rename_all = "camelCase")]
114pub struct Map {
115    pub name: String,
116    pub sha256: Option<String>,
117    pub size: Option<i64>,
118}
119
120#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
121#[serde(rename_all = "camelCase")]
122pub struct Client {
123    pub name: String,
124    pub clan: String,
125    pub country: i32,
126    pub score: i64,
127    pub is_player: Option<bool>,
128    pub skin: Option<Skin>,
129    pub afk: Option<bool>,
130    pub team: Option<i64>,
131}
132
133#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
134#[serde(rename_all = "camelCase")]
135pub struct Skin {
136    pub name: Option<String>,
137    pub color_body: Option<i64>,
138    pub color_feet: Option<i64>,
139}
140
141#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
142#[serde(rename_all = "camelCase")]
143pub struct Community {
144    pub id: String,
145    pub icon: String,
146    pub admin: Vec<String>,
147    pub public_key: Option<String>,
148    pub signature: Option<String>,
149}
150
151#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
152#[serde(rename_all = "camelCase")]
153pub struct DDPlayer {
154    pub player: String,
155    pub points: Points,
156    #[serde(rename = "team_rank")]
157    pub team_rank: Option<Rank>,
158    pub rank: Option<Rank>,
159    #[serde(rename = "points_last_year")]
160    pub points_last_year: Option<Rank>,
161    #[serde(rename = "points_last_month")]
162    pub points_last_month: Option<Rank>,
163    #[serde(rename = "points_last_week")]
164    pub points_last_week: Option<Rank>,
165    #[serde(rename = "favorite_server")]
166    pub favorite_server: FavoriteServer,
167    #[serde(rename = "first_finish")]
168    pub first_finish: FirstFinish,
169    #[serde(rename = "last_finishes")]
170    pub last_finishes: Vec<LastFinish>,
171    #[serde(rename = "favorite_partners")]
172    pub favorite_partners: Option<Vec<FavoritePartner>>,
173    pub types: Types,
174    pub activity: Vec<Activity>,
175    #[serde(rename = "hours_played_past_365_days")]
176    pub hours_played_past_365_days: i64,
177}
178
179#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
180#[serde(rename_all = "camelCase")]
181pub struct DMap {
182    pub name: String,
183    pub website: String,
184    pub thumbnail: String,
185    #[serde(rename = "web_preview")]
186    pub web_preview: String,
187    #[serde(rename = "type")]
188    pub type_field: String,
189    pub points: i64,
190    pub difficulty: i64,
191    pub mapper: String,
192    pub release: Option<f64>,
193    #[serde(rename = "median_time")]
194    pub median_time: f64,
195    #[serde(rename = "first_finish")]
196    pub first_finish: f64,
197    #[serde(rename = "last_finish")]
198    pub last_finish: f64,
199    pub finishes: i64,
200    pub finishers: i64,
201    #[serde(rename = "biggest_team")]
202    pub biggest_team: i64,
203    pub width: i64,
204    pub height: i64,
205    pub tiles: Vec<String>,
206    #[serde(rename = "team_ranks")]
207    pub team_ranks: Vec<DTeamRank>,
208    pub ranks: Vec<DRank>,
209    #[serde(rename = "max_finishes")]
210    pub max_finishes: Vec<MaxFinish>,
211}
212
213#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
214#[serde(rename_all = "camelCase")]
215pub struct DTeamRank {
216    pub rank: i64,
217    pub players: Vec<String>,
218    pub time: f64,
219    #[serde(deserialize_with = "deserialize_timestamp")]
220    pub timestamp: u64,
221    pub country: String,
222}
223
224#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
225#[serde(rename_all = "camelCase")]
226pub struct DRank {
227    pub rank: i64,
228    pub player: String,
229    pub time: f64,
230    #[serde(deserialize_with = "deserialize_timestamp")]
231    pub timestamp: u64,
232    pub country: String,
233}
234
235#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
236#[serde(rename_all = "camelCase")]
237pub struct MaxFinish {
238    pub rank: i64,
239    pub player: String,
240    pub num: i64,
241    pub time: f64,
242    #[serde(rename = "min_timestamp")]
243    #[serde(deserialize_with = "deserialize_timestamp")]
244    pub min_timestamp: u64,
245    #[serde(rename = "max_timestamp")]
246    #[serde(deserialize_with = "deserialize_timestamp")]
247    pub max_timestamp: u64,
248}
249
250#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
251#[serde(rename_all = "camelCase")]
252pub struct Points {
253    pub total: u64,
254    pub points: Option<u64>,
255    pub rank: Option<u64>,
256}
257
258#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
259#[serde(rename_all = "camelCase")]
260pub struct Rank {
261    pub points: Option<u64>,
262    pub rank: Option<u64>,
263}
264
265#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
266#[serde(rename_all = "camelCase")]
267pub struct FavoriteServer {
268    pub server: String,
269}
270
271#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
272#[serde(rename_all = "camelCase")]
273pub struct FirstFinish {
274    #[serde(deserialize_with = "deserialize_timestamp")]
275    pub timestamp: u64,
276    pub map: String,
277    pub time: f64,
278}
279
280#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
281#[serde(rename_all = "camelCase")]
282pub struct LastFinish {
283    #[serde(deserialize_with = "deserialize_timestamp")]
284    pub timestamp: u64,
285    pub map: String,
286    pub time: f64,
287    pub country: String,
288    #[serde(rename = "type")]
289    pub type_field: Option<String>,
290}
291
292#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
293#[serde(rename_all = "camelCase")]
294pub struct FavoritePartner {
295    pub name: String,
296    pub finishes: i64,
297}
298
299#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
300#[serde(rename_all = "camelCase")]
301pub struct Types {
302    #[serde(rename = "Novice")]
303    pub novice: TypeDDType,
304    #[serde(rename = "Moderate")]
305    pub moderate: TypeDDType,
306    #[serde(rename = "Brutal")]
307    pub brutal: TypeDDType,
308    #[serde(rename = "Insane")]
309    pub insane: TypeDDType,
310    #[serde(rename = "Dummy")]
311    pub dummy: TypeDDType,
312    #[serde(rename = "DDmaX.Easy")]
313    pub ddma_x_easy: TypeDDType,
314    #[serde(rename = "DDmaX.Next")]
315    pub ddma_x_next: TypeDDType,
316    #[serde(rename = "DDmaX.Pro")]
317    pub ddma_x_pro: TypeDDType,
318    #[serde(rename = "DDmaX.Nut")]
319    pub ddma_x_nut: TypeDDType,
320    #[serde(rename = "Oldschool")]
321    pub oldschool: TypeDDType,
322    #[serde(rename = "Solo")]
323    pub solo: TypeDDType,
324    #[serde(rename = "Race")]
325    pub race: TypeDDType,
326    #[serde(rename = "Fun")]
327    pub fun: TypeDDType,
328}
329
330#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
331#[serde(rename_all = "camelCase")]
332pub struct TypeDDType {
333    pub points: Points,
334    #[serde(rename = "team_rank")]
335    pub team_rank: Option<Rank>,
336    pub rank: Option<Rank>,
337    pub maps: HashMap<String, DDMap>,
338}
339
340#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
341#[serde(rename_all = "camelCase")]
342pub struct DDMap {
343    pub points: i64,
344    #[serde(rename = "total_finishes")]
345    pub total_finishes: i64,
346    pub finishes: i64,
347    #[serde(rename = "team_rank")]
348    pub team_rank: Option<i64>,
349    pub rank: Option<i64>,
350    pub time: Option<f64>,
351    #[serde(rename = "first_finish")]
352    pub first_finish: Option<f64>,
353}
354
355#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
356#[serde(rename_all = "camelCase")]
357pub struct Activity {
358    pub date: String,
359    #[serde(rename = "hours_played")]
360    pub hours_played: i64,
361}