feat: add financial metrics endpoint and optimize economy tick with aggregate building calculations

This commit is contained in:
2025-10-04 21:26:27 +00:00
parent 8441695d0a
commit 26b2551cc9
7 changed files with 278 additions and 298 deletions
+32 -40
View File
@@ -1,6 +1,8 @@
from server.game_state import GameState
from server.models import BUILDING_CONFIGS, BuildingType
import time
from collections import defaultdict
from server.logger import logger
class EconomyEngine:
"""Handles all economy calculations and ticks"""
@@ -9,55 +11,45 @@ class EconomyEngine:
self.game_state = game_state
def tick(self):
"""Process one economy tick for all players"""
current_time = time.time()
"""
Process one economy tick for all players using an efficient aggregate calculation.
"""
logger.debug("Processing economy tick...")
start_time = time.perf_counter()
for player in self.game_state.players.values():
# Calculate power factor (10% if offline, 100% if online)
time_diff = current_time - player.last_online
if player.is_online:
power_factor = 1.0
else:
power_factor = 0.1
# Process player economy
self._process_player_economy(player, power_factor)
def _process_player_economy(self, player, power_factor: float):
"""Process economy for a single player"""
total_income = 0
total_population = 0
# Get all player buildings
buildings = self.game_state.get_player_buildings(player.player_id)
for building in buildings:
player_money_deltas = defaultdict(int)
player_total_population = defaultdict(int)
# 1. Single pass over all buildings to aggregate their effects
for building in self.game_state.buildings.values():
config = BUILDING_CONFIGS[building.building_type]
owner_id = building.owner_id
# Calculate base income
base_income = config.income
# Apply connectivity bonus for income-generating buildings
if base_income > 0:
zone_size = self.game_state.get_building_zone_size(building.x, building.y)
connectivity_bonus = 1.0 + (zone_size * 0.05) # 5% per road in zone
connectivity_bonus = 1.0 + (zone_size * 0.05)
base_income = int(base_income * connectivity_bonus)
# Add to totals
total_income += base_income
total_population += config.population
player_money_deltas[owner_id] += base_income
player_total_population[owner_id] += config.population
# 2. Apply the aggregated deltas to each player
for player_id, player in self.game_state.players.items():
power_factor = 1.0 if player.is_online else 0.1
money_delta = player_money_deltas.get(player_id, 0)
player.money += int(money_delta * power_factor)
total_population = player_total_population.get(player_id, 0)
player.population = max(0, total_population)
if player.money < -100000:
player.money = -100000
# Apply power factor
total_income = int(total_income * power_factor)
# Update player stats
player.money += total_income
player.population = max(0, total_population)
# Prevent negative money (but allow debt for realism)
if player.money < -100000:
player.money = -100000
duration = time.perf_counter() - start_time
logger.debug(f"Economy tick processed in {duration:.4f} seconds for {len(self.game_state.players)} players.")
def calculate_building_stats(self, player_id: str, building_type: BuildingType) -> dict:
"""Calculate what a building would produce for a player"""
config = BUILDING_CONFIGS[building_type]