Spaces:
Running
Running
| /** | |
| * 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 = ` | |
| <div class="bg-gray-800 p-6 rounded-xl max-w-2xl"> | |
| <h3 class="text-2xl font-bold mb-4">Trading Scenario</h3> | |
| <p class="text-gray-300 mb-4">${scenarioData.prompt}</p> | |
| <div id="ai-advice-container" class="mb-4 p-4 bg-gray-700 rounded-lg"> | |
| <p class="text-green-400">🤖 AI Assistant:</p> | |
| <p id="ai-advice-text" class="mt-2">Analyzing situation...</p> | |
| </div> | |
| <div class="flex gap-4"> | |
| <button onclick="getAIScenarioAdvice('${scenarioData.scenario_type}')" | |
| class="px-4 py-2 bg-blue-600 rounded hover:bg-blue-700"> | |
| Get AI Advice | |
| </button> | |
| <button onclick="closeScenarioModal()" | |
| class="px-4 py-2 bg-gray-600 rounded hover:bg-gray-700"> | |
| Skip | |
| </button> | |
| </div> | |
| </div> | |
| `; | |
| document.body.appendChild(scenarioModal); | |
| // Auto-request AI advice | |
| getAIScenarioAdvice(scenarioData.scenario_type); | |
| } | |
| /** | |
| * Get AI advice for scenario | |
| */ | |
| async function getAIScenarioAdvice(scenarioType) { | |
| const question = `I'm facing a ${scenarioType} scenario. What should I do?`; | |
| const advice = await askAI(question); | |
| const adviceText = document.getElementById('ai-advice-text'); | |
| if (adviceText) { | |
| adviceText.textContent = advice.answer; | |
| } | |
| } | |
| /** | |
| * Close scenario modal | |
| */ | |
| function closeScenarioModal() { | |
| const modal = document.querySelector('.scenario-modal'); | |
| if (modal) { | |
| modal.remove(); | |
| } | |
| } | |
| /** | |
| * Enhanced trading function with AI integration | |
| */ | |
| async function executeTradeWithAI(symbol, action, quantity, price) { | |
| // Ask AI for advice before executing | |
| const question = `Should I ${action} ${quantity} shares of ${symbol} at $${price.toFixed(2)}?`; | |
| const aiAdvice = await askAI(question); | |
| // Show AI advice to player | |
| const confirmTrade = confirm( | |
| `AI Advice: ${aiAdvice.answer}\n\nProceed with ${action.toUpperCase()} ${quantity} ${symbol}?` | |
| ); | |
| if (confirmTrade) { | |
| // Execute trade - update game state (placeholder for now) | |
| // TODO: Implement actual trade execution with game state update | |
| console.log(`Executing ${action} ${quantity} ${symbol} at $${price.toFixed(2)}`); | |
| // Update UI to show trade was executed | |
| alert(`Trade executed: ${action.toUpperCase()} ${quantity} ${symbol}`); | |
| // Log decision | |
| await logDecision(symbol, action, quantity, price, true); | |
| // Ask for trust score | |
| const trustScore = prompt('How much did you trust the AI advice? (1-10):'); | |
| if (trustScore) { | |
| await logDecision(symbol, action, quantity, price, true, parseFloat(trustScore)); | |
| } | |
| } else { | |
| // Player ignored AI advice | |
| await logDecision(symbol, action, quantity, price, false); | |
| } | |
| } | |
| /** | |
| * Update AI parameters UI (if you add controls) | |
| */ | |
| function updateAIParamsUI() { | |
| const paramsDisplay = document.getElementById('ai-params-display'); | |
| if (paramsDisplay) { | |
| paramsDisplay.innerHTML = ` | |
| Risk: ${currentAIParams.risk_level.toFixed(1)} | | |
| Temp: ${currentAIParams.temperature.toFixed(2)} | | |
| Confidence: ${currentAIParams.confidence_boost.toFixed(0)} | |
| `; | |
| } | |
| } | |
| // Export for use in game | |
| window.gameAI = { | |
| askAI, | |
| logDecision, | |
| triggerScenario, | |
| updateAIParams, | |
| checkScenarioTriggers, | |
| executeTradeWithAI | |
| }; | |