Skip to content

Commit 9cbfa48

Browse files
authored
Current season advanced stats (#91)
2 parents d679eef + 1b24856 commit 9cbfa48

13 files changed

+276
-18
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using CsvHelper.Configuration.Attributes;
2+
3+
namespace SMB3Explorer.Models.Exports;
4+
5+
public class BattingMostRecentSeasonStatistic : BattingSeasonStatistic
6+
{
7+
public BattingMostRecentSeasonStatistic(BattingSeasonStatistic battingSeasonStatistic)
8+
{
9+
PlayerId = battingSeasonStatistic.PlayerId;
10+
FirstName = battingSeasonStatistic.FirstName;
11+
LastName = battingSeasonStatistic.LastName;
12+
CurrentTeam = battingSeasonStatistic.CurrentTeam;
13+
PreviousTeam = battingSeasonStatistic.PreviousTeam;
14+
PositionNumber = battingSeasonStatistic.PositionNumber;
15+
SecondaryPositionNumber = battingSeasonStatistic.SecondaryPositionNumber;
16+
GamesBatting = battingSeasonStatistic.GamesBatting;
17+
GamesPlayed = battingSeasonStatistic.GamesPlayed;
18+
AtBats = battingSeasonStatistic.AtBats;
19+
Runs = battingSeasonStatistic.Runs;
20+
Hits = battingSeasonStatistic.Hits;
21+
Doubles = battingSeasonStatistic.Doubles;
22+
Triples = battingSeasonStatistic.Triples;
23+
HomeRuns = battingSeasonStatistic.HomeRuns;
24+
RunsBattedIn = battingSeasonStatistic.RunsBattedIn;
25+
StolenBases = battingSeasonStatistic.StolenBases;
26+
CaughtStealing = battingSeasonStatistic.CaughtStealing;
27+
Walks = battingSeasonStatistic.Walks;
28+
Strikeouts = battingSeasonStatistic.Strikeouts;
29+
HitByPitch = battingSeasonStatistic.HitByPitch;
30+
SacrificeHits = battingSeasonStatistic.SacrificeHits;
31+
SacrificeFlies = battingSeasonStatistic.SacrificeFlies;
32+
PassedBalls = battingSeasonStatistic.PassedBalls;
33+
CompletionDate = battingSeasonStatistic.CompletionDate;
34+
SeasonId = battingSeasonStatistic.SeasonId;
35+
SeasonNum = battingSeasonStatistic.SeasonNum;
36+
Age = battingSeasonStatistic.Age;
37+
}
38+
39+
[Name("OPS+"), Index(47)]
40+
public double OnBasePercentagePlus { get; set; }
41+
}

SMB3Explorer/Models/Exports/BattingSeasonStatistic.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,23 @@ public class BattingSeasonStatistic
141141
[Name("extra_base_hit_percentage"), Index(40)]
142142
public double ExtraBaseHitPercentage => ExtraBaseHits / (double) Hits;
143143

144-
[Name("season_completion_date"), Index(41)]
144+
// Caveat with this, the denominator should be subtracting intentional walks, but that data is not available
145+
[Name("wOBA"), Index(41)]
146+
public double WeightedOnBaseAverage => ((0.69 * Walks) + (0.72 * HitByPitch) + (0.89 * Singles) + (1.27 * Doubles) +
147+
(1.62 * Triples) + (2.10 * HomeRuns)) / (AtBats + Walks + SacrificeFlies + HitByPitch);
148+
149+
[Name("ISO"), Index(42)]
150+
public double IsolatedPower => SluggingPercentage - BattingAverage;
151+
152+
[Name("season_completion_date"), Index(43)]
145153
public DateTime? CompletionDate { get; set; }
146154

147-
[Name("season_id"), Index(42)]
155+
[Name("season_id"), Index(44)]
148156
public int SeasonId { get; set; }
149157

150-
[Name("season_num"), Index(43)]
158+
[Name("season_num"), Index(45)]
151159
public int SeasonNum { get; set; }
152160

153-
[Name("age"), Index(44)]
161+
[Name("age"), Index(46)]
154162
public int Age { get; set; }
155163
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using CsvHelper.Configuration.Attributes;
2+
3+
namespace SMB3Explorer.Models.Exports;
4+
5+
public class PitchingMostRecentSeasonStatistic : PitchingSeasonStatistic
6+
{
7+
public PitchingMostRecentSeasonStatistic(PitchingSeasonStatistic pitchingSeasonStatistic)
8+
{
9+
PlayerId = pitchingSeasonStatistic.PlayerId;
10+
FirstName = pitchingSeasonStatistic.FirstName;
11+
LastName = pitchingSeasonStatistic.LastName;
12+
CurrentTeam = pitchingSeasonStatistic.CurrentTeam;
13+
PreviousTeam = pitchingSeasonStatistic.PreviousTeam;
14+
PositionNumber = pitchingSeasonStatistic.PositionNumber;
15+
PitcherRole = pitchingSeasonStatistic.PitcherRole;
16+
GamesPlayed = pitchingSeasonStatistic.GamesPlayed;
17+
GamesStarted = pitchingSeasonStatistic.GamesStarted;
18+
Wins = pitchingSeasonStatistic.Wins;
19+
Losses = pitchingSeasonStatistic.Losses;
20+
CompleteGames = pitchingSeasonStatistic.CompleteGames;
21+
Shutouts = pitchingSeasonStatistic.Shutouts;
22+
TotalPitches = pitchingSeasonStatistic.TotalPitches;
23+
Saves = pitchingSeasonStatistic.Saves;
24+
OutsPitched = pitchingSeasonStatistic.OutsPitched;
25+
HitsAllowed = pitchingSeasonStatistic.HitsAllowed;
26+
EarnedRuns = pitchingSeasonStatistic.EarnedRuns;
27+
HomeRunsAllowed = pitchingSeasonStatistic.HomeRunsAllowed;
28+
WalksAllowed = pitchingSeasonStatistic.WalksAllowed;
29+
Strikeouts = pitchingSeasonStatistic.Strikeouts;
30+
HitByPitch = pitchingSeasonStatistic.HitByPitch;
31+
BattersFaced = pitchingSeasonStatistic.BattersFaced;
32+
GamesFinished = pitchingSeasonStatistic.GamesFinished;
33+
RunsAllowed = pitchingSeasonStatistic.RunsAllowed;
34+
WildPitches = pitchingSeasonStatistic.WildPitches;
35+
CompletionDate = pitchingSeasonStatistic.CompletionDate;
36+
SeasonId = pitchingSeasonStatistic.SeasonId;
37+
SeasonNum = pitchingSeasonStatistic.SeasonNum;
38+
Age = pitchingSeasonStatistic.Age;
39+
}
40+
41+
42+
[Name("ERA-"), Index(47)]
43+
public double EarnedRunsAllowedMinus { get; set; }
44+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
WITH mostRecentSeason AS (SELECT id AS seasonID,
2+
RANK() OVER (ORDER BY id) AS seasonNum
3+
FROM t_seasons
4+
JOIN t_leagues ON t_seasons.historicalLeagueGUID = t_leagues.GUID
5+
JOIN t_franchise tf ON t_leagues.GUID = tf.leagueGUID
6+
WHERE t_leagues.GUID = CAST(@leagueId AS BLOB)
7+
ORDER BY ID DESC
8+
LIMIT 1)
9+
SELECT AVG(
10+
([hits] + [baseOnBalls] + [hitByPitch]) /
11+
CAST(NULLIF([atBats] + [baseOnBalls] + [hitByPitch] + [sacrificeFlies], 0) AS [REAL]) +
12+
(([hits] - [doubles] - [triples] - [homeruns]) + 2 * [doubles] + 3 * [triples] +
13+
4 * [homeruns]) / CAST(NULLIF([atBats], 0) AS [REAL])
14+
)
15+
AS ops
16+
FROM [v_baseball_player_info] vbpi
17+
LEFT JOIN t_baseball_player_local_ids tbpli ON vbpi.baseballPlayerGUID = tbpli.GUID
18+
LEFT JOIN t_stats_players tsp ON tbpli.localID = tsp.baseballPlayerLocalID
19+
LEFT JOIN t_stats ts ON tsp.statsPlayerID = ts.statsPlayerID
20+
LEFT JOIN t_stats_batting tsb ON ts.aggregatorID = tsb.aggregatorID
21+
LEFT JOIN t_baseball_players tbp ON tbpli.GUID = tbp.GUID
22+
LEFT JOIN t_season_stats tss ON ts.aggregatorID = tss.aggregatorID
23+
JOIN t_seasons tsea ON tss.seasonID = tsea.ID
24+
JOIN mostRecentSeason ON mostRecentSeason.seasonID = tsea.ID
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
WITH mostRecentSeason AS (SELECT id AS seasonID,
2+
RANK() OVER (ORDER BY id) AS seasonNum
3+
FROM t_seasons
4+
JOIN t_leagues ON t_seasons.historicalLeagueGUID = t_leagues.GUID
5+
JOIN t_franchise tf ON t_leagues.GUID = tf.leagueGUID
6+
WHERE t_leagues.GUID = CAST(@leagueId AS BLOB)
7+
ORDER BY ID DESC
8+
LIMIT 1)
9+
SELECT AVG(
10+
CASE
11+
WHEN tspitch.outsPitched = 0 THEN NULL
12+
ELSE (tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0)
13+
END) AS era
14+
FROM [v_baseball_player_info] vbpi
15+
LEFT JOIN t_baseball_player_local_ids tbpli ON vbpi.baseballPlayerGUID = tbpli.GUID
16+
LEFT JOIN t_stats_players tsp ON tbpli.localID = tsp.baseballPlayerLocalID
17+
LEFT JOIN t_stats ts ON tsp.statsPlayerID = ts.statsPlayerID
18+
JOIN t_stats_pitching tspitch ON ts.aggregatorID = tspitch.aggregatorID
19+
LEFT JOIN t_baseball_players tbp ON tbpli.GUID = tbp.GUID
20+
LEFT JOIN t_season_stats tss ON ts.aggregatorID = tss.aggregatorID
21+
JOIN t_seasons tsea ON tss.seasonID = tsea.ID
22+
JOIN mostRecentSeason ON mostRecentSeason.seasonID = tsea.ID

SMB3Explorer/Resources/Sql/TopPerformersBatting.sql

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,19 @@ SELECT baseballPlayerGUID,
2828
ELSE vbpi.[pitcherRole] END AS pitcherRole,
2929
CAST(secondaryPosition.optionValue AS INTEGER) AS secondaryPosition,
3030
tsb.*,
31+
100 * ((
32+
([hits] + [baseOnBalls] + [hitByPitch]) /
33+
CAST(NULLIF([atBats] + [baseOnBalls] + [hitByPitch] + [sacrificeFlies], 0) AS [REAL]) +
34+
(([hits] - [doubles] - [triples] - [homeruns]) + 2 * [doubles] + 3 * [triples] +
35+
4 * [homeruns]) / CAST(NULLIF([atBats], 0) AS [REAL])
36+
) / @leagueOps) AS opsPlus,
37+
-- sortOrder is a weighted OPS+ based on number of at bats
38+
atBats * 100 * ((
39+
([hits] + [baseOnBalls] + [hitByPitch]) /
40+
CAST(NULLIF([atBats] + [baseOnBalls] + [hitByPitch] + [sacrificeFlies], 0) AS [REAL]) +
41+
(([hits] - [doubles] - [triples] - [homeruns]) + 2 * [doubles] + 3 * [triples] +
42+
4 * [homeruns]) / CAST(NULLIF([atBats], 0) AS [REAL])
43+
) / @leagueOps) AS sortOrder,
3144
currentTeam.teamName AS currentTeam,
3245
previousTeam.teamName AS previousTeam,
3346
tbp.age AS age
@@ -56,5 +69,4 @@ FROM [v_baseball_player_info] vbpi
5669
LEFT JOIN teams previousTeam ON tt2.GUID = previousTeam.teamGUID
5770

5871
WHERE tl.GUID = CAST(@leagueId AS BLOB)
59-
ORDER BY homeruns DESC
60-
LIMIT 25
72+
ORDER BY sortOrder DESC

SMB3Explorer/Resources/Sql/TopPerformersPitching.sql

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ SELECT baseballPlayerGUID,
2828
WHEN tsp.[baseballPlayerLocalID] IS NULL THEN tsp.[pitcherRole]
2929
ELSE vbpi.[pitcherRole] END AS pitcherRole,
3030
tspitch.*,
31+
CASE
32+
WHEN tspitch.outsPitched = 0 THEN 0
33+
ELSE 100 * (
34+
@leagueEra /
35+
((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0))
36+
)
37+
END AS eraMinus,
38+
-- sortOrder is a weighted eraMinus based on innings pitched
39+
tspitch.outsPitched * 100 * (
40+
@leagueEra /
41+
((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0))
42+
) AS sortOrder,
3143
currentTeam.teamName AS currentTeam,
3244
previousTeam.teamName AS previousTeam,
3345
tbp.age AS age
@@ -63,5 +75,4 @@ WHERE tl.GUID = CAST(@leagueId AS BLOB)
6375

6476
JOIN t_seasons tsea ON tss.seasonID = tsea.ID
6577
JOIN mostRecentSeason s ON tsea.ID = s.seasonID)
66-
ORDER BY strikeOuts DESC
67-
LIMIT 25
78+
ORDER BY sortOrder DESC

SMB3Explorer/Resources/Sql/TopPerformersRookiesBatting.sql

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ SELECT vbpi.baseballPlayerGUID,
3737
ELSE vbpi.[pitcherRole] END AS pitcherRole,
3838
CAST(secondaryPosition.optionValue AS INTEGER) AS secondaryPosition,
3939
tsb.*,
40+
100 * ((
41+
([hits] + [baseOnBalls] + [hitByPitch]) /
42+
CAST(NULLIF([atBats] + [baseOnBalls] + [hitByPitch] + [sacrificeFlies], 0) AS [REAL]) +
43+
(([hits] - [doubles] - [triples] - [homeruns]) + 2 * [doubles] + 3 * [triples] +
44+
4 * [homeruns]) / CAST(NULLIF([atBats], 0) AS [REAL])
45+
) / @leagueOps) AS opsPlus,
46+
-- sortOrder is a weighted OPS+ based on number of at bats
47+
atBats * 100 * ((
48+
([hits] + [baseOnBalls] + [hitByPitch]) /
49+
CAST(NULLIF([atBats] + [baseOnBalls] + [hitByPitch] + [sacrificeFlies], 0) AS [REAL]) +
50+
(([hits] - [doubles] - [triples] - [homeruns]) + 2 * [doubles] + 3 * [triples] +
51+
4 * [homeruns]) / CAST(NULLIF([atBats], 0) AS [REAL])
52+
) / @leagueOps) AS sortOrder,
4053
currentTeam.teamName AS currentTeam,
4154
previousTeam.teamName AS previousTeam,
4255
tbp.age AS age
@@ -67,5 +80,4 @@ FROM [v_baseball_player_info] vbpi
6780
LEFT JOIN teams previousTeam ON tt2.GUID = previousTeam.teamGUID
6881

6982
WHERE tl.GUID = CAST(@leagueId AS BLOB)
70-
ORDER BY homeruns DESC
71-
LIMIT 25
83+
ORDER BY sortOrder DESC

SMB3Explorer/Resources/Sql/TopPerformersRookiesPitching.sql

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ SELECT vbpi.baseballPlayerGUID,
3737
WHEN tsp.[baseballPlayerLocalID] IS NULL THEN tsp.[pitcherRole]
3838
ELSE vbpi.[pitcherRole] END AS pitcherRole,
3939
tspitch.*,
40+
CASE
41+
WHEN tspitch.outsPitched = 0 THEN 0
42+
ELSE 100 * (
43+
@leagueEra /
44+
((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0))
45+
)
46+
END AS eraMinus,
47+
-- sortOrder is a weighted eraMinus based on innings pitched
48+
tspitch.outsPitched * 100 * (
49+
@leagueEra /
50+
((tspitch.earnedRuns * 9) / (tspitch.outsPitched / 3.0))
51+
) AS sortOrder,
4052
currentTeam.teamName AS currentTeam,
4153
previousTeam.teamName AS previousTeam,
4254
tbp.age AS age
@@ -74,5 +86,4 @@ WHERE tl.GUID = CAST(@leagueId AS BLOB)
7486

7587
JOIN t_seasons tsea ON tss.seasonID = tsea.ID
7688
JOIN mostRecentSeason s ON tsea.ID = s.seasonID)
77-
ORDER BY strikeOuts DESC
78-
LIMIT 25
89+
ORDER BY sortOrder DESC

SMB3Explorer/SMB3Explorer.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@
9191
<EmbeddedResource Include="Resources\Sql\MostRecentSeasonPlayers.sql" />
9292
<None Remove="Resources\Sql\MostRecentSeasonTeams.sql" />
9393
<EmbeddedResource Include="Resources\Sql\MostRecentSeasonTeams.sql" />
94+
<None Remove="Resources\Sql\SeasonAverageBatterStats.sql" />
95+
<EmbeddedResource Include="Resources\Sql\SeasonAverageBatterStats.sql" />
96+
<None Remove="Resources\Sql\SeasonAveragePitcherStats.sql" />
97+
<EmbeddedResource Include="Resources\Sql\SeasonAveragePitcherStats.sql" />
9498
</ItemGroup>
9599

96100
</Project>

0 commit comments

Comments
 (0)