train-journey-visuals/units.py

109 lines
2.5 KiB
Python
Raw Permalink Normal View History

2024-04-16 16:40:43 +00:00
from enum import Enum, auto
from math import pi
class UnitClass(Enum):
NONE = auto()
LENGTH = auto()
SPEED = auto()
TIME = auto()
ANGLE = auto()
class Unit(Enum):
KM_H = auto(), UnitClass.SPEED
M_S = auto(), UnitClass.SPEED
KM = auto(), UnitClass.LENGTH
M = auto(), UnitClass.LENGTH
SEC = auto(), UnitClass.TIME
MIN = auto(), UnitClass.TIME
HOUR = auto(), UnitClass.TIME
DEG = auto(), UnitClass.ANGLE
RAD = auto(), UnitClass.ANGLE
NONE = auto(), UnitClass.NONE
def __init__(self, v: int, cls: UnitClass):
self.cls: UnitClass = cls
class Value:
def __init__(self, value: float, unit: Unit):
self.value: float = value
self.unit: Unit = unit
def convert(self, to_unit: Unit) -> "Value":
if self.unit == to_unit:
return self
from_cls = self.unit.cls
to_cls = to_unit.cls
if from_cls != to_cls:
raise ValueError(f"Cannot convert from {from_cls} to {to_cls}")
cls = from_cls
if cls == UnitClass.NONE:
to_value = self.value
elif cls == UnitClass.LENGTH:
value = self.value
if self.unit == Unit.KM:
value *= 1000
to_value = value
if to_unit == Unit.KM:
to_value /= 1000
elif cls == UnitClass.TIME:
value = self.value
if self.unit == Unit.MIN:
value *= 60
elif self.unit == Unit.HOUR:
value *= 3600
to_value = value
if to_unit == Unit.MIN:
to_value /= 60
elif self.unit == Unit.HOUR:
to_value /= 3600
elif cls == UnitClass.SPEED:
value = self.value
if self.unit == Unit.KM_H:
value /= 3.6
to_value = value
if to_unit == Unit.KM_H:
to_value *= 3.6
elif cls == UnitClass.ANGLE:
value = self.value
if self.unit == Unit.RAD:
value *= 180 / pi
to_value = value
if to_unit == Unit.RAD:
value *= pi / 180
else:
raise ValueError(f"Unknown unit class: {cls}")
return Value(to_value, to_unit)
def __repr__(self):
return f"{self.value} [{self.unit}]"
if __name__ == '__main__':
v1 = Value(765, Unit.KM_H)
print(v1)
print(v1.convert(Unit.M_S))
v2 = Value(120, Unit.SEC)
print(v2)
print(v2.convert(Unit.MIN))