106 lines
3.0 KiB
Python
106 lines
3.0 KiB
Python
"""Konfigurations-Loader für das Moon/Apollo-Projekt.
|
|
|
|
Lädt Werte aus .env in Umgebungsvariablen und stellt sie typisiert bereit.
|
|
Verwendet python-dotenv. Enthält Validierung & sinnvolle Defaults.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import re
|
|
from dataclasses import dataclass
|
|
from typing import Tuple
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
# .env → os.environ laden
|
|
load_dotenv(override=False)
|
|
|
|
|
|
def _get_env(name: str, default: str) -> str:
|
|
val = os.getenv(name)
|
|
return val if val is not None and val != "" else default
|
|
|
|
|
|
def _parse_int(name: str, default: int, min_val: int | None = None) -> int:
|
|
raw = _get_env(name, str(default))
|
|
try:
|
|
v = int(raw)
|
|
if min_val is not None and v < min_val:
|
|
raise ValueError
|
|
return v
|
|
except Exception as _:
|
|
return default
|
|
|
|
|
|
def _parse_float(name: str, default: float, min_val: float | None = None) -> float:
|
|
raw = _get_env(name, str(default))
|
|
try:
|
|
v = float(raw)
|
|
if min_val is not None and v < min_val:
|
|
raise ValueError
|
|
return v
|
|
except Exception as _:
|
|
return default
|
|
|
|
|
|
_HEX = re.compile(r"^#?([0-9a-fA-F]{6})$")
|
|
|
|
|
|
def _parse_rgb(name: str, default_hex: str) -> Tuple[int, int, int]:
|
|
"""Erlaubt '#rrggbb' oder 'rrggbb'. Fällt auf default zurück, wenn ungültig."""
|
|
raw = _get_env(name, default_hex)
|
|
m = _HEX.match(raw)
|
|
hx = m.group(1) if m else default_hex.lstrip("#")
|
|
r = int(hx[0:2], 16)
|
|
g = int(hx[2:4], 16)
|
|
b = int(hx[4:6], 16)
|
|
return (r, g, b)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Settings:
|
|
# Anzeige
|
|
width: int
|
|
height: int
|
|
fps: int
|
|
bg_color: Tuple[int, int, int]
|
|
|
|
# Erde
|
|
earth_color: Tuple[int, int, int]
|
|
earth_radius: int
|
|
|
|
# Mond
|
|
moon_color: Tuple[int, int, int]
|
|
moon_radius: int
|
|
moon_orbit_radius: int
|
|
moon_angular_speed_deg: float # Grad/Sekunde
|
|
|
|
# Apollo (optional)
|
|
apollo_color: Tuple[int, int, int]
|
|
apollo_radius: int
|
|
apollo_orbit_radius: int
|
|
|
|
|
|
def get_settings() -> Settings:
|
|
"""Erzeugt Settings aus Umgebungsvariablen oder Defaults."""
|
|
return Settings(
|
|
# Anzeige
|
|
width=_parse_int("WIDTH", 800, min_val=100),
|
|
height=_parse_int("HEIGHT", 600, min_val=100),
|
|
fps=_parse_int("FPS", 60, min_val=1),
|
|
bg_color=_parse_rgb("BG_COLOR", "#0a0a14"),
|
|
# Erde
|
|
earth_color=_parse_rgb("EARTH_COLOR", "#2878ff"),
|
|
earth_radius=_parse_int("EARTH_RADIUS", 30, min_val=1),
|
|
# Mond
|
|
moon_color=_parse_rgb("MOON_COLOR", "#f0f0f0"),
|
|
moon_radius=_parse_int("MOON_RADIUS", 10, min_val=1),
|
|
moon_orbit_radius=_parse_int("MOON_ORBIT_RADIUS", 160, min_val=10),
|
|
moon_angular_speed_deg=_parse_float("MOON_ANGULAR_SPEED_DEG", 45.0, min_val=0.1),
|
|
# Apollo
|
|
apollo_color=_parse_rgb("APOLLO_COLOR", "#dc3232"),
|
|
apollo_radius=_parse_int("APOLLO_RADIUS", 7, min_val=1),
|
|
apollo_orbit_radius=_parse_int("APOLLO_ORBIT_RADIUS", 40, min_val=5),
|
|
)
|