<?php
require_once __DIR__ . '/runtime/wr_bootstrap.php';
@set_time_limit(1200);
@ini_set('memory_limit', '1536M');
require_once __DIR__ . '/config/config.php';
if (!wr_db_guard_normalize()) {
    throw new RuntimeException('DB connection unavailable');
}
require_once __DIR__ . '/Chairman/supreme/ChairmanSupremeDecisionEngineV51.php';

function wr_v51_h($value)
{
    return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
}

function wr_v51_resolve_race_date()
{
    $candidates = array('race_date', 'date', 'review_date');
    foreach ($candidates as $key) {
        if (!isset($_GET[$key])) {
            continue;
        }
        $value = trim((string)$_GET[$key]);
        $dt = DateTimeImmutable::createFromFormat('!Y-m-d', $value);
        $errors = DateTimeImmutable::getLastErrors();
        $valid = $dt instanceof DateTimeImmutable
            && ($errors === false || ((int)$errors['warning_count'] === 0 && (int)$errors['error_count'] === 0))
            && $dt->format('Y-m-d') === $value;
        if ($valid) {
            return $value;
        }
    }
    return (new DateTimeImmutable('now', new DateTimeZone('Asia/Hong_Kong')))->format('Y-m-d');
}

$date = wr_v51_resolve_race_date();
$venue = isset($_GET['venue']) ? trim((string)$_GET['venue']) : '';
$venue = preg_replace('/[^A-Za-z0-9_\-]/', '', $venue);
$action = isset($_GET['action']) ? trim((string)$_GET['action']) : 'latest';
$engine = new ChairmanSupremeDecisionEngineV51($conn);
$data = $action === 'build' ? $engine->build($date, $venue) : $engine->latest($date, $venue);
$day = isset($data['day']) && is_array($data['day']) ? $data['day'] : array();
$races = isset($data['races']) && is_array($data['races']) ? $data['races'] : array();
$groups = array('PRIMARY'=>array(), 'SECONDARY'=>array(), 'WATCH'=>array(), 'SKIP'=>array());
foreach ($races as $raceItem) {
    $a = isset($raceItem['supreme_action']) ? strtoupper((string)$raceItem['supreme_action']) : 'SKIP';
    if (!isset($groups[$a])) { $a = 'SKIP'; }
    $groups[$a][] = $raceItem;
}
$actionCounts = array();
foreach ($groups as $gk => $gv) { $actionCounts[$gk] = count($gv); }
$topPicks = array_slice($races, 0, 3);
$backtest = isset($data['backtest']) && is_array($data['backtest']) ? $data['backtest'] : array();
$btSummary = isset($backtest['summary']) && is_array($backtest['summary']) ? $backtest['summary'] : array();
$btRaces = isset($backtest['races']) && is_array($backtest['races']) ? $backtest['races'] : array();
$releaseAudit = isset($data['release_audit']) && is_array($data['release_audit']) ? $data['release_audit'] : array();
$portfolioRows = $races;
usort($portfolioRows, function ($a, $b) {
    $av = isset($a['portfolio_exposure_units']) ? (float)$a['portfolio_exposure_units'] : 0.0;
    $bv = isset($b['portfolio_exposure_units']) ? (float)$b['portfolio_exposure_units'] : 0.0;
    if ($av == $bv) { return 0; }
    return ($av > $bv) ? -1 : 1;
});
?>
<!doctype html>
<html lang="zh-Hant">
<head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>WinRacing V51.8 Backtest + Audit</title>
<style>
:root{--bg:#050914;--panel:#0b1424;--card:#08101d;--line:#2c405c;--gold:#ffc107;--green:#36f2a3;--cyan:#5edbff;--red:#ff7589;--muted:#9eb0c7}
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:#eef6ff;font-family:Arial,'Microsoft JhengHei',sans-serif;font-size:13px}.wrap{max-width:1880px;margin:auto;padding:18px}.hero,.panel{background:var(--panel);border:1px solid #31486b;border-radius:14px;padding:15px;margin-bottom:12px}.hero h1{margin:0 0 6px}.gold{color:var(--gold)}.green{color:var(--green)}.cyan{color:var(--cyan)}.red{color:var(--red)}.muted{color:var(--muted)}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.grid4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:12px}.badge{display:inline-block;padding:3px 8px;border-radius:999px;background:#162942;border:1px solid #36577e;font-weight:700}.score{font-size:24px;font-weight:900}.kpi{font-size:28px;font-weight:900}.bar{height:8px;background:#101d30;border-radius:99px;overflow:hidden;margin-top:5px}.bar>span{display:block;height:100%;background:linear-gradient(90deg,#5edbff,#36f2a3);border-radius:99px}.section-title{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 10px}.race-card h3{margin:0 0 7px}.line{height:1px;background:#1e3048;margin:8px 0}.action-primary{border-color:#36f2a3}.action-secondary{border-color:#5edbff}.action-watch{border-color:#ffc107}.action-skip{border-color:#7d4151}.mini{font-size:11px}.empty{padding:28px;text-align:center;color:#ffcf66}input{background:#07111f;color:#fff;border:1px solid #345;padding:8px}button{background:#ffc107;border:0;padding:9px 14px;font-weight:900;border-radius:6px}.portfolio-row{display:grid;grid-template-columns:70px 1fr 90px 90px;gap:8px;align-items:center;padding:7px 0;border-bottom:1px solid #17263a}.portfolio-row:last-child{border-bottom:0}.pill{padding:2px 7px;border-radius:999px;background:#13233a;border:1px solid #2e4a6d}.source{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media(max-width:1100px){.grid,.grid4{grid-template-columns:1fr 1fr}}@media(max-width:700px){.grid,.grid4{grid-template-columns:1fr}.portfolio-row{grid-template-columns:55px 1fr 70px}}
</style>
</head>
<body><div class="wrap">
<div class="hero"><h1>🏆 V51.8 — <span class="gold">Backtest + Audit Release</span></h1><div class="muted">Supreme ranking、final action、portfolio allocation、dynamic risk control 一頁總覽。Read-only DB；不修改 V44–V50。</div></div>
<div class="panel"><form method="get" action="">Race Date <input type="date" name="race_date" value="<?=wr_v51_h($date)?>"> <strong class="cyan">Selected: <?=wr_v51_h($date)?></strong> Venue <input name="venue" value="<?=wr_v51_h($venue)?>"> <button name="action" value="build">Build V51 Snapshot</button></form></div>
<div class="panel muted source">Source Race Date: <strong class="cyan"><?=wr_v51_h(isset($data['source_race_date'])?$data['source_race_date']:$date)?></strong> ｜ Source V50 Run: <strong class="cyan"><?=wr_v51_h(isset($data['source_v50_run'])?$data['source_v50_run']:'')?></strong> ｜ V51 Engine: <strong class="green"><?=wr_v51_h(isset($data['engine_version'])?$data['engine_version']:'51.8.0')?></strong></div>
<?php if (isset($data['message']) && $data['message'] !== ''): ?><div class="panel <?=($data['status']==='OK'?'green':'gold')?>"><?=wr_v51_h($data['message'])?></div><?php endif; ?>
<?php if ($day): ?>
<div class="panel"><div class="section-title"><h2>Daily Command Center</h2><span class="badge">Risk-adjusted Portfolio</span></div><div class="grid4">
<div class="card"><small>Best Supreme Banker</small><div class="kpi gold">R<?=wr_v51_h($day['best_banker_race'])?> #<?=wr_v51_h($day['best_banker_horse'])?></div><div><?=wr_v51_h($day['best_banker_name'])?></div><p><span class="badge"><?=wr_v51_h($day['best_banker_tier'])?></span> Score <?=number_format((float)$day['best_banker_score'],1)?></p></div>
<div class="card"><small>Portfolio Confidence</small><div class="kpi green"><?=number_format((float)$day['portfolio_confidence'],1)?></div><div><?=wr_v51_h($day['portfolio_state'])?></div><div class="bar"><span style="width:<?=min(100,max(0,(float)$day['portfolio_confidence']))?>%"></span></div><p><?=number_format((float)(isset($day['portfolio_total_exposure_units'])?$day['portfolio_total_exposure_units']:0),2)?>u / <?=number_format((float)(isset($day['portfolio_daily_cap_units'])?$day['portfolio_daily_cap_units']:0),2)?>u</p></div>
<div class="card"><small>Dynamic Risk</small><div class="kpi cyan"><?=wr_v51_h(isset($day['dynamic_risk_level'])?$day['dynamic_risk_level']:'LOW')?> <?=number_format((float)(isset($day['dynamic_risk_score'])?$day['dynamic_risk_score']:0),1)?></div><div class="bar"><span style="width:<?=min(100,max(0,(float)(isset($day['dynamic_risk_score'])?$day['dynamic_risk_score']:0)))?>%"></span></div><p>Reduced <?=number_format((float)(isset($day['risk_reduction_units'])?$day['risk_reduction_units']:0),2)?>u</p></div>
<div class="card"><small>Action Mix</small><div class="kpi"><?=array_sum($actionCounts)?></div><p><span class="green">PRIMARY <?=$actionCounts['PRIMARY']?></span> ｜ <span class="cyan">SECONDARY <?=$actionCounts['SECONDARY']?></span></p><p><span class="gold">WATCH <?=$actionCounts['WATCH']?></span> ｜ <span class="red">SKIP <?=$actionCounts['SKIP']?></span></p></div>
</div></div>
<?php endif; ?>
<?php if ($btSummary): ?>
<div class="panel"><div class="section-title"><h2>V51 Backtest Summary</h2><span class="badge"><?=!empty($btSummary['results_available'])?'RESULTS FOUND':'PENDING RESULTS'?></span></div><div class="grid4">
<div class="card"><small>Evaluated Races</small><div class="kpi gold"><?=wr_v51_h(isset($btSummary['evaluated'])?$btSummary['evaluated']:0)?></div><p>Win <?=number_format((float)(isset($btSummary['banker_win_rate'])?$btSummary['banker_win_rate']:0),1)?>%</p></div>
<div class="card"><small>Banker Top 2</small><div class="kpi cyan"><?=number_format((float)(isset($btSummary['banker_top2_rate'])?$btSummary['banker_top2_rate']:0),1)?>%</div><p><?=wr_v51_h(isset($btSummary['banker_top2'])?$btSummary['banker_top2']:0)?> hits</p></div>
<div class="card"><small>Banker Top 3</small><div class="kpi green"><?=number_format((float)(isset($btSummary['banker_top3_rate'])?$btSummary['banker_top3_rate']:0),1)?>%</div><p><?=wr_v51_h(isset($btSummary['banker_top3'])?$btSummary['banker_top3']:0)?> hits</p></div>
<div class="card"><small>Exposure Top3 Capture</small><div class="kpi"><?=number_format((float)(isset($btSummary['exposure_top3_capture_pct'])?$btSummary['exposure_top3_capture_pct']:0),1)?>%</div><p><?=number_format((float)(isset($btSummary['exposure_top3_units'])?$btSummary['exposure_top3_units']:0),2)?>u / <?=number_format((float)(isset($btSummary['exposure_units'])?$btSummary['exposure_units']:0),2)?>u</p></div>
</div></div>
<?php endif; ?>
<?php if ($releaseAudit): ?><div class="panel"><div class="section-title"><h2>Release Readiness Audit</h2><span class="badge <?=!empty($releaseAudit['ready'])?'green':'gold'?>"><?=wr_v51_h(isset($releaseAudit['status'])?$releaseAudit['status']:'REVIEW')?></span></div><p><?=wr_v51_h(isset($releaseAudit['passed'])?$releaseAudit['passed']:0)?> / <?=wr_v51_h(isset($releaseAudit['total'])?$releaseAudit['total']:0)?> checks passed</p></div><?php endif; ?>
<?php if ($topPicks): ?><div class="panel"><div class="section-title"><h2>Top 3 Supreme Picks</h2><span class="muted">Final Supreme Ranking</span></div><div class="grid">
<?php foreach ($topPicks as $race): ?><div class="card action-<?=strtolower(wr_v51_h($race['supreme_action']))?>"><h3 class="gold">#<?=wr_v51_h($race['supreme_rank'])?>｜R<?=wr_v51_h($race['race_num'])?> #<?=wr_v51_h($race['banker_horse'])?> <?=wr_v51_h($race['banker_name'])?></h3><div class="score"><?=number_format((float)$race['final_supreme_score'],1)?></div><p><span class="badge">Tier <?=wr_v51_h($race['supreme_tier'])?></span> <strong class="green"><?=wr_v51_h($race['supreme_action'])?></strong></p><p>Exposure <?=number_format((float)$race['portfolio_exposure_units'],2)?>u ｜ Risk <?=wr_v51_h($race['dynamic_risk_level'])?> <?=number_format((float)$race['dynamic_risk_score'],1)?></p><div class="bar"><span style="width:<?=min(100,max(0,(float)$race['final_supreme_score']))?>%"></span></div></div><?php endforeach; ?>
</div></div><?php endif; ?>
<div class="panel"><div class="section-title"><h2>Portfolio Allocation Board</h2><span class="muted">按實際 Exposure 排序</span></div>
<?php if (!$portfolioRows): ?><div class="empty">No portfolio data.</div><?php else: foreach ($portfolioRows as $race): ?><div class="portfolio-row"><strong class="gold">R<?=wr_v51_h($race['race_num'])?></strong><div>#<?=wr_v51_h($race['banker_horse'])?> <?=wr_v51_h($race['banker_name'])?> <span class="pill"><?=wr_v51_h($race['supreme_action'])?></span><div class="bar"><span style="width:<?=min(100,max(0,(float)$race['portfolio_allocation_pct']))?>%"></span></div></div><strong class="green"><?=number_format((float)$race['portfolio_exposure_units'],2)?>u</strong><span><?=number_format((float)$race['portfolio_allocation_pct'],1)?>%</span></div><?php endforeach; endif; ?>
</div>
<div class="panel"><div class="section-title"><h2>Supreme Race Decisions</h2><span class="muted">Tier / Action / Risk / Exposure</span></div>
<?php if (!$races): ?><div class="empty">No V50 source data for this date. Build V50 first.</div><?php else: ?><div class="grid">
<?php foreach ($races as $race): $cls='action-'.strtolower((string)$race['supreme_action']); ?>
<div class="card race-card <?=$cls?>"><h3 class="gold">Rank #<?=wr_v51_h($race['supreme_rank'])?>｜R<?=wr_v51_h($race['race_num'])?>｜#<?=wr_v51_h($race['banker_horse'])?> <?=wr_v51_h($race['banker_name'])?></h3><div class="score"><?=number_format((float)$race['final_supreme_score'],1)?></div><p><span class="badge">Tier <?=wr_v51_h($race['supreme_tier'])?></span> <strong class="green"><?=wr_v51_h($race['supreme_action'])?></strong> ｜ <?=number_format((float)$race['portfolio_exposure_units'],2)?>u</p><p class="cyan"><?=wr_v51_h($race['decision_reason'])?></p><div class="line"></div><p>Cal #<?=wr_v51_h($race['calibration_rank'])?> → Final #<?=wr_v51_h($race['supreme_rank'])?> (<?=wr_v51_h($race['consensus_rank_direction'])?>)</p><p>Agreement <?=number_format((float)$race['consensus_agreement_score'],1)?>｜Conflict <?=number_format((float)$race['consensus_conflict_penalty'],1)?>｜Reliability <?=number_format((float)$race['calibration_reliability'],1)?></p><p>Risk <?=wr_v51_h($race['dynamic_risk_level'])?> <?=number_format((float)$race['dynamic_risk_score'],1)?>｜Factor <?=number_format((float)$race['risk_adjustment_factor'],2)?></p><p class="mini muted"><?=wr_v51_h($race['risk_control_reason'])?></p><p>Q <?=wr_v51_h($race['q_top2'])?>｜Top4 <?=wr_v51_h($race['trio_top4'])?></p><p>Value <?=wr_v51_h($race['value_horses'])?>｜Avoid <?=wr_v51_h($race['avoid_horses'])?></p></div>
<?php endforeach; ?></div><?php endif; ?></div>
</div></body></html>
