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;
+}
} 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
});
});
- 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);
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);
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;
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;
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) {
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);
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);
});
}
}
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') {
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).
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();
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();
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
<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>
.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;
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);
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;
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%);
}
<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 – 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
<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>
'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()
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'];
update_score();
}
+function setscore2()
+{
+ scoreA = state['score1'];
+ scoreB = state['score2'];
+ document.getElementById('score2_score').innerHTML = scoreA + " – " + scoreB;
+}
+
function startclock()
{
if (!clock_running) {
showclock();
}
+function startclock2()
+{
+ if (!clock2_running) {
+ clock2_origin = Date.now();
+ clock2_running = true;
+ }
+ // No showclock.
+}
+
function stopclock()
{
if (!clock_running) return;
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;
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']);
}
}
+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']);
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();
}
}
+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;
if (clock_running) {
update_clock();
}
+ if (clock2_running) {
+ update_clock2();
+ }
}, 100);
update_score();