mlb_api/requests/person/
stats.rs1use 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}