Skip to main content

mlb_api/requests/person/
free_agents.rs

1//! Lists the registered free agents at the time.
2
3use crate::season::SeasonId;
4use crate::Copyright;
5use bon::Builder;
6use chrono::NaiveDate;
7use serde::Deserialize;
8use serde_with::serde_as;
9use serde_with::DefaultOnError;
10use std::fmt::{Display, Formatter};
11use crate::person::NamedPerson;
12use crate::meta::NamedPosition;
13use crate::request::RequestURL;
14use crate::team::NamedTeam;
15
16/// A [`Vec`] of [`FreeAgent`]s
17#[derive(Debug, Deserialize, PartialEq, Clone)]
18#[serde(rename_all = "camelCase")]
19pub struct FreeAgentsResponse {
20	pub copyright: Copyright,
21	pub free_agents: Vec<FreeAgent>,
22}
23
24#[serde_as]
25#[derive(Deserialize)]
26#[serde(rename_all = "camelCase")]
27#[doc(hidden)]
28struct __FreeAgentStruct {
29	player: NamedPerson,
30	#[serde_as(deserialize_as = "DefaultOnError")]
31	original_team: Option<NamedTeam>,
32	#[serde_as(deserialize_as = "DefaultOnError")]
33	new_team: Option<NamedTeam>,
34	notes: Option<String>,
35	date_signed: Option<NaiveDate>,
36	date_declared: Option<NaiveDate>,
37	position: NamedPosition,
38}
39
40/// Wrapper over [`NamedPerson`], displays the [`Team`](NamedTeam) they were with, the date the signed, their position, etc.
41#[derive(Debug, Deserialize, PartialEq, Clone)]
42#[serde(from = "__FreeAgentStruct")]
43pub struct FreeAgent {
44	pub player: NamedPerson,
45	pub original_team: NamedTeam,
46	pub new_team: NamedTeam,
47	pub notes: Option<String>,
48	pub date_signed: NaiveDate,
49	pub date_declared: NaiveDate,
50	pub position: NamedPosition,
51}
52
53impl From<__FreeAgentStruct> for FreeAgent {
54	fn from(value: __FreeAgentStruct) -> Self {
55		Self {
56			player: value.player,
57			original_team: value.original_team.unwrap_or_else(NamedTeam::unknown_team),
58			new_team: value.new_team.unwrap_or_else(NamedTeam::unknown_team),
59			notes: value.notes,
60			date_signed: value.date_signed.or(value.date_declared).unwrap_or_default(),
61			date_declared: value.date_declared.or(value.date_signed).unwrap_or_default(),
62			position: value.position,
63		}
64	}
65}
66
67/// Returns a [`FreeAgentsResponse`].
68#[derive(Builder)]
69#[builder(derive(Into))]
70pub struct FreeAgentsRequest {
71	#[builder(into)]
72	season: SeasonId,
73}
74
75impl<S: free_agents_request_builder::State + free_agents_request_builder::IsComplete> crate::request::RequestURLBuilderExt for FreeAgentsRequestBuilder<S> {
76	type Built = FreeAgentsRequest;
77}
78
79impl Display for FreeAgentsRequest {
80	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
81		write!(f, "http://statsapi.mlb.com/api/v1/people/freeAgents{}", gen_params! { "season": self.season })
82	}
83}
84
85impl RequestURL for FreeAgentsRequest {
86	type Response = FreeAgentsResponse;
87}
88
89#[cfg(test)]
90mod tests {
91	use crate::request::RequestURLBuilderExt;
92	use crate::person::free_agents::FreeAgentsRequest;
93	use crate::TEST_YEAR;
94
95	#[tokio::test]
96	async fn test_one_year() {
97		let _response = FreeAgentsRequest::builder().season(TEST_YEAR).build_and_get().await.unwrap();
98	}
99
100	#[tokio::test]
101	async fn test_all_seasons() {
102		for season in 2001..=TEST_YEAR {
103			let _response = FreeAgentsRequest::builder().season(season).build_and_get().await.unwrap();
104		}
105	}
106}