]> git.sesse.net Git - pkanalytics/commitdiff
Add support for stallouts.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 22 Jul 2023 19:15:43 +0000 (21:15 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 22 Jul 2023 19:15:43 +0000 (21:15 +0200)
events.cpp
mainwindow.cpp
mainwindow.ui
ultimate.js

index 88b0d4a7d0273dc7a9a727e41b49409afd981d54..83a68df516d03467ec2213e97ea3164803425baa 100644 (file)
@@ -405,7 +405,7 @@ EventsModel::Status EventsModel::get_status_at(uint64_t t)
                        num_touches = 0;
                        time_spent_in_stoppage = 0;
                }
-               if (e.type == "drop" || e.type == "was_d" || e.type == "throwaway") {
+               if (e.type == "drop" || e.type == "was_d" || e.type == "throwaway" || e.type == "stallout") {
                        set_defense();
                        num_touches = 0;
                }
@@ -523,7 +523,7 @@ void EventsModel::set_formation_at(uint64_t t, bool offense, unsigned formation)
                    e.type == "stoppage" || e.type == "reset" ||
                    e.type == "set_defense" || e.type == "set_offense" ||
                    e.type == "throwaway" || e.type == "their_throwaway" ||
-                   e.type == "drop" || e.type == "was_d" || e.type == "defense" || e.type == "interception" ||
+                   e.type == "drop" || e.type == "was_d" || e.type == "defense" || e.type == "interception" || e.type == "stallout" ||
                    e.type == "pull" || e.type == "pull_landed" || e.type == "pull_oob" || e.type == "their_pull" ||
                    e.type == "formation_offense" || e.type == "formation_defense") {
                        backdate_point = e.t + 1;
index 81e7e92dc7c70f41e68ecf9b2e9f76d249f5e68b..b8322cbb856c20f0c5902251d45e8135afd242e2 100644 (file)
@@ -212,6 +212,7 @@ MainWindow::MainWindow(EventsModel *events, PlayersModel *players,
        });
        connect(ui->drop, &QPushButton::clicked, [this]() { set_current_event_type("drop"); });
        connect(ui->goal, &QPushButton::clicked, [this]() { set_current_event_type("goal"); });
+       connect(ui->stallout, &QPushButton::clicked, [this]() { set_current_event_type("stallout"); });
        connect(ui->soft_plus, &QPushButton::clicked, [this, events]() {
                EventsModel::Status s = events->get_status_at(ui->video->get_position());
                if (s.attack_state == EventsModel::Status::OFFENSE) {
@@ -497,6 +498,7 @@ void MainWindow::update_action_buttons(uint64_t t)
                ui->throwaway->setEnabled(false);
                ui->drop->setEnabled(false);
                ui->goal->setEnabled(false);
+               ui->stallout->setEnabled(false);
                ui->soft_plus->setEnabled(false);
                ui->soft_minus->setEnabled(false);
                ui->pull_or_was_d->setEnabled(false);
@@ -527,6 +529,7 @@ void MainWindow::update_action_buttons(uint64_t t)
                ui->throwaway->setEnabled(false);
                ui->drop->setEnabled(false);
                ui->goal->setEnabled(false);
+               ui->stallout->setEnabled(false);
                ui->soft_plus->setEnabled(false);
                ui->soft_minus->setEnabled(false);
                ui->interception->setEnabled(false);
@@ -553,6 +556,7 @@ void MainWindow::update_action_buttons(uint64_t t)
                ui->catch_->setEnabled(false);
                ui->drop->setEnabled(false);
                ui->goal->setEnabled(false);
+               ui->stallout->setEnabled(false);
                ui->soft_plus->setEnabled(false);
                ui->soft_minus->setEnabled(false);
                ui->interception->setEnabled(false);
@@ -571,6 +575,7 @@ void MainWindow::update_action_buttons(uint64_t t)
        ui->throwaway->setEnabled(s.attack_state == EventsModel::Status::OFFENSE && has_selection_with_player);
        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);
        ui->soft_plus->setEnabled(s.attack_state != EventsModel::Status::NOT_STARTED && has_selection_with_player);
        ui->soft_minus->setEnabled(s.attack_state != EventsModel::Status::NOT_STARTED && has_selection_with_player);
        ui->pull_or_was_d->setEnabled(s.attack_state == EventsModel::Status::OFFENSE && has_selection_with_player);  // Was d-ed.
index 845966050d541f772b3eb9bcb2d28563219cea33..04a8f910f9d56c9222c866c849fc8aa98cd3c6a5 100644 (file)
         </item>
         <item>
          <layout class="QGridLayout" name="offense_grid">
-          <item row="0" column="0">
-           <widget class="QPushButton" name="catch_">
+          <item row="1" column="2" colspan="2">
+           <widget class="QPushButton" name="goal">
             <property name="text">
-             <string>Catch/take (&amp;c)</string>
+             <string>Goal (&amp;g)</string>
             </property>
             <property name="shortcut">
-             <string>C</string>
+             <string>G</string>
             </property>
            </widget>
           </item>
-          <item row="0" column="1">
+          <item row="0" column="2" colspan="2">
            <widget class="QPushButton" name="throwaway">
             <property name="text">
              <string>Throwaway (&amp;t)</string>
             </property>
            </widget>
           </item>
-          <item row="1" column="0">
+          <item row="1" column="0" colspan="2">
            <widget class="QPushButton" name="drop">
             <property name="text">
              <string>Drop (&amp;x)</string>
             </property>
            </widget>
           </item>
-          <item row="1" column="1">
-           <widget class="QPushButton" name="goal">
+          <item row="0" column="0" colspan="2">
+           <widget class="QPushButton" name="catch_">
             <property name="text">
-             <string>Goal (&amp;g)</string>
+             <string>Catch/take (&amp;c)</string>
             </property>
             <property name="shortcut">
-             <string>G</string>
+             <string>C</string>
             </property>
            </widget>
           </item>
-          <item row="3" column="1">
-           <widget class="QPushButton" name="offensive_formation">
-            <property name="enabled">
-             <bool>true</bool>
-            </property>
+          <item row="4" column="1" colspan="2">
+           <widget class="QPushButton" name="stallout">
             <property name="text">
-             <string>Formation (&amp;o)</string>
+             <string>Stallout (&amp;u)</string>
+            </property>
+            <property name="shortcut">
+             <string>U</string>
             </property>
            </widget>
           </item>
-          <item row="3" column="0">
+          <item row="3" column="0" colspan="2">
            <widget class="QPushButton" name="pull_or_was_d">
             <property name="text">
              <string>Pull (&amp;p)</string>
             </property>
            </widget>
           </item>
+          <item row="3" column="2" colspan="2">
+           <widget class="QPushButton" name="offensive_formation">
+            <property name="enabled">
+             <bool>true</bool>
+            </property>
+            <property name="text">
+             <string>Formation (&amp;o)</string>
+            </property>
+           </widget>
+          </item>
          </layout>
         </item>
         <item>
index 32dd2493d539260fd12a2df4e77600e3cdd53bf1..cfcdf2e682772bb0625f6b3dfbe9404271d3f1cf 100644 (file)
@@ -175,6 +175,7 @@ function process_matches(json, filters) {
                        'throwaways': 0,
                        'drops': 0,
                        'was_ds': 0,
+                       'stallouts': 0,
 
                        'defenses': 0,
                        'interceptions': 0,
@@ -403,7 +404,7 @@ function process_matches(json, filters) {
 
                        // Offense/defense management
                        let last_offense = offense;
-                       if (type === 'set_defense' || type === 'goal' || type === 'throwaway' || type === 'drop' || type === 'was_d') {
+                       if (type === 'set_defense' || type === 'goal' || type === 'throwaway' || type === 'drop' || type === 'was_d' || type === 'stallout') {
                                offense = false;
                        } else if (type === 'set_offense' || type === 'their_goal' || type === 'their_throwaway' || type === 'defense' || type === 'interception') {
                                offense = true;
@@ -517,6 +518,9 @@ function process_matches(json, filters) {
                        } else if (type === 'drop') {
                                if (keep) ++p.drops;
                                handler = prev_handler = null;
+                       } else if (type === 'stallout') {
+                               if (keep) ++p.stallouts;
+                               handler = prev_handler = null;
                        } else if (type === 'was_d') {
                                if (keep) ++p.was_ds;
                                handler = prev_handler = null;
@@ -535,7 +539,7 @@ function process_matches(json, filters) {
                        } else if (type !== 'in' && type !== 'out' && type !== 'pull' &&
                                   type !== 'their_goal' && type !== 'stoppage' && type !== 'restart' && type !== 'unknown' &&
                                   type !== 'set_defense' && type !== 'goal' && type !== 'throwaway' &&
-                                  type !== 'drop' && type !== 'was_d' && type !== 'set_offense' && type !== 'their_goal' &&
+                                  type !== 'drop' && type !== 'was_d' && type !== 'stallout' && type !== 'set_offense' && type !== 'their_goal' &&
                                   type !== 'pull' && type !== 'pull_landed' && type !== 'pull_oob' && type !== 'their_pull' &&
                                   type !== 'their_throwaway' && type !== 'defense' && type !== 'interception' &&
                                   type !== 'formation_offense' && type !== 'formation_defense') {
@@ -742,7 +746,7 @@ function make_table_general(players) {
        for (const [q,p] of get_sorted_players(players)) {
                if (q === 'globals') continue;
                let row = document.createElement('tr');
-               let pm = p.goals + p.assists + p.hockey_assists + p.defenses - p.throwaways - p.drops - p.was_ds;
+               let pm = p.goals + p.assists + p.hockey_assists + p.defenses - p.throwaways - p.drops - p.was_ds - p.stallouts;
                let soft_pm = p.offensive_soft_plus + p.defensive_soft_plus - p.offensive_soft_minus - p.defensive_soft_minus;
                let o_efficiency = make_efficiency_ci(p.offensive_points_won, p.offensive_points_completed, z);
                let d_efficiency = make_efficiency_ci(p.defensive_points_won, p.defensive_points_completed, z);
@@ -787,6 +791,7 @@ function make_table_offense(players) {
                add_th(header, 'Drops');
                add_th(header, 'D-ed');
                add_th(header, '%OK');
+               add_th(header, 'Stalls');
                add_th(header, 'Soft +/-', 6);
                rows.push(header);
        }
@@ -796,6 +801,7 @@ function make_table_offense(players) {
        let catches = 0;
        let drops = 0;
        let was_ds = 0;
+       let stallouts = 0;
        for (const [q,p] of get_sorted_players(players)) {
                if (q === 'globals') continue;
                let throw_ok = make_binomial_ci(p.num_throws - p.throwaways, p.num_throws, z);
@@ -820,6 +826,7 @@ function make_table_offense(players) {
                add_3cell(row, p.drops);
                add_3cell(row, p.was_ds);
                add_3cell_ci(row, catch_ok);
+               add_3cell(row, p.stallouts);
                add_3cell(row, '+' + p.offensive_soft_plus);
                add_3cell(row, '-' + p.offensive_soft_minus);
                row.dataset.player = q;
@@ -830,6 +837,7 @@ function make_table_offense(players) {
                catches += p.catches;
                drops += p.drops;
                was_ds += p.was_ds;
+               stallouts += p.stallouts;
        }
 
        // Globals.
@@ -852,6 +860,7 @@ function make_table_offense(players) {
        add_3cell(row, drops);
        add_3cell(row, was_ds);
        add_3cell_ci(row, catch_ok);
+       add_3cell(row, stallouts);
        add_3cell(row, '');
        add_3cell(row, '');
        rows.push(row);
@@ -1445,7 +1454,7 @@ function should_reuse_last_formation(events, t) {
                if (type === 'their_goal' || type === 'goal' ||
                    type === 'set_defense' || type === 'set_offense' ||
                    type === 'throwaway' || type === 'their_throwaway' ||
-                   type === 'drop' || type === 'defense' || type === 'interception' ||
+                   type === 'drop' || type === 'was_d' || type === 'stallout' || type === 'defense' || type === 'interception' ||
                    type === 'pull' || type === 'pull_landed' || type === 'pull_oob' || type === 'their_pull' ||
                    type === 'formation_offense' || type === 'formation_defense') {
                        return false;