Skip to main content

mlb_api/requests/stats/
macros.rs

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_rules! __stats__generate_needle_haystack_predicate {
45//     ($name:ident ! ( $($needle:ident),+ ) $d:tt) => {
46// 		#[macro_export]
47// 		#[doc(hidden)]
48// 		macro_rules! $name {
49// 			$(
50// 			([$needle $d (, $d haystack:ident)* $d (,)?] => { $d ($d t1:tt)* } else { $d ($d t2:tt)* }) => {
51// 				$d ($d t1)*
52// 			};
53// 			)+
54// 			([$d first:ident $d(, $d haystack:ident)* $d (,)?] => { $d ($d t1:tt)* } else { $d ($d t2:tt)* }) => {
55// 				$name!([$d($d haystack),*] => { $d ($d t1)* } else { $d ($d t2)* });
56// 			};
57//     		([$d(,)?] => { $d ($d t1:tt)* } else { $d ($d t2:tt)* }) => { $d ($d t2)* };
58// 		}
59//
60// 		#[doc(hidden)]
61// 		pub use $name;
62// 	};
63// }
64
65/// Generated by [`__stats__generate_needle_haystack_predicate`], cannot inline due to <https://github.com/rust-lang/rust/pull/52234>
66#[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/// Generated by [`__stats__generate_needle_haystack_predicate`], cannot inline due to <https://github.com/rust-lang/rust/pull/52234>
85#[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/// Generated by [`__stats__generate_needle_haystack_predicate`], cannot inline due to <https://github.com/rust-lang/rust/pull/52234>
101#[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/// Generated by [`__stats__generate_needle_haystack_predicate`], cannot inline due to <https://github.com/rust-lang/rust/pull/52234>
120#[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/// Generated by [`__stats__generate_needle_haystack_predicate`], cannot inline due to <https://github.com/rust-lang/rust/pull/52234>
136#[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				// $crate::__stats__request_data! { @ ? [$($stat_type),+]
271					$(#[$m])*
272					$vis struct $name {
273						$($field_tt)*
274						#[builder(into)]
275						opponent_player: $crate::person::PersonId,
276					}
277					$($impl_tt)*
278				// }
279			} else {
280				// $crate::__stats__request_data! { @ ? [$($stat_type),+]
281					$(#[$m])*
282					$vis struct $name {
283						$($field_tt)*
284					}
285					$($impl_tt)*
286				// }
287			}}
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					/*batter_team: TeamId,
309					pitcher_team: TeamId,
310					batter: PersonId,
311					pitcher: PersonId,
312					days_back: usize*/
313				}
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/// Generates stat data types to be used in requests.
454///
455/// These are commonly associated with [`person_hydrations`](crate::person_hydrations) to create a [`PersonRequest`](crate::person::PersonRequest).
456///
457/// # Stat Types & Stat Groups for [`stats!`](crate::stats!)
458///
459/// | Name                  | Stat Type                            | Stat Group | Notes                        |
460/// |-----------------------|--------------------------------------|------------|------------------------------|
461/// | `Projected`           | [`WithPlayer<_>`]                    | **`HP--`** | likely ZIPS projections      |
462/// | `YearByYear`          | [`HashMap<SeasonId, WithSeason<_>>`] | **`HPCF`** | 1.                           |
463/// | `YearByYearAdvanced`  | [`HashMap<SeasonId, WithSeason<_>>`] | **`HP--`** | 1.                           |
464/// | `Season`              | [`WithSeason<_>`]                    | **`HPCF`** |                              |
465/// | `Career`              | [`Career<_>`]                        | **`HPCF`** |                              |
466/// | `SeasonAdvanced`      | [`WithSeason<_>`]                    | **`HP--`** |                              |
467/// | `CareerAdvanced`      | [`Career<_>`]                        | **`HP--`** |                              |
468/// | `GameLog`             | [`Vec<WithGame<_>>`]                 | **`HPCF`** |                              |
469/// | `PlayLog`             | [`Vec<SingleMatchup<Play<_>>>`]      | **`HPCF`** | same format as in games      |
470/// | `PitchLog`            | [`Vec<SingleMatchup<PitchStat>>`]    | **`HPCF`** | same format as in games      |
471/// | `ExpectedStatistics`  | *no wrapper*                         | **`HP--`** | xAVG`, `xwOBA`, etc.         |
472/// | `Sabermetrics`        | *no wrapper*                         | **`HP--`** | xFIP`, `fWAR`, etc.          |
473/// | `VsPlayer5Y`          | [`AccumulatedVsPlayerMatchup<_>`]    | **`HP--`** | `opposing_player` in builder |
474/// | `LastXGames`          | [`WithTeam<_>`]                      | **`HPCF`** | `games_back` in builder      |
475/// | `ByDateRange`         | [`WithTeam<_>`]                      | **`HPCF`** | `date_range` in builder      |
476/// | `ByDateRangeAdvanced` | [`WithTeam<_>`]                      | **`HPCF`** | `date_range` in builder      |
477/// | `ByMonth`             | [`HashMap<Month, WithMonth<_>>`]     | **`HPCF`** |                              |
478/// | `ByDayOfWeek`         | [`HashMap<Weekday, WithWeekday<_>>`] | **`HPCF`** |                              |
479/// | `HomeAndAway`         | [`WithHomeAndAway<_>`]               | **`HPCF`** |                              |
480/// | `WinLoss`             | [`WithWinLoss<_>`]                   | **`HPCF`** |                              |
481/// | `OpponentsFaced`      | [`FieldedMatchup`]                   | **`HPCF`** |                              |
482/// | `StatSplits`          | [`WithSeason<_>`]                    | **`HP--`** | `situations` in builder      |
483/// | `StatSplitsAdvanced`  | [`WithSeason<_>`]                    | **`HP--`** | `situations` in builder      |
484///
485/// Note: `HPCF` stands for Hitting, Pitching, Catching, and Fielding. [`StatType`]s will be marked as for what [`StatGroup`]s they support in requests.
486///
487/// Table Footnotes
488/// 1. Seasons will display the last entry sent via the API, which is typically a full season with multiple teams, as opposed to the split with one team (ex. if a player is traded at the deadline).
489///
490/// # Examples
491///```
492/// mlb_api::stats! {
493///     pub struct MyStats {
494///         [Season, Career] = [Hitting, Pitching]
495///     }
496/// }
497///
498/// mlb_api::person_hydrations! {
499///     pub struct MyStatsHydrations {
500///         stats: MyStats,
501///     }
502/// }
503///
504/// let response = mlb_api::person::PersonRequest::<MyStatsHydrations>::builder()
505///     .id(id)
506///     .hydrations(MyStatsHydrations::builder()
507///         .stats(MyStats::builder()))
508///     .build_and_get()
509///     .await?;
510///
511/// // for simple requests which don't involve values supplied in the builder (see table above), this also works:
512/// let response = mlb_api::person::PersonRequest::<MyStatsHydrations>::for_id(id)
513///     .build_and_get()
514///     .await?;
515///
516/// let stats: &MyStats = &response.people[0].extras.stats;
517///```
518///
519/// [`HashMap<SeasonId, WithSeason<_>>`]: crate::stats::wrappers::WithSeason
520/// [`WithSeason<_>`]: crate::stats::wrappers::WithSeason
521/// [`Career<_>`]: crate::stats::wrappers::Career
522/// [`Vec<WithGame<_>>`]: crate::stats::wrappers::WithGame
523/// [`Vec<SingleMatchup<Play<_>>>`]: crate::stats::wrappers::SingleMatchup
524/// [`Vec<SingleMatchup<PitchStat>>`]: crate::stats::wrappers::SingleMatchup
525/// [`Vec<PitchUsage>`]: crate::stats::raw::PitchUsage
526/// [`AccumulatedVsPlayerMatchup<_>`]: crate::stats::wrappers::AccumulatedVsPlayerMatchup
527/// [`WithTeam<_>`]: crate::stats::wrappers::WithTeam
528/// [`HashMap<Month, WithMonth<_>>`]: crate::stats::wrappers::WithMonth
529/// [`HashMap<Weekday, WithWeekday<_>>`]: crate::stats::wrappers::WithWeekday
530/// [`WithHomeAndAway<_>`]: crate::stats::wrappers::WithHomeAndAway
531/// [`WithWinLoss<_>`]: crate::stats::wrappers::WithWinLoss
532/// [`HittingHotColdZones`]: crate::stats::raw::HittingHotColdZones
533/// [`PitchingHotColdZones`]: crate::stats::raw::PitchingHotColdZones
534/// [`FieldedMatchup`]: crate::stats::raw::FieldedMatchup
535/// [`StatType`]: crate::stat_types::StatType
536/// [`StatGroup`]: crate::stat_groups::StatGroup
537/// [`WithPlayer<_>`]: crate::stats::wrappers::WithPlayer
538#[macro_export]
539macro_rules! stats {
540    ($($t:tt)*) => {
541		$crate::__stats0! { $($t)* }
542	};
543}