From 742194d6c8b42570e529c6099fa8125ad9e423f2 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sat, 20 Oct 2018 17:12:07 +0200 Subject: [PATCH] Support having a second scorebug for a second BT6000-controlled match. --- carousel.js | 15 +++++++- client/bodet.cpp | 7 +++- client/mainwindow.cpp | 78 +++++++++++++++++++++++++++++++--------- client/mainwindow.h | 8 +++-- client/mainwindow.ui | 54 +++++++++++++++++++++++++++- score.css | 27 +++++++++++++- score.html | 14 ++++++++ score.js | 82 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 263 insertions(+), 22 deletions(-) diff --git a/carousel.js b/carousel.js index b62fc27..8daed95 100644 --- a/carousel.js +++ b/carousel.js @@ -695,5 +695,18 @@ function hidescorebug() function showscorebug() { document.getElementById('entire-bug').style.display = null; -}; +} +function showmatch2() +{ + let css = "-webkit-animation: fade-in 1.0s ease; -webkit-animation-fill-mode: both;"; + document.getElementById('scorebug2').style = css; + document.getElementById('clockbug2').style = css; +} + +function hidematch2() +{ + let css = "-webkit-animation: fade-out 1.0s ease; -webkit-animation-fill-mode: both;"; + document.getElementById('scorebug2').style = css; + document.getElementById('clockbug2').style = css; +} diff --git a/client/bodet.cpp b/client/bodet.cpp index 54ec609..b9eecc9 100644 --- a/client/bodet.cpp +++ b/client/bodet.cpp @@ -61,7 +61,12 @@ int main(int argc, char **argv) } else { inet_pton(AF_INET6, "::1", &saddr6.sin6_addr); } - saddr6.sin6_port = htons(6000); + + int port = 6000; + if (argc >= 3) { + port = atoi(argv[2]); + } + saddr6.sin6_port = htons(port); // TODO: open serial port diff --git a/client/mainwindow.cpp b/client/mainwindow.cpp index 032591e..3ea51a0 100644 --- a/client/mainwindow.cpp +++ b/client/mainwindow.cpp @@ -97,10 +97,12 @@ MainWindow::MainWindow(QWidget *parent) : }); }); - udp_thread = std::thread(&MainWindow::udp_thread_func, this); + udp_thread = std::thread(&MainWindow::udp_thread_func, this, 6000); + udp_thread2 = std::thread(&MainWindow::udp_thread_func, this, 6001); connect(ui->ws_disconnect_btn, &QPushButton::clicked, this, &MainWindow::ws_disconnect_clicked); connect(ui->set_initials_btn, &QPushButton::clicked, this, &MainWindow::set_initials_clicked); + connect(ui->set_match_2_initials_btn, &QPushButton::clicked, this, &MainWindow::set_match_2_initials_clicked); connect(ui->set_color_btn, &QPushButton::clicked, this, &MainWindow::set_color_clicked); connect(ui->set_score_btn, &QPushButton::clicked, this, &MainWindow::set_score_clicked); connect(ui->set_all_scorebug_btn, &QPushButton::clicked, this, &MainWindow::set_all_scorebug_clicked); @@ -115,6 +117,8 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->stop_clock_btn, &QPushButton::clicked, this, &MainWindow::stop_clock_clicked); connect(ui->show_clock_btn, &QPushButton::clicked, this, &MainWindow::show_clock_clicked); connect(ui->hide_clock_btn, &QPushButton::clicked, this, &MainWindow::hide_clock_clicked); + connect(ui->show_match_2_btn, &QPushButton::clicked, this, &MainWindow::show_match_2_clicked); + connect(ui->hide_match_2_btn, &QPushButton::clicked, this, &MainWindow::hide_match_2_clicked); connect(ui->set_comment_btn, &QPushButton::clicked, this, &MainWindow::set_comment_clicked); connect(ui->set_and_show_comment_btn, &QPushButton::clicked, this, &MainWindow::set_and_show_comment_clicked); @@ -163,6 +167,15 @@ void MainWindow::set_initials_clicked() ws->send_command("eval setteams()"); } +void MainWindow::set_match_2_initials_clicked() +{ + map param; + param["team1"] = escape_html(ui->match_2_initials_1_edit->text().toStdString()); + param["team2"] = escape_html(ui->match_2_initials_2_edit->text().toStdString()); + ws->send_command("update " + serialize_as_json(param)); + ws->send_command("eval setteams2()"); +} + void MainWindow::set_color_clicked() { map param; @@ -233,6 +246,16 @@ void MainWindow::hide_clock_clicked() ws->send_command("eval hideclock()"); } +void MainWindow::show_match_2_clicked() +{ + ws->send_command("eval showmatch2()"); +} + +void MainWindow::hide_match_2_clicked() +{ + ws->send_command("eval hidematch2()"); +} + void MainWindow::set_comment_clicked() { map param; @@ -366,7 +389,7 @@ void MainWindow::show_nothing_clicked() ws->send_command("eval hidetable()"); } -void MainWindow::udp_thread_func() +void MainWindow::udp_thread_func(int port) { int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (sock == -1) { @@ -384,7 +407,7 @@ void MainWindow::udp_thread_func() memset(&saddr6, 0, sizeof(saddr6)); saddr6.sin6_family = AF_INET6; inet_pton(AF_INET6, "::", &saddr6.sin6_addr); - saddr6.sin6_port = htons(6000); + saddr6.sin6_port = htons(port); if (bind(sock, (sockaddr *)&saddr6, sizeof(saddr6)) == -1) { perror("bind"); exit(1); @@ -398,8 +421,8 @@ void MainWindow::udp_thread_func() exit(1); } - post_to_main_thread([buf, err, this] { - bt6000_message_received(string(buf, err)); + post_to_main_thread([buf, err, port, this] { + bt6000_message_received(string(buf, err), port); }); } } @@ -427,11 +450,17 @@ int parse_score(char ch1, char ch2, char ch3) return s1 * 100 + s2 * 10 + s3; } -void MainWindow::bt6000_message_received(const string &msg) +void MainWindow::bt6000_message_received(const string &msg, int port) { - fprintf(stderr, "BT6000 message: '%s'\n", msg.c_str()); - if (!ui->bt6000_enable->isChecked()) { - return; + fprintf(stderr, "BT6000 message: '%s' (port %d)\n", msg.c_str(), port); + if (port == 6001) { + if (!ui->bt6000_2_enable->isChecked()) { + return; + } + } else { + if (!ui->bt6000_enable->isChecked()) { + return; + } } if (msg.size() >= 9 && msg[0] == 'G' && msg[1] == '0' && msg[2] == '1') { @@ -445,20 +474,37 @@ void MainWindow::bt6000_message_received(const string &msg) param["clock_min"] = to_string(minutes); param["clock_sec"] = to_string(seconds); ws->send_command("update " + serialize_as_json(param)); - ws->send_command("eval adjustclockfromstate()"); - if (clock_running) { - ws->send_command("eval startclock()"); + if (port == 6001) { + ws->send_command("eval adjustclock2fromstate()"); + if (clock_running) { + ws->send_command("eval startclock2()"); + } else { + ws->send_command("eval stopclock2()"); + } } else { - ws->send_command("eval stopclock()"); + ws->send_command("eval adjustclockfromstate()"); + if (clock_running) { + ws->send_command("eval startclock()"); + } else { + ws->send_command("eval stopclock()"); + } } } if (msg.size() >= 10 && msg[0] == 'G' && msg[1] == '0' && msg[2] == '2') { int score1 = parse_score(msg[4], msg[5], msg[6]); int score2 = parse_score(msg[7], msg[8], msg[9]); - ui->score_1_box->setValue(score1); - ui->score_2_box->setValue(score2); - set_score_clicked(); + if (port == 6001) { + map param; + param["score1"] = to_string(score1); + param["score2"] = to_string(score2); + ws->send_command("update " + serialize_as_json(param)); + ws->send_command("eval setscore2()"); + } else { + ui->score_1_box->setValue(score1); + ui->score_2_box->setValue(score2); + set_score_clicked(); + } } // Ignore type 3 (penalties) and type 4 (timeouts). diff --git a/client/mainwindow.h b/client/mainwindow.h index 5402654..968ef4d 100644 --- a/client/mainwindow.h +++ b/client/mainwindow.h @@ -26,6 +26,7 @@ public: private: void ws_disconnect_clicked(); void set_initials_clicked(); + void set_match_2_initials_clicked(); void set_color_clicked(); void set_score_clicked(); void set_all_scorebug_clicked(); @@ -36,6 +37,8 @@ private: void stop_clock_clicked(); void show_clock_clicked(); void hide_clock_clicked(); + void show_match_2_clicked(); + void hide_match_2_clicked(); void set_comment_clicked(); void set_and_show_comment_clicked(); void hide_comment_clicked(); @@ -51,14 +54,15 @@ private: void show_carousel_clicked(); void show_roster_carousel_clicked(); void show_nothing_clicked(); - void udp_thread_func(); - void bt6000_message_received(const std::string &msg); + void udp_thread_func(int port); + void bt6000_message_received(const std::string &msg, int port); Ui::MainWindow *ui; WSServer *ws; EventDevice *event_device; std::thread udp_thread; + std::thread udp_thread2; }; #endif // MAINWINDOW_H diff --git a/client/mainwindow.ui b/client/mainwindow.ui index 333e4b8..68bfff9 100644 --- a/client/mainwindow.ui +++ b/client/mainwindow.ui @@ -77,7 +77,17 @@ - Get BT6000 data on UDP + Score 1 UDP + + + true + + + + + + + Score 2 UDP true @@ -302,6 +312,34 @@ + + + + Match 2 + + + + + + + PCL + + + + + + + TFK + + + + + + + Set + + + @@ -450,6 +488,20 @@ + + + + Show match 2 + + + + + + + Hide match 2 + + + diff --git a/score.css b/score.css index 6e20d2c..f35086a 100644 --- a/score.css +++ b/score.css @@ -41,6 +41,18 @@ body { .scorebug td { border: 1px solid #000; } +.scorebug2 { + /*top: 52px; */ + /* left: 22px; */ + left: 1275px; + top: 13px; + font-size: 20px; +} +#clockbug2 { + left: 1360px; + top: 13px; + font-size: 20px; +} .team1color, .team2color { width: 12px; margin: 5px; @@ -61,6 +73,12 @@ body { background: linear-gradient(to bottom, #00a, #008); padding-top: var(--main-padding-top-adjust); } +#score2_team1, #score2_team2 { + background: linear-gradient(to bottom, #00a8, #0088); +} +#score2_team1, #score2_team2, #score2_score { + height: 30px; +} .score { text-align: center; background: linear-gradient(to bottom, #00c, #00a); @@ -68,9 +86,12 @@ body { height: 35px; padding-top: var(--main-padding-top-adjust); } +#score2_score { + background: linear-gradient(to bottom, #00c8, #00a8); +} /* Clock, to the right of score */ -.clockbug { +.clockbug, .clockbug2 { position: fixed; font-size: 25px; left: 352px; @@ -87,6 +108,10 @@ body { padding-top: var(--main-padding-top-adjust); width: 90px; } +#clock2 { + background: linear-gradient(to bottom, #00a8, #0088); + height: 30px; +} .clockbug-hidden { -webkit-transform:translateX(-200%); } diff --git a/score.html b/score.html index c93d640..3985d78 100644 --- a/score.html +++ b/score.html @@ -29,6 +29,18 @@ Pagacap: First to 9 points + + + + + + + + + + + +
Call on the field: Foul @@ -63,6 +75,8 @@

show lower third hide lower third + show match 2 + hide match 2

show scorebug diff --git a/score.js b/score.js index 67099a8..273a311 100644 --- a/score.js +++ b/score.js @@ -1,14 +1,18 @@ 'use strict'; let clock_running = false; +let clock2_running = false; let clock_visible = false; +let scorebug2_visible = false; let comment_visible = false; let lowerthird_visible = false; let clock_elapsed = 0; +let clock2_elapsed = 0; let clock_limit = 30 * 60; let scoreA = 0; let scoreB = 0; let clock_origin; +let clock2_origin; let state = {}; function setteams() @@ -20,6 +24,12 @@ function setteams() loadquickl3s(sheets); } +function setteams2() +{ + document.getElementById('score2_team1').innerHTML = state['team1']; + document.getElementById('score2_team2').innerHTML = state['team2']; +} + function setcolors() { document.getElementById('team1color').style.backgroundColor = state['team1color']; @@ -33,6 +43,13 @@ function setscore() update_score(); } +function setscore2() +{ + scoreA = state['score1']; + scoreB = state['score2']; + document.getElementById('score2_score').innerHTML = scoreA + " â€“ " + scoreB; +} + function startclock() { if (!clock_running) { @@ -42,6 +59,15 @@ function startclock() showclock(); } +function startclock2() +{ + if (!clock2_running) { + clock2_origin = Date.now(); + clock2_running = true; + } + // No showclock. +} + function stopclock() { if (!clock_running) return; @@ -50,6 +76,14 @@ function stopclock() clock_running = false; } +function stopclock2() +{ + if (!clock2_running) return; + clock2_elapsed = time2_elapsed(); + clock2_origin = Date.now(); + clock2_running = false; +} + function setclock(amount) { clock_elapsed = amount; @@ -57,12 +91,21 @@ function setclock(amount) update_clock(); } +function setclock2(amount) +{ + clock2_elapsed = amount; + clock2_origin = Date.now(); + update_clock2(); +} + function setclockfromstate() { let amount = parseInt(state['clock_min']) * 60 + parseInt(state['clock_sec']); setclock(amount); } +// No setclock2fromstate. + function adjustclockfromstate() { let amount = parseInt(state['clock_min']) * 60 + parseInt(state['clock_sec']); @@ -72,6 +115,15 @@ function adjustclockfromstate() } } +function adjustclock2fromstate() +{ + let amount = parseInt(state['clock_min']) * 60 + parseInt(state['clock_sec']); + let elapsed = time_elapsed2_raw(); + if (Math.abs(amount - elapsed) >= 2.0) { + setclock2(amount); + } +} + function setclocklimitfromstate() { let amount = parseInt(state['clock_limit_min']) * 60 + parseInt(state['clock_limit_sec']); @@ -166,11 +218,26 @@ function time_elapsed_raw() return clock_elapsed + elapsed; } +function time_elapsed2_raw() +{ + let elapsed = (Date.now() - clock2_origin) * 1e-3; + if (clock2_elapsed + elapsed >= clock_limit) { + // No separate clock 2 limit. + return clock_limit; + } + return clock2_elapsed + elapsed; +} + function time_elapsed() { return Math.floor(time_elapsed_raw()); } +function time_elapsed2() +{ + return Math.floor(time_elapsed2_raw()); +} + function update_clock() { let elapsed = time_elapsed(); @@ -198,6 +265,18 @@ function update_clock() } } +function update_clock2() +{ + let elapsed = time_elapsed2(); + let min = Math.floor(elapsed / 60); + let sec = elapsed % 60; + + if (sec < 10) sec = "0" + sec; + let text = min + ":" + sec; + + document.getElementById('clock2').innerHTML = text; +} + function goalA() { ++scoreA; @@ -251,6 +330,9 @@ setInterval(function() { if (clock_running) { update_clock(); } + if (clock2_running) { + update_clock2(); + } }, 100); update_score(); -- 2.39.2