diff --git a/index.css b/index.css
new file mode 100644
index 0000000..55b1bfb
--- /dev/null
+++ b/index.css
@@ -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;
+}
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..1fde5e4
--- /dev/null
+++ b/index.html
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ OK! .. READY! ... GO!
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/js/index.js b/js/index.js
new file mode 100644
index 0000000..78bd920
--- /dev/null
+++ b/js/index.js
@@ -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
+ },
+ })
+
+
+
+})
\ No newline at end of file
diff --git a/sound/0.mp3 b/sound/0.mp3
new file mode 100644
index 0000000..7d1455e
Binary files /dev/null and b/sound/0.mp3 differ
diff --git a/sound/1.mp3 b/sound/1.mp3
new file mode 100644
index 0000000..b174a74
Binary files /dev/null and b/sound/1.mp3 differ
diff --git a/sound/2.mp3 b/sound/2.mp3
new file mode 100644
index 0000000..812a778
Binary files /dev/null and b/sound/2.mp3 differ
diff --git a/sound/3.mp3 b/sound/3.mp3
new file mode 100644
index 0000000..5818736
Binary files /dev/null and b/sound/3.mp3 differ
diff --git a/sound/4.mp3 b/sound/4.mp3
new file mode 100644
index 0000000..7ced6a4
Binary files /dev/null and b/sound/4.mp3 differ
diff --git a/sound/5.mp3 b/sound/5.mp3
new file mode 100644
index 0000000..4cf80ec
Binary files /dev/null and b/sound/5.mp3 differ
diff --git a/sound/6.mp3 b/sound/6.mp3
new file mode 100644
index 0000000..1f3005a
Binary files /dev/null and b/sound/6.mp3 differ
diff --git a/sound/7.mp3 b/sound/7.mp3
new file mode 100644
index 0000000..60c01b0
Binary files /dev/null and b/sound/7.mp3 differ
diff --git a/sound/8.mp3 b/sound/8.mp3
new file mode 100644
index 0000000..5a1c53b
Binary files /dev/null and b/sound/8.mp3 differ
diff --git a/sound/9.mp3 b/sound/9.mp3
new file mode 100644
index 0000000..320079e
Binary files /dev/null and b/sound/9.mp3 differ
diff --git a/sound/ok-ready-go.mp3 b/sound/ok-ready-go.mp3
new file mode 100644
index 0000000..5e08287
Binary files /dev/null and b/sound/ok-ready-go.mp3 differ
diff --git a/sound/silence.mp3 b/sound/silence.mp3
new file mode 100644
index 0000000..16de7c3
Binary files /dev/null and b/sound/silence.mp3 differ