From: Steinar H. Gunderson Date: Mon, 1 May 2023 16:06:44 +0000 (+0200) Subject: Make it possible to sub (in/out events only, no real effect). X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=776ee56ce2e268706ebd677fdf2f5ac903aa9d43;p=pkanalytics Make it possible to sub (in/out events only, no real effect). --- diff --git a/events.cpp b/events.cpp index 4ce3e86..a2d5e07 100644 --- a/events.cpp +++ b/events.cpp @@ -117,7 +117,7 @@ void EventsModel::load_data() } } -unsigned EventsModel::insert_event(uint64_t t, int player_id) +unsigned EventsModel::insert_event(uint64_t t, int player_id, const string &type) { auto it = lower_bound(events.begin(), events.end(), t, [](const Event &e, uint64_t t) { return e.t < t; }); @@ -127,7 +127,7 @@ unsigned EventsModel::insert_event(uint64_t t, int player_id) Event e; e.t = t; e.player_id = player_id; - e.type = "unknown"; + e.type = type; events.insert(events.begin() + pos, e); endInsertRows(); @@ -142,7 +142,7 @@ unsigned EventsModel::insert_event(uint64_t t, int player_id) sqlite3_bind_int64(stmt, 1, t); sqlite3_bind_int64(stmt, 2, player_id); - sqlite3_bind_text(stmt, 3, e.type.data(), e.type.size(), SQLITE_STATIC); + sqlite3_bind_text(stmt, 3, type.data(), type.size(), SQLITE_STATIC); ret = sqlite3_step(stmt); if (ret == SQLITE_ROW) { @@ -257,3 +257,20 @@ EventsModel::Status EventsModel::get_status_at(uint64_t t) s.possession_sec = (s.offense && last_gained_possession != 0) ? (t - last_gained_possession) / 1000 : 0; return s; } + +set EventsModel::get_team_at(uint64_t t) +{ + set team; + for (const Event &e : events) { + if (e.t > t) { + break; + } + if (e.type == "in") { + team.insert(*e.player_id); + } + if (e.type == "out") { + team.erase(*e.player_id); + } + } + return team; +} diff --git a/events.h b/events.h index 910e2b9..946ebb5 100644 --- a/events.h +++ b/events.h @@ -7,6 +7,7 @@ #include #include #include +#include class EventsModel : public QAbstractTableModel { @@ -24,7 +25,7 @@ public: QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QVariant data(const QModelIndex &index, int role) const override; - unsigned insert_event(uint64_t t, int player_id); // Returns the row. + unsigned insert_event(uint64_t t, int player_id, const std::string &type = "unknown"); // Returns the row. void delete_event(unsigned row); void set_event_type(unsigned row, const std::string &type); uint64_t get_time(unsigned row) { return events[row].t; } @@ -36,6 +37,7 @@ public: unsigned possession_sec; }; Status get_status_at(uint64_t t); + std::set get_team_at(uint64_t t); private: struct Player { diff --git a/main.cpp b/main.cpp index 2e083b8..dd23d8a 100644 --- a/main.cpp +++ b/main.cpp @@ -98,6 +98,8 @@ MainWindow::MainWindow(EventsModel *events, PlayersModel *players) : events(even connect(ui->pull, &QPushButton::clicked, [this]() { set_current_event_type("pull"); }); connect(ui->pull_landed, &QPushButton::clicked, [this]() { set_current_event_type("pull_landed"); }); + connect(ui->substitution, &QPushButton::clicked, [this]() { make_substitution(); }); + QShortcut *key_delete = new QShortcut(QKeySequence(Qt::Key_Delete), this); connect(key_delete, &QShortcut::activated, [this]() { ui->delete_->animateClick(); }); connect(ui->delete_, &QPushButton::clicked, [this]() { delete_current_event(); }); @@ -158,6 +160,37 @@ void MainWindow::delete_current_event() update_status(); } +void MainWindow::make_substitution() +{ + QItemSelectionModel *select = ui->player_view->selectionModel(); + + // FIXME: we should backdate t to start of point (last goal, or 0) if: + // - no players we're removing have had actions yet + // - there have been no other in/out events + // + // ...but if so, we might need to modify in/out events that are already there + // (perhaps just overwrite them all?) + uint64_t t = player->position(); + + set old_team = events->get_team_at(t); + set new_team; + + for (QModelIndex row : select->selectedRows()) { + new_team.insert(players->get_player_id(row.row())); + } + + for (int player_id : old_team) { + if (!new_team.count(player_id)) { + events->insert_event(t, player_id, "out"); + } + } + for (int player_id : new_team) { + if (!old_team.count(player_id)) { + events->insert_event(t, player_id, "in"); + } + } +} + void MainWindow::update_status() { EventsModel::Status s = events->get_status_at(player->position()); diff --git a/mainwindow.h b/mainwindow.h index 079a371..9f27068 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -21,6 +21,7 @@ private: void insert_event(int button_id); void set_current_event_type(const std::string &type); void delete_current_event(); + void make_substitution(); void update_status(); Ui::MainWindow *ui; diff --git a/mainwindow.ui b/mainwindow.ui index a0fe53f..c3ba4d6 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -6,7 +6,7 @@ 0 0 - 1031 + 1251 754 @@ -16,7 +16,7 @@ - + @@ -388,6 +388,9 @@ Substitution (&b) + + B + @@ -395,6 +398,9 @@ Unknown (&?) + + ? + @@ -412,6 +418,9 @@ Stoppage (&v) + + V + @@ -437,7 +446,7 @@ 0 0 - 1031 + 1251 23 diff --git a/players.h b/players.h index f7886f3..24c10b9 100644 --- a/players.h +++ b/players.h @@ -22,7 +22,9 @@ public: QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QVariant data(const QModelIndex &index, int role) const override; -// Player get_player(int player_id) const; + int get_player_id(unsigned row) const { + return players[row].player_id; + } private: struct Player {