// ========================================================================= // 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 38
OCTOBER
«
Thu
3
Fri
4
Sat
5
Sun
6
Mon
7
Tue
8
Wed
9
»
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 38 NYR @ WAS 12:00 PM ABC

It was a great assist by Thompson

2 years ago
Reply
RE: Game 37: NYR v BOS

I don't blame anyone for not making noise at MSG right now...I'd be hard pressed to even go

2 years ago
Reply
RE: Game 37: NYR v BOS

Well reports today that Dolan and Drury still think they can make the playoffs, obviously aren't watching many of these games...and makes you wonder h...

2 years ago
Topic
Replies: 94
Views: 5289
Reply
RE: GAME 34: NYR v NJD 1:00pm

Just 10 shots on goal...

2 years ago
Reply
RE: GAME 34: NYR v NJD 1:00pm

Feels like at least half the team you could say that about

2 years ago
Reply
RE: GAME 34: NYR v NJD 1:00pm

They counted yesterday as well

2 years ago
Reply
RE: GAME 34: NYR v NJD 1:00pm

You'd hope Quick would get that one

2 years ago
Topic
Replies: 44
Views: 2156
Reply
RE: Game 33: Caro @ NYR 12.30PM MSG

Shesterkin almost got the pass, but nope...and Roslovic behind Ruhwedel for the easy tap in

2 years ago
Reply
RE: Game 33: Caro @ NYR 12.30PM MSG

And now Laf with a double minor...geez

2 years ago
Reply
RE: Game 33: Caro @ NYR 12.30PM MSG

Tied game...Canes haven't exactly dominated the second, but the NYR have had nothing

2 years ago
Reply
RE: GAME 32: NYR @ DAL 8:00pm MSG

Nope...there's Rempe that we know and...

2 years ago
Reply
RE: GAME 32: NYR @ DAL 8:00pm MSG

Rempe has drawn 3 power plays in this period...are we in an alternate universe?

2 years ago
Reply
RE: GAME 32: NYR @ DAL 8:00pm MSG

At the very least put Lafreniere in Kreider's place on the PP

2 years ago
Page 38 / 245
TOP