|
|
@@ -19,9 +19,9 @@ |
|
|
|
Zeitslots |
|
|
|
</v-tab> |
|
|
|
<v-tab |
|
|
|
href="#result" |
|
|
|
href="#ranking" |
|
|
|
> |
|
|
|
Ergebnisse |
|
|
|
Rangliste |
|
|
|
</v-tab> |
|
|
|
</v-tabs> |
|
|
|
<v-tabs-items |
|
|
@@ -37,7 +37,9 @@ |
|
|
|
<v-card-title class="text-h3"> |
|
|
|
Geräte |
|
|
|
<v-spacer /> |
|
|
|
<v-menu> |
|
|
|
<v-menu |
|
|
|
v-if="!hasresults" |
|
|
|
> |
|
|
|
<template #activator="{on, attrs}"> |
|
|
|
<v-btn |
|
|
|
icon |
|
|
@@ -68,6 +70,7 @@ |
|
|
|
class="row row-dense" |
|
|
|
v-bind="dragOptions" |
|
|
|
@end="orderApparatus" |
|
|
|
:disabled="hasresults" |
|
|
|
> |
|
|
|
<v-col |
|
|
|
v-for="(a) in (Event || {}).apparatus" |
|
|
@@ -78,7 +81,10 @@ |
|
|
|
> |
|
|
|
<v-card> |
|
|
|
<v-card-title class="text-h4"> |
|
|
|
<v-icon class="handle mr-4">far fa-bars</v-icon> |
|
|
|
<v-icon |
|
|
|
v-if="!hasresults" |
|
|
|
class="handle mr-4" |
|
|
|
>far fa-bars</v-icon> |
|
|
|
{{ a.apparatus.name }} |
|
|
|
</v-card-title> |
|
|
|
<v-card-text> |
|
|
@@ -86,7 +92,9 @@ |
|
|
|
<p><b>Bonus: </b> {{ a.bonus | float2_0 }}</p> |
|
|
|
<p><b>Malus: </b> {{ a.malus | float2_0 }}</p> |
|
|
|
</v-card-text> |
|
|
|
<v-card-actions> |
|
|
|
<v-card-actions |
|
|
|
v-if="!hasresults" |
|
|
|
> |
|
|
|
<v-spacer /> |
|
|
|
<v-btn icon> |
|
|
|
<v-icon>far fa-pencil</v-icon> |
|
|
@@ -145,7 +153,7 @@ |
|
|
|
> |
|
|
|
<template #header.select> |
|
|
|
<v-checkbox |
|
|
|
@change="(v) => !v ? ts.selected = [] : ts.selected = timeslots.map(t => t._id)" |
|
|
|
@change="(v) => !v ? ts.selected = [] : ts.selected = timeslots.filter(t => !t.team).map(t => t._id)" |
|
|
|
/> |
|
|
|
</template> |
|
|
|
<template #item.select="{item}"> |
|
|
@@ -180,6 +188,20 @@ |
|
|
|
@input="(v) => addTeam(item._id, v)" |
|
|
|
/> |
|
|
|
</template> |
|
|
|
<template #item.result="{item}"> |
|
|
|
<v-btn |
|
|
|
v-if="item.team" |
|
|
|
text |
|
|
|
x-small |
|
|
|
style="float: left;" |
|
|
|
@click="resultopen(item._id)" |
|
|
|
> |
|
|
|
<v-icon small> |
|
|
|
far fa-play |
|
|
|
</v-icon> |
|
|
|
</v-btn> |
|
|
|
{{ item.result ? item.result.calctime + 's' : '' }} |
|
|
|
</template> |
|
|
|
</v-data-table> |
|
|
|
</v-card> |
|
|
|
<base-material-dialog |
|
|
@@ -300,11 +322,155 @@ |
|
|
|
</template> |
|
|
|
</v-data-table> |
|
|
|
</base-material-dialog> |
|
|
|
<base-material-dialog |
|
|
|
v-model="result.open" |
|
|
|
title="Ergebnis eingeben" |
|
|
|
color="rgb(255, 4, 29)" |
|
|
|
:actions="['save','cancel']" |
|
|
|
@save="saveresult" |
|
|
|
@close="resultclose" |
|
|
|
@esc="resultclose" |
|
|
|
> |
|
|
|
<v-row |
|
|
|
class="mt-4" |
|
|
|
> |
|
|
|
<v-col |
|
|
|
cols="12" |
|
|
|
class="mb-6" |
|
|
|
> |
|
|
|
<base-material-card |
|
|
|
title="Zeitmessung" |
|
|
|
color="rgb(150,150,150)" |
|
|
|
> |
|
|
|
<v-row> |
|
|
|
<v-col |
|
|
|
cols="12" |
|
|
|
md="4" |
|
|
|
> |
|
|
|
<v-text-field |
|
|
|
readonly |
|
|
|
:value="result.time | float2_0" |
|
|
|
label="gemessene Zeit" |
|
|
|
class="zeitmessung" |
|
|
|
/> |
|
|
|
</v-col> |
|
|
|
<v-col |
|
|
|
cols="12" |
|
|
|
md="4" |
|
|
|
> |
|
|
|
<v-text-field |
|
|
|
readonly |
|
|
|
:value="`${bonusmalus}s`" |
|
|
|
:label="bonusmalus <= 0 ? 'Bonus' : 'Malus'" |
|
|
|
class="zeitmessung" |
|
|
|
/> |
|
|
|
</v-col> |
|
|
|
<v-col |
|
|
|
cols="12" |
|
|
|
md="4" |
|
|
|
> |
|
|
|
<v-text-field |
|
|
|
readonly |
|
|
|
:value="result.time + bonusmalus | float2_0" |
|
|
|
label="berechnete Zeit" |
|
|
|
class="zeitmessung" |
|
|
|
/> |
|
|
|
</v-col> |
|
|
|
<v-col |
|
|
|
cols="6" |
|
|
|
md="3" |
|
|
|
order-md="0" |
|
|
|
> |
|
|
|
<v-btn |
|
|
|
block |
|
|
|
@click="start(5)" |
|
|
|
> |
|
|
|
5s Countdown |
|
|
|
</v-btn> |
|
|
|
</v-col> |
|
|
|
<v-col |
|
|
|
cols="6" |
|
|
|
md="3" |
|
|
|
order-md="4" |
|
|
|
> |
|
|
|
<v-btn |
|
|
|
block |
|
|
|
@click="reset()" |
|
|
|
> |
|
|
|
Reset |
|
|
|
</v-btn> |
|
|
|
</v-col> |
|
|
|
<v-col |
|
|
|
cols="6" |
|
|
|
md="3" |
|
|
|
order-md="1" |
|
|
|
> |
|
|
|
<v-btn |
|
|
|
block |
|
|
|
color="green" |
|
|
|
@click="start(0)" |
|
|
|
> |
|
|
|
Start |
|
|
|
</v-btn> |
|
|
|
</v-col> |
|
|
|
<v-col |
|
|
|
cols="6" |
|
|
|
md="3" |
|
|
|
order-md="2" |
|
|
|
> |
|
|
|
<v-btn |
|
|
|
block |
|
|
|
color="primary" |
|
|
|
@click="stop()" |
|
|
|
> |
|
|
|
Stop |
|
|
|
</v-btn> |
|
|
|
</v-col> |
|
|
|
</v-row> |
|
|
|
</base-material-card> |
|
|
|
</v-col> |
|
|
|
<v-col |
|
|
|
v-for="(g, i) in apparatus" |
|
|
|
:key="g._apparatus" |
|
|
|
cols="12" |
|
|
|
sm="6" |
|
|
|
md="3" |
|
|
|
> |
|
|
|
<base-material-card |
|
|
|
:title="g.apparatus.name" |
|
|
|
color="rgb(150,150,150)" |
|
|
|
> |
|
|
|
<v-checkbox |
|
|
|
v-model="results(g._apparatus).teile" |
|
|
|
:label="`Teile OK? (max ${g.elements}, Malus +${g.malus}s)`" |
|
|
|
/> |
|
|
|
<v-checkbox |
|
|
|
v-model="results(g._apparatus).bonus" |
|
|
|
:label="`Bonus? (Bonus -${g.bonus}s)`" |
|
|
|
/> |
|
|
|
<v-checkbox |
|
|
|
v-if="i !== apparatus.length -1" |
|
|
|
v-model="results(g._apparatus).wechsel" |
|
|
|
:label="`Wechsel OK? (Malus +${g.malus}s)`" |
|
|
|
/> |
|
|
|
</base-material-card> |
|
|
|
</v-col> |
|
|
|
</v-row> |
|
|
|
</base-material-dialog> |
|
|
|
</v-tab-item> |
|
|
|
<v-tab-item |
|
|
|
value="result" |
|
|
|
value="ranking" |
|
|
|
> |
|
|
|
Ergebnisse |
|
|
|
<v-data-table |
|
|
|
:headers="ergebnis.headers" |
|
|
|
:items="ergebnisse" |
|
|
|
sort-by="time" |
|
|
|
:items-per-page="-1" |
|
|
|
> |
|
|
|
<template #item.time="{item}"> |
|
|
|
{{ item.time | float2_0 }}s |
|
|
|
</template> |
|
|
|
</v-data-table> |
|
|
|
</v-tab-item> |
|
|
|
</v-tabs-items> |
|
|
|
</v-container> |
|
|
@@ -314,7 +480,8 @@ |
|
|
|
import gql from 'graphql-tag' |
|
|
|
import moment from 'moment' |
|
|
|
|
|
|
|
const query = '_id name date _organizer apparatus { _apparatus apparatus { name logo } elements bonus malus } timeslots { _id time duration team { _id name } }' |
|
|
|
const timeslotquery = '_id time duration team { _id name } result { bonus runtime calctime results { _id teile bonus wechsel } }' |
|
|
|
const query = `_id name date _organizer apparatus { _apparatus apparatus { name logo } elements bonus malus } timeslots { ${timeslotquery} }` |
|
|
|
|
|
|
|
export default { |
|
|
|
name: 'Event', |
|
|
@@ -329,7 +496,7 @@ export default { |
|
|
|
data: () => ({ |
|
|
|
Event: null, |
|
|
|
ApparatusFind: [], |
|
|
|
tab: 'timeslot', |
|
|
|
tab: 0, |
|
|
|
ts: { |
|
|
|
headers: [ |
|
|
|
{ |
|
|
@@ -381,6 +548,35 @@ export default { |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
}, |
|
|
|
result: { |
|
|
|
open: false, |
|
|
|
id: null, |
|
|
|
results: [], |
|
|
|
start: null, |
|
|
|
stop: null, |
|
|
|
time: null, |
|
|
|
running: false, |
|
|
|
interval: null |
|
|
|
}, |
|
|
|
ergebnis: { |
|
|
|
headers: [ |
|
|
|
{ |
|
|
|
text: 'Platz', |
|
|
|
value: 'platz', |
|
|
|
sortable: false |
|
|
|
}, |
|
|
|
{ |
|
|
|
text: 'Mannschaft', |
|
|
|
value: 'team', |
|
|
|
sortable: false |
|
|
|
}, |
|
|
|
{ |
|
|
|
text: 'Zeit', |
|
|
|
value: 'time', |
|
|
|
sortable: false |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
}), |
|
|
|
|
|
|
@@ -395,6 +591,9 @@ export default { |
|
|
|
geraete () { |
|
|
|
return this.ApparatusFind?.slice()?.sort((a, b) => a.name < b.name ? -1 : 1)?.filter(g => !this.Event?.apparatus.find(a => a._apparatus === g._id)) || [] |
|
|
|
}, |
|
|
|
apparatus () { |
|
|
|
return this.Event?.apparatus || [] |
|
|
|
}, |
|
|
|
timeslots () { |
|
|
|
return this.Event?.timeslots || [] |
|
|
|
}, |
|
|
@@ -408,6 +607,33 @@ export default { |
|
|
|
} |
|
|
|
|
|
|
|
return neu.filter(n => !this.timeslots.find(o => o.time === n && o.duration === parseInt(this.ts.dialog.duration))).map(t => ({ time: t, duration: this.ts.dialog.duration })) |
|
|
|
}, |
|
|
|
bonus () { |
|
|
|
return this.apparatus.reduce((acc, curr) => { |
|
|
|
if (this.results(curr._apparatus).bonus) acc += parseInt(curr.bonus) |
|
|
|
return acc |
|
|
|
}, 0) |
|
|
|
}, |
|
|
|
malus () { |
|
|
|
return this.apparatus.reduce((acc, curr, i, arr) => { |
|
|
|
if (!this.results(curr._apparatus).teile) acc += parseInt(curr.malus) |
|
|
|
if (i !== arr.length - 1 && !this.results(curr._apparatus).wechsel) acc += parseInt(curr.malus) |
|
|
|
return acc |
|
|
|
}, 0) |
|
|
|
}, |
|
|
|
bonusmalus () { |
|
|
|
return this.malus - this.bonus |
|
|
|
}, |
|
|
|
hasresults () { |
|
|
|
return !!this.Event?.timeslots?.find(t => !!t.result) |
|
|
|
}, |
|
|
|
ergebnisse () { |
|
|
|
return this.Event?.timeslots?.reduce((acc, curr) => { |
|
|
|
if (curr.team && curr.result) { |
|
|
|
acc.push({ team: curr.team.name, time: curr.result.calctime }) |
|
|
|
} |
|
|
|
return acc |
|
|
|
}, []).sort((a, b) => a.time < b.time ? -1 : 1).map((m, i) => ({ ...m, platz: i + 1 })) |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
@@ -454,7 +680,7 @@ export default { |
|
|
|
}) |
|
|
|
}, |
|
|
|
addTimeslots () { |
|
|
|
if (this.timeslots.length > 0) { |
|
|
|
if (this.newtimeslots.length > 0) { |
|
|
|
this.$apollo.mutate({ |
|
|
|
mutation: gql`mutation($id: UUID!, $timeslots: [ITimeslot!]!) { |
|
|
|
EventAddTimeslots(id: $id, timeslots: $timeslots) { ${query} } |
|
|
@@ -503,7 +729,7 @@ export default { |
|
|
|
}) |
|
|
|
}, |
|
|
|
async deleteTeam (timeslot) { |
|
|
|
if (!this.timeslots.find(t => t._id === timeslot)?.team?.ergebnis || await this.$root.$children[0].$refs.confirm.open('Löschen', 'Bei diesem Team sind bereits Ergebnisse hinterlegt, wirklich löschen?')) { |
|
|
|
if (!this.timeslots.find(t => t._id === timeslot)?.result || await this.$root.$children[0].$refs.confirm.open('Löschen', 'Bei diesem Team sind bereits Ergebnisse hinterlegt, wirklich löschen?')) { |
|
|
|
this.$apollo.mutate({ |
|
|
|
mutation: gql`mutation($id: UUID!, $timeslot: UUID!) { |
|
|
|
EventDeleteTeam(id: $id, timeslot: $timeslot) { ${query} } |
|
|
@@ -517,6 +743,87 @@ export default { |
|
|
|
this.ts.selected = [] |
|
|
|
}) |
|
|
|
} |
|
|
|
}, |
|
|
|
resultopen (timeslot) { |
|
|
|
const result = this.Event?.timeslots?.find(t => t._id === timeslot)?.result |
|
|
|
const results = result?.results |
|
|
|
|
|
|
|
this.result.time = result?.runtime |
|
|
|
|
|
|
|
this.result.open = true |
|
|
|
this.result.id = timeslot |
|
|
|
this.result.results = this.apparatus.map((a, i, arr) => { |
|
|
|
const data = results?.find(r => r._id === a._apparatus) |
|
|
|
|
|
|
|
const ret = { |
|
|
|
_id: a._apparatus, |
|
|
|
teile: data?.teile !== undefined ? data.teile : true, |
|
|
|
bonus: data?.bonus !== undefined ? data.bonus : false |
|
|
|
} |
|
|
|
if (i !== arr.length - 1) { |
|
|
|
ret.wechsel = data?.wechsel !== undefined ? data.wechsel : true |
|
|
|
} |
|
|
|
return ret |
|
|
|
}) |
|
|
|
}, |
|
|
|
resultclose () { |
|
|
|
this.result.open = false |
|
|
|
this.result.id = null |
|
|
|
this.result.results = [] |
|
|
|
this.reset() |
|
|
|
}, |
|
|
|
results (apparatus) { |
|
|
|
return this.result?.results?.find(a => a._id === apparatus) || {} |
|
|
|
}, |
|
|
|
start (countdown) { |
|
|
|
if (this.result.running) return |
|
|
|
|
|
|
|
this.result.start = Date.now() + (countdown || 0) * 1000 |
|
|
|
this.result.running = true |
|
|
|
this.result.interval = setInterval(() => { |
|
|
|
this.result.time = (Date.now() - this.result.start) / 1000 |
|
|
|
}, 10) |
|
|
|
}, |
|
|
|
stop () { |
|
|
|
this.result.stop = Date.now() |
|
|
|
this.result.running = false |
|
|
|
if (this.result.interval !== null) { |
|
|
|
clearInterval(this.result.interval) |
|
|
|
this.result.interval = null |
|
|
|
} |
|
|
|
}, |
|
|
|
reset () { |
|
|
|
this.result.start = null |
|
|
|
this.result.stop = null |
|
|
|
this.result.time = null |
|
|
|
this.result.running = false |
|
|
|
if (this.result.interval !== null) { |
|
|
|
clearInterval(this.result.interval) |
|
|
|
this.result.interval = null |
|
|
|
} |
|
|
|
}, |
|
|
|
saveresult () { |
|
|
|
const variables = { |
|
|
|
id: this.id, |
|
|
|
timeslot: this.result.id, |
|
|
|
result: { |
|
|
|
runtime: Math.round((this.result.time) * 100) / 100, |
|
|
|
bonus: this.bonusmalus, |
|
|
|
calctime: Math.round((this.result.time + this.bonusmalus) * 100) / 100, |
|
|
|
results: this.result.results |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
this.$apollo.mutate({ |
|
|
|
mutation: gql`mutation($id: UUID!, $timeslot: UUID!, $result: IResult!) { |
|
|
|
EventSetResult(id: $id, timeslot: $timeslot, result: $result) { ${timeslotquery} } |
|
|
|
}`, |
|
|
|
variables |
|
|
|
}).then(() => { |
|
|
|
this.ts.selected = [] |
|
|
|
}) |
|
|
|
|
|
|
|
this.resultclose() |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
@@ -556,4 +863,11 @@ export default { |
|
|
|
content: ''; |
|
|
|
clear: both; |
|
|
|
} |
|
|
|
|
|
|
|
.v-text-field.zeitmessung >>> input { |
|
|
|
font-size: 3em !important; |
|
|
|
font-weight: bold !important; |
|
|
|
max-height: none; |
|
|
|
} |
|
|
|
|
|
|
|
</style> |