Skip to content

Commit 0280063

Browse files
committed
stats
1 parent 38c761f commit 0280063

13 files changed

Lines changed: 387 additions & 23 deletions

File tree

src/components/scoring/FinalScoring.vue

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ import Player from '@/services/enum/Player'
8787
import getAllEnumValues from '@brdgm/brdgm-commons/src/util/enum/getAllEnumValues'
8888
import Flower from '@/services/enum/Flower'
8989
import getFloricultureTrack from '@/util/getFloricultureTracks'
90+
import NavigationState from '@/util/NavigationState'
9091
9192
export default defineComponent({
9293
name: 'FinalScoring',
@@ -102,6 +103,10 @@ export default defineComponent({
102103
amount: {
103104
type: Object as PropType<FinalScoringAmount>,
104105
required: true
106+
},
107+
navigationState: {
108+
type: NavigationState,
109+
required: true
105110
}
106111
},
107112
computed: {
@@ -164,10 +169,11 @@ export default defineComponent({
164169
mounted() {
165170
// send anonymous game stats - max. once per game
166171
if (!this.state.gameStatsSend) {
172+
const allTurns = this.state.rounds.flatMap(r => r.turns)
167173
const stats = {
168174
version,
169175
difficultyLevel: -1,
170-
playerPower: 'TODO',
176+
playerPower: this.state.setup.playerPower ?? 'none',
171177
playerTotalVP: this.totalVPPlayer,
172178
playerScoreTrackVP: toNumber(this.amount.scoreTrackVP[0]),
173179
playerMilestonesVP: toNumber(this.amount.milestonesVP[0]),
@@ -182,29 +188,37 @@ export default defineComponent({
182188
botFloricultureVP: this.getFloricultureVP(1),
183189
playerBillboardsWon: this.amount.billboardsWon.filter(p => p == Player.PLAYER).length,
184190
botBillboardsWon: this.amount.billboardsWon.filter(p => p == Player.BOT).length,
185-
playerFloricultureSteps: 0,
186-
botFloricultureSteps: 0,
191+
playerFloricultureSteps: getAllEnumValues(Flower).map(flower => toNumber(this.amount.floricultureSteps[flower][0])).reduce((sum, steps) => sum + steps, 0),
192+
botFloricultureSteps: getAllEnumValues(Flower).map(flower => toNumber(this.amount.floricultureSteps[flower][1])).reduce((sum, steps) => sum + steps, 0),
187193
playerExtensionSmall: toNumber(this.amount.playerGardenExtensionsSmall),
188194
playerExtensionLarge: toNumber(this.amount.playerGardenExtensionsLarge),
189-
playerTurnsRound1: 0,
190-
playerTurnsRound2: 0,
191-
playerTurnsRound3: 0,
192-
playerTurnsRound4: 0,
193-
playerTurnsRound5: 0,
194-
playerTurnsRound6: 0,
195-
playerTurnsRound7: 0,
196-
playerTurnsRound8: 0,
197-
playerTurnsRound9: 0,
198-
playerTurnsRound10: 0,
199-
playerTurnsRound11: 0,
200-
playerTurnsRound12: 0,
201-
playerTurnsTotal: 0,
202-
botTurnsTotal: 0
195+
playerTurnsRound1: allTurns.filter(t => t.round == 1 && t.player == Player.PLAYER && !t.playerPass).length,
196+
playerTurnsRound2: allTurns.filter(t => t.round == 2 && t.player == Player.PLAYER && !t.playerPass).length,
197+
playerTurnsRound3: allTurns.filter(t => t.round == 3 && t.player == Player.PLAYER && !t.playerPass).length,
198+
playerTurnsRound4: allTurns.filter(t => t.round == 4 && t.player == Player.PLAYER && !t.playerPass).length,
199+
playerTurnsRound5: allTurns.filter(t => t.round == 5 && t.player == Player.PLAYER && !t.playerPass).length,
200+
playerTurnsRound6: allTurns.filter(t => t.round == 6 && t.player == Player.PLAYER && !t.playerPass).length,
201+
playerTurnsRound7: allTurns.filter(t => t.round == 7 && t.player == Player.PLAYER && !t.playerPass).length,
202+
playerTurnsRound8: allTurns.filter(t => t.round == 8 && t.player == Player.PLAYER && !t.playerPass).length,
203+
playerTurnsRound9: allTurns.filter(t => t.round == 9 && t.player == Player.PLAYER && !t.playerPass).length,
204+
playerTurnsRound10: allTurns.filter(t => t.round == 10 && t.player == Player.PLAYER && !t.playerPass).length,
205+
playerTurnsRound11: allTurns.filter(t => t.round == 11 && t.player == Player.PLAYER && !t.playerPass).length,
206+
playerTurnsRound12: allTurns.filter(t => t.round == 12 && t.player == Player.PLAYER && !t.playerPass).length,
207+
playerTurnsTotal: allTurns.filter(t => t.player == Player.PLAYER && !t.playerPass).length,
208+
botTurnsTotal: allTurns.filter(t => t.player == Player.BOT && !t.botBonusTurn).length,
209+
playerDeliveryCount: this.navigationState.botPersistence.windowStates.getTotalDeliveriesByPlayer(Player.PLAYER),
210+
botDeliveryCount: this.navigationState.botPersistence.windowStates.getTotalDeliveriesByPlayer(Player.BOT),
211+
marketTotalPrice: this.navigationState.marketPrices.getTotalMarketPrice(),
212+
botPaidCardVP: allTurns.filter(t => t.player == Player.BOT).reduce((sum, t) => sum + toNumber(t.botPaidCardVP), 0),
213+
botSoloBoardVP: allTurns.filter(t => t.player == Player.BOT).reduce((sum, t) => sum + toNumber(t.botSoloBoardVP), 0),
214+
botDeliveryVP: allTurns.filter(t => t.player == Player.BOT).reduce((sum, t) => sum + toNumber(t.botDeliveryVP), 0),
215+
botFloricultureStarsVP: toNumber(this.amount.scoreTrackVP[1])
216+
- allTurns.filter(t => t.player == Player.BOT).reduce((sum, t) => sum + toNumber(t.botDeliveryVP) + toNumber(t.botSoloBoardVP) + toNumber(t.botDeliveryVP), 0)
203217
}
204218
postGameStats(stats,
205219
import.meta.env.VITE_STATS_FORM_URL,
206220
import.meta.env.VITE_STATS_FIELD_MAPPING)
207-
// TODO: this.state.gameStatsSend = true
221+
this.state.gameStatsSend = true
208222
}
209223
}
210224
})

src/components/setup/BotModeSelection.vue

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,25 @@
55
<div class="col">
66
<div class="form-check" v-for="botMode in botModes" :key="botMode">
77
<label class="form-check-label">
8-
<input class="form-check-input" type="radio" name="botModeSelection" v-model="state.setup.botMode" :value="botMode">
8+
<input class="form-check-input" type="radio" name="botModeSelection" :value="botMode"
9+
:checked="state.setup.botMode === botMode" @change="selectBotMode(botMode)">
910
{{t(`setup.botMode.${botMode}`)}}
1011
</label>
1112
</div>
1213
</div>
1314
</div>
1415

1516
<p v-if="isAdvanced" class="mt-2 fst-italic" v-html="t('setup.botMode.advancedNote')"></p>
17+
18+
<div v-if="isAdvanced" class="row mt-2">
19+
<div class="col-auto">
20+
<select class="form-select" v-model="state.setup.playerPower">
21+
<option v-for="playerPower in playerPowers" :key="playerPower" :value="playerPower">
22+
{{t(`playerPower.${playerPower}`)}}
23+
</option>
24+
</select>
25+
</div>
26+
</div>
1627
</template>
1728

1829
<script lang="ts">
@@ -21,6 +32,7 @@ import { useI18n } from 'vue-i18n'
2132
import { useStateStore } from '@/store/state'
2233
import getAllEnumValues from '@brdgm/brdgm-commons/src/util/enum/getAllEnumValues'
2334
import BotMode from '@/services/enum/BotMode'
35+
import PlayerPower from '@/services/enum/PlayerPower'
2436
2537
export default defineComponent({
2638
name: 'BotModeSelection',
@@ -33,9 +45,22 @@ export default defineComponent({
3345
botModes(): BotMode[] {
3446
return getAllEnumValues(BotMode)
3547
},
48+
playerPowers(): PlayerPower[] {
49+
return getAllEnumValues(PlayerPower)
50+
},
3651
isAdvanced() : boolean {
3752
return this.state.setup.botMode === BotMode.ADVANCED
3853
}
54+
},
55+
methods: {
56+
selectBotMode(botMode: BotMode) {
57+
this.state.setup.botMode = botMode
58+
if (botMode === BotMode.BASE) {
59+
this.state.setup.playerPower = undefined
60+
} else if (!this.state.setup.playerPower) {
61+
this.state.setup.playerPower = this.playerPowers[0]
62+
}
63+
}
3964
}
4065
})
4166
</script>

src/locales/en.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,26 @@
154154
"l": "left",
155155
"r": "right"
156156
},
157+
"playerPower": {
158+
"barber": "Barber",
159+
"barista": "Barista",
160+
"bartender": "Bartender",
161+
"construction-worker": "Construction Worker",
162+
"courier": "Courier",
163+
"day-trader": "Day Trader",
164+
"dog-walker": "Dog Walker",
165+
"foreman": "Foreman",
166+
"grocer": "Grocer",
167+
"influencer": "Influencer",
168+
"interior-decorator": "Interior Decorator",
169+
"kindergarten-teacher": "Kindergarten Teacher",
170+
"mover": "Mover",
171+
"painter": "Painter",
172+
"scientist": "Scientist",
173+
"student": "Student",
174+
"window-washer": "Window Washer",
175+
"yoga-instructor": "Yoga Instructor"
176+
},
157177
"rules": {
158178
"action": {
159179
"managedByApp": "This action is managed by the application.",

src/services/MarketPrices.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ export default class MarketPrices {
9595
this.setPrice(flower, price - 1)
9696
}
9797

98+
/**
99+
* Gets total market price by summing prices of all flowers.
100+
* @returns Total market price
101+
*/
102+
public getTotalMarketPrice() : number {
103+
return this._prices.value.reduce((total, item) => total + item.price, 0)
104+
}
105+
98106
/**
99107
* Gets persistence view of market prices.
100108
*/

src/services/WindowStates.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ export default class WindowStates {
9595
return bestMatch
9696
}
9797

98+
/**
99+
* Gets the total number of deliveries made by the specified player.
100+
*/
101+
public getTotalDeliveriesByPlayer(player: Player) : number {
102+
return this._windowStates.value.reduce((sum, w) => sum + w.deliveries.filter(p => p === player).length, 0)
103+
}
104+
98105
/**
99106
* Sorts the windows by floor (descending) and window position (left, right).
100107
*/

src/services/enum/PlayerPower.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Player Power
3+
*/
4+
enum PlayerPower {
5+
BARBER = 'barber',
6+
BARISTA = 'barista',
7+
BARTENDER = 'bartender',
8+
CONSTRUCTION_WORKER = 'construction-worker',
9+
COURIER = 'courier',
10+
DAY_TRADER = 'day-trader',
11+
DOG_WALKER = 'dog-walker',
12+
FOREMAN = 'foreman',
13+
GROCER = 'grocer',
14+
INFLUENCER = 'influencer',
15+
INTERIOR_DECORATOR = 'interior-decorator',
16+
KINDERGARTEN_TEACHER = 'kindergarten-teacher',
17+
MOVER = 'mover',
18+
PAINTER = 'painter',
19+
SCIENTIST = 'scientist',
20+
STUDENT = 'student',
21+
WINDOW_WASHER = 'window-washer',
22+
YOGA_INSTRUCTOR = 'yoga-instructor'
23+
}
24+
export default PlayerPower

src/store/state.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Flower from '@/services/enum/Flower'
77
import Season from '@/services/enum/Season'
88
import Milestone from '@/services/enum/Milestone'
99
import WindowSelection from '@/services/enum/WindowSelection'
10+
import PlayerPower from '@/services/enum/PlayerPower'
1011

1112
export const useStateStore = defineStore(`${name}.state`, {
1213
state: () => {
@@ -55,6 +56,7 @@ export interface State {
5556
}
5657
export interface Setup {
5758
botMode: BotMode
59+
playerPower?: PlayerPower
5860
playerColor: PlayerColor
5961
botColor: PlayerColor
6062
milestoneSeasonOrder?: Season[]
@@ -78,6 +80,11 @@ export interface RoundTurn {
7880
playerDeliveryFloor?: number
7981
playerPass?: boolean
8082
botPersistence: BotPersistence
83+
// stats
84+
botBonusTurn?: boolean
85+
botPaidCardVP?: number
86+
botSoloBoardVP?: number
87+
botDeliveryVP?: number
8188
}
8289

8390
export interface FlowerPrice {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { BotAction } from '@/services/BotActions'
2+
import Action from '@/services/enum/Action'
3+
import { RoundTurn } from '@/store/state'
4+
5+
/**
6+
* Records statistics for a bot's round turn based on the actions taken.
7+
*/
8+
export default function recordBotRoundTurnStats(turn: RoundTurn, botTurn: number, actions: readonly BotAction[]) : void {
9+
const botPaidCardVP = getActionVP(actions, Action.PAID)
10+
const botSoloBoardVP = getActionVP(actions, Action.VP_5)
11+
const botDeliveryVP = getActionVP(actions, Action.DELIVERY) + getActionVP(actions, Action.WINDOW_BOX)
12+
13+
if (botTurn == 0) {
14+
turn.botBonusTurn = true
15+
}
16+
if (botPaidCardVP > 0) {
17+
turn.botPaidCardVP = botPaidCardVP
18+
}
19+
if (botSoloBoardVP > 0) {
20+
turn.botSoloBoardVP = botSoloBoardVP
21+
}
22+
if (botDeliveryVP > 0) {
23+
turn.botDeliveryVP = botDeliveryVP
24+
}
25+
}
26+
27+
function getActionVP(actions: readonly BotAction[], action: Action) : number {
28+
return actions.filter(a => a.action === action).reduce((total, a) => total + (a.vp ?? 0), 0)
29+
}

src/views/EndOfGame.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<SideBar :navigationState="navigationState" :readOnly="true"/>
33
<h1 class="mb-3">{{t('endOfGame.title')}}</h1>
44

5-
<FinalScoring :amount="amount"/>
5+
<FinalScoring :amount="amount" :navigationState="navigationState"/>
66

77
<FooterButtons :backButtonRouteTo="backButtonRouteTo" endGameButtonType="endGame"/>
88
</template>

src/views/RoundTurnBot.vue

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ import { useI18n } from 'vue-i18n'
2828
import { useRoute, useRouter } from 'vue-router'
2929
import NavigationState from '@/util/NavigationState'
3030
import FooterButtons from '@/components/structure/FooterButtons.vue'
31-
import { useStateStore } from '@/store/state'
31+
import { RoundTurn, useStateStore } from '@/store/state'
3232
import SideBar from '@/components/round/SideBar.vue'
3333
import DebugInfo from '@/components/round/DebugInfo.vue'
3434
import Card from '@/services/Card'
3535
import Player from '@/services/enum/Player'
3636
import BotClaimMilestones from '@/components/round/BotClaimMilestones.vue'
3737
import BotAction from '@/components/round/BotAction.vue'
3838
import BotActions from '@/services/BotActions'
39+
import recordBotRoundTurnStats from '@/util/recordBotRoundTurnStats'
3940
4041
export default defineComponent({
4142
name: 'RoundTurnBot',
@@ -78,13 +79,15 @@ export default defineComponent({
7879
if (this.navigationState.botTurn > 0) {
7980
this.navigationState.botPersistence.cardDeck.checkCurrentCardRemove()
8081
}
81-
this.state.storeRoundTurn({
82+
const turn : RoundTurn = {
8283
round: this.round,
8384
turn: this.turn,
8485
player: Player.BOT,
8586
marketPrices: this.navigationState.marketPrices.toPersistence(),
8687
botPersistence: this.navigationState.botPersistence.toPersistence()
87-
})
88+
}
89+
recordBotRoundTurnStats(turn, this.navigationState.botTurn, this.botActions.actions)
90+
this.state.storeRoundTurn(turn)
8891
if (this.navigationState.botTurn == this.navigationState.botTurns) {
8992
if (this.round == 12) {
9093
this.router.push(`/round/${this.round}/gameEnd/amounts`)

0 commit comments

Comments
 (0)