query("SELECT * FROM optimization_analysis_state WHERE is_running = 1 ORDER BY id DESC LIMIT 1"); $state = $stateQuery ? $stateQuery->fetch_assoc() : null; if (!$state) { writeLog("❌ No running analysis found."); exit(1); } writeLog("✅ Found running analysis with ID: " . $state['id']); writeLog("📊 Total combinations to process: " . number_format($state['total_combinations'])); // Get current progress $processedQuery = $db->query("SELECT COUNT(*) as count FROM panel_directives WHERE llm_checked = 1"); $currentProcessed = $processedQuery ? $processedQuery->fetch_assoc()['count'] : 0; writeLog("📈 Already processed: " . number_format($currentProcessed) . " combinations"); // Process combinations in small batches for better progress tracking $batchSize = 3; // Process 3 combinations at a time to manage rate limits $totalProcessed = $currentProcessed; $batchCount = 0; while (true) { $batchCount++; writeLog("--- Starting Batch #$batchCount ---"); // Get next batch of unprocessed combinations $query = $db->query(" SELECT id, attribute1_id, attribute2_id, choice1, choice2, attribute1_name, attribute2_name FROM panel_directives WHERE llm_checked = 0 ORDER BY id ASC LIMIT $batchSize "); if (!$query || $query->num_rows == 0) { writeLog("🎉 No more combinations to process. Analysis complete!"); break; } writeLog("📝 Processing batch of " . $query->num_rows . " combinations..."); $batchProcessed = 0; while ($directive = $query->fetch_assoc()) { try { $combinationText = "{$directive['attribute1_name']}='{$directive['choice1']}' + {$directive['attribute2_name']}='{$directive['choice2']}'"; writeLog("🔍 Analyzing: $combinationText (ID: {$directive['id']})"); // Check GPT rate limit before making request $rateLimitStatus = GptHelper::getRateLimitStatus(); if (!$rateLimitStatus['can_make_request']) { $waitTime = $rateLimitStatus['cooldown_remaining']; writeLog("⏳ Rate limit reached. Waiting {$waitTime} seconds..."); sleep($waitTime + 5); // Add 5 seconds buffer } // Analyze combination using GPT $result = GptHelper::analyzeCombination( $directive['attribute1_name'], $directive['choice1'], $directive['attribute2_name'], $directive['choice2'] ); // Update directive with results $stmt = $db->prepare(" UPDATE panel_directives SET llm_checked = 1, is_impossible = ?, llm_reasoning = ?, updated_at = NOW() WHERE id = ? "); $isImpossible = $result['is_impossible'] ? 1 : 0; $stmt->bind_param('isi', $isImpossible, $result['reasoning'], $directive['id']); if ($stmt->execute()) { $totalProcessed++; $batchProcessed++; $resultText = $result['is_impossible'] ? "IMPOSSIBLE" : "POSSIBLE"; writeLog("✅ Processed ID {$directive['id']} => $resultText"); writeLog(" Reasoning: " . substr($result['reasoning'], 0, 100) . "..."); } else { writeLog("❌ Failed to update directive {$directive['id']}: " . $stmt->error); } // Rate limiting - wait between requests writeLog("⏸️ Waiting 5 seconds (rate limit protection)..."); sleep(5); } catch (Exception $e) { writeLog("❌ Error processing directive {$directive['id']}: " . $e->getMessage()); // Mark as checked with error to avoid infinite loops $stmt = $db->prepare(" UPDATE panel_directives SET llm_checked = 1, llm_reasoning = ?, updated_at = NOW() WHERE id = ? "); $errorReason = 'Analysis error: ' . $e->getMessage(); $stmt->bind_param('si', $errorReason, $directive['id']); $stmt->execute(); $totalProcessed++; $batchProcessed++; // Wait longer after errors writeLog("⏸️ Waiting 10 seconds after error..."); sleep(10); } } // Update progress in state table after each batch $stmt = $db->prepare(" UPDATE optimization_analysis_state SET processed_combinations = ?, last_updated = NOW() WHERE id = ? "); $stmt->bind_param('ii', $totalProcessed, $state['id']); $stmt->execute(); $progressPercent = ($totalProcessed / $state['total_combinations']) * 100; writeLog("📊 Batch #$batchCount complete. Progress: " . number_format($totalProcessed) . "/" . number_format($state['total_combinations']) . " (" . number_format($progressPercent, 2) . "%)"); // Get current statistics $impossibleCount = $db->query("SELECT COUNT(*) as count FROM panel_directives WHERE is_impossible = 1")->fetch_assoc()['count']; $possibleCount = $db->query("SELECT COUNT(*) as count FROM panel_directives WHERE is_impossible = 0 AND llm_checked = 1")->fetch_assoc()['count']; writeLog("📈 Current results: $impossibleCount impossible, $possibleCount possible"); // Check if we should stop (if analysis was manually stopped) $checkState = $db->query("SELECT is_running FROM optimization_analysis_state WHERE id = {$state['id']}"); $currentState = $checkState ? $checkState->fetch_assoc() : null; if (!$currentState || !$currentState['is_running']) { writeLog("🛑 Analysis was stopped manually."); break; } // Small break between batches writeLog("⏸️ Brief pause between batches..."); sleep(3); } // Mark analysis as complete $stmt = $db->prepare(" UPDATE optimization_analysis_state SET is_running = 0, completed_at = NOW(), processed_combinations = ? WHERE id = ? "); $stmt->bind_param('ii', $totalProcessed, $state['id']); $stmt->execute(); // Get final counts $impossibleCount = $db->query("SELECT COUNT(*) as count FROM panel_directives WHERE is_impossible = 1")->fetch_assoc()['count']; $possibleCount = $db->query("SELECT COUNT(*) as count FROM panel_directives WHERE is_impossible = 0 AND llm_checked = 1")->fetch_assoc()['count']; writeLog("🎉 Analysis completed successfully!"); writeLog("📊 Final Statistics:"); writeLog(" - Total processed: " . number_format($totalProcessed)); writeLog(" - Impossible combinations: " . number_format($impossibleCount)); writeLog(" - Possible combinations: " . number_format($possibleCount)); writeLog(" - Batches processed: $batchCount"); $timeElapsed = time() - strtotime($state['started_at']); writeLog("⏱️ Total time: " . gmdate("H:i:s", $timeElapsed)); } catch (Exception $e) { writeLog("💥 FATAL ERROR: " . $e->getMessage()); writeLog("Stack trace: " . $e->getTraceAsString()); // Mark analysis as stopped on error if (isset($state['id'])) { $stmt = $db->prepare("UPDATE optimization_analysis_state SET is_running = 0 WHERE id = ?"); $stmt->bind_param('i', $state['id']); $stmt->execute(); writeLog("🛑 Analysis marked as stopped due to error"); } exit(1); } ?>