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