}
}
-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; });
Event e;
e.t = t;
e.player_id = player_id;
- e.type = "unknown";
+ e.type = type;
events.insert(events.begin() + pos, e);
endInsertRows();
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) {
s.possession_sec = (s.offense && last_gained_possession != 0) ? (t - last_gained_possession) / 1000 : 0;
return s;
}
+
+set<int> EventsModel::get_team_at(uint64_t t)
+{
+ set<int> 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;
+}
#include <map>
#include <vector>
#include <optional>
+#include <set>
class EventsModel : public QAbstractTableModel
{
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; }
unsigned possession_sec;
};
Status get_status_at(uint64_t t);
+ std::set<int> get_team_at(uint64_t t);
private:
struct Player {
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(); });
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<int> old_team = events->get_team_at(t);
+ set<int> 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());
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;
<rect>
<x>0</x>
<y>0</y>
- <width>1031</width>
+ <width>1251</width>
<height>754</height>
</rect>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
- <layout class="QGridLayout" name="main_grid" rowstretch="1,0,0,0,0,0" columnstretch="1,0">
+ <layout class="QGridLayout" name="main_grid" rowstretch="1,0,0" columnstretch="1,0">
<item row="0" column="0">
<widget class="QVideoWidget" name="video" native="true">
<property name="minimumSize">
<property name="text">
<string>Substitution (&b)</string>
</property>
+ <property name="shortcut">
+ <string>B</string>
+ </property>
</widget>
</item>
<item row="1" column="0">
<property name="text">
<string>Unknown (&?)</string>
</property>
+ <property name="shortcut">
+ <string>?</string>
+ </property>
</widget>
</item>
<item row="1" column="1">
<property name="text">
<string>Stoppage (&v)</string>
</property>
+ <property name="shortcut">
+ <string>V</string>
+ </property>
</widget>
</item>
</layout>
<rect>
<x>0</x>
<y>0</y>
- <width>1031</width>
+ <width>1251</width>
<height>23</height>
</rect>
</property>
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 {