<?php
/**
 * Win Racing - 大數據核心分析計算 API v38 Half Bias Test (3火至尊條件：總分>=24 + 首選>=4人 + 拋離對手>11分)
 * 終極完全體動態權重熔接版：
 * 1. 【最高指示落實】100% 完整平鋪，只加不刪除，不刪減，不刪改。
 * 2. 【第一階段鋼鐵熔接】在計算全賽季專家矩陣時，動態引入由 cron 固化的 expert_performance_stats 權重因子。
 * 3. 完美保留 10 級精細同級區間回測、戰術溢價放大因子、(4,4) 屏除機制，以及全自動抓取前 5 隻實力配腳的數據出口管線。
 */
ob_start(); 
error_reporting(0);
ini_set('display_errors', 0);
date_default_timezone_set('Asia/Hong_Kong');

require_once 'config/config.php';
if (!isset($conn)) { $conn = $db; }
$conn->set_charset("utf8mb4");

$race_id = isset($_GET['race_id']) ? intval($_GET['race_id']) : 0;
if ($race_id <= 0) {
    ob_end_clean();
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(array());
    exit;
}

// 1. 自動定位當前 race_id 的真實賽事日期
$d_stmt = $conn->prepare("SELECT racing_date FROM racing_date_2025_2026 WHERE id = ?");
$d_stmt->bind_param("i", $race_id);
$d_stmt->execute();
$d_res = $d_stmt->get_result();

if (!$d_row = $d_res->fetch_assoc()) {
    ob_end_clean();
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(array());
    $d_stmt->close();
    exit;
}
$target_date = $d_row['racing_date'];
$d_stmt->close();

// =========================================================================
// 🛡️ [WinRacing v39 Date Fallback Fix]
// 目的：race_id 對應日期有時與 race_card_static 實際排位日期不一致。
// 若 race_card_static 無 target_date，立即 fallback 去最新一個有排位資料的日期，
// 避免全場 draw=0 / predicted_running_style='' / NORMAL_PACE。
// =========================================================================
$wr_card_lookup_date = $target_date;
$wr_card_date_count = 0;
$wr_card_count_stmt = $conn->prepare("SELECT COUNT(*) AS c FROM race_card_static WHERE race_date = ?");
if ($wr_card_count_stmt) {
    $wr_card_count_stmt->bind_param("s", $wr_card_lookup_date);
    $wr_card_count_stmt->execute();
    $wr_card_count_res = $wr_card_count_stmt->get_result();
    if ($wr_card_count_row = $wr_card_count_res->fetch_assoc()) {
        $wr_card_date_count = intval($wr_card_count_row['c']);
    }
    $wr_card_count_stmt->close();
}
if ($wr_card_date_count <= 0) {
    $wr_fallback_q = $conn->query("SELECT race_date FROM race_card_static GROUP BY race_date ORDER BY race_date DESC LIMIT 1");
    if ($wr_fallback_q && $wr_fallback_q->num_rows > 0) {
        $wr_fallback_row = $wr_fallback_q->fetch_assoc();
        $wr_card_lookup_date = $wr_fallback_row['race_date'];
    }
}
// =========================================================================

// 2. 預載全局實際歷史賽果 Map，精確定位 WIN 頭馬
$results_map = array();
$res_query = $conn->query("SELECT race_date, race_number, win_horse FROM racing_results");
if ($res_query) {
    while ($res = $res_query->fetch_assoc()) {
        $results_map[$res['race_date']][intval($res['race_number'])] = intval($res['win_horse']);
    }
}

// 3. 全賽季縱向大數據軌跡重構
$tables = array('expert_ai', 'expert_ball', 'expert_racing_post', 'expert_siu_siu', 'expert_horse_king', 'expert_happy_bird');
$season_expert_matrix = array();

foreach ($tables as $table) {
    $check_table = $conn->query("SHOW TABLES LIKE '$table'");
    if($check_table->num_rows == 0) continue;

    // =========================================================================
    // 💡 [第一階段無痛熔接]：安全撈取該名家當前的動態權重加權因子 (只加不改)
    // =========================================================================
    $dynamic_weight = 1.00; 
    $weight_query = $conn->query("SELECT dynamic_weight FROM expert_performance_stats WHERE expert_code = '$table'");
    if ($weight_query && $weight_query->num_rows > 0) {
        $weight_row = $weight_query->fetch_assoc();
        $dynamic_weight = floatval($weight_row['dynamic_weight']);
    }
    // =========================================================================

    $fields = ($table === 'expert_happy_bird') ? "race_date, race_num, pick_1, pick_2, pick_3, pick_4, pick_5" : "race_date, race_num, pick_1, pick_2, pick_3, pick_4";
    $h_sql = "SELECT $fields FROM `$table` WHERE race_date >= '2025-09-28' AND race_date <= ? ORDER BY race_date ASC, race_num ASC";
    $h_stmt = $conn->prepare($h_sql);
    if ($h_stmt) {
        $h_stmt->bind_param("s", $target_date);
        $h_stmt->execute();
        $h_res = $h_stmt->get_result();
        while ($h_row = $h_res->fetch_assoc()) {
            $hd = $h_row['race_date'];
            $rn = intval($h_row['race_num']);
            
            $all_picks = array('pick_1', 'pick_2', 'pick_3', 'pick_4');
            if ($table === 'expert_happy_bird') { $all_picks[] = 'pick_5'; }
            
            foreach ($all_picks as $p_fld) {
                if (isset($h_row[$p_fld]) && $h_row[$p_fld] > 0) {
                    $h_num = intval($h_row[$p_fld]);
                    if (!isset($season_expert_matrix[$hd][$rn][$h_num])) {
                        $season_expert_matrix[$hd][$rn][$h_num] = array(
                            'horse_num' => $h_num, 'total_score' => 0, 'hit_count' => 0,
                            'p1_from' => array(), 'p2_from' => array(), 'supporters' => array(), 'expert_count' => 0
                        );
                    }
                    $season_expert_matrix[$hd][$rn][$h_num]['expert_count']++;
                    
                    if ($p_fld === 'pick_1') {
                        // 100% 保留原有計分框架，僅安全乘上名家近期狀態動態權重
                        $season_expert_matrix[$hd][$rn][$h_num]['total_score'] += (6 * $dynamic_weight);
                        $season_expert_matrix[$hd][$rn][$h_num]['hit_count'] += 1;
                        $season_expert_matrix[$hd][$rn][$h_num]['p1_from'][] = $table;
                    } elseif ($p_fld === 'pick_2') {
                        // 100% 保留原有計分框架，僅安全乘上名家近期狀態動態權重
                        $season_expert_matrix[$hd][$rn][$h_num]['total_score'] += (1 * $dynamic_weight);
                        $season_expert_matrix[$hd][$rn][$h_num]['hit_count'] += 1;
                        $season_expert_matrix[$hd][$rn][$h_num]['p2_from'][] = $table;
                    } else {
                        $season_expert_matrix[$hd][$rn][$h_num]['hit_count'] += 1;
                        $season_expert_matrix[$hd][$rn][$h_num]['supporters'][] = $table;
                    }
                }
            }
        }
        $h_stmt->close();
    }
}


// =========================================================================
// 🔥 [WinRacing v37 AJAX Bias Engine｜預載 race_card_static 並正式入分]
// 注意：analysis.php 畫面矩陣係由本 AJAX 即時計算，不是讀 analysis_cache。
// 所以 Bias 必須在 season_ranked_flow 排序前加入 total_score。
// =========================================================================
$wr_ajax_card_map = array();
$wr_ajax_has_pred = wr_ajax_col_exists($conn, 'race_card_static', 'predicted_running_style');
$wr_ajax_has_manual = wr_ajax_col_exists($conn, 'race_card_static', 'running_style');
$wr_ajax_has_draw = wr_ajax_col_exists($conn, 'race_card_static', 'draw');
$wr_ajax_has_source = wr_ajax_col_exists($conn, 'race_card_static', 'running_style_source');
$wr_ajax_has_sample = wr_ajax_col_exists($conn, 'race_card_static', 'running_style_sample');
$wr_ajax_cols = array('race_date','race_num','horse_num');
if ($wr_ajax_has_draw) $wr_ajax_cols[] = 'draw';
if ($wr_ajax_has_manual) $wr_ajax_cols[] = 'running_style';
if ($wr_ajax_has_pred) $wr_ajax_cols[] = 'predicted_running_style';
if ($wr_ajax_has_source) $wr_ajax_cols[] = 'running_style_source';
if ($wr_ajax_has_sample) $wr_ajax_cols[] = 'running_style_sample';

$wr_ajax_card_sql = "SELECT `" . implode("`,`", $wr_ajax_cols) . "` FROM race_card_static WHERE race_date <= ? OR race_date = ?";
$wr_ajax_card_stmt = $conn->prepare($wr_ajax_card_sql);
if ($wr_ajax_card_stmt) {
    $wr_ajax_card_stmt->bind_param("ss", $target_date, $wr_card_lookup_date);
    $wr_ajax_card_stmt->execute();
    $wr_ajax_card_res = $wr_ajax_card_stmt->get_result();
    while ($cr = $wr_ajax_card_res->fetch_assoc()) {
        $cd = $cr['race_date'];
        $crn = intval($cr['race_num']);
        $chn = intval($cr['horse_num']);
        $manual_style = wr_ajax_norm_style($cr['running_style'] ?? '');
        $pred_style = wr_ajax_norm_style($cr['predicted_running_style'] ?? '');
        $final_style = ($manual_style !== '') ? $manual_style : $pred_style;
        $wr_ajax_card_map[$cd][$crn][$chn] = array(
            'draw' => intval($cr['draw'] ?? 0),
            'running_style' => $manual_style,
            'predicted_running_style' => $pred_style,
            'final_style' => $final_style,
            'running_style_source' => strval($cr['running_style_source'] ?? ''),
            'running_style_sample' => intval($cr['running_style_sample'] ?? 0)
        );
    }
    $wr_ajax_card_stmt->close();
}

foreach ($season_expert_matrix as $bd => &$bd_races) {
    foreach ($bd_races as $brn => &$bd_horses) {
        foreach ($bd_horses as $bhn => &$bh) {
            $original_score = floatval($bh['total_score']);
            $draw = 0;
            $manual_style = '';
            $pred_style = '';
            $final_style = '';
            $ci = null;
            $card_source_date = $bd;

            if (isset($wr_ajax_card_map[$bd][intval($brn)][intval($bh['horse_num'])])) {
                $ci = $wr_ajax_card_map[$bd][intval($brn)][intval($bh['horse_num'])];
                $card_source_date = $bd;
            } elseif ($bd === $target_date && isset($wr_ajax_card_map[$wr_card_lookup_date][intval($brn)][intval($bh['horse_num'])])) {
                // v39 fallback：今日 race_id 日期搵唔到排位時，用最新 race_card_static 日期補入。
                $ci = $wr_ajax_card_map[$wr_card_lookup_date][intval($brn)][intval($bh['horse_num'])];
                $card_source_date = $wr_card_lookup_date;
            }

            if (is_array($ci)) {
                $draw = intval($ci['draw'] ?? 0);
                $manual_style = strval($ci['running_style'] ?? '');
                $pred_style = strval($ci['predicted_running_style'] ?? '');
                $final_style = strval($ci['final_style'] ?? '');
            }

            $bias_v1_score = wr_ajax_bias_score_v1($final_style, $draw);
            $bias_v1_breakdown = wr_ajax_bias_breakdown_v1($final_style, $draw);

            // =========================================================================
            // 🔥 [WinRacing v49 Super-Candidate Boost Bridge]
            // v48 Boost 永遠 +0 的原因：Bias function 只收到 style/draw/score，收不到 SUPER_TIEDAN tag。
            // 本橋接層在排序前用原始名家矩陣資料建立「SUPER候選」代理條件：
            // original_score >=24 且 P1>=4，或 original_score>=25。
            // 然後把 p1_count / expert_count / hit_count 傳入 Bias Engine，令 Boost 真正觸發並入分。
            // =========================================================================
            $wr_v49_p1_count = isset($bh['p1_from']) && is_array($bh['p1_from']) ? count($bh['p1_from']) : 0;
            $wr_v49_expert_count = isset($bh['expert_count']) ? intval($bh['expert_count']) : 0;
            $wr_v49_hit_count = isset($bh['hit_count']) ? intval($bh['hit_count']) : 0;
            $bias_score = wr_ajax_bias_score($final_style, $draw, $original_score, $wr_v49_p1_count, $wr_v49_expert_count, $wr_v49_hit_count);
            $bias_breakdown = wr_ajax_bias_breakdown($final_style, $draw, $original_score, $wr_v49_p1_count, $wr_v49_expert_count, $wr_v49_hit_count);

            // =========================================================================
            // ⚡ [WinRacing v52 Score Power Engine v2｜神級總分強化加權]
            // 目的：Bias / Combo / Boost 已證明生效，但當原始大數據總分差距過大時，
            //      微調無法真正影響排名；因此把歷史回測最穩定的「高總分」直接升權。
            // 回測依據：simulated_score >=25 Top2 約56.9%；SUPER_TIEDAN + score>=25 約58.4%。
            // 設計：只加不刪，Power 作為額外分數寫入 total_score，並在 formula 顯示 Power +X。
            // =========================================================================
            $wr_v51_power_score = 0.0;
            $wr_v51_power_note = 'NO_POWER';
            if ($original_score >= 30) {
                $wr_v51_power_score = 15.0;
                $wr_v51_power_note = 'POWER_SSS：原分>=30｜神級總分強化加權';
            } elseif ($original_score >= 25) {
                $wr_v51_power_score = 10.0;
                $wr_v51_power_note = 'POWER_SS：原分>=25｜高分Top2強化保護';
            } elseif ($original_score >= 20) {
                $wr_v51_power_score = 5.0;
                $wr_v51_power_note = 'POWER_S：原分>=20｜中高分強化輔助';
            }
            if (is_array($bias_breakdown)) {
                $bias_breakdown['power_score'] = round($wr_v51_power_score, 2);
                $bias_breakdown['power_note'] = $wr_v51_power_note;
                $bias_breakdown['engine'] = 'v52_power_engine_v2';
                $bias_breakdown['total_before_power'] = round(floatval($bias_score), 2);
                $bias_breakdown['total'] = round(floatval($bias_score) + $wr_v51_power_score, 2);
                $bias_breakdown['formula'] = strval($bias_breakdown['formula']) . ' + Power +' . round($wr_v51_power_score, 2) . ' = ' . ($bias_breakdown['total'] >= 0 ? '+' : '') . round($bias_breakdown['total'], 2) . '｜' . $wr_v51_power_note;
            }
            $bias_score = round(floatval($bias_score) + $wr_v51_power_score, 2);

            // =========================================================================
            // 🚀 [WinRacing v52 Power Multiplier]
            // 原分>=25 屬歷史高Top2率區間，Power後再做 1.25 倍放大，
            // 令真正高分馬與普通候選拉開，避免只加幾分無法改變排名。
            // =========================================================================
            $wr_v52_power_multiplier = 1.00;
            if ($original_score >= 25) {
                $wr_v52_power_multiplier = 1.25;
                $bias_score = round($bias_score * $wr_v52_power_multiplier, 2);
                if (is_array($bias_breakdown)) {
                    $bias_breakdown['power_multiplier'] = $wr_v52_power_multiplier;
                    $bias_breakdown['total'] = round($bias_score, 2);
                    $bias_breakdown['formula'] .= ' × PowerMultiplier 1.25 = ' . ($bias_score >= 0 ? '+' : '') . round($bias_score, 2) . '｜25+高分倍率';
                }
            }

            // =========================================================================
            // 🏆 [WinRacing v54 Signal Light Engine｜只顯示，不改分]
            // 將已回測的強/弱組合直接輸出到 JSON 及公式，方便 analysis.php 立即顯示。
            // =========================================================================
            $wr_v53_top2_radar = wr_ajax_historical_top2_radar($final_style, $draw, $original_score, $wr_v49_p1_count, $wr_v49_expert_count, $wr_v49_hit_count);
            if (is_array($bias_breakdown)) {
                $bias_breakdown['historical_top2_rate'] = $wr_v53_top2_radar['rate'];
                $bias_breakdown['historical_top2_level'] = $wr_v53_top2_radar['level'];
                $bias_breakdown['historical_top2_label'] = $wr_v53_top2_radar['label'];
                $bias_breakdown['historical_top2_display'] = $wr_v53_top2_radar['display'];
                $bias_breakdown['engine'] = 'v54_signal_light_engine';
                // v54 Signal Light：N/A 不再顯示，避免畫面過長；只顯示有統計價值的訊號燈。
                if (!empty($wr_v53_top2_radar['display'])) {
                    $bias_breakdown['formula'] .= '｜' . $wr_v53_top2_radar['display'];
                }
            }
            $bh['v52_power_multiplier'] = $wr_v52_power_multiplier;
            $bh['original_score'] = round($original_score, 2);
            $bh['bias_engine_version'] = 'v54_signal_light_engine';
            $bh['v49_p1_count'] = $wr_v49_p1_count;
            $bh['v49_expert_count'] = $wr_v49_expert_count;
            $bh['v49_hit_count'] = $wr_v49_hit_count;
            $bh['v49_super_candidate'] = ($wr_v49_p1_count >= 4 && $original_score >= 24) || ($original_score >= 25) ? 1 : 0;
            $bh['v51_power_score'] = round($wr_v51_power_score, 2);
            $bh['v51_power_note'] = $wr_v51_power_note;

            $bh['historical_top2_rate'] = $wr_v53_top2_radar['rate'];
            $bh['historical_top2_level'] = $wr_v53_top2_radar['level'];
            $bh['historical_top2_label'] = $wr_v53_top2_radar['label'];
            $bh['historical_top2_display'] = $wr_v53_top2_radar['display'];
            $bh['bias_v1_score'] = $bias_v1_score;
            $bh['bias_v1_breakdown'] = $bias_v1_breakdown;
            $bh['bias_score'] = $bias_score;
            $bh['bias_breakdown'] = $bias_breakdown;
            $bh['bias_formula'] = $bias_breakdown['formula'];
            $bh['simulated_score'] = round($original_score + $bias_score, 2);
            $bh['adjusted_total_score'] = $bh['simulated_score'];
            $bh['total_score'] = $bh['simulated_score'];
            $bh['draw'] = $draw;
            $bh['draw_category'] = wr_ajax_draw_category($draw);
            $bh['running_style'] = $manual_style;
            $bh['predicted_running_style'] = $pred_style;
            $bh['bias_running_style'] = $final_style;
            $bh['pace_type'] = ($final_style !== '') ? $final_style : 'NORMAL_PACE';
            $bh['running_style_source'] = (is_array($ci) && isset($ci['running_style_source'])) ? strval($ci['running_style_source']) : '';
            $bh['running_style_sample'] = (is_array($ci) && isset($ci['running_style_sample'])) ? intval($ci['running_style_sample']) : 0;
            $bh['card_source_date'] = $card_source_date;
            $bh['target_date'] = $target_date;
        }
        unset($bh);
    }
    unset($bd_horses);
}
unset($bd_races);

// 確立全賽季排名序列
$season_ranked_flow = array();
foreach ($season_expert_matrix as $h_date => $h_races) {
    foreach ($h_races as $hr_no => $h_horses) {
        uasort($h_horses, function($a, $b) {
            if ($a['total_score'] == $b['total_score']) { return ($a['horse_num'] < $b['horse_num']) ? -1 : 1; }
            return ($b['total_score'] <=> $a['total_score']);
        });
        $season_ranked_flow[$h_date][$hr_no] = array_values($h_horses);
    }
}

$today_races_nodes = $season_ranked_flow[$target_date] ?? array();

// 預算重心場次候選
$zhongxin_candidates = array(); 
foreach ($today_races_nodes as $r_num => $horses) {
    if (empty($horses)) continue;
    $top_score_1 = $horses[0];
    $top_score_2 = isset($horses[1]) ? $horses[1] : null;
    $score_gap = $top_score_2 ? ($top_score_1['total_score'] - $top_score_2['total_score']) : $top_score_1['total_score'];

    $is_qualified = ($score_gap >= 4 && $top_score_1['total_score'] >= 11 && $top_score_1['hit_count'] >= 2);
    if ($is_qualified) {
        $strength = ($top_score_1['total_score'] * 10) + ($score_gap * 5) + $top_score_1['hit_count'];
        $zhongxin_candidates[$r_num] = $strength;
    }
}
arsort($zhongxin_candidates);
$top_3_races = array_slice(array_keys($zhongxin_candidates), 0, 3);

// 採集自開季以來的 7分表分數軌跡
$history_7scores_flow = array();
$h_7_sql = "SELECT race_date, race_no, horse_number, score FROM race_7_scores WHERE race_date >= '2025-09-28' AND race_date <= ? ORDER BY race_date ASC, race_no ASC, id ASC";
if ($h_7_sql) {
    $h_7_stmt = $conn->prepare($h_7_sql);
    $h_7_stmt->bind_param("s", $target_date);
    $h_7_stmt->execute();
    $h_7_res = $h_7_stmt->get_result();
    while ($h_7_row = $h_7_res->fetch_assoc()) {
        $hd = $h_7_row['race_date'];
        $rn = intval($h_7_row['race_no']);
        $history_7scores_flow[$hd][$rn][] = array(
            'horse' => intval($h_7_row['horse_number']),
            'score' => intval($h_7_row['score'])
        );
    }
    $h_7_stmt->close();
}

$final_dashboard = array();

// Helper 函數：10級精細化總分階梯配置
function getScoreBandConfig($score) {
    $s = floatval($score);
    if ($s >= 19 && $s <= 20) return array('min' => 19, 'max' => 20, 'boost' => 1.10);
    if ($s >= 21 && $s <= 22) return array('min' => 21, 'max' => 22, 'boost' => 1.20);
    if ($s >= 23 && $s <= 24) return array('min' => 23, 'max' => 24, 'boost' => 1.30);
    if ($s >= 25 && $s <= 26) return array('min' => 25, 'max' => 26, 'boost' => 1.45);
    if ($s >= 27 && $s <= 28) return array('min' => 27, 'max' => 28, 'boost' => 1.60);
    if ($s >= 29 && $s <= 30) return array('min' => 29, 'max' => 30, 'boost' => 1.80);
    if ($s >= 31 && $s <= 32) return array('min' => 31, 'max' => 32, 'boost' => 2.00);
    if ($s >= 33 && $s <= 34) return array('min' => 33, 'max' => 34, 'boost' => 2.25);
    if ($s >= 35 && $s <= 36) return array('min' => 35, 'max' => 36, 'boost' => 2.50);
    if ($s > 36)              return array('min' => 36.1, 'max' => 999, 'boost' => 3.00);
    return array('min' => 0, 'max' => 18.9, 'boost' => 1.00);
}



// =========================================================================
// 🔥 [WinRacing v37 AJAX Bias Engine｜只加不刪]
// 目的：get_analysis_ajax.php 係畫面矩陣真正分數來源；
//      在排序前加入 race_card_static 的 predicted_running_style + draw Bias。
// 優先次序：running_style 手動值 > predicted_running_style 歷史推算值 > 空白。
// =========================================================================
function wr_ajax_draw_category($draw) {
    $d = intval($draw);
    if ($d >= 1 && $d <= 4) return '內檔';
    if ($d >= 5 && $d <= 8) return '中檔';
    if ($d >= 9 && $d <= 12) return '外檔';
    if ($d > 12) return '田大外檔';
    return '未知';
}

function wr_ajax_norm_style($style) {
    $s = trim(strval($style));
    if ($s === '' || strtolower($s) === 'nan' || strtoupper($s) === 'NULL') return '';
    if ($s === '跟前') return '咬前';
    if ($s === '置中') return '中置';
    if ($s === '前置') return '咬前';
    if ($s === '領放') return '放頭';
    if ($s === '留後') return '後上';
    return $s;
}

function wr_ajax_bias_score_v1($style, $draw) {
    $style = wr_ajax_norm_style($style);
    $draw_category = wr_ajax_draw_category($draw);
    $bias = 0.0;

    // WinRacing v38 Half Bias Test（保留作對照）
    if ($style === '放頭') {
        $bias += 2.5;
    } elseif ($style === '咬前' || $style === '跟前') {
        $bias += 1.5;
    } elseif ($style === '中置' || $style === '置中') {
        $bias += 0.0;
    } elseif ($style === '後上') {
        $bias -= 2.0;
    }

    if ($draw_category === '內檔') {
        $bias += 2.0;
    } elseif ($draw_category === '中檔') {
        $bias += 0.5;
    } elseif ($draw_category === '外檔') {
        $bias -= 1.0;
    } elseif ($draw_category === '田大外檔') {
        $bias -= 2.5;
    }

    if ($bias > 6.0) $bias = 6.0;
    if ($bias < -5.0) $bias = -5.0;
    return round($bias, 2);
}

function wr_ajax_bias_breakdown_v1($style, $draw) {
    $style = wr_ajax_norm_style($style);
    $draw_category = wr_ajax_draw_category($draw);
    $style_score = 0.0;
    $draw_score = 0.0;

    if ($style === '放頭') $style_score = 2.5;
    elseif ($style === '咬前' || $style === '跟前') $style_score = 1.5;
    elseif ($style === '中置' || $style === '置中') $style_score = 0.0;
    elseif ($style === '後上') $style_score = -2.0;

    if ($draw_category === '內檔') $draw_score = 2.0;
    elseif ($draw_category === '中檔') $draw_score = 0.5;
    elseif ($draw_category === '外檔') $draw_score = -1.0;
    elseif ($draw_category === '田大外檔') $draw_score = -2.5;

    $raw = $style_score + $draw_score;
    $total = $raw;
    if ($total > 6.0) $total = 6.0;
    if ($total < -5.0) $total = -5.0;

    $signStyle = $style_score >= 0 ? '+' : '';
    $signDraw = $draw_score >= 0 ? '+' : '';
    $signTotal = $total >= 0 ? '+' : '';
    return array(
        'engine' => 'v38_half_bias',
        'style' => $style,
        'style_score' => round($style_score, 2),
        'draw' => intval($draw),
        'draw_category' => $draw_category,
        'draw_score' => round($draw_score, 2),
        'total' => round($total, 2),
        'formula' => (($style !== '' ? $style : '無跑法') . ' ' . $signStyle . round($style_score, 2) . ' + ' . $draw_category . ' ' . $signDraw . round($draw_score, 2) . ' = ' . $signTotal . round($total, 2))
    );
}

// =========================================================================
// 🧠 WinRacing v50 Bias Engine v5｜Visible Combo Boost 實戰版
// 依 2025-10-01 至今回測結果強化：
// - SUPER_TIEDAN + 咬前 + 中檔 Top2 75.00% → 強升權
// - SUPER_TIEDAN + 放頭 + 中檔 Top2 73.91% → 強升權
// - SUPER_TIEDAN + 咬前 Top2 71.43% → 升權
// - SUPER_TIEDAN + 中置 Top2 43.14% → 降權
// - SUPER_TIEDAN + 放頭 + 內檔 Top2 14.29% → 強降權警告
// 設計原則：讓回測已驗證的「前速中檔」真正影響排名，而非只作顯示。
// =========================================================================

// =========================================================================
// 🏆 WinRacing v54 Signal Light Engine｜只顯示，不改分
// 目的：不再繼續加 Bias / Power，而是在每匹馬輸出歷史Top2雷達，
//      讓畫面同時看到「大數據總分」及「歷史組合命中率」。
// 注意：此函數完全不改 total_score，只寫入 JSON 欄位及公式說明。
// =========================================================================
function wr_ajax_historical_top2_radar($style, $draw, $original_score = 0, $p1_count = 0, $expert_count = 0, $hit_count = 0) {
    $style = wr_ajax_norm_style($style);
    $draw_category = wr_ajax_draw_category($draw);
    $score = floatval($original_score);
    $p1_count = intval($p1_count);
    $is_super_candidate = (($p1_count >= 4 && $score >= 24) || ($score >= 25));

    $rate = null;
    $level = 'NO_DATA';
    $label = '未命中已回測組合';
    $emoji = '▫️';

    if ($is_super_candidate && ($style === '咬前' || $style === '跟前') && $draw_category === '中檔') {
        $rate = 75.00; $level = 'SSS'; $emoji = '🏆'; $label = 'SUPER候選 + 咬前 + 中檔｜歷史Top2 75.00%';
    } elseif ($is_super_candidate && $style === '放頭' && $draw_category === '中檔') {
        $rate = 73.91; $level = 'SS'; $emoji = '🏆'; $label = 'SUPER候選 + 放頭 + 中檔｜歷史Top2 73.91%';
    } elseif ($is_super_candidate && ($style === '咬前' || $style === '跟前')) {
        $rate = 71.43; $level = 'S'; $emoji = '👍'; $label = 'SUPER候選 + 咬前｜歷史Top2 71.43%';
    } elseif ($is_super_candidate && $style === '放頭' && $draw_category === '內檔') {
        $rate = 14.29; $level = 'DANGER'; $emoji = '💀'; $label = 'SUPER候選 + 放頭 + 內檔｜歷史Top2 14.29%';
    } elseif ($style === '放頭' && $draw_category === '內檔') {
        $rate = 14.29; $level = 'DANGER'; $emoji = '💀'; $label = '放頭 + 內檔｜歷史低效Top2 14.29%';
    } elseif ($is_super_candidate && $style === '中置') {
        $rate = 43.14; $level = 'WEAK'; $emoji = '⚠️'; $label = 'SUPER候選 + 中置｜歷史Top2 43.14%';
    } elseif ($is_super_candidate && $draw_category === '中檔') {
        $rate = 62.65; $level = 'A'; $emoji = '🔥'; $label = 'SUPER候選 + 中檔｜歷史Top2 62.65%';
    } elseif ($is_super_candidate && $style === '後上') {
        $rate = 59.46; $level = 'A-'; $emoji = '👍'; $label = 'SUPER候選 + 後上｜歷史Top2 59.46%';
    } elseif ($is_super_candidate && $score >= 25) {
        $rate = 58.40; $level = 'A-'; $emoji = '👍'; $label = 'SUPER候選 + 25分以上｜歷史Top2 58.40%';
    } elseif ($score >= 25) {
        $rate = 56.94; $level = 'A-'; $emoji = '👍'; $label = '原分25+｜歷史Top2 56.94%';
    } elseif ($is_super_candidate && $draw_category === '內檔') {
        $rate = 44.29; $level = 'WEAK'; $emoji = '⚠️'; $label = 'SUPER候選 + 內檔｜歷史Top2 44.29%';
    }

    // v54 Signal Light：沒有命中已回測組合時，display 留空，不再輸出 N/A。
    if (is_null($rate)) {
        $display = '';
    } elseif ($rate >= 70) {
        $display = '🏆 神級組合｜Top2 ' . number_format($rate, 2) . '%';
    } elseif ($rate >= 60) {
        $display = '🟢 強組合｜Top2 ' . number_format($rate, 2) . '%';
    } elseif ($rate >= 40) {
        $display = '🟡 普通組合｜Top2 ' . number_format($rate, 2) . '%';
    } else {
        $display = '💀 高危組合｜Top2 ' . number_format($rate, 2) . '%';
    }

    return array(
        'rate' => is_null($rate) ? null : round($rate, 2),
        'level' => $level,
        'label' => $label,
        'emoji' => $emoji,
        'display' => $display
    );
}

function wr_ajax_bias_score($style, $draw, $original_score = 0, $p1_count = 0, $expert_count = 0, $hit_count = 0) {
    $bd = wr_ajax_bias_breakdown($style, $draw, $original_score, $p1_count, $expert_count, $hit_count);
    return round(floatval($bd['total']), 2);
}

function wr_ajax_bias_breakdown($style, $draw, $original_score = 0, $p1_count = 0, $expert_count = 0, $hit_count = 0) {
    $style = wr_ajax_norm_style($style);
    $draw_category = wr_ajax_draw_category($draw);
    $score = floatval($original_score);
    $p1_count = intval($p1_count);
    $expert_count = intval($expert_count);
    $hit_count = intval($hit_count);
    $is_super_candidate = (($p1_count >= 4 && $score >= 24) || ($score >= 25));

    $style_score = 0.0;
    $draw_score = 0.0;
    $combo_score = 0.0;
    $boost_score = 0.0;
    $tier_note = 'NORMAL';

    // v47 基礎跑法分：咬前升權；放頭保守；中置降級；後上微扣
    if ($style === '咬前' || $style === '跟前') {
        $style_score = 1.5;
    } elseif ($style === '放頭') {
        $style_score = 1.0;
    } elseif ($style === '後上') {
        $style_score = -0.8;
    } elseif ($style === '中置' || $style === '置中') {
        $style_score = -1.5;
    }

    // v47 檔位分：中檔經回測證明係鐵膽高效區；內檔只作小加，不再盲撐
    if ($draw_category === '中檔') {
        $draw_score = 2.0;
    } elseif ($draw_category === '內檔') {
        $draw_score = 0.5;
    } elseif ($draw_category === '外檔') {
        $draw_score = -1.0;
    } elseif ($draw_category === '田大外檔') {
        $draw_score = -2.5;
    }

    // v47 組合校準：直接由回測勝率轉成強權重
    if (($style === '咬前' || $style === '跟前') && $draw_category === '中檔') {
        $combo_score += 2.5;
        $tier_note = 'SSS：咬前+中檔｜回測Top2 75%';
    } elseif ($style === '放頭' && $draw_category === '中檔') {
        $combo_score += 2.2;
        $tier_note = 'SS：放頭+中檔｜回測Top2 73.91%';
    } elseif (($style === '咬前' || $style === '跟前') && $draw_category === '內檔') {
        $combo_score += 1.0;
        $tier_note = 'S：咬前+內檔';
    } elseif ($style === '後上' && $draw_category === '中檔') {
        $combo_score += 1.0;
        $tier_note = 'A：後上+中檔';
    } elseif ($style === '放頭' && $draw_category === '內檔') {
        $combo_score -= 4.0;
        $tier_note = '⚠️ 強降權：放頭+內檔｜回測Top2 14.29%';
    } elseif ($style === '中置' || $style === '置中') {
        $combo_score -= 1.0;
        $tier_note = '降級：中置｜回測Top2偏低';
    }

    // =========================================================================
    // 🔥 v50 Visible Combo Boost：不再只等 SUPER候選才顯示 Boost。
    // 目的：令回測證明有效/低效的跑法+檔位組合，即使未達 SUPER，也會在畫面及排名中可見。
    // SUPER候選仍有額外加權；非SUPER亦有實戰權重。
    // =========================================================================
    if (($style === '咬前' || $style === '跟前') && $draw_category === '中檔') {
        if ($is_super_candidate) {
            $boost_score += 5.0;
            $tier_note = 'SSS：SUPER候選 + 咬前 + 中檔｜回測Top2 75%';
        } else {
            $boost_score += 3.0;
            $tier_note = 'A+：咬前 + 中檔｜前速中檔升權';
        }
    } elseif ($style === '放頭' && $draw_category === '中檔') {
        if ($is_super_candidate) {
            $boost_score += 4.0;
            $tier_note = 'SS：SUPER候選 + 放頭 + 中檔｜回測Top2 73.91%';
        } else {
            $boost_score += 2.5;
            $tier_note = 'A：放頭 + 中檔｜前速中檔升權';
        }
    } elseif ($style === '放頭' && $draw_category === '內檔') {
        if ($is_super_candidate) {
            $boost_score -= 4.0;
            $tier_note = '⚠️ 強降權：SUPER候選 + 放頭 + 內檔｜回測Top2 14.29%';
        } else {
            $boost_score -= 2.5;
            $tier_note = '⚠️ 降權：放頭 + 內檔｜回測低效警告';
        }
    } elseif ($style === '中置' || $style === '置中') {
        if ($is_super_candidate) {
            $boost_score -= 2.0;
            $tier_note = '降級：SUPER候選 + 中置｜回測Top2偏低';
        } else {
            $boost_score -= 1.0;
            $tier_note = '降權：中置｜回測Top2偏低';
        }
    }

    if ($score >= 25 && $boost_score >= 0) {
        $boost_score += 2.0;
        if ($tier_note === 'NORMAL') $tier_note = 'S：25+高分保護Boost';
        else $tier_note .= '｜25+高分保護Boost';
    }

    // 25分以上保護：只保護真正高分馬不被過度打沉，但保留低效組合警告
    $raw = $style_score + $draw_score + $combo_score + $boost_score;
    if ($score >= 25 && $raw < -1.5) {
        $raw = -1.5;
        $tier_note .= '｜25+保護下限';
    }

    // v49 安全閘：SUPER候選可強烈影響排名，但仍避免完全蓋過名家矩陣
    $total = $raw;
    if ($total > 10.0) $total = 10.0;
    if ($total < -7.0) $total = -7.0;

    $signStyle = $style_score >= 0 ? '+' : '';
    $signDraw = $draw_score >= 0 ? '+' : '';
    $signCombo = $combo_score >= 0 ? '+' : '';
    $signBoost = $boost_score >= 0 ? '+' : '';
    $signTotal = $total >= 0 ? '+' : '';

    return array(
        'engine' => 'v52_power_engine_v2',
        'style' => $style,
        'style_score' => round($style_score, 2),
        'draw' => intval($draw),
        'draw_category' => $draw_category,
        'draw_score' => round($draw_score, 2),
        'combo_score' => round($combo_score, 2),
        'boost_score' => round($boost_score, 2),
        'p1_count' => $p1_count,
        'expert_count' => $expert_count,
        'hit_count' => $hit_count,
        'is_super_candidate' => $is_super_candidate ? 1 : 0,
        'original_score' => round($score, 2),
        'tier_note' => $tier_note,
        'total' => round($total, 2),
        'formula' => (($style !== '' ? $style : '無跑法') . ' ' . $signStyle . round($style_score, 2) . ' + ' . $draw_category . ' ' . $signDraw . round($draw_score, 2) . ' + Combo ' . $signCombo . round($combo_score, 2) . ' + Boost ' . $signBoost . round($boost_score, 2) . ' = ' . $signTotal . round($total, 2) . '｜' . $tier_note)
    );
}

function wr_ajax_col_exists($conn, $table, $col) {
    $safeTable = $conn->real_escape_string($table);
    $safeCol = $conn->real_escape_string($col);
    $q = $conn->query("SHOW COLUMNS FROM `$safeTable` LIKE '$safeCol'");
    return ($q && $q->num_rows > 0);
}
function isScoreInBand($score, $band) {
    $s = floatval($score);
    if ($band['min'] == 36.1) { return $s > 36; }
    return ($s >= $band['min'] && $s <= $band['max']);
}

// 6. 今日賽日 1 至 11 場，縱向大數據滾動追蹤
foreach ($today_races_nodes as $r_num => $sorted_horses) {
    if (empty($sorted_horses)) continue;

    $top_score_1 = $sorted_horses[0];
    $top_score_2 = isset($sorted_horses[1]) ? $sorted_horses[1] : null;
    $score_gap = $top_score_2 ? ($top_score_1['total_score'] - $top_score_2['total_score']) : $top_score_1['total_score'];

    $type = "CIXUAN"; $dan_text = "-"; $jiao_text = "-"; $exclude_dans = array();

    // =========================================================================
    // 🌟 [戰術場合推薦引擎：膽與配腳全自動演算段]
    // =========================================================================
    if (in_array($r_num, $top_3_races)) {
        if ($top_score_1['total_score'] >= 24 && count($top_score_1['p1_from']) >= 4 && $score_gap > 11) { 
            $type = "ZHONGXIN_3"; $dan_text = "【超級鐵膽】 " . $top_score_1['horse_num'] . " 號馬"; 
        } else if ($top_score_1['total_score'] >= 13 && $score_gap >= 5 && $top_score_1['hit_count'] >= 3) { 
            $type = "ZHONGXIN_2"; $dan_text = "【聚焦精選膽】 " . $top_score_1['horse_num'] . " 號馬"; 
        } else { 
            $type = "ZHONGXIN_1"; $dan_text = "【正路穩健膽】 " . $top_score_1['horse_num'] . " 號馬"; 
        }
        $exclude_dans[] = $top_score_1['horse_num'];
    } else if ($top_score_1['total_score'] < 10) {
        $type = "LENGBAO"; $dan_text = "【隱藏冷膽】 " . $top_score_1['horse_num'] . " 號馬";
        $exclude_dans[] = $top_score_1['horse_num'];
    } else {
        // 雙膽互托局面
        $type = "CIXUAN"; 
        $h2_id = isset($sorted_horses[1]) ? $sorted_horses[1]['horse_num'] : '?';
        $dan_text = "【雙膽互托】 " . $top_score_1['horse_num'] . " 號 及 " . $h2_id . " 號馬";
        $exclude_dans[] = $top_score_1['horse_num'];
        if (isset($sorted_horses[1])) { $exclude_dans[] = $sorted_horses[1]['horse_num']; }
    }

    // 🌟 完美復活：全自動篩選大數據綜合實力最高的前 5 隻「配腳馬」
    $jiao_arr = array();
    foreach ($sorted_horses as $h_check) {
        if (!in_array($h_check['horse_num'], $exclude_dans)) {
            $jiao_arr[] = $h_check['horse_num'] . " 號馬";
            if (count($jiao_arr) === 5) { break; } // 精確鎖定5隻
        }
    }
    $jiao_text = !empty($jiao_arr) ? implode(' , ', $jiao_arr) : "-";

    $ec1 = isset($sorted_horses[0]) ? intval($sorted_horses[0]['expert_count']) : 0;
    $ec2 = isset($sorted_horses[1]) ? intval($sorted_horses[1]['expert_count']) : 0;
    
    $h1_num = isset($sorted_horses[0]) ? intval($sorted_horses[0]['horse_num']) : 0;
    $h2_num = isset($sorted_horses[1]) ? intval($sorted_horses[1]['horse_num']) : 0;

    $score_val1 = floatval($sorted_horses[0]['total_score']);
    $score_val2 = isset($sorted_horses[1]) ? floatval($sorted_horses[1]['total_score']) : 0;

    $band_config1 = getScoreBandConfig($score_val1);
    $band_config2 = getScoreBandConfig($score_val2);

    $race_tag = ""; 
    if ($ec1 == 6 && $ec2 <= 3 && $score_val1 > 20) { $race_tag = "ZHONGXIN"; }
    elseif (($ec1 == 6 && $ec2 == 6) || ($ec1 == 5 && $ec2 == 5)) { $race_tag = "SUB_ZHONGXIN"; }

    $probability_output = array(); 
    $total_win_ratio_output = array(); 
    $over22_win_ratio_output = array(); 
    $weighted_score_output = array(); 

    // A. 基礎機率計數器
    $c1_total = 0; $c1_win = 0; $c2_total = 0; $c2_win1 = 0; $c2_win2 = 0; $c3_total = 0; $c3_win1 = 0; $c3_win2 = 0; 
    $c4_total = 0; $c4_win = 0; $c5_total = 0; $c5_win1 = 0; $c5_win2 = 0; $c7_total = 0; $c7_win1 = 0; $c7_win2 = 0; 

    // B. >20分線計數器 (總勝出率)
    $r1_total = 0; $r1_win = 0; $r2_total = 0; $r2_win1 = 0; $r2_win2 = 0; $r3_total = 0; $r3_win1 = 0; $r3_win2 = 0; 
    $r4_total = 0; $r4_win = 0; $r5_total = 0; $r5_win1 = 0; $r5_win2 = 0; $r7_total = 0; $r7_win1 = 0; $r7_win2 = 0; 

    // C. 10級精細化區間計數器 (動態門檻勝率)
    $v1_total = 0; $v1_win = 0; $v2_total = 0; $v2_win1 = 0; $v2_win2 = 0; $v3_total = 0; $v3_win1 = 0; $v3_win2 = 0; 
    $v4_total = 0; $v4_win = 0; $v5_total = 0; $v5_win1 = 0; $v5_win2 = 0; $v7_total = 0; $v7_win1 = 0; $v7_win2 = 0; 

    $is_probability_pattern = false;
    if (($ec1 == 6 && $ec2 != 6) || ($ec1 == 6 && $ec2 == 6) || ($ec1 == 5 && $ec2 == 5) || ($ec1 > 6) || ($ec2 > 6) || ($ec1 == 5 && $ec2 == 4) || ($ec1 == 4 && $ec2 == 5)) {
        $is_probability_pattern = true;
    }

    if ($is_probability_pattern) {
        foreach ($season_ranked_flow as $h_date => $h_races) {
            foreach ($h_races as $hr_no => $h_horses) {
                if ($h_date === $target_date && $hr_no == $r_num) {
                    if (!isset($results_map[$h_date][$hr_no]) || $results_map[$h_date][$hr_no] <= 0) { continue 2; }
                }
                if ($h_date === $target_date && $hr_no > $r_num) { continue 2; }
                if (count($h_horses) < 2) continue;

                $act_win_uid = intval($results_map[$h_date][$hr_no] ?? 0);
                $hec1 = intval($h_horses[0]['expert_count']);
                $hec2 = intval($h_horses[1]['expert_count']);
                
                $h_score1 = floatval($h_horses[0]['total_score']);
                $h_score2 = floatval($h_horses[1]['total_score']);

                $hist_h1 = intval($h_horses[0]['horse_num']);
                $hist_h2 = intval($h_horses[1]['horse_num']);

                if ($ec1 == 6 && $ec2 != 6) {
                    if ($hec1 == 6 && $hec2 != 6) {
                        $c1_total++; if ($hist_h1 == $act_win_uid) $c1_win++;
                        if ($h_score1 > 20) { $r1_total++; if ($hist_h1 == $act_win_uid) $r1_win++; }
                        if (isScoreInBand($h_score1, $band_config1)) { $v1_total++; if ($hist_h1 == $act_win_uid) $v1_win++; }
                    }
                }
                elseif ($ec1 == 6 && $ec2 == 6) {
                    if ($hec1 == 6 && $hec2 == 6) {
                        $c2_total++; if ($hist_h1 == $act_win_uid) $c2_win1++; if ($hist_h2 == $act_win_uid) $c2_win2++;
                        
                        if ($h_score1 > 20 || $h_score2 > 20) { $r2_total++; }
                        if ($h_score1 > 20 && $hist_h1 == $act_win_uid) $r2_win1++;
                        if ($h_score2 > 20 && $hist_h2 == $act_win_uid) $r2_win2++;
                        
                        if (isScoreInBand($h_score1, $band_config1) || isScoreInBand($h_score2, $band_config2)) { $v2_total++; }
                        if (isScoreInBand($h_score1, $band_config1) && $hist_h1 == $act_win_uid) $v2_win1++;
                        if (isScoreInBand($h_score2, $band_config2) && $hist_h2 == $act_win_uid) $v2_win2++;
                    }
                }
                elseif ($ec1 == 5 && $ec2 == 5) {
                    if ($hec1 == 5 && $hec2 == 5) {
                        $c3_total++; if ($hist_h1 == $act_win_uid) $c3_win1++; if ($hist_h2 == $act_win_uid) $c3_win2++;
                        
                        if ($h_score1 > 20 || $h_score2 > 20) { $r3_total++; }
                        if ($h_score1 > 20 && $hist_h1 == $act_win_uid) $r3_win1++;
                        if ($h_score2 > 20 && $hist_h2 == $act_win_uid) $r3_win2++;
                        
                        if (isScoreInBand($h_score1, $band_config1) || isScoreInBand($h_score2, $band_config2)) { $v3_total++; }
                        if (isScoreInBand($h_score1, $band_config1) && $hist_h1 == $act_win_uid) $v3_win1++;
                        if (isScoreInBand($h_score2, $band_config2) && $hist_h2 == $act_win_uid) $v3_win2++;
                    }
                }
                elseif ($ec1 == 5 && $ec2 == 4) {
                    if ($hec1 == 5 && $hec2 == 4) {
                        $c5_total++; if ($hist_h1 == $act_win_uid) $c5_win1++; if ($hist_h2 == $act_win_uid) $c5_win2++;
                        
                        if ($h_score1 > 20 || $h_score2 > 20) { $r5_total++; }
                        if ($h_score1 > 20 && $hist_h1 == $act_win_uid) $r5_win1++;
                        if ($h_score2 > 20 && $hist_h2 == $act_win_uid) $r5_win2++;
                        
                        if (isScoreInBand($h_score1, $band_config1) || isScoreInBand($h_score2, $band_config2)) { $v5_total++; }
                        if (isScoreInBand($h_score1, $band_config1) && $hist_h1 == $act_win_uid) $v5_win1++;
                        if (isScoreInBand($h_score2, $band_config2) && $hist_h2 == $act_win_uid) $v5_win2++;
                    }
                }
                elseif ($ec1 == 4 && $ec2 == 5) {
                    if ($hec1 == 4 && $hec2 == 5) {
                        $c7_total++; if ($hist_h1 == $act_win_uid) $c7_win1++; if ($hist_h2 == $act_win_uid) $c7_win2++;
                        
                        if ($h_score1 > 20 || $h_score2 > 20) { $r7_total++; }
                        if ($h_score1 > 20 && $hist_h1 == $act_win_uid) $r7_win1++;
                        if ($h_score2 > 20 && $hist_h2 == $act_win_uid) $r7_win2++;
                        
                        if (isScoreInBand($h_score1, $band_config1) || isScoreInBand($h_score2, $band_config2)) { $v7_total++; }
                        if (isScoreInBand($h_score1, $band_config1) && $hist_h1 == $act_win_uid) $v7_win1++;
                        if (isScoreInBand($h_score2, $band_config2) && $hist_h2 == $act_win_uid) $v7_win2++;
                    }
                }
                
                if ($ec1 > 6 || $ec2 > 6) {
                    if ($hec1 > 6 && $hec2 <= 6) {
                        $c4_total++; if ($hist_h1 == $act_win_uid) $c4_win++;
                        if ($h_score1 > 20) { $r4_total++; if ($hist_h1 == $act_win_uid) $r4_win++; }
                        if (isScoreInBand($h_score1, $band_config1)) { $v4_total++; if ($hist_h1 == $act_win_uid) $v4_win++; }
                    } elseif ($hec1 <= 6 && $hec2 > 6) {
                        $c4_total++; if ($hist_h2 == $act_win_uid) $c4_win++;
                        if ($h_score2 > 20) { $r4_total++; if ($hist_h2 == $act_win_uid) $r4_win++; }
                        if (isScoreInBand($h_score2, $band_config2)) { $v4_total++; if ($hist_h2 == $act_win_uid) $v4_win++; }
                    } elseif ($hec1 > 6 && $hec2 > 6) {
                        $c4_total++; if ($hist_h1 == $act_win_uid || $hist_h2 == $act_win_uid) { $c4_win++; }
                        if ($h_score1 > 20 || $h_score2 > 20) { $r4_total++; if (($h_score1 > 20 && $hist_h1 == $act_win_uid) || ($h_score2 > 20 && $hist_h2 == $act_win_uid)) { $r4_win++; } }
                        if (isScoreInBand($h_score1, $band_config1) || isScoreInBand($h_score2, $band_config2)) { $v4_total++; if ((isScoreInBand($h_score1, $band_config1) && $hist_h1 == $act_win_uid) || (isScoreInBand($h_score2, $band_config2) && $hist_h2 == $act_win_uid)) { $v4_win++; } }
                    }
                }
            }
        }
    }

    $premium_mult1 = 1.0; $premium_mult2 = 1.0;
    if ($score_val1 >= 27) $premium_mult1 = 1.50; elseif ($score_val1 >= 25) $premium_mult1 = 1.30; elseif ($score_val1 >= 23) $premium_mult1 = 1.15;
    if ($score_val2 >= 27) $premium_mult2 = 1.50; elseif ($score_val2 >= 25) $premium_mult2 = 1.30; elseif ($score_val2 >= 23) $premium_mult2 = 1.15;

    if ($ec1 == 6 && $ec2 != 6) {
        if ($c1_total > 0) { $probability_output[$h1_num] = "<b>{$c1_win} / {$c1_total}</b><br><small class='text-success'>(".round(($c1_win / $c1_total) * 100, 1)."%)</small>"; }
        if ($r1_total > 0) { $total_win_ratio_output[$h1_num] = "<b>{$r1_win} / {$r1_total}</b><br><small class='text-success'>(".round(($r1_win / $r1_total) * 100, 1)."%)</small>"; }
        if ($v1_total > 0) { $over22_win_ratio_output[$h1_num] = "<b>{$v1_win} / {$v1_total}</b><br><small class='text-success'>(".round(($v1_win / $v1_total) * 100, 1)."%)</small>"; }
        if ($c1_total > 0 && $r1_total > 0 && $v1_total > 0) {
            $p_avg = (($c1_win / $c1_total) + ($r1_win / $r1_total) + ($v1_win / $v1_total)) / 3;
            $final_ev_score = $p_avg * 100 * floatval($band_config1['boost']) * $premium_mult1;
            if ($final_ev_score > 100) $final_ev_score = 100; 
            $weighted_score_output[$h1_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($final_ev_score, 1)."分</strong>";
        }
    } 
    elseif ($ec1 == 6 && $ec2 == 6) {
        if ($c2_total > 0) {
            $probability_output[$h1_num] = "<b>{$c2_win1} / {$c2_total}</b><br><small class='text-warning'>(".round(($c2_win1 / $c2_total) * 100, 1)."%)</small>";
            $probability_output[$h2_num] = "<b>{$c2_win2} / {$c2_total}</b><br><small class='text-warning'>(".round(($c2_win2 / $c2_total) * 100, 1)."%)</small>";
        }
        if ($r2_total > 0) {
            $total_win_ratio_output[$h1_num] = "<b>{$r2_win1} / {$r2_total}</b><br><small class='text-warning'>(".round(($r2_win1 / $r2_total) * 100, 1)."%)</small>";
            $total_win_ratio_output[$h2_num] = "<b>{$r2_win2} / {$r2_total}</b><br><small class='text-warning'>(".round(($r2_win2 / $r2_total) * 100, 1)."%)</small>";
        }
        if ($v2_total > 0) {
            $over22_win_ratio_output[$h1_num] = "<b>{$v2_win1} / {$v2_total}</b><br><small class='text-warning'>(".round(($v2_win1 / $v2_total) * 100, 1)."%)</small>";
            $over22_win_ratio_output[$h2_num] = "<b>{$v2_win2} / {$v2_total}</b><br><small class='text-warning'>(".round(($v2_win2 / $v2_total) * 100, 1)."%)</small>";
            if ($c2_total > 0 && $r2_total > 0 && $v2_total > 0) {
                $ev1 = ((($c2_win1 / $c2_total) + ($r2_win1 / $r2_total) + ($v2_win1 / $v2_total)) / 3) * 100 * floatval($band_config1['boost']) * $premium_mult1;
                $ev2 = ((($c2_win2 / $c2_total) + ($r2_win2 / $r2_total) + ($v2_win2 / $v2_total)) / 3) * 100 * floatval($band_config2['boost']) * $premium_mult2;
                if ($ev1 > 100) $ev1 = 100; if ($ev2 > 100) $ev2 = 100;
                $weighted_score_output[$h1_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev1, 1)."分</strong>";
                $weighted_score_output[$h2_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev2, 1)."分</strong>";
            }
        }
    } 
    elseif ($ec1 == 5 && $ec2 == 5) {
        if ($c3_total > 0) {
            $probability_output[$h1_num] = "<b>{$c3_win1} / {$c3_total}</b><br><small class='text-info'>(".round(($c3_win1 / $c3_total) * 100, 1)."%)</small>";
            $probability_output[$h2_num] = "<b>{$c3_win2} / {$c3_total}</b><br><small class='text-info'>(".round(($c3_win2 / $c3_total) * 100, 1)."%)</small>";
        }
        if ($r3_total > 0) {
            $total_win_ratio_output[$h1_num] = "<b>{$r3_win1} / {$r3_total}</b><br><small class='text-info'>(".round(($r3_win1 / $r3_total) * 100, 1)."%)</small>";
            $total_win_ratio_output[$h2_num] = "<b>{$r3_win2} / {$r3_total}</b><br><small class='text-info'>(".round(($r3_win2 / $r3_total) * 100, 1)."%)</small>";
        }
        if ($v3_total > 0) {
            $over22_win_ratio_output[$h1_num] = "<b>{$v3_win1} / {$v3_total}</b><br><small class='text-info'>(".round(($v3_win1 / $v3_total) * 100, 1)."%)</small>";
            $over22_win_ratio_output[$h2_num] = "<b>{$v3_win2} / {$v3_total}</b><br><small class='text-info'>(".round(($v3_win2 / $v3_total) * 100, 1)."%)</small>";
            if ($c3_total > 0 && $r3_total > 0 && $v3_total > 0) {
                $ev1 = ((($c3_win1 / $c3_total) + ($r3_win1 / $r3_total) + ($v3_win1 / $v3_total)) / 3) * 100 * floatval($band_config1['boost']) * $premium_mult1;
                $ev2 = ((($c3_win2 / $c3_total) + ($r3_win2 / $r3_total) + ($v3_win2 / $v3_total)) / 3) * 100 * floatval($band_config2['boost']) * $premium_mult2;
                if ($ev1 > 100) $ev1 = 100; if ($ev2 > 100) $ev2 = 100;
                $weighted_score_output[$h1_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev1, 1)."分</strong>";
                $weighted_score_output[$h2_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev2, 1)."分</strong>";
            }
        }
    } 
    elseif ($ec1 == 5 && $ec2 == 4) {
        if ($c5_total > 0) {
            $probability_output[$h1_num] = "<b>{$c5_win1} / {$c5_total}</b><br><small style='color:#a29bfe;'>(".round(($c5_win1 / $c5_total) * 100, 1)."%)</small>";
            $probability_output[$h2_num] = "<b>{$c5_win2} / {$c5_total}</b><br><small style='color:#a29bfe;'>(".round(($c5_win2 / $c5_total) * 100, 1)."%)</small>";
        }
        if ($r5_total > 0) {
            $total_win_ratio_output[$h1_num] = "<b>{$r5_win1} / {$r5_total}</b><br><small style='color:#a29bfe;'>(".round(($r5_win1 / $r5_total) * 100, 1)."%)</small>";
            $total_win_ratio_output[$h2_num] = "<b>{$r5_win2} / {$r5_total}</b><br><small style='color:#a29bfe;'>(".round(($r5_win2 / $r5_total) * 100, 1)."%)</small>";
        }
        if ($v5_total > 0) {
            $over22_win_ratio_output[$h1_num] = "<b>{$v5_win1} / {$v5_total}</b><br><small style='color:#a29bfe;'>(".round(($v5_win1 / $v5_total) * 100, 1)."%)</small>";
            $over22_win_ratio_output[$h2_num] = "<b>{$v5_win2} / {$v5_total}</b><br><small style='color:#a29bfe;'>(".round(($v5_win2 / $v5_total) * 100, 1)."%)</small>";
            if ($c5_total > 0 && $r5_total > 0 && $v5_total > 0) {
                $ev1 = ((($c5_win1 / $c5_total) + ($r5_win1 / $r5_total) + ($v5_win1 / $v5_total)) / 3) * 100 * floatval($band_config1['boost']) * $premium_mult1;
                $ev2 = ((($c5_win2 / $c5_total) + ($r5_win2 / $r5_total) + ($v5_win2 / $v5_total)) / 3) * 100 * floatval($band_config2['boost']) * $premium_mult2;
                if ($ev1 > 100) $ev1 = 100; if ($ev2 > 100) $ev2 = 100;
                $weighted_score_output[$h1_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev1, 1)."分</strong>";
                $weighted_score_output[$h2_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev2, 1)."分</strong>";
            }
        }
    }
    elseif ($ec1 == 4 && $ec2 == 5) {
        if ($c7_total > 0) {
            $probability_output[$h1_num] = "<b>{$c7_win1} / {$c7_total}</b><br><small style='color:#00cec9;'>(".round(($c7_win1 / $c7_total) * 100, 1)."%)</small>";
            $probability_output[$h2_num] = "<b>{$c7_win2} / {$c7_total}</b><br><small style='color:#00cec9;'>(".round(($c7_win2 / $c7_total) * 100, 1)."%)</small>";
        }
        if ($r7_total > 0) {
            $total_win_ratio_output[$h1_num] = "<b>{$r7_win1} / {$r7_total}</b><br><small style='color:#00cec9;'>(".round(($r7_win1 / $r7_total) * 100, 1)."%)</small>";
            $total_win_ratio_output[$h2_num] = "<b>{$r7_win2} / {$r7_total}</b><br><small style='color:#00cec9;'>(".round(($r7_win2 / $r7_total) * 100, 1)."%)</small>";
        }
        if ($v7_total > 0) {
            $over22_win_ratio_output[$h1_num] = "<b>{$v7_win1} / {$v7_total}</b><br><small style='color:#00cec9;'>(".round(($v7_win1 / $v7_total) * 100, 1)."%)</small>";
            $over22_win_ratio_output[$h2_num] = "<b>{$v7_win2} / {$v7_total}</b><br><small style='color:#00cec9;'>(".round(($v7_win2 / $v7_total) * 100, 1)."%)</small>";
            if ($c7_total > 0 && $r7_total > 0 && $v7_total > 0) {
                $ev1 = ((($c7_win1 / $c7_total) + ($r7_win1 / $r7_total) + ($v7_win1 / $v7_total)) / 3) * 100 * floatval($band_config1['boost']) * $premium_mult1;
                $ev2 = ((($c7_win2 / $c7_total) + ($r7_win2 / $r7_total) + ($v7_win2 / $v7_total)) / 3) * 100 * floatval($band_config2['boost']) * $premium_mult2;
                if ($ev1 > 100) $ev1 = 100; if ($ev2 > 100) $ev2 = 100;
                $weighted_score_output[$h1_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev1, 1)."分</strong>";
                $weighted_score_output[$h2_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev2, 1)."分</strong>";
            }
        }
    }
    
    if ($ec1 > 6 || $ec2 > 6) {
        // 🛡️ [WinRacing v64 Safety Add-On｜只加不刪]
        // 原版直接使用 $formatted_c4 / $formatted_r4；若未預先生成，會因 error_reporting(0) 靜默變空。
        // 這裡只補回格式字串，不改原判斷。
        $formatted_c4 = ($c4_total > 0) ? "<b>{$c4_win} / {$c4_total}</b><br><small class='text-danger' style='font-weight:bold;'>(".round(($c4_win / $c4_total) * 100, 1)."%)</small>" : "-";
        $formatted_r4 = ($r4_total > 0) ? "<b>{$r4_win} / {$r4_total}</b><br><small class='text-danger' style='font-weight:bold;'>(".round(($r4_win / $r4_total) * 100, 1)."%)</small>" : "-";
        if ($c4_total > 0) { $probability_output[$h1_num] = $formatted_c4; }
        if ($r4_total > 0) { $total_win_ratio_output[$h1_num] = $formatted_r4; }
        if ($v4_total > 0) {
            $formatted_v4 = "<b>{$v4_win} / {$v4_total}</b><br><small class='text-danger' style='font-weight:bold;'>(".round(($v4_win / $v4_total) * 100, 1)."%)</small>";
            if ($ec1 > 6 && $ec2 <= 6) { $over22_win_ratio_output[$h1_num] = $formatted_v4; } 
            elseif ($ec1 <= 6 && $ec2 > 6) { $over22_win_ratio_output[$h2_num] = $formatted_v4; } 
            elseif ($ec1 > 6 && $ec2 > 6) { $over22_win_ratio_output[$h1_num] = $formatted_v4; $over22_win_ratio_output[$h2_num] = $formatted_v4; }
            
            if ($c4_total > 0 && $r4_total > 0 && $v4_total > 0) {
                $ev1 = ((($c4_win / $c4_total) + ($r4_win / $r4_total) + ($v4_win / $v4_total)) / 3) * 100 * floatval($band_config1['boost']) * $premium_mult1;
                $ev2 = ((($c4_win / $c4_total) + ($r4_win / $r4_total) + ($v4_win / $v4_total)) / 3) * 100 * floatval($band_config2['boost']) * $premium_mult2;
                if ($ev1 > 100) $ev1 = 100; if ($ev2 > 100) $ev2 = 100;
                if ($ec1 > 6 && $ec2 <= 6) { $weighted_score_output[$h1_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev1, 1)."分</strong>"; }
                elseif ($ec1 <= 6 && $ec2 > 6) { $weighted_score_output[$h2_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev2, 1)."分</strong>"; }
                elseif ($ec1 > 6 && $ec2 > 6) { $weighted_score_output[$h1_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev1, 1)."分</strong>"; $weighted_score_output[$h2_num] = "<strong style='color:#ff7675; font-size:1.15rem;'>".round($ev2, 1)."分</strong>"; }
            }
        }
    }

    // =========================================================================
    // 🧮 [WinRacing v64 Missing-Score Fallback Engine｜只加不刪]
    // 目的：原本「機率 / 總勝出率 / 動態門檻勝率 / 加權總分」只會在特定名家組合
    //      例如 6/非6、6/6、5/5、5/4、4/5、>6 時輸出。
    //      其餘馬匹會顯示「-」，令畫面好似沒有計算。
    // 做法：完全保留原本所有計算；只在某匹馬仍然是空白時，追加 Rank Fallback 回測：
    //      以「同一綜合排名位置」作歷史樣本，補算機率、>20總勝出率、同分段動態勝率、加權分。
    // 安全：只補空格，不覆蓋原本已有的核心分數；不刪除、不改原公式。
    // =========================================================================
    foreach ($sorted_horses as $wr64_idx => $wr64_info) {
        $wr64_horse_num = intval($wr64_info['horse_num']);
        $wr64_score = floatval($wr64_info['total_score'] ?? 0);
        $wr64_band = getScoreBandConfig($wr64_score);
        $wr64_premium = 1.0;
        if ($wr64_score >= 27) { $wr64_premium = 1.50; }
        elseif ($wr64_score >= 25) { $wr64_premium = 1.30; }
        elseif ($wr64_score >= 23) { $wr64_premium = 1.15; }

        $wr64_prob_total = 0; $wr64_prob_win = 0;
        $wr64_ratio_total = 0; $wr64_ratio_win = 0;
        $wr64_band_total = 0; $wr64_band_win = 0;

        foreach ($season_ranked_flow as $wr64_h_date => $wr64_h_races) {
            foreach ($wr64_h_races as $wr64_hr_no => $wr64_h_horses) {
                // 與原本主邏輯一致：今日未跑賽事不納入回測；今日之後場次不偷看。
                if ($wr64_h_date === $target_date && intval($wr64_hr_no) == intval($r_num)) {
                    if (!isset($results_map[$wr64_h_date][$wr64_hr_no]) || intval($results_map[$wr64_h_date][$wr64_hr_no]) <= 0) { continue 2; }
                }
                if ($wr64_h_date === $target_date && intval($wr64_hr_no) > intval($r_num)) { continue 2; }
                if (!isset($results_map[$wr64_h_date][$wr64_hr_no]) || intval($results_map[$wr64_h_date][$wr64_hr_no]) <= 0) { continue; }
                if (!isset($wr64_h_horses[$wr64_idx])) { continue; }

                $wr64_hist_node = $wr64_h_horses[$wr64_idx];
                $wr64_hist_horse = intval($wr64_hist_node['horse_num'] ?? 0);
                $wr64_hist_score = floatval($wr64_hist_node['total_score'] ?? 0);
                $wr64_actual_win = intval($results_map[$wr64_h_date][$wr64_hr_no]);

                $wr64_prob_total++;
                if ($wr64_hist_horse === $wr64_actual_win) { $wr64_prob_win++; }

                if ($wr64_hist_score > 20) {
                    $wr64_ratio_total++;
                    if ($wr64_hist_horse === $wr64_actual_win) { $wr64_ratio_win++; }
                }

                if (isScoreInBand($wr64_hist_score, $wr64_band)) {
                    $wr64_band_total++;
                    if ($wr64_hist_horse === $wr64_actual_win) { $wr64_band_win++; }
                }
            }
        }

        if ((!isset($probability_output[$wr64_horse_num]) || $probability_output[$wr64_horse_num] === '-' || $probability_output[$wr64_horse_num] === '') && $wr64_prob_total > 0) {
            $wr64_prob_pct = round(($wr64_prob_win / $wr64_prob_total) * 100, 1);
            $probability_output[$wr64_horse_num] = "<b>{$wr64_prob_win} / {$wr64_prob_total}</b><br><small style='color:#94a3b8;'>({$wr64_prob_pct}%) Rank補算</small>";
        }

        if ((!isset($total_win_ratio_output[$wr64_horse_num]) || $total_win_ratio_output[$wr64_horse_num] === '-' || $total_win_ratio_output[$wr64_horse_num] === '') && $wr64_ratio_total > 0) {
            $wr64_ratio_pct = round(($wr64_ratio_win / $wr64_ratio_total) * 100, 1);
            $total_win_ratio_output[$wr64_horse_num] = "<b>{$wr64_ratio_win} / {$wr64_ratio_total}</b><br><small style='color:#94a3b8;'>({$wr64_ratio_pct}%) >20補算</small>";
        }

        if ((!isset($over22_win_ratio_output[$wr64_horse_num]) || $over22_win_ratio_output[$wr64_horse_num] === '-' || $over22_win_ratio_output[$wr64_horse_num] === '') && $wr64_band_total > 0) {
            $wr64_band_pct = round(($wr64_band_win / $wr64_band_total) * 100, 1);
            $over22_win_ratio_output[$wr64_horse_num] = "<b>{$wr64_band_win} / {$wr64_band_total}</b><br><small style='color:#94a3b8;'>({$wr64_band_pct}%) 分段補算</small>";
        }

        if (!isset($weighted_score_output[$wr64_horse_num]) || $weighted_score_output[$wr64_horse_num] === '-' || $weighted_score_output[$wr64_horse_num] === '') {
            $wr64_components = array();
            if ($wr64_prob_total > 0) { $wr64_components[] = ($wr64_prob_win / $wr64_prob_total); }
            if ($wr64_ratio_total > 0) { $wr64_components[] = ($wr64_ratio_win / $wr64_ratio_total); }
            if ($wr64_band_total > 0) { $wr64_components[] = ($wr64_band_win / $wr64_band_total); }

            if (count($wr64_components) > 0) {
                $wr64_avg = array_sum($wr64_components) / count($wr64_components);
                $wr64_ev = $wr64_avg * 100 * floatval($wr64_band['boost']) * $wr64_premium;
                if ($wr64_ev > 100) { $wr64_ev = 100; }
                $weighted_score_output[$wr64_horse_num] = "<strong style='color:#94a3b8; font-size:1.05rem;'>" . round($wr64_ev, 1) . "分</strong><br><small style='color:#94a3b8;'>Rank補算</small>";
            }
        }
    }

    foreach ($sorted_horses as $idx => $h_info) {
        $sorted_horses[$idx]['probability_output'] = $probability_output[intval($h_info['horse_num'])] ?? "-";
        $sorted_horses[$idx]['ratio_output'] = $total_win_ratio_output[intval($h_info['horse_num'])] ?? "-"; 
        $sorted_horses[$idx]['over22_output'] = $over22_win_ratio_output[intval($h_info['horse_num'])] ?? "-"; 
        $sorted_horses[$idx]['weighted_score_output'] = $weighted_score_output[intval($h_info['horse_num'])] ?? "-"; 
    }

    // 🌟 完美同步映射：將復活後的配腳資料 $jiao_text 正式載入 API 出口管線
    $final_dashboard[$r_num] = array(
        'meta' => array( 'type' => $type, 'target' => array( 'dan' => $dan_text, 'jiao' => $jiao_text ), 'race_tag' => $race_tag ),
        'horses' => $sorted_horses
    );
}

ob_end_clean(); 
header('Content-Type: application/json; charset=utf-8');
echo json_encode($final_dashboard, JSON_UNESCAPED_UNICODE);
?>