Source code for models.charger
"""Charger model for the electric recreational port simulator."""
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional
[docs]
class ChargerState(Enum):
"""Charger state: idle or charging."""
IDLE = "idle"
CHARGING = "charging"
[docs]
@dataclass
class Charger:
"""
Charging station at the port.
Attributes:
max_power: Maximum output power (kW).
efficiency: Charging efficiency in (0, 1]; default 0.95.
power: Current output power (kW).
name: Identifier; auto-generated as Charger_N if empty.
_state: Internal state; use .state property.
connected_boat: Name of connected boat, or None.
"""
max_power: int
efficiency: float = 0.95
power: float = 0.0
name: str = ""
_state: ChargerState = field(default=ChargerState.IDLE, init=False)
connected_boat: Optional[str] = field(default=None, init=False)
_charger_count: int = field(default=0, init=False, repr=False)
def __post_init__(self):
"""Validate attributes and set default name if empty."""
if not self.name:
Charger._charger_count = getattr(Charger, "_charger_count", 0) + 1
self.name = f"Charger_{Charger._charger_count}"
if self.max_power <= 0:
raise ValueError("Max power must be positive")
if not 0 < self.efficiency <= 1:
raise ValueError("Efficiency must be between 0 and 1")
if self.power < 0:
raise ValueError("Power cannot be negative")
if self.power > self.max_power:
raise ValueError("Power cannot exceed max_power")
@property
def state(self) -> ChargerState:
"""Current charger state."""
return self._state
@state.setter
def state(self, new_state: ChargerState):
"""Set state; must be ChargerState. If IDLE, power and connected_boat are reset."""
if not isinstance(new_state, ChargerState):
raise ValueError(
f"State must be a ChargerState enum, got {type(new_state)}"
)
self._state = new_state
if new_state == ChargerState.IDLE:
self.power = 0.0
self.connected_boat = None
@property
def effective_power(self) -> float:
"""Power delivered to the battery after efficiency (kW)."""
return self.power * self.efficiency
def __repr__(self) -> str:
boat_info = (
f", connected to '{self.connected_boat}'" if self.connected_boat else ""
)
return (
f"Charger(name='{self.name}', max_power={self.max_power}kW, "
f"efficiency={self.efficiency:.1%}, power={self.power}kW, "
f"state={self.state.value}{boat_info})"
)