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.
127 lines
4.3 KiB
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'),
|
|
};
|
|
}
|