/
45case
/
ptable
Обзор
Документация
Войти
/
45case
/
ptable
Код
Запросы
3
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
dev
src/entities/element/lib/formatElementMass.ts
140 строк
4 KB
Olya
Страница Электроны + сайдбар с характеритстиками (Степень окисления, Конфигурация, Развёрнутая, Уровни энергии, ВЗМО)
24 июл 2026, 11:54
24 июл 2026, 11:54
3cf1d48
Код
Авторство
О чём код?
import { ptableAtomicMassAbridgedByZ } from "./ptableAtomicMassAbridged"; /** * Format atomic mass for UI. * - Default: ptable-style abridged card label (≤ 5 significant figures). * - `full: true`: raw `weight` string from JSON (full precision). * Parentheses around mass numbers (Tc, Mt, …) are omitted. */ export function formatElementMass( value: number | null, options?: { /** Atomic number — used to look up the exact ptable abridged label. */ atomicNumber?: number | null; /** Original ptable `weight` string; preferred for `full` and as fallback. */ source?: string | null; /** Show the full JSON weight string instead of the abridged card label. */ full?: boolean; /** Appended after the formatted mass, e.g. `"u"`. */ unit?: string; }, ) { const unit = options?.unit ? ` ${options.unit}` : ""; const source = options?.source?.trim(); if (options?.full) { if (source) { return `${stripMassParentheses(source).replace(".", ",")}${unit}`; } if (value == null || !Number.isFinite(value)) { return value == null ? "—" : `—${unit}`; } return `${String(value).replace(".", ",")}${unit}`; } const atomicNumber = options?.atomicNumber; if (atomicNumber != null) { const abridged = ptableAtomicMassAbridgedByZ[atomicNumber]; if (abridged) { return `${stripMassParentheses(abridged).replace(".", ",")}${unit}`; } } if (source) { return `${abridgeWeightSource(source).replace(".", ",")}${unit}`; } if (value == null) { return "—"; } if (!Number.isFinite(value)) { return `—${unit}`; } if (Number.isInteger(value)) { return `${value}${unit}`; } return `${abridgeWeightValue(value).replace(".", ",")}${unit}`; } function stripMassParentheses(label: string): string { return label.replace(/^\((.+)\)$/, "$1"); } function countSignificantFigures(decimalStr: string): number { const cleaned = decimalStr.replace(/^[+-]/, "").toLowerCase(); if (cleaned.includes("e")) { return countSignificantFigures(cleaned.split("e")[0]!); } const digits = cleaned.replace(".", "").replace(/^0+/, ""); return digits.length || 1; } /** Fallback abridgment when no Z lookup is available. */ function abridgeWeightSource(source: string): string { const value = Number(source); if (!Number.isFinite(value)) { return source; } if (!source.includes(".")) { return String(Math.trunc(value)); } if (countSignificantFigures(source) < 5) { return source; } return abridgeWeightValue(value); } function abridgeWeightValue(value: number): string { if (value === 0) { return "0"; } const abs = Math.abs(value); const order = Math.floor(Math.log10(abs)); const decimals = Math.max(0, 5 - 1 - order); // Round via string to reduce binary float drift (e.g. 50.9415 → 50.942). const fixed = abs.toFixed(decimals + 2); const [wholePart, fracPart = ""] = fixed.split(".") as [string, string]; const digits = `${wholePart}${fracPart}`.replace(/^0+/, "") || "0"; const roundedDigits = roundDigitString(digits, 5); const sign = value < 0 ? "-" : ""; if (order >= 4) { return `${sign}${roundedDigits}`; } if (order >= 0) { const wholeLength = order + 1; const whole = roundedDigits.slice(0, wholeLength) || "0"; const frac = roundedDigits.slice(wholeLength).padEnd(decimals, "0").slice(0, decimals); return frac ? `${sign}${whole}.${frac}` : `${sign}${whole}`; } const precision = value.toPrecision(5); return /[eE]/.test(precision) ? String(Number(precision)) : precision; } function roundDigitString(digits: string, significantFigures: number): string { if (digits.length <= significantFigures) { return digits.padEnd(significantFigures, "0"); } const head = digits.slice(0, significantFigures); const next = Number(digits[significantFigures] ?? "0"); if (next < 5) { return head; } const asNumber = BigInt(head) + 1n; return asNumber.toString().padStart(significantFigures, "0"); }