Skip to content

Commit

Permalink
Format -> UnitMap (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonaskello authored Oct 20, 2020
1 parent a63c160 commit cc33332
Show file tree
Hide file tree
Showing 13 changed files with 81 additions and 115 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased](https://github.com/dividab/uom/compare/v5.0.0...master)

- Moved `Format.getUnitsForQuantity` to `UnitMap.getUnitsForQuantity`.
- Moved `Format.getUnitFormat` to `UnitFormat.getUnitFormat`.
- Removed extra paramter in `UnitMap.getUnitsForQuantity`.
- Remove `Format` module.
- Refactor tests, move to `__tests__` folder

## [v5.0.0](https://github.com/dividab/uom/compare/v4.1.0...v5.0.0) - 2020-10-08
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,16 @@ function calculate(Amount<Length> length1, Amount<Length> length2): Amount<Lengt

Asosciating formatting directly with an `Unit` or `Quantity` is generally not a good idea. Formatting is application specific and should be implemented within application code. For example, an application may have air flows and water flows that both are of `VolumeFlow` quantity. In this case you may want separate labels and default units for air flow and water flow. Associating formatting directly with `VolumeFlow` or its units will not solve this. Instead, try tagging each `VolumeFlow` field within the application with either `air_flow`, or `water_flow` and provide different labels and default units per tag.

However if you are just building something smaller and want quick formatting, the [uo] package has some opinionated formatting that is directly associated with each `Unit` built-in. Specifically you can get the label and number of decimals for each unit.

However if you are just building something smaller and want quick formatting, this package has some opinionated formatting that is directly associated with each `Unit` built-in. Specifically you can get the label and number of decimals for each unit.

```ts
import { Amount, Format } from "uom";
import { Units } from "uom-units";

const length = Amount.create(10, Units.Meter);
const format = Format.getUnitFormat(length);
const format = UnitFormat.getUnitFormat(length);
console.log(
"The amount is " +
Math.round(Amount.valueAs(Units.Inch, amount), format.decimalCount) +
Expand Down
48 changes: 18 additions & 30 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@
<dl>
<dt><a href="#module_Serialize">Serialize</a></dt>
<dd></dd>
<dt><a href="#module_Format">Format</a></dt>
<dd></dd>
<dt><a href="#module_Amount">Amount</a></dt>
<dd></dd>
<dt><a href="#module_Unit">Unit</a></dt>
<dd></dd>
</dl>

## Functions

<dl>
<dt><a href="#getUnitsForQuantity">getUnitsForQuantity(quantity)</a></dt>
<dd><p>Get all units registered for quantity</p>
</dd>
</dl>

<a name="module_Serialize"></a>

## Serialize
Expand Down Expand Up @@ -61,34 +67,6 @@ Convert a serialized amount to it's deserialized representation
| --- |
| amountString |

<a name="module_Format"></a>

## Format

* [Format](#module_Format)
* [.getUnitFormat(unit)](#module_Format.getUnitFormat)
* [.getUnitsForQuantity(quantity)](#module_Format.getUnitsForQuantity)

<a name="module_Format.getUnitFormat"></a>

### Format.getUnitFormat(unit)
Get formatting info from unit


| Param |
| --- |
| unit |

<a name="module_Format.getUnitsForQuantity"></a>

### Format.getUnitsForQuantity(quantity)
Get all units registered for quantity


| Param |
| --- |
| quantity |

<a name="module_Amount"></a>

## Amount
Expand Down Expand Up @@ -380,3 +358,13 @@ Converts numeric values from a unit to another unit.
| fromUnit | The unit from which to convert the numeric value. |
| toUnit | The unit to which to convert the numeric value. |

<a name="getUnitsForQuantity"></a>

## getUnitsForQuantity(quantity)
Get all units registered for quantity


| Param |
| --- |
| quantity |

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"verify": "yarn lint && yarn build && yarn test-coverage",
"test-coverage": "jest",
"report-coverage": "codecov -f coverage/lcov.info",
"gen-docs": "jsdoc2md --partial docs/scope.hbs --files lib-esm/serialize.js lib-esm/format.js lib-esm/amount.js lib-esm/unit.js > docs/api.md",
"gen-docs": "jsdoc2md --partial docs/scope.hbs --files lib-esm/serialize.js lib-esm/unit-map.js lib-esm/amount.js lib-esm/unit.js > docs/api.md",
"preversion": "git checkout master && git pull && yarn test && yarn build",
"postversion": "git push --tags && yarn publish --new-version $npm_package_version && git push --follow-tags && echo \"Successfully released version $npm_package_version!\""
},
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/serialize.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as Serialize from "../serialize";
import * as BaseUnits from "../base-units";
import { UnitMap } from "../unit";
import { UnitMap } from "../unit-map";

const baseUnitsLower = Object.keys(BaseUnits).reduce<UnitMap>(
(soFar, current) => {
Expand Down
24 changes: 0 additions & 24 deletions src/__tests__/tsconfig.json

This file was deleted.

20 changes: 20 additions & 0 deletions src/__tests__/unit-format.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as BaseUnits from "../base-units";
import * as UnitFormat from "../unit-format";

const UnitsFormat = {
Meter: UnitFormat.createUnitFormat("m", 2),
Kelvin: UnitFormat.createUnitFormat("°K", 2),
};

describe("format_test", () => {
test("should get label for Kelvin", (done) => {
const format = UnitFormat.getUnitFormat(BaseUnits.Kelvin, UnitsFormat);
if (!format) {
done.fail();
done();
} else {
expect(format.label).toEqual("°K");
done();
}
});
});
22 changes: 3 additions & 19 deletions src/__tests__/format.test.ts → src/__tests__/unit-map.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as Format from "../format";
import * as UnitMap from "../unit-map";
import * as BaseUnits from "../base-units";
import { createUnitFormat } from "../unit-format";

const containsAll = <T>(
arr1: ReadonlyArray<T>,
Expand All @@ -11,22 +10,7 @@ const sameMembers = <T>(
arr2: ReadonlyArray<T>
): boolean => containsAll(arr1, arr2) && containsAll(arr2, arr1);

const UnitsFormat = {
Meter: createUnitFormat("m", 2),
Kelvin: createUnitFormat("°K", 2),
};

describe("format_test", () => {
test("should get label for Kelvin", (done) => {
const format = Format.getUnitFormat(BaseUnits.Kelvin, UnitsFormat);
if (!format) {
done.fail();
done();
} else {
expect(format.label).toEqual("°K");
done();
}
});
test("Should get units for Length", () => {
const expected = [
BaseUnits.Meter,
Expand All @@ -39,7 +23,7 @@ describe("format_test", () => {
// Units.Inch,
// Units.Mile
];
const actual = Format.getUnitsForQuantity("Length", UnitsFormat, BaseUnits);
const actual = UnitMap.getUnitsForQuantity("Length", BaseUnits);
expect(actual.length).toEqual(expected.length);
expect(sameMembers(actual, expected)).toBeTruthy();
});
Expand All @@ -55,7 +39,7 @@ describe("format_test", () => {
// Units.Inch,
// Units.Mile
];
const actual = Format.getUnitsForQuantity("length", UnitsFormat, BaseUnits);
const actual = UnitMap.getUnitsForQuantity("length", BaseUnits);
expect(actual.length).toEqual(expected.length);
expect(sameMembers(actual, expected)).toBeTruthy();
});
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as Amount from "./amount";
import * as Unit from "./unit";
import * as Format from "./format";
import * as UnitMap from "./unit-map";
import * as UnitFormat from "./unit-format";
import * as Serialize from "./serialize";
import * as UnitPrefix from "./unit-prefix";
import * as BaseUnits from "./base-units";

export { Amount, Unit, UnitFormat, Format, Serialize, UnitPrefix, BaseUnits };
export { Amount, Unit, UnitFormat, UnitMap, Serialize, UnitPrefix, BaseUnits };
5 changes: 3 additions & 2 deletions src/serialize.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as Unit from "./unit";
import * as UnitMap from "./unit-map";
import * as Amount from "./amount";

/**
Expand All @@ -11,7 +12,7 @@ import * as Amount from "./amount";
*/
export function stringToUnit<T>(
unitString: string,
unitLookup: Unit.UnitLookup
unitLookup: UnitMap.UnitLookup
): Unit.Unit<T> | undefined {
return unitLookup(unitString) as Unit.Unit<T>;
}
Expand Down Expand Up @@ -43,7 +44,7 @@ export function amountToString(amount: Amount.Amount<unknown>): string {
*/
export function stringToAmount(
amountString: string,
unitLookup: Unit.UnitLookup
unitLookup: UnitMap.UnitLookup
): Amount.Amount<unknown> | undefined {
const parts = amountString.split(":");
const value = parseFloat(parts[0]);
Expand Down
13 changes: 13 additions & 0 deletions src/unit-format.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as Unit from "./unit";

/**
* @module UnitFormat
*/
Expand All @@ -9,6 +11,17 @@ export interface UnitFormat {

export type UnitFormatMap = { readonly [key: string]: UnitFormat };

/**
* Get formatting info from unit
* @param unit
*/
export function getUnitFormat(
unit: Unit.Unit<unknown>,
unitsFormat: UnitFormatMap
): UnitFormat | undefined {
return unitsFormat[unit.name];
}

/**
* Creates a unit format
* @param label
Expand Down
42 changes: 13 additions & 29 deletions src/format.ts → src/unit-map.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,30 @@
import * as Unit from "./unit";
import { UnitFormat, UnitFormatMap } from "./unit-format";

// export type UnitFormatMap<TUnitMap> = { [P in keyof TUnitMap]: UnitFormat };

/**
* @module Format
* @module UnitMap
*/

/**
* Get formatting info from unit
* @param unit
*/
export function getUnitFormat(
unit: Unit.Unit<unknown>,
unitsFormat: UnitFormatMap
): UnitFormat | undefined {
return unitsFormat[unit.name];
}
export type UnitLookup = (unitString: string) => Unit.Unit<unknown> | undefined;

export type UnitMap = {
readonly [key: string]: Unit.Unit<unknown>;
};

/**
* Get all units registered for quantity
* @param quantity
*/
export function getUnitsForQuantity(
quantity: string,
unitsFormat: UnitFormatMap,
units: Unit.UnitMap
units: UnitMap
): ReadonlyArray<Unit.Unit<unknown>> {
const quantityToUnits = getUnitsPerQuantity(unitsFormat, units);
const quantityToUnits = getUnitsPerQuantity(units);
const unitsForQuantity = quantityToUnits[quantity.toLowerCase()];
return unitsForQuantity || [];
}

interface LocalCache {
readonly input:
| {
readonly [key: string]: UnitFormat;
}
| undefined;
readonly input: UnitMap | undefined;
readonly output: // eslint-disable-next-line functional/prefer-readonly-type
{ readonly [key: string]: Array<Unit.Unit<unknown>> } | undefined;
}
Expand All @@ -48,17 +35,14 @@ let cache: LocalCache = {
output: undefined,
};
function getUnitsPerQuantity(
unitsFormat: {
readonly [key: string]: UnitFormat;
},
units: Unit.UnitMap
units: UnitMap
): { readonly [key: string]: ReadonlyArray<Unit.Unit<unknown>> } {
if (cache.input === unitsFormat && cache.output !== undefined) {
if (cache.input === units && cache.output !== undefined) {
return cache.output;
}
const quantityToUnits: { [key: string]: Array<Unit.Unit<unknown>> } = {};

for (const unitKey of Object.keys(unitsFormat)) {
for (const unitKey of Object.keys(units)) {
const unit = units[unitKey];
const quantityKey = (unit.quantity as string).toLowerCase();
quantityToUnits[quantityKey] = (quantityToUnits[quantityKey] || []).concat(
Expand All @@ -67,7 +51,7 @@ function getUnitsPerQuantity(
}

cache = {
input: unitsFormat,
input: units,
output: quantityToUnits,
};

Expand Down
6 changes: 0 additions & 6 deletions src/unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ export interface Unit<TQuantityName> {
readonly unitInfo: UnitInfo<TQuantityName>;
}

export type UnitLookup = (unitString: string) => Unit<unknown> | undefined;

export type UnitMap = {
readonly [key: string]: Unit<unknown>;
};

/**
* This record represents a determinate quantity (as of length, time, heat, or value)
* adopted as a standard of measurement.
Expand Down

0 comments on commit cc33332

Please sign in to comment.