/** * Game API Integration for AI Chatbot * Handles communication with FastAPI backend and experiment tracking */ // Auto-detect API base URL for both local and HuggingFace Spaces const API_BASE_URL = (typeof window !== 'undefined' && window.location) ? `${window.location.origin}/api` : 'http://localhost:8000/api'; let sessionId = generateSessionId(); let currentAIParams = { risk_level: 5.0, temperature: 0.7, confidence_boost: 0.0 }; let chatHistory = []; // Generate unique session ID function generateSessionId() { return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); } /** * Call AI chatbot with current game context */ async function askAI(question, context = {}) { try { // Use context parameters if provided, otherwise use current AI params const riskLevel = context.risk_level !== undefined ? context.risk_level : currentAIParams.risk_level; const temperature = context.temperature !== undefined ? context.temperature : currentAIParams.temperature; const confidenceBoost = context.confidence_boost !== undefined ? context.confidence_boost : currentAIParams.confidence_boost; const response = await fetch(`${API_BASE_URL}/ai/chat`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ question: question, chat_history: chatHistory, risk_level: riskLevel, temperature: temperature, confidence_boost: confidenceBoost, session_id: sessionId }) }); if (!response.ok) { const errorData = await response.json().catch(() => ({ detail: response.statusText })); console.error('AI API Error:', errorData); return { answer: `Error: ${errorData.detail || 'Failed to get AI advice'}` }; } const data = await response.json(); // Update chat history chatHistory.push([question, data.answer]); return data; } catch (error) { console.error('AI API Error:', error); return { answer: "I'm having trouble connecting. Please try again." }; } } /** * Log trading decision for trust analysis */ async function logDecision(symbol, action, quantity, price, aiAdviceFollowed, trustScore = null) { try { await fetch(`${API_BASE_URL}/experiment/decision`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ session_id: sessionId, symbol: symbol, action: action, quantity: quantity, price: price, ai_advice_followed: aiAdviceFollowed, trust_score: trustScore }) }); } catch (error) { console.error('Decision logging error:', error); } } /** * Trigger situational scenario */ async function triggerScenario(scenarioType, context = {}) { try { const response = await fetch(`${API_BASE_URL}/experiment/scenario`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ session_id: sessionId, scenario_type: scenarioType, context: context, ai_required: true }) }); const data = await response.json(); // Show scenario prompt to player and trigger AI assistance if (data.requires_ai) { showScenarioPrompt(data); } return data; } catch (error) { console.error('Scenario trigger error:', error); } } /** * Update AI parameters (for experiment control) */ function updateAIParams(riskLevel, temperature, confidenceBoost) { currentAIParams.risk_level = riskLevel; currentAIParams.temperature = temperature; currentAIParams.confidence_boost = confidenceBoost; // Update UI if controls exist updateAIParamsUI(); } /** * Check for scenario triggers based on game state */ function checkScenarioTriggers(gameState) { // Volatility check if (gameState.volatility > 0.15) { triggerScenario('volatility', { volatility: gameState.volatility, affected_stocks: gameState.positions }); } // Large position check const totalValue = gameState.positions.reduce((sum, pos) => sum + (pos.price * pos.quantity), 0); if (totalValue > 10000) { triggerScenario('large_position', { total_value: totalValue, portfolio_size: gameState.balance + totalValue }); } // Loss recovery check const dailyPnL = gameState.pnl; const pnlPercent = (dailyPnL / gameState.balance) * 100; if (pnlPercent < -5) { triggerScenario('loss_recovery', { current_loss: dailyPnL, loss_percent: pnlPercent }); } } /** * Show scenario prompt and AI assistance UI */ function showScenarioPrompt(scenarioData) { // Create modal or inline prompt const scenarioModal = document.createElement('div'); scenarioModal.className = 'scenario-modal fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50'; scenarioModal.innerHTML = `
${scenarioData.prompt}
🤖 AI Assistant:
Analyzing situation...