Global Inflation & Hyperinflation Watchlist
Track and analyze simulated annual inflation trends across various countries, identifying potential hyperinflation risks.
Analysis Setup
Inflation Trend Analysis
Note: This tool uses simulated data for illustrative purposes. Real-world inflation data can be complex and influenced by numerous factors.
Annual Inflation Rate (%) Over Time
Watchlist Summary (Average & Max Inflation)
| Country | Average Annual Inflation (%) | Max Annual Inflation (%) | Status |
|---|
No countries flagged for high or hyperinflation in this period.
AI-Powered Insights
Generating AI insights...
`; const selectedCountryKeys = Array.from(document.querySelectorAll('#country-selection input:checked')).map(cb => cb.dataset.countryKey); const startYear = parseInt(startYearInput.value); const endYear = parseInt(endYearInput.value); // Input Validation if (selectedCountryKeys.length === 0) { showMessageBox("Selection Error", "Please select at least one country/region for analysis."); resetButtonState(trackBtn, trackBtnText, trackSpinner); return; } if (isNaN(startYear) || isNaN(endYear) || startYear < 1950 || endYear > 2023 || startYear >= endYear) { showMessageBox("Input Error", "Please enter valid start and end years (1950-2023) where the start year is before the end year."); resetButtonState(trackBtn, trackBtnText, trackSpinner); return; } // Generate simulated data for all selected countries const allInflationData = {}; selectedCountryKeys.forEach(countryKey => { allInflationData[countryKey] = generateSimulatedInflationData(countryKey, startYear, endYear); }); displayInflationTrends(allInflationData, selectedCountryKeys, startYear, endYear); populateWatchlistTable(allInflationData, selectedCountryKeys); const resultsSectionElement = document.getElementById('results-section'); if (resultsSectionElement) { resultsSectionElement.classList.remove('hidden'); resultsSectionElement.scrollIntoView({ behavior: 'smooth' }); } if (downloadPdfBtn) downloadPdfBtn.disabled = false; // Generate AI insights await getAIAnalysis(allInflationData, selectedCountryKeys, startYear, endYear); resetButtonState(trackBtn, trackBtnText, trackSpinner); }; // --- Display Results --- /** * Displays the inflation trends in a Chart.js line chart. */ function displayInflationTrends(allInflationData, selectedCountryKeys, startYear, endYear) { const ctx = inflationTrendChartCanvas?.getContext('2d'); if (!ctx) return; if (inflationChartInstance) { inflationChartInstance.destroy(); } const labels = Array.from({ length: endYear - startYear + 1 }, (_, i) => startYear + i); const datasets = selectedCountryKeys.map((countryKey, index) => { const countryData = allInflationData[countryKey].map(d => d.inflation); const colors = [ 'rgb(79, 70, 229)', // Indigo 'rgb(234, 88, 12)', // Orange 'rgb(16, 185, 129)', // Emerald 'rgb(59, 130, 246)', // Blue 'rgb(124, 58, 237)', // Violet 'rgb(244, 63, 94)', // Rose 'rgb(6, 182, 212)', // Cyan 'rgb(107, 114, 128)',// Gray 'rgb(251, 191, 36)', // Yellow 'rgb(185, 28, 28)', // Red 'rgb(2, 132, 199)' // Sky blue ]; return { label: COUNTRIES[countryKey].displayName, data: countryData, borderColor: colors[index % colors.length], backgroundColor: colors[index % colors.length], fill: false, tension: 0.1 // Smooth lines }; }); inflationChartInstance = new Chart(ctx, { type: 'line', data: { labels: labels, datasets: datasets }, options: { responsive: true, maintainAspectRatio: false, plugins: { tooltip: { callbacks: { label: function(context) { let label = context.dataset.label || ''; if (label) { label += ': '; } if (context.parsed.y !== null) { label += context.parsed.y.toFixed(2) + '%'; } return label; } } } }, scales: { x: { title: { display: true, text: 'Year' } }, y: { title: { display: true, text: 'Annual Inflation Rate (%)' }, beginAtZero: false } } } }); } /** * Populates the watchlist table with summary inflation metrics. */ function populateWatchlistTable(allInflationData, selectedCountryKeys) { if (!watchlistTableBody || !noWatchlistMessage) return; watchlistTableBody.innerHTML = ''; // Clear previous results let flaggedCountriesCount = 0; selectedCountryKeys.forEach(countryKey => { const countryData = allInflationData[countryKey]; const inflationRates = countryData.map(d => d.inflation); if (inflationRates.length === 0) return; // Skip if no data for this country const averageInflation = inflationRates.reduce((sum, val) => sum + val, 0) / inflationRates.length; const maxInflation = Math.max(...inflationRates); let status = 'Stable'; let rowClass = ''; // Initialize as empty if (maxInflation >= HYPERINFLATION_THRESHOLD_ANNUAL) { status = 'Hyperinflation Risk'; rowClass = 'hyperinflation-flag'; flaggedCountriesCount++; } else if (averageInflation >= HIGH_INFLATION_THRESHOLD_ANNUAL) { status = 'High Inflation'; rowClass = 'high-inflation-flag'; flaggedCountriesCount++; } else if (maxInflation >= HIGH_INFLATION_THRESHOLD_ANNUAL) { // If max was high but average was not status = 'Volatile (Spikes)'; rowClass = 'high-inflation-flag'; flaggedCountriesCount++; } const row = watchlistTableBody.insertRow(); // Only add the class if rowClass is not empty. This fixes the SyntaxError. if (rowClass) { row.classList.add(rowClass); } row.innerHTML = ` for titles and - for lists.
`;
try {
const payload = { contents: [{ role: "user", parts: [{ text: prompt }] }] };
const apiKey = ""; // API key is handled by the Canvas environment at runtime
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 AI analysis. Please try again.
";
if (result.candidates && result.candidates[0] && result.candidates[0].content && result.candidates[0].content.parts[0]) {
text = result.candidates[0].content.parts[0].text;
}
aiContainer.innerHTML = text;
} catch (error) {
console.error("Error fetching AI insights:", error);
aiContainer.innerHTML = `Error generating AI insights.
`;
}
};
// --- PDF Export Logic ---
/**
* Exports the visible analysis summary (chart, watchlist table, and AI insights) to a PDF document.
*/
window.downloadPDF = async () => { // Make it global for onclick attribute
const btn = document.getElementById('pdf-button-container')?.querySelector('button');
if (!btn) return;
btn.disabled = true;
btn.textContent = 'Generating PDF...';
const content = document.getElementById('summary-for-pdf');
if (!content) {
showMessageBox("PDF Error", "Content for PDF not found.");
btn.disabled = false;
btn.textContent = 'Download Analysis as PDF';
return;
}
try {
// Temporarily adjust chart and table sizes for better PDF rendering
const chartCanvas = inflationTrendChartCanvas;
const originalChartWidth = chartCanvas.style.width;
const originalChartHeight = chartCanvas.style.height;
chartCanvas.style.width = '1000px'; // Larger size for better quality capture
chartCanvas.style.height = '500px';
if (inflationChartInstance) {
inflationChartInstance.resize(); // Trigger Chart.js to redraw with new dimensions
}
const watchlistTable = document.getElementById('watchlist-table');
const originalTableWidth = watchlistTable.style.width;
watchlistTable.style.width = 'fit-content'; // Allow table to expand naturally for capture
const canvas = await html2canvas(content, {
scale: 2, // Increase scale for better resolution
useCORS: true,
logging: false,
backgroundColor: '#ffffff' // Ensure the background is white for PDF
});
// Restore original chart and table sizes
chartCanvas.style.width = originalChartWidth;
chartCanvas.style.height = originalChartHeight;
if (inflationChartInstance) {
inflationChartInstance.resize();
}
watchlistTable.style.width = originalTableWidth;
const imgData = canvas.toDataURL('image/png');
const { jsPDF } = window.jspdf;
// Determine orientation based on content width. If the captured canvas is very wide, use landscape.
const orientation = canvas.width > canvas.height * 1.5 ? 'landscape' : 'portrait';
const pdf = new jsPDF({ orientation: orientation, unit: 'mm', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const pdfHeight = pdf.internal.pageSize.getHeight();
const imgWidth = pdfWidth - 20; // 10mm margin on each side
let imgHeight = (canvas.height * imgWidth) / canvas.width;
let finalImgWidth = imgWidth;
let finalImgHeight = imgHeight;
if (finalImgHeight > pdfHeight - 20) { // If image is taller than page height
finalImgHeight = pdfHeight - 20;
finalImgWidth = (canvas.width * finalImgHeight) / canvas.height;
}
const x = (pdfWidth - finalImgWidth) / 2;
const y = (pdfHeight - finalImgHeight) / 2;
pdf.addImage(imgData, 'PNG', x, y, finalImgWidth, finalImgHeight);
pdf.save(`Inflation_Watchlist_Analysis_${new Date().toISOString().slice(0, 10)}.pdf`);
showMessageBox("PDF Generated", "Your Global Inflation Watchlist analysis PDF has been successfully downloaded.");
} catch(e) {
console.error("PDF Generation Error: ", e);
showMessageBox("PDF Error", "An error occurred while generating the PDF. Please ensure all content is visible and try again.");
} finally {
btn.disabled = false;
btn.textContent = 'Download Analysis as PDF';
}
};
// --- Initial Setup ---
initCountryCheckboxes();
// Optionally, run initial analysis on page load
// runAnalysis();
});
Could not generate AI analysis. Please try again.
"; if (result.candidates && result.candidates[0] && result.candidates[0].content && result.candidates[0].content.parts[0]) { text = result.candidates[0].content.parts[0].text; } aiContainer.innerHTML = text; } catch (error) { console.error("Error fetching AI insights:", error); aiContainer.innerHTML = `Error generating AI insights.
`; } }; // --- PDF Export Logic --- /** * Exports the visible analysis summary (chart, watchlist table, and AI insights) to a PDF document. */ window.downloadPDF = async () => { // Make it global for onclick attribute const btn = document.getElementById('pdf-button-container')?.querySelector('button'); if (!btn) return; btn.disabled = true; btn.textContent = 'Generating PDF...'; const content = document.getElementById('summary-for-pdf'); if (!content) { showMessageBox("PDF Error", "Content for PDF not found."); btn.disabled = false; btn.textContent = 'Download Analysis as PDF'; return; } try { // Temporarily adjust chart and table sizes for better PDF rendering const chartCanvas = inflationTrendChartCanvas; const originalChartWidth = chartCanvas.style.width; const originalChartHeight = chartCanvas.style.height; chartCanvas.style.width = '1000px'; // Larger size for better quality capture chartCanvas.style.height = '500px'; if (inflationChartInstance) { inflationChartInstance.resize(); // Trigger Chart.js to redraw with new dimensions } const watchlistTable = document.getElementById('watchlist-table'); const originalTableWidth = watchlistTable.style.width; watchlistTable.style.width = 'fit-content'; // Allow table to expand naturally for capture const canvas = await html2canvas(content, { scale: 2, // Increase scale for better resolution useCORS: true, logging: false, backgroundColor: '#ffffff' // Ensure the background is white for PDF }); // Restore original chart and table sizes chartCanvas.style.width = originalChartWidth; chartCanvas.style.height = originalChartHeight; if (inflationChartInstance) { inflationChartInstance.resize(); } watchlistTable.style.width = originalTableWidth; const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; // Determine orientation based on content width. If the captured canvas is very wide, use landscape. const orientation = canvas.width > canvas.height * 1.5 ? 'landscape' : 'portrait'; const pdf = new jsPDF({ orientation: orientation, unit: 'mm', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgWidth = pdfWidth - 20; // 10mm margin on each side let imgHeight = (canvas.height * imgWidth) / canvas.width; let finalImgWidth = imgWidth; let finalImgHeight = imgHeight; if (finalImgHeight > pdfHeight - 20) { // If image is taller than page height finalImgHeight = pdfHeight - 20; finalImgWidth = (canvas.width * finalImgHeight) / canvas.height; } const x = (pdfWidth - finalImgWidth) / 2; const y = (pdfHeight - finalImgHeight) / 2; pdf.addImage(imgData, 'PNG', x, y, finalImgWidth, finalImgHeight); pdf.save(`Inflation_Watchlist_Analysis_${new Date().toISOString().slice(0, 10)}.pdf`); showMessageBox("PDF Generated", "Your Global Inflation Watchlist analysis PDF has been successfully downloaded."); } catch(e) { console.error("PDF Generation Error: ", e); showMessageBox("PDF Error", "An error occurred while generating the PDF. Please ensure all content is visible and try again."); } finally { btn.disabled = false; btn.textContent = 'Download Analysis as PDF'; } }; // --- Initial Setup --- initCountryCheckboxes(); // Optionally, run initial analysis on page load // runAnalysis(); });