DATA/UPBIT/daemon/target/daemon_upbit_trading_day.php
<?php
// =============================================================
// [1. 초기 세팅 & 무기 장착]
// =============================================================

chdir(dirname(__FILE__)); 

// ★ CLI 환경에서 DOCUMENT_ROOT 강제 지정
if (empty($_SERVER['DOCUMENT_ROOT'])) {
    $_SERVER['DOCUMENT_ROOT'] = '/home/www';
}

// ★ 데몬 상태 기록 함수 로드
include_once('./db_record.php');

try {
    if (!file_exists('./upbit_api.class.php')) {
        throw new Exception("upbit_api.class.php 파일을 찾을 수 없습니다.");
    }
    include_once('./upbit_api.class.php'); 

    require_once $_SERVER['DOCUMENT_ROOT'].'/DB/key_upbit_trade.php'; 

    $upbit_access = $UPBIT_ACCESS_KEY; 
    $upbit_secret = $UPBIT_SECRET_KEY;

    if (empty($upbit_access) || empty($upbit_secret)) {
        throw new Exception("키 파일은 있는데 내용이 비어있습니다.");
    }

    $upbit = new Upbit($upbit_access, $upbit_secret);

} catch (Throwable $e) { 
    echo "[" . date('Y-m-d H:i:s') . "] 초기 세팅 에러: " . $e->getMessage() . "\n"; 
    exit;
}

// =============================================================
// [2. 무한 씹질 루프 (감시 시작)]
// =============================================================
$done_memory      = [];
$last_cleanup_min = ''; // ★ 메모리 정리 기준 분
$pdo_gnu          = null;
$db_upbit         = null;

echo "[" . date('Y-m-d H:i:s') . "] 데몬 정상 가동 시작...\n";

while (true) {
    try {
        // ★ [좀비 치료제] 그누보드 연결 없으면 새로 개통
        if (!$pdo_gnu) {
            $pdo_gnu = require $_SERVER['DOCUMENT_ROOT'].'/DB/db_gnu.php'; 
        }

        // ★ [좀비 치료제] 업비트 시세 DB 연결 없으면 새로 개통
        if (!$db_upbit) {
            require $_SERVER['DOCUMENT_ROOT'].'/DB/db_upbit.php';
            $db_upbit = $db_upbit ?? null;
        }

        $now_dt        = new DateTime();
        $current_ymdhi = $now_dt->format('Y-m-d H:i'); 
        $current_hi    = $now_dt->format('H:i');          
        $current_m     = (int)$now_dt->format('H') * 60 + (int)$now_dt->format('i');        

        // ★ [heartbeat] 분이 바뀔 때만 기록
        static $last_heartbeat_min = '';
        if ($current_ymdhi !== $last_heartbeat_min) {
            record_daemon($db_upbit, 'RUNNING', 'heartbeat');
            $last_heartbeat_min = $current_ymdhi;

            // ★ [메모리 정리] 분이 바뀔 때만 이전 분 키 제거
            foreach ($done_memory as $k => $v) {
                if (strpos($k, $current_ymdhi) === false) {
                    unset($done_memory[$k]);
                }
            }
            $last_cleanup_min = $current_ymdhi;
        }

        $stmt = $pdo_gnu->query("SELECT * FROM g5_write_daemon_day_upbit WHERE x2_run = '1'");
        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

        foreach ($rows as $row) {
            // ★ [몸통 중복 가드] Y-m-d H:i 기준 같은 분에 1번만 실행
            $memory_key = $row['wr_id'] . '_' . $current_ymdhi;
            if (isset($done_memory[$memory_key])) continue;

            $is_execute  = false;
            $target_file = '';

            // [조건 A] x2_all_day_1~10 동적 체크 (켜진 1개만 사용)
            for ($i = 1; $i <= 10; $i++) {
                if (empty($row["x2_all_day_{$i}"])) continue;

                $interval_key = ($i === 1) ? 'x2_interval' : "x2_interval_{$i}";
                $interval_min = (int)($row[$interval_key] ?? 0);

                if ($interval_min > 0 && ($current_m % $interval_min) == 0) {
                    $is_execute  = true;
                    $target_file = "day_time_code_{$i}.php";
                }
                break;
            }

            // [조건 B] 아무것도 없으면 지정시간 타격기
            if (!$target_file) {
                $target_hi = sprintf("%02d:%02d", $row['x2_hour'], $row['x2_min']);
                if ($current_hi == $target_hi) {
                    $is_execute  = true;
                    $target_file = 'day_target_code.php';
                }
            }

            // [실행] 조건 맞으면 타격기 호출
            if ($is_execute && $target_file != '') {
                if (file_exists($target_file)) {
                    include $target_file;

                    $done_memory[$memory_key] = true;
                    usleep(200000);
                } else {
                    echo "오류: 실행 파일($target_file)이 없습니다.\n";
                }
            }
        }

    } catch (Throwable $e) { 
        record_daemon($db_upbit, 'ERROR', "err=" . $e->getMessage());
        $pdo_gnu  = null; 
        $db_upbit = null;
    }

    usleep(31000000); // 31초 대기 (변경 가능)
}
?>