diff --git a/idol_api/src/models.rs b/idol_api/src/models.rs index d568526..e99156f 100644 --- a/idol_api/src/models.rs +++ b/idol_api/src/models.rs @@ -5,6 +5,8 @@ pub struct PitchingStats { pub player_id: String, #[serde(with = "serde_with::rust::display_fromstr")] pub k_per_9: f64, + #[serde(with = "serde_with::rust::display_fromstr")] + pub games: usize, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -58,6 +60,7 @@ pub struct Game { pub away_odds: f64, pub home_odds: f64, pub inning: usize, + pub season: usize, } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] @@ -72,6 +75,7 @@ pub struct Simulation { #[serde(rename_all = "camelCase")] pub struct Games { pub sim: Simulation, + pub schedule: Vec, pub tomorrow_schedule: Vec, } @@ -102,3 +106,16 @@ pub struct Team { pub struct Idol { pub player_id: String, } + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct GameUpdates { + pub next_page: String, + pub data: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct GameUpdate { + pub data: Game, +} diff --git a/idol_api/src/state.rs b/idol_api/src/state.rs index fb188af..560a0f1 100644 --- a/idol_api/src/state.rs +++ b/idol_api/src/state.rs @@ -1,5 +1,6 @@ use super::models::{ - AtBatLeader, Event, Game, Idol, PitchingStats, Position, StrikeoutLeader, Team, + AtBatLeader, Event, Game, GameUpdate, GameUpdates, Idol, PitchingStats, Position, + StrikeoutLeader, Team, }; use anyhow::Result; use log::*; @@ -14,14 +15,19 @@ pub struct State { pub players: Vec, pub games: Vec, pub idols: Vec, + pub black_hole_sun_2: Vec, + pub season: usize, } impl State { pub fn from_event(data: &Event) -> Result { - Self::from_games_and_season( - data.value.games.tomorrow_schedule.clone(), - data.value.games.sim.season, - ) + let games = if data.value.games.tomorrow_schedule.len() == 0 { + warn!("No games scheduled, checking current games"); + data.value.games.schedule.clone() + } else { + data.value.games.tomorrow_schedule.clone() + }; + Self::from_games_and_season(games, data.value.games.sim.season) } pub fn from_games_and_season(games: Vec, season: usize) -> Result { @@ -68,6 +74,12 @@ impl State { .send()? .json::()? .data; + debug!("Getting Sun 2 and Black Hole events"); + let black_hole_sun_2 = client + .get("https://api.sibr.dev/chronicler/v1/games/updates?search=%22Sun%202%22%20or%20%22Black%20Hole%22&count=1000&order=desc") + .send()? + .json::()? + .data; let idols = client .get("https://www.blaseball.com/api/getIdols") .send()? @@ -80,6 +92,8 @@ impl State { players, games, idols, + black_hole_sun_2, + season, }) } } diff --git a/idol_api/src/team_pair.rs b/idol_api/src/team_pair.rs index 5622fdd..9b7025b 100644 --- a/idol_api/src/team_pair.rs +++ b/idol_api/src/team_pair.rs @@ -65,6 +65,13 @@ impl TeamPair { } } + pub fn any(self, mut func: F) -> bool + where + F: FnMut(T) -> bool, + { + func(self.home) || func(self.away) + } + pub fn as_ref(&self) -> TeamPair<&T> { TeamPair { home: &self.home, diff --git a/idol_historical/src/main.rs b/idol_historical/src/main.rs index 1f01857..66af05a 100644 --- a/idol_historical/src/main.rs +++ b/idol_historical/src/main.rs @@ -89,6 +89,7 @@ impl StatState { .map(|x| PitchingStats { player_id: x.0.clone(), k_per_9: (x.1.strikeouts * 9) as f64 / x.1.innings_pitched as f64, + games: 0, }) .collect(); let mut games = Vec::new(); @@ -110,7 +111,9 @@ impl StatState { teams, players, games, - idols: vec![], // TODO + idols: vec![], // TODO + black_hole_sun_2: vec![], // TODO + season: 0, // TODO }) } } diff --git a/idol_predictor/src/algorithms.rs b/idol_predictor/src/algorithms.rs index 9655b3f..ef298be 100644 --- a/idol_predictor/src/algorithms.rs +++ b/idol_predictor/src/algorithms.rs @@ -170,6 +170,21 @@ algorithm!(NAME_LENGTH, "name length", [], Unforbidden, |x| { x.player.name.len() as f64 }); +algorithm!(GAMES_PER_GAME, "games per game", [], Unforbidden, |x| { + let normal_games = x.stats?.games; + let extra = x + .state + .black_hole_sun_2 + .iter() + .map(|y| &y.data) + .take_while(|y| y.season == x.state.season) + .filter_map(|y| y.pitcher_ids()) + .filter(|y| y.any(|z| z == x.id)) + .count(); + let games = normal_games + extra; + games as f64 / normal_games as f64 +}); + pub const ALGORITHMS: &[Algorithm] = &[SO9, RUTHLESSNESS, STAT_RATIO]; pub const JOKE_ALGORITHMS: &[Algorithm] = &[ @@ -180,4 +195,5 @@ pub const JOKE_ALGORITHMS: &[Algorithm] = &[ IDOLS, BATTING_STARS, NAME_LENGTH, + GAMES_PER_GAME, ];