]> git.sesse.net Git - ultimatescore/blob - score.js
1d30924c2a444e2c9a49db503f94b88f284d8f3b
[ultimatescore] / score.js
1 'use strict';
2
3 let num_clocks = 3;
4 let clocks = [
5         { 'running': false, 'elapsed': 0, 'origin': undefined, 'id': 'clock' },
6         { 'running': false, 'elapsed': 0, 'origin': undefined, 'id': 'clock2' },
7         { 'running': false, 'elapsed': 0, 'origin': undefined, 'id': 'clock3' }
8 ];
9
10 let clock_visible = false;
11 let comment_visible = false;
12 let lowerthird_visible = false;
13 let clock_limit = 30 * 60;
14 let scoreA = 0;
15 let scoreB = 0;
16 let state = {};
17
18 function setteams()
19 {
20         document.getElementById('team1').innerHTML = state['team1'];
21         document.getElementById('team2').innerHTML = state['team2'];
22
23         let sheets = { 'A': state['team1'], 'B': state['team2'] };
24         loadquickl3s(sheets);
25 }
26
27 function setteams2()
28 {
29         document.getElementById('score2_team1').innerHTML = state['team1'];
30         document.getElementById('score2_team2').innerHTML = state['team2'];
31 }
32
33 function setteams3()
34 {
35         document.getElementById('score3_team1').innerHTML = state['team1'];
36         document.getElementById('score3_team2').innerHTML = state['team2'];
37 }
38
39 function setcolors()
40 {
41         document.getElementById('team1color').style.backgroundColor = state['team1color'];
42         document.getElementById('team2color').style.backgroundColor = state['team2color'];
43 }
44
45 function setscore()
46 {
47         scoreA = state['score1'];
48         scoreB = state['score2'];
49         update_score();
50 }
51
52 function setscore2()
53 {
54         scoreA = state['score1'];
55         scoreB = state['score2'];
56         document.getElementById('score2_score').innerHTML = scoreA + " – " + scoreB;
57 }
58
59 function setscore3()
60 {
61         scoreA = state['score1'];
62         scoreB = state['score2'];
63         document.getElementById('score3_score').innerHTML = scoreA + " – " + scoreB;
64 }
65
66 function startclock(num)
67 {
68         if (!clocks[num].running) {
69                 clocks[num].origin = Date.now();
70                 clocks[num].running = true;
71         }
72         if (num == 0) {
73                 showclock();
74         }
75 }
76
77 function stopclock(num)
78 {
79         if (!clocks[num].running) return;
80         clocks[num].elapsed = time_elapsed(num);
81         clocks[num].origin = Date.now();
82         clocks[num].running = false;
83 }
84
85 function setclock(num, amount)
86 {
87         clocks[num].elapsed = amount;
88         clocks[num].origin = Date.now();
89         update_clock(num);
90 }
91
92 function setclockfromstate()
93 {
94         let amount = parseInt(state['clock_min']) * 60 + parseInt(state['clock_sec']);
95         setclock(0, amount);
96 }
97
98 // No setclock2fromstate.
99
100 function adjustclockfromstate(num)
101 {
102         let amount = parseInt(state['clock_min']) * 60 + parseInt(state['clock_sec']);
103         let elapsed = time_elapsed_raw(num);
104         if (Math.abs(amount - elapsed) >= 2.0) {
105                 setclock(num, amount);
106         }
107 }
108
109 function setclocklimitfromstate()
110 {
111         let amount = parseInt(state['clock_limit_min']) * 60 + parseInt(state['clock_limit_sec']);
112         clock_limit = amount;
113 }
114
115 function showclock()
116 {
117         if (clock_visible) return;
118         let clockbug = document.getElementById('clockbug');
119         clockbug.className = 'clockbug clockbug-animate-in';
120         clock_visible = true;
121 }
122
123 function hideclock()
124 {
125         if (!clock_visible) return;
126         let clockbug = document.getElementById('clockbug');
127         clockbug.className = 'clockbug clockbug-animate-out';
128         clock_visible = false;
129 }
130
131 function setcomment()
132 {
133         document.getElementById('comment').innerHTML = state['comment'];
134 }
135
136 function showcomment()
137 {
138         if (comment_visible) return;
139         let commentbug = document.getElementById('commentbug');
140         commentbug.className = 'commentbug commentbug-animate-in';
141         comment_visible = true;
142 }
143
144 function hidecomment()
145 {
146         if (!comment_visible) return;
147         let commentbug = document.getElementById('commentbug');
148         commentbug.className = 'commentbug commentbug-animate-out';
149         comment_visible = false;
150 }
151
152 function showlowerthird()
153 {
154         if (lowerthird_visible) return;
155
156         document.getElementById('lowerthird-headline').className = 'lowerthird-headline lowerthird-headline-animate-in';
157         document.getElementById('lowerthird-headline-content').className = 'lowerthird-headline-content lowerthird-headline-content-animate-in';
158         document.getElementById('lowerthird-subheading').className = 'lowerthird-subheading lowerthird-subheading-animate-in';
159         document.getElementById('lowerthird-subheading-content').className = 'lowerthird-subheading-content lowerthird-subheading-content-animate-in';
160         document.getElementById('lowerthird-picture').className = 'lowerthird-picture lowerthird-picture-animate-in';
161         document.getElementById('lowerthird-picture-content').className = 'lowerthird-picture-content lowerthird-picture-content-animate-in';
162         lowerthird_visible = true;
163 }
164
165 function setandshowlowerthird()
166 {
167         document.getElementById('lowerthird-headline-content').innerHTML = state['text1'];
168         document.getElementById('lowerthird-subheading-content').innerHTML = state['text2'];
169         let img = document.getElementById('lowerthird-img');
170         if (state['image'] === undefined) {
171                 img.style.display = 'none';
172         } else {
173                 img.src = state['image'];
174                 img.style.display = 'inline';
175         }
176         showlowerthird();
177 }
178
179 function hidelowerthird()
180 {
181         if (!lowerthird_visible) return;
182         document.getElementById('lowerthird-headline').className = 'lowerthird-headline lowerthird-headline-hidden lowerthird-headline-animate-out';
183         document.getElementById('lowerthird-headline-content').className = 'lowerthird-headline-content lowerthird-headline-content-animate-out';
184         document.getElementById('lowerthird-subheading').className = 'lowerthird-subheading lowerthird-subheading-animate-out';
185         document.getElementById('lowerthird-subheading-content').className = 'lowerthird-subheading-content lowerthird-subheading-content-animate-out';
186         document.getElementById('lowerthird-picture').className = 'lowerthird-picture lowerthird-picture-animate-out';
187         document.getElementById('lowerthird-picture-content').className = 'lowerthird-picture-content lowerthird-picture-content-animate-out';
188         lowerthird_visible = false;
189 }
190
191 function set_sound_shark_volume_db(volume_db)
192 {
193         let img = document.getElementById('lowerthird-img');
194         let should_enable = (volume_db > -40.0);
195         let currently_enabled = (img.style.display === 'inline' && img.src.match(/microphone\.png$/));
196
197         if (should_enable === currently_enabled) {
198                 return;
199         }
200
201         if (should_enable) {
202                 img.style.display = 'inline';
203                 img.src = 'generic/microphone.png';
204                 document.getElementById('lowerthird-picture').className = 'lowerthird-picture lowerthird-picture-animate-in';
205                 document.getElementById('lowerthird-picture-content').className = 'lowerthird-picture-content lowerthird-picture-content-animate-in';
206         } else {
207                 document.getElementById('lowerthird-picture').className = 'lowerthird-picture lowerthird-picture-animate-out';
208                 document.getElementById('lowerthird-picture-content').className = 'lowerthird-picture-content lowerthird-picture-content-animate-out';
209         }
210 }
211
212 function time_elapsed_raw(num)
213 {
214         let elapsed = (Date.now() - clocks[num].origin) * 1e-3;
215         if (clocks[num].elapsed + elapsed >= clock_limit) {
216                 console.log("limit for", num);
217                 if (num == 0) {
218                         clocks[num].elapsed = clock_limit;
219                         clocks[num].origin = Date.now();
220                         clocks[num].running = false;
221
222                         if (state['autocomment_on_clock_limit'] == '1' && !comment_visible) {
223                                 state['comment'] = state['autocomment'];
224                                 setcomment();
225                                 showcomment();
226                         }
227                 }
228
229                 return clock_limit;
230         }
231         return clocks[num].elapsed + elapsed;
232 }
233
234 function time_elapsed(num)
235 {
236         return Math.floor(time_elapsed_raw(num));
237 }
238
239 function update_given_clock(elapsed, id)
240 {
241         let min = Math.floor(elapsed / 60);
242         let sec = elapsed % 60;
243
244         if (sec < 10) sec = "0" + sec;
245         let text = min + ":" + sec;
246
247         if (ultimateconfig['exohack']) {
248                 // This is a hack around the fact that Exo has variable-width numerals.
249                 // It doesn't look fantastic, but for the clock, it's better not to have
250                 // the text jumping around.
251                 let html = "";
252                 for (let i = 0; i < text.length; ++i) {
253                         if (text.charAt(i) === ':') {
254                                 html += ':';
255                         } else {
256                                 html += "<div style='display: inline-block; width: 15px'>" + text.charAt(i) + "</div>";
257                         }
258                 }
259                 document.getElementById(id).innerHTML = html;
260         } else {
261                 document.getElementById(id).innerHTML = text;
262         }
263 }
264
265 function update_clock(num)
266 {
267         update_given_clock(time_elapsed(num), clocks[num].id);
268 }
269
270 function goalA()
271 {
272         ++scoreA;
273         update_score();
274 }
275
276 function goalB()
277 {
278         ++scoreB;
279         update_score();
280 }
281
282 function ungoalA()
283 {
284         if (scoreA > 0) --scoreA;
285         update_score();
286 }
287
288 function ungoalB()
289 {
290         if (scoreB > 0) --scoreB;
291         update_score();
292 }
293
294 function resetscore()
295 {
296         scoreA = scoreB = 0;
297         update_score();
298 }
299
300 function update_score()
301 {
302         document.getElementById('score').innerHTML = scoreA + "&nbsp;–&nbsp;" + scoreB;
303 }
304
305 /* called by the Nageru theme only */
306 function play()
307 {
308         document.getElementById('manualcontrols').style.display = 'none';
309         document.getElementById('area').style.display = 'none';
310 }
311
312 function update(v)
313 {
314         console.log('[[[' + v + ']]]');
315         let j = JSON.parse(v);
316         for(let key in j) state[key] = j[key];
317 }
318
319 setInterval(function() {
320         for (let i = 0; i < num_clocks; ++i) {
321                 if (clocks[i].running) {
322                         update_clock(i);
323                 }
324         }
325 }, 100);
326 update_score();
327
328 //play();
329 //startclock();
330
331 let websocket = null;
332
333 function open_ws()
334 {
335         console.log("Connecting...");
336         try {
337                 if (websocket)
338                         websocket.close();
339                 websocket = new WebSocket("ws://127.0.0.1:5250/");
340                 websocket.onopen = function(evt) {
341                         console.log("Connected to client.");
342                 };
343                 websocket.onclose = function(evt) {
344                         console.log("Disconnected from client.");
345                         setTimeout(open_ws, 100);
346                 };
347                 websocket.onmessage = function(evt) {
348                         let msg = evt.data;
349                         let m = msg.match(/^update (.*)/);
350                         if (m !== null) {
351                                 update(m[1]);
352                         }
353                         m = msg.match(/^eval (.*)/);
354                         if (m !== null) {
355                                 eval(m[1]);
356                         }
357                 };
358                 websocket.onerror = function(evt) {
359                         console.log('Error: ' + evt.data);
360                 };
361         } catch (exception) {
362                 console.log('Error: ' + exception);
363                 setTimeout(open_ws, 100);
364         }
365 };
366 open_ws();