Skip to content

Commit

Permalink
refactor project
Browse files Browse the repository at this point in the history
  • Loading branch information
tanzhijian committed Dec 21, 2023
1 parent d4c742b commit 6b8df51
Show file tree
Hide file tree
Showing 13 changed files with 425 additions and 258 deletions.
2 changes: 0 additions & 2 deletions auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,6 @@ import { UnwrapRef } from 'vue'
declare module 'vue' {
interface ComponentCustomProperties {
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly Game: UnwrapRef<typeof import('./src/composables/logic')['Game']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
readonly computed: UnwrapRef<typeof import('vue')['computed']>
Expand Down Expand Up @@ -576,7 +575,6 @@ declare module 'vue' {
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly Game: UnwrapRef<typeof import('./src/composables/logic')['Game']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
readonly computed: UnwrapRef<typeof import('vue')['computed']>
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="icon" href="/favicon.png">
<title>Score Simulator</title>
<meta name="description" content="Opinionated Vite Starter Template">
</head>
Expand Down
Binary file added public/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
100 changes: 100 additions & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import type { MatchTypes, MatchesTypes } from '~/types'
import { Frame, FrameTeam, Result, ResultTeam } from '~/models'

export function selectMatches(
date: string,
matches: MatchesTypes,
): MatchTypes[] {
const selected = matches[date]
selected.sort((aMatch: MatchTypes, bMatch: MatchTypes) => {
const aDate = new Date(aMatch.utc_time)
const bDate = new Date(bMatch.utc_time)
if (aDate < bDate)
return -1
if (aDate > bDate)
return 1
return 0
})
return selected
}

export class Game {
constructor(public match: MatchTypes) {}

result = ref(new Result(
new ResultTeam(this.match.home.name),
new ResultTeam(this.match.away.name),
this.match.competition.name,
))

generateXG(mu: number, sigma = 0.1) {
// 使用逆变换法生成正态分布的随机数来得到 xg
// 标准差先使用一点假设的数值
const u = Math.random()
const z
= Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * Math.random())

let xg = mu + sigma * z
if (xg <= 0)
xg = 0.01
else if (xg > 1)
xg = 0.99

return xg
}

attack(): Frame {
const frame = new Frame(new FrameTeam(), new FrameTeam())

const homeXGPerShot = this.match.home.xg / this.match.home.shots
const awayXGPerShot = this.match.away.xg / this.match.away.shots
const homeShotPercentage
= this.match.home.shots / (this.match.home.shots + this.match.away.shots)
const shotProbPerMinute
= (this.match.home.shots + this.match.away.shots)
/ ((this.match.home.played + this.match.away.played) / 2)
/ 90

if (Math.random() < shotProbPerMinute) {
if (Math.random() < homeShotPercentage) {
frame.home.shot = true
frame.home.xg = this.generateXG(homeXGPerShot)
if (Math.random() < homeXGPerShot)
frame.home.score = true
}
else {
frame.away.shot = true
frame.away.xg = this.generateXG(awayXGPerShot)
if (Math.random() < awayXGPerShot)
frame.away.score = true
}
}

return frame
}

play(fulltime: number = 90, delay: number = 100): void {
this.result.value.reset()
this.result.value.played = true

const intervalId = setInterval(() => {
const frame = this.attack()
this.result.value.home.shots += +frame.home.shot
this.result.value.home.xg += frame.home.xg
this.result.value.home.score += +frame.home.score
this.result.value.away.shots += +frame.away.shot
this.result.value.away.xg += frame.away.xg
this.result.value.away.score += +frame.away.score

if (frame.home.score)
this.result.value.home.goalMinutes.push(this.result.value.timing)
else if (frame.away.score)
this.result.value.away.goalMinutes.push(this.result.value.timing)

this.result.value.timing += 1

if (this.result.value.timing >= fulltime)
clearInterval(intervalId)
}, delay)
}
}
49 changes: 21 additions & 28 deletions src/components/Match.vue
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
<script setup lang="ts">
import { useDateFormat } from '@vueuse/core'
import type { Match } from '~/types'
import { Game } from '~/composables/logic'
import type { MatchTypes } from '~/types'
import { Game } from '~/api'
const props = defineProps<{ match: Match }>()
const props = defineProps<{ match: MatchTypes }>()
const formatter = 'YYYY-MM-DD HH:mm'
const formattedDatetime = useDateFormat(props.match.utc_time, formatter)
const FULLTIME = 90
const DELAY = 100
const game = new Game(
props.match.home.shots,
props.match.home.xg,
props.match.home.played,
props.match.away.shots,
props.match.away.xg,
props.match.away.played,
)
const game = new Game(props.match)
</script>

<template>
Expand All @@ -42,42 +35,42 @@ const game = new Game(
<div>{{ match.home.name }}</div>
<div text="left gray" flex="~ gap1" justify-center p5>
<div
v-if="game.state.value.homeGoalLog.length !== 0" i-carbon-circle-packing mt="0.3"
v-if="game.result.value.home.goalLog.length !== 0" i-carbon-circle-packing mt="0.3"
style="min-width: 1.25rem;"
/>
{{ game.state.value.homeGoalLog }}
{{ game.result.value.home.goalLog }}
</div>
</div>
<!-- 比分和状态 -->
<div flex-1>
<div v-if="!game.state.value.played && !match.finished" text-8>
<div v-if="!game.result.value.played && !match.finished" text-8>
-
</div>
<div v-else text-8>
{{
match.finished ? match.home.score : game.state.value.homeScore
match.finished ? match.home.score : game.result.value.home.score
}}
-
{{
match.finished ? match.away.score : game.state.value.awayScore
match.finished ? match.away.score : game.result.value.away.score
}}
</div>
<div>
<div v-if="!game.state.value.played" text="gray">
<div v-if="!game.result.value.played" text="gray">
{{ formattedDatetime }}
</div>
<div v-else-if="game.state.value.timing >= 90">
<div v-else-if="game.result.value.timing >= 90">
<div>
{{ game.state.value.homeXG.toFixed(2) }}
{{ game.result.value.home.xg.toFixed(2) }}
- xG -
{{ game.state.value.awayXG.toFixed(2) }}
{{ game.result.value.away.xg.toFixed(2) }}
</div>
<span text="green-600" font-mono>
{{ game.state.value.xgProgress }}
{{ game.result.value.xgProgressBar }}
</span>
</div>
<div v-else text="green-600 4">
{{ `${game.state.value.timing}:00` }}
{{ `${game.result.value.timing}:00` }}
</div>
</div>
<!-- 按钮 -->
Expand All @@ -86,18 +79,18 @@ const game = new Game(
Full time
</div>
<div
v-else-if="game.state.value.timing > 0 && game.state.value.timing < 90
v-else-if="game.result.value.timing > 0 && game.result.value.timing < 90
" text="3"
>
<div>
- Shots -
</div>
<div>
{{ game.state.value.homeShots }}
{{ game.result.value.home.shots }}
<span text="green-600" font-mono>
{{ game.state.value.shotsProgress }}
{{ game.result.value.shotsProgressBar }}
</span>
{{ game.state.value.awayShots }}
{{ game.result.value.away.shots }}
</div>
</div>
<button v-else i-carbon-play-filled bg-green-600 @click="game.play(FULLTIME, DELAY)" />
Expand All @@ -111,10 +104,10 @@ const game = new Game(
<div>{{ match.away.name }}</div>
<div text="left gray" flex="~ gap1" justify-center p5>
<div
v-if="game.state.value.awayGoalLog.length !== 0" i-carbon-circle-packing mt="0.3"
v-if="game.result.value.away.goalLog.length !== 0" i-carbon-circle-packing mt="0.3"
style="min-width: 1.25rem;"
/>
{{ game.state.value.awayGoalLog }}
{{ game.result.value.away.goalLog }}
</div>
</div>
</div>
Expand Down
149 changes: 0 additions & 149 deletions src/composables/logic.ts

This file was deleted.

Loading

0 comments on commit 6b8df51

Please sign in to comment.