You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
v/src/glob/lib/unit_engine.ts

127 lines
4.3 KiB

import type { LocaleResolver, GlobLocale } from "./comn_types.ts";
import type { UnitCategoryData, UnitCategoryInstance, UnitCategoryKey, UnitDisplay, UnitInstance, UnitSystem } from "./unit_types.ts";
import { resolveLocale } from "./comn_engine.ts";
import { DEFAULT_ISO_LOCALE } from "@/ling/lib/consts.ts";
import { type LingNode, type LingInstance, ling } from "@/ling/lib";
import { unitData } from "./unit_data.ts";
import { unitsLingNode } from "./unit_langs.ts";
// ==============================
// CONVERSIÓN DE TEMPERATURA
// ==============================
function convertTemp(value: number, from: string, to: string): number {
if (from === to) return value;
let c: number;
switch (from) {
case 'c': c = value; break;
case 'f': c = (value - 32) * 5 / 9; break;
case 'k': c = value - 273.15; break;
default: c = value;
}
switch (to) {
case 'c': return c;
case 'f': return c * 9 / 5 + 32;
case 'k': return c + 273.15;
default: return c;
}
}
// ==============================
// CATEGORY ENGINE
// ==============================
function createCategory<S extends LingNode>(
categoryKey : UnitCategoryKey,
category : UnitCategoryData,
getSystem : () => UnitSystem,
defaultLocale: LocaleResolver,
ling : LingInstance<S>,
): UnitCategoryInstance {
function resolveTargetUnit(): string {
return getSystem() === 'imperial' ? category.baseImperial : category.base;
}
function formatValue(value: number, unitKey: string, display: UnitDisplay, locale: GlobLocale): string {
const formatted = new Intl.NumberFormat(locale, { maximumFractionDigits: 2 }).format(value);
if (display === 'abbr') {
// Lee símbolo de ling: units.weight.kg.abbr
const abbr = ling.t(`units.${categoryKey}.${unitKey}.abbr` as any);
return `${formatted} ${abbr}`;
}
// Lee nombre pluralizado de ling: units.weight.kg.name
const name = ling.t(`units.${categoryKey}.${unitKey}.name` as any, { count: value });
return `${formatted} ${name}`;
}
function convert(value: number, from: string, to: string): number {
if (from === to) return value;
if (categoryKey === 'temp') return convertTemp(value, from, to);
const fromData = category.units[from];
const toData = category.units[to];
if (!fromData || !toData) return value;
return (value * fromData.factor) / toData.factor;
}
function f(value: number, display: UnitDisplay = 'abbr', locale: LocaleResolver = defaultLocale): string {
const loc = resolveLocale(locale);
const unit = resolveTargetUnit();
return formatValue(value, unit, display, loc);
}
function fTo(value: number, targetUnit?: string, display: UnitDisplay = 'abbr', locale: LocaleResolver = defaultLocale): string {
const loc = resolveLocale(locale);
const to = targetUnit ?? resolveTargetUnit();
const converted = convert(value, category.base, to);
return formatValue(converted, to, display, loc);
}
return { f, fTo, convert };
}
// ==============================
// UNIT ENGINE
// ==============================
export function createUnit<S extends LingNode>(
ling : LingInstance<S>,
categories : Partial<Record<UnitCategoryKey, UnitCategoryData>> = {},
opts : { selectedSystem?: UnitSystem } = {},
defaultLocale: LocaleResolver = 'es'
): UnitInstance {
// El módulo registra sus propias traducciones en ling
ling.extend('units', unitsLingNode);
let currentSystem: UnitSystem = opts.selectedSystem ?? 'metric';
function getSystem(): UnitSystem { return currentSystem; }
function setSystem(s: UnitSystem) { currentSystem = s; }
const merged: Record<UnitCategoryKey, UnitCategoryData> = {
...unitData,
...categories,
};
const makeCategory = (key: UnitCategoryKey) =>
createCategory(key, merged[key], getSystem, defaultLocale, ling);
return {
getSystem,
setSystem,
weight : makeCategory('weight'),
length : makeCategory('length'),
temp : makeCategory('temp'),
volume : makeCategory('volume'),
area : makeCategory('area'),
};
}

Powered by TurnKey Linux.