♻️ refactor(utils/conversion): simplify length chart and remove currency conversion via floatrates.com
This commit is contained in:
1 file changed
+57
-57
+57
-57
@@ -29,50 +29,50 @@ class Units():
|
||||
|
||||
self.LENGTH_CHART: dict[str, float] = {
|
||||
# meter
|
||||
"m": 1,
|
||||
"M": 1,
|
||||
"meter": 1,
|
||||
"m": 1,
|
||||
"M": 1,
|
||||
"meter": 1,
|
||||
# kilometer
|
||||
"km": 1e3,
|
||||
"KM": 1e3,
|
||||
"kilometer": 1e3,
|
||||
"km": 1e3,
|
||||
"KM": 1e3,
|
||||
"kilometer": 1e3,
|
||||
# centimeter
|
||||
"cm": 1e-2,
|
||||
"CM": 1e-2,
|
||||
"centimeter": 1e-2,
|
||||
"cm": 1e-2,
|
||||
"CM": 1e-2,
|
||||
"centimeter": 1e-2,
|
||||
# millimeter
|
||||
"mm": 1e-3,
|
||||
"mm": 1e-3,
|
||||
"MM": 1e-3,
|
||||
"millimeter": 1e-3,
|
||||
# micrometer
|
||||
"um": 1e-6,
|
||||
"um": 1e-6,
|
||||
"UM": 1e-6,
|
||||
"micrometer": 1e-6,
|
||||
# nanometer
|
||||
"nm": 1e-9,
|
||||
"NM": 1e-9,
|
||||
# nanometer
|
||||
"nm": 1e-9,
|
||||
"NM": 1e-9,
|
||||
"nanometer": 1e-9,
|
||||
# mile
|
||||
"mi": 1609.344,
|
||||
"MI": 1609.344,
|
||||
"mile": 1609.344,
|
||||
"mi": 1609.344,
|
||||
"MI": 1609.344,
|
||||
"mile": 1609.344,
|
||||
# yard
|
||||
"yd": 0.9144,
|
||||
"YD": 0.9144,
|
||||
"yd": 0.9144,
|
||||
"YD": 0.9144,
|
||||
"yard": 0.9144,
|
||||
# foot
|
||||
"ft": 0.3048,
|
||||
"FT": 0.3048,
|
||||
"foot": 0.3048,
|
||||
"feet": 0.3048,
|
||||
"ft": 0.3048,
|
||||
"FT": 0.3048,
|
||||
"foot": 0.3048,
|
||||
"feet": 0.3048,
|
||||
# inch
|
||||
"in": 0.0254,
|
||||
"IN": 0.0254,
|
||||
"inch": 0.0254,
|
||||
"inches": 0.0254,
|
||||
# nautical mile
|
||||
"nmi": 1852,
|
||||
"NMI": 1852,
|
||||
"nmi": 1852,
|
||||
"NMI": 1852,
|
||||
"nautical-mile": 1852,
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ class Units():
|
||||
"megohm": 1e6,
|
||||
"MΩ": 1e6,
|
||||
}
|
||||
|
||||
|
||||
self.CAPACITANCE_CHART: dict[str, float] = {
|
||||
"farad": 1,
|
||||
"F": 1,
|
||||
@@ -283,7 +283,7 @@ class Units():
|
||||
"lm": 1,
|
||||
"lux": 1,
|
||||
"lx": 1,
|
||||
}
|
||||
}
|
||||
|
||||
self.AREA_CHART: dict[str, float] = {
|
||||
"square-meter": 1,
|
||||
@@ -300,7 +300,7 @@ class Units():
|
||||
"mm2": 1e-6,
|
||||
}
|
||||
|
||||
# Ya no usamos currency_converter aquí.
|
||||
# We no longer use currency_converter here.
|
||||
|
||||
|
||||
class Conversion():
|
||||
@@ -309,10 +309,10 @@ class Conversion():
|
||||
|
||||
def convert(self, value: float, from_type: str, to_type: str):
|
||||
"""
|
||||
Generalized conversion function que funciona con todas las categorías,
|
||||
incluyendo moneda via floatrates.com.
|
||||
Generalized conversion function that works with all categories,
|
||||
including currency via floatrates.com.
|
||||
"""
|
||||
# Colección de todos los charts no-monedas
|
||||
# Collection of all non-currency charts
|
||||
charts = {
|
||||
"WEIGHT_CHART": self.units.WEIGHT_CHART,
|
||||
"LENGTH_CHART": self.units.LENGTH_CHART,
|
||||
@@ -322,7 +322,7 @@ class Conversion():
|
||||
"STORAGE_TYPE_CHART": self.units.STORAGE_TYPE_CHART,
|
||||
"ANGLE_CHART": self.units.ANGLE_CHART,
|
||||
"ENERGY_CHART": self.units.ENERGY_CHART,
|
||||
"SPEED_CHART": self.units.SPEED_CHART,
|
||||
"SPEED_CHART": self.units.SPEED_CHART,
|
||||
"PRESSURE_CHART": self.units.PRESSURE_CHART,
|
||||
"FORCE_CHART": self.units.FORCE_CHART,
|
||||
"POWER_CHART": self.units.POWER_CHART,
|
||||
@@ -336,17 +336,17 @@ class Conversion():
|
||||
"AREA_CHART": self.units.AREA_CHART,
|
||||
}
|
||||
|
||||
# 1) Revisar si está en alguno de los charts (no monedas)
|
||||
# 1) Check if it's in any of the charts (non-currency)
|
||||
for chart_name, chart in charts.items():
|
||||
if from_type in chart and to_type in chart:
|
||||
# Temperaturas usan lambdas
|
||||
# Temperatures use lambdas
|
||||
if chart_name == "TEMPERATURE_CHART":
|
||||
if from_type == to_type:
|
||||
return value
|
||||
to_kelvin = chart[from_type][0]
|
||||
from_kelvin = chart[to_type][1]
|
||||
return from_kelvin(to_kelvin(value))
|
||||
|
||||
|
||||
# Handle WEIGHT_CHART separately (tuple values)
|
||||
if chart_name == "WEIGHT_CHART":
|
||||
if from_type == to_type:
|
||||
@@ -355,24 +355,24 @@ class Conversion():
|
||||
from_kg = chart[to_type][1]
|
||||
return value * to_kg * from_kg
|
||||
|
||||
# Cualquier otro chart numérico
|
||||
# Any other numeric chart
|
||||
if from_type == to_type:
|
||||
return value
|
||||
return value * (chart[from_type] / chart[to_type])
|
||||
|
||||
# 2) Si ambos son códigos de moneda (p. ej. “USD”, “ARS”)
|
||||
# asumimos que están en mayúsculas y tienen 3 letras.
|
||||
# 2) If both are currency codes (e.g. “USD”, “ARS”)
|
||||
# we assume they are uppercase and have 3 letters.
|
||||
if len(from_type) == 3 and len(to_type) == 3 and from_type.isalpha() and to_type.isalpha():
|
||||
return self._convert_currency_via_floatrates(value, from_type, to_type)
|
||||
|
||||
# 3) Si no cae en ningún caso, error.
|
||||
# 3) If it doesn't fall into any case, error.
|
||||
raise ValueError(f"Unsupported conversion: {from_type} to {to_type}")
|
||||
|
||||
def _convert_currency_via_floatrates(self, value: float, from_code: str, to_code: str) -> float:
|
||||
"""
|
||||
Convierte usando el JSON de floatrates.com:
|
||||
- Hace GET a https://www.floatrates.com/daily/{from_lower}.json
|
||||
- Toma el rate de la clave to_lower y multiplica.
|
||||
Converts using the JSON from floatrates.com:
|
||||
- Makes GET to https://www.floatrates.com/daily/{from_lower}.json
|
||||
- Takes the rate from the to_lower key and multiplies.
|
||||
"""
|
||||
from_lower = from_code.lower()
|
||||
to_lower = to_code.lower()
|
||||
@@ -383,11 +383,11 @@ class Conversion():
|
||||
url = f"https://www.floatrates.com/daily/{from_lower}.json"
|
||||
resp = requests.get(url, timeout=5)
|
||||
if resp.status_code != 200:
|
||||
raise ValueError(f"Error al obtener datos de floatrates para {from_code}")
|
||||
raise ValueError(f"Error getting data from floatrates for {from_code}")
|
||||
|
||||
data = resp.json()
|
||||
if to_lower not in data:
|
||||
raise ValueError(f"Moneda destino '{to_code}' no encontrada en la respuesta de floatrates para '{from_code}'")
|
||||
raise ValueError(f"Target currency '{to_code}' not found in floatrates response for '{from_code}'")
|
||||
|
||||
rate = data[to_lower]["rate"]
|
||||
return value * rate
|
||||
@@ -396,11 +396,11 @@ class Conversion():
|
||||
parts = input.split()
|
||||
addition = "s" if parts[-1].endswith("s") else ""
|
||||
|
||||
if "and" in parts: # valor unidad1 and valor2 unidad2 _ a unidad_destino
|
||||
if "and" in parts: # value unit1 and value2 unit2 _ to target_unit
|
||||
parts.remove("and")
|
||||
if len(parts) != 6:
|
||||
raise ValueError("Formato inválido. Esperado: 'value from_type and value2 from_type2 _ to_type'")
|
||||
|
||||
raise ValueError("Invalid format. Expected: 'value from_type and value2 from_type2 _ to_type'")
|
||||
|
||||
value1, from_type1, value2, from_type2, _, to_type = parts
|
||||
value1, value2 = float(value1), float(value2)
|
||||
from_type1 = self.clean_type(from_type1)
|
||||
@@ -416,7 +416,7 @@ class Conversion():
|
||||
return res, to_type + addition
|
||||
else:
|
||||
if len(parts) != 4:
|
||||
raise ValueError("Formato inválido. Esperado: 'value from_type _ to_type'")
|
||||
raise ValueError("Invalid format. Expected: 'value from_type _ to_type'")
|
||||
value, from_type, _, to_type = parts
|
||||
value = float(value)
|
||||
from_type = self.clean_type(from_type)
|
||||
@@ -425,25 +425,25 @@ class Conversion():
|
||||
|
||||
def clean_type(self, type: str) -> str:
|
||||
"""
|
||||
Si es moneda (3 letras), lo pasa a mayúsculas.
|
||||
Si termina en 's' (y no es 'celsius'), le quita la 's' para
|
||||
las otras unidades. """
|
||||
If it's currency (3 letters), convert to uppercase.
|
||||
If it ends in 's' (and is not 'celsius'), remove the 's' for
|
||||
other units. """
|
||||
if len(type) == 3 and type.isalpha():
|
||||
return type.upper()
|
||||
if type.endswith("s") and type.lower() != "celsius":
|
||||
# Para las tablas que tienen singular/plural
|
||||
# For tables that have singular/plural
|
||||
singular = type[:-1].lower()
|
||||
# Si existe en STORAGE_TYPE_CHART, lo usamos;
|
||||
# si no, devolvemos singular en minúsculas para otros charts.
|
||||
# If it exists in STORAGE_TYPE_CHART, we use it;
|
||||
# if not, we return singular in lowercase for other charts.
|
||||
if singular in self.units.STORAGE_TYPE_CHART:
|
||||
return singular
|
||||
return singular.lower()
|
||||
return type
|
||||
|
||||
|
||||
# Ejemplo rápido de uso:
|
||||
# Quick usage example:
|
||||
if __name__ == "__main__":
|
||||
conv = Conversion()
|
||||
# Convierte 10 USD a ARS:
|
||||
# Convert 10 USD to ARS:
|
||||
result, suffix = conv.parse_input_and_convert("10 USD _ ARS")
|
||||
print(f"{result:.2f} {suffix}") # Ej: "10 USD _ ARS" -> "38754.23 ARS"
|
||||
print(f"{result:.2f} {suffix}") # Ex: "10 USD _ ARS" -> "38754.23 ARS"
|
||||
Reference in new issue
Block a user