// ========================================================================= // 5. SPECIAL: Player Profile - /profile/ // ========================================================================= add_shortcode('otg_player_profile', 'otg_render_player_profile'); function otg_render_player_filter_dropdown() { global $wpdb; // Fetch all players sorted alphabetically $all_players = $wpdb->get_results(" SELECT ID, Name FROM otg_players ORDER BY Name ASC "); $current_player_id = isset($_GET['player_id']) ? intval($_GET['player_id']) : 0; $html = '
'; $html .= '
'; $html .= ''; $html .= '
'; $html .= '
'; return $html; } function otg_render_player_profile($atts) { global $wpdb; $a = shortcode_atts(array('id' => 0), $atts, 'otg_player_profile'); $player_id = isset($_GET['player_id']) ? intval($_GET['player_id']) : intval($a['id']); // Always render the player selection dropdown box at the top $html = otg_render_player_filter_dropdown(); if (!$player_id) { return $html . "Player ID required."; } $p = $wpdb->get_row($wpdb->prepare("SELECT * FROM otg_players WHERE ID = %d", $player_id)); if (!$p) return $html . "Player not found."; $game_type = isset($_GET['game_type']) ? intval($_GET['game_type']) : 2; // Updated CSS: Simplified background rules for NYR (dark blue), NHL (dark grey), and Other (black/darker grey) + Last 10 Form Box Styles + DNP Tiles + Milestones Card Header Wrapper $html .= ''; // Render Bio Card First $html .= otg_render_player_bio($p); // Check if player has played any regular season games for the Rangers $has_played_for_rangers = false; $is_goalie = ($p->Position === 'Goaltender'); if (!empty($p->nhl_id)) { $rangers_gp_count = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(*) FROM otg_rangers_player_boxscores b JOIN otg_rangers_games g ON b.game_id = g.game_id WHERE b.player_id = %d AND g.game_state IS NULL AND g.game_type = 2 ", $p->nhl_id)); if (intval($rangers_gp_count) > 0) { $has_played_for_rangers = true; } } // --- Active Player Milestone Progress Banner & Milestones Matrix (Rendered only if they have played for Rangers) --- if ($has_played_for_rangers && isset($p->is_active) && intval($p->is_active) === 1 && !empty($p->nhl_id)) { // Open the container card with the "Next Rangers Milestones" header row (using h4) $html .= '
'; $html .= '

Next Rangers Milestones

'; if (!$is_goalie) { $all_boxscores = $wpdb->get_results($wpdb->prepare(" SELECT g.game_id, b.goals, b.assists, b.points FROM otg_rangers_player_boxscores b JOIN otg_rangers_games g ON b.game_id = g.game_id WHERE b.player_id = %d AND g.game_state IS NULL AND g.game_type = 2 ORDER BY g.game_date ASC, g.game_id ASC ", $p->nhl_id)); $curr_gp = count($all_boxscores); $curr_g = 0; $curr_a = 0; $curr_p = 0; foreach ($all_boxscores as $bs) { $curr_g += intval($bs->goals); $curr_a += intval($bs->assists); $curr_p += intval($bs->points); } $next_gp = (floor($curr_gp / 100) + 1) * 100; $next_g = (floor($curr_g / 100) + 1) * 100; $next_a = (floor($curr_a / 100) + 1) * 100; $next_p = (floor($curr_p / 100) + 1) * 100; $away_gp = $next_gp - $curr_gp; $away_g = $next_g - $curr_g; $away_a = $next_a - $curr_a; $away_p = $next_p - $curr_p; $html .= '
'; $html .= '
Games Played
'.number_format($away_gp).' away from '.number_format($next_gp).'
'; $html .= '
Goals
'.number_format($away_g).' away from '.number_format($next_g).'
'; $html .= '
Assists
'.number_format($away_a).' away from '.number_format($next_a).'
'; $html .= '
Points
'.number_format($away_p).' away from '.number_format($next_p).'
'; $html .= '
'; } else { $all_boxscores = $wpdb->get_results($wpdb->prepare(" SELECT g.game_id, b.decision, b.time_on_ice FROM otg_rangers_player_boxscores b JOIN otg_rangers_games g ON b.game_id = g.game_id WHERE b.player_id = %d AND g.game_state IS NULL AND g.game_type = 2 ORDER BY g.game_date ASC, g.game_id ASC ", $p->nhl_id)); $curr_gp = 0; $curr_gs = 0; $curr_w = 0; foreach ($all_boxscores as $bs) { $toi_val = $bs->time_on_ice; $toi_sec = is_numeric($toi_val) ? floatval($toi_val) : (function_exists('toi_to_seconds') ? toi_to_seconds($toi_val) : 0); if ($toi_sec > 0) { $curr_gp += 1; $curr_gs += 1; if (isset($bs->decision) && strtoupper(trim($bs->decision)) === 'W') { $curr_w += 1; } } } $next_gp = (floor($curr_gp / 100) + 1) * 100; $next_gs = (floor($curr_gs / 100) + 1) * 100; $next_w = (floor($curr_w / 100) + 1) * 100; $away_gp = $next_gp - $curr_gp; $away_gs = $next_gs - $curr_gs; $away_w = $next_w - $curr_w; $html .= '
'; $html .= '
Games Played
'.number_format($away_gp).' away from '.number_format($next_gp).'
'; $html .= '
Games Started
'.number_format($away_gs).' away from '.number_format($next_gs).'
'; $html .= '
Wins
'.number_format($away_w).' away from '.number_format($next_w).'
'; $html .= '
'; } // Close the container card $html .= '
'; } // --- Last 10 Games Logic (Skaters & Goaltenders) --- $is_active_player = isset($p->is_active) && intval($p->is_active) === 1; $player_status_val = trim($p->Status ?? $p->status ?? ''); if ($is_active_player && strcasecmp($player_status_val, 'Rangers') === 0 && !empty($p->nhl_id)) { if (!$is_goalie) { $last_10_games = $wpdb->get_results($wpdb->prepare(" SELECT g.game_id, g.game_date, g.is_home, g.opponent_abbr, g.game_state, b.goals, b.assists, b.points, b.shots, b.pim, b.plus_minus, b.player_id AS played_in_game FROM otg_rangers_games g LEFT JOIN otg_rangers_player_boxscores b ON g.game_id = b.game_id AND b.player_id = %d WHERE g.game_state IS NULL AND g.game_type IN (2, 3) ORDER BY g.game_date DESC, g.game_id DESC LIMIT 10 ", $p->nhl_id)); if (!empty($last_10_games)) { $last_10_games = array_reverse($last_10_games); $l10_total_pts = 0; $l10_total_g = 0; $l10_total_a = 0; $l10_total_shots = 0; foreach ($last_10_games as $g_stat) { if (!empty($g_stat->played_in_game)) { $l10_total_pts += intval($g_stat->points); $l10_total_g += intval($g_stat->goals); $l10_total_a += intval($g_stat->assists); $l10_total_shots += intval($g_stat->shots); } } $html .= '
'; $html .= '
Recent Form • Last ' . count($last_10_games) . ' Games
'; $html .= '
'; $html .= '
' . $l10_total_pts . ' pts • ' . $l10_total_g . ' G • ' . $l10_total_a . ' A • ' . $l10_total_shots . ' shots in last ' . count($last_10_games) . '
'; $html .= '
'; $html .= '
'; foreach ($last_10_games as $gs) { $prefix = ($gs->is_home == 1) ? '' : '@ '; $opp_label = $prefix . esc_html($gs->opponent_abbr); $did_play = !empty($gs->played_in_game); if (!$did_play) { $tile_class = 'otg-l10-tile did-not-play'; } else { $is_high_impact = (intval($gs->points) >= 3); $tile_class = $is_high_impact ? 'otg-l10-tile highlighted' : 'otg-l10-tile'; } $game_date_formatted = date('M j', strtotime($gs->game_date)); $box_link = '/box/?game_id=' . esc_attr($gs->game_id); $html .= '
'; $html .= ''; if ($did_play) { $shot_val = intval($gs->shots); $underline_opacity = min(1.0, max(0.2, $shot_val / 8)); $html .= '
'.intval($gs->points).' Pts
'; $html .= '
'.intval($gs->goals).'G '.intval($gs->assists).'A
'; $html .= '
'.$shot_val.' SOG
'; if ($shot_val > 0) { $html .= '
'; } } else { $html .= '
DNP
'; $html .= '
-
'; } $html .= '
'; } $html .= '
'; $html .= '
'; } } else { $last_10_games = $wpdb->get_results($wpdb->prepare(" SELECT g.game_id, g.game_date, g.is_home, g.opponent_abbr, g.game_state, b.decision, b.goals_against, b.shots_against, b.time_on_ice, b.player_id AS played_in_game FROM otg_rangers_games g LEFT JOIN otg_rangers_player_boxscores b ON g.game_id = b.game_id AND b.player_id = %d WHERE g.game_state IS NULL AND g.game_type IN (2, 3) ORDER BY g.game_date DESC, g.game_id DESC LIMIT 10 ", $p->nhl_id)); if (!empty($last_10_games)) { $last_10_games = array_reverse($last_10_games); $l10_wins = 0; $l10_losses = 0; $l10_ot = 0; $l10_sa = 0; $l10_ga = 0; $l10_sv = 0; $l10_min_sec = 0; foreach ($last_10_games as $g_stat) { $toi_val = $g_stat->time_on_ice; $toi_sec = is_numeric($toi_val) ? floatval($toi_val) : (function_exists('toi_to_seconds') ? toi_to_seconds($toi_val) : 0); if (!empty($g_stat->played_in_game) && $toi_sec > 0) { $dec = strtoupper(trim($g_stat->decision ?? '')); if ($dec === 'W') $l10_wins++; elseif ($dec === 'L') $l10_losses++; elseif ($dec === 'O' || $dec === 'T') $l10_ot++; $l10_sa += intval($g_stat->shots_against); $l10_ga += intval($g_stat->goals_against); $l10_min_sec += $toi_sec; } } $l10_sv = $l10_sa - $l10_ga; $l10_svp = ($l10_sa > 0) ? number_format(($l10_sv / $l10_sa), 3) : '.000'; $l10_hours = $l10_min_sec / 3600; $l10_gaa = ($l10_hours > 0) ? number_format(($l10_ga / $l10_hours), 2) : '0.00'; $html .= '
'; $html .= '
Recent Form • Last ' . count($last_10_games) . ' Games
'; $html .= '
'; $html .= '
' . $l10_wins . '-' . $l10_losses . '-' . $l10_ot . ' • ' . $l10_svp . ' SV% • ' . $l10_gaa . ' GAA • ' . $l10_sa . ' SA in last ' . count($last_10_games) . '
'; $html .= '
'; $html .= '
'; foreach ($last_10_games as $gs) { $prefix = ($gs->is_home == 1) ? '' : '@ '; $opp_label = $prefix . esc_html($gs->opponent_abbr); $did_play = false; if (!empty($gs->played_in_game)) { $toi_val = $gs->time_on_ice; $toi_sec = is_numeric($toi_val) ? floatval($toi_val) : (function_exists('toi_to_seconds') ? toi_to_seconds($toi_val) : 0); if ($toi_sec > 0) { $did_play = true; } } if (!$did_play) { $tile_class = 'otg-l10-tile did-not-play'; } else { $dec = strtoupper(trim($gs->decision ?? '')); $is_win = ($dec === 'W'); $tile_class = $is_win ? 'otg-l10-tile highlighted' : 'otg-l10-tile'; } $game_date_formatted = date('M j', strtotime($gs->game_date)); $box_link = '/box/?game_id=' . esc_attr($gs->game_id); $html .= '
'; $html .= ''; if ($did_play) { $sa = intval($gs->shots_against); $ga = intval($gs->goals_against); $sv = $sa - $ga; $dec_label = !empty($gs->decision) ? $gs->decision : '-'; $tile_svp = ($sa > 0) ? number_format(($sv / $sa), 3) : '.000'; $toi_g = $gs->time_on_ice; $toi_sec_g = is_numeric($toi_g) ? floatval($toi_g) : (function_exists('toi_to_seconds') ? toi_to_seconds($toi_g) : 0); $tile_hours = $toi_sec_g / 3600; $tile_gaa = ($tile_hours > 0) ? number_format(($ga / $tile_hours), 2) : '0.00'; $html .= '
'.esc_html($dec_label).' • '.$tile_svp.'
'; $html .= '
'.$tile_gaa.' GAA • '.$sa.' SA
'; } else { $html .= '
DNP
'; $html .= '
-
'; } $html .= '
'; } $html .= '
'; $html .= '
'; } } } $stats_table = $is_goalie ? 'otg_goalie_seasonal_stats' : 'otg_player_seasonal_stats'; $stats = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$stats_table} WHERE nhl_id = %d AND game_type_id = %d ORDER BY season ASC", $p->nhl_id, $game_type)); $calc_age = function($season_string, $birthday) { if (empty($birthday) || $birthday === '1800-01-01') return '-'; $year_str = substr($season_string, 0, 4); if (!is_numeric($year_str)) return '-'; $dec_31 = new DateTime($year_str . '-12-31'); $bday = new DateTime($birthday); if ($bday > $dec_31) return '-'; return $bday->diff($dec_31)->y; }; if (!empty($stats)) { $html .= '

Statistics

'; $html .= '
'; $html .= '
'; $html .= '
'; $html .= 'Regular Season'; $html .= 'Playoffs'; $html .= '
'; $html .= '
'; $html .= '
'; $td_style = 'padding: 4px 6px; border-bottom: 1px solid rgba(255,255,255,0.05); vertical-align: middle; line-height: 1.2;'; $th_style = 'padding: 8px 6px; border-bottom: 2px solid #555; background-color: #1a1a1a; color: #fff; text-transform: uppercase; font-size: 0.9em;'; if ($is_goalie) { // 1. Header for Goaltenders (Including GS column) $html .= ''; // 2. Data Rows & Aggregation for Goaltenders $totals = [ 'NHL' => ['GP' => 0, 'GS' => 0, 'W' => 0, 'L' => 0, 'TOT' => 0, 'MIN' => 0, 'SO' => 0, 'GA' => 0, 'SA' => 0, 'G' => 0, 'A' => 0, 'PIM' => 0], 'NYR' => ['GP' => 0, 'GS' => 0, 'W' => 0, 'L' => 0, 'TOT' => 0, 'MIN' => 0, 'SO' => 0, 'GA' => 0, 'SA' => 0, 'G' => 0, 'A' => 0, 'PIM' => 0] ]; $highs = ['GS'=>0, 'W'=>0, 'L'=>0, 'SO'=>0, 'SV_PCT'=>0, 'GAA'=>99, 'G'=>0, 'A'=>0, 'PIM'=>0, 'GP'=>0, 'TOT'=>0, 'MIN'=>0, 'GA'=>0, 'SV'=>0, 'SA'=>0]; $count = 0; // Helper function to convert MM:SS or HHH:SS to total seconds if not already defined if (!function_exists('toi_to_seconds_local')) { function toi_to_seconds_local($toi) { if (empty($toi)) return 0; if (is_numeric($toi)) return (int)$toi; $parts = explode(':', $toi); if (count($parts) === 2) { return ((int)$parts[0] * 60) + (int)$parts[1]; } return 0; } } foreach ($stats as $s) { $games_started = (isset($s->games_started) && is_numeric($s->games_started)) ? (int)$s->games_started : 0; $losses = (isset($s->losses) && is_numeric($s->losses)) ? (int)$s->losses : 0; $ties = (isset($s->ties) && is_numeric($s->ties)) ? (int)$s->ties : 0; $ot_losses = (isset($s->ot_losses) && is_numeric($s->ot_losses)) ? (int)$s->ot_losses : 0; $shots_against = (isset($s->shots_against) && is_numeric($s->shots_against)) ? (float)$s->shots_against : 0; $goals_against = (isset($s->goals_against) && is_numeric($s->goals_against)) ? (float)$s->goals_against : 0; $tot = $ties + $ot_losses; $sv = $shots_against - $goals_against; $y1 = substr($s->season, 0, 4); $y2 = str_pad((int)substr($s->season, 0, 4) + 1, 4, '0', STR_PAD_LEFT); $disp_season = $y1 . '-' . substr($y2, 2, 2); $player_age = $calc_age($s->season, $p->Birthday); $is_nhl = ($s->league_name === 'NHL'); // Fixed: Explicitly evaluating team_name for New York Rangers rows in otg_goalie_season_stats $is_nyr = (trim($s->team_name) === 'New York Rangers' && $is_nhl); $row_classes = 'league-' . ($is_nhl ? 'nhl' : 'other'); if ($is_nyr) { $row_classes .= ' team-nyr'; } $display = ($is_nhl || $is_nyr) ? '' : 'display: none;'; $html .= ''; // Aggregation if ($is_nhl) { $t = &$totals['NHL']; $t['GP'] += (int)$s->games_played; $t['GS'] += $games_started; $t['W'] += (int)$s->wins; $t['L'] += $losses; $t['TOT'] += $tot; $t['MIN'] += toi_to_seconds_local($s->time_on_ice); $t['SO'] += (int)$s->shutouts; $t['GA'] += (float)$s->goals_against; $t['SA'] += (float)$s->shots_against; $t['G'] += (int)$s->goals; $t['A'] += (int)$s->assists; $t['PIM'] += (int)$s->pim; } if ($is_nyr) { $t = &$totals['NYR']; $t['GP'] += (int)$s->games_played; $t['GS'] += $games_started; $t['W'] += (int)$s->wins; $t['L'] += $losses; $t['TOT'] += $tot; $t['MIN'] += toi_to_seconds_local($s->time_on_ice); $t['SO'] += (int)$s->shutouts; $t['GA'] += (float)$s->goals_against; $t['SA'] += (float)$s->shots_against; $t['G'] += (int)$s->goals; $t['A'] += (int)$s->assists; $t['PIM'] += (int)$s->pim; } // Track Highs (NHL Only) if ($is_nhl) { $count++; $current_gaa = ($s->time_on_ice > 0) ? ($s->goals_against / ($s->time_on_ice / 60)) : 0; $highs['GP'] = max($highs['GP'], (int)$s->games_played); $highs['GS'] = max($highs['GS'], (int)$games_started); $highs['W'] = max($highs['W'], (int)$s->wins); $highs['L'] = max($highs['L'], (int)$losses); $highs['TOT'] = max($highs['TOT'], (int)($s->ties + $s->ot_losses)); $highs['SO'] = max($highs['SO'], (int)$s->shutouts); $highs['GA'] = max($highs['GA'], (int)$s->goals_against); $highs['G'] = max($highs['G'], (int)$s->goals); $highs['A'] = max($highs['A'], (int)$s->assists); $highs['PIM'] = max($highs['PIM'], (int)$s->pim); $highs['SV_PCT'] = max($highs['SV_PCT'], (float)$s->save_pctg); $highs['MIN'] = max($highs['MIN'], function_exists('toi_to_seconds') ? toi_to_seconds($s->time_on_ice) : 0); $highs['SV'] = max($highs['SV'], (int)$sv); $highs['SA'] = max($highs['SA'], (int)$s->shots_against); if ($current_gaa > 0) { $highs['GAA'] = ($highs['GAA'] === 99.00) ? $current_gaa : min($highs['GAA'], $current_gaa); } } } // 3. Summary Rows with Separator for Goaltenders $f = 'padding: 7px 4px; font-weight: bold; text-align: center;'; $fl = 'padding: 7px 4px; font-weight: bold; text-align: left;'; $html .= ''; $labels_map = [ 'NHL' => 'NHL Career Totals', 'NYR' => 'NYR Career Totals' ]; foreach (['NHL', 'NYR'] as $scope) { if (!empty($totals[$scope]) && $totals[$scope]['GP'] > 0) { $t = $totals[$scope]; $row_class = ($scope === 'NYR') ? 'summary-row-nyr' : 'summary-row-nhl'; $sv = $t['SA'] - $t['GA']; $total_minutes = $t['MIN'] / 60; $gaa = ($total_minutes > 0) ? ($t['GA'] / ($total_minutes / 60)) : 0; $svp = ($t['SA'] > 0) ? ($sv / $t['SA']) : 0; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; } } // Career Highs & Averages for Goaltenders $html .= ''; if ($count > 0 && !empty($totals['NHL'])) { $t = $totals['NHL']; $avg_gp = round($t['GP'] / $count); $avg_gs = round($t['GS'] / $count); $avg_w = round($t['W'] / $count); $avg_l = round($t['L'] / $count); $avg_tot = round($t['TOT'] / $count); $avg_min_sec = function_exists('format_seconds_to_toi') ? format_seconds_to_toi(floor($t['MIN'] / $count)) : floor($t['MIN'] / $count); $avg_so = round($t['SO'] / $count); $avg_ga = round($t['GA'] / $count); $avg_sv = round(($t['SA'] - $t['GA']) / $count); $avg_sa = round($t['SA'] / $count); $total_minutes = $t['MIN'] / 60; $gaa = ($total_minutes > 0) ? ($t['GA'] / ($total_minutes / 60)) : 0; $svp = ($t['SA'] > 0) ? (($t['SA'] - $t['GA']) / $t['SA']) : 0; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; } } else { $html .= ''; foreach ($stats as $s) { $y1 = substr($s->season, 0, 4); $y2 = str_pad((int)substr($s->season, 0, 4) + 1, 4, '0', STR_PAD_LEFT); $disp_season = $y1 . '-' . substr($y2, 2, 2); $player_age = $calc_age($s->season, $p->Birthday); $is_nhl = ($s->league_name === 'NHL'); $is_nyr = ($s->team_name === 'New York Rangers'); $row_classes = 'league-' . ($is_nhl ? 'nhl' : 'other'); if ($is_nyr) { $row_classes .= ' team-nyr'; } $display = ($is_nhl || $is_nyr) ? '' : 'display: none;'; $pm = ($s->plus_minus > 0) ? '+' . $s->plus_minus : $s->plus_minus; $html .= ''; } $nhl_stats = array_filter($stats, function($s) { return ($s->league_name === 'NHL'); }); $nyr_stats = array_filter($stats, function($s) { return ($s->team_name === 'New York Rangers' && $s->league_name === 'NHL'); }); function get_stats_data($data_set) { $res = ['GP' => 0, 'G' => 0, 'A' => 0, 'P' => 0, 'PIM' => 0, '+/-' => 0, 'PPG' => 0, 'PPP' => 0, 'SHG' => 0, 'SHP' => 0, 'OTG' => 0, 'GWG' => 0, 'S' => 0, 'TOI_SEC' => 0]; $highs = ['G' => 0, 'A' => 0, 'P' => 0, 'PIM' => 0, 'plus_minus' => -100, 'PPG' => 0, 'PPP' => 0, 'SHG' => 0, 'SHP' => 0, 'OTG' => 0, 'GWG' => 0, 'S' => 0, 'TOI_SEC' => 0]; foreach ($data_set as $s) { $res['GP'] += $s->games_played; $res['G'] += $s->goals; $res['A'] += $s->assists; $res['P'] += $s->points; $res['PIM'] += $s->pim; $res['+/-'] += $s->plus_minus; $res['PPG'] += $s->power_play_goals; $res['PPP'] += $s->power_play_points; $res['SHG'] += $s->shorthanded_goals; $res['SHP'] += $s->shorthanded_points; $res['OTG'] += $s->ot_goals; $res['GWG'] += $s->game_winning_goals; $res['S'] += $s->shots; list($m, $ss) = explode(':', $s->avg_toi); $res['TOI_SEC'] += ($m * 60) + $ss; if ($s->goals > $highs['G']) $highs['G'] = $s->goals; if ($s->assists > $highs['A']) $highs['A'] = $s->assists; if ($s->points > $highs['P']) $highs['P'] = $s->points; if ($s->pim > $highs['PIM']) $highs['PIM'] = $s->pim; if ($s->plus_minus > $highs['plus_minus']) $highs['plus_minus'] = $s->plus_minus; if ($s->power_play_goals > $highs['PPG']) $highs['PPG'] = $s->power_play_goals; if ($s->power_play_points > $highs['PPP']) $highs['PPP'] = $s->power_play_points; if ($s->shorthanded_goals > $highs['SHG']) $highs['SHG'] = $s->shorthanded_goals; if ($s->shorthanded_points > $highs['SHP']) $highs['SHP'] = $s->shorthanded_points; if ($s->ot_goals > $highs['OTG']) $highs['OTG'] = $s->ot_goals; if ($s->game_winning_goals > $highs['GWG']) $highs['GWG'] = $s->game_winning_goals; if ($s->shots > $highs['S']) $highs['S'] = $s->shots; $toi_total = ($m * 60) + $ss; if ($toi_total > $highs['TOI_SEC']) $highs['TOI_SEC'] = $toi_total; } return [$res, $highs]; } if (!empty($nhl_stats)) { list($nhl_tot, $nhl_high) = get_stats_data($nhl_stats); list($nyr_tot, $nyr_high) = get_stats_data($nyr_stats); $count = count($nhl_stats); $f = 'padding: 7px 4px; font-weight: bold; vertical-align: middle; text-align: center;'; $fl = 'padding: 7px 4px; font-weight: bold; vertical-align: middle; text-align: left;'; $html .= ''; $html .= ''; if (!empty($nyr_stats)) { $html .= ''; } $avg_m = floor(($nhl_tot['TOI_SEC'] / $count) / 60); $avg_s = str_pad(round(fmod(($nhl_tot['TOI_SEC'] / $count), 60)), 2, '0', STR_PAD_LEFT); $html .= ''; $high_m = floor(($nhl_high['TOI_SEC']) / 60); $high_s = str_pad(round(fmod($nhl_high['TOI_SEC'], 60)), 2, '0', STR_PAD_LEFT); $html .= ''; } } $html .= '
Season Age Team League GP GS W L T/OT MIN SO GA SV SA GAA Sv% G A PIM
'.esc_html($disp_season).' '.esc_html($player_age).' '.esc_html($s->team_name).' '.esc_html($s->league_name).' '.esc_html($s->games_played).' '.esc_html($games_started).' '.esc_html($s->wins).' '.esc_html($losses).' '.esc_html($tot).' '.esc_html($s->time_on_ice).' '.esc_html($s->shutouts).' '.esc_html($s->goals_against).' '.esc_html($sv).' '.esc_html($s->shots_against).' '.number_format($s->goals_against_avg, 2).' '.number_format($s->save_pctg, 3).' '.esc_html($s->goals).' '.esc_html($s->assists).' '.esc_html($s->pim).'
'.$labels_map[$scope].''.($scope === 'NYR' ? 'NHL' : 'NHL').''.$t['GP'].''.$t['GS'].''.$t['W'].''.$t['L'].''.$t['TOT'].''.(function_exists('format_seconds_to_toi') ? esc_html(format_seconds_to_toi($t['MIN'])) : $t['MIN']).''.$t['SO'].''.$t['GA'].''.$sv.''.$t['SA'].''.number_format($gaa, 2).''.number_format($svp, 3).''.$t['G'].''.$t['A'].''.$t['PIM'].'
NHL Career Highs NHL '.$highs['GP'].' '.$highs['GS'].' '.$highs['W'].' '.$highs['L'].' '.$highs['TOT'].' '.(function_exists('format_seconds_to_toi') ? format_seconds_to_toi($highs['MIN']) : $highs['MIN']).' '.$highs['SO'].' '.$highs['GA'].' '.$highs['SV'].' '.$highs['SA'].' '.number_format($highs['GAA'], 2).' '.number_format($highs['SV_PCT'], 3).' '.$highs['G'].' '.$highs['A'].' '.$highs['PIM'].'
NHL Career AveragesNHL'.$avg_gp.''.$avg_gs.''.$avg_w.''.$avg_l.''.$avg_tot.''.$avg_min_sec.''.$avg_so.''.$avg_ga.''.$avg_sv.''.$avg_sa.''.number_format($gaa, 2).''.number_format($svp, 3).''.round($t['G'] / $count).''.round($t['A'] / $count).''.round($t['PIM'] / $count).'
SeasonAgeTeamLeagueGPGAPPIM+/-PPGPPPSHGSHPOTGGWGSS%FO%TOI
'.esc_html($disp_season).''.esc_html($player_age).''.esc_html($s->team_name).''.esc_html($s->league_name).''.esc_html($s->games_played).''.esc_html($s->goals).''.esc_html($s->assists).''.esc_html($s->points).''.esc_html($s->pim).''.$pm.''.esc_html($s->power_play_goals).''.esc_html($s->power_play_points).''.esc_html($s->shorthanded_goals).''.esc_html($s->shorthanded_points).''.esc_html($s->ot_goals).''.esc_html($s->game_winning_goals).''.esc_html($s->shots).''.number_format((float)$s->shooting_pctg * 100, 1).'%'.number_format((float)$s->faceoff_winning_pctg * 100, 1).'%'.esc_html($s->avg_toi).'
NHL Career TotalsNHL'.$nhl_tot['GP'].''.$nhl_tot['G'].''.$nhl_tot['A'].''.$nhl_tot['P'].''.$nhl_tot['PIM'].''.(($nhl_tot['+/-'] > 0) ? '+' . $nhl_tot['+/-'] : $nhl_tot['+/-']).''.$nhl_tot['PPG'].''.$nhl_tot['PPP'].''.$nhl_tot['SHG'].''.$nhl_tot['SHP'].''.$nhl_tot['OTG'].''.$nhl_tot['GWG'].''.$nhl_tot['S'].'
NYR Career TotalsNHL'.$nyr_tot['GP'].''.$nyr_tot['G'].''.$nyr_tot['A'].''.$nyr_tot['P'].''.$nyr_tot['PIM'].''.(($nyr_tot['+/-'] > 0) ? '+' . $nyr_tot['+/-'] : $nyr_tot['+/-']).''.$nyr_tot['PPG'].''.$nyr_tot['PPP'].''.$nyr_tot['SHG'].''.$nyr_tot['SHP'].''.$nyr_tot['OTG'].''.$nyr_tot['GWG'].''.$nyr_tot['S'].'
NHL Career AveragesNHL'.round($nhl_tot['GP']/$count).''.round($nhl_tot['G']/$count).''.round($nhl_tot['A']/$count).''.round($nhl_tot['P']/$count).''.round($nhl_tot['PIM']/$count).''.(($nhl_tot['+/-'] > 0) ? '+' . round($nhl_tot['+/-']/$count) : round($nhl_tot['+/-']/$count)).''.round($nhl_tot['PPG']/$count).''.round($nhl_tot['PPP']/$count).''.round($nhl_tot['SHG']/$count).''.round($nhl_tot['SHP']/$count).''.round($nhl_tot['OTG']/$count).''.round($nhl_tot['GWG']/$count).''.round($nhl_tot['S']/$count).''.$avg_m.':'.$avg_s.'
NHL Career HighsNHL'.$nhl_high['G'].''.$nhl_high['A'].''.$nhl_high['P'].''.$nhl_high['PIM'].''.(($nhl_high['plus_minus'] > 0) ? '+' . $nhl_high['plus_minus'] : $nhl_high['plus_minus']).''.$nhl_high['PPG'].''.$nhl_high['PPP'].''.$nhl_high['SHG'].''.$nhl_high['SHP'].''.$nhl_high['OTG'].''.$nhl_high['GWG'].''.$nhl_high['S'].''.$high_m.':'.$high_s.'
'; } // ===================================================================== // COMPLETED MILESTONES MATRIX SECTION (Skaters & Goaltenders) // ===================================================================== if ($has_played_for_rangers && !empty($p->nhl_id)) { if (!$is_goalie) { $game_boxscores = $wpdb->get_results($wpdb->prepare(" SELECT g.game_id, g.game_date, g.opponent_abbr, g.is_home, b.goals, b.assists, b.points FROM otg_rangers_player_boxscores b JOIN otg_rangers_games g ON b.game_id = g.game_id WHERE b.player_id = %d AND g.game_state IS NULL AND g.game_type = 2 ORDER BY g.game_date ASC, g.game_id ASC ", $p->nhl_id)); if (!empty($game_boxscores)) { $running_gp = 0; $running_g = 0; $running_a = 0; $running_p = 0; $found_gp_milestones = []; $found_g_milestones = []; $found_a_milestones = []; $found_p_milestones = []; $milestone_matrix_data = [ 'Games Played' => [], 'Goals' => [], 'Assists' => [], 'Points' => [] ]; foreach ($game_boxscores as $gb) { $prev_gp = $running_gp; $prev_g = $running_g; $prev_a = $running_a; $prev_p = $running_p; $running_gp += 1; $running_g += intval($gb->goals); $running_a += intval($gb->assists); $running_p += intval($gb->points); $prefix = ($gb->is_home == 1) ? '' : '@ '; $game_link = '' . $prefix . esc_html($gb->opponent_abbr) . ' (' . date('M j, Y', strtotime($gb->game_date)) . ')'; // Target GP Check $target_gp = floor($running_gp / 100) * 100; if ($target_gp >= 100 && $prev_gp < $target_gp && !in_array($target_gp, $found_gp_milestones)) { $found_gp_milestones[] = $target_gp; $milestone_matrix_data['Games Played'][$target_gp] = $game_link; } // Target Goals Check $target_g = floor($running_g / 100) * 100; if ($target_g >= 100 && $prev_g < $target_g && !in_array($target_g, $found_g_milestones)) { $found_g_milestones[] = $target_g; $milestone_matrix_data['Goals'][$target_g] = $game_link; } // Target Assists Check $target_a = floor($running_a / 100) * 100; if ($target_a >= 100 && $prev_a < $target_a && !in_array($target_a, $found_a_milestones)) { $found_a_milestones[] = $target_a; $milestone_matrix_data['Assists'][$target_a] = $game_link; } // Target Points Check $target_p = floor($running_p / 100) * 100; if ($target_p >= 100 && $prev_p < $target_p && !in_array($target_p, $found_p_milestones)) { $found_p_milestones[] = $target_p; $milestone_matrix_data['Points'][$target_p] = $game_link; } } $all_tiers = []; foreach ($milestone_matrix_data as $cat_arr) { foreach (array_keys($cat_arr) as $tier) { $all_tiers[] = $tier; } } $all_tiers = array_unique($all_tiers); sort($all_tiers); if (!empty($all_tiers)) { $html .= '
'; $html .= '

Rangers Milestones

'; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; foreach ($all_tiers as $tier) { $html .= ''; } $html .= ''; $html .= ''; foreach (['Games Played', 'Goals', 'Assists', 'Points'] as $category) { $html .= ''; $html .= ''; foreach ($all_tiers as $tier) { $cell_content = isset($milestone_matrix_data[$category][$tier]) ? $milestone_matrix_data[$category][$tier] : '-'; $html .= ''; } $html .= ''; } $html .= '
Category' . number_format($tier) . '
' . esc_html($category) . '' . $cell_content . '
'; } } } else { $game_boxscores = $wpdb->get_results($wpdb->prepare(" SELECT g.game_id, g.game_date, g.opponent_abbr, g.is_home, b.decision, b.time_on_ice FROM otg_rangers_player_boxscores b JOIN otg_rangers_games g ON b.game_id = g.game_id WHERE b.player_id = %d AND g.game_state IS NULL AND g.game_type = 2 ORDER BY g.game_date ASC, g.game_id ASC ", $p->nhl_id)); if (!empty($game_boxscores)) { $running_gp = 0; $running_gs = 0; $running_w = 0; $found_gp_milestones = []; $found_gs_milestones = []; $found_w_milestones = []; $milestone_matrix_data = [ 'Games Played' => [], 'Games Started' => [], 'Wins' => [] ]; foreach ($game_boxscores as $gb) { $toi_val = $gb->time_on_ice; $toi_sec = is_numeric($toi_val) ? floatval($toi_val) : (function_exists('toi_to_seconds') ? toi_to_seconds($toi_val) : 0); if ($toi_sec > 0) { $prev_gp = $running_gp; $prev_gs = $running_gs; $prev_w = $running_w; $running_gp += 1; $running_gs += 1; if (isset($gb->decision) && strtoupper(trim($gb->decision)) === 'W') { $running_w += 1; } $prefix = ($gb->is_home == 1) ? '' : '@ '; $game_link = '' . $prefix . esc_html($gb->opponent_abbr) . ' (' . date('M j, Y', strtotime($gb->game_date)) . ')'; // Target GP Check (every 100 games for goalies) $target_gp = floor($running_gp / 100) * 100; if ($target_gp >= 100 && $prev_gp < $target_gp && !in_array($target_gp, $found_gp_milestones)) { $found_gp_milestones[] = $target_gp; $milestone_matrix_data['Games Played'][$target_gp] = $game_link; } // Target GS Check (every 100 starts) $target_gs = floor($running_gs / 100) * 100; if ($target_gs >= 100 && $prev_gs < $target_gs && !in_array($target_gs, $found_gs_milestones)) { $found_gs_milestones[] = $target_gs; $milestone_matrix_data['Games Started'][$target_gs] = $game_link; } // Target Wins Check (every 100 wins) $target_w = floor($running_w / 100) * 100; if ($target_w >= 100 && $prev_w < $target_w && !in_array($target_w, $found_w_milestones)) { $found_w_milestones[] = $target_w; $milestone_matrix_data['Wins'][$target_w] = $game_link; } } } $all_tiers = []; foreach ($milestone_matrix_data as $cat_arr) { foreach (array_keys($cat_arr) as $tier) { $all_tiers[] = $tier; } } $all_tiers = array_unique($all_tiers); sort($all_tiers); if (!empty($all_tiers)) { $html .= '
'; $html .= '

Rangers Milestones

'; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; foreach ($all_tiers as $tier) { $html .= ''; } $html .= ''; $html .= ''; foreach (['Games Played', 'Games Started', 'Wins'] as $category) { $html .= ''; $html .= ''; foreach ($all_tiers as $tier) { $cell_content = isset($milestone_matrix_data[$category][$tier]) ? $milestone_matrix_data[$category][$tier] : '-'; $html .= ''; } $html .= ''; } $html .= '
Category' . number_format($tier) . '
' . esc_html($category) . '' . $cell_content . '
'; } } } } $html .= ''; return $html; } function otg_render_player_bio($p) { global $wpdb; // --- Height/Birth/Hand Logic --- $feet = floor($p->Height / 12); $inches = $p->Height % 12; $height_display = "{$feet}-{$inches}"; $current_date = new DateTime(); $bday_date = (!empty($p->Birthday) && $p->Birthday !== '1800-01-01') ? new DateTime($p->Birthday) : null; $death_val = !empty($p->Death) ? $p->Death : (!empty($p->death_date) ? $p->death_date : null); $death_date = (!empty($death_val) && $death_val !== '0000-00-00' && $death_val !== '1800-01-01') ? new DateTime($death_val) : null; if ($bday_date) { if ($death_date) { $age_at_death = $bday_date->diff($death_date)->y; $formatted_death_date = $death_date->format('F ') . get_ordinal($death_date->format('j')) . $death_date->format(', Y'); $bday = $bday_date->format('F jS, Y') . ' - ' . $age_at_death . ' years (Died: ' . $formatted_death_date . ')'; } else { $age_current = $bday_date->diff($current_date)->y; $bday = $bday_date->format('F jS, Y') . ' - ' . $age_current . ' years'; } } else { $bday = '-'; } $birthplace = esc_html($p->Birthplace) . (!empty($p->State) ? ' ' . esc_html($p->State) : ''); // --- Draft Logic --- $draft = $wpdb->get_row($wpdb->prepare("SELECT * FROM otg_draft WHERE ID = %d", $p->ID)); if ($draft) { $draft_year = esc_attr($draft->Draft); $draft_link = ''.$draft_year.''; $draft_display = "{$draft->Team} - {$draft_link} " . get_ordinal($draft->Round) . " round (" . get_ordinal($draft->Pick) . " overall)"; } else { $draft_display = "N/A"; } $hand_label = ($p->Position === 'Goaltender') ? 'Catches' : 'Shoots'; $hand_value = ($p->Hand === 'L') ? 'Left' : 'Right'; $debut = !empty($p->nhl_id) ? $wpdb->get_row($wpdb->prepare(" SELECT g.game_date, g.game_id FROM otg_rangers_games g JOIN otg_rangers_player_boxscores b ON g.game_id = b.game_id WHERE b.player_id = %d AND b.team_abbr = 'NYR' AND g.game_type != 1 ORDER BY g.game_date ASC LIMIT 1 ", $p->nhl_id)) : null; $debut_display = $debut ? ''.date('F j, Y', strtotime($debut->game_date)).'' : 'Has not played for Rangers'; $numbers = !empty($p->nhl_id) ? $wpdb->get_col($wpdb->prepare(" SELECT DISTINCT jersey_number FROM otg_rangers_player_boxscores WHERE player_id = %d AND team_abbr = 'NYR' AND jersey_number IS NOT NULL AND jersey_number != '' ORDER BY jersey_number ASC ", $p->nhl_id)) : []; $numbers_display = $numbers ? implode(', ', $numbers) : 'N/A'; $data = [['Position', $p->Position], ['Height', $height_display], ['Weight', $p->Weight], [$hand_label, $hand_value], ['Birthday', $bday], ['Birthplace', $birthplace], ['Drafted', $draft_display], ['Rangers Debut', $debut_display], ['Numbers Worn', $numbers_display]]; $player_status = !empty($p->Status) ? trim($p->Status) : (!empty($p->status) ? trim($p->status) : ''); if (!empty($player_status)) { $player_bucket = isset($p->player_bucket) ? trim($p->player_bucket) : ''; $detailed_status = isset($p->detailed_status) ? trim($p->detailed_status) : ''; $current_team_display = ''; if ($player_status === 'NHL') { $current_team_display = $player_bucket; } elseif ($player_status === 'UFA') { $current_team_display = !empty($detailed_status) ? 'UFA - formerly with ' . $detailed_status : 'UFA'; } elseif ($player_status === 'Ex-Ranger') { if ($player_bucket === 'AHL' || $player_bucket === 'ECHL') { $current_team_display = $detailed_status . ' (' . $player_bucket . ')'; } elseif ($player_bucket === 'Europe') { $current_team_display = $detailed_status; } } if (!empty($current_team_display)) { $data[] = ['Current Team', esc_html($current_team_display)]; } } // --- Pull explicitly active season using active_season = 'y' --- $current_season = $wpdb->get_var("SELECT season FROM otg_rangers_season_settings WHERE active_season = 'y' LIMIT 1"); if (!$current_season) { $current_season = '2026-27'; // Fallback } $contract = $wpdb->get_row($wpdb->prepare("SELECT free_agent_type, fa_season, aav FROM otg_rangers_contracts WHERE player_id = %d LIMIT 1", $p->ID)); if ($contract && !empty($contract->fa_season)) { $fa_season = $contract->fa_season; $current_season_year = intval(substr($current_season, 0, 4)); $fa_season_year = intval(substr($fa_season, 0, 4)); $formatted_aav = !empty($contract->aav) ? '$' . number_format(floatval($contract->aav), 0) . ' AAV' : '$0 AAV'; if ($fa_season === $current_season) { $contract_display = esc_html($contract->free_agent_type); } elseif ($fa_season_year > $current_season_year) { $years_remaining = $fa_season_year - $current_season_year; $year_label = ($years_remaining === 1) ? 'more year' : 'more years'; $contract_display = sprintf('Signed for %d %s - %s (%s, %s)', $years_remaining, $year_label, $formatted_aav, esc_html($contract->free_agent_type), esc_html($fa_season)); } else { $contract_display = esc_html($contract->free_agent_type); } $data[] = ['Contract Status', $contract_display]; } $coach_row = $wpdb->get_row($wpdb->prepare("SELECT CoachID FROM otg_coach_statistics WHERE CoachID = %d LIMIT 1", $p->ID)); $gm_row = $wpdb->get_row($wpdb->prepare("SELECT id, name FROM otg_general_managers WHERE player_id = %d LIMIT 1", $p->ID)); if ($coach_row || $gm_row) { $links = []; if ($coach_row) { $links[] = 'Coach'; } if ($gm_row) { $gm_slug = strtolower(str_replace(' ', '-', $gm_row->name)); $links[] = 'GM'; } $data[] = ['Profiles', implode(' | ', $links)]; } $player_id_val = intval($p->ID); $base_dir = $_SERVER['DOCUMENT_ROOT'] . '/images/players/'; $base_url = 'https://outsidethegarden.com/images/players/'; $default_img = 'https://outsidethegarden.com/images/players/default_player.png'; $display_img = $default_img; $extensions = ['jpg', 'jpeg', 'png']; foreach ($extensions as $ext) { if (file_exists($base_dir . $player_id_val . '.' . $ext)) { $display_img = $base_url . $player_id_val . '.' . $ext; break; } } $html = '
'; $html .= '
'; $html .= '
'; $html .= '

'; $html .= ''.strtoupper(esc_html($p->Name)).'

'; $html .= ''; $html .= '
'; $html .= '
'; foreach ($data as $index => $row) { $border_style = ($index === count($data) - 1) ? 'border-bottom: none;' : 'border-bottom: 1px solid #808080;'; $html .= '
'.$row[0].':
'.$row[1].'
'; } $html .= '
'; return $html; } Fish – Activity – OutsideTheGarden Boards – Page 43
OCTOBER
«
Thu
17
Fri
18
Sat
19
Sun
20
Mon
21
Tue
22
Wed
23
»
Fish
Fish
@fish
Moderator
Member
Joined: August 22, 2023 2:27 pm
Last seen: August 13, 2026 12:15 pm
Topics: 388 / Replies: 3281
Reply
RE: GAME 26: NYR (14-10-1) v SEA (13-14-1) 1:00pm NHLN, MSG

Zibanejad's first 70 minutes since Trouba was dispatched have been amongst his best...nice to see the forwards backchecking too

2 years ago
Reply
RE: GAME 25: NYR (13-10-1) v PIT (11-124) 7:30PM ESPN+ HULU

Yeah the guy I wondered whether they were sending back might have been Ben Chiarot, and he'd be just another Trouba, albeit half the price

2 years ago
Reply
RE: GAME 25: NYR (13-10-1) v PIT (11-124) 7:30PM ESPN+ HULU

Reilly Smith looks like he wants to tell the Penguins something about trading him in the Summer

2 years ago
Reply
RE: GAME 25: NYR (13-10-1) v PIT (11-124) 7:30PM ESPN+ HULU

Kind of like that recovering alcoholic. They made it into the bar and didn't order a drink in the first 30 minutes...that's great!

2 years ago
Reply
RE: GAME 25: NYR (13-10-1) v PIT (11-124) 7:30PM ESPN+ HULU

One of the beat writers there thought it might have been a shoulder/arm thing, Chytil apparently skated in the ad break in a little discomfort but not...

2 years ago
Reply
Reply
RE: GAME 25: NYR (13-10-1) v PIT (11-124) 7:30PM ESPN+ HULU

I wonder if he's going to be one of the next guys to go. He just seems really off

2 years ago
Reply
RE: GAME 25: NYR (13-10-1) v PIT (11-124) 7:30PM ESPN+ HULU

Zibanejad sure has a skip in his step tonight...he looks pretty good right now

2 years ago
Reply
RE: GAME 25: NYR (13-10-1) v PIT (11-124) 7:30PM ESPN+ HULU

Still the worst pass for me so far was that Smith one where instead of taking it out of the defensive zone, he sends it back and has it picked off...f...

2 years ago
Reply
RE: GAME 25: NYR (13-10-1) v PIT (11-124) 7:30PM ESPN+ HULU

Penguins look awful...which is maybe making the Rangers look better than they are

2 years ago
Reply
RE: Trouba traded to Anaheim for Urho Vaakanainen and 4th round pick

While I didn't necessarily have issue with trading McDonagh at the time...adding Miller in there as well, and then the return on that deal. Not a gre...

2 years ago
Page 43 / 245
TOP