Commit | Line | Data |
---|---|---|
72b294bb | 1 | "use strict"; |
2 | ||
3 | function Timer(id) { | |
4 | var precision = 100; // milliseconds | |
5 | var defaultTime = (15 * 60 + 0) * 1000; // milliseconds | |
6 | var time = defaultTime; | |
7 | var intervalID; | |
8 | this.isTicking = false; | |
9 | var outputTime = function() { | |
10 | document.getElementById(id).innerHTML = timeToTimeStr(time); | |
11 | var flagid = "flag-" + id.split('-')[1]; | |
12 | var flagelem = document.getElementById(flagid); | |
13 | flagelem.style.visibility = time <= 0 ? "visible" : "hidden"; | |
14 | }; | |
6f474901 AIL |
15 | |
16 | var startTickingUnixTime = null; | |
17 | var remainingTimeAtTickingStart = null; | |
18 | ||
72b294bb | 19 | var thisTimer = this; // workaround to use this in setInterval |
20 | this.tick = function() { | |
6f474901 AIL |
21 | var currentPassedTime = new Date() - startTickingUnixTime; |
22 | time = remainingTimeAtTickingStart - currentPassedTime; | |
72b294bb | 23 | if(time <= 0) { |
6f474901 | 24 | time = 0; |
72b294bb | 25 | // time's up |
26 | clearInterval(intervalID); | |
27 | thisTimer.isTicking = false; | |
28 | } | |
29 | outputTime(); | |
30 | }; | |
31 | this.start = function() { | |
6f474901 AIL |
32 | startTickingUnixTime = new Date(); |
33 | remainingTimeAtTickingStart = time; | |
72b294bb | 34 | intervalID = setInterval(this.tick, precision); |
35 | this.isTicking = true; | |
36 | }; | |
37 | this.stop = function() { | |
38 | clearInterval(intervalID); | |
39 | this.isTicking = false; | |
40 | }; | |
41 | this.setTime = function(t) { | |
42 | time = t; | |
43 | defaultTime = t; | |
44 | outputTime(); | |
45 | }; | |
46 | this.getTime = function() { | |
47 | return time; | |
48 | }; | |
49 | this.reset = function() { | |
50 | if(this.isTicking) { | |
51 | this.stop(); | |
52 | } | |
53 | this.setTime(defaultTime); | |
54 | }; | |
55 | this.getDefaultTime = function() { | |
56 | return defaultTime; | |
57 | }; | |
58 | } | |
59 | ||
60 | var currentTimers = new (function() { | |
61 | this.leftTimer = new Timer("timer-left"); | |
62 | this.rightTimer = new Timer("timer-right"); | |
63 | this.active = this.leftTimer; | |
64 | this.passive = this.rightTimer; | |
65 | this.isPaused = true; | |
66 | this.swap = function() { | |
67 | var tmp = this.passive; | |
68 | this.passive = this.active; | |
69 | this.active = tmp; | |
70 | var icon = document.getElementById("play"); | |
71 | icon.innerHTML = (icon.innerHTML == "◀" ? "▶" : "◀"); | |
72 | }; | |
73 | this.pause = function() { | |
74 | this.active.stop(); | |
75 | this.isPaused = true; | |
76 | document.getElementById("pause").style.visibility = "visible"; | |
77 | }; | |
78 | this.resume = function() { | |
79 | this.active.start(); | |
80 | this.isPaused = false; | |
81 | document.getElementById("pause").style.visibility = "hidden"; | |
82 | }; | |
83 | })(); | |
84 | ||
85 | function timeStrToTime(timeStr) { | |
86 | var minute = parseInt(timeStr.substr(0, 2)); | |
87 | var second = parseInt(timeStr.substr(3, 2)); | |
88 | return (minute * 60 + second) * 1000; | |
89 | } | |
90 | ||
91 | function timeToTimeStr(time) { | |
92 | var minute = Math.floor(time / 1000 / 60); | |
93 | var second = Math.floor(time / 1000) % 60; | |
94 | if(minute < 10) { | |
95 | minute = '0' + minute.toString(); | |
96 | } | |
97 | if(second < 10) { | |
98 | second = '0' + second.toString(); | |
99 | } | |
100 | return minute + ':' + second; | |
101 | } | |
102 | ||
103 | document.onkeydown = function(e) { | |
104 | if(e.key) { | |
105 | switch(e.key) { | |
106 | case ' ': return toggle(); | |
107 | case 'S': | |
108 | case 's': return setTime(); | |
109 | case 'R': | |
110 | case 'r': return reset(); | |
111 | case 'p': | |
112 | case 'P': return pauseResume(); | |
113 | default: return; | |
114 | } | |
115 | } else if(e.keyCode) { | |
116 | switch(e.keyCode) { | |
117 | case 32: return toggle(); // space | |
118 | case 83: return setTime(); // S | |
119 | case 82: return reset(); // R | |
120 | case 80: return pauseResume(); // P | |
121 | default: return; | |
122 | } | |
123 | } else { | |
124 | alert("Browser not supported"); | |
125 | } | |
126 | }; | |
127 | ||
128 | function toggle() { | |
129 | if(!currentTimers.isPaused) { | |
130 | currentTimers.active.stop(); | |
131 | currentTimers.passive.start(); | |
132 | } | |
133 | currentTimers.swap(); | |
134 | var lbt = document.getElementById('left-button-top'); | |
135 | var leftIsLong = lbt.getAttribute('class') == 'button-long'; | |
136 | var lbt_d = lbt.getAttribute('d').split(' '); | |
137 | var lbb = document.getElementById('left-button-body'); | |
138 | var rbt = document.getElementById('right-button-top'); | |
139 | var rbt_d = rbt.getAttribute('d').split(' '); | |
140 | var rbb = document.getElementById('right-button-body'); | |
6f474901 | 141 | |
72b294bb | 142 | var y_diff = 50 * (leftIsLong ? 1 : -1); |
143 | var classes = ['button-short', 'button-long']; | |
144 | ||
145 | lbt_d[2] = (parseInt(lbt_d[2]) + y_diff).toString(); | |
146 | lbt_d[10] = (parseInt(lbt_d[10]) + y_diff).toString(); | |
147 | lbb.setAttribute('height', | |
148 | (parseInt(lbb.getAttribute('height')) - y_diff).toString()); | |
149 | lbb.setAttribute('y', (parseInt(lbb.getAttribute('y')) + y_diff).toString()); | |
150 | rbt_d[2] = (parseInt(rbt_d[2]) - y_diff).toString(); | |
151 | rbt_d[10] = (parseInt(rbt_d[10]) - y_diff).toString(); | |
152 | rbb.setAttribute('height', | |
153 | (parseInt(rbb.getAttribute('height')) + y_diff).toString()); | |
154 | rbb.setAttribute('y', (parseInt(rbb.getAttribute('y')) - y_diff).toString()); | |
155 | lbt.setAttribute('class', classes[(leftIsLong + 1) % 2]); | |
156 | lbb.setAttribute('class', classes[(leftIsLong + 1) % 2]); | |
157 | rbt.setAttribute('class', classes[(leftIsLong + 1) % 2]); | |
158 | rbb.setAttribute('class', classes[(leftIsLong + 1) % 2]); | |
159 | lbt.setAttribute('d', lbt_d.join(' ')); | |
160 | rbt.setAttribute('d', rbt_d.join(' ')); | |
6f474901 | 161 | |
72b294bb | 162 | lbt.setAttribute('onclick', leftIsLong ? '' : 'toggle()'); |
163 | lbb.setAttribute('onclick', leftIsLong ? '' : 'toggle()'); | |
164 | lbt.setAttribute('cursor', leftIsLong ? 'default' : 'pointer'); | |
165 | lbb.setAttribute('cursor', leftIsLong ? 'default' : 'pointer'); | |
166 | rbt.setAttribute('onclick', leftIsLong ? 'toggle()' : ''); | |
167 | rbb.setAttribute('onclick', leftIsLong ? 'toggle()' : ''); | |
168 | rbt.setAttribute('cursor', leftIsLong ? 'pointer' : 'default'); | |
169 | rbb.setAttribute('cursor', leftIsLong ? 'pointer' : 'default'); | |
170 | } | |
171 | ||
172 | function pauseResume() { | |
173 | if(currentTimers.isPaused) { | |
174 | currentTimers.resume(); | |
175 | } else { | |
176 | currentTimers.pause(); | |
177 | } | |
178 | } | |
179 | ||
180 | function setTime() { | |
181 | var leftstart, rightstart; | |
182 | var def = timeToTimeStr(currentTimers.leftTimer.getDefaultTime()); | |
183 | var regex = /[0-9][0-9]:[0-5][0-9]/; | |
6f474901 | 184 | |
72b294bb | 185 | leftstart = prompt("Time for LEFT player in MM:SS", def); |
186 | if(leftstart === null) return; // Cancel | |
187 | while(!leftstart.match(regex)) { | |
188 | leftstart = prompt("Invalid value\nTime for LEFT player in MM:SS", def); | |
189 | if(leftstart === null) return; // Cancel | |
190 | } | |
191 | def = leftstart; | |
192 | rightstart = prompt("Time for RIGHT player in MM:SS", def); | |
193 | if(rightstart === null) return; // Cancel | |
194 | while(!rightstart.match(regex)) { | |
195 | rightstart = prompt("Invalid value\nTime for RIGHT player in MM:SS", def); | |
196 | if(rightstart === null) return; // Cancel | |
197 | } | |
198 | currentTimers.leftTimer.setTime(timeStrToTime(leftstart)); | |
199 | currentTimers.rightTimer.setTime(timeStrToTime(rightstart)); | |
200 | } | |
201 | ||
202 | function reset() { | |
203 | currentTimers.pause(); | |
204 | currentTimers.active.reset(); | |
205 | currentTimers.passive.reset(); | |
206 | } | |
207 | ||
208 | function init() { | |
209 | insertcss(); | |
6f474901 | 210 | setTimeout(fitscreen, 2000); // hack to allow DOM to be redrawn with new css |
72b294bb | 211 | } |
212 | ||
213 | function fitscreen() { | |
214 | /* | |
215 | * Scale body so as to fit the screen | |
216 | */ | |
217 | var heightRatio = window.innerHeight / document.body.scrollHeight; | |
218 | var widthRatio = window.innerWidth / document.body.scrollWidth; | |
6f474901 | 219 | var scaleRatio = Math.min(heightRatio, widthRatio, 1); |
72b294bb | 220 | document.body.style.transform = 'scale(' + scaleRatio + ')'; |
221 | } | |
222 | ||
223 | function insertcss() { | |
224 | /* fix positions for browsers that don't support flex */ | |
6f474901 AIL |
225 | var cssfile = document.getElementById("style"); |
226 | if(!('align-items' in document.body.style)) { | |
72b294bb | 227 | cssfile.setAttribute("href", "noflex.css"); |
228 | } | |
72b294bb | 229 | } |