`;
};
// --- AI ANALYSIS ---
window.getAIAnalysis = async () => {
const btn = document.getElementById('ai-analysis-btn');
btn.disabled = true;
document.getElementById('ai-btn-text').style.display = 'none';
document.getElementById('ai-spinner').style.display = 'inline-block';
const region = document.getElementById('ai-region-select').value;
const riskType = document.getElementById('ai-risk-select').value;
const regionData = REGION_DATA[region];
const prompt = `
Act as a geopolitical risk analyst for an investment firm.
Analyze the following scenario and provide a brief for an investor.
- Region of Interest: ${region}
- Specific Risk to Analyze: ${riskType}
- Internal Risk Scores for ${region}: Political=${regionData.political}, Economic=${regionData.economic}, Social=${regionData.social}.
Please provide:
1. A brief "Executive Summary" of the situation.
2. A list of 2-3 "Key Drivers" for this risk.
3. A list of 2-3 potential "Investment Implications".
Format the response in simple HTML using only for titles and
for titles and - for lists.
`;
try {
const payload = { contents: [{ role: "user", parts: [{ text: prompt }] }] };
const apiKey = ""; // Provided by Canvas
const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`;
const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });
const result = await response.json();
let text = "Could not generate analysis. Please try again.";
if (result.candidates && result.candidates[0].content && result.candidates[0].content.parts[0]) {
text = result.candidates[0].content.parts[0].text;
}
state.aiAnalysisHTML = text;
document.getElementById('ai-analysis-content').innerHTML = state.aiAnalysisHTML;
document.getElementById('ai-analysis-container').classList.remove('hidden');
document.getElementById('summary-ai-content').innerHTML = state.aiAnalysisHTML;
} finally {
btn.disabled = false;
document.getElementById('ai-btn-text').style.display = 'inline-block';
document.getElementById('ai-spinner').style.display = 'none';
}
};
// --- PORTFOLIO IMPACT ---
const updatePortfolioAllocation = () => {
const sliders = document.querySelectorAll('#portfolio-sliders input');
let total = 0;
sliders.forEach(slider => {
const value = parseInt(slider.value);
total += value;
state.portfolio[slider.dataset.asset] = value / 100;
});
const totalEl = document.getElementById('allocation-total');
totalEl.textContent = `Total: ${total}%`;
totalEl.className = `text-center mt-4 font-bold ${total === 100 ? 'text-green-600' : 'text-red-600'}`;
runImpactAnalysis(); // Re-run analysis on slider change
};
const runImpactAnalysis = () => {
state.shockScenario = document.getElementById('shock-scenario-select').value;
const impacts = SHOCK_SCENARIOS[state.shockScenario];
const resultsContainer = document.getElementById('portfolio-impact-results');
let weightedImpact = 0;
let resultsHTML = '';
for (const asset of PORTFOLIO_ASSETS) {
const weight = state.portfolio[asset] || 0;
const impact = impacts[asset] || 0;
weightedImpact += weight * impact;
resultsHTML += `${asset} Impact: ${(impact * 100).toFixed(1)}%`;
}
resultsHTML += `Total Portfolio Impact: ${(weightedImpact * 100).toFixed(2)}%`;
resultsHTML += '';
resultsContainer.innerHTML = resultsHTML;
// Update summary tab content
document.getElementById('summary-portfolio-content').innerHTML = resultsHTML;
generateImpactChart();
};
// --- CHARTS & PDF ---
const generateImpactChart = () => {
const impacts = SHOCK_SCENARIOS[state.shockScenario];
const ctx = document.getElementById('impact-chart').getContext('2d');
const data = {
labels: PORTFOLIO_ASSETS,
datasets: [{
label: 'Projected Impact',
data: PORTFOLIO_ASSETS.map(asset => (impacts[asset] || 0) * 100),
backgroundColor: PORTFOLIO_ASSETS.map(asset => ((impacts[asset] || 0) >= 0 ? 'rgba(5, 150, 105, 0.6)' : 'rgba(220, 38, 38, 0.6)'))
}]
};
if (impactChart) impactChart.destroy();
impactChart = new Chart(ctx, { type: 'bar', data: data, options: { indexAxis: 'y', plugins: { legend: { display: false } }, scales: { x: { ticks: { callback: v => `${v}%`} } } } });
};
window.downloadPDF = async () => {
const btn = document.querySelector('#pdf-button-container button');
btn.disabled = true; btn.textContent = 'Generating...';
const { jsPDF } = window.jspdf;
const content = document.getElementById('summary-for-pdf');
try {
const canvas = await html2canvas(content, { scale: 2 });
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({ orientation: 'landscape', unit: 'mm', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
let imgWidth = pdfWidth - 20;
let imgHeight = canvas.height * imgWidth / canvas.width;
pdf.addImage(imgData, 'PNG', 10, 10, imgWidth, imgHeight);
pdf.save(`Geopolitical_Risk_Report_${new Date().toISOString().slice(0, 10)}.pdf`);
} finally {
btn.disabled = false; btn.textContent = 'Download Report as PDF';
}
};
init();
});
';
for (const asset of PORTFOLIO_ASSETS) {
const weight = state.portfolio[asset] || 0;
const impact = impacts[asset] || 0;
weightedImpact += weight * impact;
resultsHTML += `
';
resultsContainer.innerHTML = resultsHTML;
// Update summary tab content
document.getElementById('summary-portfolio-content').innerHTML = resultsHTML;
generateImpactChart();
};
// --- CHARTS & PDF ---
const generateImpactChart = () => {
const impacts = SHOCK_SCENARIOS[state.shockScenario];
const ctx = document.getElementById('impact-chart').getContext('2d');
const data = {
labels: PORTFOLIO_ASSETS,
datasets: [{
label: 'Projected Impact',
data: PORTFOLIO_ASSETS.map(asset => (impacts[asset] || 0) * 100),
backgroundColor: PORTFOLIO_ASSETS.map(asset => ((impacts[asset] || 0) >= 0 ? 'rgba(5, 150, 105, 0.6)' : 'rgba(220, 38, 38, 0.6)'))
}]
};
if (impactChart) impactChart.destroy();
impactChart = new Chart(ctx, { type: 'bar', data: data, options: { indexAxis: 'y', plugins: { legend: { display: false } }, scales: { x: { ticks: { callback: v => `${v}%`} } } } });
};
window.downloadPDF = async () => {
const btn = document.querySelector('#pdf-button-container button');
btn.disabled = true; btn.textContent = 'Generating...';
const { jsPDF } = window.jspdf;
const content = document.getElementById('summary-for-pdf');
try {
const canvas = await html2canvas(content, { scale: 2 });
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({ orientation: 'landscape', unit: 'mm', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
let imgWidth = pdfWidth - 20;
let imgHeight = canvas.height * imgWidth / canvas.width;
pdf.addImage(imgData, 'PNG', 10, 10, imgWidth, imgHeight);
pdf.save(`Geopolitical_Risk_Report_${new Date().toISOString().slice(0, 10)}.pdf`);
} finally {
btn.disabled = false; btn.textContent = 'Download Report as PDF';
}
};
init();
});
${asset} Impact: ${(impact * 100).toFixed(1)}%
`;
}
resultsHTML += `Total Portfolio Impact: ${(weightedImpact * 100).toFixed(2)}%
`;
resultsHTML += '