]> git.sesse.net Git - pkanalytics/commitdiff
Make the throwaway behavior more sane.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Tue, 1 Aug 2023 22:11:33 +0000 (00:11 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Tue, 1 Aug 2023 22:11:33 +0000 (00:11 +0200)
This finally allows you to just press â€œt” for a throwaway,
and whoever holds the disc will be taken to have thrown it away.
The old behavior (re-add the same player, press t) is still allowed,
and detected heuristically.

events.cpp
events.h
mainwindow.cpp
mainwindow.h

index 4fd7ff6321ea5050a08e6721adf99d033fe45bb5..1dd7ca1f449dc1a181d0583c850bb34441ef489a 100644 (file)
@@ -471,13 +471,14 @@ EventsModel::Status EventsModel::get_status_at(uint64_t t)
        s.defensive_formation = 0;
        s.stoppage = false;
        s.pull_state = Status::SHOULD_PULL;
+       s.last_catching_player = -1;
        uint64_t last_gained_possession = 0;
        uint64_t last_stoppage = 0;
        uint64_t time_spent_in_stoppage = 0;
        unsigned num_touches = 0;
 
-       auto set_offense = [&s] { s.attack_state = Status::OFFENSE; };
-       auto set_defense = [&s] { s.attack_state = Status::DEFENSE; };
+       auto set_offense = [&s] { s.attack_state = Status::OFFENSE; s.last_catching_player = -1; };
+       auto set_defense = [&s] { s.attack_state = Status::DEFENSE; s.last_catching_player = -1; };
 
        for (const Event &e : events) {
                if (e.t > t) {
@@ -490,6 +491,7 @@ EventsModel::Status EventsModel::get_status_at(uint64_t t)
                        // No effect on pull status.
                } else if (e.type == EventType::PULL) {
                        s.pull_state = Status::PULL_IN_AIR;
+                       s.last_catching_player = -1;  // Just to be sure.
                } else {
                        s.pull_state = Status::NOT_PULLING;  // Includes pull_landed and pull_oob.
                }
@@ -516,10 +518,12 @@ EventsModel::Status EventsModel::get_status_at(uint64_t t)
                                time_spent_in_stoppage = 0;
                        }
                        ++num_touches;
+                       s.last_catching_player = *e.player_id;
                }
                if (e.type == EventType::INTERCEPTION) {
                        num_touches = 1;
                        set_offense();
+                       s.last_catching_player = *e.player_id;
                        last_gained_possession = e.t;
                        time_spent_in_stoppage = 0;
                }
index 903c107beb89dbd30570a74ea881f8a6dc439cd8..441b00eee939170479784e9ea9f21fc95568400a 100644 (file)
--- a/events.h
+++ b/events.h
@@ -76,6 +76,7 @@ public:
                unsigned num_passes;
                unsigned possession_sec;
                unsigned stoppage_sec;
+               int last_catching_player;  // -1 if we are not on offense, or last disc-related event wasn't a catch.
        };
        Status get_status_at(uint64_t t);
        std::set<int> get_team_at(uint64_t t);
index bf0ec2bcc80addab23e00ab393feabb49ba0567c..bb6883f7cf58918f50f4e1e6f0a8c7c7ce77140a 100644 (file)
@@ -263,7 +263,7 @@ MainWindow::MainWindow(EventsModel *events, PlayersModel *players,
                if (s.attack_state == EventsModel::Status::DEFENSE && s.pull_state == EventsModel::Status::PULL_IN_AIR) {
                        insert_noplayer_event("pull_oob");
                } else {
-                       set_current_event_type("throwaway");
+                       insert_throwaway();
                }
        });
        connect(ui->drop, &QPushButton::clicked, [this] { set_current_event_type("drop"); });
@@ -425,6 +425,36 @@ void MainWindow::set_current_event_type(const string &type)
        update_ui_from_time(ui->video->get_position());
 }
 
+void MainWindow::insert_throwaway()
+{
+       uint64_t t = ui->video->get_position();
+
+       QItemSelectionModel *select = ui->event_view->selectionModel();
+       if (select->hasSelection()) {
+               int row = select->selectedRows().front().row();  // Should only be one, due to our selection behavior.
+               // We could want to modify this catch event into a throwaway. See if that is the case.
+               int last_catching_player = events->get_status_at(events->get_time(row) - 1).last_catching_player;
+               if (last_catching_player != -1 && last_catching_player == events->get_player_id(row)) {
+                       // Last event was that this player caught the disc, so yes, make this a throwaway.
+                       events->set_event_type(row, "throwaway");
+                       update_ui_from_time(t);
+                       return;
+               }
+               // It doesn't make sense that the player throws it away without holding the disc first,
+               // so we insert a new event where the person holding the disc throws it away.
+               // (In other words, fall back to inserting a new one based on time.)
+       }
+
+       int last_catching_player = events->get_status_at(t - 1).last_catching_player;
+       if (last_catching_player == -1) {
+               return;
+       }
+
+       ui->event_view->selectionModel()->blockSignals(true);
+       ui->event_view->selectRow(events->insert_event(t, last_catching_player, nullopt, "throwaway"));
+       ui->event_view->selectionModel()->blockSignals(false);
+}
+
 // Formation buttons either modify the existing formation (if we've selected
 // a formation change event), or insert a new one (if not).
 void MainWindow::insert_or_change_formation(bool offense)
@@ -668,7 +698,7 @@ void MainWindow::update_action_buttons(uint64_t t)
        ui->pull_or_was_d->setEnabled(true);
 
        ui->catch_->setEnabled(s.attack_state == EventsModel::Status::OFFENSE && has_selection_with_player);
-       ui->throwaway->setEnabled(s.attack_state == EventsModel::Status::OFFENSE && has_selection_with_player);
+       ui->throwaway->setEnabled(s.attack_state == EventsModel::Status::OFFENSE && s.last_catching_player != -1);
        ui->drop->setEnabled(s.attack_state == EventsModel::Status::OFFENSE && has_selection_with_player);
        ui->goal->setEnabled(s.attack_state == EventsModel::Status::OFFENSE && has_selection_with_player);
        ui->stallout->setEnabled(s.attack_state == EventsModel::Status::OFFENSE && has_selection_with_player);
index 5298eba3609dc5a4d718ccc23c5c666ede484898..5592e3ebcfed5b4543355e7f2391805e7b44570b 100644 (file)
@@ -29,6 +29,7 @@ private:
        void insert_player_event(int button_id);
        void insert_noplayer_event(const std::string &type);
        void set_current_event_type(const std::string &type);
+       void insert_throwaway();
        void insert_or_change_formation(bool offense);
        void delete_current_event();
        void make_substitution();