Skip to content

Commit 2fe5548

Browse files
committed
pass info
1 parent e725071 commit 2fe5548

12 files changed

Lines changed: 383 additions & 15 deletions

File tree

src/components/round/DebugInfo.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<p class="debug">
55
<b>Card Deck</b>: {{ navigationState.cardDeck.toPersistence() }}<br/>
66
<b>Bot Garden</b>: {{ navigationState.botGarden.toPersistence() }}<br/>
7+
<b>Player Turns:</b> {{ navigationState.playerTurns }}, <b>Delivery Floor:</b> {{ navigationState.playerDeliveryFloor }}<br/>
78
</p>
89
</div>
910
</template>

src/components/round/SideBar.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ export default defineComponent({
146146
margin-bottom: 0.25rem;
147147
.price {
148148
&.buy {
149-
color: darkgreen;
149+
color: darkred;
150150
}
151151
&.sell {
152-
color: red;
152+
color: darkgreen;
153153
}
154154
.value {
155155
font-weight: bold;
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<template>
2+
<span v-if="income || actions || burnCardCount">: </span>
3+
<span v-if="income"><span class="income">$<span class="value">{{income}}</span></span></span>
4+
<div class="actions">
5+
<template v-for="action of actions" :key="action">
6+
<span v-if="isBillboardAction(action)" class="billboard">{{t('roundTurnPlayer.passInfo.billboard', {floor})}}</span>
7+
<AppIcon v-else type="action" :name="action" class="icon" :class="{small}"/>
8+
</template>
9+
</div>
10+
<div class="burnCards" v-if="burnCardCount">
11+
{{ burnCardCount }}✕
12+
</div>
13+
</template>
14+
15+
<script lang="ts">
16+
import { defineComponent } from 'vue'
17+
import { useI18n } from 'vue-i18n'
18+
import { useStateStore } from '@/store/state'
19+
import getSoloBoardPassAction from '@/util/getSoloBoardPassAction'
20+
import Action from '@/services/enum/Action'
21+
import AppIcon from '../structure/AppIcon.vue'
22+
23+
export default defineComponent({
24+
name: 'SoloBoardPassActionInfo',
25+
components: {
26+
AppIcon
27+
},
28+
setup() {
29+
const { t } = useI18n()
30+
const state = useStateStore()
31+
return { t, state }
32+
},
33+
props: {
34+
soloBoardPassAction: {
35+
type: Object as () => ReturnType<typeof getSoloBoardPassAction>,
36+
required: true
37+
},
38+
small: {
39+
type: Boolean,
40+
required: false
41+
}
42+
},
43+
computed: {
44+
income() : number|undefined {
45+
return this.soloBoardPassAction.income == 0 ? undefined : this.soloBoardPassAction.income
46+
},
47+
actions() : Action[]|undefined {
48+
return this.soloBoardPassAction.action.length == 0 ? undefined : this.soloBoardPassAction.action
49+
},
50+
burnCardCount() : number|undefined {
51+
return this.soloBoardPassAction.botBurnCardCount == 0 ? undefined : this.soloBoardPassAction.botBurnCardCount
52+
},
53+
floor() : number {
54+
return this.soloBoardPassAction.floor
55+
}
56+
},
57+
methods: {
58+
isBillboardAction(action : Action) : boolean {
59+
return action == Action.BILLBOARD
60+
}
61+
}
62+
})
63+
</script>
64+
65+
<style lang="scss" scoped>
66+
.income {
67+
margin-left: 0.25rem;
68+
color: darkgreen;
69+
.value {
70+
font-weight: bold;
71+
}
72+
}
73+
.actions {
74+
display: inline-flex;
75+
margin-left: 0.5rem;
76+
gap: 0.25rem;
77+
.icon {
78+
height: 1.25rem;
79+
&.small {
80+
height: 1rem;
81+
}
82+
}
83+
.billboard {
84+
font-weight: bold;
85+
color: #000;
86+
}
87+
}
88+
.burnCards {
89+
margin-left: 0.5rem;
90+
color: #000;
91+
}
92+
</style>

src/locales/en.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
"validationHint": "Please select the flower colors you planted in your garden."
3333
}
3434
},
35+
"roundTurnPlayer": {
36+
"passInfo": {
37+
"nextTurn": "Pass next turn",
38+
"billboard": "M{floor}"
39+
}
40+
},
3541
"sideBar": {
3642
"round": "Year {round}",
3743
"turn": "Turn {turn}",

src/services/SoloBoard.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import Action from './enum/Action'
2+
import BotMode from './enum/BotMode'
23

34
export default interface SoloBoard {
4-
id: string
5+
id: BotMode
56
floorActions: FloorActions[]
67
// index = number of actions taken by user
78
botCardCount: number[]

src/services/SoloBoards.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import findMandatory from '@brdgm/brdgm-commons/src/util/map/findMandatory'
22
import SoloBoard from './SoloBoard'
33
import Action from './enum/Action'
4+
import BotMode from './enum/BotMode'
45

56
/**
67
* Solo boards
78
*/
89
const soloBoards : SoloBoard[] = [
910
{
10-
id: 'base',
11+
id: BotMode.BASE,
1112
floorActions: [
1213
{
1314
floor: 5,
@@ -68,7 +69,7 @@ const soloBoards : SoloBoard[] = [
6869
botCardCount: [2, 3, 4, 4, 5, 5]
6970
},
7071
{
71-
id: 'advanced',
72+
id: BotMode.ADVANCED,
7273
floorActions: [
7374
{
7475
floor: 5,
@@ -130,7 +131,7 @@ const soloBoards : SoloBoard[] = [
130131
}
131132
]
132133

133-
const soloBoardsMap = new Map<string,SoloBoard>()
134+
const soloBoardsMap = new Map<BotMode,SoloBoard>()
134135
for (const soloBoard of soloBoards) {
135136
soloBoardsMap.set(soloBoard.id, soloBoard)
136137
}
@@ -142,7 +143,7 @@ export default {
142143
* @param id ID
143144
* @returns Solo board
144145
*/
145-
get(id: string) : SoloBoard {
146+
get(id: BotMode) : SoloBoard {
146147
return findMandatory(soloBoardsMap, id)
147148
},
148149

src/util/NavigationState.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,36 @@ import BotGarden from '@/services/BotGarden'
77
import getAllEnumValues from '@brdgm/brdgm-commons/src/util/enum/getAllEnumValues'
88
import Flower from '@/services/enum/Flower'
99
import MarketPrices from '@/services/MarketPrices'
10+
import Player from '@/services/enum/Player'
11+
import SoloBoard from '@/services/SoloBoard'
12+
import SoloBoards from '@/services/SoloBoards'
1013

1114
export default class NavigationState {
1215

1316
readonly round : number
1417
readonly turn : number
1518
readonly season : Season
1619

20+
readonly playerTurns: number
21+
readonly playerDeliveryFloor: number
22+
1723
readonly marketPrices : MarketPrices
1824
readonly cardDeck : CardDeck
1925
readonly botGarden : BotGarden
26+
readonly soloBoard : SoloBoard
2027

2128
constructor(route: RouteLocation, state: State) {
2229
this.round = getIntRouteParam(route, 'round')
2330
this.season = getSeason(this.round, state)
2431
this.turn = getIntRouteParam(route, 'turn')
2532

33+
this.playerTurns = getPlayerTurns(this.round, this.turn, state)
34+
this.playerDeliveryFloor = getPlayerDeliveryFloor(this.round, this.turn, state)
35+
2636
this.marketPrices = MarketPrices.fromPersistence(getFlowerPrices(this.round, this.turn, state))
2737
this.cardDeck = CardDeck.fromPersistence(getBotPersistence(this.round, this.turn, state).cardDeck)
2838
this.botGarden = BotGarden.fromPersistence(getBotPersistence(this.round, this.turn, state).garden, this.marketPrices.flowerOrder)
39+
this.soloBoard = SoloBoards.get(state.setup.botMode)
2940
}
3041

3142
}
@@ -35,6 +46,14 @@ function getSeason(round: number, state: State) : Season {
3546
return roundData ? roundData.season : Season.AUTUMN
3647
}
3748

49+
function getPlayerTurns(round: number, turn: number, state: State) : number {
50+
return getTurns(round, turn, state).filter(t => t.player == Player.PLAYER).length
51+
}
52+
53+
function getPlayerDeliveryFloor(round: number, turn: number, state: State) : number {
54+
return getTurns(round, turn, state).find(t => t.player == Player.PLAYER)?.playerDeliveryFloor ?? 1
55+
}
56+
3857
function getFlowerPrices(round: number, turn: number, state: State) : FlowerPrice[] {
3958
const prices = getTurns(round, turn, state).find(t => t.botPersistence)?.marketPrices
4059
if (prices) {

src/util/getSoloBoardPassAction.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import Action from '@/services/enum/Action'
2+
import SoloBoard from '@/services/SoloBoard'
3+
4+
/**
5+
* Get bot actions, income and bot card count from solo board when player passes.
6+
*/
7+
export default function getSoloBoardPassAction(soloBoard: SoloBoard, playerTurns: number, playerDeliveryFloor: number) : SoloBoardPassAction {
8+
let turnsUpTo5 = playerTurns
9+
let turnsBeyond5 = 0
10+
if (playerTurns > 5) {
11+
turnsUpTo5 = 5
12+
turnsBeyond5 = playerTurns - 5
13+
}
14+
15+
const floorActions = soloBoard.floorActions.find(floorAction => floorAction.floor === playerDeliveryFloor)
16+
const income = floorActions?.floorAction[turnsUpTo5]?.income ?? 0
17+
const action = floorActions?.floorAction[turnsUpTo5]?.action ?? []
18+
const botCardCount = soloBoard.botCardCount[turnsUpTo5] ?? 0
19+
const botBurnCardCount = turnsBeyond5 * 3
20+
const floor = playerDeliveryFloor
21+
22+
return {
23+
income,
24+
action,
25+
botCardCount,
26+
botBurnCardCount,
27+
floor
28+
}
29+
}
30+
31+
export interface SoloBoardPassAction {
32+
income: number
33+
action: Action[]
34+
botCardCount: number
35+
botBurnCardCount: number
36+
floor: number
37+
}

src/views/RoundTurnPlayer.vue

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,31 @@
22
<SideBar :navigationState="navigationState"/>
33
<h1>{{t('player.player')}}</h1>
44

5-
<p class="mt-4" v-html="t('roundTurnPlayer.execute')"></p>
5+
<p class="mt-4">Select your action:</p>
6+
7+
<div class="actions">
8+
<button class="btn btn-primary btn-lg" @click="next">
9+
Make Delivery
10+
</button>
11+
<button class="btn btn-primary btn-lg" @click="next">
12+
Buy Flower
13+
</button>
14+
<button class="btn btn-primary btn-lg" @click="next">
15+
Other Action
16+
</button>
17+
<div>
18+
<button class="btn btn-outline-danger btn-lg w-100 d-flex align-items-center" data-bs-toggle="modal" data-bs-target="#passModal">
19+
{{t('action.pass')}}<SoloBoardPassActionInfo :soloBoardPassAction="soloBoardPassAction"/>
20+
</button>
21+
<div class="small mt-1 fst-italic d-flex align-items-center">
22+
<span>{{t('roundTurnPlayer.passInfo.nextTurn')}}</span><SoloBoardPassActionInfo :soloBoardPassAction="soloBoardPassActionNextTurn" :small="true"/>
23+
</div>
24+
</div>
25+
</div>
626

727
<button class="btn btn-primary btn-lg mt-4" @click="next">
828
{{t('action.next')}}
929
</button>
10-
<button class="btn btn-outline-danger btn-lg mt-4 ms-2" data-bs-toggle="modal" data-bs-target="#passModal">
11-
{{t('action.pass')}}
12-
</button>
1330

1431
<ModalDialog id="passModal" :title="t('action.pass')">
1532
<template #body>
@@ -27,7 +44,7 @@
2744
</template>
2845

2946
<script lang="ts">
30-
import { defineComponent } from 'vue'
47+
import { defineComponent, ref } from 'vue'
3148
import { useI18n } from 'vue-i18n'
3249
import { useRoute, useRouter } from 'vue-router'
3350
import NavigationState from '@/util/NavigationState'
@@ -36,13 +53,17 @@ import { useStateStore } from '@/store/state'
3653
import ModalDialog from '@brdgm/brdgm-commons/src/components/structure/ModalDialog.vue'
3754
import SideBar from '@/components/round/SideBar.vue'
3855
import DebugInfo from '@/components/round/DebugInfo.vue'
56+
import getSoloBoardPassAction, { SoloBoardPassAction } from '@/util/getSoloBoardPassAction'
57+
import SoloBoardPassActionInfo from '@/components/round/SoloBoardPassActionInfo.vue'
58+
import Player from '@/services/enum/Player'
3959
4060
export default defineComponent({
4161
name: 'RoundTurnPlayer',
4262
components: {
4363
FooterButtons,
4464
ModalDialog,
4565
SideBar,
66+
SoloBoardPassActionInfo,
4667
DebugInfo
4768
},
4869
setup() {
@@ -53,15 +74,24 @@ export default defineComponent({
5374
5475
const navigationState = new NavigationState(route, state)
5576
const { round, turn } = navigationState
77+
const playerDeliveryFloor = ref(navigationState.playerDeliveryFloor)
5678
57-
return { t, router, navigationState, state, round, turn }
79+
return { t, router, navigationState, state, round, turn, playerDeliveryFloor }
5880
},
5981
computed: {
6082
backButtonRouteTo() : string {
6183
if (this.turn > 1) {
6284
return `/round/${this.round}/turn/${this.turn - 1}/player`
6385
}
6486
return ''
87+
},
88+
soloBoardPassAction() : SoloBoardPassAction {
89+
const { soloBoard, playerTurns, playerDeliveryFloor } = this.navigationState
90+
return getSoloBoardPassAction(soloBoard, playerTurns, playerDeliveryFloor)
91+
},
92+
soloBoardPassActionNextTurn() : SoloBoardPassAction {
93+
const { soloBoard, playerTurns, playerDeliveryFloor } = this.navigationState
94+
return getSoloBoardPassAction(soloBoard, playerTurns + 1, playerDeliveryFloor)
6595
}
6696
},
6797
methods: {
@@ -72,6 +102,13 @@ export default defineComponent({
72102
this.nextWithPassed(true)
73103
},
74104
nextWithPassed(passed : boolean) {
105+
this.state.storeRoundTurn({
106+
round: this.round,
107+
turn: this.turn,
108+
player: Player.PLAYER,
109+
marketPrices: this.navigationState.marketPrices.toPersistence(),
110+
playerDeliveryFloor: this.playerDeliveryFloor
111+
})
75112
if (passed) {
76113
this.router.push(`/round/${this.round}/turn/${this.turn + 1}/bot`)
77114
}
@@ -82,3 +119,12 @@ export default defineComponent({
82119
}
83120
})
84121
</script>
122+
123+
<style lang="scss" scoped>
124+
.actions {
125+
display: flex;
126+
flex-direction: column;
127+
gap: 1rem;
128+
max-width: 15rem;
129+
}
130+
</style>

0 commit comments

Comments
 (0)