isLoggedIn()) { throw new Exception('Unauthorized'); } $input = json_decode(file_get_contents('php://input'), true); $action = $input['action'] ?? ''; if (!in_array($action, ['start', 'pause', 'stop', 'reset', 'generate', 'status'])) { throw new Exception('Invalid action'); } $db = Database::getInstance(); switch ($action) { case 'start': $result = startAnalysis($db); break; case 'pause': $result = pauseAnalysis($db); break; case 'stop': $result = stopAnalysis($db); break; case 'reset': $result = resetAnalysisState($db); break; case 'generate': $result = generateCombinationsAction($db); break; case 'status': $result = getAnalysisStatus($db); break; } echo json_encode($result); } catch (Exception $e) { http_response_code(500); echo json_encode([ 'success' => false, 'message' => $e->getMessage() ]); } function startAnalysis($db) { try { // Check if analysis is already running $stateQuery = $db->query("SELECT * FROM optimization_analysis_state WHERE is_running = 1 LIMIT 1"); if ($stateQuery && $stateQuery->num_rows > 0) { return [ 'success' => false, 'message' => 'Analysis is already running' ]; } // Check for new attributes and regenerate combinations if needed $newCombinationsGenerated = regenerateCombinationsIfNeeded($db); // Get total combinations count $totalQuery = $db->query("SELECT COUNT(*) as count FROM panel_directives"); $totalCombinations = $totalQuery->fetch_assoc()['count']; if ($totalCombinations == 0) { // Generate combinations if none exist generateCombinations($db); $totalQuery = $db->query("SELECT COUNT(*) as count FROM panel_directives"); $totalCombinations = $totalQuery->fetch_assoc()['count']; } // Get processed count $processedQuery = $db->query("SELECT COUNT(*) as count FROM panel_directives WHERE llm_checked = 1"); $processedCount = $processedQuery->fetch_assoc()['count']; // Update or create analysis state $existingState = $db->query("SELECT id FROM optimization_analysis_state ORDER BY id DESC LIMIT 1"); if ($existingState && $existingState->num_rows > 0) { $stateId = $existingState->fetch_assoc()['id']; $stmt = $db->prepare("UPDATE optimization_analysis_state SET is_running = 1, started_at = NOW(), total_combinations = ?, processed_combinations = ?, should_pause = 0, completed_at = NULL WHERE id = ?"); $stmt->bind_param('iii', $totalCombinations, $processedCount, $stateId); } else { $stmt = $db->prepare("INSERT INTO optimization_analysis_state (total_combinations, processed_combinations, is_running, started_at, should_pause) VALUES (?, ?, 1, NOW(), 0)"); $stmt->bind_param('ii', $totalCombinations, $processedCount); } if (!$stmt->execute()) { throw new Exception("Failed to update analysis state"); } // Start background process with proper file path $processFile = file_exists('enhanced_process_optimization.php') ? 'enhanced_process_optimization.php' : 'process_optimization_analysis.php'; $command = "php " . __DIR__ . "/$processFile > /dev/null 2>&1 &"; exec($command); return [ 'success' => true, 'message' => 'Analysis started successfully', 'total_combinations' => $totalCombinations, 'new_combinations_generated' => $newCombinationsGenerated, 'process_file_used' => $processFile ]; } catch (Exception $e) { return [ 'success' => false, 'message' => 'Error starting analysis: ' . $e->getMessage() ]; } } function pauseAnalysis($db) { try { // Set pause flag - the background process will check this $stmt = $db->prepare("UPDATE optimization_analysis_state SET should_pause = 1 WHERE is_running = 1"); if (!$stmt->execute()) { throw new Exception("Failed to pause analysis"); } // Wait a moment for the process to pause sleep(2); // Update state to paused $stmt = $db->prepare("UPDATE optimization_analysis_state SET is_running = 0, should_pause = 0 WHERE should_pause = 1"); $stmt->execute(); return [ 'success' => true, 'message' => 'Analysis paused successfully' ]; } catch (Exception $e) { return [ 'success' => false, 'message' => 'Error pausing analysis: ' . $e->getMessage() ]; } } function stopAnalysis($db) { try { // Stop analysis and reset state $stmt = $db->prepare("UPDATE optimization_analysis_state SET is_running = 0, should_pause = 0, completed_at = NOW() WHERE is_running = 1"); if (!$stmt->execute()) { throw new Exception("Failed to stop analysis"); } return [ 'success' => true, 'message' => 'Analysis stopped successfully' ]; } catch (Exception $e) { return [ 'success' => false, 'message' => 'Error stopping analysis: ' . $e->getMessage() ]; } } function regenerateCombinationsIfNeeded($db) { try { // Get the latest modification time of attributes $attrQuery = $db->query("SELECT MAX(updated_at) as latest FROM attributes"); $latestAttr = $attrQuery->fetch_assoc()['latest']; // Get the creation time of the most recent directive $directiveQuery = $db->query("SELECT MAX(created_at) as latest FROM panel_directives"); $latestDirective = $directiveQuery->fetch_assoc()['latest']; // If attributes were modified after the last directive creation, regenerate if ($latestAttr && $latestDirective && strtotime($latestAttr) > strtotime($latestDirective)) { error_log("Regenerating combinations due to attribute changes"); // Clear existing unchecked directives $db->query("DELETE FROM panel_directives WHERE llm_checked = 0"); // Generate new combinations generateCombinations($db); return true; } return false; } catch (Exception $e) { error_log("Error checking for new combinations: " . $e->getMessage()); return false; } } function generateCombinations($db) { try { // Get all attributes $attributesQuery = $db->query("SELECT id, name, choices FROM attributes ORDER BY id"); $attributes = []; while ($attr = $attributesQuery->fetch_assoc()) { $choices = json_decode($attr['choices'], true); if ($choices && is_array($choices)) { $attributes[] = [ 'id' => $attr['id'], 'name' => $attr['name'], 'choices' => $choices ]; } } if (count($attributes) < 2) { throw new Exception("Need at least 2 attributes to generate combinations"); } $generatedCount = 0; $stmt = $db->prepare("INSERT IGNORE INTO panel_directives (attribute1_id, attribute2_id, choice1, choice2, attribute1_name, attribute2_name, status) VALUES (?, ?, ?, ?, ?, ?, 'pending')"); // Generate all possible combinations between different attributes for ($i = 0; $i < count($attributes); $i++) { for ($j = $i + 1; $j < count($attributes); $j++) { $attr1 = $attributes[$i]; $attr2 = $attributes[$j]; foreach ($attr1['choices'] as $choice1) { foreach ($attr2['choices'] as $choice2) { $stmt->bind_param('iissss', $attr1['id'], $attr2['id'], $choice1, $choice2, $attr1['name'], $attr2['name'] ); if ($stmt->execute()) { $generatedCount++; } } } } } error_log("Generated $generatedCount new combinations"); return $generatedCount; } catch (Exception $e) { error_log("Error generating combinations: " . $e->getMessage()); throw $e; } } function resetAnalysisState($db) { try { // Stop any running analysis $stmt = $db->prepare("UPDATE optimization_analysis_state SET is_running = 0, should_pause = 0, completed_at = NOW() WHERE is_running = 1"); if (!$stmt->execute()) { throw new Exception("Failed to reset analysis state"); } return [ 'success' => true, 'message' => 'Analysis state reset successfully' ]; } catch (Exception $e) { return [ 'success' => false, 'message' => 'Error resetting analysis state: ' . $e->getMessage() ]; } } function generateCombinationsAction($db) { try { $count = generateCombinations($db); return [ 'success' => true, 'message' => "Generated $count combinations successfully" ]; } catch (Exception $e) { return [ 'success' => false, 'message' => 'Error generating combinations: ' . $e->getMessage() ]; } } function getAnalysisStatus($db) { try { // Get current state $stateQuery = $db->query("SELECT * FROM optimization_analysis_state ORDER BY id DESC LIMIT 1"); $state = $stateQuery ? $stateQuery->fetch_assoc() : null; // Get statistics $totalQuery = $db->query("SELECT COUNT(*) as count FROM panel_directives"); $total = $totalQuery->fetch_assoc()['count']; $processedQuery = $db->query("SELECT COUNT(*) as count FROM panel_directives WHERE llm_checked = 1"); $processed = $processedQuery->fetch_assoc()['count']; return [ 'success' => true, 'state' => $state, 'statistics' => [ 'total' => $total, 'processed' => $processed, 'pending' => $total - $processed ] ]; } catch (Exception $e) { return [ 'success' => false, 'message' => 'Error getting analysis status: ' . $e->getMessage() ]; } } ?>