abort();
}
}
+
+EventsModel::Status EventsModel::get_status_at(uint64_t t)
+{
+ Status s;
+ s.our_score = 0;
+ s.their_score = 0;
+ s.offense = true;
+ uint64_t last_gained_possession = 0;
+ unsigned num_touches = 0;
+ for (const Event &e : events) {
+ if (e.t > t) {
+ break;
+ }
+ if (e.type == "goal") {
+ ++s.our_score;
+ s.offense = false;
+ num_touches = 0;
+ }
+ if (e.type == "their_goal") {
+ ++s.their_score;
+ s.offense = true;
+ num_touches = 0;
+ }
+ if (e.type == "catch") {
+ if (num_touches == 0) { // Pick up.
+ last_gained_possession = e.t;
+ }
+ ++num_touches;
+ }
+ if (e.type == "interception") {
+ num_touches = 1;
+ s.offense = true;
+ last_gained_possession = e.t;
+ }
+ }
+ s.num_passes = (num_touches == 0) ? 0 : num_touches - 1;
+ s.possession_sec = (s.offense && last_gained_possession != 0) ? (t - last_gained_possession) / 1000 : 0;
+ return s;
+}
void delete_event(unsigned row);
void set_event_type(unsigned row, const std::string &type);
+ struct Status {
+ unsigned our_score, their_score;
+ bool offense;
+ unsigned num_passes;
+ unsigned possession_sec;
+ };
+ Status get_status_at(uint64_t t);
+
private:
struct Player {
int player_id;
ui->setupUi(this);
connect(player, &QMediaPlayer::positionChanged, [this](uint64_t pos) {
- ui->timestamp->setText(QString::fromUtf8(format_timestamp(pos)));
- if (buffered_seek) {
- player->setPosition(*buffered_seek);
- buffered_seek.reset();
- }
- if (!playing) {
- player->pause(); // We only played to get a picture.
- }
+ position_changed(pos);
});
player->setVideoOutput(ui->video);
connect(ui->delete_, &QPushButton::clicked, [this]() { delete_current_event(); });
}
+void MainWindow::position_changed(uint64_t pos)
+{
+ ui->timestamp->setText(QString::fromUtf8(format_timestamp(pos)));
+ if (buffered_seek) {
+ player->setPosition(*buffered_seek);
+ buffered_seek.reset();
+ }
+ if (!playing) {
+ player->pause(); // We only played to get a picture.
+ }
+ update_status();
+}
+
void MainWindow::setModel(EventsModel *model)
{
ui->event_view->setModel(model);
}
int row = select->selectedRows().front().row(); // Should only be one, due to our selection behavior.
model->set_event_type(row, type);
+ update_status();
}
void MainWindow::delete_current_event()
}
int row = select->selectedRows().front().row(); // Should only be one, due to our selection behavior.
model->delete_event(row);
+ update_status();
+}
+
+void MainWindow::update_status()
+{
+ EventsModel::Status s = model->get_status_at(player->position());
+ char buf[256];
+ snprintf(buf, sizeof(buf), "%d–%d | %s | %d passes, %d sec possession",
+ s.our_score, s.their_score, s.offense ? "offense" : "defense", s.num_passes, s.possession_sec);
+ ui->status->setText(buf);
}
sqlite3 *open_db(const char *filename)