openenv / engine.py
ishraddhapawar's picture
Upload 45 files
ad77c79 verified
Raw History Blame Contribute Delete
4.01 kB
# server/engine.py β€” Shared domain logic for the Supply Chain Simulator
# Both main.py (HTTP API) and openenv_wrapper.py (RL API) import from here
# to respect clean client/server separation.
import random
import uuid
from typing import Any, List, Dict
# ─── CONSTANTS ───────────────────────────────────────────────────────
INITIAL_FUNDS = 100000
SALE_PRICE = 150
STORAGE_COST = 10
CONTAINER_SIZE = 100
SHIPPING_COST = 3000
LATE_PENALTY_RATE = 0.20
# ─── DATA DEFINITIONS ───────────────────────────────────────────────
INITIAL_FACTORIES = [
{"id": "china", "name": "China (Shenzhen)", "baseCost": 50, "lat": 22.5, "lng": 114},
{"id": "india", "name": "India (Mumbai)", "baseCost": 45, "lat": 19, "lng": 72.8},
{"id": "mexico", "name": "Mexico (Monterrey)", "baseCost": 70, "lat": 25.6, "lng": -100.3},
{"id": "vietnam", "name": "Vietnam (Ho Chi Minh)", "baseCost": 42, "lat": 10.8, "lng": 106.6},
{"id": "brazil", "name": "Brazil (SΓ£o Paulo)", "baseCost": 65, "lat": -23.5, "lng": -46.6},
{"id": "germany", "name": "Germany (Stuttgart)", "baseCost": 90, "lat": 48.8, "lng": 9.2},
]
INITIAL_PORTS = [
{"id": "shanghai", "name": "Port of Shanghai", "baseDelay": 1},
{"id": "singapore", "name": "Port of Singapore", "baseDelay": 1},
{"id": "rotterdam", "name": "Port of Rotterdam", "baseDelay": 2},
{"id": "la", "name": "Port of LA", "baseDelay": 1},
{"id": "busan", "name": "Port of Busan", "baseDelay": 1},
{"id": "dubai", "name": "Port of Dubai (Jebel Ali)", "baseDelay": 2},
{"id": "santos", "name": "Port of Santos", "baseDelay": 2},
]
WAREHOUSES = [
{"id": "usa", "name": "USA (Chicago)"},
{"id": "eu", "name": "EU (Frankfurt)"},
{"id": "asia", "name": "Asia (Tokyo)"},
{"id": "mideast", "name": "Middle East (Dubai)"},
{"id": "latam", "name": "Latin America (SΓ£o Paulo)"},
{"id": "oceania", "name": "Oceania (Sydney)"},
]
INITIAL_DEMAND = {"usa": 100, "eu": 80, "asia": 120, "mideast": 60, "latam": 70, "oceania": 50}
ALL_WAREHOUSE_IDS = [w["id"] for w in WAREHOUSES]
# ─── GAME STATE ──────────────────────────────────────────────────────
class GameState:
turn: int = 1
scenario: str = "normal"
balance: float = INITIAL_FUNDS
benchmark_balance: float = INITIAL_FUNDS
inventory: Dict[str, int] = {}
demands: Dict[str, int] = {}
factoryCosts: List[Dict[str, Any]] = []
portDelays: List[Dict[str, Any]] = []
inTransit: List[Dict[str, Any]] = []
history: List[Dict[str, Any]] = []
events: List[Dict[str, Any]] = []
alerts: List[Dict[str, Any]] = []
month_shipping_costs: float = 0.0
month_goods_costs: float = 0.0
last_revenue: float = 0.0
def __init__(self) -> None:
self.reset()
def reset(self):
self.turn = 1
self.scenario = "normal"
self.balance = INITIAL_FUNDS
self.benchmark_balance = INITIAL_FUNDS
self.inventory = {w["id"]: 0 for w in WAREHOUSES}
self.demands = dict(INITIAL_DEMAND)
self.factoryCosts = [{"id": f["id"], "name": f["name"], "baseCost": f["baseCost"], "currentCost": f["baseCost"]} for f in INITIAL_FACTORIES]
self.portDelays = [{"id": p["id"], "name": p["name"], "baseDelay": p["baseDelay"], "currentDelay": p["baseDelay"], "isClosed": False} for p in INITIAL_PORTS]
self.inTransit = []
self.history = [{"month": 0, "profit": 0, "revenue": 0, "storage_costs": 0, "shipping_costs": 0, "penalties": 0, "balance": INITIAL_FUNDS, "benchmark": INITIAL_FUNDS}]
self.events = []
self.alerts = []
self.month_shipping_costs = 0
self.month_goods_costs = 0
self.last_revenue = 0