Files
alro65 0dbc2a4518 v0.1-sprint0: Esqueleto completo AR-ShipDesign
- Estructura completa de carpetas (236 módulos stub + implementados)
- pyproject.toml, requirements, .gitignore, LICENSE (propietario)
- core/project.py: serialización .arsd (ZIP con JSON)
- core/units.py: conversiones SI <-> imperial completas
- ui/main_window.py: layout DELFTship-style con todos los paneles
  - Árbol de proyecto (dock izquierda)
  - Tabs de módulos (centro)
  - Panel de propiedades (dock derecha)
  - Panel hidrostáticos en vivo (inferior, fijo)
- ui/i18n: español e inglés
- ui/themes: tema claro y oscuro
- utils/logger.py, settings.py, validation.py
- data/liquids.json: 15 líquidos navales
- data/stability_criteria.json: IMO IS Code 2008, A.749(18), USCG
- tests/test_startup.py: 12 tests, todos PASSED
- Módulo scantling/ ISO 12215 (stubs Sprint 2.5)
- Módulo fabrication/molds/ para moldes FRP (stubs Sprint 13B)
- Módulo fabrication/ para CNC plasma/router/laser (stubs Sprint 13)
2026-05-26 22:10:18 -04:00

286 lines
9.0 KiB
Python

"""
Conversiones de unidades SI ↔ Imperial para AR-ShipDesign.
Internamente todo se almacena en SI (m, kg, s, N, Pa, W).
Este módulo convierte para visualización en UI cuando el usuario
selecciona unidades imperiales.
Unidades SI base:
Longitud → metro (m)
Masa → kilogramo (kg)
Fuerza → Newton (N)
Presión → Pascal (Pa)
Potencia → Watt (W)
Velocidad → metro/segundo (m/s)
Volumen → metro cúbico (m³)
Área → metro cuadrado (m²)
Temperatura → Celsius (°C)
"""
from __future__ import annotations
from enum import Enum
class UnitSystem(Enum):
SI = "si"
IMPERIAL = "imperial"
# ──────────────────────────────────────────────
# LONGITUD
# ──────────────────────────────────────────────
def m_to_ft(m: float) -> float:
"""Metros → Pies."""
return m * 3.280839895
def ft_to_m(ft: float) -> float:
"""Pies → Metros."""
return ft / 3.280839895
def m_to_in(m: float) -> float:
"""Metros → Pulgadas."""
return m * 39.3700787
def in_to_m(inches: float) -> float:
"""Pulgadas → Metros."""
return inches / 39.3700787
def mm_to_in(mm: float) -> float:
"""Milímetros → Pulgadas."""
return mm / 25.4
def in_to_mm(inches: float) -> float:
"""Pulgadas → Milímetros."""
return inches * 25.4
def nm_to_km(nm: float) -> float:
"""Millas náuticas → Kilómetros."""
return nm * 1.852
def km_to_nm(km: float) -> float:
"""Kilómetros → Millas náuticas."""
return km / 1.852
# ──────────────────────────────────────────────
# VELOCIDAD
# ──────────────────────────────────────────────
def ms_to_kn(ms: float) -> float:
"""m/s → Nudos."""
return ms * 1.943844
def kn_to_ms(kn: float) -> float:
"""Nudos → m/s."""
return kn / 1.943844
def kn_to_kmh(kn: float) -> float:
"""Nudos → km/h."""
return kn * 1.852
def kmh_to_kn(kmh: float) -> float:
"""km/h → Nudos."""
return kmh / 1.852
# ──────────────────────────────────────────────
# MASA Y FUERZA
# ──────────────────────────────────────────────
def kg_to_lb(kg: float) -> float:
"""Kilogramos → Libras."""
return kg * 2.204622622
def lb_to_kg(lb: float) -> float:
"""Libras → Kilogramos."""
return lb / 2.204622622
def kg_to_ton_metric(kg: float) -> float:
"""Kilogramos → Toneladas métricas."""
return kg / 1000.0
def ton_metric_to_kg(t: float) -> float:
"""Toneladas métricas → Kilogramos."""
return t * 1000.0
def kg_to_ton_long(kg: float) -> float:
"""Kilogramos → Toneladas largas (UK)."""
return kg / 1016.0469088
def ton_long_to_kg(t: float) -> float:
"""Toneladas largas → Kilogramos."""
return t * 1016.0469088
def n_to_lbf(n: float) -> float:
"""Newton → Libra-fuerza."""
return n * 0.224808943
def lbf_to_n(lbf: float) -> float:
"""Libra-fuerza → Newton."""
return lbf / 0.224808943
# ──────────────────────────────────────────────
# PRESIÓN
# ──────────────────────────────────────────────
def pa_to_psi(pa: float) -> float:
"""Pascal → PSI."""
return pa * 0.000145038
def psi_to_pa(psi: float) -> float:
"""PSI → Pascal."""
return psi / 0.000145038
def pa_to_bar(pa: float) -> float:
"""Pascal → Bar."""
return pa / 100000.0
def bar_to_pa(bar: float) -> float:
"""Bar → Pascal."""
return bar * 100000.0
def pa_to_kpa(pa: float) -> float:
"""Pascal → Kilopascal."""
return pa / 1000.0
def kpa_to_pa(kpa: float) -> float:
"""Kilopascal → Pascal."""
return kpa * 1000.0
# ──────────────────────────────────────────────
# POTENCIA
# ──────────────────────────────────────────────
def w_to_hp(w: float) -> float:
"""Watt → Caballos de vapor (metric HP)."""
return w / 735.49875
def hp_to_w(hp: float) -> float:
"""HP métrico → Watt."""
return hp * 735.49875
def w_to_bhp(w: float) -> float:
"""Watt → BHP (brake horsepower, SAE)."""
return w / 745.69987
def bhp_to_w(bhp: float) -> float:
"""BHP → Watt."""
return bhp * 745.69987
def w_to_kw(w: float) -> float:
"""Watt → Kilowatt."""
return w / 1000.0
def kw_to_w(kw: float) -> float:
"""Kilowatt → Watt."""
return kw * 1000.0
# ──────────────────────────────────────────────
# VOLUMEN
# ──────────────────────────────────────────────
def m3_to_ft3(m3: float) -> float:
"""m³ → ft³."""
return m3 * 35.3146667
def ft3_to_m3(ft3: float) -> float:
"""ft³ → m³."""
return ft3 / 35.3146667
def m3_to_liters(m3: float) -> float:
"""m³ → Litros."""
return m3 * 1000.0
def liters_to_m3(liters: float) -> float:
"""Litros → m³."""
return liters / 1000.0
def m3_to_usgal(m3: float) -> float:
"""m³ → Galones US."""
return m3 * 264.172052
def usgal_to_m3(gal: float) -> float:
"""Galones US → m³."""
return gal / 264.172052
# ──────────────────────────────────────────────
# ÁREA
# ──────────────────────────────────────────────
def m2_to_ft2(m2: float) -> float:
"""m² → ft²."""
return m2 * 10.7639104
def ft2_to_m2(ft2: float) -> float:
"""ft² → m²."""
return ft2 / 10.7639104
# ──────────────────────────────────────────────
# TEMPERATURA
# ──────────────────────────────────────────────
def c_to_f(celsius: float) -> float:
"""Celsius → Fahrenheit."""
return celsius * 9 / 5 + 32
def f_to_c(fahrenheit: float) -> float:
"""Fahrenheit → Celsius."""
return (fahrenheit - 32) * 5 / 9
# ──────────────────────────────────────────────
# DENSIDAD
# ──────────────────────────────────────────────
def kg_m3_to_lb_ft3(rho: float) -> float:
"""kg/m³ → lb/ft³."""
return rho * 0.062427961
def lb_ft3_to_kg_m3(rho: float) -> float:
"""lb/ft³ → kg/m³."""
return rho / 0.062427961
# ──────────────────────────────────────────────
# MOMENTO
# ──────────────────────────────────────────────
def nm_to_ft_lbf(nm: float) -> float:
"""Newton·metro → ft·lbf."""
return nm * 0.737562149
def ft_lbf_to_nm(ft_lbf: float) -> float:
"""ft·lbf → Newton·metro."""
return ft_lbf / 0.737562149
# ──────────────────────────────────────────────
# HELPER GENÉRICO para la UI
# ──────────────────────────────────────────────
UNIT_LABELS: dict[str, dict[str, str]] = {
"length": {"si": "m", "imperial": "ft"},
"length_small": {"si": "mm", "imperial": "in"},
"speed": {"si": "m/s", "imperial": "kn"},
"speed_nav": {"si": "kn", "imperial": "kn"},
"mass": {"si": "kg", "imperial": "lb"},
"displacement": {"si": "t", "imperial": "LT"},
"power": {"si": "kW", "imperial": "BHP"},
"pressure": {"si": "kPa", "imperial": "psi"},
"volume": {"si": "m³", "imperial": "ft³"},
"area": {"si": "m²", "imperial": "ft²"},
"temperature": {"si": "°C", "imperial": "°F"},
"density": {"si": "kg/m³", "imperial": "lb/ft³"},
}
def unit_label(quantity: str, system: str = "si") -> str:
"""Retorna la etiqueta de unidad para una cantidad dada."""
return UNIT_LABELS.get(quantity, {}).get(system, "—")