- tools/simulate.py + puga/simulate.py: replica of PRUNplanner's simulator (flows and efficiency verified against screenshots), reports real new capex (planned minus built) - tools/scan.py: staffing variants, freight, HQ/experts, --planet mode, demolish-later, --min-n as a pure market-size filter, --json output - tools/history.py, tools/persistence.py: margin history and short-horizon payback checks - tools/plan_push.py: guarded delete; tools/state.py: syncs to empire/ - README with features and setup; CLAUDE.md made generic - Own-empire material (profile, state, plans, notes) moved to gitignored empire/; generic examples in plans/examples and state/company.example.yaml Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
36 lines
1.0 KiB
Python
36 lines
1.0 KiB
Python
"""Settings from .env (gitignored) and process environment. Never log secret values."""
|
|
import os
|
|
from . import ROOT
|
|
|
|
|
|
def _load_env() -> dict[str, str]:
|
|
out: dict[str, str] = {}
|
|
p = ROOT / ".env"
|
|
if p.exists():
|
|
for line in p.read_text().splitlines():
|
|
line = line.split("#", 1)[0].strip()
|
|
if "=" in line:
|
|
k, v = line.split("=", 1)
|
|
out[k.strip()] = v.strip().strip("'\"")
|
|
return out
|
|
|
|
|
|
_ENV = _load_env()
|
|
|
|
|
|
def get(key: str, default: str | None = None) -> str | None:
|
|
return os.environ.get(key) or _ENV.get(key) or default
|
|
|
|
|
|
DEFAULT_CX = get("DEFAULT_CX", "AI1")
|
|
CACHE_DIR = ROOT / "data" / "cache"
|
|
|
|
|
|
EMPIRE_DIR = ROOT / "empire" # gitignored: our empire: player profile, company state, own plans and notes
|
|
|
|
|
|
def state_path():
|
|
"""Real company state if synced (empire/), else the tracked example so the tools still run."""
|
|
real = EMPIRE_DIR / "state" / "company.yaml"
|
|
return real if real.exists() else ROOT / "state" / "company.example.yaml"
|