JoshBot / game /game-api-integration.js
LittleMonkeyLab's picture
Upload 19 files
e44e7cc verified
/**
* 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
};