feat: counting used tools to sort
This commit is contained in:
68
src/modules/5s/BoardGamePerformance.vue
Normal file
68
src/modules/5s/BoardGamePerformance.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<script setup lang="ts">
|
||||
import { useBoardGameStore } from '@/modules/5s/board-game-store'
|
||||
import { toDuration, toSeconds } from '@/modules/5s/utils'
|
||||
import { getNatural } from '@/utils'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const boardGameStore = useBoardGameStore()
|
||||
|
||||
const duration = ref<string | null>(null)
|
||||
|
||||
setInterval(() => {
|
||||
duration.value = boardGameStore.meta.start
|
||||
? toDuration(
|
||||
new Date(boardGameStore.meta.start),
|
||||
boardGameStore.meta.end ? new Date(boardGameStore.meta.end) : new Date()
|
||||
)
|
||||
: null
|
||||
}, 1000)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="board-game-performance">
|
||||
<p class="numeric">{{ duration }}</p>
|
||||
|
||||
<template v-if="boardGameStore.meta.perfs.length > 0">
|
||||
<h3>Last performances</h3>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Round</th>
|
||||
<th>Duration</th>
|
||||
<th>Board Games</th>
|
||||
<th>Time / board game</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(perf, index) in boardGameStore.meta.perfs">
|
||||
<td>{{ index + 1 }}</td>
|
||||
<td class="numeric">
|
||||
{{ toDuration(new Date(perf.start), new Date(perf.end)) }}
|
||||
</td>
|
||||
<td class="numeric">
|
||||
{{ perf.totalGames }}
|
||||
</td>
|
||||
<td class="numeric">
|
||||
{{
|
||||
getNatural(
|
||||
toSeconds(new Date(perf.start), new Date(perf.end)),
|
||||
perf.totalGames
|
||||
)
|
||||
}}s
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{{ boardGameStore.countUsedTools }}
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.board-game-performance {
|
||||
.numeric {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -4,14 +4,36 @@ import { shuffleArray } from '@/utils'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const boardGameStore = useBoardGameStore()
|
||||
|
||||
const isSeiriActivated = computed(() => boardGameStore.sUsed.includes('seiri'))
|
||||
const isSeitonActivated = computed(() =>
|
||||
boardGameStore.sUsed.includes('seiton')
|
||||
)
|
||||
// const isSeisoActivated = computed(() => boardGameStore.sUsed.includes('seiso'))
|
||||
|
||||
const rawTools = computed(() =>
|
||||
shuffleArray(
|
||||
boardGameStore.tools.map((t) => `${t.name} (ref: ${t.reference})`)
|
||||
).join(', ')
|
||||
const neededTools = computed(
|
||||
() =>
|
||||
new Set(
|
||||
boardGameStore.boardGames
|
||||
.flatMap((g) => g.parts)
|
||||
.flatMap((p) => p.tasks)
|
||||
.flatMap((t) => t.tools)
|
||||
.map((t) => t.id)
|
||||
)
|
||||
)
|
||||
|
||||
const tools = computed(() => {
|
||||
if (isSeiriActivated.value) {
|
||||
return boardGameStore.tools.filter((t) => neededTools.value.has(t.id))
|
||||
} else {
|
||||
return boardGameStore.tools
|
||||
}
|
||||
})
|
||||
|
||||
const toolsToDisplay = computed(() =>
|
||||
shuffleArray(tools.value.map((t) => `${t.name} (ref: ${t.reference})`)).join(
|
||||
', '
|
||||
)
|
||||
)
|
||||
</script>
|
||||
|
||||
@@ -23,18 +45,20 @@ const rawTools = computed(() =>
|
||||
<tr>
|
||||
<th>Tool</th>
|
||||
<th>Reference</th>
|
||||
<th>Used</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="tool in boardGameStore.tools" :key="tool.reference">
|
||||
<tr v-for="tool in tools" :key="tool.reference">
|
||||
<td>{{ tool.name }}</td>
|
||||
<td>{{ tool.reference }}</td>
|
||||
<td class="numeric">{{ tool.reference }}</td>
|
||||
<td>{{ boardGameStore.countUsedTools[tool.id] }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ rawTools }}
|
||||
{{ toolsToDisplay }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,30 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { useBoardGameStore } from '@/modules/5s/board-game-store'
|
||||
import BoardGamePerformance from '@/modules/5s/BoardGamePerformance.vue'
|
||||
import BoardGameToolbox from '@/modules/5s/BoardGameToolbox.vue'
|
||||
import { _5S, is5S } from '@/modules/5s/types/5s'
|
||||
import { toDuration } from '@/modules/5s/utils'
|
||||
import { onMounted, ref, toValue } from 'vue'
|
||||
|
||||
const userInput = ref('')
|
||||
const mode = ref<_5S | null>(null)
|
||||
const boardGameStore = useBoardGameStore()
|
||||
const duration = ref<string | null>(null)
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
onMounted(() => {
|
||||
boardGameStore.initGame()
|
||||
})
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
duration.value = boardGameStore.meta.start
|
||||
? toDuration(
|
||||
new Date(boardGameStore.meta.start),
|
||||
boardGameStore.meta.end ? new Date(boardGameStore.meta.end) : new Date()
|
||||
)
|
||||
: null
|
||||
}, 1000)
|
||||
|
||||
const submit = () => {
|
||||
const lastInput = toValue(userInput)
|
||||
userInput.value = ''
|
||||
@@ -49,6 +38,11 @@ const submit = () => {
|
||||
boardGameStore.activateS(command)
|
||||
return
|
||||
}
|
||||
|
||||
// d for debug
|
||||
if (command === 'd') {
|
||||
boardGameStore.increment()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -151,18 +145,7 @@ const submit = () => {
|
||||
</div>
|
||||
<aside class="performance prose">
|
||||
<h2>Performance</h2>
|
||||
|
||||
<p class="duration numeric">{{ duration }}</p>
|
||||
|
||||
<template v-if="boardGameStore.meta.perfs.length > 0">
|
||||
<h3>Last performances</h3>
|
||||
|
||||
<ul>
|
||||
<li v-for="[start, end] in boardGameStore.meta.perfs">
|
||||
{{ toDuration(new Date(start), new Date(end)) }}
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<BoardGamePerformance />
|
||||
</aside>
|
||||
</div>
|
||||
</template>
|
||||
@@ -171,12 +154,6 @@ const submit = () => {
|
||||
@import url('https://fonts.googleapis.com/css2?family=Google+Sans+Code&display=swap');
|
||||
|
||||
.board-game-workshop {
|
||||
flex: 1;
|
||||
font-family: 'Google Sans Code', monospace;
|
||||
font-optical-sizing: auto;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
padding: 1rem;
|
||||
@@ -218,7 +195,7 @@ aside,
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.duration {
|
||||
text-align: right;
|
||||
.card-title {
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { boardGames } from '@/modules/5s/types/board-games'
|
||||
import { tools } from '@/modules/5s/types/tools'
|
||||
import { BoardGame, Part, Task, Tool } from '@/modules/5s/types/workshop'
|
||||
import { toDuration } from '@/modules/5s/utils'
|
||||
import { randomAlias } from '@/utils'
|
||||
import { accumulate, randomAlias } from '@/utils'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
type State = {
|
||||
@@ -17,14 +17,20 @@ type State = {
|
||||
meta: {
|
||||
start: string | null
|
||||
end: string | null
|
||||
perfs: Array<[string, string]>
|
||||
perfs: Array<{
|
||||
start: string
|
||||
end: string
|
||||
boardGames: BoardGame[]
|
||||
countGames: Record<string, number>
|
||||
totalGames: number
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
const firstDemands = [
|
||||
boardGames[0],
|
||||
boardGames[0]
|
||||
// boardGames[0],
|
||||
// boardGames[0],
|
||||
// boardGames[0]
|
||||
]
|
||||
|
||||
@@ -113,7 +119,17 @@ export const useBoardGameStore = defineStore('board-game', {
|
||||
|
||||
// All board games complete
|
||||
this.meta.end = new Date().toISOString()
|
||||
this.meta.perfs = [...this.meta.perfs, [this.meta.start, this.meta.end]]
|
||||
const countGames = accumulate(this.boardGames.map((b) => b.name))
|
||||
this.meta.perfs = [
|
||||
...this.meta.perfs,
|
||||
{
|
||||
start: this.meta.start,
|
||||
end: this.meta.end,
|
||||
boardGames: [...this.boardGames],
|
||||
countGames,
|
||||
totalGames: this.boardGames.length
|
||||
}
|
||||
]
|
||||
this.currentBoardGameIndex = null
|
||||
this.currentPartIndex = null
|
||||
this.currentTaskIndex = null
|
||||
@@ -162,6 +178,50 @@ export const useBoardGameStore = defineStore('board-game', {
|
||||
}
|
||||
|
||||
return toDuration(new Date(this.meta.start), new Date(this.meta.end))
|
||||
},
|
||||
countUsedTools(): Record<string, number> {
|
||||
const metaToolIds = this.meta.perfs
|
||||
.flatMap((p) => p.boardGames)
|
||||
.flatMap((b) => b.parts)
|
||||
.flatMap((p) => p.tasks)
|
||||
.flatMap((t) => t.tools)
|
||||
.map((t) => t.id)
|
||||
|
||||
if (
|
||||
!this.meta.start ||
|
||||
!this.currentTask ||
|
||||
!this.currentPart ||
|
||||
!this.currentBoardGame ||
|
||||
this.currentTaskIndex === null ||
|
||||
this.currentPartIndex === null ||
|
||||
this.currentBoardGameIndex === null
|
||||
) {
|
||||
return accumulate(metaToolIds)
|
||||
}
|
||||
|
||||
const currentBoardGameIndex = this.currentBoardGameIndex
|
||||
const currentPartIndex = this.currentPartIndex
|
||||
const currentTaskIndex = this.currentTaskIndex
|
||||
|
||||
const toolIds = this.boardGames
|
||||
.filter((_, i) => i <= currentBoardGameIndex)
|
||||
.flatMap((b, boardIndex) =>
|
||||
boardIndex === currentBoardGameIndex
|
||||
? b.parts.filter((_, i) => i <= currentPartIndex)
|
||||
: b.parts
|
||||
)
|
||||
.flatMap((p, partIndex) =>
|
||||
partIndex === currentPartIndex
|
||||
? p.tasks.filter((_, i) => i <= currentTaskIndex)
|
||||
: p.tasks
|
||||
)
|
||||
.flatMap((t, taskIndex) =>
|
||||
taskIndex === currentTaskIndex
|
||||
? this.usedTools
|
||||
: t.tools.map((t) => t.id)
|
||||
)
|
||||
|
||||
return accumulate([...metaToolIds, ...toolIds])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -10,7 +10,6 @@ import { NonEmptyArray } from '@/modules/5s/types/tools'
|
||||
export type Tool = {
|
||||
name: string
|
||||
alias: string
|
||||
cooldown: number
|
||||
}
|
||||
|
||||
export type Task = {
|
||||
@@ -29,14 +28,14 @@ export type BoardGame = {
|
||||
}
|
||||
|
||||
export const tools: Tool[] = [
|
||||
{ name: 'Card Printer', alias: 'card-printer', cooldown: 5 },
|
||||
{ name: 'Miniature Mold', alias: 'mini-mold', cooldown: 15 },
|
||||
{ name: 'Dice Engraver', alias: 'dice-engraver', cooldown: 10 },
|
||||
{ name: 'Board Cutter', alias: 'board-cutter', cooldown: 8 },
|
||||
{ name: 'Rulebook Designer', alias: 'rulebook-dzn', cooldown: 6 },
|
||||
{ name: 'Box Assembler', alias: 'box-asm', cooldown: 4 },
|
||||
{ name: 'Component Painter', alias: 'painter', cooldown: 12 },
|
||||
{ name: 'Lamination Machine', alias: 'laminator', cooldown: 7 }
|
||||
{ name: 'Card Printer', alias: 'card-printer' },
|
||||
{ name: 'Miniature Mold', alias: 'mini-mold' },
|
||||
{ name: 'Dice Engraver', alias: 'dice-engraver' },
|
||||
{ name: 'Board Cutter', alias: 'board-cutter' },
|
||||
{ name: 'Rulebook Designer', alias: 'rulebook-dzn' },
|
||||
{ name: 'Box Assembler', alias: 'box-asm' },
|
||||
{ name: 'Component Painter', alias: 'painter' },
|
||||
{ name: 'Lamination Machine', alias: 'laminator' }
|
||||
]
|
||||
export type NonEmptyArray<T> = [T, ...T[]]
|
||||
|
||||
|
||||
@@ -1,53 +1,47 @@
|
||||
import { Tool } from '@/modules/5s/types/workshop'
|
||||
|
||||
export const tools: Tool[] = [
|
||||
{ name: 'Card Printer', id: 'card-printer', reference: '', cooldown: 5 },
|
||||
{ name: 'Miniature Mold', id: 'mini-mold', reference: '', cooldown: 15 },
|
||||
{ name: 'Dice Engraver', id: 'dice-engraver', reference: '', cooldown: 10 },
|
||||
{ name: 'Cutter', id: 'cutter', reference: '', cooldown: 8 },
|
||||
{ name: 'Rulebook Designer', id: 'rulebook-dzn', reference: '', cooldown: 6 },
|
||||
{ name: 'Box Assembler', id: 'box-asm', reference: '', cooldown: 4 },
|
||||
{ name: 'Component Painter', id: 'painter', reference: '', cooldown: 12 },
|
||||
{ name: 'Lamination Machine', id: 'laminator', reference: '', cooldown: 7 },
|
||||
{ name: 'Card Printer', id: 'card-printer', reference: '' },
|
||||
{ name: 'Miniature Mold', id: 'mini-mold', reference: '' },
|
||||
{ name: 'Dice Engraver', id: 'dice-engraver', reference: '' },
|
||||
{ name: 'Cutter', id: 'cutter', reference: '' },
|
||||
{ name: 'Rulebook Designer', id: 'rulebook-dzn', reference: '' },
|
||||
{ name: 'Box Assembler', id: 'box-asm', reference: '' },
|
||||
{ name: 'Component Painter', id: 'painter', reference: '' },
|
||||
{ name: 'Lamination Machine', id: 'laminator', reference: '' },
|
||||
// Additional realistic tools
|
||||
{
|
||||
name: 'Shrink Wrap Machine',
|
||||
id: 'shrink-wrap',
|
||||
reference: '',
|
||||
cooldown: 9
|
||||
reference: ''
|
||||
},
|
||||
{
|
||||
name: 'Punch Board Cutter',
|
||||
id: 'punch-cutter',
|
||||
reference: '',
|
||||
cooldown: 11
|
||||
reference: ''
|
||||
},
|
||||
{
|
||||
name: 'Sticker Applicator',
|
||||
id: 'sticker-applicator',
|
||||
reference: '',
|
||||
cooldown: 6
|
||||
reference: ''
|
||||
},
|
||||
{
|
||||
name: 'Foil Stamping Press',
|
||||
id: 'foil-stamp',
|
||||
reference: '',
|
||||
cooldown: 13
|
||||
reference: ''
|
||||
},
|
||||
{
|
||||
name: 'Scanner',
|
||||
id: 'scanner',
|
||||
reference: '',
|
||||
cooldown: 5
|
||||
reference: ''
|
||||
},
|
||||
{
|
||||
name: 'Instruction Sheet Folder',
|
||||
id: 'sheet-folder',
|
||||
reference: '',
|
||||
cooldown: 7
|
||||
reference: ''
|
||||
},
|
||||
{ name: 'Plastic Bag Sealer', id: 'bag-sealer', reference: '', cooldown: 4 },
|
||||
{ name: 'Barcode Printer', id: 'barcode-printer', reference: '', cooldown: 8 }
|
||||
{ name: 'Plastic Bag Sealer', id: 'bag-sealer', reference: '' },
|
||||
{ name: 'Barcode Printer', id: 'barcode-printer', reference: '' }
|
||||
]
|
||||
export type NonEmptyArray<T> = [T, ...T[]]
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ export type Tool = {
|
||||
name: string
|
||||
id: string
|
||||
reference: string
|
||||
cooldown: number
|
||||
}
|
||||
|
||||
export type Task = {
|
||||
|
||||
@@ -22,3 +22,7 @@ export const toDuration = (startDate: Date, endDate: Date = new Date()) => {
|
||||
|
||||
return parts.join(' ')
|
||||
}
|
||||
|
||||
export const toSeconds = (start: Date, endDate: Date): number => {
|
||||
return Math.floor((endDate.getTime() - start.getTime()) / 1000)
|
||||
}
|
||||
|
||||
10
src/utils.ts
10
src/utils.ts
@@ -21,6 +21,9 @@ export const getMean = (data: number[]) =>
|
||||
export const getRound = (data: number, total: number) =>
|
||||
(Math.round(100 * (data / total)) / 100 || 0).toFixed(2)
|
||||
|
||||
export const getNatural = (data: number, total: number) =>
|
||||
(Math.round(100 * (data / total)) / 100 || 0).toFixed(0)
|
||||
|
||||
export const shuffleArray = <T>(array: T[]) => {
|
||||
let currentIndex = array.length,
|
||||
randomIndex
|
||||
@@ -37,6 +40,13 @@ export const shuffleArray = <T>(array: T[]) => {
|
||||
return array
|
||||
}
|
||||
|
||||
export const accumulate = (array: string[]) => {
|
||||
return array.reduce<Record<string, number>>((acc, toolId) => {
|
||||
acc[toolId] = (acc[toolId] || 0) + 1
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
|
||||
export const popNElement = <T>(array: T[], numberOfElements: number) => {
|
||||
const poppedElements: T[] = []
|
||||
|
||||
|
||||
Reference in New Issue
Block a user