Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
{}
{
"i18n-ally.localesPaths": [
"src/locales"
]
}
1 change: 1 addition & 0 deletions src/components/round/DebugInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<b>draftingPriority</b>: <span v-html="getCardDeckInfo(draftingPriority)"></span><br/>
<b>construction</b>: <span v-html="getCardDeckInfo(construction)"></span><br/>
<b>war</b>: <span v-html="getCardDeckInfo(war)"></span><br/>
<b>lastDraftStep</b>: {{navigationState.lastDraftStep}}<br/>
</p>
</div>
</template>
Expand Down
100 changes: 43 additions & 57 deletions src/components/round/TechCardDraft.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,27 @@
<button class="btn btn-primary btn-lg me-3 mt-2" @click="next()">
{{t('action.next')}}
</button>
<button class="btn btn-outline-secondary btn-sm mt-2" @click="reset()">
{{t('action.reset')}}
</button>

<div class="draftedCards">
<div v-if="playerTechs.length > 0" class="mt-3">
<TechCardsPlayerDraft :navigationState="navigationState" :playerTechs="playerTechs"/>
<div v-if="techDraftStep.playerTechs.length > 0" class="mt-3">
<TechCardsPlayerDraft :navigationState="navigationState" :playerTechs="techDraftStep.playerTechs"/>
</div>

<div v-if="botTechs.length > 0" class="mt-3">
<div v-if="techDraftStep.botTechs.length > 0" class="mt-3">
<h5>{{t('phaseADrafting.botDraft')}}</h5>
<div class="techs">
<div class="techRow">
<TechCard v-for="tech of botTechs" :key="tech" :navigationState="navigationState" :tech="tech" class="techCard disabled"/>
<TechCard v-for="tech of techDraftStep.botTechs" :key="tech" :navigationState="navigationState" :tech="tech" class="techCard disabled"/>
</div>
</div>
</div>
</div>

</template>

<script lang="ts">
import { defineComponent, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useStateStore } from '@/store/state'
import { TechDraftStep, useStateStore } from '@/store/state'
import NavigationState from '@/util/NavigationState'
import TechCardSelection from '@/services/TechCardSelection'
import Tech from '@/services/enum/Tech'
Expand All @@ -67,6 +63,7 @@ import TechCard from './TechCard.vue'
import AppIcon from '../structure/AppIcon.vue'
import TechCardsPlayerDraft from './TechCardsPlayerDraft.vue'
import { useRouter } from 'vue-router'
import { cloneDeep } from 'lodash'

export default defineComponent({
name: 'TechCardDraft',
Expand All @@ -81,11 +78,18 @@ export default defineComponent({
const router = useRouter()

const roundData = state.rounds.find(item => item.round == props.navigationState.round)!
const botTechs = ref(roundData.botTechs ?? [])
const playerTechs = ref(roundData.playerTechs ?? [])
const playerSpecialActions = ref(roundData.playerSpecialActions ?? 0)
const lastTechDraftStep = props.navigationState.lastDraftStep
const techDraftStep = ref({
round: props.navigationState.round,
step: props.navigationState.draftingStep,
nextStartPlayer: lastTechDraftStep?.nextStartPlayer,
nextArchitectPlayer: lastTechDraftStep?.nextArchitectPlayer,
botTechs: cloneDeep(lastTechDraftStep?.botTechs ?? []),
playerTechs: cloneDeep(lastTechDraftStep?.playerTechs ?? []),
playerSpecialActions: lastTechDraftStep?.playerSpecialActions ?? 0
} as TechDraftStep)

return { t, state, router, roundData, botTechs, playerTechs, playerSpecialActions }
return { t, state, router, roundData, techDraftStep }
},
props: {
navigationState: {
Expand All @@ -108,22 +112,22 @@ export default defineComponent({
return this.navigationState.techCardSelection
},
botMarkerPlaced() : number {
return this.botTechs.length
return this.techDraftStep.botTechs.length
},
playerMarkerPlaced() : number {
return this.playerTechs.length + this.playerSpecialActions
return this.techDraftStep.playerTechs.length + this.techDraftStep.playerSpecialActions
},
draftingCompleted() : boolean {
return this.botMarkerPlaced == 4 && this.playerMarkerPlaced == 4
},
playerIncomeTotal() : number {
return this.playerTechs.map(tech => this.techCardSelection.getIncome(tech)).filter(value => value < 5).reduce((a,b) => a+b, 0)
return this.techDraftStep.playerTechs.map(tech => this.techCardSelection.getIncome(tech)).filter(value => value < 5).reduce((a,b) => a+b, 0)
},
playerIncomeLockedTotal() : number {
return this.playerTechs.map(tech => this.techCardSelection.getIncome(tech)).filter(value => value == 5).reduce((a,b) => a+b, 0)
return this.techDraftStep.playerTechs.map(tech => this.techCardSelection.getIncome(tech)).filter(value => value == 5).reduce((a,b) => a+b, 0)
},
botRound8Army() : boolean {
return this.navigationState.round == 8 && this.botTechs.includes(Tech.ARMY)
return this.navigationState.round == 8 && this.techDraftStep.botTechs.includes(Tech.ARMY)
}
},
methods: {
Expand All @@ -145,21 +149,15 @@ export default defineComponent({
await new Promise(resolve => setTimeout(resolve, 400))
this.removeAnimation = false
this.navigationState.techCardSelection.remove(tech)
this.persist()
},
async nextTurn() {
if (this.draftingCompleted) {
return
}
if (this.botMarkerPlaced < this.playerMarkerPlaced) {
if (this.roundData.startPlayer == Player.BOT) {
await this.nextTurnBot()
}
else if (this.playerMarkerPlaced < this.botMarkerPlaced) {
await this.nextTurnPlayer()
}
else if (this.roundData.startPlayer == Player.BOT) {
await this.nextTurnBot()
}
else {
await this.nextTurnPlayer()
}
Expand All @@ -169,15 +167,14 @@ export default defineComponent({
const draftingRowCard = botCards.draftingRow.draw()
const draftingPriorityCard = botCards.draftingPriority.draw()
const tech = techCardSelection.determineTech(draftingRowCard, draftingPriorityCard, prosperityCards.current.flat())
this.botTechs.push(tech)
this.techDraftStep.botTechs.push(tech)
if (tech == Tech.ARMY) {
this.roundData.nextStartPlayer = Player.BOT
this.techDraftStep.nextStartPlayer = Player.BOT
}
if (tech == Tech.ENGINEERING) {
this.roundData.nextArchitectPlayer = Player.BOT
this.techDraftStep.nextArchitectPlayer = Player.BOT
}
await this.remove(tech)
await this.nextTurn()
},
async nextTurnPlayer() {
this.playerTurn = true
Expand All @@ -191,48 +188,37 @@ export default defineComponent({
return
}
this.playerTurn = false
this.playerTechs.push(t)
this.roundData.playerTechs = this.playerTechs
this.techDraftStep.playerTechs.push(t)
if (t == Tech.ARMY) {
this.roundData.nextStartPlayer = Player.PLAYER
this.techDraftStep.nextStartPlayer = Player.PLAYER
}
if (t == Tech.ENGINEERING) {
this.roundData.nextArchitectPlayer = Player.PLAYER
this.techDraftStep.nextArchitectPlayer = Player.PLAYER
}
await this.remove(t)
await this.nextTurn()
},
async reset() {
this.techCardSelection.reset()
this.navigationState.botCards.draftingRow.reset()
this.navigationState.botCards.draftingPriority.reset()
this.roundData.nextStartPlayer = undefined
this.roundData.nextArchitectPlayer = undefined
this.roundData.playerTechs = undefined

this.botTechs = []
this.playerTechs = []
this.playerSpecialActions = 0

this.persist()
await this.nextTurn()
await this.playerTurnCompleted()
},
async next() {
if (this.draftingCompleted) {
this.router.push(this.nextButtonRouteTo)
}
else {
this.playerSpecialActions++
this.techDraftStep.playerSpecialActions++
this.playerTurn = false
this.persist()
await this.nextTurn()
await this.playerTurnCompleted()
}
},
async playerTurnCompleted() {
// if player was first player, execute bot turn before going to next step
if (this.roundData.startPlayer == Player.PLAYER) {
await this.nextTurnBot()
}
this.persistAndNextStep()
},
persist() : void {
this.roundData.techCardSelection = this.techCardSelection.toPersistence()
this.roundData.botTechs = this.botTechs
this.roundData.playerTechs = this.playerTechs
this.roundData.playerSpecialActions = this.playerSpecialActions
persistAndNextStep() : void {
this.techDraftStep.techCardSelection = this.techCardSelection.toPersistence()
this.state.storeTechDraftStep(this.techDraftStep)
this.router.push(`/round/${this.navigationState.round}/drafting/${this.techDraftStep.step+1}`)
}
},
mounted() {
Expand Down
3 changes: 1 addition & 2 deletions src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@
"backToHome": "Zurück zum Anfang",
"back": "Zurück",
"close": "Schließen",
"ok": "OK",
"reset": "Zurücksetzen"
"ok": "OK"
},
"footer": {
"credits": "Credits"
Expand Down
3 changes: 1 addition & 2 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@
"backToHome": "Back to Home",
"back": "Back",
"close": "Close",
"ok": "OK",
"reset": "Reset"
"ok": "OK"
},
"footer": {
"credits": "Credits"
Expand Down
5 changes: 5 additions & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ const routes: Array<RouteRecordRaw> = [
},
{
path: '/round/:round/drafting',
// redirect to step 1 of drafting phase (route is kept for backward compatibility)
redirect: (to) => ({ name: 'PhaseADrafting', params: { round: to.params.round, step: '1' } })
},
{
path: '/round/:round/drafting/:step',
name: 'PhaseADrafting',
component: PhaseADrafting
},
Expand Down
7 changes: 0 additions & 7 deletions src/services/TechCardSelection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,6 @@ export default class TechCardSelection {
throw new Error('Tech card not found.')
}

/**
* Resets the removed tech cards.
*/
public reset() : void {
this._removedTechs.value = []
}

/**
* Creates a selection of techs in 4 ros respecting the placeholder rows.
*/
Expand Down
23 changes: 22 additions & 1 deletion src/store/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ export const useStateStore = defineStore(`${name}.state`, {
storeRound(round : Round) {
this.rounds = this.rounds.filter(item => item.round < round.round)
this.rounds.push(round)
},
storeTechDraftStep(techDraftStep : TechDraftStep) {
const round = this.rounds.find(item => item.round == techDraftStep.round)
if (round) {
round.techDraftSteps = (round.techDraftSteps ?? []).filter(item => item.step < techDraftStep.step)
round.techDraftSteps.push(techDraftStep)
}
}
},
persist: true
Expand All @@ -51,12 +58,26 @@ export interface Round {
prosperityCards: ProsperityCardsPersistence
botCards: BotCardsPersistence
rowPlaceholders: RowPlaceholdersPersistence
techCardSelection: TechCardSelectionPersistence
initialTechCardSelection?: TechCardSelectionPersistence
techDraftSteps?: TechDraftStep[]
// the following fields are deprecated, latest implementation uses the initialTechCardSelection and techDraftSteps fields instead
nextStartPlayer?: Player
nextArchitectPlayer?: Player
botTechs?: Tech[]
playerTechs?: Tech[]
playerSpecialActions?: number
techCardSelection?: TechCardSelectionPersistence
}

export interface TechDraftStep {
round: number
step: number
techCardSelection: TechCardSelectionPersistence
nextStartPlayer?: Player
nextArchitectPlayer?: Player
botTechs: Tech[]
playerTechs: Tech[]
playerSpecialActions: number
}

export interface BotCardsPersistence {
Expand Down
33 changes: 28 additions & 5 deletions src/util/NavigationState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Round, State } from '@/store/state'
import { Round, State, TechCardSelectionPersistence, TechDraftStep } from '@/store/state'
import { RouteLocation } from 'vue-router'
import getIntRouteParam from '@brdgm/brdgm-commons/src/util/router/getIntRouteParam'
import Player from '@/services/enum/Player'
Expand All @@ -10,15 +10,18 @@ import TechCardSelection from '@/services/TechCardSelection'
export default class NavigationState {

readonly round : number
readonly draftingStep: number
readonly prosperityCards : ProsperityCards
readonly botCards : BotCards
readonly rowPlaceholders : RowPlaceholders
readonly techCardSelection : TechCardSelection

private readonly roundData : Round
readonly lastDraftStep? : TechDraftStep

constructor(route: RouteLocation, state: State) {
this.round = getIntRouteParam(route, 'round')
this.draftingStep = getIntRouteParam(route, 'step')

let roundData = state.rounds.find(item => item.round === this.round)
if (!roundData) {
Expand All @@ -31,22 +34,42 @@ export default class NavigationState {
prosperityCards: ProsperityCards.new().toPersistence(),
botCards: BotCards.new(state.setup.difficultyLevel).toPersistence(),
rowPlaceholders: rowPlaceholders.toPersistence(),
techCardSelection: TechCardSelection.new(rowPlaceholders.rows, this.round).toPersistence()
}
}
this.roundData = roundData
this.lastDraftStep = this.getLastDraftStep()
this.prosperityCards = ProsperityCards.fromPersistence(roundData.prosperityCards)
this.botCards = BotCards.fromPersistence(roundData.botCards)
this.rowPlaceholders = RowPlaceholders.fromPersistence(roundData.rowPlaceholders)
this.techCardSelection = TechCardSelection.fromPersistence(roundData.techCardSelection, this.round)
this.techCardSelection = TechCardSelection.fromPersistence(this.getTechCardSelectionPersistence(), this.round)
}

public get startPlayer() : Player {
return this.roundData.nextStartPlayer ?? this.roundData.startPlayer
return this.lastDraftStep?.nextStartPlayer ?? this.roundData.nextStartPlayer ?? this.roundData.startPlayer
}

public get architectPlayer() : Player {
return this.roundData.nextArchitectPlayer ?? this.roundData.architectPlayer
return this.lastDraftStep?.nextArchitectPlayer ?? this.roundData.nextArchitectPlayer ?? this.roundData.architectPlayer
}

private getLastDraftStep() : TechDraftStep | undefined {
return (this.roundData.techDraftSteps?.toSorted((a, b) => a.step - b.step) ?? [])
.findLast(item => item.step < this.draftingStep || this.draftingStep == 0)
}

private getTechCardSelectionPersistence() : TechCardSelectionPersistence {
if (this.lastDraftStep?.techCardSelection) {
return this.lastDraftStep?.techCardSelection
}
if (this.roundData.initialTechCardSelection) {
return this.roundData.initialTechCardSelection
}
if (this.roundData.techCardSelection) {
// backward compatibility with old implementation; reset selection to restart draft
return { techs: this.roundData.techCardSelection.techs, removedTechs: [] }
}
// should never happen
return TechCardSelection.new(this.rowPlaceholders.rows, this.round).toPersistence()
}

}
Loading
Loading