@accelint/geo 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +233 -1
- package/catalog-info.yaml +1 -1
- package/dist/cartesian.d.ts +2 -0
- package/dist/cartesian.js +2 -0
- package/dist/cartesian.js.map +1 -1
- package/dist/coordinates/coordinate.d.ts +41 -7
- package/dist/coordinates/coordinate.js +102 -12
- package/dist/coordinates/coordinate.js.map +1 -1
- package/dist/coordinates/latlon/decimal-degrees/formatter.d.ts +20 -0
- package/dist/coordinates/latlon/decimal-degrees/formatter.js +38 -0
- package/dist/coordinates/latlon/decimal-degrees/formatter.js.map +1 -1
- package/dist/coordinates/latlon/decimal-degrees/parser.d.ts +68 -2
- package/dist/coordinates/latlon/decimal-degrees/parser.js +66 -5
- package/dist/coordinates/latlon/decimal-degrees/parser.js.map +1 -1
- package/dist/coordinates/latlon/decimal-degrees/system.d.ts +32 -0
- package/dist/coordinates/latlon/decimal-degrees/system.js +31 -0
- package/dist/coordinates/latlon/decimal-degrees/system.js.map +1 -1
- package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.d.ts +20 -0
- package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.js +37 -0
- package/dist/coordinates/latlon/degrees-decimal-minutes/formatter.js.map +1 -1
- package/dist/coordinates/latlon/degrees-decimal-minutes/parser.d.ts +72 -2
- package/dist/coordinates/latlon/degrees-decimal-minutes/parser.js +66 -3
- package/dist/coordinates/latlon/degrees-decimal-minutes/parser.js.map +1 -1
- package/dist/coordinates/latlon/degrees-decimal-minutes/system.d.ts +32 -0
- package/dist/coordinates/latlon/degrees-decimal-minutes/system.js +31 -0
- package/dist/coordinates/latlon/degrees-decimal-minutes/system.js.map +1 -1
- package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.d.ts +20 -0
- package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.js +37 -0
- package/dist/coordinates/latlon/degrees-minutes-seconds/formatter.js.map +1 -1
- package/dist/coordinates/latlon/degrees-minutes-seconds/parser.d.ts +74 -2
- package/dist/coordinates/latlon/degrees-minutes-seconds/parser.js +66 -3
- package/dist/coordinates/latlon/degrees-minutes-seconds/parser.js.map +1 -1
- package/dist/coordinates/latlon/degrees-minutes-seconds/system.d.ts +32 -0
- package/dist/coordinates/latlon/degrees-minutes-seconds/system.js +31 -0
- package/dist/coordinates/latlon/degrees-minutes-seconds/system.js.map +1 -1
- package/dist/coordinates/latlon/internal/coordinate-system.d.ts +22 -0
- package/dist/coordinates/latlon/internal/create-cache.d.ts +17 -1
- package/dist/coordinates/latlon/internal/create-cache.js +19 -3
- package/dist/coordinates/latlon/internal/create-cache.js.map +1 -1
- package/dist/coordinates/latlon/internal/exhaustive-errors.d.ts +15 -0
- package/dist/coordinates/latlon/internal/exhaustive-errors.js +28 -0
- package/dist/coordinates/latlon/internal/exhaustive-errors.js.map +1 -1
- package/dist/coordinates/latlon/internal/format.d.ts +20 -0
- package/dist/coordinates/latlon/internal/format.js +20 -0
- package/dist/coordinates/latlon/internal/format.js.map +1 -1
- package/dist/coordinates/latlon/internal/in-range.d.ts +23 -0
- package/dist/coordinates/latlon/internal/in-range.js +24 -0
- package/dist/coordinates/latlon/internal/in-range.js.map +1 -1
- package/dist/coordinates/latlon/internal/index.d.ts +16 -1
- package/dist/coordinates/latlon/internal/index.js +25 -1
- package/dist/coordinates/latlon/internal/index.js.map +1 -1
- package/dist/coordinates/latlon/internal/lexer.d.ts +2 -0
- package/dist/coordinates/latlon/internal/lexer.js +26 -0
- package/dist/coordinates/latlon/internal/lexer.js.map +1 -1
- package/dist/coordinates/latlon/internal/normalize.d.ts +67 -0
- package/dist/coordinates/latlon/internal/normalize.js +87 -0
- package/dist/coordinates/latlon/internal/normalize.js.map +1 -0
- package/dist/coordinates/latlon/internal/ordinal.d.ts +25 -0
- package/dist/coordinates/latlon/internal/ordinal.js +25 -0
- package/dist/coordinates/latlon/internal/ordinal.js.map +1 -1
- package/dist/coordinates/latlon/internal/parse-format.d.ts +22 -0
- package/dist/coordinates/latlon/internal/parse-format.js +43 -1
- package/dist/coordinates/latlon/internal/parse-format.js.map +1 -1
- package/dist/coordinates/latlon/internal/parse.d.ts +2 -0
- package/dist/coordinates/latlon/internal/parse.js +4 -1
- package/dist/coordinates/latlon/internal/parse.js.map +1 -1
- package/dist/coordinates/latlon/internal/pipes/check-ambiguous.d.ts +17 -0
- package/dist/coordinates/latlon/internal/pipes/check-ambiguous.js +16 -0
- package/dist/coordinates/latlon/internal/pipes/check-ambiguous.js.map +1 -1
- package/dist/coordinates/latlon/internal/pipes/check-numbers.d.ts +25 -0
- package/dist/coordinates/latlon/internal/pipes/check-numbers.js +33 -0
- package/dist/coordinates/latlon/internal/pipes/check-numbers.js.map +1 -1
- package/dist/coordinates/latlon/internal/pipes/fix-bearings.d.ts +17 -0
- package/dist/coordinates/latlon/internal/pipes/fix-bearings.js +31 -0
- package/dist/coordinates/latlon/internal/pipes/fix-bearings.js.map +1 -1
- package/dist/coordinates/latlon/internal/pipes/fix-dividers.d.ts +17 -0
- package/dist/coordinates/latlon/internal/pipes/fix-dividers.js +29 -0
- package/dist/coordinates/latlon/internal/pipes/fix-dividers.js.map +1 -1
- package/dist/coordinates/latlon/internal/pipes/genome.d.ts +16 -0
- package/dist/coordinates/latlon/internal/pipes/genome.js +41 -0
- package/dist/coordinates/latlon/internal/pipes/genome.js.map +1 -1
- package/dist/coordinates/latlon/internal/pipes/index.d.ts +32 -2
- package/dist/coordinates/latlon/internal/pipes/index.js +57 -4
- package/dist/coordinates/latlon/internal/pipes/index.js.map +1 -1
- package/dist/coordinates/latlon/internal/pipes/simpler.d.ts +16 -3
- package/dist/coordinates/latlon/internal/pipes/simpler.js +15 -3
- package/dist/coordinates/latlon/internal/pipes/simpler.js.map +1 -1
- package/dist/coordinates/latlon/internal/validate.d.ts +75 -0
- package/dist/coordinates/latlon/internal/validate.js +105 -0
- package/dist/coordinates/latlon/internal/validate.js.map +1 -0
- package/dist/coordinates/latlon/internal/violation.d.ts +18 -0
- package/dist/coordinates/latlon/internal/violation.js +18 -0
- package/dist/coordinates/latlon/internal/violation.js.map +1 -1
- package/dist/coordinates/mgrs/parser.d.ts +24 -0
- package/dist/coordinates/mgrs/parser.js +56 -0
- package/dist/coordinates/mgrs/parser.js.map +1 -1
- package/dist/coordinates/mgrs/system.d.ts +31 -0
- package/dist/coordinates/mgrs/system.js +30 -0
- package/dist/coordinates/mgrs/system.js.map +1 -1
- package/dist/coordinates/utm/parser.d.ts +24 -0
- package/dist/coordinates/utm/parser.js +56 -0
- package/dist/coordinates/utm/parser.js.map +1 -1
- package/dist/coordinates/utm/system.d.ts +21 -0
- package/dist/coordinates/utm/system.js +20 -0
- package/dist/coordinates/utm/system.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/patterning.d.ts +12 -2
- package/dist/patterning.js +12 -2
- package/dist/patterning.js.map +1 -1
- package/package.json +3 -1
|
@@ -19,6 +19,16 @@ const GENOME_PATTERN = /^(B?)([DN]?[MN]?[SN]?)(B?)(?:B?)([DN]?[MN]?[SN]?)(?:B?)$
|
|
|
19
19
|
* Get the position (index) of where to insert a divider into the token list;
|
|
20
20
|
* basically, the count of numeric components (left-of-divider position) plus
|
|
21
21
|
* 1 if there is a bearing identifier (left-of-divider).
|
|
22
|
+
*
|
|
23
|
+
* @param _full - Full regex match string (unused).
|
|
24
|
+
* @param args - Regex capture groups: [bearing1, number1, bearing2, number2].
|
|
25
|
+
* @returns String representation of the divider index position.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* dividerIndexer('BDNBDNB', 'B', 'DN', 'B', 'DN');
|
|
30
|
+
* // '3' (bearing + 2 numeric components)
|
|
31
|
+
* ```
|
|
22
32
|
*/
|
|
23
33
|
function dividerIndexer(_full, ...args) {
|
|
24
34
|
const [bearing1 = "", number1, bearing2 = "", number2] = args;
|
|
@@ -34,6 +44,22 @@ function dividerIndexer(_full, ...args) {
|
|
|
34
44
|
* - S = seconds (number with seconds character following)
|
|
35
45
|
* - N = number (no identifying character following)
|
|
36
46
|
* - X = for unmatched token types
|
|
47
|
+
*
|
|
48
|
+
* @param acc - Accumulated genome sequence string.
|
|
49
|
+
* @param t - Current token to classify.
|
|
50
|
+
* @returns Updated genome sequence with new character appended.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* genomeSequencer('', '45°');
|
|
55
|
+
* // 'D'
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* genomeSequencer('D', 'N');
|
|
61
|
+
* // 'DB'
|
|
62
|
+
* ```
|
|
37
63
|
*/
|
|
38
64
|
function genomeSequencer(acc, t) {
|
|
39
65
|
if (t.includes(SYMBOLS.DEGREES)) return `${acc}D`;
|
|
@@ -46,6 +72,21 @@ function genomeSequencer(acc, t) {
|
|
|
46
72
|
/**
|
|
47
73
|
* Use the "genome" sequence of the token list to find the index for inserting
|
|
48
74
|
* a missing divider token.
|
|
75
|
+
*
|
|
76
|
+
* @param tokens - Array of coordinate tokens to analyze.
|
|
77
|
+
* @returns Index position where divider should be inserted, or 0 if pattern doesn't match.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* getGenomeIndex(['45°', '30'', 'N', '122°', '15'', 'W']);
|
|
82
|
+
* // 3 (insert divider after latitude components)
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* getGenomeIndex(['45', '30', '15']);
|
|
88
|
+
* // 0 (pattern doesn't match genome sequence)
|
|
89
|
+
* ```
|
|
49
90
|
*/
|
|
50
91
|
function getGenomeIndex(tokens) {
|
|
51
92
|
const seq = tokens.reduce(genomeSequencer, "");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"genome.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/genome.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { SYMBOL_PATTERNS, SYMBOLS } from '..';\nimport type { Tokens } from '../lexer';\n\nconst GENOME_PATTERN =\n /^(B?)([DN]?[MN]?[SN]?)(B?)(?:B?)([DN]?[MN]?[SN]?)(?:B?)$/;\n\n/**\n * Get the position (index) of where to insert a divider into the token list;\n * basically, the count of numeric components (left-of-divider position) plus\n * 1 if there is a bearing identifier (left-of-divider).\n */\nfunction dividerIndexer(_full: string, ...args: string[]) {\n const [bearing1 = '', number1, bearing2 = '', number2] = args;\n\n // if no numeric values exist there no way to infer a location to insert a divider\n if (!(number1?.length && number2?.length)) {\n return '0';\n }\n\n return `${number1.length + (bearing1.length || bearing2.length)}`;\n}\n\n/**\n * The genome sequence is a simplification of the tokens list:\n *\n * - B = bearings (NSEW)\n * - D = degrees (number with degree character following)\n * - M = minutes (number with minutes character following)\n * - S = seconds (number with seconds character following)\n * - N = number (no identifying character following)\n * - X = for unmatched token types\n */\nfunction genomeSequencer(acc: string, t: string) {\n if (t.includes(SYMBOLS.DEGREES)) {\n return `${acc}D`;\n }\n\n if (t.includes(SYMBOLS.MINUTES)) {\n return `${acc}M`;\n }\n\n if (t.includes(SYMBOLS.SECONDS)) {\n return `${acc}S`;\n }\n\n if (SYMBOL_PATTERNS.NSEW.test(t)) {\n return `${acc}B`;\n }\n\n if (/\\d/.test(t)) {\n return `${acc}N`;\n }\n\n return `${acc}X`;\n}\n\n/**\n * Use the \"genome\" sequence of the token list to find the index for inserting\n * a missing divider token.\n */\nexport function getGenomeIndex(tokens: Tokens) {\n const seq = tokens.reduce(genomeSequencer, '');\n\n return GENOME_PATTERN.test(seq)\n ? Number.parseInt(seq.replace(GENOME_PATTERN, dividerIndexer), 10)\n : 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAM,iBACJ
|
|
1
|
+
{"version":3,"file":"genome.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/genome.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { SYMBOL_PATTERNS, SYMBOLS } from '..';\nimport type { Tokens } from '../lexer';\n\nconst GENOME_PATTERN =\n /^(B?)([DN]?[MN]?[SN]?)(B?)(?:B?)([DN]?[MN]?[SN]?)(?:B?)$/;\n\n/**\n * Get the position (index) of where to insert a divider into the token list;\n * basically, the count of numeric components (left-of-divider position) plus\n * 1 if there is a bearing identifier (left-of-divider).\n *\n * @param _full - Full regex match string (unused).\n * @param args - Regex capture groups: [bearing1, number1, bearing2, number2].\n * @returns String representation of the divider index position.\n *\n * @example\n * ```typescript\n * dividerIndexer('BDNBDNB', 'B', 'DN', 'B', 'DN');\n * // '3' (bearing + 2 numeric components)\n * ```\n */\nfunction dividerIndexer(_full: string, ...args: string[]) {\n const [bearing1 = '', number1, bearing2 = '', number2] = args;\n\n // if no numeric values exist there no way to infer a location to insert a divider\n if (!(number1?.length && number2?.length)) {\n return '0';\n }\n\n return `${number1.length + (bearing1.length || bearing2.length)}`;\n}\n\n/**\n * The genome sequence is a simplification of the tokens list:\n *\n * - B = bearings (NSEW)\n * - D = degrees (number with degree character following)\n * - M = minutes (number with minutes character following)\n * - S = seconds (number with seconds character following)\n * - N = number (no identifying character following)\n * - X = for unmatched token types\n *\n * @param acc - Accumulated genome sequence string.\n * @param t - Current token to classify.\n * @returns Updated genome sequence with new character appended.\n *\n * @example\n * ```typescript\n * genomeSequencer('', '45°');\n * // 'D'\n * ```\n *\n * @example\n * ```typescript\n * genomeSequencer('D', 'N');\n * // 'DB'\n * ```\n */\nfunction genomeSequencer(acc: string, t: string) {\n if (t.includes(SYMBOLS.DEGREES)) {\n return `${acc}D`;\n }\n\n if (t.includes(SYMBOLS.MINUTES)) {\n return `${acc}M`;\n }\n\n if (t.includes(SYMBOLS.SECONDS)) {\n return `${acc}S`;\n }\n\n if (SYMBOL_PATTERNS.NSEW.test(t)) {\n return `${acc}B`;\n }\n\n if (/\\d/.test(t)) {\n return `${acc}N`;\n }\n\n return `${acc}X`;\n}\n\n/**\n * Use the \"genome\" sequence of the token list to find the index for inserting\n * a missing divider token.\n *\n * @param tokens - Array of coordinate tokens to analyze.\n * @returns Index position where divider should be inserted, or 0 if pattern doesn't match.\n *\n * @example\n * ```typescript\n * getGenomeIndex(['45°', '30'', 'N', '122°', '15'', 'W']);\n * // 3 (insert divider after latitude components)\n * ```\n *\n * @example\n * ```typescript\n * getGenomeIndex(['45', '30', '15']);\n * // 0 (pattern doesn't match genome sequence)\n * ```\n */\nexport function getGenomeIndex(tokens: Tokens) {\n const seq = tokens.reduce(genomeSequencer, '');\n\n return GENOME_PATTERN.test(seq)\n ? Number.parseInt(seq.replace(GENOME_PATTERN, dividerIndexer), 10)\n : 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAM,iBACJ;;;;;;;;;;;;;;;;AAiBF,SAAS,eAAe,OAAe,GAAG,MAAgB;CACxD,MAAM,CAAC,WAAW,IAAI,SAAS,WAAW,IAAI,WAAW;AAGzD,KAAI,EAAE,SAAS,UAAU,SAAS,QAChC,QAAO;AAGT,QAAO,GAAG,QAAQ,UAAU,SAAS,UAAU,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6B1D,SAAS,gBAAgB,KAAa,GAAW;AAC/C,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,EAAE,SAAS,QAAQ,QAAQ,CAC7B,QAAO,GAAG,IAAI;AAGhB,KAAI,gBAAgB,KAAK,KAAK,EAAE,CAC9B,QAAO,GAAG,IAAI;AAGhB,KAAI,KAAK,KAAK,EAAE,CACd,QAAO,GAAG,IAAI;AAGhB,QAAO,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;;AAsBhB,SAAgB,eAAe,QAAgB;CAC7C,MAAM,MAAM,OAAO,OAAO,iBAAiB,GAAG;AAE9C,QAAO,eAAe,KAAK,IAAI,GAC3B,OAAO,SAAS,IAAI,QAAQ,gBAAgB,eAAe,EAAE,GAAG,GAChE"}
|
|
@@ -20,7 +20,21 @@ type PipeResult = ReturnType<Pipe>;
|
|
|
20
20
|
* Consistently create a PipesResult array to return. Use this instead of
|
|
21
21
|
* casting to PipesResult everywhere.
|
|
22
22
|
*
|
|
23
|
-
* @param
|
|
23
|
+
* @param t - Array of coordinate tokens.
|
|
24
|
+
* @param e - Error status: true = has error, false = no error, or error message string.
|
|
25
|
+
* @returns Pipe result tuple with tokens (empty if error) and error status.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* pipesResult(['45', 'N', '/', '122', 'W'], false);
|
|
30
|
+
* // [['45', 'N', '/', '122', 'W'], false]
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* pipesResult(['45'], 'Too few numbers.');
|
|
36
|
+
* // [[], 'Too few numbers.']
|
|
37
|
+
* ```
|
|
24
38
|
*
|
|
25
39
|
* @remarks
|
|
26
40
|
* pure function
|
|
@@ -30,7 +44,23 @@ declare const pipesResult: (t: Tokens, e: boolean | string) => PipeResult;
|
|
|
30
44
|
* Run the tokens through a preset pipeline of violations checks exiting the
|
|
31
45
|
* process as early as possible when violations are found because violations
|
|
32
46
|
* will make further violations checks less accurate and could return inaccurate
|
|
33
|
-
* violations that could be misleading or hide the most important violation
|
|
47
|
+
* violations that could be misleading or hide the most important violation.
|
|
48
|
+
*
|
|
49
|
+
* @param tokens - Array of parsed coordinate tokens to validate and normalize.
|
|
50
|
+
* @param format - Optional coordinate format (LATLON or LONLAT) for inference.
|
|
51
|
+
* @returns Tuple of [processed tokens, array of error messages].
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* pipesRunner(['45', 'N', '/', '122', 'W'], 'LATLON');
|
|
56
|
+
* // [['45', 'N', '/', '122', 'W'], []]
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* pipesRunner(['45'], 'LATLON');
|
|
62
|
+
* // [[], ['Too few numbers.']]
|
|
63
|
+
* ```
|
|
34
64
|
*/
|
|
35
65
|
declare function pipesRunner(tokens: Tokens, format?: Format): [Tokens, string[]];
|
|
36
66
|
//#endregion
|
|
@@ -18,19 +18,56 @@ import { fixBearings } from "./fix-bearings.js";
|
|
|
18
18
|
import { fixDivider } from "./fix-dividers.js";
|
|
19
19
|
|
|
20
20
|
//#region src/coordinates/latlon/internal/pipes/index.ts
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Make a RegExp global.
|
|
23
|
+
*
|
|
24
|
+
* @param k - Key of the SYMBOL_PATTERNS object.
|
|
25
|
+
* @returns New global RegExp based on the pattern.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* makeGlobal('NSEW');
|
|
30
|
+
* // /[NSEW]/g
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
22
33
|
const makeGlobal = (k) => new RegExp(SYMBOL_PATTERNS[k], "g");
|
|
23
34
|
/**
|
|
24
35
|
* Consistently create a PipesResult array to return. Use this instead of
|
|
25
36
|
* casting to PipesResult everywhere.
|
|
26
37
|
*
|
|
27
|
-
* @param
|
|
38
|
+
* @param t - Array of coordinate tokens.
|
|
39
|
+
* @param e - Error status: true = has error, false = no error, or error message string.
|
|
40
|
+
* @returns Pipe result tuple with tokens (empty if error) and error status.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* pipesResult(['45', 'N', '/', '122', 'W'], false);
|
|
45
|
+
* // [['45', 'N', '/', '122', 'W'], false]
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* pipesResult(['45'], 'Too few numbers.');
|
|
51
|
+
* // [[], 'Too few numbers.']
|
|
52
|
+
* ```
|
|
28
53
|
*
|
|
29
54
|
* @remarks
|
|
30
55
|
* pure function
|
|
31
56
|
*/
|
|
32
57
|
const pipesResult = (t, e) => [e ? [] : t, e];
|
|
33
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Check if there are more than 2 of something.
|
|
60
|
+
*
|
|
61
|
+
* @param p - Regular expression pattern to match.
|
|
62
|
+
* @returns Function that takes tokens and returns pipe result with error if >2 matches found.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const checkBearings = tooMany(/[NSEW]/g);
|
|
67
|
+
* checkBearings(['N', 'S', 'E', 'W']);
|
|
68
|
+
* // Returns error=true (more than 2 bearings)
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
34
71
|
const tooMany = (p) => (t) => pipesResult(t, (t.join("").match(p) ?? []).length > 2);
|
|
35
72
|
const pipes = [
|
|
36
73
|
["Too many bearings.", tooMany(makeGlobal("NSEW"))],
|
|
@@ -47,7 +84,23 @@ const pipes = [
|
|
|
47
84
|
* Run the tokens through a preset pipeline of violations checks exiting the
|
|
48
85
|
* process as early as possible when violations are found because violations
|
|
49
86
|
* will make further violations checks less accurate and could return inaccurate
|
|
50
|
-
* violations that could be misleading or hide the most important violation
|
|
87
|
+
* violations that could be misleading or hide the most important violation.
|
|
88
|
+
*
|
|
89
|
+
* @param tokens - Array of parsed coordinate tokens to validate and normalize.
|
|
90
|
+
* @param format - Optional coordinate format (LATLON or LONLAT) for inference.
|
|
91
|
+
* @returns Tuple of [processed tokens, array of error messages].
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* pipesRunner(['45', 'N', '/', '122', 'W'], 'LATLON');
|
|
96
|
+
* // [['45', 'N', '/', '122', 'W'], []]
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* pipesRunner(['45'], 'LATLON');
|
|
102
|
+
* // [[], ['Too few numbers.']]
|
|
103
|
+
* ```
|
|
51
104
|
*/
|
|
52
105
|
function pipesRunner(tokens, format) {
|
|
53
106
|
let copy = tokens.slice(0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["pipes: [string, Pipe][]","error: PipeResult[1]"],"sources":["../../../../../src/coordinates/latlon/internal/pipes/index.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { type Format, SYMBOL_PATTERNS } from '..';\nimport { checkAmbiguousGrouping } from './check-ambiguous';\nimport { checkNumberValues } from './check-numbers';\nimport { fixBearings } from './fix-bearings';\nimport { fixDivider } from './fix-dividers';\nimport type { Tokens } from '../lexer';\n\ntype Pipe = (t: Tokens, f?: Format) => [Tokens, boolean | string];\n\nexport type PipeResult = ReturnType<Pipe>;\n\n
|
|
1
|
+
{"version":3,"file":"index.js","names":["pipes: [string, Pipe][]","error: PipeResult[1]"],"sources":["../../../../../src/coordinates/latlon/internal/pipes/index.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { type Format, SYMBOL_PATTERNS } from '..';\nimport { checkAmbiguousGrouping } from './check-ambiguous';\nimport { checkNumberValues } from './check-numbers';\nimport { fixBearings } from './fix-bearings';\nimport { fixDivider } from './fix-dividers';\nimport type { Tokens } from '../lexer';\n\ntype Pipe = (t: Tokens, f?: Format) => [Tokens, boolean | string];\n\nexport type PipeResult = ReturnType<Pipe>;\n\n/**\n * Make a RegExp global.\n *\n * @param k - Key of the SYMBOL_PATTERNS object.\n * @returns New global RegExp based on the pattern.\n *\n * @example\n * ```typescript\n * makeGlobal('NSEW');\n * // /[NSEW]/g\n * ```\n */\nconst makeGlobal = (k: keyof typeof SYMBOL_PATTERNS) =>\n new RegExp(SYMBOL_PATTERNS[k], 'g');\n\n/**\n * Consistently create a PipesResult array to return. Use this instead of\n * casting to PipesResult everywhere.\n *\n * @param t - Array of coordinate tokens.\n * @param e - Error status: true = has error, false = no error, or error message string.\n * @returns Pipe result tuple with tokens (empty if error) and error status.\n *\n * @example\n * ```typescript\n * pipesResult(['45', 'N', '/', '122', 'W'], false);\n * // [['45', 'N', '/', '122', 'W'], false]\n * ```\n *\n * @example\n * ```typescript\n * pipesResult(['45'], 'Too few numbers.');\n * // [[], 'Too few numbers.']\n * ```\n *\n * @remarks\n * pure function\n */\nexport const pipesResult = (t: Tokens, e: boolean | string): PipeResult => [\n // if there are errors do NOT return the tokens\n e ? [] : t,\n e,\n];\n\n/**\n * Check if there are more than 2 of something.\n *\n * @param p - Regular expression pattern to match.\n * @returns Function that takes tokens and returns pipe result with error if >2 matches found.\n *\n * @example\n * ```typescript\n * const checkBearings = tooMany(/[NSEW]/g);\n * checkBearings(['N', 'S', 'E', 'W']);\n * // Returns error=true (more than 2 bearings)\n * ```\n */\nconst tooMany = (p: RegExp) => (t: Tokens) =>\n pipesResult(t, (t.join('').match(p) ?? []).length > 2);\n\nconst pipes: [string, Pipe][] = [\n // Unrecoverable violations\n ['Too many bearings.', tooMany(makeGlobal('NSEW'))],\n ['Too many numeric signs.', tooMany(/[-+]/g)],\n ['Too many degrees indicators.', tooMany(makeGlobal('DEGREES'))],\n ['Too many minutes indicators.', tooMany(makeGlobal('MINUTES'))],\n ['Too many seconds indicators.', tooMany(makeGlobal('SECONDS'))],\n ['Number values checks.', checkNumberValues],\n ['Ambiguous grouping of numbers with no divider.', checkAmbiguousGrouping],\n\n // fix values and formatting to be consistent\n ['Unable to identify latitude from longitude.', fixDivider],\n ['Unable to identify bearings.', fixBearings],\n];\n\n/**\n * Run the tokens through a preset pipeline of violations checks exiting the\n * process as early as possible when violations are found because violations\n * will make further violations checks less accurate and could return inaccurate\n * violations that could be misleading or hide the most important violation.\n *\n * @param tokens - Array of parsed coordinate tokens to validate and normalize.\n * @param format - Optional coordinate format (LATLON or LONLAT) for inference.\n * @returns Tuple of [processed tokens, array of error messages].\n *\n * @example\n * ```typescript\n * pipesRunner(['45', 'N', '/', '122', 'W'], 'LATLON');\n * // [['45', 'N', '/', '122', 'W'], []]\n * ```\n *\n * @example\n * ```typescript\n * pipesRunner(['45'], 'LATLON');\n * // [[], ['Too few numbers.']]\n * ```\n */\nexport function pipesRunner(\n tokens: Tokens,\n format?: Format,\n): [Tokens, string[]] {\n let copy = tokens.slice(0);\n let error: PipeResult[1] = false;\n const errors = [] as string[];\n\n for (const [message, op] of pipes) {\n [copy, error] = op(copy, format);\n\n if (error) {\n // accumulate the \"errors\" because if tokens are returned\n // the errors are only warnings and are recoverable\n errors.push(error === true ? message : error);\n\n if (!copy.length) {\n return [copy, [error === true ? message : error]];\n }\n }\n }\n\n return [copy, errors];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAM,cAAc,MAClB,IAAI,OAAO,gBAAgB,IAAI,IAAI;;;;;;;;;;;;;;;;;;;;;;;;AAyBrC,MAAa,eAAe,GAAW,MAAoC,CAEzE,IAAI,EAAE,GAAG,GACT,EACD;;;;;;;;;;;;;;AAeD,MAAM,WAAW,OAAe,MAC9B,YAAY,IAAI,EAAE,KAAK,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE;AAExD,MAAMA,QAA0B;CAE9B,CAAC,sBAAsB,QAAQ,WAAW,OAAO,CAAC,CAAC;CACnD,CAAC,2BAA2B,QAAQ,QAAQ,CAAC;CAC7C,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,gCAAgC,QAAQ,WAAW,UAAU,CAAC,CAAC;CAChE,CAAC,yBAAyB,kBAAkB;CAC5C,CAAC,kDAAkD,uBAAuB;CAG1E,CAAC,+CAA+C,WAAW;CAC3D,CAAC,gCAAgC,YAAY;CAC9C;;;;;;;;;;;;;;;;;;;;;;;AAwBD,SAAgB,YACd,QACA,QACoB;CACpB,IAAI,OAAO,OAAO,MAAM,EAAE;CAC1B,IAAIC,QAAuB;CAC3B,MAAM,SAAS,EAAE;AAEjB,MAAK,MAAM,CAAC,SAAS,OAAO,OAAO;AACjC,GAAC,MAAM,SAAS,GAAG,MAAM,OAAO;AAEhC,MAAI,OAAO;AAGT,UAAO,KAAK,UAAU,OAAO,UAAU,MAAM;AAE7C,OAAI,CAAC,KAAK,OACR,QAAO,CAAC,MAAM,CAAC,UAAU,OAAO,UAAU,MAAM,CAAC;;;AAKvD,QAAO,CAAC,MAAM,OAAO"}
|
|
@@ -13,15 +13,28 @@
|
|
|
13
13
|
import { Tokens } from "../lexer.js";
|
|
14
14
|
|
|
15
15
|
//#region src/coordinates/latlon/internal/pipes/simpler.d.ts
|
|
16
|
+
|
|
16
17
|
/**
|
|
17
18
|
* Create a simplified pattern string - numbers = 'N', bearings = 'B' - to
|
|
18
19
|
* allow for simpler pattern matching.
|
|
19
20
|
*
|
|
20
|
-
* @
|
|
21
|
-
*
|
|
21
|
+
* @param tokens - Array of coordinate tokens to simplify.
|
|
22
|
+
* @returns Simplified pattern string where 'N' = number and 'B' = bearing.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* simpler(['45', '30', 'N', '/', '122', '15', 'W']);
|
|
27
|
+
* // 'NNBNNNB'
|
|
28
|
+
* ```
|
|
22
29
|
*
|
|
23
30
|
* @example
|
|
24
|
-
*
|
|
31
|
+
* ```typescript
|
|
32
|
+
* simpler(['45', 'N']);
|
|
33
|
+
* // 'NB'
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* pure function
|
|
25
38
|
*/
|
|
26
39
|
declare const simpler: (tokens: Tokens) => string;
|
|
27
40
|
//#endregion
|
|
@@ -16,11 +16,23 @@
|
|
|
16
16
|
* Create a simplified pattern string - numbers = 'N', bearings = 'B' - to
|
|
17
17
|
* allow for simpler pattern matching.
|
|
18
18
|
*
|
|
19
|
-
* @
|
|
20
|
-
*
|
|
19
|
+
* @param tokens - Array of coordinate tokens to simplify.
|
|
20
|
+
* @returns Simplified pattern string where 'N' = number and 'B' = bearing.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* simpler(['45', '30', 'N', '/', '122', '15', 'W']);
|
|
25
|
+
* // 'NNBNNNB'
|
|
26
|
+
* ```
|
|
21
27
|
*
|
|
22
28
|
* @example
|
|
23
|
-
*
|
|
29
|
+
* ```typescript
|
|
30
|
+
* simpler(['45', 'N']);
|
|
31
|
+
* // 'NB'
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @remarks
|
|
35
|
+
* pure function
|
|
24
36
|
*/
|
|
25
37
|
const simpler = (tokens) => tokens.map((t) => /\d/.test(t) ? "N" : "B").join("");
|
|
26
38
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simpler.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/simpler.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport type { Tokens } from '../lexer';\n\n/**\n * Create a simplified pattern string - numbers = 'N', bearings = 'B' - to\n * allow for simpler pattern matching.\n *\n * @
|
|
1
|
+
{"version":3,"file":"simpler.js","names":[],"sources":["../../../../../src/coordinates/latlon/internal/pipes/simpler.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport type { Tokens } from '../lexer';\n\n/**\n * Create a simplified pattern string - numbers = 'N', bearings = 'B' - to\n * allow for simpler pattern matching.\n *\n * @param tokens - Array of coordinate tokens to simplify.\n * @returns Simplified pattern string where 'N' = number and 'B' = bearing.\n *\n * @example\n * ```typescript\n * simpler(['45', '30', 'N', '/', '122', '15', 'W']);\n * // 'NNBNNNB'\n * ```\n *\n * @example\n * ```typescript\n * simpler(['45', 'N']);\n * // 'NB'\n * ```\n *\n * @remarks\n * pure function\n */\nexport const simpler = (tokens: Tokens) =>\n tokens.map((t) => (/\\d/.test(t) ? 'N' : 'B')).join('');\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAa,WAAW,WACtB,OAAO,KAAK,MAAO,KAAK,KAAK,EAAE,GAAG,MAAM,IAAK,CAAC,KAAK,GAAG"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//#region src/coordinates/latlon/internal/validate.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Checks if a value is a finite number (not NaN, not Infinity, not -Infinity).
|
|
4
|
+
*
|
|
5
|
+
* @param value - The numeric value to check
|
|
6
|
+
* @returns True if the value is a finite number, false otherwise
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* isFiniteNumber(42); // true
|
|
11
|
+
* isFiniteNumber(NaN); // false
|
|
12
|
+
* isFiniteNumber(Infinity); // false
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
declare function isFiniteNumber(value: number): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Validates that a value is within a signed range (-limit to +limit).
|
|
18
|
+
*
|
|
19
|
+
* @param label - The label for error messages (used as-is for range errors,
|
|
20
|
+
* lowercased for "Invalid" errors)
|
|
21
|
+
* @param value - The numeric value to validate
|
|
22
|
+
* @param limit - The absolute limit (validates -limit to +limit)
|
|
23
|
+
* @returns Error message string if validation fails, undefined if valid
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* validateSignedRange('Latitude', 45, 90);
|
|
28
|
+
* // => undefined
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* validateSignedRange('Latitude', 95, 90);
|
|
34
|
+
* // => '[ERROR] Latitude value (95) is outside valid range (-90 to 90).'
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* validateSignedRange('Longitude', NaN, 180);
|
|
40
|
+
* // => '[ERROR] Invalid longitude value (NaN); expected a finite number.'
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
declare function validateSignedRange(label: string, value: number, limit: number): string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Validates numeric latitude and longitude coordinate values.
|
|
46
|
+
*
|
|
47
|
+
* @param lat - The latitude value to validate (must be -90 to 90)
|
|
48
|
+
* @param lon - The longitude value to validate (must be -180 to 180)
|
|
49
|
+
* @returns Array of error message strings, empty if all validations pass
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* validateNumericCoordinate(45.5, -122.6);
|
|
54
|
+
* // => []
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* validateNumericCoordinate(91, -122.6);
|
|
60
|
+
* // => ['[ERROR] Latitude value (91) is outside valid range (-90 to 90).']
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* validateNumericCoordinate(NaN, 200);
|
|
66
|
+
* // => [
|
|
67
|
+
* // '[ERROR] Invalid latitude value (NaN); expected a finite number.',
|
|
68
|
+
* // '[ERROR] Longitude value (200) is outside valid range (-180 to 180).'
|
|
69
|
+
* // ]
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
declare function validateNumericCoordinate(lat: number, lon: number): string[];
|
|
73
|
+
//#endregion
|
|
74
|
+
export { isFiniteNumber, validateNumericCoordinate, validateSignedRange };
|
|
75
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at https://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
import { violation } from "./violation.js";
|
|
15
|
+
|
|
16
|
+
//#region src/coordinates/latlon/internal/validate.ts
|
|
17
|
+
const LAT_LIMIT = 90;
|
|
18
|
+
const LON_LIMIT = 180;
|
|
19
|
+
/**
|
|
20
|
+
* Checks if a value is a finite number (not NaN, not Infinity, not -Infinity).
|
|
21
|
+
*
|
|
22
|
+
* @param value - The numeric value to check
|
|
23
|
+
* @returns True if the value is a finite number, false otherwise
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* isFiniteNumber(42); // true
|
|
28
|
+
* isFiniteNumber(NaN); // false
|
|
29
|
+
* isFiniteNumber(Infinity); // false
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
function isFiniteNumber(value) {
|
|
33
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Validates that a value is within a signed range (-limit to +limit).
|
|
37
|
+
*
|
|
38
|
+
* @param label - The label for error messages (used as-is for range errors,
|
|
39
|
+
* lowercased for "Invalid" errors)
|
|
40
|
+
* @param value - The numeric value to validate
|
|
41
|
+
* @param limit - The absolute limit (validates -limit to +limit)
|
|
42
|
+
* @returns Error message string if validation fails, undefined if valid
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* validateSignedRange('Latitude', 45, 90);
|
|
47
|
+
* // => undefined
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* validateSignedRange('Latitude', 95, 90);
|
|
53
|
+
* // => '[ERROR] Latitude value (95) is outside valid range (-90 to 90).'
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* validateSignedRange('Longitude', NaN, 180);
|
|
59
|
+
* // => '[ERROR] Invalid longitude value (NaN); expected a finite number.'
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
function validateSignedRange(label, value, limit) {
|
|
63
|
+
if (!isFiniteNumber(value)) return violation(`Invalid ${label.toLowerCase()} value (${value}); expected a finite number.`);
|
|
64
|
+
if (value < -limit || value > limit) return violation(`${label} value (${value}) is outside valid range (-${limit} to ${limit}).`);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Validates numeric latitude and longitude coordinate values.
|
|
68
|
+
*
|
|
69
|
+
* @param lat - The latitude value to validate (must be -90 to 90)
|
|
70
|
+
* @param lon - The longitude value to validate (must be -180 to 180)
|
|
71
|
+
* @returns Array of error message strings, empty if all validations pass
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* validateNumericCoordinate(45.5, -122.6);
|
|
76
|
+
* // => []
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* validateNumericCoordinate(91, -122.6);
|
|
82
|
+
* // => ['[ERROR] Latitude value (91) is outside valid range (-90 to 90).']
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* validateNumericCoordinate(NaN, 200);
|
|
88
|
+
* // => [
|
|
89
|
+
* // '[ERROR] Invalid latitude value (NaN); expected a finite number.',
|
|
90
|
+
* // '[ERROR] Longitude value (200) is outside valid range (-180 to 180).'
|
|
91
|
+
* // ]
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
function validateNumericCoordinate(lat, lon) {
|
|
95
|
+
const errors = [];
|
|
96
|
+
const latError = validateSignedRange("Latitude", lat, LAT_LIMIT);
|
|
97
|
+
if (latError) errors.push(latError);
|
|
98
|
+
const lonError = validateSignedRange("Longitude", lon, LON_LIMIT);
|
|
99
|
+
if (lonError) errors.push(lonError);
|
|
100
|
+
return errors;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
//#endregion
|
|
104
|
+
export { isFiniteNumber, validateNumericCoordinate, validateSignedRange };
|
|
105
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","names":["errors: string[]"],"sources":["../../../../src/coordinates/latlon/internal/validate.ts"],"sourcesContent":["/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { violation } from './violation';\n\nconst LAT_LIMIT = 90;\nconst LON_LIMIT = 180;\n\n/**\n * Checks if a value is a finite number (not NaN, not Infinity, not -Infinity).\n *\n * @param value - The numeric value to check\n * @returns True if the value is a finite number, false otherwise\n *\n * @example\n * ```typescript\n * isFiniteNumber(42); // true\n * isFiniteNumber(NaN); // false\n * isFiniteNumber(Infinity); // false\n * ```\n */\nexport function isFiniteNumber(value: number): boolean {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\n/**\n * Validates that a value is within a signed range (-limit to +limit).\n *\n * @param label - The label for error messages (used as-is for range errors,\n * lowercased for \"Invalid\" errors)\n * @param value - The numeric value to validate\n * @param limit - The absolute limit (validates -limit to +limit)\n * @returns Error message string if validation fails, undefined if valid\n *\n * @example\n * ```typescript\n * validateSignedRange('Latitude', 45, 90);\n * // => undefined\n * ```\n *\n * @example\n * ```typescript\n * validateSignedRange('Latitude', 95, 90);\n * // => '[ERROR] Latitude value (95) is outside valid range (-90 to 90).'\n * ```\n *\n * @example\n * ```typescript\n * validateSignedRange('Longitude', NaN, 180);\n * // => '[ERROR] Invalid longitude value (NaN); expected a finite number.'\n * ```\n */\nexport function validateSignedRange(\n label: string,\n value: number,\n limit: number,\n): string | undefined {\n if (!isFiniteNumber(value)) {\n return violation(\n `Invalid ${label.toLowerCase()} value (${value}); expected a finite number.`,\n );\n }\n\n if (value < -limit || value > limit) {\n return violation(\n `${label} value (${value}) is outside valid range (-${limit} to ${limit}).`,\n );\n }\n}\n\n/**\n * Validates numeric latitude and longitude coordinate values.\n *\n * @param lat - The latitude value to validate (must be -90 to 90)\n * @param lon - The longitude value to validate (must be -180 to 180)\n * @returns Array of error message strings, empty if all validations pass\n *\n * @example\n * ```typescript\n * validateNumericCoordinate(45.5, -122.6);\n * // => []\n * ```\n *\n * @example\n * ```typescript\n * validateNumericCoordinate(91, -122.6);\n * // => ['[ERROR] Latitude value (91) is outside valid range (-90 to 90).']\n * ```\n *\n * @example\n * ```typescript\n * validateNumericCoordinate(NaN, 200);\n * // => [\n * // '[ERROR] Invalid latitude value (NaN); expected a finite number.',\n * // '[ERROR] Longitude value (200) is outside valid range (-180 to 180).'\n * // ]\n * ```\n */\nexport function validateNumericCoordinate(lat: number, lon: number): string[] {\n const errors: string[] = [];\n\n const latError = validateSignedRange('Latitude', lat, LAT_LIMIT);\n if (latError) {\n errors.push(latError);\n }\n\n const lonError = validateSignedRange('Longitude', lon, LON_LIMIT);\n if (lonError) {\n errors.push(lonError);\n }\n\n return errors;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAcA,MAAM,YAAY;AAClB,MAAM,YAAY;;;;;;;;;;;;;;AAelB,SAAgB,eAAe,OAAwB;AACrD,QAAO,OAAO,UAAU,YAAY,OAAO,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8B5D,SAAgB,oBACd,OACA,OACA,OACoB;AACpB,KAAI,CAAC,eAAe,MAAM,CACxB,QAAO,UACL,WAAW,MAAM,aAAa,CAAC,UAAU,MAAM,8BAChD;AAGH,KAAI,QAAQ,CAAC,SAAS,QAAQ,MAC5B,QAAO,UACL,GAAG,MAAM,UAAU,MAAM,6BAA6B,MAAM,MAAM,MAAM,IACzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCL,SAAgB,0BAA0B,KAAa,KAAuB;CAC5E,MAAMA,SAAmB,EAAE;CAE3B,MAAM,WAAW,oBAAoB,YAAY,KAAK,UAAU;AAChE,KAAI,SACF,QAAO,KAAK,SAAS;CAGvB,MAAM,WAAW,oBAAoB,aAAa,KAAK,UAAU;AACjE,KAAI,SACF,QAAO,KAAK,SAAS;AAGvB,QAAO"}
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
//#region src/coordinates/latlon/internal/violation.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Formats an error message with a standard [ERROR] prefix.
|
|
4
|
+
*
|
|
5
|
+
* @param s - The error message string to format.
|
|
6
|
+
* @returns Formatted error string with [ERROR] prefix.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* violation('Invalid coordinate value.');
|
|
11
|
+
* // '[ERROR] Invalid coordinate value.'
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* violation('Degrees value (91) exceeds max value (90).');
|
|
17
|
+
* // '[ERROR] Degrees value (91) exceeds max value (90).'
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
2
20
|
declare const violation: (s: string) => string;
|
|
3
21
|
//#endregion
|
|
4
22
|
export { violation };
|
|
@@ -12,6 +12,24 @@
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
//#region src/coordinates/latlon/internal/violation.ts
|
|
15
|
+
/**
|
|
16
|
+
* Formats an error message with a standard [ERROR] prefix.
|
|
17
|
+
*
|
|
18
|
+
* @param s - The error message string to format.
|
|
19
|
+
* @returns Formatted error string with [ERROR] prefix.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* violation('Invalid coordinate value.');
|
|
24
|
+
* // '[ERROR] Invalid coordinate value.'
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* violation('Degrees value (91) exceeds max value (90).');
|
|
30
|
+
* // '[ERROR] Degrees value (91) exceeds max value (90).'
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
15
33
|
const violation = (s) => `[ERROR] ${s}`;
|
|
16
34
|
|
|
17
35
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"violation.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/violation.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport const violation = (s: string) => `[ERROR] ${s}`;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"violation.js","names":[],"sources":["../../../../src/coordinates/latlon/internal/violation.ts"],"sourcesContent":["// __private-exports\n/*\n * Copyright 2024 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/**\n * Formats an error message with a standard [ERROR] prefix.\n *\n * @param s - The error message string to format.\n * @returns Formatted error string with [ERROR] prefix.\n *\n * @example\n * ```typescript\n * violation('Invalid coordinate value.');\n * // '[ERROR] Invalid coordinate value.'\n * ```\n *\n * @example\n * ```typescript\n * violation('Degrees value (91) exceeds max value (90).');\n * // '[ERROR] Degrees value (91) exceeds max value (90).'\n * ```\n */\nexport const violation = (s: string) => `[ERROR] ${s}`;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,aAAa,MAAc,WAAW"}
|
|
@@ -13,6 +13,30 @@
|
|
|
13
13
|
import { ParseResults } from "../latlon/internal/parse.js";
|
|
14
14
|
|
|
15
15
|
//#region src/coordinates/mgrs/parser.d.ts
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Parses a Military Grid Reference System (MGRS) coordinate string into latitude/longitude values.
|
|
19
|
+
*
|
|
20
|
+
* Converts MGRS coordinates to UTM, then to latitude/longitude decimal degrees. Returns
|
|
21
|
+
* detailed error messages for invalid MGRS formats including zone numbers, band letters,
|
|
22
|
+
* square identification, and numerical locations.
|
|
23
|
+
*
|
|
24
|
+
* @param _format - Format parameter (unused, MGRS has fixed format).
|
|
25
|
+
* @param input - The MGRS coordinate string to parse (e.g., '31U BF 12345 67890').
|
|
26
|
+
* @returns Parse results with coordinate values or detailed error messages.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* parseMGRS(null, '31U BF 12345 67890');
|
|
31
|
+
* // [[['48.123456', 'N'], ['11.234567', 'E']], []]
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* parseMGRS(null, 'invalid');
|
|
37
|
+
* // [[], ['Invalid UTM zone number found...']]
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
16
40
|
declare function parseMGRS(_format: any, input: string): ParseResults;
|
|
17
41
|
//#endregion
|
|
18
42
|
export { parseMGRS };
|