Add team pitching table
This commit is contained in:
parent
0ca9a9e8b3
commit
672ef8ece1
1
components.d.ts
vendored
1
components.d.ts
vendored
@ -26,6 +26,7 @@ declare module '@vue/runtime-core' {
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
StandingsTable: typeof import('./src/components/StandingsTable.vue')['default']
|
||||
TeamPitchingTable: typeof import('./src/components/TeamPitchingTable.vue')['default']
|
||||
TeamScheduleTable: typeof import('./src/components/TeamScheduleTable.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { aggregatePitchingStats, type PitchingStat } from '@/services/pitchingStatsService'
|
||||
import { outsToInnings } from '@/services/utilities'
|
||||
import { hitsPer9, hrsPer9, outsToInnings, winPercentage } from '@/services/utilities'
|
||||
|
||||
interface PitchingStatWithSeason extends PitchingStat {
|
||||
seasonNumber: number
|
||||
@ -170,19 +170,13 @@ export default {
|
||||
return outsToInnings(stat)
|
||||
},
|
||||
winPercentage(stat: PitchingStat): string {
|
||||
if (stat.win + stat.loss === 0) return '-'
|
||||
|
||||
return (stat.win / (stat.win + stat.loss)).toFixed(3)
|
||||
return winPercentage(stat)
|
||||
},
|
||||
hitsPer9(stat: PitchingStat): string {
|
||||
if (stat.outs === 0) return '-'
|
||||
|
||||
return (stat.hits * 27 / stat.outs).toFixed(1)
|
||||
return hitsPer9(stat)
|
||||
},
|
||||
hrsPer9(stat: PitchingStat): string {
|
||||
if (stat.outs === 0) return '-'
|
||||
|
||||
return (stat.hr * 27 / stat.outs).toFixed(1)
|
||||
return hrsPer9(stat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
163
src/components/TeamPitchingTable.vue
Normal file
163
src/components/TeamPitchingTable.vue
Normal file
@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<div v-if="pitchingStats.length" class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3>Team Pitching {{ isRegularSeason ? '' : ' - Postseason' }}</h3>
|
||||
<div class="table-responsive-xl">
|
||||
<table class="table table-sm table-striped" id="table-pitching-stats">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Player</th>
|
||||
<th>W</th>
|
||||
<th>L</th>
|
||||
<th>W-L%</th>
|
||||
<th>ERA</th>
|
||||
<th>G</th>
|
||||
<th>GS</th>
|
||||
<th>SV</th>
|
||||
<th>HD</th>
|
||||
<th>BSV</th>
|
||||
<th>IP</th>
|
||||
<th>H</th>
|
||||
<th>R</th>
|
||||
<th>ER</th>
|
||||
<th>HR</th>
|
||||
<th>BB</th>
|
||||
<th>SO</th>
|
||||
<th>HBP</th>
|
||||
<th>BK</th>
|
||||
<th>WP</th>
|
||||
<th>IR</th>
|
||||
<th>IRS</th>
|
||||
<th>WHIP</th>
|
||||
<th>H/9</th>
|
||||
<th>HR/9</th>
|
||||
<th>BB/9</th>
|
||||
<th>SO/9</th>
|
||||
<th>SO/BB</th>
|
||||
<!-- <th>Last G</th>
|
||||
<th>Last G-2</th> -->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="team-pitching-stats">
|
||||
<tr v-for="stat in pitchingStats">
|
||||
<td>
|
||||
<RouterLink
|
||||
:to="{ name: 'player', params: { seasonNumber: seasonNumber, playerName: stat.player.name } }">
|
||||
{{ stat.player.name }}
|
||||
</RouterLink>
|
||||
</td>
|
||||
<td>{{ stat.win }}</td>
|
||||
<td>{{ stat.loss }}</td>
|
||||
<td>{{ winPercentage(stat) }}</td>
|
||||
<td>{{ stat.era.toFixed(2) }}</td>
|
||||
<td>{{ stat.games }}</td>
|
||||
<td>{{ stat.gs }}</td>
|
||||
<td>{{ stat.save }}</td>
|
||||
<td>{{ stat.hold }}</td>
|
||||
<td>{{ stat.bsave }}</td>
|
||||
<td>{{ outsToInnings(stat) }}</td>
|
||||
<td>{{ stat.hits }}</td>
|
||||
<td>{{ stat.run }}</td>
|
||||
<td>{{ stat.e_run }}</td>
|
||||
<td>{{ stat.hr }}</td>
|
||||
<td>{{ stat.bb }}</td>
|
||||
<td>{{ stat.so }}</td>
|
||||
<td>{{ stat.hbp }}</td>
|
||||
<td>{{ stat.balk }}</td>
|
||||
<td>{{ stat.wp }}</td>
|
||||
<td>{{ stat.ir }}</td>
|
||||
<td>{{ stat.ir_sc }}</td>
|
||||
<td>{{ stat.whip.toFixed(2) }}</td>
|
||||
<td>{{ hitsPer9(stat) }}</td>
|
||||
<td>{{ hrsPer9(stat) }}</td>
|
||||
<td>{{ stat.bbPer9.toFixed(1) }}</td>
|
||||
<td>{{ stat.kPer9.toFixed(1) }}</td>
|
||||
<td>{{ stat.kPerBB.toFixed(1) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr v-if="totalPitchingStat">
|
||||
<th>Total</th>
|
||||
<th>{{ totalPitchingStat.win }}</th>
|
||||
<th>{{ totalPitchingStat.loss }}</th>
|
||||
<th>{{ winPercentage(totalPitchingStat) }}</th>
|
||||
<th>{{ totalPitchingStat.era.toFixed(2) }}</th>
|
||||
<th>{{ totalPitchingStat.games }}</th>
|
||||
<th>{{ totalPitchingStat.gs }}</th>
|
||||
<th>{{ totalPitchingStat.save }}</th>
|
||||
<th>{{ totalPitchingStat.hold }}</th>
|
||||
<th>{{ totalPitchingStat.bsave }}</th>
|
||||
<th>{{ outsToInnings(totalPitchingStat) }}</th>
|
||||
<th>{{ totalPitchingStat.hits }}</th>
|
||||
<th>{{ totalPitchingStat.run }}</th>
|
||||
<th>{{ totalPitchingStat.e_run }}</th>
|
||||
<th>{{ totalPitchingStat.hr }}</th>
|
||||
<th>{{ totalPitchingStat.bb }}</th>
|
||||
<th>{{ totalPitchingStat.so }}</th>
|
||||
<th>{{ totalPitchingStat.hbp }}</th>
|
||||
<th>{{ totalPitchingStat.balk }}</th>
|
||||
<th>{{ totalPitchingStat.wp }}</th>
|
||||
<th>{{ totalPitchingStat.ir }}</th>
|
||||
<th>{{ totalPitchingStat.ir_sc }}</th>
|
||||
<th>{{ totalPitchingStat.whip.toFixed(2) }}</th>
|
||||
<th>{{ hitsPer9(totalPitchingStat) }}</th>
|
||||
<th>{{ hrsPer9(totalPitchingStat) }}</th>
|
||||
<th>{{ totalPitchingStat.bbPer9.toFixed(1) }}</th>
|
||||
<th>{{ totalPitchingStat.kPer9.toFixed(1) }}</th>
|
||||
<th>{{ totalPitchingStat.kPerBB.toFixed(1) }}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { aggregatePitchingStats, fetchPitchingStatsBySeasonAndTeamId, type PitchingStat } from '@/services/pitchingStatsService'
|
||||
import { outsToInnings, winPercentage, hitsPer9, hrsPer9 } from '@/services/utilities'
|
||||
|
||||
export default {
|
||||
name: "TeamPitchingTable",
|
||||
props: {
|
||||
seasonNumber: { type: Number, required: true },
|
||||
teamId: { type: Number, required: true },
|
||||
isRegularSeason: { type: Boolean, required: true }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pitchingStats: [] as PitchingStat[]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
totalPitchingStat(): PitchingStat | undefined {
|
||||
if (this.pitchingStats.length > 0) {
|
||||
return aggregatePitchingStats(this.pitchingStats)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
async fetchData(): Promise<void> {
|
||||
const unsortedPitchingStats: PitchingStat[] = await fetchPitchingStatsBySeasonAndTeamId(this.seasonNumber, this.teamId, this.isRegularSeason)
|
||||
this.pitchingStats = unsortedPitchingStats.sort((s1, s2) => s2.outs - s1.outs)
|
||||
},
|
||||
outsToInnings(stat: PitchingStat): string {
|
||||
return outsToInnings(stat)
|
||||
},
|
||||
winPercentage(stat: PitchingStat): string {
|
||||
return winPercentage(stat)
|
||||
},
|
||||
hitsPer9(stat: PitchingStat): string {
|
||||
return hitsPer9(stat)
|
||||
},
|
||||
hrsPer9(stat: PitchingStat): string {
|
||||
return hrsPer9(stat)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -7,7 +7,7 @@ export async function fetchGamesBySeasonAndTeamId(seasonNumber: number, teamId:
|
||||
return []
|
||||
}
|
||||
|
||||
const response = await fetch(`${SITE_URL}/api/v3/games?season=${seasonNumber}&team1_id=${teamId}&team2_id=${teamId}`)
|
||||
const response = await fetch(`${SITE_URL}/api/v3/games?season=${seasonNumber}&team1_id=${teamId}&team2_id=${teamId}&season_type=regular`)
|
||||
|
||||
const gamesResponse: {
|
||||
count: number
|
||||
|
||||
@ -152,6 +152,19 @@ export async function fetchPitchingStatsBySeasonAndPlayerId(seasonNumber: number
|
||||
return normalizePitchingStat(pitchingStatsResponse.stats[0])
|
||||
}
|
||||
|
||||
export async function fetchPitchingStatsBySeasonAndTeamId(seasonNumber: number, teamId: number, isRegularSeason: boolean): Promise<PitchingStat[]> {
|
||||
const response = await fetch(`${SITE_URL}/api/v3/plays/pitching?season=${seasonNumber}&team_id=${teamId}&group_by=playerteam&s_type=${isRegularSeason ? 'regular' : 'post'}`)
|
||||
|
||||
const pitchingStatsResponse: {
|
||||
count: number
|
||||
stats: PitchingStatRaw[]
|
||||
} = await response.json()
|
||||
|
||||
if (pitchingStatsResponse.count === 0) return []
|
||||
|
||||
return pitchingStatsResponse.stats.map(normalizePitchingStat)
|
||||
}
|
||||
|
||||
async function fetchLegacyPitchingStatsBySeasonAndPlayerId(seasonNumber: number, playerId: number, isRegularSeason: boolean): Promise<PitchingStat | undefined> {
|
||||
const response = await fetch(`${SITE_URL}/api/v3/pitchingstats/totals?season=${seasonNumber}&player_id=${playerId}&s_type=${isRegularSeason ? 'regular' : 'post'}`)
|
||||
|
||||
|
||||
@ -44,3 +44,21 @@ export function woba(stat: { bb: number, hbp: number, hit: number, double: numbe
|
||||
export function outsToInnings(stat: { outs: number }): string {
|
||||
return (stat.outs / 3).toFixed(1)
|
||||
}
|
||||
|
||||
export function winPercentage(stat: { win: number, loss: number }): string {
|
||||
if (stat.win + stat.loss === 0) return '-'
|
||||
|
||||
return (stat.win / (stat.win + stat.loss)).toFixed(3)
|
||||
}
|
||||
|
||||
export function hitsPer9(stat: { outs: number, hits: number }): string {
|
||||
if (stat.outs === 0) return '-'
|
||||
|
||||
return (stat.hits * 27 / stat.outs).toFixed(1)
|
||||
}
|
||||
|
||||
export function hrsPer9(stat: { outs: number, hr: number }): string {
|
||||
if (stat.outs === 0) return '-'
|
||||
|
||||
return (stat.hr * 27 / stat.outs).toFixed(1)
|
||||
}
|
||||
|
||||
@ -157,6 +157,12 @@
|
||||
|
||||
<!-- Schedule -->
|
||||
<TeamScheduleTable v-if="!isFreeAgentTeam && team" :season-number="seasonNumber" :team-id="team.id" />
|
||||
|
||||
<!-- Team Pitching -->
|
||||
<TeamPitchingTable v-if="!isFreeAgentTeam && team" :is-regular-season="true" :season-number="seasonNumber"
|
||||
:team-id="team.id" />
|
||||
<TeamPitchingTable v-if="!isFreeAgentTeam && team" :is-regular-season="false" :season-number="seasonNumber"
|
||||
:team-id="team.id" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -168,11 +174,13 @@ import { fetchStandings, type TeamStanding } from '@/services/standingsService'
|
||||
import { fetchTeam } from '@/services/teamsService'
|
||||
import { fetchTransactionsByTeamAndWeek, type Transaction } from '@/services/transactionsService'
|
||||
import TeamScheduleTable from '@/components/TeamScheduleTable.vue'
|
||||
import TeamPitchingTable from '@/components/TeamPitchingTable.vue'
|
||||
|
||||
export default {
|
||||
name: "TeamView",
|
||||
components: {
|
||||
TeamScheduleTable
|
||||
TeamScheduleTable,
|
||||
TeamPitchingTable
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user