]> git.sesse.net Git - pkanalytics/commitdiff
Implement O and D efficiency in the viewer.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 10 May 2023 19:21:51 +0000 (21:21 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 10 May 2023 19:21:51 +0000 (21:21 +0200)
ultimate.js

index 3b72f019737a0ff3b3f1e79152e371cd3269e40a..330bdd6f44ada5ee46dd3ba0f3e37b7981d9654a 100644 (file)
@@ -54,6 +54,12 @@ function process_matches(json) {
                        'points_played': 0,
                        'playing_time_ms': 0,
 
+                       // For efficiency.
+                       'offensive_points_completed': 0,
+                       'offensive_points_won': 0,
+                       'defensive_points_completed': 0,
+                       'defensive_points_won': 0,
+
                        'offensive_soft_plus': 0,
                        'offensive_soft_minus': 0,
                        'defensive_soft_plus': 0,
@@ -76,6 +82,7 @@ function process_matches(json) {
                let offense = null;
                let puller = null;
                let pull_started = null;
+               let last_pull_was_ours = null;  // Effectively whether we're playing an O or D point (not affected by turnovers).
                let point_num = 0;
                for (const [q,p] of Object.entries(players)) {
                        p.on_field_since = null;
@@ -98,14 +105,27 @@ function process_matches(json) {
                                live_since = t;
                        } else if (type === 'goal' || type === 'their_goal' || type === 'stoppage') {
                                for (const [q,p] of Object.entries(players)) {
-                                       if (p.on_field_since !== null) {
-                                               if (p.last_point_seen !== point_num) {
-                                                       // In case the player did nothing this point,
-                                                       // not even subbing in.
-                                                       p.last_point_seen = point_num;
-                                                       ++p.points_played;
+                                       if (p.on_field_since === null) {
+                                               continue;
+                                       }
+                                       if (p.last_point_seen !== point_num) {
+                                               // In case the player did nothing this point,
+                                               // not even subbing in.
+                                               p.last_point_seen = point_num;
+                                               ++p.points_played;
+                                       }
+                                       attribute_player_time(p, t, live_since);
+
+                                       if (last_pull_was_ours === true) {  // D point.
+                                               ++p.defensive_points_completed;
+                                               if (type === 'goal') {
+                                                       ++p.defensive_points_won;
+                                               }
+                                       } else if (last_pull_was_ours === false) {  // O point.
+                                               ++p.offensive_points_completed;
+                                               if (type === 'goal') {
+                                                       ++p.offensive_points_won;
                                                }
-                                               attribute_player_time(p, t, live_since);
                                        }
                                }
                                live_since = null;
@@ -142,6 +162,25 @@ function process_matches(json) {
                        } else if (type === 'set_offense' || type === 'their_goal' || type === 'their_throwaway' || type === 'defense' || type === 'interception') {
                                offense = true;
                        }
+                       if (type === 'pull') {
+                               last_pull_was_ours = true;
+                       } else if (type === 'their_pull') {
+                               last_pull_was_ours = false;
+                       } else if (type === 'set_offense' && last_pull_was_ours === null) {
+                               // set_offense could either be “changed to offense for some reason
+                               // we could not express”, or “we started in the middle of a point,
+                               // and we are offense”. We assume that if we already saw the pull,
+                               // it's the former, and if not, it's the latter; thus, the === null
+                               // test above. (It could also be “we set offense before the pull,
+                               // so that we get the right button enabled”, in which case it will
+                               // be overwritten by the next pull/their_pull event anyway.)
+                               last_pull_was_ours = false;
+                       } else if (type === 'set_defense' && last_pull_was_ours === null) {
+                               // Similar.
+                               last_pull_was_ours = true;
+                       } else if (type === 'goal' || type === 'their_goal') {
+                               last_pull_was_ours = null;
+                       }
 
                        // Event management
                        if (type === 'catch' || type === 'goal') {
@@ -258,6 +297,8 @@ function make_table_general(players) {
                add_cell(header, 'th', 'Player');
                add_cell(header, 'th', '+/-');
                add_cell(header, 'th', 'Soft +/-');
+               add_cell(header, 'th', 'O efficiency');
+               add_cell(header, 'th', 'D efficiency');
                add_cell(header, 'th', 'Points played');
                add_cell(header, 'th', 'Time played');
                rows.push(header);
@@ -267,9 +308,13 @@ function make_table_general(players) {
                let row = document.createElement('tr');
                let pm = p.goals + p.assists + p.hockey_assists + p.defenses - p.throwaways - p.drops;
                let soft_pm = p.offensive_soft_plus + p.defensive_soft_plus - p.offensive_soft_minus - p.defensive_soft_minus;
+               let o_efficiency = (p.offensive_points_won / p.offensive_points_completed) * 2 - 1;
+               let d_efficiency = (p.defensive_points_won / p.defensive_points_completed) * 2 - 1;
                add_cell(row, 'td', p.name);  // TODO: number?
                add_cell(row, 'td', pm > 0 ? ('+' + pm) : pm);
                add_cell(row, 'td', soft_pm > 0 ? ('+' + soft_pm) : soft_pm);
+               add_cell(row, 'td', p.offensive_points_completed > 0 ? o_efficiency.toFixed(2) : 'N/A');
+               add_cell(row, 'td', p.defensive_points_completed > 0 ? d_efficiency.toFixed(2) : 'N/A');
                add_cell(row, 'td', p.points_played);
                add_cell(row, 'td', Math.floor(p.playing_time_ms / 60000) + ' min');
                rows.push(row);