]> git.sesse.net Git - ultimatescore/commitdiff
Support having a second scorebug for a second BT6000-controlled match.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 20 Oct 2018 15:12:07 +0000 (17:12 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 20 Oct 2018 15:12:07 +0000 (17:12 +0200)
carousel.js
client/bodet.cpp
client/mainwindow.cpp
client/mainwindow.h
client/mainwindow.ui
score.css
score.html
score.js

index b62fc270fb8ffdbbaa8b5bc402cd543b6ac9d8b3..8daed95d6e55bffa5b1cef6e8804e46250f384ff 100644 (file)
@@ -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;
+}
index 54ec609e1f9ea108b156c8881ed3e85d887a4e31..b9eecc9c6ac83991daaebf5ae05ceabe5d8226e4 100644 (file)
@@ -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
 
index 032591e03f215c4b2e6a0b5da533d2926743a981..3ea51a013db70c18cdbb2fe783d3af7020c7806d 100644 (file)
@@ -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<string, string> 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<string, string> 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<string, string> 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<string, string> 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).
index 5402654fdce11930ffe935ad34e2ac641680af1b..968ef4daabbc41d0a1cebe9018fb516c741c5c37 100644 (file)
@@ -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
index 333e4b89c8deb9d7baf3f84c8ee0fdd9f820d39d..68bfff94c4d7068ac6483942164c49de78054a57 100644 (file)
         <item>
          <widget class="QCheckBox" name="bt6000_enable">
           <property name="text">
-           <string>Get BT6000 data on UDP</string>
+           <string>Score 1 UDP</string>
+          </property>
+          <property name="checked">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QCheckBox" name="bt6000_2_enable">
+          <property name="text">
+           <string>Score 2 UDP</string>
           </property>
           <property name="checked">
            <bool>true</bool>
             </property>
            </widget>
           </item>
+          <item row="5" column="0">
+           <widget class="QLabel" name="label_17">
+            <property name="text">
+             <string>Match 2</string>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="1">
+           <widget class="QLineEdit" name="match_2_initials_1_edit">
+            <property name="text">
+             <string>PCL</string>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="2">
+           <widget class="QLineEdit" name="match_2_initials_2_edit">
+            <property name="text">
+             <string>TFK</string>
+            </property>
+           </widget>
+          </item>
+          <item row="5" column="3">
+           <widget class="QPushButton" name="set_match_2_initials_btn">
+            <property name="text">
+             <string>Set</string>
+            </property>
+           </widget>
+          </item>
          </layout>
         </item>
        </layout>
           </property>
          </widget>
         </item>
+        <item>
+         <widget class="QPushButton" name="show_match_2_btn">
+          <property name="text">
+           <string>Show match 2</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="hide_match_2_btn">
+          <property name="text">
+           <string>Hide match 2</string>
+          </property>
+         </widget>
+        </item>
        </layout>
       </item>
       <item>
index 6e20d2cf2dee8ea0aae89e66b164c3af36b0ae51..f35086a616e018e38dd7d5bdc662ac73d341360e 100644 (file)
--- 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%);
 }
index c93d640bd5ebd285fe07fce6c12058f0d07bed2b..3985d78fc62bb5d99ed70fbd1345aafd244aca95 100644 (file)
           <td class="comment" id="comment">Pagacap: First to 9 points</td>
         </tr>
       </table>
+      <table class="scorebug scorebug2" id="scorebug2" style="display: none">
+        <tr>
+          <td class="team1" id="score2_team1">TM3</td>
+          <td class="score" id="score2_score">0&nbsp;–&nbsp;0</td>
+          <td class="team2" id="score2_team2">TM4</td>
+        </tr>
+      </table>
+      <table class="clockbug2 clockbug-hidden" id="clockbug2" style="display: none">
+        <tr>
+          <td class="clock" id="clock2">0:00</td>
+        </tr>
+      </table>
     </div>
     <div class="lowerthird-headline lowerthird-headline-hidden" id="lowerthird-headline"><div class="lowerthird-headline-content lowerthird-headline-content-hidden" id="lowerthird-headline-content">
       Call on the field: Foul
@@ -63,6 +75,8 @@
       <p>
         <a href="javascript:showlowerthird()">show lower third</a>
         <a href="javascript:hidelowerthird()">hide lower third</a>
+        <a href="javascript:showmatch2()">show match 2</a>
+        <a href="javascript:hidematch2()">hide match 2</a>
       </p>
       <p>
         <a href="javascript:stopcarousel();hidetable();showscorebug()">show scorebug</a>
index 67099a8cb4b6620471d4072288b5bcacd6063139..273a311896ee3712ef8c87bc48d7971b4ab01f80 100644 (file)
--- 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 + "&nbsp;–&nbsp;" + 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();