1#[macro_export]
2#[doc(hidden)]
3macro_rules! __stats__stat_type_definition {
4 ($parent_name:ident => $vis:vis struct $name:ident { $stat_type:ident => [$($stat_group:ident),+] }) => {
5 ::pastey::paste! {
6 #[derive(Debug, PartialEq, Eq, Clone)]
7 $vis struct $name {
8 $($vis [< $stat_group:snake >]: ::std::boxed::Box<<$crate::stats::stat_types::[<__ $stat_type StatTypeStats>] as $crate::stats::StatTypeStats>::$stat_group>),+
9 }
10
11 impl [<__ $parent_name Split Parser>] for $name {
12 fn parse(parsed_stats: &mut $crate::stats::parse::__ParsedStats) -> ::core::result::Result<Self, ::std::string::String> {
13 Ok(Self {
14 $([<$stat_group:snake>]: ::std::boxed::Box::new(
15 $crate::stats::parse::make_stat_split::<<$crate::stats::stat_types::[< __ $stat_type StatTypeStats >] as $crate::stats::StatTypeStats>::$stat_group>(
16 parsed_stats, ::core::stringify!([<$stat_type:lower_camel>]), $crate::stat_groups::StatGroup::$stat_group
17 ).map_err(|e| ::std::string::ToString::to_string(&e))?
18 )),+
19 })
20 }
21 }
22 }
23 };
24}
25
26#[macro_export]
27#[doc(hidden)]
28macro_rules! __stats__base_hydration_text {
29 ([$first_stat_type:ident $(, $stat_type:ident)* $(,)?] [$first_stat_group:ident $(, $stat_group:ident)* $(,)?]) => {
30 ::pastey::paste! {
31 ::core::concat!(
32 "type=[",
33 ::core::stringify!([<$first_stat_type:lower_camel>]),
34 $(",", ::core::stringify!([<$stat_type:lower_camel>]), )*
35 "],group=[",
36 ::core::stringify!([<$first_stat_group:lower_camel>]),
37 $(",", ::core::stringify!([<$stat_group:lower_camel>]), )*
38 "]"
39 )
40 }
41 };
42}
43
44#[macro_export]
67#[doc(hidden)]
68macro_rules! __stats__needle_haystack_metrics {
69 ([$($haystack:ident),+ $(,)?] => { $($t:tt)* }) => {
70 $crate::__stats__needle_haystack_metrics!([$($haystack),+] => { $($t)* } else {});
71 };
72 ([MetricLog $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
73 $($t1)*
74 };
75 ([MetricAverages $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
76 $($t1)*
77 };
78 ([$first:ident $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
79 $crate::__stats__needle_haystack_metrics!([$($haystack),*] => { $($t1)* } else { $($t2)* });
80 };
81 ([$(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => { $($t2)* };
82}
83
84#[macro_export]
86#[doc(hidden)]
87macro_rules! __stats__needle_haystack_date_range {
88 ([$($haystack:ident),+ $(,)?] => { $($t:tt)* }) => {
89 $crate::__stats__needle_haystack_date_range!([$($haystack),+] => { $($t)* } else {});
90 };
91 ([ByDateRange $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
92 $($t1)*
93 };
94 ([$first:ident $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
95 $crate::__stats__needle_haystack_date_range!([$($haystack),*] => { $($t1)* } else { $($t2)* });
96 };
97 ([$(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => { $($t2)* };
98}
99
100#[macro_export]
102#[doc(hidden)]
103macro_rules! __stats__needle_haystack_situations {
104 ([$($haystack:ident),+ $(,)?] => { $($t:tt)* }) => {
105 $crate::__stats__needle_haystack_situations!([$($haystack),+] => { $($t)* } else {});
106 };
107 ([StatSplits $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
108 $($t1)*
109 };
110 ([StatSplitsAdvanced $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
111 $($t1)*
112 };
113 ([$first:ident $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
114 $crate::__stats__needle_haystack_situations!([$($haystack),*] => { $($t1)* } else { $($t2)* });
115 };
116 ([$(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => { $($t2)* };
117}
118
119#[macro_export]
121#[doc(hidden)]
122macro_rules! __stats__needle_haystack_games_back {
123 ([$($haystack:ident),+ $(,)?] => { $($t:tt)* }) => {
124 $crate::__stats__needle_haystack_games_back!([$($haystack),+] => { $($t)* } else {});
125 };
126 ([LastXGames $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
127 $($t1)*
128 };
129 ([$first:ident $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
130 $crate::__stats__needle_haystack_games_back!([$($haystack),*] => { $($t1)* } else { $($t2)* });
131 };
132 ([$(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => { $($t2)* };
133}
134
135#[macro_export]
137#[doc(hidden)]
138macro_rules! __stats__needle_haystack_opponent_player {
139 ([$($haystack:ident),+ $(,)?] => { $($t:tt)* }) => {
140 $crate::__stats__needle_haystack_opponent_player!([$($haystack),+] => { $($t)* } else {});
141 };
142 ([VsPlayer5Y $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
143 $($t1)*
144 };
145 ([VsPlayerTotal $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
146 $($t1)*
147 };
148 ([VsPlayer $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
149 $($t1)*
150 };
151 ([$first:ident $(, $haystack:ident)* $(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => {
152 $crate::__stats__needle_haystack_opponent_player!([$($haystack),*] => { $($t1)* } else { $($t2)* });
153 };
154 ([$(,)?] => { $($t1:tt)* } else { $($t2:tt)* }) => { $($t2)* };
155}
156
157#[macro_export]
158#[doc(hidden)]
159macro_rules! __stats__request_data {
160 (@ metrics [$($stat_type:ident),+] $(#[$m:meta])* $vis:vis struct $name:ident { $($field_tt:tt)* } $($impl_tt:tt)*) => {
161 ::pastey::paste! {
162 $crate::__stats__needle_haystack_metrics! { [$($stat_type),+] => {
163 $crate::__stats__request_data! { @ date_range [$($stat_type),+]
164 $(#[$m])*
165 $vis struct $name {
166 $($field_tt)*
167 metrics: ::std::vec::Vec<$crate::metrics::MetricId>,
168 }
169 $($impl_tt)*
170 impl<S: [<$name:snake _builder>]::State> [<$name Builder>]<S> {
171 pub fn metric(self, metric: impl ::core::convert::Into<$crate::metrics::MetricId>) -> [<$name Builder>]<[<$name:snake _builder>]::SetMetrics<S>>
172 where
173 S::Metrics: [<$name:snake _builder>]::IsUnset
174 {
175 self.metrics(::std::vec![::core::convert::Into::into(metric)])
176 }
177 }
178 }
179 } else {
180 $crate::__stats__request_data! { @ date_range [$($stat_type),+]
181 $(#[$m])*
182 $vis struct $name {
183 $($field_tt)*
184 }
185 $($impl_tt)*
186 }
187 }}
188 }
189 };
190 (@ date_range [$($stat_type:ident),+] $(#[$m:meta])* $vis:vis struct $name:ident { $($field_tt:tt)* } $($impl_tt:tt)*) => {
191 ::pastey::paste! {
192 $crate::__stats__needle_haystack_date_range!{[$($stat_type),+] => {
193 $crate::__stats__request_data! { @ situations [$($stat_type),+]
194 $(#[$m])*
195 $vis struct $name {
196 $($field_tt)*
197 date_range: $crate::types::NaiveDateRange,
198 }
199 $($impl_tt)*
200 }
201 } else {
202 $crate::__stats__request_data! { @ situations [$($stat_type),+]
203 $(#[$m])*
204 $vis struct $name {
205 $($field_tt)*
206 }
207 $($impl_tt)*
208 }
209 }}
210 }
211 };
212 (@ situations [$($stat_type:ident),+] $(#[$m:meta])* $vis:vis struct $name:ident { $($field_tt:tt)* } $($impl_tt:tt)*) => {
213 ::pastey::paste! {
214 $crate::__stats__needle_haystack_situations!{[$($stat_type),+] => {
215 $crate::__stats__request_data! { @ games_back [$($stat_type),+]
216 $(#[$m])*
217 $vis struct $name {
218 $($field_tt)*
219 situations: ::std::vec::Vec<$crate::situations::SituationCodeId>,
220 #[builder(default)]
221 situation_filter: $crate::situations::SituationCodeFilter,
222 }
223 $($impl_tt)*
224 impl<S: [<$name:snake _builder>]::State> [<$name Builder>]<S> {
225 #[allow(dead_code)]
226 pub fn situation(self, situation: impl ::core::convert::Into<$crate::situations::SituationCodeId>) -> [<$name Builder>]<[<$name:snake _builder>]::SetSituations<S>>
227 where
228 S::Situations: [<$name:snake _builder>]::IsUnset
229 {
230 self.situations(::std::vec![::core::convert::Into::into(situation)])
231 }
232 }
233 }
234 } else {
235 $crate::__stats__request_data! { @ games_back [$($stat_type),+]
236 $(#[$m])*
237 $vis struct $name {
238 $($field_tt)*
239 }
240 $($impl_tt)*
241 }
242 }}
243 }
244 };
245 (@ games_back [$($stat_type:ident),+] $(#[$m:meta])* $vis:vis struct $name:ident { $($field_tt:tt)* } $($impl_tt:tt)*) => {
246 ::pastey::paste! {
247 $crate::__stats__needle_haystack_games_back!{[$($stat_type),+] => {
248 $crate::__stats__request_data! { @ opponent_player [$($stat_type),+]
249 $(#[$m])*
250 $vis struct $name {
251 $($field_tt)*
252 games_back: usize,
253 }
254 $($impl_tt)*
255 }
256 } else {
257 $crate::__stats__request_data! { @ opponent_player [$($stat_type),+]
258 $(#[$m])*
259 $vis struct $name {
260 $($field_tt)*
261 }
262 $($impl_tt)*
263 }
264 }}
265 }
266 };
267 (@ opponent_player [$($stat_type:ident),+] $(#[$m:meta])* $vis:vis struct $name:ident { $($field_tt:tt)* } $($impl_tt:tt)*) => {
268 ::pastey::paste! {
269 $crate::__stats__needle_haystack_opponent_player!{[$($stat_type),+] => {
270 $(#[$m])*
272 $vis struct $name {
273 $($field_tt)*
274 #[builder(into)]
275 opponent_player: $crate::person::PersonId,
276 }
277 $($impl_tt)*
278 } else {
280 $(#[$m])*
282 $vis struct $name {
283 $($field_tt)*
284 }
285 $($impl_tt)*
286 }}
288 }
289 };
290 ($vis:vis $name:ident [$($stat_type:ident),+]) => {
291 ::pastey::paste! {
292 $crate::__stats__request_data! { @ metrics [$($stat_type),+]
293 #[derive(::bon::Builder)]
294 #[builder(derive(Into))]
295 #[allow(unused)]
296 $vis struct [<$name RequestData>] {
297 #[builder(default)]
298 game_type: $crate::game_types::GameType,
299 #[builder(into)]
300 season: ::core::option::Option<$crate::season::SeasonId>,
301 team_ids: ::core::option::Option<::std::vec::Vec<$crate::team::TeamId>>,
302 sport_ids: ::core::option::Option<::std::vec::Vec<$crate::sport::SportId>>,
303 league_ids: ::core::option::Option<::std::vec::Vec<$crate::league::LeagueId>>,
304 #[builder(default)]
305 player_pool: $crate::types::PlayerPool,
306
307
308 }
314
315 #[allow(unused)]
316 impl<S: [<$name:snake _request_data_builder>]::State> [<$name RequestDataBuilder>]<S> {
317 pub fn team_id(self, team_id: impl ::core::convert::Into<$crate::team::TeamId>) -> [<$name RequestDataBuilder>]<[<$name:snake _request_data_builder>]::SetTeamIds<S>>
318 where
319 S::TeamIds: [<$name:snake _request_data_builder>]::IsUnset
320 {
321 self.team_ids(::std::vec![::core::convert::Into::into(team_id)])
322 }
323
324 pub fn sport_id(self, sport_id: impl ::core::convert::Into<$crate::sport::SportId>) -> [<$name RequestDataBuilder>]<[<$name:snake _request_data_builder>]::SetSportIds<S>>
325 where
326 S::SportIds: [<$name:snake _request_data_builder>]::IsUnset
327 {
328 self.sport_ids(::std::vec![::core::convert::Into::into(sport_id)])
329 }
330
331 pub fn league_id(self, league_id: impl ::core::convert::Into<$crate::league::LeagueId>) -> [<$name RequestDataBuilder>]<[<$name:snake _request_data_builder>]::SetLeagueIds<S>>
332 where
333 S::LeagueIds: [<$name:snake _request_data_builder>]::IsUnset
334 {
335 self.league_ids(::std::vec![::core::convert::Into::into(league_id)])
336 }
337 }
338 }
339
340 impl ::core::fmt::Display for [<$name RequestData>] {
341 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
342 use ::itertools::Itertools;
343
344 ::core::fmt::Write::write_fmt(f, ::core::format_args!("gameType={:?},", self.game_type))?;
345 if let ::core::option::Option::Some(season) = self.season {
346 ::core::fmt::Write::write_fmt(f, ::core::format_args!("season={},", season))?;
347 }
348 if let ::core::option::Option::Some(ids) = ::core::option::Option::as_ref(&self.team_ids) {
349 ::core::fmt::Write::write_fmt(f, ::core::format_args!("teamIds=[{}],", ids.iter().join(",")))?;
350 }
351 if let ::core::option::Option::Some(ids) = ::core::option::Option::as_ref(&self.sport_ids) {
352 ::core::fmt::Write::write_fmt(f, ::core::format_args!("sportIds=[{}],", ids.iter().join(",")))?;
353 }
354 if let ::core::option::Option::Some(ids) = ::core::option::Option::as_ref(&self.league_ids) {
355 ::core::fmt::Write::write_fmt(f, ::core::format_args!("leagueIds=[{}],", ids.iter().join(",")))?;
356 }
357 ::core::fmt::Write::write_fmt(f, ::core::format_args!("playerPool={},", self.player_pool))?;
358
359 $crate::__stats__needle_haystack_metrics! { [$($stat_type),+] => {
360 ::core::fmt::Write::write_fmt(f, ::core::format_args!("metrics={},", self.metrics.iter().join(",")))?;
361 } else {}}
362 $crate::__stats__needle_haystack_date_range! { [$($stat_type),+] => {
363 ::core::fmt::Write::write_fmt(f, ::core::format_args!("startDate={},endDate={},", self.date_range.start().format($crate::types::MLB_API_DATE_FORMAT), self.date_range.end().format($crate::types::MLB_API_DATE_FORMAT)))?;
364 } else {}}
365 $crate::__stats__needle_haystack_situations! { [$($stat_type),+] => {
366 ::core::fmt::Write::write_fmt(f, ::core::format_args!("sitCodes=[{}],combineSits={},", self.situations.iter().join(","), self.situation_filter == $crate::situations::SituationCodeFilter::All))?;
367 } else {}}
368 $crate::__stats__needle_haystack_opponent_player! { [$($stat_type),+] => {
369 ::core::fmt::Write::write_fmt(f, ::core::format_args!("opposingPlayerId={},", self.opponent_player))?;
370 } else {}}
371
372 Ok(())
373 }
374 }
375
376 $crate::__stats__needle_haystack_metrics! { [$($stat_type),+] => {} else {
377 $crate::__stats__needle_haystack_date_range! { [$($stat_type),+] => {} else {
378 $crate::__stats__needle_haystack_situations! { [$($stat_type),+] => {} else {
379 impl ::core::default::Default for [<$name RequestData>] {
380 fn default() -> Self {
381 [<$name RequestDataBuilder>]::<[<$name:snake _request_data_builder>]::Empty>::build(Self::builder())
382 }
383 }
384 }}
385 }}
386 }}
387
388 impl $name {
389 #[allow(unused)]
390 pub fn builder() -> [<$name RequestDataBuilder>] {
391 [<$name RequestData>]::builder()
392 }
393 }
394 }
395 };
396}
397
398#[doc(hidden)]
399#[macro_export]
400macro_rules! __stats0 {
401 ($vis:vis struct $name:ident {
402 [$($stat_type:ident),+ $(,)?] = $stat_groups:tt
403 }) => {
404 ::pastey::paste! {
405 #[derive(Debug, PartialEq, Eq, Clone)]
406 $vis struct $name {
407 $($vis [<$stat_type:snake>]: [<$name $stat_type Split>],)*
408 }
409
410 #[doc(hidden)]
411 trait [<__ $name Split Parser>] {
412 fn parse(parsed_stats: &mut $crate::stats::parse::__ParsedStats) -> ::core::result::Result<Self, ::std::string::String>
413 where
414 Self: Sized;
415 }
416
417 $($crate::__stats__stat_type_definition!($name => $vis struct [<$name $stat_type Split>] { $stat_type => $stat_groups });)+
418
419 impl<'de> ::serde::Deserialize<'de> for $name {
420 fn deserialize<D: ::serde::de::Deserializer<'de>>(deserializer: D) -> ::core::result::Result<Self, D::Error>
421 where
422 Self: Sized
423 {
424 let mut parsed_stats: $crate::stats::parse::__ParsedStats = <$crate::stats::parse::__ParsedStats as ::serde::Deserialize>::deserialize(deserializer)?;
425
426 Ok(Self {
427 $([<$stat_type:snake>]: <[<$name $stat_type Split>] as [<__ $name Split Parser>]>::parse(&mut parsed_stats).map_err(<D::Error as ::serde::de::Error>::custom)?),+
428 })
429 }
430 }
431
432 impl $crate::hydrations::Hydrations for $name {}
433
434 $crate::__stats__request_data!($vis $name [$($stat_type),+]);
435
436 impl $crate::hydrations::HydrationText for $name {
437 type RequestData = [<$name RequestData>];
438
439 fn hydration_text(data: &<Self as $crate::hydrations::HydrationText>::RequestData) -> ::std::borrow::Cow<'static, str> {
440 let base: &'static str = $crate::__stats__base_hydration_text!([$($stat_type),+] $stat_groups);
441 let data: ::std::string::String = ::std::string::ToString::to_string(data);
442 if str::is_empty(&*data) {
443 ::std::borrow::Cow::Borrowed(base)
444 } else {
445 ::std::borrow::Cow::Owned(::std::format!("{base},{data}"))
446 }
447 }
448 }
449 }
450 };
451}
452
453#[macro_export]
539macro_rules! stats {
540 ($($t:tt)*) => {
541 $crate::__stats0! { $($t)* }
542 };
543}