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 303
AUGUST
«
Sun
16
Mon
17
Tue
18
Wed
19
Thu
20
Fri
21
Sat
22
»
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
RE: GAME 30 TUESDAY DECEMBER 19 NYR @ TOR 7:00 PM MSG

Leaks will put martin on the bench inside 3 mins Need a dagger

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

Did Martin think that the Dman with average at best hands was going to cut and go backhand on him? He left that left side of the net open way too soon...

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

laf interfered with no whistles to be found

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

Trouba gets tripped and it leads to all kinds of pressure

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

Jeez didn't see that coming.... Can we start the period over?

3 years ago
Page 303 / 356
TOP