"; } flush(); } function updateProgress($processed, $total, $currentStatus = '') { global $startTime; try { $db = Database::getInstance(); $elapsed = microtime(true) - $startTime; $rate = $processed > 0 ? ($processed / ($elapsed / 3600)) : 0; // per hour $eta = $total > $processed && $rate > 0 ? (($total - $processed) / $rate) * 3600 : 0; // in seconds $etaFormatted = $eta > 0 ? gmdate('H:i:s', $eta) : 'Unknown'; $updateQuery = " UPDATE optimization_analysis_state SET processed_combinations = ?, current_combination = ?, processing_rate = ?, last_update = NOW() WHERE id = 1 "; $stmt = $db->prepare($updateQuery); $stmt->bind_param('isd', $processed, $currentStatus, $rate); $stmt->execute(); writeLog("Progress: $processed/$total (" . round(($processed/$total)*100, 1) . "%) | Rate: " . round($rate, 2) . "/hour | ETA: $etaFormatted"); } catch (Exception $e) { writeLog("Failed to update progress: " . $e->getMessage(), 'ERROR'); } } function safeApiCall($attr1, $choice1, $attr2, $choice2, $attempt = 1) { $maxAttempts = MAX_RETRIES; try { writeLog("API Call Attempt $attempt/$maxAttempts: $attr1=$choice1 + $attr2=$choice2"); // Check if we need to wait for rate limits $rateLimitStatus = GptHelper::getRateLimitStatus(false); // Use standard limits if (!$rateLimitStatus['can_make_request']) { $waitTime = $rateLimitStatus['cooldown_remaining'] + 30; // Add 30 second buffer writeLog("Rate limit active. Waiting $waitTime seconds...", 'WARN'); sleep($waitTime); } // Make the actual request $result = GptHelper::analyzeCombination($attr1, $choice1, $attr2, $choice2); writeLog("API call successful: " . ($result['is_impossible'] ? 'IMPOSSIBLE' : 'POSSIBLE')); return $result; } catch (Exception $e) { writeLog("API call attempt $attempt failed: " . $e->getMessage(), 'ERROR'); if ($attempt < $maxAttempts) { // Exponential backoff $backoffTime = CONSERVATIVE_DELAY * pow(EXPONENTIAL_BACKOFF_BASE, $attempt - 1); $backoffTime = min($backoffTime, 600); // Cap at 10 minutes writeLog("Retrying in $backoffTime seconds (exponential backoff)...", 'WARN'); sleep($backoffTime); return safeApiCall($attr1, $choice1, $attr2, $choice2, $attempt + 1); } else { throw new Exception("Max retries exceeded: " . $e->getMessage()); } } } // Start processing try { writeLog("=== Conservative OptimAIze Analysis Started ==="); writeLog("Configuration: Ultra-conservative mode - 1 request per 90 seconds"); $db = Database::getInstance(); writeLog("Database connected successfully"); // Reset GPT rate limits GptHelper::resetRateLimit(); writeLog("Rate limits reset"); // Get total count $countResult = $db->query("SELECT COUNT(*) as total FROM panel_directives WHERE llm_checked = 0"); $totalCount = $countResult->fetch_assoc()['total']; if ($totalCount == 0) { writeLog("No combinations to process. Analysis complete!"); $db->query("UPDATE optimization_analysis_state SET is_running = 0, completed_at = NOW() WHERE id = 1"); exit(0); } writeLog("Total combinations to analyze: $totalCount"); writeLog("Estimated time: " . round($totalCount * (CONSERVATIVE_DELAY / 3600), 1) . " hours"); // Update state to running $db->query("UPDATE optimization_analysis_state SET is_running = 1, started_at = NOW(), total_combinations = $totalCount WHERE id = 1"); $processedCount = 0; $successCount = 0; $errorCount = 0; // Main processing loop - one combination at a time while ($processedCount < $totalCount) { // Check if we should pause or stop $stateResult = $db->query("SELECT is_running, should_pause FROM optimization_analysis_state WHERE id = 1"); $state = $stateResult->fetch_assoc(); if (!$state['is_running']) { writeLog("Analysis stopped by user"); break; } if ($state['should_pause']) { writeLog("Analysis paused by user. Waiting..."); sleep(30); continue; } // Get next combination $query = $db->query(" SELECT id, attribute1_name, choice1, attribute2_name, choice2 FROM panel_directives WHERE llm_checked = 0 ORDER BY id ASC LIMIT 1 "); if (!$query || $query->num_rows == 0) { writeLog("No more combinations to process"); break; } $directive = $query->fetch_assoc(); $combinationText = "{$directive['attribute1_name']}='{$directive['choice1']}' + {$directive['attribute2_name']}='{$directive['choice2']}'"; writeLog("Processing combination ID {$directive['id']}: $combinationText"); try { // Analyze combination with retries $result = safeApiCall( $directive['attribute1_name'], $directive['choice1'], $directive['attribute2_name'], $directive['choice2'] ); // Update database $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()) { $processedCount++; $successCount++; $resultText = $result['is_impossible'] ? "IMPOSSIBLE" : "POSSIBLE"; $cacheText = isset($result['cached']) && $result['cached'] ? " (cached)" : ""; writeLog("✅ SUCCESS: ID {$directive['id']} => $resultText$cacheText"); writeLog(" Reasoning: " . substr($result['reasoning'], 0, 100) . "..."); // Update progress updateProgress($processedCount, $totalCount, $combinationText); } else { throw new Exception("Database update failed: " . $stmt->error); } } catch (Exception $e) { $errorCount++; writeLog("❌ FAILED: ID {$directive['id']} - " . $e->getMessage(), 'ERROR'); // Mark as checked but with error (to avoid infinite retry) $errorStmt = $db->prepare(" UPDATE panel_directives SET llm_checked = 1, is_impossible = 0, llm_reasoning = ?, updated_at = NOW() WHERE id = ? "); $errorReason = "Processing failed: " . $e->getMessage(); $errorStmt->bind_param('si', $errorReason, $directive['id']); $errorStmt->execute(); $processedCount++; // Count as processed even if failed } // Conservative delay between requests if ($processedCount < $totalCount) { writeLog("Waiting " . CONSERVATIVE_DELAY . " seconds before next request..."); sleep(CONSERVATIVE_DELAY); } } // Final statistics $endTime = microtime(true); $totalTime = $endTime - $startTime; writeLog("=== Analysis Complete ==="); writeLog("Total processed: $processedCount"); writeLog("Successful: $successCount"); writeLog("Errors: $errorCount"); writeLog("Total time: " . gmdate('H:i:s', $totalTime)); writeLog("Success rate: " . round(($successCount / max($processedCount, 1)) * 100, 1) . "%"); // Mark as completed $db->query("UPDATE optimization_analysis_state SET is_running = 0, completed_at = NOW(), total_processed = $processedCount WHERE id = 1"); writeLog("Analysis completed successfully!"); } catch (Exception $e) { writeLog("FATAL ERROR: " . $e->getMessage(), 'ERROR'); try { $db = Database::getInstance(); $db->query("UPDATE optimization_analysis_state SET is_running = 0, error_message = '" . $e->getMessage() . "' WHERE id = 1"); } catch (Exception $e2) { writeLog("Could not update error state: " . $e2->getMessage(), 'ERROR'); } exit(1); } ?>