GNU/_PAGE/data/upbit/whale/whale_heartbeat.php
<?php require_once '/home/www/GNU/_PAGE/head.php'; ?>

<?php
require_once '/home/www/DB/db_upbit.php';
// DB 핸들러 보정
$db_upbit = isset($pdo) ? $pdo : $db_upbit;

// 1. 파라미터 수신 및 기본값 설정
$target_market = isset($_GET['market']) ? $_GET['market'] : 'KRW-BTC';
$target_table = isset($_GET['table']) ? $_GET['table'] : 'stats_direction_01_1m'; 

// 테이블 리스트 (요청사항: 15m 추가)
$table_list = [
    'stats_direction_01',
    'stats_direction_01_1m',
    'stats_direction_01_5m',
    'stats_direction_01_15m',
    'stats_direction_01_1h',
    'stats_direction_01_24h'
];

// 테이블별 시간 단위 및 누적 계산용 정보 (한글화)
$time_unit_map = [
    'stats_direction_01'    => ['name' => '실시간(Tick)', 'suffix' => '틱 전', 'step' => 1],
    'stats_direction_01_1m' => ['name' => '1분(Minute)', 'suffix' => '분 전', 'step' => 1],
    'stats_direction_01_5m' => ['name' => '5분(5 Min)', 'suffix' => '분 전', 'step' => 5],
    'stats_direction_01_15m'=> ['name' => '15분(15 Min)', 'suffix' => '분 전', 'step' => 15],
    'stats_direction_01_1h' => ['name' => '1시간(Hour)', 'suffix' => '시간 전', 'step' => 1],
    'stats_direction_01_24h'=> ['name' => '1일(Day)', 'suffix' => '일 전', 'step' => 1]
];
$current_unit_info = isset($time_unit_map[$target_table]) ? $time_unit_map[$target_table] : ['name' => '분석중', 'suffix' => '?', 'step' => 1];

// [통계학자 공식] LIMIT 맵핑
$limit_map = [
    'stats_direction_01'    => 60, 
    'stats_direction_01_1m' => 60, 
    'stats_direction_01_5m' => 12, 
    'stats_direction_01_15m'=> 40, // 15분 단위 40개 (약 10시간)
    'stats_direction_01_1h' => 24, 
    'stats_direction_01_24h'=> 30  
];
$limit_count = isset($limit_map[$target_table]) ? $limit_map[$target_table] : 60;

// 2. 데이터 호출
try {
    if (!in_array($target_table, $table_list)) throw new Exception("Invalid Table Access");
    
    $sql = "SELECT * FROM {$target_table} ORDER BY id DESC LIMIT :l_cnt";
    $stmt = $db_upbit->prepare($sql);
    $stmt->bindValue(':l_cnt', (int)$limit_count, PDO::PARAM_INT);
    $stmt->execute();
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
    echo "<div style='color:white; padding:20px; background:#f43f5e;'>로직 오류: " . htmlspecialchars($e->getMessage()) . "</div>";
    $rows = [];
}

// 3. 헤더 지능 연산
$h_total_energy = 0; $h_total_bias = 0; $h_trend_count = 0;
$actual_count = count($rows);

if ($actual_count > 0) {
    foreach ($rows as $r) {
        $h_total_energy += $r['side_total'];
        $h_total_bias += $r['side_bias'];
        if ($r['side_trend'] > 0) $h_trend_count++;
    }
    $h_avg_bias = $h_total_bias / $actual_count;
    $h_status_text = ($h_total_energy >= 0) ? "엘도라도 (BUY_ACTIVE)" : "COIN LIFE INDEX · PURE STATUS (코인 생명력 · 순수 상태판)";
    $h_status_color = ($h_total_energy >= 0) ? "#10b981" : "#f43f5e"; 
}
?>


<!-- 웹 폰트 및 아이콘 로드 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=JetBrains+Mono:wght@400;700&family=Noto+Sans+KR:wght@300;400;700&display=swap" rel="stylesheet">

<style>
    :root {
        --bg-deep: #050505;
        --card-bg: rgba(22, 26, 37, 0.6);
        --accent-blue: #38bdf8;
        --neon-green: #10b981;
        --neon-red: #f43f5e;
        --glass-border: rgba(255, 255, 255, 0.05);
    }

    #RADAR_BIG { 
        background: var(--bg-deep); 
        color: #e5e7eb; 
        padding: 40px; 
        font-family: 'Noto Sans KR', sans-serif; 
        min-height: 100vh;
        background-image: radial-gradient(circle at 50% 0%, #1a1f35 0%, #050505 100%);
    }

    /* 로딩 애니메이션 */
    @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }

    .control-panel { 
        display: flex; justify-content: space-between; align-items: center; 
        margin-bottom: 30px; border-bottom: 1px solid rgba(255,255,255,0.05); padding-bottom: 25px;
        animation: fadeInUp 0.5s ease-out;
    }
    
    select { 
        background: #111; color: #fff; border: 1px solid #333; padding: 10px 18px; 
        border-radius: 8px; font-size: 14px; font-weight: bold; cursor: pointer;
        transition: 0.3s; font-family: 'JetBrains Mono';
    }
    select:hover { border-color: var(--accent-blue); box-shadow: 0 0 10px rgba(56, 189, 248, 0.2); }

    .btn-refresh { 
        background: var(--accent-blue); color: #000; border: none; padding: 10px 25px; 
        border-radius: 8px; font-weight: 900; cursor: pointer; font-size: 14px; 
        transition: 0.3s; font-family: 'Orbitron';
    }

    .intel-header { 
        background: var(--card-bg); backdrop-filter: blur(10px);
        border: 1px solid var(--glass-border); padding: 35px; border-radius: 20px; margin-bottom: 40px; 
        display: flex; justify-content: space-between; align-items: center; 
        border-left: 8px solid <?= $h_status_color ?>;
        animation: fadeInUp 0.7s ease-out;
        box-shadow: 0 10px 30px rgba(0,0,0,0.4);
    }
    .intel-title { font-family: 'Orbitron', sans-serif; font-size: 38px; font-weight: 900; color: #fff; letter-spacing: -1px; }

    .grid-10x6 { display: grid; grid-template-columns: repeat(6, 1fr); gap: 15px; }
    
    .data-card { 
        background: var(--card-bg); border: 1px solid var(--glass-border); padding: 20px; 
        border-radius: 15px; text-align: center; position: relative;
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        animation: fadeInUp 0.5s ease-out backwards;
    }
    .data-card:hover { 
        transform: translateY(-8px); 
        background: rgba(40, 40, 50, 0.8);
        border-color: var(--accent-blue);
        box-shadow: 0 15px 30px rgba(0,0,0,0.5);
        z-index: 10;
    }

    /* 사이버네틱 풍선도움말 */
    .data-card::before {
        content: attr(data-tooltip);
        position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%);
        background: var(--accent-blue); color: #000; padding: 10px 15px;
        border-radius: 6px; font-size: 11px; font-weight: 800; white-space: pre;
        opacity: 0; visibility: hidden; transition: 0.2s; pointer-events: none;
        box-shadow: 0 5px 15px rgba(0,0,0,0.5); z-index: 100;
        line-height: 1.5; text-align: left; font-family: 'Noto Sans KR';
    }
    .data-card:hover::before { opacity: 1; visibility: visible; bottom: calc(100% + 12px); }

    .card-time { font-size: 11px; color: #64748b; margin-bottom: 12px; font-family: 'JetBrains Mono'; letter-spacing: 1px; font-weight: bold; }
    .card-val { font-family: 'JetBrains Mono'; font-size: 26px; font-weight: 800; margin: 5px 0; }
    
    .card-sub { 
        font-size: 12px; display: flex; justify-content: space-between; 
        margin-top: 15px; border-top: 1px solid rgba(255,255,255,0.05); padding-top: 12px;
    }
    .label-tag { font-size: 10px; font-family: 'Orbitron'; color: #666; font-weight: 700; text-transform: uppercase; }

    <?php for($i=1; $i<=60; $i++): ?>
    .grid-item:nth-child(<?= $i ?>) { animation-delay: <?= 0.2 + ($i * 0.02) ?>s; }
    <?php endfor; ?>
</style>

<div id="RADAR_BIG">
    <!-- 컨트롤 패널 -->
    <div class="control-panel">
        <div class="select-group">
            <div style="display:flex; flex-direction:column; margin-right:40px;">
                <span style="font-family:'Orbitron'; font-size:10px; color:var(--accent-blue); letter-spacing:4px; margin-bottom:4px;">QUANTUM_RADAR</span>
                <h2 style="margin:0; font-size:26px; color:#fff; font-weight:900; letter-spacing:-1px;">비트 레이더</h2>
            </div>
            <form method="GET" style="display:flex; gap:12px;">
                <select name="market" onchange="this.form.submit()">
                    <option value="KRW-BTC" selected>BTC/KRW (BITCOIN)</option>
                </select>
                <select name="table" onchange="this.form.submit()">
                    <?php foreach ($table_list as $t): ?>
                        <option value="<?= $t ?>" <?= $target_table == $t ? 'selected' : '' ?>><?= $t ?></option>
                    <?php endforeach; ?>
                </select>
            </form>
        </div>
        <button onclick="location.reload()" class="btn-refresh"><i class="fa-solid fa-bolt"></i> 새로고침</button>
    </div>

    <?php if ($actual_count > 0): ?>
    <!-- 통합 판독 헤더 (한글화) -->
    <div class="intel-header">
        <div>
            <div style="font-family:'Orbitron'; font-size:12px; color:<?= $h_status_color ?>; font-weight:bold; letter-spacing:4px; margin-bottom:10px;">
                <i class="fa-solid fa-microchip"></i> 퀀텀 분석 프로토콜
            </div>
            <div class="intel-title"><?= $h_status_text ?></div>
        </div>
        <div style="display:flex; gap:40px; text-align:right;">
            <div style="background:rgba(0,0,0,0.2); padding:15px 25px; border-radius:12px; border:1px solid rgba(255,255,255,0.03);">
                <div class="label-tag">종합 에너지</div>
                <div style="font-family:'JetBrains Mono'; font-size:32px; font-weight:900; color:<?= $h_status_color ?>;"><?= number_format($h_total_energy) ?></div>
            </div>
            <div style="background:rgba(0,0,0,0.2); padding:15px 25px; border-radius:12px; border:1px solid rgba(255,255,255,0.03);">
                <div class="label-tag">평균 편차</div>
                <div style="font-family:'JetBrains Mono'; font-size:32px; font-weight:900; color:#fbbf24;"><?= round($h_avg_bias, 2) ?></div>
            </div>
            <div style="background:rgba(0,0,0,0.2); padding:15px 25px; border-radius:12px; border:1px solid rgba(255,255,255,0.03);">
                <div class="label-tag">추세 강도</div>
                <div style="font-family:'JetBrains Mono'; font-size:32px; font-weight:900; color:var(--accent-blue);"><?= round(($h_trend_count/$actual_count)*100) ?>%</div>
            </div>
        </div>
    </div>

    <!-- 데이터 그리드 -->
    <div class="grid-10x6">
        <?php 
        $i = 0;
        foreach ($rows as $row): 
            $is_up = ($row['side_total'] >= 0);
            $color = $is_up ? 'var(--neon-green)' : 'var(--neon-red)';
            $icon = $is_up ? "fa-circle-arrow-up" : "fa-circle-arrow-down";
            
            // 누적 시간 계산 (현재 시점으로부터 얼마나 전인지)
            $offset_time = $i * $current_unit_info['step'];
            $time_flow_text = ($i === 0) ? "LATEST (최신)" : "-" . $offset_time . " " . $current_unit_info['suffix'];
            
            // 툴팁 내용 구성
            $tooltip_text = "[분석 상세 내역]\n";
            $tooltip_text .= "분석 주기: " . $current_unit_info['name'] . "\n";
            $tooltip_text .= "기준 시각: " . $row['trade_time_kst'] . "\n";
            $tooltip_text .= "에너지 총량: " . number_format($row['side_total']) . "\n";
            $tooltip_text .= "세력 편차: " . round($row['side_bias'], 2);
        ?>
        <div class="data-card grid-item" 
             style="border-bottom:4px solid <?= $color ?>;" 
             data-tooltip="<?= $tooltip_text ?>">
            
            <div class="card-time">
                <i class="fa-solid fa-timeline" style="font-size:10px; opacity:0.5; margin-right:4px;"></i>
                <?= $time_flow_text ?>
            </div>
            
            <div class="card-val" style="color:<?= $color ?>;">
                <?= number_format($row['side_total']) ?>
            </div>
            
            <div class="card-sub">
                <span style="font-family:'JetBrains Mono'; color:#888; font-size:10px;">P_BIAS: <b style="color:#eee;"><?= round($row['side_bias'], 1) ?></b></span>
                <span style="color:<?= $color ?>;">
                    <i class="fa-solid <?= $icon ?>"></i>
                </span>
            </div>
        </div>
        <?php 
            $i++; 
        endforeach; ?>
    </div>
    <?php else: ?>
        <div style="padding:100px; text-align:center; color:#444; border:1px dashed #333; border-radius:20px; font-family:'Orbitron';">NO DATA SIGNAL FOUND.</div>
    <?php endif; ?>
</div>

<?php require_once '/home/www/GNU/_PAGE/tail.php'; ?>