-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
159 lines (138 loc) · 5.54 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<html>
<head>
<link
rel="stylesheet"
media="(prefers-color-scheme:light)"
href="https://cdn.jsdelivr.net/npm/@shoelace-style/[email protected]/cdn/themes/light.css"
/>
<link
rel="stylesheet"
media="(prefers-color-scheme:dark)"
href="https://cdn.jsdelivr.net/npm/@shoelace-style/[email protected]/cdn/themes/dark.css"
onload="document.documentElement.classList.add('sl-theme-dark');"
/>
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/[email protected]/cdn/shoelace-autoloader.js"></script>
</head>
<body>
<div class="title">
<h1>Dry Fire</h1>
</div>
<div class="description">
<p>Test reaction speed with just a phone or computer. This page will beep randomly within the parameters provided below. When it beeps, react. The par beep shows if the reaction was fast enough.</p>
<p>Timer will wait a random amount of time between min and max, then beep. After par seconds, it will beep again and start a new timer</p>
</div>
<div class="settings">
<sl-card class="card-header">
<sl-input type="number" id="min" label="Min Standby (sec)" help-text="The minimum pause between the par beep and the start beep" value="120"></sl-input>
<sl-input type="number" id="max" label="Max Standby (sec)" help-text="The maximum pause between the par beep and the start beep" value="600"></sl-input>
<sl-input type="number" id="par" label="Par (sec)" help-text="The pause between the start beep and the par beep" value="1.5"></sl-input>
<div slot="footer">
<sl-button id="start" variant="primary" onclick="handleStart()">Start</sl-button>
<sl-button id="stop" variant="normal" onclick="handleStop()" disabled>Stop</sl-button>
</div>
</sl-card>
</div>
<div class="footer" style="color: var(--sl-color-neutral-300)">
<p>Made with <sl-animation name="heartBeat" duration="99999" play><sl-icon style="font-size: 10px; color: #e25555;" name="suit-heart-fill"></sl-icon></sl-animation> by NonlinearFruit (<a href="https://github.com/NonlinearFruit/dry-fire">source</a>)</p>
</div>
<style>
body {
display: grid;
grid-template-columns: 1fr auto 1fr;
grid-template-rows: 1fr auto auto auto 2fr;
justify-items: center;
}
.title {
grid-column: 2 / 3;
grid-row: 2 / 3;
}
.description {
grid-column: 2 / 3;
grid-row: 3 / 4;
width:0;
min-width:100%;
}
.settings {
grid-column: 2 / 3;
grid-row: 4 / 5;
}
.footer {
grid-column: 2 / 3;
grid-row: 5 / 6;
}
</style>
<script>
var audioCtx = new (window.AudioContext || window.webkitAudioContext || window.audioContext);
var isRunning = false;
var isDebug = true;
function goSignal() {
log("go signal about to beep");
beep(115, 500, 0.5);
}
function parBeep() {
log("par about to beep");
beep(115, 1000, 0.5);
}
function getRandomNumber(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
function handleStart() {
const start = document.getElementById("start");
const stop = document.getElementById("stop");
start.toggleAttribute("disabled");
stop.toggleAttribute("disabled");
isRunning = true;
runCycle();
}
function handleStop() {
const start = document.getElementById("start");
const stop = document.getElementById("stop");
start.toggleAttribute("disabled");
stop.toggleAttribute("disabled");
isRunning = false;
}
function runCycle() {
log("Running another cycle");
const min = Number(document.getElementById("min").value);
const max = Number(document.getElementById("max").value);
const par = Number(document.getElementById("par").value);
const delay = getRandomNumber(min*1000, max*1000)
log(" Min: "+min);
log(" Max: "+max);
log(" Par: "+par);
log(" Delay: "+delay);
setTimeout(async () => {
goSignal();
await new Promise(r => setTimeout(r, par*1000));
parBeep();
if (isRunning) runCycle();
}, delay);
log(" isRunning: "+isRunning);
}
function log(msg) {
if (isDebug) {
console.log(msg);
}
}
// https://stackoverflow.com/a/29641185
// All arguments are optional:
// duration of the tone in milliseconds. Default is 500
// frequency of the tone in hertz. default is 440
// volume of the tone. Default is 1, off is 0.
// type of tone. Possible values are sine, square, sawtooth, triangle, and custom. Default is sine.
// callback to use on end of tone
function beep(duration, frequency, volume, type, callback) {
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
if (volume){gainNode.gain.value = volume;}
if (frequency){oscillator.frequency.value = frequency;}
if (type){oscillator.type = type;}
if (callback){oscillator.onended = callback;}
oscillator.start(audioCtx.currentTime);
oscillator.stop(audioCtx.currentTime + ((duration || 500) / 1000));
};
</script>
</body>
</html>