use crate::types::common::LocalizedString;
use crate::types::enums::{Handedness, HomeRoad, Position};
use crate::types::game_type::GameType;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PlayerLanding {
pub player_id: i64,
pub is_active: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub current_team_id: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub current_team_abbrev: Option<String>,
pub first_name: LocalizedString,
pub last_name: LocalizedString,
#[serde(skip_serializing_if = "Option::is_none")]
pub sweater_number: Option<i32>,
pub position: Position,
pub headshot: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub hero_image: Option<String>,
pub height_in_inches: i32,
pub weight_in_pounds: i32,
pub birth_date: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub birth_city: Option<LocalizedString>,
#[serde(skip_serializing_if = "Option::is_none")]
pub birth_state_province: Option<LocalizedString>,
#[serde(skip_serializing_if = "Option::is_none")]
pub birth_country: Option<String>,
pub shoots_catches: Handedness,
#[serde(skip_serializing_if = "Option::is_none")]
pub draft_details: Option<DraftDetails>,
#[serde(skip_serializing_if = "Option::is_none")]
pub player_slug: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub featured_stats: Option<FeaturedStats>,
#[serde(skip_serializing_if = "Option::is_none")]
pub career_totals: Option<CareerTotals>,
#[serde(skip_serializing_if = "Option::is_none")]
pub season_totals: Option<Vec<SeasonTotal>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub awards: Option<Vec<Award>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_five_games: Option<Vec<GameLog>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct DraftDetails {
pub year: i32,
pub team_abbrev: String,
pub round: i32,
pub pick_in_round: i32,
pub overall_pick: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct FeaturedStats {
pub season: i32,
pub regular_season: PlayerStats,
#[serde(skip_serializing_if = "Option::is_none")]
pub playoffs: Option<PlayerStats>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct CareerTotals {
pub regular_season: PlayerStats,
#[serde(skip_serializing_if = "Option::is_none")]
pub playoffs: Option<PlayerStats>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PlayerStats {
#[serde(skip_serializing_if = "Option::is_none")]
pub games_played: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub goals: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assists: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub points: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub plus_minus: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pim: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub power_play_goals: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub power_play_points: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub short_handed_goals: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub short_handed_points: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shots: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shooting_pctg: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub faceoff_win_pctg: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub avg_toi: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub wins: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub losses: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ot_losses: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shutouts: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub goals_against_avg: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub save_pctg: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SeasonTotal {
pub season: i32,
#[serde(rename = "gameTypeId")]
pub game_type: GameType,
pub league_abbrev: String,
pub team_name: LocalizedString,
#[serde(skip_serializing_if = "Option::is_none")]
pub team_common_name: Option<LocalizedString>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sequence: Option<i32>,
pub games_played: i32,
#[serde(skip_serializing_if = "Option::is_none")]
pub goals: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assists: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub points: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub plus_minus: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pim: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Award {
pub trophy: LocalizedString,
pub seasons: Vec<AwardSeason>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AwardSeason {
pub season_id: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct GameLog {
pub game_id: i64,
pub game_date: String,
pub team_abbrev: String,
pub home_road_flag: HomeRoad,
pub opponent_abbrev: String,
pub goals: i32,
pub assists: i32,
pub points: i32,
pub plus_minus: i32,
pub power_play_goals: i32,
pub power_play_points: i32,
pub shots: i32,
pub shifts: i32,
pub toi: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub game_winning_goals: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ot_goals: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pim: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PlayerGameLog {
#[serde(skip)]
pub player_id: i64,
#[serde(rename = "seasonId")]
pub season: i32,
#[serde(rename = "gameTypeId")]
pub game_type: GameType,
pub game_log: Vec<GameLog>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PlayerSearchResult {
#[serde(rename = "playerId")]
pub player_id: String,
pub name: String,
#[serde(rename = "positionCode")]
pub position: Position,
#[serde(skip_serializing_if = "Option::is_none")]
pub team_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub team_abbrev: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sweater_number: Option<i32>,
pub active: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub height: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub birth_city: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub birth_state_province: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub birth_country: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_player_stats_deserialization() {
let json = r#"{
"gamesPlayed": 82,
"goals": 41,
"assists": 52,
"points": 93,
"plusMinus": 21,
"pim": 40,
"powerPlayGoals": 15,
"powerPlayPoints": 40,
"shots": 305,
"shootingPctg": 0.134,
"faceoffWinPctg": 0.489,
"avgToi": "21:30"
}"#;
let stats: PlayerStats = serde_json::from_str(json).unwrap();
assert_eq!(stats.games_played, Some(82));
assert_eq!(stats.goals, Some(41));
assert_eq!(stats.assists, Some(52));
assert_eq!(stats.points, Some(93));
assert_eq!(stats.plus_minus, Some(21));
}
#[test]
fn test_draft_details_deserialization() {
let json = r#"{
"year": 2015,
"teamAbbrev": "EDM",
"round": 1,
"pickInRound": 1,
"overallPick": 1
}"#;
let draft: DraftDetails = serde_json::from_str(json).unwrap();
assert_eq!(draft.year, 2015);
assert_eq!(draft.team_abbrev, "EDM");
assert_eq!(draft.overall_pick, 1);
}
#[test]
fn test_player_search_result_deserialization() {
let json = r#"{
"playerId": "8478402",
"name": "Connor McDavid",
"positionCode": "C",
"teamId": "22",
"teamAbbrev": "EDM",
"sweaterNumber": 97,
"active": true,
"height": "6'1\"",
"birthCity": "Richmond Hill",
"birthStateProvince": "ON",
"birthCountry": "CAN"
}"#;
let result: PlayerSearchResult = serde_json::from_str(json).unwrap();
assert_eq!(result.player_id, "8478402");
assert_eq!(result.name, "Connor McDavid");
assert_eq!(result.position, Position::Center);
assert!(result.active);
}
}