mlb_api/endpoints/teams/team/
mod.rs

1pub mod alumni; // done
2pub mod coaches; // done
3pub mod leaders;
4pub mod personnel; // done
5pub mod roster; // done
6pub mod stats;
7pub mod uniforms; // done
8
9use crate::endpoints::divisions::NamedDivision;
10use crate::endpoints::league::NamedLeague;
11use crate::endpoints::sports::NamedSport;
12use crate::endpoints::venue::NamedVenue;
13use derive_more::{Deref, DerefMut, Display, From};
14use serde::Deserialize;
15use serde_with::DefaultOnError;
16use serde_with::serde_as;
17use std::ops::{Deref, DerefMut};
18use strum::EnumTryAs;
19
20#[serde_as]
21#[derive(Deserialize)]
22#[serde(rename_all = "camelCase")]
23struct RegularTeamRaw {
24	#[serde(deserialize_with = "crate::types::from_yes_no")]
25	#[serde(default)]
26	all_star_status: bool,
27	active: bool,
28	season: u16,
29	#[serde_as(deserialize_as = "DefaultOnError")]
30	#[serde(default)]
31	venue: NamedVenue,
32	#[serde(flatten)]
33	name: TeamNameRaw,
34	location_name: Option<String>,
35	#[serde(default, deserialize_with = "crate::types::try_from_str")]
36	first_year_of_play: Option<u16>,
37	#[serde_as(deserialize_as = "DefaultOnError")]
38	#[serde(default)]
39	league: NamedLeague,
40	division: Option<NamedDivision>,
41	sport: NamedSport,
42	#[serde(flatten)]
43	parent_organization: Option<Organization>,
44	#[serde(flatten)]
45	inner: NamedTeam,
46}
47
48#[derive(Debug, Deserialize, Deref, DerefMut, PartialEq, Eq, Clone)]
49#[serde(from = "RegularTeamRaw")]
50pub struct RegularTeam {
51	pub all_star_status: bool,
52	pub active: bool,
53	pub season: u16,
54	pub venue: NamedVenue,
55	pub name: TeamName,
56	pub location_name: Option<String>,
57	pub first_year_of_play: u16,
58	pub league: NamedLeague,
59	pub division: Option<NamedDivision>,
60	pub sport: NamedSport,
61	pub parent_organization: Option<Organization>,
62
63	#[deref]
64	#[deref_mut]
65	#[serde(flatten)]
66	inner: NamedTeam,
67}
68
69impl From<RegularTeamRaw> for RegularTeam {
70	fn from(value: RegularTeamRaw) -> Self {
71		let RegularTeamRaw {
72			all_star_status,
73			active,
74			season,
75			venue,
76			name,
77			location_name,
78			first_year_of_play,
79			league,
80			division,
81			sport,
82			parent_organization,
83			inner,
84		} = value;
85
86		RegularTeam {
87			all_star_status,
88			active,
89			season,
90			venue,
91			name: name.initialize(inner.id),
92			location_name,
93			first_year_of_play: first_year_of_play.unwrap_or(season),
94			league,
95			division,
96			sport,
97			parent_organization,
98			inner,
99		}
100	}
101}
102
103#[derive(Debug, Deserialize, Deref, DerefMut, PartialEq, Eq, Clone)]
104#[serde(rename_all = "camelCase")]
105pub struct MLBTeam {
106	pub spring_venue: NamedVenue,
107	pub spring_league: NamedLeague,
108
109	#[deref]
110	#[deref_mut]
111	#[serde(flatten)]
112	pub inner: RegularTeam,
113}
114
115#[derive(Deserialize)]
116struct NamedTeamRaw {
117	#[serde(flatten)]
118	name: TeamNameRaw,
119
120	#[serde(flatten)]
121	inner: IdentifiableTeam,
122}
123
124impl From<NamedTeamRaw> for NamedTeam {
125	fn from(value: NamedTeamRaw) -> Self {
126		let NamedTeamRaw { name, inner } = value;
127		Self { name: name.initialize(inner.id), inner }
128	}
129}
130
131#[derive(Debug, Deserialize, Deref, DerefMut, PartialEq, Eq, Clone)]
132#[serde(from = "NamedTeamRaw")]
133pub struct NamedTeam {
134	pub name: TeamName,
135
136	#[deref]
137	#[deref_mut]
138	inner: IdentifiableTeam,
139}
140
141#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
142pub struct IdentifiableTeam {
143	pub id: TeamId,
144}
145
146#[derive(Debug, Deserialize, Eq, Clone, From, EnumTryAs)]
147#[serde(untagged)]
148pub enum Team {
149	MLB(MLBTeam),
150	Regular(RegularTeam),
151	Named(NamedTeam),
152	Identifiable(IdentifiableTeam),
153}
154
155impl Team {
156	#[must_use]
157	pub(crate) const fn unknown_team() -> Self {
158		Self::Identifiable(IdentifiableTeam { id: TeamId::new(0) })
159	}
160}
161
162impl PartialEq for Team {
163	fn eq(&self, other: &Self) -> bool {
164		self.id == other.id
165	}
166}
167
168impl Deref for Team {
169	type Target = IdentifiableTeam;
170
171	fn deref(&self) -> &Self::Target {
172		match self {
173			Self::MLB(inner) => inner,
174			Self::Regular(inner) => inner,
175			Self::Named(inner) => inner,
176			Self::Identifiable(inner) => inner,
177		}
178	}
179}
180
181impl DerefMut for Team {
182	fn deref_mut(&mut self) -> &mut Self::Target {
183		match self {
184			Self::MLB(inner) => inner,
185			Self::Regular(inner) => inner,
186			Self::Named(inner) => inner,
187			Self::Identifiable(inner) => inner,
188		}
189	}
190}
191
192#[derive(Deserialize)]
193#[serde(rename_all = "camelCase")]
194struct TeamNameRaw {
195	pub name: String,
196	pub team_code: Option<String>,
197	pub file_code: Option<String>,
198	pub abbreviation: Option<String>,
199	pub team_name: Option<String>,
200	pub short_name: Option<String>,
201	pub franchise_name: Option<String>,
202	pub club_name: Option<String>,
203}
204
205#[derive(Debug, Eq, Clone, From)]
206pub enum TeamName {
207	Hydrated(HydratedTeamName),
208	Unhydrated(UnhydratedTeamName),
209}
210
211impl PartialEq for TeamName {
212	fn eq(&self, other: &Self) -> bool {
213		self.name == other.name
214	}
215}
216
217impl Deref for TeamName {
218	type Target = UnhydratedTeamName;
219
220	fn deref(&self) -> &Self::Target {
221		match self {
222			Self::Hydrated(inner) => inner,
223			Self::Unhydrated(inner) => inner,
224		}
225	}
226}
227
228impl DerefMut for TeamName {
229	fn deref_mut(&mut self) -> &mut Self::Target {
230		match self {
231			Self::Hydrated(inner) => inner,
232			Self::Unhydrated(inner) => inner,
233		}
234	}
235}
236
237#[derive(Debug, Deref, DerefMut, PartialEq, Eq, Clone)]
238pub struct UnhydratedTeamName {
239	pub name: String,
240}
241
242#[derive(Debug, Deref, DerefMut, PartialEq, Eq, Clone)]
243pub struct HydratedTeamName {
244	#[deref]
245	#[deref_mut]
246	inner: UnhydratedTeamName,
247
248	pub team_code: String,
249	pub file_code: String,
250	pub abbreviation: String,
251	pub team_name: String,
252	pub short_name: String,
253	pub franchise_name: String,
254	pub club_name: String,
255}
256
257impl TeamNameRaw {
258	fn initialize(self, id: TeamId) -> TeamName {
259		let Self {
260			name,
261			team_code,
262			file_code,
263			abbreviation,
264			team_name,
265			short_name,
266			franchise_name,
267			club_name,
268		} = self;
269
270		let inner = UnhydratedTeamName { name };
271		if let Some(team_code) = team_code
272			&& let Some(abbreviation) = abbreviation
273			&& let Some(team_name) = team_name
274			&& let Some(short_name) = short_name
275		{
276			TeamName::Hydrated(HydratedTeamName {
277				file_code: file_code.unwrap_or_else(|| format!("t{id}")),
278				franchise_name: franchise_name.unwrap_or_else(|| short_name.clone()),
279				club_name: club_name.unwrap_or_else(|| team_name.clone()),
280				team_code,
281				abbreviation,
282				team_name,
283				short_name,
284				inner,
285			})
286		} else {
287			TeamName::Unhydrated(inner)
288		}
289	}
290}
291
292#[repr(transparent)]
293#[derive(Debug, Deserialize, Deref, Display, PartialEq, Eq, Copy, Clone, Hash)]
294pub struct TeamId(u32);
295
296impl TeamId {
297	#[must_use]
298	pub const fn new(id: u32) -> Self {
299		Self(id)
300	}
301}
302
303#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
304#[serde(rename_all = "camelCase")]
305pub struct NamedOrganization {
306	#[serde(rename = "parentOrgName")]
307	pub name: String,
308	#[serde(rename = "parentOrgId")]
309	pub id: OrganizationId,
310}
311
312#[repr(transparent)]
313#[derive(Debug, Deserialize, Deref, Display, PartialEq, Eq, Copy, Clone, Hash)]
314pub struct OrganizationId(u16);
315
316#[derive(Debug, Deserialize, Eq, Clone, From, EnumTryAs)]
317#[serde(untagged)]
318pub enum Organization {
319	NamedOrganization(NamedOrganization),
320}
321
322impl PartialEq for Organization {
323	fn eq(&self, other: &Self) -> bool {
324		self.id == other.id
325	}
326}
327
328impl Deref for Organization {
329	type Target = NamedOrganization;
330
331	fn deref(&self) -> &Self::Target {
332		match self {
333			Self::NamedOrganization(inner) => inner,
334		}
335	}
336}
337
338impl DerefMut for Organization {
339	fn deref_mut(&mut self) -> &mut Self::Target {
340		match self {
341			Organization::NamedOrganization(inner) => inner,
342		}
343	}
344}