430 lines
10 KiB
Svelte
430 lines
10 KiB
Svelte
<script>
|
|
import { onMount } from 'svelte';
|
|
import { colors } from '$lib/stores/colors.js';
|
|
import { rounds } from '$lib/stores/rounds.js';
|
|
import { categories } from '$lib/stores/categories.js';
|
|
import { dev } from '$app/environment';
|
|
import { createPriority, surfer } from '$lib/priority.js';
|
|
|
|
window.document.body.oncontextmenu = function () {
|
|
return false;
|
|
};
|
|
|
|
$: start = false;
|
|
|
|
let next_priority;
|
|
|
|
let priority = createPriority();
|
|
|
|
$: priority;
|
|
|
|
console.log(`surfers: ${JSON.stringify(priority.surfers)}`);
|
|
|
|
let footer_height = 8;
|
|
let setup_height = (100 - footer_height) / priority.surfersCount - 2.2 / priority.surfersCount;
|
|
|
|
// $: if ($priority.surfers) {
|
|
// SaveToLocalCahe();
|
|
// }
|
|
|
|
onMount(async () => {
|
|
LoadFromLocalCache();
|
|
console.log(`onMount: ${JSON.stringify(priority)}`);
|
|
});
|
|
|
|
function hasDuplicateColors() {
|
|
const colors = [];
|
|
|
|
console.log(JSON.stringify(priority.surfers));
|
|
|
|
for (let i = 0; i < priority.surfersCount; i++) {
|
|
const color = priority.surfers[i].color;
|
|
|
|
if (colors.includes(color)) {
|
|
console.log(`duplicate color: ${color}`);
|
|
return true;
|
|
}
|
|
|
|
colors.push(color);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function ResetPriority() {
|
|
for (let i = 0; i < priority.surfersCount; i++) {
|
|
priority.surfers[i].priority = '';
|
|
}
|
|
}
|
|
|
|
function StartHeat() {
|
|
if (hasDuplicateColors()) {
|
|
alert('Duplicate colors');
|
|
return;
|
|
}
|
|
ResetPriority();
|
|
start = true;
|
|
next_priority = 1;
|
|
SaveToLocalCahe();
|
|
SendPriority();
|
|
}
|
|
|
|
function StopHeat() {
|
|
ResetLocalCache();
|
|
start = false;
|
|
ResetPriority();
|
|
SendPriority();
|
|
}
|
|
|
|
function AddSurfer() {
|
|
if (priority.surfersCount < 6) {
|
|
priority.surfersCount += 1;
|
|
priority = createPriority(priority.surfersCount);
|
|
}
|
|
}
|
|
|
|
function RemSurfer() {
|
|
if (priority.surfersCount > 2) {
|
|
priority.surfersCount -= 1;
|
|
priority = createPriority(priority.surfersCount);
|
|
}
|
|
}
|
|
|
|
function ResetLocalCache() {
|
|
console.log('ResetLocalCache');
|
|
window.sessionStorage.clear();
|
|
priority = createPriority();
|
|
console.log(`reset store: ${JSON.stringify(priority)}`);
|
|
}
|
|
|
|
function SaveToLocalCahe() {
|
|
window.sessionStorage.setItem('priority', JSON.stringify(priority));
|
|
window.sessionStorage.setItem('start', JSON.stringify(start));
|
|
console.log(`update cache: ${JSON.stringify(priority)}`);
|
|
}
|
|
|
|
function LoadFromLocalCache() {
|
|
let pri = window.sessionStorage.getItem('priority');
|
|
if (pri) {
|
|
console.log(`load cache: ${pri}`);
|
|
priority = JSON.parse(pri);
|
|
start = JSON.parse(window.sessionStorage.getItem('start'));
|
|
console.log(`loaded cache: ${JSON.stringify(priority)} - ${start}`);
|
|
} else {
|
|
console.log(`no cache found`);
|
|
}
|
|
}
|
|
|
|
async function SendPriority() {
|
|
if (dev) {
|
|
return;
|
|
}
|
|
const res = await fetch(`/api/priority`, {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
surfers: priority.surfers,
|
|
round: priority.round,
|
|
surfersCount: priority.surfersCount
|
|
}),
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
});
|
|
console.log(`SendPriority: ${JSON.stringify(priority)}`);
|
|
}
|
|
|
|
function NextPriority() {
|
|
let max = 0;
|
|
next_priority = 0;
|
|
for (let i = 0; i < priority.surfersCount; i++) {
|
|
let pri = parseInt(priority.surfers[i].priority);
|
|
console.log(`pos: [${i}] - pri: ${pri}`);
|
|
if (pri > max) {
|
|
max = pri;
|
|
console.log(`max: ${max}`);
|
|
}
|
|
}
|
|
next_priority = max + 1;
|
|
if (next_priority > priority.surfersCount) {
|
|
next_priority = priority.surfersCount;
|
|
}
|
|
console.log(`next: ${next_priority} - max: ${max}`);
|
|
}
|
|
|
|
async function ChangePriority(id) {
|
|
console.log(priority.surfers[id]);
|
|
if (priority.surfers[id].priority === '1') {
|
|
next_priority = 1;
|
|
for (let i = 0; i < priority.surfersCount; i++) {
|
|
if (i != id) {
|
|
if (priority.surfers[i].priority === '') {
|
|
console.log(`empty: [${i}] ${priority.surfers[i].priority}`);
|
|
continue;
|
|
}
|
|
let pos = parseInt(priority.surfers[i].priority);
|
|
let newpos = pos - 1;
|
|
console.log(`oldpos: [${i}] ${priority.surfers[i].priority} - newpos: ${newpos}`);
|
|
priority.surfers[i].priority = newpos.toString();
|
|
}
|
|
}
|
|
priority.surfers[id].priority = '';
|
|
NextPriority();
|
|
} else if (priority.surfers[id].priority === '') {
|
|
console.log(`priority empty; pressed: [${id}] ${priority.surfers[id].priority}`);
|
|
priority.surfers[id].priority = next_priority.toString();
|
|
NextPriority();
|
|
} else {
|
|
console.log(`pressed: [${id}] ${priority.surfers[id].priority}`);
|
|
let oldpos = parseInt(priority.surfers[id].priority);
|
|
for (let i = 0; i < priority.surfersCount; i++) {
|
|
if (i != id) {
|
|
console.log(
|
|
`pos: [${i}] ${priority.surfers[i].priority} ${priority.surfers[i].priority > oldpos}`
|
|
);
|
|
let pos = parseInt(priority.surfers[i].priority);
|
|
if (pos > oldpos) {
|
|
console.log(`newpos: ${priority.surfers[i].priority}`);
|
|
priority.surfers[i].priority = (pos - 1).toString();
|
|
}
|
|
} else {
|
|
priority.surfers[i].priority = '';
|
|
console.log(`last: [${i}] ${priority.surfers[i].priority}`);
|
|
}
|
|
}
|
|
NextPriority();
|
|
}
|
|
|
|
SaveToLocalCahe();
|
|
SendPriority();
|
|
}
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<link
|
|
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
|
|
rel="stylesheet"
|
|
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
|
|
crossorigin="anonymous"
|
|
/>
|
|
<script
|
|
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
|
|
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
|
|
crossorigin="anonymous"
|
|
></script>
|
|
</svelte:head>
|
|
|
|
{#if start}
|
|
<div class="container-fluid text-center mb-1">
|
|
<div class="row bg-secondary p-1">
|
|
<div class="col align-items-center">
|
|
<button class="button" on:click={StopHeat}>STOP</button>
|
|
</div>
|
|
</div>
|
|
<!-- Next: {next_priority} -->
|
|
</div>
|
|
|
|
<ul>
|
|
{#each priority.surfers as surfer, id}
|
|
<li style="--height:{setup_height}vh">
|
|
{#if surfer.priority == '1'}
|
|
<div
|
|
class="priority"
|
|
id="p"
|
|
on:click={() => ChangePriority(id)}
|
|
on:keypress={() => ChangePriority(id)}
|
|
role="button"
|
|
tabindex="-1"
|
|
>
|
|
P
|
|
</div>
|
|
{:else}
|
|
<div
|
|
class="priority"
|
|
id="n"
|
|
on:click={() => ChangePriority(id)}
|
|
on:keypress={() => ChangePriority(id)}
|
|
role="button"
|
|
tabindex="-1"
|
|
>
|
|
{surfer.priority}
|
|
</div>
|
|
{/if}
|
|
<div class="color" style:background-color={surfer.color}>
|
|
{surfer.name}
|
|
</div>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
{:else}
|
|
<div class="container-fluid text-center mb-1">
|
|
<div class="row bg-secondary p-1">
|
|
<div class="col align-items-center">
|
|
<button class="btn btn-success btn-sm" on:click={StartHeat}>START</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- <div class="container-fluid text-center"></div> -->
|
|
|
|
<div class="container-fluid text-center">
|
|
<div class="row row-cols-auto justify-content-between align-content-center bg-light mb-1">
|
|
<div class="col align-self-center">
|
|
<div class="btn-toolbar btn-group-sm" role="toolbar">
|
|
<button class="btn btn-primary" on:click={AddSurfer}>+</button>
|
|
<button class="btn btn-outline-black disabled">{priority.surfersCount}</button>
|
|
<button class="btn btn-primary" on:click={RemSurfer}>-</button>
|
|
</div>
|
|
</div>
|
|
<div class="col align-self-center mt-1">
|
|
<div class="row row-cols-auto justify-content- align-content-center bg-light mb-1">
|
|
<div class="col align-self-center">
|
|
<div class="input-group">
|
|
<span class="input-group-text bg-info">Round</span>
|
|
<select
|
|
class="form-select form-select-sm"
|
|
name="round"
|
|
id="round"
|
|
bind:value={priority.round.name}
|
|
>
|
|
{#each $rounds as round}
|
|
<option value={round.title}>{round.name}</option>
|
|
{/each}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col align-self-center">
|
|
<div class="input-group">
|
|
<span class="input-group-text bg-info">Category</span>
|
|
<select
|
|
class="form-select form-select-sm"
|
|
name="cetegory"
|
|
id="category"
|
|
bind:value={priority.round.category}
|
|
>
|
|
{#each $categories as category}
|
|
<option value={category.title}>{category.name}</option>
|
|
{/each}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col align-self-center">
|
|
<div class="input-group">
|
|
<span class="input-group-text bg-info">Heat</span>
|
|
<input
|
|
type="number"
|
|
class="form-control"
|
|
min="1"
|
|
max="999"
|
|
size="3"
|
|
bind:value={priority.round.heat}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div class="col align-self-center">
|
|
<div class="input-group">
|
|
<span class="input-group-text bg-info">Timer</span>
|
|
<input
|
|
type="number"
|
|
class="form-control"
|
|
min="0"
|
|
max="60"
|
|
size="3"
|
|
bind:value={priority.round.time}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col align-self-center">
|
|
<button class="btn btn-danger btn-sm" on:click={ResetLocalCache}>Reset</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<table class="table table-striped table-borderless table-sm">
|
|
<thead>
|
|
<tr class="table-primary">
|
|
<td> Name </td>
|
|
<td> Color </td>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="table-group-divider">
|
|
{#each priority.surfers as surfer, id (surfer.id)}
|
|
<tr class="table-light">
|
|
<td><input class="input" type="text" size="30" bind:value={surfer.name} /></td>
|
|
<td>
|
|
<div class="select">
|
|
<select
|
|
name="color{id}"
|
|
{id}
|
|
bind:value={surfer.color}
|
|
style="background-color: {surfer.color};"
|
|
>
|
|
{#each $colors as color}
|
|
<option value={color} style="background-color: {color}">{color}</option>
|
|
{/each}
|
|
</select>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{:else}
|
|
<tr>
|
|
<th />
|
|
<td />
|
|
</tr>
|
|
{/each}
|
|
</tbody>
|
|
</table>
|
|
{/if}
|
|
|
|
<style>
|
|
:global(body) {
|
|
/* overflow-y: hidden; */
|
|
overflow-x: hidden;
|
|
margin: 0.2vmin;
|
|
align-content: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
ul {
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
li {
|
|
display: flex;
|
|
flex-direction: row;
|
|
margin-top: 0.2vh;
|
|
margin-bottom: 0.2vh;
|
|
overflow: hidden;
|
|
height: var(--height);
|
|
}
|
|
|
|
.priority {
|
|
text-align: center;
|
|
align-self: center;
|
|
min-height: var(--height);
|
|
min-width: var(--height);
|
|
margin-right: 0.2vw;
|
|
background-color: gray;
|
|
}
|
|
|
|
.priority#p {
|
|
font-size: 16vmin;
|
|
background-color: lightgray;
|
|
height: 100%;
|
|
}
|
|
|
|
.priority#n {
|
|
font-size: 14vmin;
|
|
height: 100%;
|
|
}
|
|
|
|
.color {
|
|
display: flex;
|
|
width: 100vw;
|
|
justify-content: center;
|
|
align-items: center;
|
|
text-align: center;
|
|
}
|
|
</style>
|