add quality issue

This commit is contained in:
Julien Calixte
2023-07-22 17:34:26 +02:00
parent 1579e2598e
commit 05e89f6b03
7 changed files with 115 additions and 39 deletions

View File

@@ -1,3 +1,9 @@
@import url('https://fonts.googleapis.com/css2?family=Cutive+Mono&display=swap');
:root {
--feature-item-height: 70px;
}
ul { ul {
list-style: none; list-style: none;
padding: 0; padding: 0;
@@ -8,7 +14,7 @@ ul {
border: 3px solid var(--background-color); border: 3px solid var(--background-color);
color: var(--background-color); color: var(--background-color);
background-color: white; background-color: white;
height: 62px; height: var(--feature-item-height);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
@@ -32,3 +38,8 @@ ul {
color: white; color: white;
transition-delay: 3s; transition-delay: 3s;
} }
.numeric {
font-family: 'Cutive Mono', monospace;
font-weight: bold;
}

View File

@@ -0,0 +1,31 @@
<script setup lang="ts">
import { Feature } from '@/modules/feature/feature'
import { computed } from 'vue'
const props = defineProps<{ feature: Feature }>()
const hasQualityIssues = computed(() => props.feature.qualityIssue > 0)
</script>
<template>
<div class="feature-item">
<div class="bin">
<div>
{{ feature.name }}
<span class="numeric">({{ feature.complexity }})</span>
</div>
<div class="lead-time numeric">{{ feature.leadTime }} days</div>
<div v-if="hasQualityIssues" class="red-bin numeric">
{{ feature.qualityIssue }} issues
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.feature-item {
.red-bin {
background-color: #ff7979;
padding: 0 0.5rem;
}
}
</style>

View File

@@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import FeatureItem from '@/modules/feature/FeatureItem.vue'
import { Feature } from '@/modules/feature/feature' import { Feature } from '@/modules/feature/feature'
import { FeatureStep } from '@/modules/feature/feature-steps' import { FeatureStep } from '@/modules/feature/feature-steps'
import { computed } from 'vue' import { computed } from 'vue'
@@ -34,13 +35,11 @@ const isLive = computed(
<h5>📝</h5> <h5>📝</h5>
<ul v-if="hasFeaturesInProgress"> <ul v-if="hasFeaturesInProgress">
<li v-for="feature in featuresInProgress" :key="feature.name"> <li v-for="feature in featuresInProgress" :key="feature.name">
<Starport :port="feature.name" style="height: 62px"> <Starport
<div class="bin"> :port="feature.name"
<div> style="height: var(--feature-item-height)"
{{ feature.name }} >
</div> <FeatureItem :feature="feature" />
<div class="lead-time">{{ feature.leadTime }} days</div>
</div>
</Starport> </Starport>
</li> </li>
</ul> </ul>
@@ -56,13 +55,11 @@ const isLive = computed(
</div> </div>
<ul class="done-list" v-if="hasFeaturesDone"> <ul class="done-list" v-if="hasFeaturesDone">
<li v-for="feature in featuresDone" :key="feature.name"> <li v-for="feature in featuresDone" :key="feature.name">
<Starport :port="feature.name" style="height: 62px"> <Starport
<div class="bin"> :port="feature.name"
<div> style="height: var(--feature-item-height)"
{{ feature.name }} >
</div> <FeatureItem :feature="feature" />
<div class="lead-time">{{ feature.leadTime }} days</div>
</div>
</Starport> </Starport>
</li> </li>
</ul> </ul>
@@ -71,11 +68,7 @@ const isLive = computed(
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
@import url('https://fonts.googleapis.com/css2?family=Cutive+Mono&display=swap');
.feature-step { .feature-step {
--success-color: #20bf6b;
header { header {
padding: 0.5rem; padding: 0.5rem;
border: solid 2px var(--background-color); border: solid 2px var(--background-color);
@@ -100,11 +93,6 @@ const isLive = computed(
flex-direction: column; flex-direction: column;
} }
.lead-time {
font-family: 'Cutive Mono', monospace;
font-weight: bold;
}
.done-list { .done-list {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;

View File

@@ -3,6 +3,46 @@ import { FeatureStep } from '@/modules/feature/feature-steps'
import { features } from '@/modules/feature/feature.fixture' import { features } from '@/modules/feature/feature.fixture'
import { pickRandomElement, popNElement, shuffleArray } from '@/utils' import { pickRandomElement, popNElement, shuffleArray } from '@/utils'
const hasQualityIssue = (
complexity: number,
tasksInParallel: number
): boolean => {
let probabilityOfQualityIssue = 0
switch (complexity) {
case 1:
probabilityOfQualityIssue = 0.8
break
case 2:
probabilityOfQualityIssue = 0.7
break
case 3:
probabilityOfQualityIssue = 0.6
break
default:
probabilityOfQualityIssue = 0.5
break
}
let multiplicator = 1
switch (tasksInParallel) {
case 1:
multiplicator = 1
case 2:
multiplicator = 1.05
case 3:
multiplicator = 1.08
case 4:
multiplicator = 1.1
case 5:
multiplicator = 1.15
}
return Math.random() > probabilityOfQualityIssue / multiplicator
}
export const createFeatureBoard = () => { export const createFeatureBoard = () => {
const boardFeatures = shuffleArray(features) const boardFeatures = shuffleArray(features)
@@ -24,6 +64,7 @@ export const createFeatureBoard = () => {
if (isFeatureLive) { if (isFeatureLive) {
return return
} }
feature.leadTime++ feature.leadTime++
switch (feature.status) { switch (feature.status) {
@@ -32,7 +73,20 @@ export const createFeatureBoard = () => {
break break
case 'done': case 'done':
feature.status = 'doing' feature.status = 'doing'
if (
hasQualityIssue(
feature.complexity,
features.filter(
(f) => f.status === 'doing' && f.step === feature.step
).length
)
) {
feature.step = Math.min(4, feature.step + 1)
feature.qualityIssue++
} else {
feature.step-- feature.step--
}
break break
} }
}) })

View File

@@ -6,24 +6,14 @@ export type FeatureStep = {
export const featureSteps: FeatureStep[] = [ export const featureSteps: FeatureStep[] = [
{ {
title: 'Pitch', title: 'Product',
stepIndex: 6, stepIndex: 4,
blueBuckets: 2 blueBuckets: 2
}, },
{ {
title: 'Design', title: 'Design',
stepIndex: 5,
blueBuckets: 1
},
{
title: 'Investigation',
stepIndex: 4,
blueBuckets: 1
},
{
title: 'Product',
stepIndex: 3, stepIndex: 3,
blueBuckets: 2 blueBuckets: 1
}, },
{ {
title: 'Development', title: 'Development',

View File

@@ -208,5 +208,6 @@ export const features: Feature[] = featureNames.map((name) => ({
complexity: Math.floor(Math.random() * 5), complexity: Math.floor(Math.random() * 5),
leadTime: 0, leadTime: 0,
status: 'doing', status: 'doing',
step: Infinity step: Infinity,
qualityIssue: 0
})) }))

View File

@@ -6,4 +6,5 @@ export type Feature = {
leadTime: number leadTime: number
status: FeatureStatus status: FeatureStatus
step: number step: number
qualityIssue: number
} }