.then(response => response.json())
.then(response => { global_json = response; process_matches(global_json, global_filters); });
+function format_time(t)
+{
+ const ms = t % 1000 + '';
+ t = Math.floor(t / 1000);
+ const sec = t % 60 + '';
+ t = Math.floor(t / 60);
+ const min = t % 60 + '';
+ const hour = Math.floor(t / 60) + '';
+ return hour + ':' + min.padStart(2, '0') + ':' + sec.padStart(2, '0') + '.' + ms.padStart(3, '0');
+}
+
function attribute_player_time(player, to, from, offense) {
let delta_time;
if (player.on_field_since > from) {
'throwaways': 0,
'drops': 0,
'was_ds': 0,
+ 'stallouts': 0,
'defenses': 0,
- 'interceptions': 0,
'points_played': 0,
'playing_time_ms': 0,
'offensive_playing_time_ms': 0,
live_since = t;
} else if (type === 'catch' && last_pull_was_ours === null) {
// Someone forgot to add the pull, so we'll need to wing it.
- console.log('Missing pull on ' + our_score + '\u2013' + their_score + ' in ' + match['description'] + '; pretending to have one.');
+ console.log(match['description'] + ' ' + format_time(t) + ': Missing pull on ' + our_score + '\u2013' + their_score + '; pretending to have one.');
live_since = t;
last_pull_was_ours = !offense;
} else if (type === 'goal' || type === 'their_goal' || type === 'stoppage') {
// 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;
}
}
+ if (type !== 'out' && type !== 'in' && p !== undefined && p.on_field_since === null) {
+ console.log(match['description'] + ' ' + format_time(t) + ': Event “' + type + '” on subbed-out player ' + p.name);
+ }
+ if (type === 'catch' && handler !== null && players[handler].on_field_since === null) {
+ // The handler subbed out and was replaced with another handler,
+ // so this wasn't a pass.
+ console.log(match['description'] + ' ' + format_time(t) + ': Disc came from subbed-out player ' + players[handler].name + '; not counting a pass.');
+ handler = null;
+ }
+
// Event management
if (type === 'catch' || type === 'goal') {
if (handler !== null) {
} 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;
if (keep) ++p.defenses;
} else if (type === 'interception') {
if (keep) {
- ++p.interceptions;
+ ++p.catches;
++p.defenses;
++p.touches;
}
} 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') {
- console.log("Unknown event:", e);
+ console.log(format_time(t) + ": Unknown event “" + e + "”");
}
if (type === 'goal' || type === 'their_goal') {
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);
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);
}
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);
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;
catches += p.catches;
drops += p.drops;
was_ds += p.was_ds;
+ stallouts += p.stallouts;
}
// Globals.
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);
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;