isLoggedIn()) { throw new Exception('Unauthorized'); } $db = Database::getInstance(); // Get batch size from request (default 3 for shared hosting) $batchSize = isset($_POST['batch_size']) ? min(10, max(1, (int)$_POST['batch_size'])) : 3; // Check if analysis should be running $stateQuery = $db->query("SELECT * FROM optimization_analysis_state WHERE is_running = 1 ORDER BY id DESC LIMIT 1"); $state = $stateQuery ? $stateQuery->fetch_assoc() : null; if (!$state) { echo json_encode([ 'success' => false, 'message' => 'No active analysis found', 'should_stop' => true ]); exit; } // Check if we should pause if ($state['should_pause']) { echo json_encode([ 'success' => true, 'message' => 'Analysis paused', 'processed' => 0, 'should_stop' => true ]); exit; } // Get next batch of unprocessed combinations $query = $db->query(" SELECT id, attribute1_name, choice1, attribute2_name, choice2 FROM panel_directives WHERE llm_checked = 0 ORDER BY id ASC LIMIT $batchSize "); if (!$query || $query->num_rows == 0) { // No more combinations to process - mark as complete $db->query("UPDATE optimization_analysis_state SET is_running = 0, completed_at = NOW() WHERE is_running = 1"); echo json_encode([ 'success' => true, 'message' => 'Analysis completed!', 'processed' => 0, 'completed' => true, 'should_stop' => true ]); exit; } $combinations = []; while ($row = $query->fetch_assoc()) { $combinations[] = $row; } $processed = 0; $errors = 0; $results = []; // Process each combination foreach ($combinations as $combo) { try { $result = processSingleCombination($combo, $db); if ($result['success']) { $processed++; $results[] = [ 'id' => $combo['id'], 'status' => $result['is_impossible'] ? 'impossible' : 'possible', 'reasoning' => substr($result['reasoning'], 0, 100) ]; } else { $errors++; $results[] = [ 'id' => $combo['id'], 'status' => 'error', 'reasoning' => $result['error'] ]; } } catch (Exception $e) { $errors++; $results[] = [ 'id' => $combo['id'], 'status' => 'error', 'reasoning' => $e->getMessage() ]; } } // Update progress $totalProcessedQuery = $db->query("SELECT COUNT(*) as count FROM panel_directives WHERE llm_checked = 1"); $totalProcessed = $totalProcessedQuery ? $totalProcessedQuery->fetch_assoc()['count'] : 0; $db->query("UPDATE optimization_analysis_state SET processed_combinations = $totalProcessed, last_updated = NOW() WHERE is_running = 1"); echo json_encode([ 'success' => true, 'processed' => $processed, 'errors' => $errors, 'total_processed' => $totalProcessed, 'results' => $results, 'has_more' => true, 'message' => "Processed batch: $processed success, $errors errors" ]); } catch (Exception $e) { error_log("AJAX processor error: " . $e->getMessage()); echo json_encode([ 'success' => false, 'message' => $e->getMessage(), 'should_stop' => true ]); } function processSingleCombination($combination, $db) { try { // Build the prompt $prompt = sprintf( "Analyze this Indian demographic combination:\n\n%s = %s\n%s = %s\n\nIs this combination realistic in Indian society? Consider cultural norms, economic factors, and social structures. Respond with 'POSSIBLE' or 'IMPOSSIBLE' followed by a brief reason (max 50 words).", $combination['attribute1_name'], $combination['choice1'], $combination['attribute2_name'], $combination['choice2'] ); $messages = [ [ 'role' => 'system', 'content' => 'You are an expert in Indian demographics and social structures. Analyze combinations for realism.' ], [ 'role' => 'user', 'content' => $prompt ] ]; // Make GPT request with rate limiting $response = GptHelper::makeRequest($messages, 'gpt-4o-mini', 0.1); if (!$response['success']) { throw new Exception("GPT API error: " . $response['error']); } $content = trim($response['response']); $isImpossible = stripos($content, 'IMPOSSIBLE') === 0 ? 1 : 0; // Extract reasoning $reasoning = trim(str_ireplace(['POSSIBLE', 'IMPOSSIBLE'], '', $content)); if (empty($reasoning)) { $reasoning = $content; } // Update database $stmt = $db->prepare("UPDATE panel_directives SET llm_checked = 1, is_impossible = ?, llm_reasoning = ?, updated_at = NOW() WHERE id = ?"); $stmt->bind_param('isi', $isImpossible, $reasoning, $combination['id']); if (!$stmt->execute()) { throw new Exception("Database update failed: " . $db->getLastError()); } return [ 'success' => true, 'is_impossible' => $isImpossible, 'reasoning' => $reasoning ]; } catch (Exception $e) { // Mark as checked with error $stmt = $db->prepare("UPDATE panel_directives SET llm_checked = 1, is_impossible = 0, llm_reasoning = ?, updated_at = NOW() WHERE id = ?"); $errorMsg = "Error: " . $e->getMessage(); $stmt->bind_param('si', $errorMsg, $combination['id']); $stmt->execute(); return [ 'success' => false, 'error' => $e->getMessage() ]; } } ?>