Feat: initial proof of concept

This commit is contained in:
Dorian Zedler 2023-02-07 13:44:57 +01:00
parent 1414e378aa
commit 608f6b9590
Signed by: dorian
GPG key ID: 989DE36109AFA354
15 changed files with 184 additions and 0 deletions

28
index.css Normal file
View file

@ -0,0 +1,28 @@
@keyframes blinker {
50% {
opacity: 0.3;
}
}
.timer {
font-size: 8em;
font-weight: bold;
text-align: center;
line-height: 1.2;
}
.timer.over {
color: #0f0;
animation: blinker 2s ease infinite;
}
main {
height: 100vh;
}
main > div {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}

48
index.html Normal file
View file

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script src="https://unpkg.com/crypto-js@4.1.1/crypto-js.js"></script>
<script src="js/index.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css" />
<link rel="stylesheet" href="index.css" />
<audio id="sound-0" src="sound/0.mp3" preload="auto"></audio>
<audio id="sound-1" src="sound/1.mp3" preload="auto"></audio>
<audio id="sound-2" src="sound/2.mp3" preload="auto"></audio>
<audio id="sound-3" src="sound/3.mp3" preload="auto"></audio>
<audio id="sound-4" src="sound/4.mp3" preload="auto"></audio>
<audio id="sound-5" src="sound/5.mp3" preload="auto"></audio>
<audio id="sound-6" src="sound/6.mp3" preload="auto"></audio>
<audio id="sound-7" src="sound/7.mp3" preload="auto"></audio>
<audio id="sound-8" src="sound/8.mp3" preload="auto"></audio>
<audio id="sound-9" src="sound/9.mp3" preload="auto"></audio>
<audio id="sound-ok-ready-go" src="sound/ok-ready-go.mp3" preload="auto"></audio>
<audio id="sound-silence" src="sound/silence.mp3" preload="auto"></audio>
</head>
<body>
<main class="container">
<div x-data>
<div @click="$store.localState.next()">
<hgroup>
<h1>OK! .. READY! ... GO!</h1>
<h2 x-text="$store.localState.stateHint"></h2>
</hgroup>
<div x-data="Timer">
<p :class="'timer' + (over ? ' over':'')"
x-text="time + 's'"></p>
</div>
</div>
</div>
</main>
</body>

108
js/index.js Normal file
View file

@ -0,0 +1,108 @@
async function play() {
const number = document.getElementById("number").value;
sayNumber(number);
}
async function sayNumber(number) {
console.log(number)
number = number.toString();
number = number.replace(/[^0-9]/, "");
for(let i = 0; i < number.length; i++) {
await playAudio(document.getElementById(`sound-${number[i]}`));
}
}
function playAudio(audio){
return new Promise(res=>{
audio.play()
audio.onended = res
})
}
function Timer() {
return {
time: 0,
over: false,
init() {
setInterval(() => {
const startedAt = Alpine.store("localState").startedAt;
const resultTime = Alpine.store("localState").time;
let time;
if (!startedAt && !resultTime) {
time = 0;
this.over = false;
} else if (resultTime) {
time = (resultTime / 1000);
this.over = true;
} else {
this.over = false;
time =
((new Date().getTime() - startedAt) / 1000)
;
}
this.time = time.toFixed(2)
}, 10);
},
};
}
document.addEventListener("alpine:init", () => {
Alpine.store("localState", {
_state: 0,
// 0: idle
// 1: starting
// 2: running
// 3: stopped
startedAt: null,
time: null,
stateHint: "",
init() {
Alpine.effect(() => {
switch(this._state) {
case 0: {
this.startedAt = null;
this.time = null;
this.stateHint = "Tap to start";
break;
}
case 1: {
this.stateHint = "Get ready..."
playAudio(document.getElementById("sound-ok-ready-go")).then(() => {
Alpine.store("localState")._state = 2;
});
break;
}
case 2: {
this.stateHint = "Tap to stop"
this.startedAt = new Date().getTime() - 200;
break;
}
case 3: {
this.stateHint = "Tap to reset"
this.time = new Date().getTime() - this.startedAt;
sayNumber((this.time / 1000).toFixed(2));
this.startedAt = null;
break;
}
}
})
},
next() {
console.log("next");
playAudio(document.getElementById("sound-silence"))
if(this._state == 1) return;
this._state = (this._state + 1) % 4
},
})
})

BIN
sound/0.mp3 Normal file

Binary file not shown.

BIN
sound/1.mp3 Normal file

Binary file not shown.

BIN
sound/2.mp3 Normal file

Binary file not shown.

BIN
sound/3.mp3 Normal file

Binary file not shown.

BIN
sound/4.mp3 Normal file

Binary file not shown.

BIN
sound/5.mp3 Normal file

Binary file not shown.

BIN
sound/6.mp3 Normal file

Binary file not shown.

BIN
sound/7.mp3 Normal file

Binary file not shown.

BIN
sound/8.mp3 Normal file

Binary file not shown.

BIN
sound/9.mp3 Normal file

Binary file not shown.

BIN
sound/ok-ready-go.mp3 Normal file

Binary file not shown.

BIN
sound/silence.mp3 Normal file

Binary file not shown.