mlb_api/endpoints/person/
types.rs1use std::ops::{Deref, DerefMut};
2use chrono::NaiveDate;
3use derive_more::{Deref, Display, DerefMut};
4use serde::Deserialize;
5use crate::types::{Gender, Handedness, HeightMeasurement, Position};
6
7#[derive(Debug, Deref, DerefMut, Deserialize, PartialEq, Eq, Clone)]
8#[serde(rename_all = "camelCase")]
9pub struct Ballplayer {
10 #[deref]
11 #[deref_mut]
12 #[serde(flatten)]
13 inner: HydratedPerson,
14
15 #[serde(deserialize_with = "crate::types::from_str")]
16 pub primary_number: u8,
17 pub current_age: u8,
18 #[serde(flatten)]
19 pub birth_data: BirthData,
20 #[serde(flatten)]
21 pub body_measurements: BodyMeasurements,
22 pub gender: Gender,
23 pub draft_year: u16,
24 #[serde(rename = "mlbDebutDate")] pub mlb_debut: NaiveDate,
25 pub bat_side: Handedness,
26 pub pitch_hand: Handedness,
27 #[serde(flatten)]
28 pub strike_zone: StrikeZone,
29}
30
31#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
32#[serde(rename_all = "camelCase")]
33pub struct BirthData {
34 pub birth_date: NaiveDate,
35 pub birth_city: String,
36 #[serde(rename = "birthStateProvince")] pub birth_state_or_province: String,
37 pub birth_country: String,
38}
39
40#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
41#[serde(rename_all = "camelCase")]
42pub struct BodyMeasurements {
43 #[serde(deserialize_with = "crate::types::from_str")]
44 pub height: HeightMeasurement,
45 pub weight: u16,
46}
47
48#[derive(Debug, Deserialize, PartialEq, Clone)]
49#[serde(rename_all = "camelCase")]
50pub struct StrikeZone {
51 pub strike_zone_top: f64,
52 pub strike_zone_bottom: f64,
53}
54
55impl Eq for StrikeZone {}
56
57#[derive(Debug, Deref, DerefMut, Deserialize, PartialEq, Eq, Clone)]
58#[serde(rename_all = "camelCase")]
59pub struct HydratedPerson {
60 #[deref]
61 #[deref_mut]
62 #[serde(flatten)]
63 inner: UnhydratedPerson,
64
65 pub primary_position: Position,
66 #[serde(default)]
68 pub first_name: String,
69 pub middle_name: Option<String>,
70 #[serde(default)]
71 pub last_name: String,
72 #[serde(default)]
73 #[serde(rename = "useName")] pub use_first_name: String,
74 #[serde(default)]
75 pub use_last_name: String,
76 #[serde(default)]
77 pub boxscore_name: String,
78
79 pub is_player: bool,
80 pub is_verified: bool,
81 pub active: bool,
82}
83
84impl HydratedPerson {
85 #[must_use]
86 pub fn name_first_last(&self) -> String {
87 format!("{0} {1}", self.first_name, self.last_name)
88 }
89
90 #[must_use]
91 pub fn name_last_first(&self) -> String {
92 format!("{1}, {0}", self.first_name, self.last_name)
93 }
94
95 #[must_use]
96 pub fn name_last_first_initial(&self) -> String {
97 if let Some(char) = self.first_name.chars().next() {
98 format!("{1}, {0}", char, self.last_name)
99 } else {
100 self.last_name.clone()
101 }
102 }
103
104 #[must_use]
105 pub fn name_first_initial_last(&self) -> String {
106 if let Some(char) = self.first_name.chars().next() {
107 format!("{0} {1}", char, self.last_name)
108 } else {
109 self.last_name.clone()
110 }
111 }
112
113 #[must_use]
114 pub fn name_fml(&self) -> String {
115 if let Some(middle) = &self.middle_name {
116 format!("{0} {1} {2}", self.first_name, middle, self.last_name)
117 } else {
118 format!("{0} {1}", self.first_name, self.last_name)
119 }
120 }
121
122 #[must_use]
123 pub fn name_lfm(&self) -> String {
124 if let Some(middle) = &self.middle_name {
125 format!("{2}, {0} {1}", self.first_name, middle, self.last_name)
126 } else {
127 format!("{1}, {0}", self.first_name, self.last_name)
128 }
129 }
130}
131
132#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
133#[serde(rename_all = "camelCase")]
134pub struct UnhydratedPerson {
135 pub id: PersonId,
136 pub full_name: String,
137}
138
139#[repr(transparent)]
140#[derive(Debug, Deref, Display, Deserialize, PartialEq, Eq, Clone)]
141pub struct PersonId(u32);
142
143#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
144#[serde(untagged)]
145pub enum Person {
146 Ballplayer(Ballplayer),
147 Hydrated(HydratedPerson),
148 Unhydrated(UnhydratedPerson),
149}
150
151impl Deref for Person {
152 type Target = UnhydratedPerson;
153
154 fn deref(&self) -> &Self::Target {
155 match self {
156 Self::Ballplayer(inner) => inner,
157 Self::Hydrated(inner) => inner,
158 Self::Unhydrated(inner) => inner,
159 }
160 }
161}
162
163impl DerefMut for Person {
164 fn deref_mut(&mut self) -> &mut Self::Target {
165 match self {
166 Self::Ballplayer(inner) => inner,
167 Self::Hydrated(inner) => inner,
168 Self::Unhydrated(inner) => inner,
169 }
170 }
171}