Files
KSP_project/app/services/fuel_conversion.py
T
2026-05-08 15:16:04 +08:00

81 lines
2.2 KiB
Python

from __future__ import annotations
from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
FUEL_FACTORS: list[tuple[str, Decimal]] = [
("HTPB", Decimal("0.00177")),
("Solid", Decimal("0.00178")),
("PBAN", Decimal("0.001772")),
("Kerolox", Decimal("0.0010290673")),
("Hydrolox", Decimal("0.00036235886")),
("Methalox", Decimal("0.000845043157")),
("Hydrazine", Decimal("0.001004")),
("MMH/NTO", Decimal("0.00116557")),
]
FUEL_DENSITY_T_PER_LITER = dict(FUEL_FACTORS)
VALUE_STEP = Decimal("0.000001")
def list_fuel_factors() -> list[dict[str, float | str]]:
return [
{"fuel": fuel, "tonnes_per_liter": _to_float(factor)}
for fuel, factor in FUEL_FACTORS
]
def convert_value(mode: str, raw_value: object) -> dict[str, object]:
value = _parse_positive_decimal(raw_value)
normalized_mode = mode.strip().lower()
if normalized_mode == "volume":
results = [
{
"fuel": fuel,
"value": _to_float(value * factor),
"unit": "t",
}
for fuel, factor in FUEL_FACTORS
]
return {
"mode": normalized_mode,
"input_value": _to_float(value),
"input_unit": "L",
"results": results,
}
if normalized_mode == "mass":
results = [
{
"fuel": fuel,
"value": _to_float(value / factor),
"unit": "L",
}
for fuel, factor in FUEL_FACTORS
]
return {
"mode": normalized_mode,
"input_value": _to_float(value),
"input_unit": "t",
"results": results,
}
raise ValueError("mode must be either 'volume' or 'mass'")
def _parse_positive_decimal(raw_value: object) -> Decimal:
try:
value = Decimal(str(raw_value))
except (InvalidOperation, ValueError, TypeError) as exc:
raise ValueError("value must be numeric") from exc
if value <= 0:
raise ValueError("value must be greater than zero")
return value
def _to_float(value: Decimal) -> float:
return float(value.quantize(VALUE_STEP, rounding=ROUND_HALF_UP))