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

@@ -177,8 +177,8 @@ class EconomicSimulation:
gini_coefficient=gini,
wealth_concentration_top10=wealth_conc,
capital_share=capital_share,
average_wealth=np.mean(total_wealth_data),
median_wealth=np.median(total_wealth_data)
average_wealth=float(np.mean(total_wealth_data)),
median_wealth=float(np.median(total_wealth_data))
)
def _calculate_gini_coefficient(self, wealth_data: List[float]) -> float:
@@ -296,6 +296,67 @@ class EconomicSimulation:
return distribution
def get_wealth_histogram(self, num_bins: int = 10) -> Tuple[List[str], List[int]]:
"""
Get wealth distribution as histogram data for charting.
Args:
num_bins: Number of bins for the histogram
Returns:
Tuple of (bin_labels, bin_counts) for histogram chart
"""
if not self.agents:
return [], []
# Get current total wealth for all agents (capital + consumption)
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
wealth_values.append(total_wealth)
if not wealth_values:
return [], []
# 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)]
# Create bins
bin_width = (max_wealth - min_wealth) / num_bins
bins = [min_wealth + i * bin_width for i in range(num_bins + 1)]
# Count agents in each bin
bin_counts = [0] * num_bins
bin_labels = []
for i in range(num_bins):
# Create label for this bin
bin_start = bins[i]
bin_end = bins[i + 1]
if i == num_bins - 1: # Last bin includes upper bound
bin_labels.append(f"${bin_start:.0f} - ${bin_end:.0f}")
else:
bin_labels.append(f"${bin_start:.0f} - ${bin_end:.0f}")
# Count agents in this bin
for wealth in wealth_values:
if i == num_bins - 1: # Last bin includes upper bound
if bin_start <= wealth <= bin_end:
bin_counts[i] += 1
else:
if bin_start <= wealth < bin_end:
bin_counts[i] += 1
return bin_labels, bin_counts
def update_parameters(self, new_parameters: SimulationParameters):
"""
Update simulation parameters and restart with new settings.