Skip to main content

mlb_api/requests/person/
stats.rs

1//! Gets the stats of a player for a single game.
2
3use crate::game::GameId;
4use crate::person::PersonId;
5use crate::Copyright;
6use bon::Builder;
7use serde::Deserialize;
8use std::fmt::{Display, Formatter};
9use serde::de::{Deserializer, Error};
10use crate::stats::raw::PlayStat;
11use crate::request::RequestURL;
12use crate::meta::StatGroup;
13use crate::stats::parse::{__ParsedStats, make_stat_split};
14use crate::stats::raw::{fielding, hitting, pitching};
15use crate::stats::wrappers::{AccumulatedVsPlayerMatchup, WithNone};
16
17#[derive(Debug, Deserialize, PartialEq, Clone)]
18pub struct PersonSingleGameStatsResponse {
19	pub copyright: Copyright,
20	#[serde(flatten)]
21	pub stats: SingleGameStats,
22}
23
24#[derive(Builder)]
25#[builder(derive(Into))]
26pub struct PersonSingleGameStatsRequest {
27	#[builder(into)]
28	person_id: PersonId,
29	#[builder(into)]
30	game_id: GameId,
31}
32
33impl<S: person_single_game_stats_request_builder::State + person_single_game_stats_request_builder::IsComplete> crate::request::RequestURLBuilderExt for PersonSingleGameStatsRequestBuilder<S> {
34	type Built = PersonSingleGameStatsRequest;
35}
36
37impl Display for PersonSingleGameStatsRequest {
38	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
39		write!(f, "http://statsapi.mlb.com/api/v1/people/{}/stats/game{}", self.person_id, self.game_id)
40	}
41}
42
43impl RequestURL for PersonSingleGameStatsRequest {
44	type Response = PersonSingleGameStatsResponse;
45}
46
47#[cfg(test)]
48mod tests {
49	use crate::person::stats::PersonSingleGameStatsRequest;
50	use crate::request::RequestURLBuilderExt;
51
52	#[tokio::test]
53	async fn single_sample() {
54		let _ = PersonSingleGameStatsRequest::builder()
55			.person_id(660_271)
56			.game_id(776_562)
57			.build_and_get()
58			.await
59			.unwrap();
60	}
61}
62
63#[derive(Debug, PartialEq, Clone)]
64pub struct SingleGameStats {
65	pub game_log: SingleGameStatsSimplifiedGameLogSplit,
66	pub vs_player5_y: SingleGameStatsVsPlayer5YSplit,
67	pub play_log: SingleGameStatsSimplifiedPlayLogSplit,
68}
69
70#[derive(Debug, PartialEq, Clone)]
71pub struct SingleGameStatsSimplifiedGameLogSplit {
72	pub hitting: Box<WithNone<hitting::__SimplifiedGameLogStatsData>>,
73	pub pitching: Box<WithNone<pitching::__SimplifiedGameLogStatsData>>,
74	pub fielding: Box<WithNone<fielding::__SimplifiedGameLogStatsData>>,
75}
76
77#[derive(Debug, PartialEq, Clone)]
78pub struct SingleGameStatsVsPlayer5YSplit {
79	pub hitting: Box<AccumulatedVsPlayerMatchup<hitting::__VsPlayerStatsData>>,
80	pub pitching: Box<AccumulatedVsPlayerMatchup<pitching::__VsPlayerStatsData>>,
81}
82
83#[derive(Debug, PartialEq, Clone)]
84pub struct SingleGameStatsSimplifiedPlayLogSplit {
85	pub hitting: Box<Vec<WithNone<PlayStat>>>,
86}
87
88impl<'de> Deserialize<'de> for SingleGameStats {
89	fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
90	where
91		Self: Sized,
92	{
93		let mut parsed_stats: __ParsedStats = <__ParsedStats as Deserialize>::deserialize(deserializer)?;
94
95		Ok(Self {
96			game_log: SingleGameStatsSimplifiedGameLogSplit {
97				hitting: Box::new(
98					make_stat_split::<WithNone<hitting::__SimplifiedGameLogStatsData>>(
99						&mut parsed_stats, "gameLog", StatGroup::Hitting,
100					).map_err(D::Error::custom)?
101				),
102				pitching: Box::new(
103					make_stat_split::<WithNone<pitching::__SimplifiedGameLogStatsData>>(
104						&mut parsed_stats, "gameLog", StatGroup::Pitching,
105					).map_err(D::Error::custom)?
106				),
107				fielding: Box::new(
108					make_stat_split::<WithNone<fielding::__SimplifiedGameLogStatsData>>(
109						&mut parsed_stats, "gameLog", StatGroup::Fielding,
110					).map_err(D::Error::custom)?
111				),
112			},
113			vs_player5_y: SingleGameStatsVsPlayer5YSplit {
114				hitting: Box::new(
115					make_stat_split::<AccumulatedVsPlayerMatchup<hitting::__VsPlayerStatsData>>(
116						&mut parsed_stats, "vsPlayer5Y", StatGroup::Hitting,
117					).map_err(D::Error::custom)?
118				),
119				pitching: Box::new(
120					make_stat_split::<AccumulatedVsPlayerMatchup<pitching::__VsPlayerStatsData>>(
121						&mut parsed_stats, "vsPlayer5Y", StatGroup::Pitching,
122					).map_err(D::Error::custom)?
123				),
124			},
125			play_log: SingleGameStatsSimplifiedPlayLogSplit {
126				hitting: Box::new(
127					make_stat_split::<Vec<WithNone<PlayStat>>>(
128						&mut parsed_stats, "playLog", StatGroup::Hitting,
129					).map_err(D::Error::custom)?
130				),
131			},
132		})
133	}
134}