]> git.sesse.net Git - ultimatescore/blob - score.js
Make the roster scripts executable.
[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 = 25 * 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         // The BT-6000 likes to reset to 0:00 a while after the match is over,
92         // so go hide it then.
93         if (num == 0 && !clocks[num].running) {
94                 hideclock();
95         }
96 }
97
98 function setclockfromstate()
99 {
100         let amount = parseInt(state['clock_min']) * 60 + parseInt(state['clock_sec']);
101         setclock(0, amount);
102 }
103
104 // No setclock2fromstate.
105
106 function adjustclockfromstate(num)
107 {
108         let amount = parseInt(state['clock_min']) * 60 + parseInt(state['clock_sec']);
109         let elapsed = time_elapsed_raw(num);
110         if (Math.abs(amount - elapsed) >= 2.0) {
111                 setclock(num, amount);
112         }
113 }
114
115 function setclocklimitfromstate()
116 {
117         let amount = parseInt(state['clock_limit_min']) * 60 + parseInt(state['clock_limit_sec']);
118         clock_limit = amount;
119 }
120
121 function showclock()
122 {
123         if (clock_visible) return;
124         let clockbug = document.getElementById('clockbug');
125         clockbug.className = 'clockbug clockbug-animate-in';
126         clock_visible = true;
127 }
128
129 function hideclock()
130 {
131         if (!clock_visible) return;
132         let clockbug = document.getElementById('clockbug');
133         clockbug.className = 'clockbug clockbug-animate-out';
134         clock_visible = false;
135 }
136
137 function setcomment()
138 {
139         document.getElementById('comment').innerHTML = state['comment'];
140 }
141
142 function showcomment()
143 {
144         if (comment_visible) return;
145         let commentbug = document.getElementById('commentbug');
146         commentbug.className = 'commentbug commentbug-animate-in';
147         comment_visible = true;
148 }
149
150 function hidecomment()
151 {
152         if (!comment_visible) return;
153         let commentbug = document.getElementById('commentbug');
154         commentbug.className = 'commentbug commentbug-animate-out';
155         comment_visible = false;
156 }
157
158 function showlowerthird()
159 {
160         if (lowerthird_visible) return;
161
162         document.getElementById('lowerthird-headline').className = 'lowerthird-headline lowerthird-headline-animate-in';
163         document.getElementById('lowerthird-headline-content').className = 'lowerthird-headline-content lowerthird-headline-content-animate-in';
164         document.getElementById('lowerthird-subheading').className = 'lowerthird-subheading lowerthird-subheading-animate-in';
165         document.getElementById('lowerthird-subheading-content').className = 'lowerthird-subheading-content lowerthird-subheading-content-animate-in';
166         document.getElementById('lowerthird-picture').className = 'lowerthird-picture lowerthird-picture-animate-in';
167         document.getElementById('lowerthird-picture-content').className = 'lowerthird-picture-content lowerthird-picture-content-animate-in';
168         lowerthird_visible = true;
169 }
170
171 function setandshowlowerthird()
172 {
173         document.getElementById('lowerthird-headline-content').innerHTML = state['text1'];
174         document.getElementById('lowerthird-subheading-content').innerHTML = state['text2'];
175         let img = document.getElementById('lowerthird-img');
176         if (state['image'] === undefined) {
177                 img.style.display = 'none';
178         } else {
179                 img.src = state['image'];
180                 img.style.display = 'inline';
181         }
182         showlowerthird();
183 }
184
185 function hidelowerthird()
186 {
187         if (!lowerthird_visible) return;
188         document.getElementById('lowerthird-headline').className = 'lowerthird-headline lowerthird-headline-hidden lowerthird-headline-animate-out';
189         document.getElementById('lowerthird-headline-content').className = 'lowerthird-headline-content lowerthird-headline-content-animate-out';
190         document.getElementById('lowerthird-subheading').className = 'lowerthird-subheading lowerthird-subheading-animate-out';
191         document.getElementById('lowerthird-subheading-content').className = 'lowerthird-subheading-content lowerthird-subheading-content-animate-out';
192         document.getElementById('lowerthird-picture').className = 'lowerthird-picture lowerthird-picture-animate-out';
193         document.getElementById('lowerthird-picture-content').className = 'lowerthird-picture-content lowerthird-picture-content-animate-out';
194         lowerthird_visible = false;
195 }
196
197 function set_sound_shark_volume_db(volume_db)
198 {
199         let img = document.getElementById('lowerthird-img');
200         let should_enable = (volume_db > -40.0);
201         let currently_enabled = (img.style.display === 'inline' && img.src.match(/microphone\.png$/));
202
203         if (should_enable === currently_enabled) {
204                 return;
205         }
206
207         if (should_enable) {
208                 img.style.display = 'inline';
209                 img.src = 'generic/microphone.png';
210                 document.getElementById('lowerthird-picture').className = 'lowerthird-picture lowerthird-picture-animate-in';
211                 document.getElementById('lowerthird-picture-content').className = 'lowerthird-picture-content lowerthird-picture-content-animate-in';
212         } else {
213                 document.getElementById('lowerthird-picture').className = 'lowerthird-picture lowerthird-picture-animate-out';
214                 document.getElementById('lowerthird-picture-content').className = 'lowerthird-picture-content lowerthird-picture-content-animate-out';
215         }
216 }
217
218 function time_elapsed_raw(num)
219 {
220         let elapsed = (Date.now() - clocks[num].origin) * 1e-3;
221         if (clocks[num].elapsed + elapsed >= clock_limit) {
222                 console.log("limit for", num);
223                 if (num == 0) {
224                         clocks[num].elapsed = clock_limit;
225                         clocks[num].origin = Date.now();
226                         clocks[num].running = false;
227
228                         if (state['autocomment_on_clock_limit'] == '1' && !comment_visible) {
229                                 state['comment'] = state['autocomment'];
230                                 setcomment();
231                                 showcomment();
232                         }
233                 }
234
235                 return clock_limit;
236         }
237         return clocks[num].elapsed + elapsed;
238 }
239
240 function time_elapsed(num)
241 {
242         return Math.floor(time_elapsed_raw(num));
243 }
244
245 function update_given_clock(elapsed, id)
246 {
247         let min = Math.floor(elapsed / 60);
248         let sec = elapsed % 60;
249
250         if (sec < 10) sec = "0" + sec;
251         let text = min + ":" + sec;
252
253         if (ultimateconfig['exohack']) {
254                 // This is a hack around the fact that Exo has variable-width numerals.
255                 // It doesn't look fantastic, but for the clock, it's better not to have
256                 // the text jumping around.
257                 let html = "";
258                 for (let i = 0; i < text.length; ++i) {
259                         if (text.charAt(i) === ':') {
260                                 html += ':';
261                         } else {
262                                 html += "<div style='display: inline-block; width: 15px'>" + text.charAt(i) + "</div>";
263                         }
264                 }
265                 document.getElementById(id).innerHTML = html;
266         } else {
267                 document.getElementById(id).innerHTML = text;
268         }
269 }
270
271 function update_clock(num)
272 {
273         update_given_clock(time_elapsed(num), clocks[num].id);
274 }
275
276 function goalA()
277 {
278         ++scoreA;
279         update_score();
280 }
281
282 function goalB()
283 {
284         ++scoreB;
285         update_score();
286 }
287
288 function ungoalA()
289 {
290         if (scoreA > 0) --scoreA;
291         update_score();
292 }
293
294 function ungoalB()
295 {
296         if (scoreB > 0) --scoreB;
297         update_score();
298 }
299
300 function resetscore()
301 {
302         scoreA = scoreB = 0;
303         update_score();
304 }
305
306 function update_score()
307 {
308         document.getElementById('score').innerHTML = scoreA + "&nbsp;–&nbsp;" + scoreB;
309 }
310
311 /* called by the Nageru theme only */
312 function play()
313 {
314         document.getElementById('manualcontrols').style.display = 'none';
315         document.getElementById('area').style.display = 'none';
316 }
317
318 function update(v)
319 {
320         console.log('[[[' + v + ']]]');
321         let j = JSON.parse(v);
322         for(let key in j) state[key] = j[key];
323 }
324
325 setInterval(function() {
326         for (let i = 0; i < num_clocks; ++i) {
327                 if (clocks[i].running) {
328                         update_clock(i);
329                 }
330         }
331 }, 100);
332 update_score();
333
334 //play();
335 //startclock();
336
337 let websocket = null;
338
339 function open_ws()
340 {
341         console.log("Connecting...");
342         try {
343                 if (websocket)
344                         websocket.close();
345                 websocket = new WebSocket("ws://127.0.0.1:5250/");
346                 websocket.onopen = function(evt) {
347                         console.log("Connected to client.");
348                 };
349                 websocket.onclose = function(evt) {
350                         console.log("Disconnected from client.");
351                         setTimeout(open_ws, 100);
352                 };
353                 websocket.onmessage = function(evt) {
354                         let msg = evt.data;
355                         let m = msg.match(/^update (.*)/);
356                         if (m !== null) {
357                                 update(m[1]);
358                         }
359                         m = msg.match(/^eval (.*)/);
360                         if (m !== null) {
361                                 eval(m[1]);
362                         }
363                 };
364                 websocket.onerror = function(evt) {
365                         console.log('Error: ' + evt.data);
366                 };
367         } catch (exception) {
368                 console.log('Error: ' + exception);
369                 setTimeout(open_ws, 100);
370         }
371 };
372 open_ws();