Add Bullpen Table POC

This commit is contained in:
Peter 2024-11-09 10:10:38 -06:00
parent 4532dd671e
commit b991fbff98
3 changed files with 123 additions and 1 deletions

1
components.d.ts vendored
View File

@ -9,6 +9,7 @@ export {}
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
export interface GlobalComponents { export interface GlobalComponents {
BullpenTable: typeof import('./src/components/BullpenTable.vue')['default']
CardImagesDisplay: typeof import('./src/components/CardImagesDisplay.vue')['default'] CardImagesDisplay: typeof import('./src/components/CardImagesDisplay.vue')['default']
ExtendedStandingsTable: typeof import('./src/components/ExtendedStandingsTable.vue')['default'] ExtendedStandingsTable: typeof import('./src/components/ExtendedStandingsTable.vue')['default']
IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default'] IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default']

View File

@ -0,0 +1,117 @@
<template>
<div class="bullpen-table">
<div class="row">
<h3>Bullpen</h3>
<div class="table-responsive-xl">
<table class="table table-sm table-striped">
<thead class="thead-dark">
<tr>
<th>Name</th>
<th>Positions</th>
<th>W{{weekNumber - 1}}G1</th>
<th>W{{weekNumber - 1}}G2</th>
<th>W{{weekNumber - 1}}G3</th>
<th>W{{weekNumber - 1}}G4</th>
<th v-if="weekNumber - 1 > 18">W{{weekNumber - 1}}G5</th>
<th v-if="weekNumber - 1 > 19">W{{weekNumber - 1}}G6</th>
<th v-if="weekNumber - 1 > 19">W{{weekNumber - 1}}G7</th>
<th>W{{weekNumber}}G1</th>
<th>W{{weekNumber}}G2</th>
<th>W{{weekNumber}}G3</th>
<th>W{{weekNumber}}G4</th>
<th v-if="weekNumber > 18">W{{weekNumber}}G5</th>
<th v-if="weekNumber > 19">W{{weekNumber}}G6</th>
<th v-if="weekNumber > 19">W{{weekNumber}}G7</th>
</tr>
</thead>
<tbody>
<tr v-for="player in sortedPlayers" :key="player.name">
<td :title="player.il_return ? `Injured until ${player.il_return}` : ''">
{{ player.il_return ? '🏥' : '' }}
<RouterLink :to="{ name: 'player', params: { seasonNumber: seasonNumber, playerName: player.name } }">
{{ player.name }}
</RouterLink>
{{ player.il_return ? '🏥' : '' }}
</td>
<td>
{{ allPositions(player) }}
</td>
<td>{{getIPForPitcherGame(player, weekNumber - 1, 1)}}</td>
<td>{{getIPForPitcherGame(player, weekNumber - 1, 2)}}</td>
<td>{{getIPForPitcherGame(player, weekNumber - 1, 3)}}</td>
<td>{{getIPForPitcherGame(player, weekNumber - 1, 4)}}</td>
<td v-if="weekNumber - 1 > 18">{{getIPForPitcherGame(player, weekNumber - 1, 5)}}</td>
<td v-if="weekNumber - 1 > 19">{{getIPForPitcherGame(player, weekNumber - 1, 6)}}</td>
<td v-if="weekNumber - 1 > 19">{{getIPForPitcherGame(player, weekNumber - 1, 7)}}</td>
<td>{{getIPForPitcherGame(player, weekNumber, 1)}}</td>
<td>{{getIPForPitcherGame(player, weekNumber, 2)}}</td>
<td>{{getIPForPitcherGame(player, weekNumber, 3)}}</td>
<td>{{getIPForPitcherGame(player, weekNumber, 4)}}</td>
<td v-if="weekNumber > 18">{{getIPForPitcherGame(player, weekNumber, 5)}}</td>
<td v-if="weekNumber > 19">{{getIPForPitcherGame(player, weekNumber, 6)}}</td>
<td v-if="weekNumber > 19">{{getIPForPitcherGame(player, weekNumber, 7)}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script lang="ts">
import { type Game } from '@/services/apiResponseTypes'
import { fetchPitchingStatsForLastTwoWeeksByTeam, type PitchingStat } from '@/services/pitchingStatsService'
import { fetchPlayersByTeam, type Player } from '@/services/playersService'
export default {
name: 'BullpenTable',
data() {
return {
pitcherStatsByNameWeekGame: {} as Record<string, PitchingStat>,
sortedPlayers: [] as Player[]
}
},
props: {
seasonNumber: { type: Number, required: true },
weekNumber: { type: Number, required: true },
teamId: { type: Number, required: true },
},
created() {
this.fetchData()
},
methods: {
async fetchData(): Promise<void> {
const pitcherStatsByGame: PitchingStat[] = await fetchPitchingStatsForLastTwoWeeksByTeam(this.seasonNumber, this.weekNumber, this.teamId)
const players: Player[] = await fetchPlayersByTeam(this.seasonNumber, this.teamId)
this.sortedPlayers = players.filter(p => ['SP', 'RP'].includes(p.pos_1)).sort(this.sortPitchers)
console.log(this.sortedPlayers)
this.pitcherStatsByNameWeekGame = Object.fromEntries(pitcherStatsByGame.map(stat => [this.recordKeySelector(stat), stat]))
console.log(this.pitcherStatsByNameWeekGame)
},
//sorts SP above RP and more expensive players up top
sortPitchers(p1: Player, p2: Player): number {
if (p1.pos_1 === p2.pos_1) return p2.wara - p1.wara
return p1.pos_1 === 'SP' ? -1 : 1
},
allPositions(player: Player): string {
let positions = []
positions.push(player.pos_1, player.pos_2, player.pos_3, player.pos_4, player.pos_5, player.pos_6, player.pos_7)
return positions.filter(p => p).join(' ')
},
recordKeySelector(stat: PitchingStat): string {
return `${stat.player.name}-${(stat.game as Game).week}-${(stat.game as Game).game_num}`
},
alternateRecordKeySelector(player: Player, weekNumber: number, gameNumber: number): string {
return `${player.name}-${weekNumber}-${gameNumber}`
},
getIPForPitcherGame(player: Player, weekNumber: number, gameNumber: number): string {
const key = this.alternateRecordKeySelector(player, weekNumber, gameNumber)
const stat: PitchingStat = this.pitcherStatsByNameWeekGame[key]
if (!stat) return '-'
return `${stat?.ip.toFixed(1)}IP`
}
}
}
</script>

View File

@ -155,6 +155,8 @@
</div> </div>
</div> </div>
<BullpenTable v-if="weekNumber && team?.id" :season-number="seasonNumber" :week-number="weekNumber" :team-id="team.id" />
<!-- Schedule --> <!-- Schedule -->
<TeamScheduleTable v-if="!isFreeAgentTeam && team" :season-number="seasonNumber" :team-id="team.id" /> <TeamScheduleTable v-if="!isFreeAgentTeam && team" :season-number="seasonNumber" :team-id="team.id" />
@ -191,10 +193,12 @@ import TeamScheduleTable from '@/components/TeamScheduleTable.vue'
import TeamPitchingTable from '@/components/TeamPitchingTable.vue' import TeamPitchingTable from '@/components/TeamPitchingTable.vue'
import TeamBattingTable from '@/components/TeamBattingTable.vue' import TeamBattingTable from '@/components/TeamBattingTable.vue'
import TeamFieldingTable from '@/components/TeamFieldingTable.vue' import TeamFieldingTable from '@/components/TeamFieldingTable.vue'
import BullpenTable from '@/components/BullpenTable.vue'
export default { export default {
name: 'TeamView', name: 'TeamView',
components: { components: {
BullpenTable,
TeamScheduleTable, TeamScheduleTable,
TeamPitchingTable, TeamPitchingTable,
TeamBattingTable, TeamBattingTable,
@ -309,7 +313,7 @@ export default {
allPositions(player: Player): string { allPositions(player: Player): string {
let positions = [] let positions = []
positions.push(player.pos_1, player.pos_2, player.pos_3, player.pos_4, player.pos_5, player.pos_6, player.pos_7) positions.push(player.pos_1, player.pos_2, player.pos_3, player.pos_4, player.pos_5, player.pos_6, player.pos_7)
return positions.join(' ') return positions.filter(p => p).join(' ')
}, },
swarTotal(players: Player[]): number { swarTotal(players: Player[]): number {
return players.map(p => p.wara).reduce((prev, curr) => prev + curr, 0) return players.map(p => p.wara).reduce((prev, curr) => prev + curr, 0)