Skip to main content

mlb_api/requests/
division.rs

1//! A division, like the AL East or NL West.
2//!
3//! These are created for every league, not just the MLB and contain important division-specific information like `num_playoff_teams`, `has_wildcard` and `active`.
4
5use crate::cache::Requestable;
6use crate::league::LeagueId;
7use crate::request::RequestURL;
8use crate::season::SeasonId;
9use crate::sport::SportId;
10use crate::Copyright;
11use bon::Builder;
12use derive_more::{Deref, DerefMut};
13use serde::Deserialize;
14use std::fmt::{Display, Formatter};
15
16#[cfg(feature = "cache")]
17use crate::{rwlock_const_new, RwLock, cache::CacheTable};
18
19/// A [`Vec`] of [`Division`]s
20///
21/// Response to a [`DivisionsRequest`]
22///
23/// Example: <http://statsapi.mlb.com/api/v1/divisions>
24#[derive(Debug, Deserialize, PartialEq, Clone)]
25#[serde(rename_all = "camelCase")]
26pub struct DivisionsResponse {
27	pub copyright: Copyright,
28	pub divisions: Vec<Division>,
29}
30
31id!(#[doc = "A [`u32`] representing the ID of the division"] DivisionId { id: u32 });
32
33/// A division with a name.
34#[derive(Debug, Deserialize, Clone, Eq)]
35#[serde(rename_all = "camelCase")]
36pub struct NamedDivision {
37	pub name: String,
38	#[serde(flatten)]
39	pub id: DivisionId,
40}
41
42/// A complete division of info, returned from [`DivisionsResponse`]
43#[derive(Debug, Deserialize, Deref, DerefMut, Clone)]
44#[serde(rename_all = "camelCase")]
45pub struct Division {
46	#[serde(rename = "nameShort")]
47	pub short_name: String,
48	pub season: SeasonId,
49	pub abbreviation: String,
50	pub league: LeagueId,
51	pub sport: SportId,
52	pub has_wildcard: bool,
53	pub num_playoff_teams: Option<u8>,
54	pub active: bool,
55
56	#[deref]
57	#[deref_mut]
58	#[serde(flatten)]
59	inner: NamedDivision,
60}
61
62id_only_eq_impl!(Division, id);
63id_only_eq_impl!(NamedDivision, id);
64
65/// Returns a [`DivisionsResponse`]
66#[derive(Builder)]
67#[builder(derive(Into))]
68pub struct DivisionsRequest {
69	#[builder(into)]
70	division_id: Option<DivisionId>,
71	#[builder(into)]
72	league_id: Option<LeagueId>,
73	#[builder(into)]
74	sport_id: Option<SportId>,
75	#[builder(into)]
76	season: Option<SeasonId>,
77}
78
79impl<S: divisions_request_builder::State + divisions_request_builder::IsComplete> crate::request::RequestURLBuilderExt for DivisionsRequestBuilder<S> {
80    type Built = DivisionsRequest;
81}
82
83impl Display for DivisionsRequest {
84	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
85		write!(
86			f,
87			"http://statsapi.mlb.com/api/v1/divisions{}",
88			gen_params! { "divisionId"?: self.division_id, "leagueId"?: self.league_id, "sportId"?: self.sport_id, "season"?: self.season }
89		)
90	}
91}
92
93impl RequestURL for DivisionsRequest {
94	type Response = DivisionsResponse;
95}
96
97#[cfg(feature = "cache")]
98static CACHE: RwLock<CacheTable<Division>> = rwlock_const_new(CacheTable::new());
99
100impl Requestable for Division {
101	type Identifier = DivisionId;
102	type URL = DivisionsRequest;
103
104	fn id(&self) -> &Self::Identifier {
105		&self.id
106	}
107
108	#[cfg(feature = "aggressive_cache")]
109	fn url_for_id(_id: &Self::Identifier) -> Self::URL {
110		DivisionsRequest::builder().build()
111	}
112
113	#[cfg(not(feature = "aggressive_cache"))]
114	fn url_for_id(id: &Self::Identifier) -> Self::URL {
115		DivisionsRequest::builder().division_id(*id).build()
116	}
117
118	fn get_entries(response: <Self::URL as RequestURL>::Response) -> impl IntoIterator<Item=Self>
119	where
120		Self: Sized
121	{
122		response.divisions
123	}
124
125	#[cfg(feature = "cache")]
126	fn get_cache_table() -> &'static RwLock<CacheTable<Self>>
127	where
128		Self: Sized
129	{
130		&CACHE
131	}
132}
133
134entrypoint!(DivisionId => Division);
135entrypoint!(NamedDivision.id => Division);
136entrypoint!(Division.id => Division);
137
138#[cfg(test)]
139mod tests {
140	use crate::division::DivisionsRequest;
141	use crate::request::RequestURLBuilderExt;
142
143	#[tokio::test]
144	async fn all_divisions_this_season() {
145		let _response = DivisionsRequest::builder().build_and_get().await.unwrap();
146	}
147}