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