diff --git a/app/routes/api.py b/app/routes/api.py index 5fbb66c..c443ffc 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -18,6 +18,42 @@ from app import simulation_manager api_bp = Blueprint('api', __name__) +@api_bp.route('/test-websocket', methods=['GET']) +def test_websocket(): + """ + Test WebSocket connectivity and emit test data. + + Returns: + JSON response indicating WebSocket test status + """ + try: + # Emit a test message to all connected clients + test_data = { + 'test': True, + 'message': 'WebSocket test from server', + 'timestamp': time.time(), + 'distribution': { + 'labels': ['Test $0-100', 'Test $100-200', 'Test $200-300'], + 'counts': [3, 5, 2] + } + } + + socketio.emit('websocket_test', test_data, broadcast=True) + + return jsonify({ + 'status': 'success', + 'message': 'WebSocket test message sent', + 'test_data': test_data + }) + + except Exception as e: + current_app.logger.error(f"WebSocket test error: {str(e)}") + return jsonify({ + 'status': 'error', + 'message': f'WebSocket test failed: {str(e)}' + }), 500 + + @api_bp.route('/simulation', methods=['POST']) def create_simulation(): """ diff --git a/app/routes/main.py b/app/routes/main.py index de69af0..b712be7 100644 --- a/app/routes/main.py +++ b/app/routes/main.py @@ -101,6 +101,92 @@ def results(simulation_id): title=f"Results - Simulation {simulation_id[:8]}") +@main_bp.route('/test-simulation') +def test_simulation(): + """ + Test endpoint to simulate a full simulation run and check distribution data flow. + + Returns: + JSON response with complete simulation test results + """ + import time + from app.models.economic_model import EconomicSimulation, SimulationParameters + + # Create test simulation with small parameters for quick testing + test_params = SimulationParameters( + r_rate=0.05, + g_rate=0.03, + initial_capital=1000, + initial_consumption=1000, + num_agents=20, + iterations=10 + ) + + test_sim = EconomicSimulation(test_params) + + # Simulate the full flow + results = { + 'simulation_created': True, + 'steps_completed': 0, + 'distribution_data': [], + 'final_distribution': None, + 'errors': [] + } + + try: + # Run simulation steps + for i in range(10): + snapshot = test_sim.step() + results['steps_completed'] = i + 1 + + # Test distribution data generation at each step + if i % 3 == 0: # Test every 3rd step like real simulation + try: + labels, counts = test_sim.get_wealth_histogram(5) + distribution_data = { + 'iteration': snapshot.iteration, + 'labels': labels, + 'counts': counts, + 'total_agents': len(test_sim.agents) + } + results['distribution_data'].append(distribution_data) + except Exception as e: + results['errors'].append(f'Distribution generation error at step {i}: {str(e)}') + + # Get final distribution + try: + final_labels, final_counts = test_sim.get_wealth_histogram(8) + results['final_distribution'] = { + 'labels': final_labels, + 'counts': final_counts, + 'total_count': sum(final_counts) + } + except Exception as e: + results['errors'].append(f'Final distribution error: {str(e)}') + + # Test API-style response format + results['api_format_test'] = { + 'distribution': { + 'labels': final_labels, + 'counts': final_counts, + 'bins': 8 + }, + 'latest_snapshot': { + 'iteration': test_sim.current_iteration, + 'total_wealth': test_sim.snapshots[-1].total_wealth if test_sim.snapshots else 0, + 'gini_coefficient': test_sim.snapshots[-1].gini_coefficient if test_sim.snapshots else 0 + } + } + + except Exception as e: + results['errors'].append(f'General simulation error: {str(e)}') + + results['success'] = len(results['errors']) == 0 + results['timestamp'] = time.time() + + return jsonify(results) + + @main_bp.route('/debug') def debug_info(): """ diff --git a/app/static/js/simulation.js b/app/static/js/simulation.js index 237b175..3e503be 100644 --- a/app/static/js/simulation.js +++ b/app/static/js/simulation.js @@ -1,3 +1,26 @@ +/** + * Test WebSocket connectivity and chart update + * Call from browser console: testWebSocket() + */ +window.testWebSocket = async function() { + debugLog('=== WEBSOCKET CONNECTIVITY TEST ==='); + + try { + const response = await fetch('/api/test-websocket'); + const result = await response.json(); + debugLog('WebSocket test API response', result); + + if (result.status === 'success') { + debugLog('✅ WebSocket test message sent from server'); + debugLog('Wait for incoming WebSocket message...'); + } else { + debugLog('❌ WebSocket test API failed', result); + } + } catch (error) { + debugLog('❌ WebSocket test API error', error); + } +}; + /** * Production debugging test function * Call from browser console: testDistributionChart() @@ -458,6 +481,23 @@ function initializeRealtimeUpdates() { } }); + // WebSocket test handler + socket.on('websocket_test', function(data) { + debugLog('WebSocket test message received', data); + + // Test updating the distribution chart with test data + if (charts.distribution && data.distribution) { + try { + charts.distribution.data.labels = data.distribution.labels; + charts.distribution.data.datasets[0].data = data.distribution.counts; + charts.distribution.update(); + debugLog('✅ WebSocket test: Chart updated successfully with test data'); + } catch (error) { + debugLog('❌ WebSocket test: Chart update failed', error); + } + } + }); + // Simulation progress updates socket.on('simulation_progress', function(data) { debugLog('Received real-time progress update');