feat: turn into game!
This commit is contained in:
@@ -1,13 +1,23 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useBoardGameStore } from '@/modules/5s/board-game-store'
|
import { useBoardGameStore } from '@/modules/5s/board-game-store'
|
||||||
import { tools } from '@/modules/5s/types/tools'
|
import { tools } from '@/modules/5s/types/tools'
|
||||||
|
import { toDuration } from '@/modules/5s/utils'
|
||||||
import { ref, toValue } from 'vue'
|
import { ref, toValue } from 'vue'
|
||||||
|
|
||||||
const userInput = ref('')
|
const userInput = ref('')
|
||||||
const boardGameStore = useBoardGameStore()
|
const boardGameStore = useBoardGameStore()
|
||||||
|
const duration = ref<string | null>(null)
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
duration.value = boardGameStore.start
|
||||||
|
? toDuration(new Date(boardGameStore.start))
|
||||||
|
: null
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
const lastInput = toValue(userInput)
|
const tool = toValue(userInput)
|
||||||
|
|
||||||
|
boardGameStore.craftWithTool(tool)
|
||||||
|
|
||||||
userInput.value = ''
|
userInput.value = ''
|
||||||
}
|
}
|
||||||
@@ -17,9 +27,20 @@ const submit = () => {
|
|||||||
<div class="board-game-workshop">
|
<div class="board-game-workshop">
|
||||||
<aside>
|
<aside>
|
||||||
<h2>Tools</h2>
|
<h2>Tools</h2>
|
||||||
<ul>
|
<table>
|
||||||
<li v-for="tool in tools">{{ tool.name }}</li>
|
<thead>
|
||||||
</ul>
|
<tr>
|
||||||
|
<th>Tool</th>
|
||||||
|
<th>Alias</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="tool in tools" :key="tool.alias">
|
||||||
|
<td>{{ tool.name }}</td>
|
||||||
|
<td>{{ tool.alias }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<div class="main">
|
<div class="main">
|
||||||
@@ -39,6 +60,25 @@ const submit = () => {
|
|||||||
<h3>
|
<h3>
|
||||||
{{ boardGameStore.currentBoardGame.name }}
|
{{ boardGameStore.currentBoardGame.name }}
|
||||||
</h3>
|
</h3>
|
||||||
|
<div v-if="boardGameStore.currentTask">
|
||||||
|
<h4>current task</h4>
|
||||||
|
<p>{{ boardGameStore.currentTask.name }}</p>
|
||||||
|
with tools:
|
||||||
|
<ul>
|
||||||
|
<li
|
||||||
|
v-for="tool in boardGameStore.currentTask.tools"
|
||||||
|
:key="tool.alias"
|
||||||
|
:class="{
|
||||||
|
'used-tool': boardGameStore.usedTools.some(
|
||||||
|
(t) => t === tool.alias
|
||||||
|
)
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ tool.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
<ul>
|
<ul>
|
||||||
<li
|
<li
|
||||||
v-for="part in boardGameStore.currentBoardGame.parts"
|
v-for="part in boardGameStore.currentBoardGame.parts"
|
||||||
@@ -56,6 +96,12 @@ const submit = () => {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<aside v-if="duration">
|
||||||
|
<h2>Performance</h2>
|
||||||
|
|
||||||
|
<p>{{ duration }}</p>
|
||||||
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -71,6 +117,7 @@ const submit = () => {
|
|||||||
min-width: 600px;
|
min-width: 600px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
gap: 4rem;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
font-family: 'Google Sans Code', monospace;
|
font-family: 'Google Sans Code', monospace;
|
||||||
@@ -80,6 +127,10 @@ const submit = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.used-tool {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,131 @@
|
|||||||
import { boardGames } from '@/modules/5s/types/board-games'
|
import { boardGames } from '@/modules/5s/types/board-games'
|
||||||
import { BoardGame } from '@/modules/5s/types/workshop'
|
import { BoardGame, Part, Task } from '@/modules/5s/types/workshop'
|
||||||
|
import { toDuration } from '@/modules/5s/utils'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
boardGames: BoardGame[]
|
boardGames: BoardGame[]
|
||||||
currentBoardGame: BoardGame | null
|
currentBoardGameIndex: number | null
|
||||||
|
currentPartIndex: number | null
|
||||||
|
currentTaskIndex: number | null
|
||||||
|
usedTools: string[]
|
||||||
|
start: string | null
|
||||||
|
end: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useBoardGameStore = defineStore('day', {
|
export const useBoardGameStore = defineStore('board-game', {
|
||||||
state: (): State => ({
|
state: (): State => ({
|
||||||
boardGames: [],
|
boardGames: [],
|
||||||
currentBoardGame: null
|
currentBoardGameIndex: null,
|
||||||
|
currentPartIndex: null,
|
||||||
|
currentTaskIndex: null,
|
||||||
|
usedTools: [],
|
||||||
|
start: null,
|
||||||
|
end: null
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
initGame() {
|
initGame() {
|
||||||
this.currentBoardGame = boardGames[0]
|
this.boardGames = [boardGames[0], boardGames[1]]
|
||||||
|
this.currentBoardGameIndex = 0
|
||||||
|
this.currentPartIndex = 0
|
||||||
|
this.currentTaskIndex = 0
|
||||||
|
this.start = new Date().toISOString()
|
||||||
|
},
|
||||||
|
craftWithTool(tool: string) {
|
||||||
|
if (!this.currentTask) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.currentTask.tools.some((t) => t.alias === tool)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.usedTools = [...this.usedTools, tool]
|
||||||
|
|
||||||
|
if (this.usedTools.length === this.currentTask.tools.length) {
|
||||||
|
this.usedTools = []
|
||||||
|
this.increment()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
increment() {
|
||||||
|
if (
|
||||||
|
!this.currentTask ||
|
||||||
|
!this.currentPart ||
|
||||||
|
!this.currentBoardGame ||
|
||||||
|
this.currentTaskIndex === null ||
|
||||||
|
this.currentPartIndex === null ||
|
||||||
|
this.currentBoardGameIndex === null
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to next task
|
||||||
|
if (this.currentTaskIndex + 1 < this.currentPart.tasks.length) {
|
||||||
|
this.currentTaskIndex += 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// All tasks in part complete, move to next part
|
||||||
|
this.currentTaskIndex = 0
|
||||||
|
if (this.currentPartIndex + 1 < this.currentBoardGame.parts.length) {
|
||||||
|
this.currentPartIndex += 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// All parts in board game complete, move to next board game
|
||||||
|
this.currentPartIndex = 0
|
||||||
|
if (this.currentBoardGameIndex + 1 < this.boardGames.length) {
|
||||||
|
this.currentBoardGameIndex += 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// All board games complete
|
||||||
|
this.end = new Date().toISOString()
|
||||||
|
this.currentBoardGameIndex = null
|
||||||
|
this.currentPartIndex = null
|
||||||
|
this.currentTaskIndex = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
currentBoardGame(): BoardGame | null {
|
||||||
|
if (this.currentBoardGameIndex === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentBoardGameIndex >= this.boardGames.length) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.boardGames[this.currentBoardGameIndex]
|
||||||
|
},
|
||||||
|
currentPart(): Part | null {
|
||||||
|
if (!this.currentBoardGame || this.currentPartIndex === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentPartIndex >= this.currentBoardGame.parts.length) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.currentBoardGame.parts[this.currentPartIndex]
|
||||||
|
},
|
||||||
|
currentTask(): Task | null {
|
||||||
|
if (!this.currentPart || this.currentTaskIndex === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentTaskIndex >= this.currentPart.tasks.length) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.currentPart.tasks[this.currentTaskIndex]
|
||||||
|
},
|
||||||
|
durationToComplete(): string | null {
|
||||||
|
if (!this.start || !this.end) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return toDuration(new Date(this.start), new Date(this.end))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
24
src/modules/5s/utils.ts
Normal file
24
src/modules/5s/utils.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
export const toDuration = (startDate: Date, endDate: Date = new Date()) => {
|
||||||
|
const diffMs = endDate.getTime() - startDate.getTime()
|
||||||
|
|
||||||
|
if (diffMs < 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const seconds = Math.floor(diffMs / 1000) % 60
|
||||||
|
const minutes = Math.floor(diffMs / (1000 * 60)) % 60
|
||||||
|
const hours = Math.floor(diffMs / (1000 * 60 * 60))
|
||||||
|
|
||||||
|
const parts = []
|
||||||
|
|
||||||
|
if (hours > 0) {
|
||||||
|
parts.push(`${hours}h`)
|
||||||
|
}
|
||||||
|
if (minutes > 0) {
|
||||||
|
parts.push(`${minutes}m`)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts.push(`${seconds}s`)
|
||||||
|
|
||||||
|
return parts.join(' ')
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user