From b3a1ab2476d99c94a7e0f2631f6f833c8ce31b6e Mon Sep 17 00:00:00 2001 From: Yves Ulrich Tittes Date: Mon, 14 Oct 2024 13:25:02 +0200 Subject: [PATCH 1/3] =?UTF-8?q?added=20=C3=85=20as=20mathjs=20accepted=20u?= =?UTF-8?q?nit=20for=20SI=20unit=20calculations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/utils.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/common/utils.ts b/src/common/utils.ts index f30ec2734..fcd5f31c3 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -2,7 +2,7 @@ import { Logger } from "@nestjs/common"; import { inspect } from "util"; import { DateTime } from "luxon"; -import { format, unit } from "mathjs"; +import { format, unit, Unit, createUnit } from "mathjs"; import { Expression, FilterQuery, Model, PipelineStage } from "mongoose"; import { DatasetType } from "src/datasets/dataset-type.enum"; import { @@ -13,14 +13,23 @@ import { } from "./interfaces/common.interface"; import { ScientificRelation } from "./scientific-relation.enum"; +// add Å to mathjs accepted units as equivalent to angstrom +const isAlphaOriginal = Unit.isValidAlpha +Unit.isValidAlpha = function (c) { + return isAlphaOriginal(c) || c == 'Å' +} +createUnit('Å', '1 angstrom') + export const convertToSI = ( inputValue: number, inputUnit: string, ): { valueSI: number; unitSI: string } => { try { + // catch and normalize the different versions of Å in unicode + const normalizedUnit = inputUnit.normalize('NFC'); // Workaround related to a bug reported at https://github.com/josdejong/mathjs/issues/3097 and https://github.com/josdejong/mathjs/issues/2499 - const quantity = unit(inputValue, inputUnit) - .to(unit(inputUnit).toSI().toJSON().unit) + const quantity = unit(inputValue, normalizedUnit) + .to(unit(normalizedUnit).toSI().toJSON().unit) .toJSON(); return { valueSI: Number(quantity.value), unitSI: quantity.unit }; } catch (error) { From 7b47fe52c18e581c1e3171d38e7a5b999fd1bbbd Mon Sep 17 00:00:00 2001 From: Yves Ulrich Tittes Date: Mon, 21 Oct 2024 10:52:31 +0200 Subject: [PATCH 2/3] Added testing for SI unit conversions --- src/common/utils.spec.ts | 49 ++++++++++++++++++++++++++++++++++++++++ src/common/utils.ts | 3 +-- 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/common/utils.spec.ts diff --git a/src/common/utils.spec.ts b/src/common/utils.spec.ts new file mode 100644 index 000000000..ebd037444 --- /dev/null +++ b/src/common/utils.spec.ts @@ -0,0 +1,49 @@ +// Currently only covers converToSI +import { convertToSI } from './utils'; +import { createUnit, Unit } from 'mathjs'; + + +describe('convertToSI', () => { + it('should convert a known unit to SI successfully', () => { + const result = convertToSI(1, 'cm'); + expect(result.valueSI).toBeCloseTo(0.01); + expect(result.unitSI).toEqual('m'); + }); + + it('should convert angstrom to SI successfully', () => { + const result = convertToSI(1, 'Å'); + expect(result.valueSI).toBeCloseTo(1e-10); + expect(result.unitSI).toEqual('m'); + }); + + it('should handle different versions of Å in unicode', () => { + const inputUnit = '\u212B'; // Old unicode representation of "Å", is not boolean equal to the one we added. + const result = convertToSI(1, inputUnit); + expect(result.valueSI).toBeCloseTo(1e-10); + expect(result.unitSI).toEqual('m'); + }); + + it('should return the input value and unit if conversion fails', () => { + const result = convertToSI(1, 'invalidUnit'); + expect(result.valueSI).toEqual(1); + expect(result.unitSI).toEqual('invalidUnit'); + }); + + it('should convert SI units correctly', () => { + const result = convertToSI(1000, 'g'); + expect(result.valueSI).toBeCloseTo(1); + expect(result.unitSI).toEqual('kg'); + }); + + it('should handle already normalized units', () => { + const result = convertToSI(1, 'm'); + expect(result.valueSI).toEqual(1); + expect(result.unitSI).toEqual('m'); + }); + + it('should handle negative values properly', () => { + const result = convertToSI(-5, 'cm'); + expect(result.valueSI).toBeCloseTo(-0.05); + expect(result.unitSI).toEqual('m'); + }); +}); \ No newline at end of file diff --git a/src/common/utils.ts b/src/common/utils.ts index fcd5f31c3..230def355 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -25,8 +25,7 @@ export const convertToSI = ( inputUnit: string, ): { valueSI: number; unitSI: string } => { try { - // catch and normalize the different versions of Å in unicode - const normalizedUnit = inputUnit.normalize('NFC'); + const normalizedUnit = inputUnit.normalize('NFC'); // catch and normalize the different versions of Å in unicode // Workaround related to a bug reported at https://github.com/josdejong/mathjs/issues/3097 and https://github.com/josdejong/mathjs/issues/2499 const quantity = unit(inputValue, normalizedUnit) .to(unit(normalizedUnit).toSI().toJSON().unit) From 586d86d42f512d53aeb1c4e7775316be09182760 Mon Sep 17 00:00:00 2001 From: Yves Ulrich Tittes Date: Mon, 21 Oct 2024 15:14:52 +0200 Subject: [PATCH 3/3] ran lint --- src/common/utils.spec.ts | 50 +++++++++++++++++++--------------------- src/common/utils.ts | 10 ++++---- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/common/utils.spec.ts b/src/common/utils.spec.ts index ebd037444..90605c228 100644 --- a/src/common/utils.spec.ts +++ b/src/common/utils.spec.ts @@ -1,49 +1,47 @@ // Currently only covers converToSI -import { convertToSI } from './utils'; -import { createUnit, Unit } from 'mathjs'; +import { convertToSI } from "./utils"; - -describe('convertToSI', () => { - it('should convert a known unit to SI successfully', () => { - const result = convertToSI(1, 'cm'); +describe("convertToSI", () => { + it("should convert a known unit to SI successfully", () => { + const result = convertToSI(1, "cm"); expect(result.valueSI).toBeCloseTo(0.01); - expect(result.unitSI).toEqual('m'); + expect(result.unitSI).toEqual("m"); }); - it('should convert angstrom to SI successfully', () => { - const result = convertToSI(1, 'Å'); + it("should convert angstrom to SI successfully", () => { + const result = convertToSI(1, "Å"); expect(result.valueSI).toBeCloseTo(1e-10); - expect(result.unitSI).toEqual('m'); + expect(result.unitSI).toEqual("m"); }); - it('should handle different versions of Å in unicode', () => { - const inputUnit = '\u212B'; // Old unicode representation of "Å", is not boolean equal to the one we added. + it("should handle different versions of Å in unicode", () => { + const inputUnit = "\u212B"; // Old unicode representation of "Å", is not boolean equal to the one we added. const result = convertToSI(1, inputUnit); expect(result.valueSI).toBeCloseTo(1e-10); - expect(result.unitSI).toEqual('m'); + expect(result.unitSI).toEqual("m"); }); - it('should return the input value and unit if conversion fails', () => { - const result = convertToSI(1, 'invalidUnit'); + it("should return the input value and unit if conversion fails", () => { + const result = convertToSI(1, "invalidUnit"); expect(result.valueSI).toEqual(1); - expect(result.unitSI).toEqual('invalidUnit'); + expect(result.unitSI).toEqual("invalidUnit"); }); - it('should convert SI units correctly', () => { - const result = convertToSI(1000, 'g'); + it("should convert SI units correctly", () => { + const result = convertToSI(1000, "g"); expect(result.valueSI).toBeCloseTo(1); - expect(result.unitSI).toEqual('kg'); + expect(result.unitSI).toEqual("kg"); }); - it('should handle already normalized units', () => { - const result = convertToSI(1, 'm'); + it("should handle already normalized units", () => { + const result = convertToSI(1, "m"); expect(result.valueSI).toEqual(1); - expect(result.unitSI).toEqual('m'); + expect(result.unitSI).toEqual("m"); }); - it('should handle negative values properly', () => { - const result = convertToSI(-5, 'cm'); + it("should handle negative values properly", () => { + const result = convertToSI(-5, "cm"); expect(result.valueSI).toBeCloseTo(-0.05); - expect(result.unitSI).toEqual('m'); + expect(result.unitSI).toEqual("m"); }); -}); \ No newline at end of file +}); diff --git a/src/common/utils.ts b/src/common/utils.ts index 230def355..b771e2420 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -14,18 +14,18 @@ import { import { ScientificRelation } from "./scientific-relation.enum"; // add Å to mathjs accepted units as equivalent to angstrom -const isAlphaOriginal = Unit.isValidAlpha +const isAlphaOriginal = Unit.isValidAlpha; Unit.isValidAlpha = function (c) { - return isAlphaOriginal(c) || c == 'Å' -} -createUnit('Å', '1 angstrom') + return isAlphaOriginal(c) || c == "Å"; +}; +createUnit("Å", "1 angstrom"); export const convertToSI = ( inputValue: number, inputUnit: string, ): { valueSI: number; unitSI: string } => { try { - const normalizedUnit = inputUnit.normalize('NFC'); // catch and normalize the different versions of Å in unicode + const normalizedUnit = inputUnit.normalize("NFC"); // catch and normalize the different versions of Å in unicode // Workaround related to a bug reported at https://github.com/josdejong/mathjs/issues/3097 and https://github.com/josdejong/mathjs/issues/2499 const quantity = unit(inputValue, normalizedUnit) .to(unit(normalizedUnit).toSI().toJSON().unit)