Skip to main content

mlb_api/requests/person/
stats.rs

1use std::borrow::Cow;
2use crate::game::GameId;
3use crate::person::PersonId;
4use crate::types::Copyright;
5use bon::Builder;
6use serde::Deserialize;
7use std::fmt::{Display, Formatter};
8use serde::de::{Deserializer, Error};
9use crate::__stats__request_data;
10use crate::hydrations::{HydrationText, Hydrations};
11use crate::stats::{StatTypeStats, PlayStat};
12use crate::request::RequestURL;
13use crate::stat_groups::StatGroup;
14use crate::stats::parse::{__ParsedStats, make_stat_split};
15use crate::stats::raw::{fielding, hitting, pitching};
16use crate::stats::stat_types::__VsPlayer5YStatTypeStats;
17use crate::stats::wrappers::WithNone;
18
19#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
20pub struct PersonSingleGameStatsResponse {
21	pub copyright: Copyright,
22	#[serde(flatten)]
23	pub stats: SingleGameStats,
24}
25
26#[derive(Builder)]
27#[builder(derive(Into))]
28pub struct PersonSingleGameStatsRequest {
29	#[builder(into)]
30	person_id: PersonId,
31	#[builder(into)]
32	game_id: GameId,
33	#[builder(into)]
34	#[builder(default)]
35	bonus: SingleGameStatsRequestData,
36}
37
38impl<S: person_single_game_stats_request_builder::State + person_single_game_stats_request_builder::IsComplete> crate::request::RequestURLBuilderExt for PersonSingleGameStatsRequestBuilder<S> {
39	type Built = PersonSingleGameStatsRequest;
40}
41
42impl Display for PersonSingleGameStatsRequest {
43	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
44		write!(f, "http://statsapi.mlb.com/api/v1/people/{}/stats/game/{}?{}", self.person_id, self.game_id, self.bonus)
45	}
46}
47
48impl RequestURL for PersonSingleGameStatsRequest {
49	type Response = PersonSingleGameStatsResponse;
50}
51
52#[cfg(test)]
53mod tests {
54	use crate::person::stats::PersonSingleGameStatsRequest;
55	use crate::request::RequestURLBuilderExt;
56
57	#[tokio::test]
58	async fn single_sample() {
59		let _ = PersonSingleGameStatsRequest::builder()
60			.person_id(660_271)
61			.game_id(776_562)
62			.build_and_get()
63			.await
64			.unwrap();
65	}
66}
67
68#[derive(Debug, PartialEq, Eq, Clone)]
69pub struct SingleGameStats {
70	pub game_log: SingleGameStatsSimplifiedGameLogSplit,
71	pub vs_player5_y: SingleGameStatsVsPlayer5YSplit,
72	pub play_log: SingleGameStatsSimplifiedPlayLogSplit,
73}
74
75#[derive(Debug, PartialEq, Eq, Clone)]
76pub struct SingleGameStatsSimplifiedGameLogSplit {
77	pub hitting: Box<<GameLogStats as StatTypeStats>::Hitting>,
78	pub pitching: Box<<GameLogStats as StatTypeStats>::Pitching>,
79	pub fielding: Box<<GameLogStats as StatTypeStats>::Fielding>,
80}
81
82#[derive(Debug, PartialEq, Eq, Clone)]
83pub struct SingleGameStatsVsPlayer5YSplit {
84	pub hitting: Box<<__VsPlayer5YStatTypeStats as StatTypeStats>::Hitting>,
85	pub pitching: Box<<__VsPlayer5YStatTypeStats as StatTypeStats>::Pitching>,
86}
87
88#[derive(Debug, PartialEq, Eq, Clone)]
89pub struct SingleGameStatsSimplifiedPlayLogSplit {
90	pub hitting: Box<<PlayLogStats as StatTypeStats>::Hitting>,
91}
92
93impl<'de> Deserialize<'de> for SingleGameStats {
94	fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
95	where
96		Self: Sized,
97	{
98		let mut parsed_stats: __ParsedStats = <__ParsedStats as Deserialize>::deserialize(deserializer)?;
99
100		Ok(Self {
101			game_log: SingleGameStatsSimplifiedGameLogSplit {
102				hitting: Box::new(
103					make_stat_split::<<GameLogStats as StatTypeStats>::Hitting>(
104						&mut parsed_stats, "gameLog", StatGroup::Hitting,
105					).map_err(D::Error::custom)?
106				),
107				pitching: Box::new(
108					make_stat_split::<<GameLogStats as StatTypeStats>::Pitching>(
109						&mut parsed_stats, "gameLog", StatGroup::Pitching,
110					).map_err(D::Error::custom)?
111				),
112				fielding: Box::new(
113					make_stat_split::<<GameLogStats as StatTypeStats>::Fielding>(
114						&mut parsed_stats, "gameLog", StatGroup::Fielding,
115					).map_err(D::Error::custom)?
116				),
117			},
118			vs_player5_y: SingleGameStatsVsPlayer5YSplit {
119				hitting: Box::new(
120					make_stat_split::<<__VsPlayer5YStatTypeStats as StatTypeStats>::Hitting>(
121						&mut parsed_stats, "vsPlayer5Y", StatGroup::Hitting,
122					).map_err(D::Error::custom)?
123				),
124				pitching: Box::new(
125					make_stat_split::<<__VsPlayer5YStatTypeStats as StatTypeStats>::Pitching>(
126						&mut parsed_stats, "vsPlayer5Y", StatGroup::Pitching,
127					).map_err(D::Error::custom)?
128				),
129			},
130			play_log: SingleGameStatsSimplifiedPlayLogSplit {
131				hitting: Box::new(
132					make_stat_split::<<PlayLogStats as StatTypeStats>::Hitting>(
133						&mut parsed_stats, "playLog", StatGroup::Hitting,
134					).map_err(D::Error::custom)?
135				),
136			},
137		})
138	}
139}
140
141pub struct GameLogStats;
142
143impl StatTypeStats for GameLogStats {
144	type Hitting = WithNone<hitting::__SimplifiedGameLogStatsData>;
145	type Pitching = WithNone<pitching::__SimplifiedGameLogStatsData>;
146	type Fielding = WithNone<fielding::__SimplifiedGameLogStatsData>;
147	type Catching = ();
148}
149
150pub struct PlayLogStats;
151
152impl StatTypeStats for PlayLogStats {
153	type Hitting = Vec<WithNone<PlayStat>>;
154	type Pitching = Vec<WithNone<PlayStat>>;
155	type Fielding = Vec<WithNone<PlayStat>>;
156	type Catching = ();
157}
158
159impl Hydrations for SingleGameStats {}
160
161__stats__request_data!(pub SingleGameStats [Season]);
162
163impl HydrationText for SingleGameStats {
164	type RequestData = SingleGameStatsRequestData;
165
166	fn hydration_text(_: &Self::RequestData) -> Cow<'static, str> {
167		panic!("HydrationText::hydration_text() called on SingleGameStats. Must use `PersonSingleGameStatsRequest` instead.")
168	}
169}