mcsr_ranked_api/user/info/
mod.rs1pub mod all_seasons;
2
3use chrono::serde::{ts_seconds, ts_seconds_option};
4use chrono::{DateTime, Utc};
5use serde::Deserialize;
6#[cfg(feature = "serialize")]
7use serde::Serialize;
8
9use super::UserProfile;
10#[cfg(feature = "achievements")]
11use crate::achievement::Achievement;
12use crate::types::{Elo, Phase, PhasePoints, Rank, RankedAndCasual};
13#[cfg(feature = "weekly_races")]
14use crate::weekly_race::result::WeeklyRaceResult;
15
16#[cfg(feature = "achievements")]
18#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
19#[cfg_attr(feature = "serialize", derive(Serialize))]
20#[serde(rename_all = "camelCase")]
21pub struct UserAchievements {
22 pub display: Box<[Achievement]>,
24 pub total: Box<[Achievement]>,
26}
27#[cfg(feature = "achievements")]
28impl UserAchievements {
29 pub fn displayed(&self) -> &[Achievement] {
31 &self.display
32 }
33 pub fn total(&self) -> &[Achievement] {
35 &self.total
36 }
37}
38
39#[cfg_attr(feature = "serialize", derive(Serialize))]
40#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
41#[serde(rename_all = "camelCase")]
42pub struct UserTimestamps {
43 #[serde(with = "ts_seconds")]
44 first_online: DateTime<Utc>,
45 #[serde(with = "ts_seconds")]
46 last_online: DateTime<Utc>,
47 #[serde(with = "ts_seconds")]
48 last_ranked: DateTime<Utc>,
49 #[serde(with = "ts_seconds_option")]
50 next_decay: Option<DateTime<Utc>>,
51}
52
53#[cfg_attr(feature = "serialize", derive(Serialize))]
55#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
56#[serde(rename_all = "camelCase")]
57pub struct UserStats {
58 pub best_time: RankedAndCasual<Option<u64>>,
59 pub highest_win_streak: RankedAndCasual,
60 pub current_win_streak: RankedAndCasual,
61 pub played_matches: RankedAndCasual,
62 pub playtime: RankedAndCasual,
63 pub completion_time: RankedAndCasual,
64 pub forfeits: RankedAndCasual,
65 pub completions: RankedAndCasual,
66 pub wins: RankedAndCasual,
67 #[serde(rename = "loses")]
68 pub losses: RankedAndCasual,
69}
70
71#[cfg_attr(feature = "serialize", derive(Serialize))]
73#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
74#[serde(rename_all = "camelCase")]
75pub struct UserStatistics {
76 pub season: UserStats,
77 pub total: UserStats,
78}
79
80#[cfg_attr(feature = "serialize", derive(Serialize))]
82#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
83#[serde(rename_all = "camelCase")]
84pub struct UserConnection {
85 pub id: Box<str>,
86 pub name: Box<str>,
87}
88
89#[cfg_attr(feature = "serialize", derive(Serialize))]
91#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
92#[serde(rename_all = "camelCase")]
93pub struct UserConnections {
94 #[serde(default)]
95 pub discord: Option<UserConnection>,
96 #[serde(default)]
97 pub twitch: Option<UserConnection>,
98 #[serde(default)]
99 pub youtube: Option<UserConnection>,
100}
101
102#[cfg_attr(feature = "serialize", derive(Serialize))]
103#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
104#[serde(rename_all = "camelCase")]
105pub struct EloPointsInfo {
106 #[serde(rename = "eloRate")]
107 pub elo: Option<Elo>,
108 #[serde(rename = "eloRank")]
109 pub rank: Option<Rank>,
110 #[serde(alias = "phasePoint", alias = "point")]
111 pub points: PhasePoints,
112}
113
114#[cfg_attr(feature = "serialize", derive(Serialize))]
115#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
116#[serde(rename_all = "camelCase")]
117pub struct PhaseInfo {
118 pub phase: Phase,
119 #[serde(flatten)]
120 pub info: EloPointsInfo,
121}
122#[cfg(test)]
123impl PhaseInfo {
124 pub(crate) fn new(phase: Phase, elo: Elo, rank: Rank, points: PhasePoints) -> Self {
125 Self {
126 phase,
127 info: EloPointsInfo {
128 elo: Some(elo),
129 rank: Some(rank),
130 points,
131 },
132 }
133 }
134}
135
136#[cfg_attr(feature = "serialize", derive(Serialize))]
138#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
139#[serde(rename_all = "camelCase")]
140pub struct UserSeasonOutcome {
141 pub last: EloPointsInfo,
142 pub highest: Option<Elo>,
143 pub lowest: Option<Elo>,
144 pub phases: Box<[PhaseInfo]>,
145}
146#[cfg(test)]
147impl UserSeasonOutcome {
148 pub(crate) fn new(
149 last_elo: Elo,
150 last_rank: Rank,
151 last_points: PhasePoints,
152 highest_elo: Elo,
153 lowest_elo: Elo,
154 phases: impl IntoIterator<Item = PhaseInfo>,
155 ) -> Self {
156 Self {
157 last: EloPointsInfo {
158 elo: Some(last_elo),
159 rank: Some(last_rank),
160 points: last_points,
161 },
162 highest: Some(highest_elo),
163 lowest: Some(lowest_elo),
164 phases: phases.into_iter().collect(),
165 }
166 }
167}
168
169impl UserSeasonOutcome {
170 pub fn phases(&self) -> &[PhaseInfo] {
172 &self.phases
173 }
174}
175
176#[cfg_attr(feature = "serialize", derive(Serialize))]
178#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
179#[serde(rename_all = "camelCase")]
180pub struct UserInfo {
181 #[serde(flatten)]
182 pub profile: UserProfile,
183 #[cfg(feature = "achievements")]
184 pub achievements: UserAchievements,
185 #[serde(rename = "timestamp")]
186 pub timestamps: UserTimestamps,
187 pub statistics: UserStatistics,
188 pub connections: UserConnections,
189 pub season_result: Option<UserSeasonOutcome>,
190 #[cfg(feature = "weekly_races")]
191 pub weekly_races: Box<[WeeklyRaceResult]>,
192}
193impl UserInfo {
194 pub fn weekly_races(&self) -> &[WeeklyRaceResult] {
196 &self.weekly_races
197 }
198}