Add production optimization with OR-Tools for HoI4 factory allocation and time-based planning#20
Conversation
… for HoI4 Co-authored-by: Napolitain <18146363+Napolitain@users.noreply.github.com>
Co-authored-by: Napolitain <18146363+Napolitain@users.noreply.github.com>
…risons Co-authored-by: Napolitain <18146363+Napolitain@users.noreply.github.com>
Co-authored-by: Napolitain <18146363+Napolitain@users.noreply.github.com>
There was a problem hiding this comment.
Pull Request Overview
This PR implements Phase 4 of the Hearts of Iron IV optimization system, adding production optimization capabilities using OR-Tools. The implementation focuses on factory allocation, equipment production, and time-based planning.
Key changes:
- Adds time simulation system with
GameDateandGameClockclasses for date-based planning - Implements equipment models covering infantry, armor, air, and naval equipment types
- Creates production system with factory efficiency modeling (10% → 100% over 90 days)
- Integrates OR-Tools linear programming solver for multi-objective factory allocation optimization
Reviewed Changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
games/hoi4/models/game_date.py |
Implements date/time management for HOI4 timeline with historical dates |
games/hoi4/models/equipment.py |
Defines equipment types, costs, resources, and combat statistics |
games/hoi4/models/production.py |
Production line and factory management with efficiency modeling |
games/hoi4/optimization/production_optimizer.py |
OR-Tools integration for optimal factory allocation |
games/hoi4/optimization/__init__.py |
Package initialization for optimization module |
tests/test_hoi4_phase4.py |
Comprehensive test suite with 31 tests covering all new functionality |
games/hoi4/optimization_demo.py |
Working demonstration script showcasing optimization capabilities |
games/hoi4/README.md |
Updated documentation with Phase 4 features and examples |
games/hoi4/PHASE4_SUMMARY.md |
Complete technical documentation of Phase 4 implementation |
games/hoi4/IMPLEMENTATION_SUMMARY.md |
High-level summary of implementation approach and achievements |
games/hoi4/__init__.py |
Updated exports for new classes |
games/hoi4/models/__init__.py |
Updated exports for new models |
|
|
||
| # Calculate expected output per factory | ||
| # Simplified: assume average efficiency | ||
| avg_efficiency = 0.5 * (1.0 + efficiency_modifiers) # Rough average |
There was a problem hiding this comment.
The hardcoded constant 0.5 for average efficiency is a magic number. This value represents the average efficiency over the production period (starting at 10% and reaching 100% over 90 days). Consider extracting this as a named constant (e.g., AVG_EFFICIENCY_MULTIPLIER = 0.5) with a comment explaining it represents the average of the efficiency growth curve, or better yet, calculate it dynamically based on BASE_EFFICIENCY and MAX_EFFICIENCY as (BASE_EFFICIENCY + MAX_EFFICIENCY) / 2 = (0.1 + 1.0) / 2 = 0.55.
There was a problem hiding this comment.
Fixed in 35453af - extracted to _calculate_average_efficiency() method that calculates (BASE_EFFICIENCY + MAX_EFFICIENCY) / 2 = 0.55 dynamically instead of hardcoded 0.5.
| days = start_date.days_until(goal.target_date) | ||
|
|
||
| # Calculate expected output per factory | ||
| avg_efficiency = 0.5 * (1.0 + efficiency_modifiers) |
There was a problem hiding this comment.
Same magic number 0.5 repeated here. This duplication increases maintenance burden. The average efficiency calculation appears in multiple places (lines 180, 198, 266, 323, 370). Extract this into a private helper method like _calculate_average_efficiency(efficiency_modifiers: float) -> float to ensure consistency and make the formula easier to update.
There was a problem hiding this comment.
Fixed in 35453af - all 5 occurrences now use the _calculate_average_efficiency() helper method.
| days = start_date.days_until(goal.target_date) | ||
|
|
||
| # Resource consumption per factory over the period | ||
| avg_efficiency = 0.5 * (1.0 + efficiency_modifiers) |
There was a problem hiding this comment.
Another instance of the duplicated average efficiency calculation. Consolidating these calculations into a helper method would improve maintainability.
There was a problem hiding this comment.
Fixed in 35453af - consolidated into the helper method.
|
|
||
| # Calculate expected output | ||
| days = start_date.days_until(goal.target_date) | ||
| avg_efficiency = 0.5 * (1.0 + efficiency_modifiers) |
There was a problem hiding this comment.
Fourth occurrence of the duplicated average efficiency calculation. This should use the same helper method as suggested earlier.
There was a problem hiding this comment.
Fixed in 35453af - consolidated into the helper method.
| return 0.0 | ||
|
|
||
| # Average efficiency over period | ||
| avg_efficiency = 0.5 * (1.0 + efficiency_modifiers) |
There was a problem hiding this comment.
Fifth occurrence of the duplicated average efficiency calculation. Consolidating all these instances would significantly improve code maintainability.
There was a problem hiding this comment.
Fixed in 35453af - consolidated into the helper method.
| from dataclasses import dataclass, field | ||
| from typing import Dict, List, Optional | ||
| from enum import Enum | ||
| from .equipment import Equipment, EquipmentType, EquipmentCategory |
There was a problem hiding this comment.
Import of 'EquipmentType' is not used.
| from .equipment import Equipment, EquipmentType, EquipmentCategory | |
| from .equipment import Equipment, EquipmentCategory |
There was a problem hiding this comment.
Fixed in 35453af - removed unused EquipmentType import.
| Uses OR-Tools to optimize factory allocation and production schedules. | ||
| """ | ||
|
|
||
| from typing import Dict, List, Optional, Tuple |
There was a problem hiding this comment.
Import of 'Tuple' is not used.
| from typing import Dict, List, Optional, Tuple | |
| from typing import Dict, List, Optional |
There was a problem hiding this comment.
Fixed in 35453af - removed unused Tuple import.
| from dataclasses import dataclass, field | ||
| from ortools.linear_solver import pywraplp | ||
| from ..models.equipment import Equipment, EquipmentCategory | ||
| from ..models.production import Production, ProductionLine |
There was a problem hiding this comment.
Import of 'ProductionLine' is not used.
Import of 'Production' is not used.
| from ..models.production import Production, ProductionLine | |
| # Removed unused imports: Production, ProductionLine |
There was a problem hiding this comment.
Fixed in 35453af - removed unused Production and ProductionLine imports.
| """ | ||
|
|
||
| import unittest | ||
| from datetime import datetime |
| create_infantry_equipment, create_artillery, | ||
| get_equipment, get_equipment_by_type, EQUIPMENT_DATABASE | ||
| ) | ||
| from games.hoi4.models.production import Production, ProductionLine, FactoryType |
There was a problem hiding this comment.
Import of 'FactoryType' is not used.
| from games.hoi4.models.production import Production, ProductionLine, FactoryType | |
| from games.hoi4.models.production import Production, ProductionLine |
There was a problem hiding this comment.
Fixed in 35453af - removed unused FactoryType import.
|
@copilot address feedback |
…, improve test assertions Co-authored-by: Napolitain <18146363+Napolitain@users.noreply.github.com>
Implementation Complete ✅
Successfully addressed all PR review feedback.
Changes Made
Code Quality Improvements
_calculate_average_efficiency()method that calculates the average efficiency dynamically as(BASE_EFFICIENCY + MAX_EFFICIENCY) / 2 = 0.55instead of hardcoded 0.5All Tasks Completed
Test Results:
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.