2025-04-02 20:39:30 -04:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use serde_alias::serde_alias;
|
2025-04-05 21:14:52 -04:00
|
|
|
use chrono::{DateTime, Utc};
|
|
|
|
|
use chrono_tz::US::Eastern;
|
2025-04-02 20:39:30 -04:00
|
|
|
|
2025-04-05 20:19:42 -04:00
|
|
|
const TEAM_ID: i32 = 111;
|
2025-04-02 20:39:30 -04:00
|
|
|
|
|
|
|
|
#[serde_alias(CamelCase,SnakeCase)]
|
2025-04-05 18:39:04 -04:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
2025-04-02 20:39:30 -04:00
|
|
|
pub struct Schedule {
|
2025-04-05 18:39:04 -04:00
|
|
|
pub dates: Vec<Date>,
|
2025-04-02 20:39:30 -04:00
|
|
|
}
|
|
|
|
|
|
2025-04-05 18:39:04 -04:00
|
|
|
#[serde_alias(CamelCase,SnakeCase)]
|
2025-04-02 20:39:30 -04:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
2025-04-05 18:39:04 -04:00
|
|
|
pub struct Date {
|
|
|
|
|
pub date: String,
|
|
|
|
|
pub games: Vec<Game>,
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-02 20:39:30 -04:00
|
|
|
#[serde_alias(CamelCase,SnakeCase)]
|
2025-04-05 18:39:04 -04:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
2025-04-02 20:39:30 -04:00
|
|
|
pub struct Game {
|
2025-04-05 18:39:04 -04:00
|
|
|
pub season: String,
|
|
|
|
|
pub teams: Teams,
|
|
|
|
|
pub official_date: String,
|
2025-04-05 21:14:52 -04:00
|
|
|
pub game_date: String,
|
2025-04-02 20:39:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
|
|
|
#[serde_alias(CamelCase,SnakeCase)]
|
|
|
|
|
pub struct Teams {
|
|
|
|
|
away: Team,
|
|
|
|
|
home: Team,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[serde_alias(CamelCase,SnakeCase)]
|
2025-04-05 18:39:04 -04:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
2025-04-02 20:39:30 -04:00
|
|
|
pub struct Team {
|
|
|
|
|
team: TeamInfo,
|
|
|
|
|
league_record: TeamRecord,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[serde_alias(CamelCase,SnakeCase)]
|
2025-04-05 18:39:04 -04:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
2025-04-02 20:39:30 -04:00
|
|
|
pub struct TeamInfo {
|
|
|
|
|
id: i32,
|
|
|
|
|
name: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[serde_alias(CamelCase,SnakeCase)]
|
2025-04-05 18:39:04 -04:00
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
2025-04-02 20:39:30 -04:00
|
|
|
pub struct TeamRecord {
|
|
|
|
|
wins: i32,
|
|
|
|
|
losses: i32,
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-05 18:39:04 -04:00
|
|
|
pub struct GameInfo {
|
|
|
|
|
pub opponent: String,
|
|
|
|
|
pub date: String,
|
2025-04-05 21:14:52 -04:00
|
|
|
pub start_time: String,
|
2025-04-02 20:39:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Gets the full forecast from the response.
|
2025-04-05 18:39:04 -04:00
|
|
|
pub fn get_schedule() -> Vec<GameInfo> {
|
2025-04-02 20:39:30 -04:00
|
|
|
let client = reqwest::blocking::Client::new();
|
2025-04-05 20:19:42 -04:00
|
|
|
let schedule_url = build_api_url();
|
|
|
|
|
let schedule_json: String = client.get(&schedule_url).send().expect("Unable to get data").text().unwrap().to_string();
|
2025-04-05 18:39:04 -04:00
|
|
|
let schedule: Schedule = serde_json::from_str(&schedule_json).expect("JSON was not well-formatted");
|
|
|
|
|
let mut full_schedule: Vec<GameInfo> = vec![];
|
|
|
|
|
let dates = schedule.dates;
|
|
|
|
|
for date in dates {
|
|
|
|
|
for game in date.games {
|
|
|
|
|
let facing = extract_opponent(&game.teams);
|
|
|
|
|
let game_info = GameInfo {
|
|
|
|
|
opponent: facing,
|
|
|
|
|
date: game.official_date,
|
2025-04-05 21:14:52 -04:00
|
|
|
start_time: get_start_time(&game.game_date),
|
2025-04-05 18:39:04 -04:00
|
|
|
};
|
|
|
|
|
full_schedule.push(game_info);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
full_schedule
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-05 20:19:42 -04:00
|
|
|
// Determine who the opponent is from the teams.
|
2025-04-05 18:39:04 -04:00
|
|
|
pub fn extract_opponent(teams: &Teams) -> String {
|
|
|
|
|
if teams.home.team.name == "Boston Red Sox" {
|
|
|
|
|
teams.away.team.name.to_string()
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
teams.home.team.name.to_string()
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-02 20:39:30 -04:00
|
|
|
|
2025-04-05 20:19:42 -04:00
|
|
|
// Build the url for the api request.
|
|
|
|
|
fn build_api_url() -> String {
|
|
|
|
|
let url_first: String = "https://statsapi.mlb.com/api/v1/schedule?sportId=1&teamId=".to_string();
|
|
|
|
|
let url_second: String= "&startDate=2025-04-01&endDate=2025-09-30".to_string();
|
|
|
|
|
format!("{}{}{}", url_first, TEAM_ID, url_second)
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-05 21:14:52 -04:00
|
|
|
fn get_start_time(iso_string: &String) -> String {
|
|
|
|
|
let utc_dt: DateTime<Utc> = iso_string.parse().expect("Invalid ISO8601 string");
|
|
|
|
|
let est_dt = utc_dt.with_timezone(&Eastern);
|
|
|
|
|
est_dt.format("%I:%M").to_string()
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-05 18:39:04 -04:00
|
|
|
#[cfg(test)]
|
2025-04-05 20:19:42 -04:00
|
|
|
mod team_tests {
|
2025-04-05 18:39:04 -04:00
|
|
|
use super::*;
|
|
|
|
|
#[test]
|
|
|
|
|
fn check_schedule_retrieval() {
|
|
|
|
|
get_schedule();
|
|
|
|
|
}
|
2025-04-02 20:39:30 -04:00
|
|
|
}
|