Fix wealth distribution chart functionality

- Add get_wealth_histogram() method to EconomicModel for histogram data
- Add new API endpoint /simulation/<id>/distribution for chart data
- Extend main data API with include_distribution parameter
- Update real-time progress updates to include distribution data
- Fix frontend updateCharts() to handle wealth distribution chart
- Add distribution data processing in simulation.js
- Update test_charts.py to verify histogram functionality

Resolves issue where wealth distribution chart was not updating during simulations.
This commit is contained in:
2025-08-24 20:10:58 +02:00
parent 27e185c2a6
commit 3a08de3a4a
4 changed files with 193 additions and 9 deletions

View File

@@ -111,6 +111,9 @@ def start_simulation(simulation_id: str):
# Emit progress update every 10 iterations or at milestones
if i % 10 == 0 or i == total_iterations - 1:
# Get distribution data for real-time chart updates
bin_labels, bin_counts = simulation.get_wealth_histogram(10)
progress_data = {
'simulation_id': simulation_id,
'iteration': snapshot.iteration,
@@ -119,7 +122,11 @@ def start_simulation(simulation_id: str):
'total_wealth': snapshot.total_wealth,
'gini_coefficient': snapshot.gini_coefficient,
'capital_share': snapshot.capital_share,
'wealth_concentration_top10': snapshot.wealth_concentration_top10
'wealth_concentration_top10': snapshot.wealth_concentration_top10,
'distribution': {
'labels': bin_labels,
'counts': bin_counts
}
}
socketio.emit('simulation_progress', progress_data,
@@ -272,6 +279,19 @@ def get_simulation_data(simulation_id: str):
'capital_shares': capital_over_time
}
# Include current wealth distribution histogram if requested
if request.args.get('include_distribution', '').lower() == 'true':
num_bins = request.args.get('bins', 10, type=int)
if num_bins < 1 or num_bins > 50:
num_bins = 10
bin_labels, bin_counts = simulation.get_wealth_histogram(num_bins)
response_data['distribution'] = {
'labels': bin_labels,
'counts': bin_counts,
'bins': num_bins
}
return jsonify(response_data)
except Exception as e:
@@ -279,6 +299,49 @@ def get_simulation_data(simulation_id: str):
return jsonify({'error': 'Internal server error'}), 500
@api_bp.route('/simulation/<simulation_id>/distribution', methods=['GET'])
def get_wealth_distribution(simulation_id: str):
"""
Get current wealth distribution histogram for charting.
Args:
simulation_id: Unique simulation identifier
Query Parameters:
bins: Number of histogram bins (default: 10)
Returns:
JSON response with histogram data
"""
try:
simulation = simulation_manager.get_simulation(simulation_id)
if not simulation:
return jsonify({'error': 'Simulation not found'}), 404
# Get number of bins from query parameter
num_bins = request.args.get('bins', 10, type=int)
if num_bins < 1 or num_bins > 50:
num_bins = 10 # Default to 10 bins
# Get histogram data
bin_labels, bin_counts = simulation.get_wealth_histogram(num_bins)
return jsonify({
'simulation_id': simulation_id,
'histogram': {
'labels': bin_labels,
'counts': bin_counts,
'total_agents': len(simulation.agents),
'bins': num_bins
}
})
except Exception as e:
current_app.logger.error(f"Error getting wealth distribution: {str(e)}")
return jsonify({'error': 'Internal server error'}), 500
@api_bp.route('/simulation/<simulation_id>/export/<format_type>', methods=['GET'])
def export_simulation_data(simulation_id: str, format_type: str):
"""