File size: 4,011 Bytes
ad77c79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# 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