const DEFAULT_MAGNITUDE_STEPS = [ { min: 1000, decimals: 2 }, { min: 1, decimals: 4 }, { min: 0.001, decimals: 6 }, { min: 0, decimals: 9 } ] function getOption(options, index) { return options[Number(index)] || options[0] } function normalizeIndex(index, options, fallback = 0) { const numericIndex = Number(index) if (!Number.isInteger(numericIndex) || numericIndex < 0 || numericIndex >= options.length) return fallback return numericIndex } function parseLooseNumber(value, allowNegative = true) { const text = String(value === undefined || value === null ? '' : value).trim().replace(/,/g, '.') if (!text) return null const numberValue = Number(text) if (!Number.isFinite(numberValue)) return NaN if (!allowNegative && numberValue < 0) return NaN return numberValue } function parsePositiveNumber(value) { const numberValue = parseLooseNumber(value, true) if (numberValue === null) return null return Number.isFinite(numberValue) && numberValue > 0 ? numberValue : NaN } function trimFixed(text) { return text.replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '') } function formatMagnitudeNumber(value, options = {}) { const { fallbackText = '--', steps = DEFAULT_MAGNITUDE_STEPS, zeroText = '0' } = options const numberValue = Number(value) if (!Number.isFinite(numberValue)) return fallbackText if (numberValue === 0) return zeroText const absValue = Math.abs(numberValue) const selectedStep = (steps || DEFAULT_MAGNITUDE_STEPS).find((step) => absValue >= step.min) || (steps || DEFAULT_MAGNITUDE_STEPS)[(steps || DEFAULT_MAGNITUDE_STEPS).length - 1] let text = trimFixed(numberValue.toFixed(selectedStep.decimals)) if (text === '0' && absValue > 0) { text = trimFixed(numberValue.toFixed(12)) } return text } function selectBestUnit(units, baseValue, fallbackIndex = 0) { const absValue = Math.abs(Number(baseValue)) if (!Number.isFinite(absValue) || absValue <= 0) { return { index: fallbackIndex, unit: getOption(units, fallbackIndex) } } let selectedIndex = 0 for (let index = 0; index < units.length; index += 1) { if (absValue / units[index].factor >= 1) selectedIndex = index } return { index: selectedIndex, unit: getOption(units, selectedIndex) } } function formatScaledValue(baseValue, unit, options = {}) { const { includeUnit = false } = options const selectedUnit = unit || { factor: 1, label: '' } const valueText = formatMagnitudeNumber(baseValue / selectedUnit.factor, options) return includeUnit && selectedUnit.label ? `${valueText} ${selectedUnit.label}` : valueText } module.exports = { DEFAULT_MAGNITUDE_STEPS, formatMagnitudeNumber, formatScaledValue, getOption, normalizeIndex, parseLooseNumber, parsePositiveNumber, selectBestUnit, trimFixed }