use crate::stats::raw::OmittedStatError;
use crate::stats::units::{CountingStat, InningsPitched, PercentageStat, ThreeDecimalPlaceRateStat, TwoDecimalPlaceRateStat};
type Result<T, E = OmittedStatError> = core::result::Result<T, E>;
macro_rules! wrap {
($expr:expr) => {
(move || Result::<_>::Ok($expr))().unwrap_or_default()
};
}
#[must_use]
pub fn avg(hits: Result<CountingStat>, at_bats: Result<CountingStat>) -> ThreeDecimalPlaceRateStat {
wrap!(ThreeDecimalPlaceRateStat::new(hits? as f64 / at_bats? as f64))
}
#[must_use]
pub fn slg(total_bases: Result<CountingStat>, at_bats: Result<CountingStat>) -> ThreeDecimalPlaceRateStat {
wrap!(ThreeDecimalPlaceRateStat::new(total_bases? as f64 / at_bats? as f64))
}
#[must_use]
pub fn obp(
hits: Result<CountingStat>,
base_on_balls: Result<CountingStat>,
intentional_walks: Result<CountingStat>,
hit_by_pitch: Result<CountingStat>,
at_bats: Result<CountingStat>,
sac_bunts: Result<CountingStat>,
sac_hits: Result<CountingStat>,
) -> ThreeDecimalPlaceRateStat {
wrap!(ThreeDecimalPlaceRateStat::new((hits? + base_on_balls? + intentional_walks? + hit_by_pitch?) as f64 / (at_bats? + base_on_balls? + intentional_walks? + hit_by_pitch? + sac_bunts? + sac_hits?) as f64))
}
#[must_use]
pub fn ops(obp: Result<ThreeDecimalPlaceRateStat>, slg: Result<ThreeDecimalPlaceRateStat>) -> ThreeDecimalPlaceRateStat {
wrap!(ThreeDecimalPlaceRateStat::new(*obp? + *slg?))
}
#[must_use]
pub fn stolen_base_pct(stolen_bases: Result<CountingStat>, caught_stealing: Result<CountingStat>) -> PercentageStat {
wrap!(PercentageStat::new(stolen_bases? as f64 / (stolen_bases? + caught_stealing?) as f64))
}
#[must_use]
pub fn caught_stealing_pct(stolen_bases: Result<CountingStat>, caught_stealing: Result<CountingStat>) -> PercentageStat {
wrap!(PercentageStat::new(caught_stealing? as f64 / (stolen_bases? + caught_stealing?) as f64))
}
#[must_use]
pub fn babip(
hits: Result<CountingStat>,
home_runs: Result<CountingStat>,
at_bats: Result<CountingStat>,
strikeouts: Result<CountingStat>,
sac_flies: Result<CountingStat>,
) -> ThreeDecimalPlaceRateStat {
wrap!(ThreeDecimalPlaceRateStat::new((hits? - home_runs?) as f64 / (at_bats? - strikeouts? - home_runs? - sac_flies?) as f64))
}
#[must_use]
pub fn bb_pct(base_on_balls: Result<CountingStat>, plate_appearances: Result<CountingStat>) -> PercentageStat {
wrap!(PercentageStat::new(base_on_balls? as f64 / plate_appearances? as f64))
}
#[must_use]
pub fn k_pct(strikeouts: Result<CountingStat>, plate_appearances: Result<CountingStat>) -> PercentageStat {
wrap!(PercentageStat::new(strikeouts? as f64 / plate_appearances? as f64))
}
pub fn extra_bases(doubles: Result<CountingStat>, triples: Result<CountingStat>, home_runs: Result<CountingStat>) -> Result<CountingStat> {
Ok(doubles? + triples? * 2 + home_runs? * 3)
}
#[must_use]
pub fn iso(extra_bases: Result<CountingStat>, at_bats: Result<CountingStat>) -> ThreeDecimalPlaceRateStat {
wrap!(ThreeDecimalPlaceRateStat::new(extra_bases? as f64 / at_bats? as f64))
}
#[must_use]
pub fn strikeout_to_walk_ratio(strikeouts: Result<CountingStat>, base_on_balls: Result<CountingStat>) -> TwoDecimalPlaceRateStat {
wrap!(TwoDecimalPlaceRateStat::new(strikeouts? as f64 / base_on_balls? as f64))
}
#[must_use]
pub fn whiff_pct(whiffs: Result<CountingStat>, total_swings: Result<CountingStat>) -> PercentageStat {
wrap!(PercentageStat::new(whiffs? as f64 / total_swings? as f64))
}
#[must_use]
pub fn era(earned_runs: Result<CountingStat>, innings_pitched: Result<InningsPitched>) -> TwoDecimalPlaceRateStat {
wrap!(TwoDecimalPlaceRateStat::new(earned_runs? as f64 * 27.0 / innings_pitched?.as_outs() as f64))
}
#[must_use]
pub fn whip(hits: Result<CountingStat>, base_on_balls: Result<CountingStat>, innings_pitched: Result<InningsPitched>) -> TwoDecimalPlaceRateStat {
wrap!(TwoDecimalPlaceRateStat::new(((base_on_balls? + hits?) as f64) / innings_pitched?.as_fraction()))
}
#[must_use]
pub fn win_pct(wins: Result<CountingStat>, losses: Result<CountingStat>) -> ThreeDecimalPlaceRateStat {
wrap!(ThreeDecimalPlaceRateStat::new(wins? as f64 / (wins? + losses?) as f64))
}
#[must_use]
pub fn pitches_per_inning_pitched(number_of_pitches: Result<CountingStat>, innings_pitched: Result<InningsPitched>) -> TwoDecimalPlaceRateStat {
wrap!(TwoDecimalPlaceRateStat::new(number_of_pitches? as f64 / innings_pitched?.as_fraction()))
}
#[must_use]
pub fn k_per_9(strikeouts: Result<CountingStat>, innings_pitched: Result<InningsPitched>) -> TwoDecimalPlaceRateStat {
wrap!(TwoDecimalPlaceRateStat::new(strikeouts? as f64 * 27.0 / innings_pitched?.as_outs() as f64))
}
#[must_use]
pub fn bb_per_9(base_on_balls: Result<CountingStat>, innings_pitched: Result<InningsPitched>) -> TwoDecimalPlaceRateStat {
wrap!(TwoDecimalPlaceRateStat::new(base_on_balls? as f64 * 27.0 / innings_pitched?.as_outs() as f64))
}
#[must_use]
pub fn hits_per_9(hits: Result<CountingStat>, innings_pitched: Result<InningsPitched>) -> TwoDecimalPlaceRateStat {
wrap!(TwoDecimalPlaceRateStat::new(hits? as f64 * 27.0 / innings_pitched?.as_outs() as f64))
}
#[must_use]
pub fn runs_scored_per_9(runs: Result<CountingStat>, innings_pitched: Result<InningsPitched>) -> TwoDecimalPlaceRateStat {
wrap!(TwoDecimalPlaceRateStat::new(runs? as f64 * 27.0 / innings_pitched?.as_outs() as f64))
}
#[must_use]
pub fn home_runs_per_9(home_runs: Result<CountingStat>, innings_pitched: Result<InningsPitched>) -> TwoDecimalPlaceRateStat {
wrap!(TwoDecimalPlaceRateStat::new(home_runs? as f64 / innings_pitched?.as_outs() as f64))
}