From 24fff4d1558912cdfc2dd922930c270424ffec79 Mon Sep 17 00:00:00 2001 From: Trey Brittain Date: Mon, 15 May 2023 10:17:17 -0500 Subject: [PATCH] Add FIP and FIP- to pitcher exports, and fix sort order for pitchers with 0 earned runs (leading to 0 ERA-) --- .../PitchingMostRecentSeasonStatistic.cs | 8 +++-- .../Models/Exports/PitchingSeasonStatistic.cs | 33 +++++++++++-------- .../Sql/SeasonAveragePitcherStats.sql | 8 ++++- .../Resources/Sql/TopPerformersPitching.sql | 27 +++++++++++---- .../Sql/TopPerformersRookiesPitching.sql | 25 ++++++++++---- .../DataServiceMostRecentSeason.cs | 25 ++++++++++---- 6 files changed, 89 insertions(+), 37 deletions(-) diff --git a/SMB3Explorer/Models/Exports/PitchingMostRecentSeasonStatistic.cs b/SMB3Explorer/Models/Exports/PitchingMostRecentSeasonStatistic.cs index 18019af..e180dcb 100644 --- a/SMB3Explorer/Models/Exports/PitchingMostRecentSeasonStatistic.cs +++ b/SMB3Explorer/Models/Exports/PitchingMostRecentSeasonStatistic.cs @@ -37,8 +37,10 @@ public PitchingMostRecentSeasonStatistic(PitchingSeasonStatistic pitchingSeasonS SeasonNum = pitchingSeasonStatistic.SeasonNum; Age = pitchingSeasonStatistic.Age; } - - - [Name("ERA-"), Index(47)] + + [Name("ERA-"), Index(48)] public double EarnedRunsAllowedMinus { get; set; } + + [Name("FIP-"), Index(49)] + public double FieldingIndependentPitchingMinus { get; set; } } \ No newline at end of file diff --git a/SMB3Explorer/Models/Exports/PitchingSeasonStatistic.cs b/SMB3Explorer/Models/Exports/PitchingSeasonStatistic.cs index ae138fb..0686988 100644 --- a/SMB3Explorer/Models/Exports/PitchingSeasonStatistic.cs +++ b/SMB3Explorer/Models/Exports/PitchingSeasonStatistic.cs @@ -106,45 +106,50 @@ public class PitchingSeasonStatistic [Name("batting_average_against"), Index(32)] public double BattingAverageAgainst => HitsAllowed / (double) BattersFaced; - [Name("whip"), Index(33)] + [Name("fip"), Index(33)] + public double FieldingIndependentPitching => + (((13 * HomeRunsAllowed) + (3 * (WalksAllowed + HitByPitch)) - + (2 * Strikeouts)) / (double) OutsPitched) + 3.10; + + [Name("whip"), Index(34)] public double WalksAndHitsPerInning => (WalksAllowed + HitsAllowed) / InningsPitched; - [Name("win_percentage"), Index(34)] + [Name("win_percentage"), Index(35)] public double WinPercentage => Wins / (double) (Wins + Losses); - [Name("opponent_on_base_percentage"), Index(35)] + [Name("opponent_on_base_percentage"), Index(36)] public double OpponentOnBasePercentage => (HitsAllowed + WalksAllowed + HitByPitch) / (double) BattersFaced; - [Name("strikeout_to_walk_ratio"), Index(36)] + [Name("strikeout_to_walk_ratio"), Index(37)] public double StrikeoutToWalkRatio => Strikeouts / (double) WalksAllowed; - [Name("strikeouts_per_nine_innings"), Index(37)] + [Name("strikeouts_per_nine_innings"), Index(38)] public double StrikeoutsPerNineInnings => Strikeouts / (InningsPitched / 9.0); - [Name("walks_per_nine_innings"), Index(38)] + [Name("walks_per_nine_innings"), Index(39)] public double WalksPerNineInnings => WalksAllowed / (InningsPitched / 9.0); - [Name("hits_per_nine_innings"), Index(39)] + [Name("hits_per_nine_innings"), Index(40)] public double HitsPerNineInnings => HitsAllowed / (InningsPitched / 9.0); - [Name("home_runs_per_nine_innings"), Index(40)] + [Name("home_runs_per_nine_innings"), Index(41)] public double HomeRunsPerNineInnings => HomeRunsAllowed / (InningsPitched / 9.0); - [Name("pitches_per_inning"), Index(41)] + [Name("pitches_per_inning"), Index(42)] public double PitchesPerInning => TotalPitches / InningsPitched; - [Name("pitches_per_game"), Index(42)] + [Name("pitches_per_game"), Index(43)] public double PitchesPerGame => TotalPitches / (double) GamesPlayed; - [Name("season_completion_date"), Index(43)] + [Name("season_completion_date"), Index(44)] public DateTime? CompletionDate { get; set; } - [Name("season_id"), Index(44)] + [Name("season_id"), Index(45)] public int SeasonId { get; set; } - [Name("season_num"), Index(45)] + [Name("season_num"), Index(46)] public int SeasonNum { get; set; } - [Name("age"), Index(46)] + [Name("age"), Index(47)] public int Age { get; set; } } \ No newline at end of file diff --git a/SMB3Explorer/Resources/Sql/SeasonAveragePitcherStats.sql b/SMB3Explorer/Resources/Sql/SeasonAveragePitcherStats.sql index 66ccf5d..cc17307 100644 --- a/SMB3Explorer/Resources/Sql/SeasonAveragePitcherStats.sql +++ b/SMB3Explorer/Resources/Sql/SeasonAveragePitcherStats.sql @@ -10,7 +10,13 @@ SELECT AVG( CASE WHEN tspitch.outsPitched = 0 THEN NULL ELSE (tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0) - END) AS era + END) AS era, + AVG( + CASE + WHEN tspitch.outsPitched = 0 THEN NULL + ELSE (((13 * tspitch.homeRuns) + (3 * (tspitch.baseOnBalls + tspitch.battersHitByPitch)) - + (2 * tspitch.strikeOuts)) / (tspitch.outsPitched / 3.0) + 3.10) + END) AS fip FROM [v_baseball_player_info] vbpi LEFT JOIN t_baseball_player_local_ids tbpli ON vbpi.baseballPlayerGUID = tbpli.GUID LEFT JOIN t_stats_players tsp ON tbpli.localID = tsp.baseballPlayerLocalID diff --git a/SMB3Explorer/Resources/Sql/TopPerformersPitching.sql b/SMB3Explorer/Resources/Sql/TopPerformersPitching.sql index 1148285..a39a48f 100644 --- a/SMB3Explorer/Resources/Sql/TopPerformersPitching.sql +++ b/SMB3Explorer/Resources/Sql/TopPerformersPitching.sql @@ -28,18 +28,31 @@ SELECT baseballPlayerGUID, WHEN tsp.[baseballPlayerLocalID] IS NULL THEN tsp.[pitcherRole] ELSE vbpi.[pitcherRole] END AS pitcherRole, tspitch.*, + CASE + WHEN tspitch.outsPitched = 0 OR tspitch.earnedRuns = 0 THEN 0 + ELSE 100 * ( + @leagueEra / + ((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0)) + ) + END AS eraMinus, CASE WHEN tspitch.outsPitched = 0 THEN 0 ELSE 100 * ( - @leagueEra / - ((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0)) + @leagueFip / + (((13 * IFNULL(tspitch.homeRuns, 0)) + + (3 * (IFNULL(tspitch.baseOnBalls, 0) + IFNULL(tspitch.battersHitByPitch, 0))) - + (2 * IFNULL(tspitch.strikeOuts, 0))) / (tspitch.outsPitched / 3.0) + 3.10) ) - END AS eraMinus, + END AS fipMinus, -- sortOrder is a weighted eraMinus based on innings pitched - tspitch.outsPitched * 100 * ( - @leagueEra / - ((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0)) - ) AS sortOrder, + CASE + WHEN tspitch.earnedRuns = 0 + THEN 99999999 + ELSE + tspitch.outsPitched * 100 * ( + @leagueEra / + ((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0)) + ) END AS sortOrder, currentTeam.teamName AS currentTeam, previousTeam.teamName AS previousTeam, tbp.age AS age diff --git a/SMB3Explorer/Resources/Sql/TopPerformersRookiesPitching.sql b/SMB3Explorer/Resources/Sql/TopPerformersRookiesPitching.sql index a9e7e7c..940fd67 100644 --- a/SMB3Explorer/Resources/Sql/TopPerformersRookiesPitching.sql +++ b/SMB3Explorer/Resources/Sql/TopPerformersRookiesPitching.sql @@ -38,17 +38,30 @@ SELECT vbpi.baseballPlayerGUID, ELSE vbpi.[pitcherRole] END AS pitcherRole, tspitch.*, CASE - WHEN tspitch.outsPitched = 0 THEN 0 + WHEN tspitch.outsPitched = 0 OR tspitch.earnedRuns = 0 THEN 0 ELSE 100 * ( @leagueEra / ((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0)) ) - END AS eraMinus, + END AS eraMinus, + CASE + WHEN tspitch.outsPitched = 0 THEN 0 + ELSE 100 * ( + @leagueFip / + (((13 * IFNULL(tspitch.homeRuns, 0)) + + (3 * (IFNULL(tspitch.baseOnBalls, 0) + IFNULL(tspitch.battersHitByPitch, 0))) - + (2 * IFNULL(tspitch.strikeOuts, 0))) / (tspitch.outsPitched / 3.0) + 3.10) + ) + END AS fipMinus, -- sortOrder is a weighted eraMinus based on innings pitched - tspitch.outsPitched * 100 * ( - @leagueEra / - ((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0)) - ) AS sortOrder, + CASE + WHEN tspitch.earnedRuns = 0 + THEN 99999999 + ELSE + tspitch.outsPitched * 100 * ( + @leagueEra / + ((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0)) + ) END AS sortOrder, currentTeam.teamName AS currentTeam, previousTeam.teamName AS previousTeam, tbp.age AS age diff --git a/SMB3Explorer/Services/DataService/DataServiceMostRecentSeason.cs b/SMB3Explorer/Services/DataService/DataServiceMostRecentSeason.cs index 2945a29..b687192 100644 --- a/SMB3Explorer/Services/DataService/DataServiceMostRecentSeason.cs +++ b/SMB3Explorer/Services/DataService/DataServiceMostRecentSeason.cs @@ -52,7 +52,7 @@ public async IAsyncEnumerable GetMostRecentSea public async IAsyncEnumerable GetMostRecentSeasonTopPitchingStatistics( bool isRookies = false) { - var seasonAverageEra = await GetAverageSeasonEra(); + var seasonAveragePitcherStats = await GetAverageSeasonPitcherStats(); var command = Connection!.CreateCommand(); @@ -68,7 +68,12 @@ public async IAsyncEnumerable GetMostRecentSe command.Parameters.Add(new SqliteParameter("@leagueEra", SqliteType.Real) { - Value = seasonAverageEra + Value = seasonAveragePitcherStats.Era + }); + + command.Parameters.Add(new SqliteParameter("@leagueFip", SqliteType.Real) + { + Value = seasonAveragePitcherStats.Fip }); var reader = await command.ExecuteReaderAsync(); @@ -78,9 +83,14 @@ public async IAsyncEnumerable GetMostRecentSe var pitcherStatistic = GetPitchingSeasonStatistic(true, reader); var mostRecentSeasonStatistic = new PitchingMostRecentSeasonStatistic(pitcherStatistic); - + var eraMinus = reader["eraMinus"].ToString()!; - mostRecentSeasonStatistic.EarnedRunsAllowedMinus = string.IsNullOrEmpty(eraMinus) ? 0 : double.Parse(eraMinus); + mostRecentSeasonStatistic.EarnedRunsAllowedMinus = + string.IsNullOrEmpty(eraMinus) ? 0 : double.Parse(eraMinus); + + var fipMinus = reader["fipMinus"].ToString()!; + mostRecentSeasonStatistic.FieldingIndependentPitchingMinus = + string.IsNullOrEmpty(fipMinus) ? 0 : double.Parse(fipMinus); yield return mostRecentSeasonStatistic; } @@ -236,7 +246,7 @@ private async Task GetAverageSeasonOps() return opsOrdinal; } - private async Task GetAverageSeasonEra() + private async Task GetAverageSeasonPitcherStats() { var command = Connection!.CreateCommand(); @@ -252,6 +262,9 @@ private async Task GetAverageSeasonEra() reader.Read(); var eraOrdinal = reader.GetDouble(0); - return eraOrdinal; + var fipOrdinal = reader.GetDouble(1); + return new AverageSeasonPitcherStats(eraOrdinal, fipOrdinal); } + + private record AverageSeasonPitcherStats(double Era, double Fip); } \ No newline at end of file