From 130283b7f10a0bc17569d2ae06e8537094b7cafa Mon Sep 17 00:00:00 2001 From: Peter Date: Thu, 31 Oct 2024 07:26:16 -0500 Subject: [PATCH 1/5] Create /teamleaderboards page and tables --- components.d.ts | 3 + .../LeaderboardTeamBattingTable.vue | 154 ++++++++++++++++ .../LeaderboardTeamFieldingTable.vue | 103 +++++++++++ .../LeaderboardTeamPitchingTable.vue | 168 ++++++++++++++++++ src/components/TeamFieldingTable.vue | 6 +- src/router/index.ts | 5 + src/services/battingStatsService.ts | 19 ++ src/services/fieldingStatsService.ts | 19 ++ src/services/pitchingStatsService.ts | 18 ++ src/views/TeamLeaderboardView.vue | 107 +++++++++++ src/views/TransactionsView.vue | 0 11 files changed, 599 insertions(+), 3 deletions(-) create mode 100644 src/components/LeaderboardTeamBattingTable.vue create mode 100644 src/components/LeaderboardTeamFieldingTable.vue create mode 100644 src/components/LeaderboardTeamPitchingTable.vue create mode 100644 src/views/TeamLeaderboardView.vue create mode 100644 src/views/TransactionsView.vue diff --git a/components.d.ts b/components.d.ts index 09af641..3bdcdd8 100644 --- a/components.d.ts +++ b/components.d.ts @@ -18,6 +18,9 @@ declare module '@vue/runtime-core' { IconTooling: typeof import('./src/components/icons/IconTooling.vue')['default'] LastFourGamesBattingTable: typeof import('./src/components/LastFourGamesBattingTable.vue')['default'] LastFourGamesPitchingTable: typeof import('./src/components/LastFourGamesPitchingTable.vue')['default'] + LeaderboardTeamBattingTable: typeof import('./src/components/LeaderboardTeamBattingTable.vue')['default'] + LeaderboardTeamFieldingTable: typeof import('./src/components/LeaderboardTeamFieldingTable.vue')['default'] + LeaderboardTeamPitchingTable: typeof import('./src/components/LeaderboardTeamPitchingTable.vue')['default'] NavBar: typeof import('./src/components/NavBar.vue')['default'] NewsPreview: typeof import('./src/components/NewsPreview.vue')['default'] PlayerBattingSummaryTable: typeof import('./src/components/PlayerBattingSummaryTable.vue')['default'] diff --git a/src/components/LeaderboardTeamBattingTable.vue b/src/components/LeaderboardTeamBattingTable.vue new file mode 100644 index 0000000..4885dc2 --- /dev/null +++ b/src/components/LeaderboardTeamBattingTable.vue @@ -0,0 +1,154 @@ + + + diff --git a/src/components/LeaderboardTeamFieldingTable.vue b/src/components/LeaderboardTeamFieldingTable.vue new file mode 100644 index 0000000..c16313c --- /dev/null +++ b/src/components/LeaderboardTeamFieldingTable.vue @@ -0,0 +1,103 @@ + + diff --git a/src/components/LeaderboardTeamPitchingTable.vue b/src/components/LeaderboardTeamPitchingTable.vue new file mode 100644 index 0000000..64ac54d --- /dev/null +++ b/src/components/LeaderboardTeamPitchingTable.vue @@ -0,0 +1,168 @@ + + + diff --git a/src/components/TeamFieldingTable.vue b/src/components/TeamFieldingTable.vue index c0fc986..b54d663 100644 --- a/src/components/TeamFieldingTable.vue +++ b/src/components/TeamFieldingTable.vue @@ -18,7 +18,7 @@ - + {{ stat.player.name }} @@ -36,7 +36,7 @@ - + Total {{ stat.pos }} {{ stat.xCheckCount }} @@ -58,7 +58,7 @@ import { aggregateFieldingStats, fetchFieldingStatsBySeasonAndTeamId, totaledFie import { POS_MAP } from '@/services/utilities' export default { - name: "TeamFieldingTable", + name: 'TeamFieldingTable', props: { seasonNumber: { type: Number, required: true }, teamId: { type: Number, required: true }, diff --git a/src/router/index.ts b/src/router/index.ts index a689d1c..394b528 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -36,6 +36,11 @@ export const routes: RouteRecordRaw[] = [ name: 'leaderboards', component: () => import('../views/LeaderboardView.vue') }, + { + path: '/teamleaderboards', + name: 'teamleaderboards', + component: () => import('../views/TeamLeaderboardView.vue') + }, { path: '/rules', name: 'rules', diff --git a/src/services/battingStatsService.ts b/src/services/battingStatsService.ts index 91f2534..776ab18 100644 --- a/src/services/battingStatsService.ts +++ b/src/services/battingStatsService.ts @@ -123,6 +123,25 @@ export async function fetchBattingStatsBySeasonAndTeamId(seasonNumber: number, t return battingStatsResponse.stats } +// Differs from fetchBattingStatsBySeasonAndTeamId because it groups stats by team, not individual player stats on a given team +export async function fetchTeamBattingStatsBySeason(seasonNumber: number): Promise { + // different endpoint for pre-modern stats (/plays) era + if (seasonNumber < MODERN_STAT_ERA_START) { + return [] + } + + const response = await fetch(`${SITE_URL}/api/v3/plays/batting?season=${seasonNumber}&group_by=team&s_type=regular`) + + const battingStatsResponse: { + count: number + stats: BattingStat[] + } = await response.json() + + if (battingStatsResponse.count === 0) return [] + + return battingStatsResponse.stats +} + async function fetchLegacyBattingStatsBySeasonAndPlayerId(seasonNumber: number, playerId: number, isRegularSeason: boolean): Promise { const response = await fetch(`${SITE_URL}/api/v3/battingstats/totals?season=${seasonNumber}&player_id=${playerId}&s_type=${isRegularSeason ? 'regular' : 'post'}`) diff --git a/src/services/fieldingStatsService.ts b/src/services/fieldingStatsService.ts index 8320f98..7238fa6 100644 --- a/src/services/fieldingStatsService.ts +++ b/src/services/fieldingStatsService.ts @@ -89,6 +89,25 @@ export async function fetchFieldingStatsBySeasonAndTeamId(seasonNumber: number, return fieldingStatsResponse.stats.map(normalizeFieldingStat) } +export async function fetchTeamFieldingStatsBySeason(seasonNumber: number): Promise { + // different endpoint for pre-modern stats (/plays) era + if (seasonNumber < MODERN_STAT_ERA_START) { + return [] + } + + // TODO might want to make this playerpositionteam grouping (currently does not exist) + const response = await fetch(`${SITE_URL}/api/v3/plays/fielding?season=${seasonNumber}&group_by=team&s_type=regular`) + + const fieldingStatsResponse: { + count: number + stats: FieldingStatRaw[] + } = await response.json() + + if (fieldingStatsResponse.count === 0) return [] + + return fieldingStatsResponse.stats.map(normalizeFieldingStat) +} + export async function fetchFieldingStatsBySeason(seasonNumber: number, isRegularSeason: boolean): Promise { // different endpoint for pre-modern stats (/plays) era if (seasonNumber < MODERN_STAT_ERA_START) { diff --git a/src/services/pitchingStatsService.ts b/src/services/pitchingStatsService.ts index fdf90c2..83b5963 100644 --- a/src/services/pitchingStatsService.ts +++ b/src/services/pitchingStatsService.ts @@ -171,6 +171,24 @@ export async function fetchPitchingStatsBySeasonAndTeamId(seasonNumber: number, return pitchingStatsResponse.stats.map(normalizePitchingStat) } +export async function fetchTeamPitchingStatsBySeason(seasonNumber: number): Promise { + // different endpoint for pre-modern stats (/plays) era + if (seasonNumber < MODERN_STAT_ERA_START) { + return [] + } + + const response = await fetch(`${SITE_URL}/api/v3/plays/pitching?season=${seasonNumber}&group_by=team&s_type=regular`) + + const pitchingStatsResponse: { + count: number + stats: PitchingStatRaw[] + } = await response.json() + + if (pitchingStatsResponse.count === 0) return [] + + return pitchingStatsResponse.stats.map(normalizePitchingStat) +} + export async function fetchPitchingStatsBySeason(seasonNumber: number, isRegularSeason: boolean): Promise { // different endpoint for pre-modern stats (/plays) era if (seasonNumber < MODERN_STAT_ERA_START) { diff --git a/src/views/TeamLeaderboardView.vue b/src/views/TeamLeaderboardView.vue new file mode 100644 index 0000000..f3c438c --- /dev/null +++ b/src/views/TeamLeaderboardView.vue @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/src/views/TransactionsView.vue b/src/views/TransactionsView.vue new file mode 100644 index 0000000..e69de29 From 334f5acdb36bd89938f87b24b665d9c6e73f65ef Mon Sep 17 00:00:00 2001 From: Peter Date: Thu, 31 Oct 2024 07:28:14 -0500 Subject: [PATCH 2/5] Clean up page and unused methods --- src/views/TeamLeaderboardView.vue | 55 +------------------------------ 1 file changed, 1 insertion(+), 54 deletions(-) diff --git a/src/views/TeamLeaderboardView.vue b/src/views/TeamLeaderboardView.vue index f3c438c..b4ba18b 100644 --- a/src/views/TeamLeaderboardView.vue +++ b/src/views/TeamLeaderboardView.vue @@ -3,7 +3,6 @@

Season {{ seasonNumber }} Team Stats

-

Week {{ weekNumber }}

{{ statType }} Stats

@@ -29,8 +28,7 @@ import LeaderboardTeamBattingTable from '@/components/LeaderboardTeamBattingTable.vue' import LeaderboardTeamFieldingTable from '@/components/LeaderboardTeamFieldingTable.vue' import LeaderboardTeamPitchingTable from '@/components/LeaderboardTeamPitchingTable.vue' -import { type LeagueInfo, fetchCurrentLeagueInfo } from '@/services/currentService' -import { CURRENT_SEASON, GAMES_PER_WEEK, MODERN_STAT_ERA_START, WEEKS_PER_SEASON } from '@/services/utilities' +import { CURRENT_SEASON, MODERN_STAT_ERA_START } from '@/services/utilities' export default { name: 'TeamLeaderboardView', @@ -44,9 +42,6 @@ export default { currentSeasonNumber: CURRENT_SEASON, seasonNumber: CURRENT_SEASON, statType: 'Batting' as 'Batting' | 'Pitching' | 'Fielding', - pitchingType: 'All' as 'All' | 'Starters' | 'Relievers', - - weekNumber: undefined! as number } }, computed: { @@ -54,54 +49,6 @@ export default { if (!this.currentSeasonNumber) return [] return Array.from({ length: this.currentSeasonNumber - MODERN_STAT_ERA_START + 1 }, (_, i) => i + MODERN_STAT_ERA_START) }, - weekNumberForCalcs(): number { - if (this.seasonNumber < this.currentSeasonNumber) return WEEKS_PER_SEASON - // since stats are for regular season, do not use post season weeks to up PA/IP mins - return Math.max(0, Math.min(this.weekNumber, WEEKS_PER_SEASON)) - }, - statMinimum(): string { - if (this.statType == 'Batting') return `PA: ${this.plateAppearanceMinimum}` - if (this.statType == 'Pitching') return `IP: ${this.inningsPitchedMinimum}` - return `${Math.floor(this.weekNumberForCalcs * 2)}/${Math.floor(this.weekNumberForCalcs)}/${Math.floor(this.weekNumberForCalcs * 0.5)}/${Math.floor(this.weekNumberForCalcs * 0.25)}` - }, - plateAppearanceMinimum(): number { - const MIN_PLATE_APPEARANCES_PER_GAME = 3 - return this.weekNumberForCalcs * GAMES_PER_WEEK * MIN_PLATE_APPEARANCES_PER_GAME - }, - inningsPitchedMinimum(): number { - if (this.pitchingType === 'Relievers') return this.weekNumberForCalcs - - const MIN_IP_PER_GAME = 1 - return this.weekNumberForCalcs * GAMES_PER_WEEK * MIN_IP_PER_GAME - }, - }, - created() { - this.fetchData() - }, - watch: { - seasonNumber(newValue, oldValue) { - if (newValue !== oldValue) - this.fetchData() - }, - statType(newValue, oldValue) { - if (newValue !== oldValue) - this.fetchData() - } - }, - methods: { - async fetchData(): Promise { - const leagueInfo: LeagueInfo = await fetchCurrentLeagueInfo() - this.weekNumber = leagueInfo.week - } } } - - \ No newline at end of file From ef788ffdb81220c7a9aaaa3ef1ae53328497c0c7 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 1 Nov 2024 06:40:35 -0500 Subject: [PATCH 3/5] Add team stats to navbar --- src/components/NavBar.vue | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 1946c22..e826baa 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -18,7 +18,10 @@ Standings +