From 52b8ab2248769ec1e5023bc39197850f92254064 Mon Sep 17 00:00:00 2001 From: Markus Busche Date: Tue, 26 Aug 2025 09:32:30 +0000 Subject: [PATCH] Fix wealth distribution histogram issue by correcting wealth calculation and improving data handling --- app/models/economic_model.py | 15 ++++--- app/routes/api.py | 13 +++++- app/static/js/simulation.js | 78 +++++++++++++++++++++++++++++++++--- 3 files changed, 92 insertions(+), 14 deletions(-) diff --git a/app/models/economic_model.py b/app/models/economic_model.py index 71c1e4c..0a2686e 100644 --- a/app/models/economic_model.py +++ b/app/models/economic_model.py @@ -309,25 +309,27 @@ class EconomicSimulation: if not self.agents: return [], [] - # Get current total wealth for all agents (capital + consumption) + # Get current total wealth for all agents using the correct method wealth_values = [] for agent in self.agents: - if agent.wealth_history and agent.consumption_history: - total_wealth = agent.wealth_history[-1] + agent.consumption_history[-1] - else: - total_wealth = agent.initial_capital + agent.initial_consumption + total_wealth = agent.get_total_wealth() wealth_values.append(total_wealth) if not wealth_values: return [], [] + # Debug logging + print(f"DEBUG: Wealth values - count: {len(wealth_values)}, min: {min(wealth_values)}, max: {max(wealth_values)}") + # Calculate histogram bins min_wealth = min(wealth_values) max_wealth = max(wealth_values) if min_wealth == max_wealth: # All agents have same wealth - return [f"${min_wealth:.0f}"], [len(wealth_values)] + result = [f"${min_wealth:.0f}"], [len(wealth_values)] + print(f"DEBUG: All agents have same wealth - labels: {result[0]}, counts: {result[1]}") + return result # Create bins bin_width = (max_wealth - min_wealth) / num_bins @@ -355,6 +357,7 @@ class EconomicSimulation: if bin_start <= wealth < bin_end: bin_counts[i] += 1 + print(f"DEBUG: Histogram result - labels: {bin_labels}, counts: {bin_counts}") return bin_labels, bin_counts def update_parameters(self, new_parameters: SimulationParameters): diff --git a/app/routes/api.py b/app/routes/api.py index c443ffc..21f0e77 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -150,6 +150,9 @@ def start_simulation(simulation_id: str): # Get distribution data for real-time chart updates bin_labels, bin_counts = simulation.get_wealth_histogram(10) + # Debug logging + print(f"DEBUG: Sending distribution data - labels: {bin_labels}, counts: {bin_counts}") + progress_data = { 'simulation_id': simulation_id, 'iteration': snapshot.iteration, @@ -363,7 +366,10 @@ def get_wealth_distribution(simulation_id: str): # Get histogram data bin_labels, bin_counts = simulation.get_wealth_histogram(num_bins) - return jsonify({ + # Debug logging + print(f"DEBUG: Distribution endpoint - labels: {bin_labels}, counts: {bin_counts}, bins: {num_bins}") + + response_data = { 'simulation_id': simulation_id, 'histogram': { 'labels': bin_labels, @@ -371,7 +377,10 @@ def get_wealth_distribution(simulation_id: str): 'total_agents': len(simulation.agents), 'bins': num_bins } - }) + } + + print(f"DEBUG: Distribution endpoint response: {response_data}") + return jsonify(response_data) except Exception as e: current_app.logger.error(f"Error getting wealth distribution: {str(e)}") diff --git a/app/static/js/simulation.js b/app/static/js/simulation.js index d9c317a..c3ce244 100644 --- a/app/static/js/simulation.js +++ b/app/static/js/simulation.js @@ -21,6 +21,59 @@ window.testWebSocket = async function() { } }; +/** + * Test distribution data generation + * Call from browser console: testDistributionData() + */ +window.testDistributionData = async function() { + debugLog('=== DISTRIBUTION DATA TEST ==='); + + try { + // First check if we have a simulation ID + const simulationId = currentSimulation.id; + if (!simulationId) { + debugLog('❌ No active simulation found'); + return; + } + + // Fetch distribution data directly from API + debugLog('Fetching distribution data from API...'); + const response = await fetch(`/api/simulation/${simulationId}/distribution?bins=5`); + const data = await response.json(); + + debugLog('Distribution API response', data); + + if (data.histogram) { + debugLog('Histogram data', { + labels: data.histogram.labels, + counts: data.histogram.counts, + total_agents: data.histogram.total_agents + }); + + // Try to update chart with this data + if (charts.distribution && data.histogram.labels && data.histogram.counts) { + debugLog('Attempting to update chart with API data...'); + try { + charts.distribution.data.labels = data.histogram.labels; + charts.distribution.data.datasets[0].data = data.histogram.counts; + charts.distribution.update(); + debugLog('✅ Chart updated successfully with API data'); + } catch (error) { + debugLog('❌ Error updating chart with API data', error); + } + } else { + debugLog('❌ Cannot update chart - missing chart instance or data'); + } + } else { + debugLog('❌ No histogram data in response'); + } + } catch (error) { + debugLog('❌ Error fetching distribution data', error); + } + + debugLog('=== DISTRIBUTION DATA TEST COMPLETE ==='); +}; + /** * Enhanced distribution update test function * Call from browser console: testDistributionUpdate() @@ -483,10 +536,10 @@ function initializeCharts() { charts.distribution = new Chart(distributionCtx, { type: 'bar', data: { - labels: [], + labels: [], // Initialize with empty arrays datasets: [{ label: 'Number of Agents', - data: [], + data: [], // Initialize with empty array backgroundColor: 'rgba(40, 167, 69, 0.7)', borderColor: '#28a745', borderWidth: 1 @@ -515,7 +568,8 @@ function initializeCharts() { title: { display: true, text: 'Number of Agents' - } + }, + beginAtZero: true // Ensure y-axis starts at zero } } } @@ -963,7 +1017,13 @@ function updateSimulationProgress(data) { socketConnected: window.MarkovEconomics ? window.MarkovEconomics.isConnected : 'unknown' }); - if (data.distribution && data.distribution.labels && data.distribution.counts) { + // More robust handling of distribution data + if (data.distribution && + Array.isArray(data.distribution.labels) && + Array.isArray(data.distribution.counts) && + data.distribution.labels.length > 0 && + data.distribution.counts.length > 0) { + debugLog('Updating distribution data', { labelsLength: data.distribution.labels.length, countsLength: data.distribution.counts.length, @@ -971,6 +1031,7 @@ function updateSimulationProgress(data) { counts: data.distribution.counts }); + // Store the distribution data properly currentSimulation.data.distribution.labels = [...data.distribution.labels]; currentSimulation.data.distribution.counts = [...data.distribution.counts]; } else { @@ -1015,11 +1076,16 @@ function updateCharts() { canvasElement: document.getElementById('distributionChart') }); + // Ensure we have valid data before updating if (distData.labels && distData.labels.length > 0 && distData.counts && distData.counts.length > 0) { try { - charts.distribution.data.labels = distData.labels; - charts.distribution.data.datasets[0].data = distData.counts; + // Make sure we're working with arrays + const labels = Array.isArray(distData.labels) ? distData.labels : []; + const counts = Array.isArray(distData.counts) ? distData.counts : []; + + charts.distribution.data.labels = labels; + charts.distribution.data.datasets[0].data = counts; charts.distribution.update('none'); debugLog('✅ Distribution chart updated successfully'); } catch (error) {