#!/usr/bin/env python3 from numbers import Number from typing import Callable import constants class Converter(object): def __init__(self, name: str, category: str, to_canonical: Callable, from_canonical: Callable, unit: str) -> None: self.name = name self.category = category self.to_canonical = to_canonical self.from_canonical = from_canonical self.unit = unit def to_canonical(self, n: Number) -> Number: return self.to_canonical(n) def from_canonical(self, n: Number) -> Number: return self.from_canonical(n) def unit_suffix(self) -> str: return self.unit conversion_catalog = { "Second": Converter("Second", "time", lambda s: s, lambda s: s, "s"), "Minute": Converter("Minute", "time", lambda m: (m * constants.SECONDS_PER_MINUTE), lambda s: (s / constants.SECONDS_PER_MINUTE), "m"), "Hour": Converter("Hour", "time", lambda h: (h * constants.SECONDS_PER_HOUR), lambda s: (s / constants.SECONDS_PER_HOUR), "h"), "Day": Converter("Day", "time", lambda d: (d * constants.SECONDS_PER_DAY), lambda s: (s / constants.SECONDS_PER_DAY), "d"), "Week": Converter("Week", "time", lambda w: (w * constants.SECONDS_PER_WEEK), lambda s: (s / constants.SECONDS_PER_WEEK), "w"), "Fahrenheit": Converter("Fahrenheit", "temperature", lambda f: (f - 32.0) * 0.55555555, lambda c: c * 1.8 + 32.0, "°F"), "Celsius": Converter("Celsius", "temperature", lambda c: c, lambda c: c, "°C"), "Kelvin": Converter("Kelvin", "temperature", lambda k: k - 273.15, lambda c: c + 273.15, "°K"), } def convert(magnitude: Number, from_thing: str, to_thing: str) -> Number: src = conversion_catalog.get(from_thing, None) dst = conversion_catalog.get(to_thing, None) if src is None or dst is None: raise ValueError("No known conversion") if src.category != dst.category: raise ValueError("Incompatible conversion") return _convert(magnitude, src, dst) def _convert(magnitude: Number, from_unit: Converter, to_unit: Converter) -> Number: canonical = from_unit.to_canonical(magnitude) converted = to_unit.from_canonical(canonical) return converted def sec_to_min(s: float) -> float: return convert(s, "Second", "Minute") def sec_to_hour(s: float) -> float: return convert(s, "Second", "Hour") def sec_to_day(s: float) -> float: return convert(s, "Second", "Day") def sec_to_week(s: float) -> float: return convert(s, "Second", "Week") def min_to_sec(m: float) -> float: return convert(m, "Minute", "Second") def min_to_hour(m: float) -> float: return convert(m, "Minute", "Hour") def min_to_day(m: float) -> float: return convert(m, "Minute", "Day") def min_to_week(m: float) -> float: return convert(m, "Minute", "Week") def hour_to_sec(h: float) -> float: return convert(h, "Hour", "Second") def hour_to_min(h: float) -> float: return convert(h, "Hour", "Minute") def hour_to_day(h: float) -> float: return convert(h, "Hour", "Day") def hour_to_week(h: float) -> float: return convert(h, "Hour", "Week") def day_to_sec(d: float) -> float: return convert(d, "Day", "Second") def day_to_min(d: float) -> float: return convert(d, "Day", "Minute") def day_to_hour(d: float) -> float: return convert(d, "Day", "Hour") def day_to_week(d: float) -> float: return convert(d, "Day", "Week") def week_to_sec(w: float) -> float: return convert(w, "Week", "Second") def week_to_min(w: float) -> float: return convert(w, "Week", "Minute") def week_to_hour(w: float) -> float: return convert(w, "Week", "Hour") def week_to_day(w: float) -> float: return convert(w, "Week", "Day") def f_to_c(temp_f: float) -> float: """Fahrenheit to Celsius.""" return convert(temp_f, "Fahrenheit", "Celsius") def c_to_f(temp_c: float) -> float: """Celsius to Fahrenheit.""" return convert(temp_c, "Celsius", "Fahrenheit")