if (!defined('ABSPATH')) { exit; } add_shortcode('otg_season_comparison', 'otg_render_season_comparison'); function otg_render_season_comparison($atts) { global $wpdb; // 1. Get Parameters & Defaults $game_type = isset($_GET['game_type']) ? sanitize_text_field($_GET['game_type']) : '2'; $compare_mode = isset($_GET['compare_mode']) ? sanitize_text_field($_GET['compare_mode']) : 'date'; // 'date' or 'game_num' $target_date = isset($_GET['target_date']) ? sanitize_text_field($_GET['target_date']) : '12-01'; // Default Dec 1st (MM-DD) $target_game = isset($_GET['target_game']) ? (int)$_GET['target_game'] : 33; // Default Game 33 // Available seasons $all_seasons = $wpdb->get_col("SELECT DISTINCT season FROM otg_rangers_games WHERE game_type = " . (int)$game_type . " ORDER BY season DESC"); if (empty($all_seasons)) { return '
No historical season data available for game type ' . esc_html($game_type) . '. Check if table otg_rangers_games has data.
'; } $start_season = isset($_GET['start_season']) && !empty($_GET['start_season']) ? sanitize_text_field($_GET['start_season']) : reset($all_seasons); $end_season = isset($_GET['end_season']) && !empty($_GET['end_season']) ? sanitize_text_field($_GET['end_season']) : end($all_seasons); // Default sorting $default_sort = 'Pts:desc'; $sort_input = isset($_GET['sort']) ? sanitize_text_field($_GET['sort']) : $default_sort; $active_sorts = []; if (!empty($sort_input)) { foreach (explode(',', $sort_input) as $sort_pair) { $parts = explode(':', trim($sort_pair)); if (!empty($parts[0])) { $active_sorts[] = [ 'col' => trim($parts[0]), 'dir' => (isset($parts[1]) && strtolower($parts[1]) === 'asc') ? 'asc' : 'desc' ]; } } } if (empty($active_sorts)) { $active_sorts[] = ['col' => 'Pts', 'dir' => 'desc']; } $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 50; $paged = isset($_GET['paged']) ? max(1, (int)$_GET['paged']) : 1; $offset = ($paged - 1) * $limit; // 2. Fetch and Compute Season-by-Season Snapshot Data $start_idx = array_search($start_season, $all_seasons); $end_idx = array_search($end_season, $all_seasons); if ($start_idx !== false && $end_idx !== false) { $min_idx = min($start_idx, $end_idx); $max_idx = max($start_idx, $end_idx); $filtered_seasons = array_slice($all_seasons, $min_idx, ($max_idx - $min_idx + 1)); } else { $filtered_seasons = $all_seasons; } $raw_data = []; foreach ($filtered_seasons as $season) { if ($compare_mode === 'date') { $parts = explode('-', $season); $start_year = isset($parts[0]) ? trim($parts[0]) : ''; $end_year = isset($parts[1]) ? trim($parts[1]) : ''; $target_parts = explode('-', $target_date); $m = isset($target_parts[0]) ? str_pad(trim($target_parts[0]), 2, '0', STR_PAD_LEFT) : '12'; $d = isset($target_parts[1]) ? str_pad(trim($target_parts[1]), 2, '0', STR_PAD_LEFT) : '01'; $calendar_year = ($m >= '08') ? $start_year : ('20' . $end_year); $full_target_date = $calendar_year . '-' . $m . '-' . $d; $season_start_date = $start_year . '-10-01'; $query = $wpdb->prepare(" SELECT game_date, game_state, game_outcome, overtime_status, is_home, home_score, away_score, rangers_score as gf, opponent_score as ga FROM otg_rangers_games WHERE season = %s AND game_type = %d AND (game_state IS NULL OR game_state != 'FUT') AND game_date >= %s AND game_date <= %s ORDER BY game_date ASC ", $season, (int)$game_type, $season_start_date, $full_target_date); } else { $query = $wpdb->prepare(" SELECT game_date, game_state, game_outcome, overtime_status, is_home, home_score, away_score, rangers_score as gf, opponent_score as ga FROM otg_rangers_games WHERE season = %s AND game_type = %d AND (game_state IS NULL OR game_state != 'FUT') ORDER BY game_date ASC LIMIT %d ", $season, (int)$game_type, $target_game); } $games = $wpdb->get_results($query); $gp = count($games); if ($gp === 0) continue; $w = 0; $l = 0; $ot = 0; $gf = 0; $ga = 0; foreach ($games as $g) { $r_score = (int)$g->gf; $o_score = (int)$g->ga; $outcome = strtoupper(trim($g->game_outcome)); $ot_status = strtoupper(trim($g->overtime_status)); // Determine outcome and points based on database game_outcome and overtime_status if ($outcome === 'W') { $w++; } elseif ($outcome === 'L') { $l++; } else { if ($ot_status === 'OT' || $ot_status === 'SO' || $outcome === 'T') { $ot++; } else { $l++; } } $gf += $r_score; $ga += $o_score; } $pts = ($w * 2) + ($ot * 1); $pt_pct = ($gp > 0) ? ($pts / ($gp * 2)) : 0; $agf = ($gp > 0) ? ($gf / $gp) : 0; $aga = ($gp > 0) ? ($ga / $gp) : 0; $raw_data[] = [ 'season' => $season, 'gp' => $gp, 'w' => $w, 'l' => $l, 'ot' => $ot, 'pts' => $pts, 'gf' => $gf, 'ga' => $ga, 'diff' => $gf - $ga, 'agf' => round($agf, 2), 'aga' => round($aga, 2), 'pt_pct' => round($pt_pct, 4) ]; } // 3. Sorting Logic usort($raw_data, function($a, $b) use ($active_sorts) { foreach ($active_sorts as $sort) { $col = $sort['col']; $dir = $sort['dir']; $valA = $a[$col] ?? $a['season'] ?? 0; $valB = $b[$col] ?? $b['season'] ?? 0; if ($valA == $valB) continue; if ($dir === 'asc') { return ($valA < $valB) ? -1 : 1; } else { return ($valA > $valB) ? -1 : 1; } } return 0; }); $total_records = count($raw_data); $data = array_slice($raw_data, $offset, $limit); $start_row = $total_records > 0 ? $offset + 1 : 0; $end_row = min($offset + $limit, $total_records); $total_pages = $limit > 0 ? ceil($total_records / $limit) : 1; $input_style = 'width: 100%; height: 38px; padding: 0 10px; background: #222; border: 1px solid #444; color: #fff; border-radius: 4px; box-sizing: border-box; font-size: 0.9em; line-height: normal;'; // 4. Render Output $output = '
'; // Header & Regular Season / Playoffs Switcher $output .= '
'; $output .= '
Season-to-Season Comparison
'; $query_params_base = '&compare_mode=' . urlencode($compare_mode) . '&target_date=' . urlencode($target_date) . '&target_game=' . urlencode($target_game) . '&start_season=' . urlencode($start_season) . '&end_season=' . urlencode($end_season) . '&limit=' . urlencode($limit) . '&sort=' . urlencode($sort_input); $output .= '
'; $output .= 'Regular Season'; $output .= 'Playoffs'; $output .= '
'; $output .= '
'; // Filter Form $current_url = strtok($_SERVER['REQUEST_URI'], '?'); $output .= '
'; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= '
'; // Comparison Mode selector $output .= '
'; $output .= ''; $output .= ''; $output .= '
'; // Dynamic inputs container $output .= '
'; $output .= ''; $output .= ''; $output .= '
'; $output .= '
'; $output .= ''; $output .= ''; $output .= '
'; // Season Range Filters $output .= '
'; $output .= ''; $output .= ''; $output .= '
'; $output .= '
'; $output .= ''; $output .= ''; $output .= '
'; // Rows per page $output .= '
'; $output .= ''; $output .= ''; $output .= '
'; // Buttons $output .= '
'; $output .= ''; $output .= 'Clear'; $output .= '
'; $output .= '
'; $output .= '
'; // Embedded CSS $output .= ''; $active_sort_map = []; foreach ($active_sorts as $index => $s_item) { $active_sort_map[$s_item['col']] = [ 'dir' => $s_item['dir'], 'priority' => count($active_sorts) > 1 ? ($index + 1) : null ]; } $headers = ['#', 'Season', 'GP', 'W', 'L', 'OT', 'Pts', 'GF', 'GA', 'DIFF', 'AGF', 'AGA', 'Pt%']; $col_map = ['#'=>'', 'Season'=>'season', 'GP'=>'gp', 'W'=>'w', 'L'=>'l', 'OT'=>'ot', 'Pts'=>'pts', 'GF'=>'gf', 'GA'=>'ga', 'DIFF'=>'diff', 'AGF'=>'agf', 'AGA'=>'aga', 'Pt%'=>'pt_pct']; $col_sort_keys = []; $output .= ''; foreach ($headers as $i => $header_name) { $sort_col = $col_map[$header_name] ?? $header_name; $col_sort_keys[$i] = $sort_col; $is_sorted = isset($active_sort_map[$sort_col]); $arrow = ''; $priority_badge = ''; if ($is_sorted) { $arrow = ($active_sort_map[$sort_col]['dir'] === 'asc') ? ' ' : ' '; if ($active_sort_map[$sort_col]['priority'] !== null) { $priority_badge = ' ' . $active_sort_map[$sort_col]['priority'] . ''; } } $classes = ($header_name === 'Season' ? 'text-left ' : '') . ($is_sorted ? 'highlight-col' : ''); $onclick = ($header_name !== '#') ? 'onclick="handleSort(event, \'' . esc_attr($sort_col) . '\')"' : ''; $cursor = ($header_name !== '#') ? 'style="cursor: pointer;"' : ''; $output .= ''; } $output .= ''; if (empty($data)) { $output .= ''; } else { $current_rank = $offset + 1; foreach ($data as $row) { $diff_val = $row['diff']; $diff_str = ($diff_val > 0) ? '+' . $diff_val : $diff_val; $display_vals = [ $current_rank, $row['season'], $row['gp'], $row['w'], $row['l'], $row['ot'], $row['pts'], $row['gf'], $row['ga'], $diff_str, number_format((float)$row['agf'], 2), number_format((float)$row['aga'], 2), number_format((float)$row['pt_pct'] * 100, 1) . '%' ]; $output .= ''; foreach ($display_vals as $idx => $val) { $sort_key = $col_sort_keys[$idx] ?? ''; $is_season_col = ($idx === 1); $is_sorted = !empty($sort_key) && isset($active_sort_map[$sort_key]); $classes = ($is_sorted ? 'highlight-col ' : '') . ($is_season_col ? 'text-left' : ''); $output .= ''; } $output .= ''; $current_rank++; } } $output .= '
' . $header_name . $arrow . $priority_badge . '
No season comparison records found matching your filters.
' . esc_html($val) . '
'; // Pagination Bar if ($total_records > 0) { $params_prev = $_GET; $params_prev['paged'] = max(1, $paged - 1); $prev_url = '?' . http_build_query($params_prev); $params_next = $_GET; $params_next['paged'] = min($total_pages, $paged + 1); $next_url = '?' . http_build_query($params_next); $output .= '
'; $output .= '
Showing ' . $start_row . ' to ' . $end_row . ' of ' . $total_records . ' seasons
'; $output .= '
'; if ($paged > 1) { $output .= '« Previous'; } else { $output .= '« Previous'; } $output .= 'Page ' . $paged . ' of ' . max(1, $total_pages) . ''; if ($paged < $total_pages) { $output .= 'Next »'; } else { $output .= 'Next »'; } $output .= '
'; } $output .= '
'; // JS Helpers $js_active_sorts = json_encode($active_sorts); $output .= ''; return $output; } Doug Glatt – Activity – OutsideTheGarden Boards – Page 304
AUGUST
«
Sun
23
Mon
24
Tue
25
Wed
26
Thu
27
Fri
28
Sat
29
»
May 29
MTL 1-3
1
CAR 3-1
6
Jun 2
VGK 0-0
5
CAR 0-0
4
Jun 4
VGK 1-0
3
CAR 0-1
4
OT
Jun 6
CAR 1-1
4
VGK 1-1
5
OT
Jun 9
CAR 1-2
5
VGK 2-1
3
Jun 11
VGK 2-2
2
CAR 2-2
4
Jun 14
CAR 3-2
3
VGK 2-3
0
Sep 19
DAL 0-0-0
7:00 PM
STL 0-0-0
PRESEASON
Doug Glatt
Doug Glatt
@pierre_pdare
Legend
Joined: August 26, 2023 2:21 pm
Last seen: September 8, 2026 10:40 pm
Topics: 112 / Replies: 5217
Reply
Reply
Reply
RE: GAME 30 TUESDAY DECEMBER 19 NYR @ TOR 7:00 PM MSG

Igor has looked good but Rangers starting to give up a lot of chances

3 years ago
Reply
3 years ago
Reply
RE: GAME 30 TUESDAY DECEMBER 19 NYR @ TOR 7:00 PM MSG

Just leave Matthews alone after you turn the puck over....

3 years ago
Reply
3 years ago
Reply
RE: GAME 30 TUESDAY DECEMBER 19 NYR @ TOR 7:00 PM MSG

Fox was determined to keep giving that cross ice pass up at the blue line

3 years ago
Reply
Reply
RE: GAME 30 TUESDAY DECEMBER 19 NYR @ TOR 7:00 PM MSG

Rangers have missed the net on some good chances

3 years ago
Page 304 / 356
TOP