@accelint/geo 0.1.3 → 0.2.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.
Files changed (112) hide show
  1. package/README.md +3 -0
  2. package/dist/cartesian.d.ts +21 -0
  3. package/dist/cartesian.js +11 -0
  4. package/dist/cartesian.js.map +1 -0
  5. package/dist/coordinates/coordinate.d.ts +72 -0
  6. package/dist/coordinates/coordinate.js +87 -0
  7. package/dist/coordinates/coordinate.js.map +1 -0
  8. package/dist/coordinates/latlon/decimal-degrees/parser.d.ts +8 -0
  9. package/dist/coordinates/latlon/decimal-degrees/parser.js +77 -0
  10. package/dist/coordinates/latlon/decimal-degrees/parser.js.map +1 -0
  11. package/dist/coordinates/latlon/decimal-degrees/system.d.ts +8 -0
  12. package/dist/coordinates/latlon/decimal-degrees/system.js +21 -0
  13. package/dist/coordinates/latlon/decimal-degrees/system.js.map +1 -0
  14. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.d.ts +8 -0
  15. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.js +86 -0
  16. package/dist/coordinates/latlon/degrees-decimal-minutes/parser.js.map +1 -0
  17. package/dist/coordinates/latlon/degrees-decimal-minutes/system.d.ts +8 -0
  18. package/dist/coordinates/latlon/degrees-decimal-minutes/system.js +26 -0
  19. package/dist/coordinates/latlon/degrees-decimal-minutes/system.js.map +1 -0
  20. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.d.ts +8 -0
  21. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.js +85 -0
  22. package/dist/coordinates/latlon/degrees-minutes-seconds/parser.js.map +1 -0
  23. package/dist/coordinates/latlon/degrees-minutes-seconds/system.d.ts +8 -0
  24. package/dist/coordinates/latlon/degrees-minutes-seconds/system.js +28 -0
  25. package/dist/coordinates/latlon/degrees-minutes-seconds/system.js.map +1 -0
  26. package/dist/coordinates/latlon/internal/coordinate-system.d.ts +12 -0
  27. package/dist/coordinates/latlon/internal/coordinate-system.js +3 -0
  28. package/dist/coordinates/latlon/internal/coordinate-system.js.map +1 -0
  29. package/dist/coordinates/latlon/internal/create-cache.d.ts +12 -0
  30. package/dist/coordinates/latlon/internal/create-cache.js +15 -0
  31. package/dist/coordinates/latlon/internal/create-cache.js.map +1 -0
  32. package/dist/coordinates/latlon/internal/exhaustive-errors.d.ts +9 -0
  33. package/dist/coordinates/latlon/internal/exhaustive-errors.js +72 -0
  34. package/dist/coordinates/latlon/internal/exhaustive-errors.js.map +1 -0
  35. package/dist/coordinates/latlon/internal/in-range.d.ts +7 -0
  36. package/dist/coordinates/latlon/internal/in-range.js +14 -0
  37. package/dist/coordinates/latlon/internal/in-range.js.map +1 -0
  38. package/dist/coordinates/latlon/internal/index.d.ts +59 -0
  39. package/dist/coordinates/latlon/internal/index.js +117 -0
  40. package/dist/coordinates/latlon/internal/index.js.map +1 -0
  41. package/dist/coordinates/latlon/internal/lexer.d.ts +20 -0
  42. package/dist/coordinates/latlon/internal/lexer.js +46 -0
  43. package/dist/coordinates/latlon/internal/lexer.js.map +1 -0
  44. package/dist/coordinates/latlon/internal/parse-format.d.ts +15 -0
  45. package/dist/coordinates/latlon/internal/parse-format.js +63 -0
  46. package/dist/coordinates/latlon/internal/parse-format.js.map +1 -0
  47. package/dist/coordinates/latlon/internal/parse.d.ts +41 -0
  48. package/dist/coordinates/latlon/internal/parse.js +16 -0
  49. package/dist/coordinates/latlon/internal/parse.js.map +1 -0
  50. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.d.ts +10 -0
  51. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.js +23 -0
  52. package/dist/coordinates/latlon/internal/pipes/check-ambiguous.js.map +1 -0
  53. package/dist/coordinates/latlon/internal/pipes/check-numbers.d.ts +8 -0
  54. package/dist/coordinates/latlon/internal/pipes/check-numbers.js +35 -0
  55. package/dist/coordinates/latlon/internal/pipes/check-numbers.js.map +1 -0
  56. package/dist/coordinates/latlon/internal/pipes/fix-bearings.d.ts +12 -0
  57. package/dist/coordinates/latlon/internal/pipes/fix-bearings.js +68 -0
  58. package/dist/coordinates/latlon/internal/pipes/fix-bearings.js.map +1 -0
  59. package/dist/coordinates/latlon/internal/pipes/fix-dividers.d.ts +15 -0
  60. package/dist/coordinates/latlon/internal/pipes/fix-dividers.js +34 -0
  61. package/dist/coordinates/latlon/internal/pipes/fix-dividers.js.map +1 -0
  62. package/dist/coordinates/latlon/internal/pipes/genome.d.ts +9 -0
  63. package/dist/coordinates/latlon/internal/pipes/genome.js +37 -0
  64. package/dist/coordinates/latlon/internal/pipes/genome.js.map +1 -0
  65. package/dist/coordinates/latlon/internal/pipes/index.d.ts +24 -0
  66. package/dist/coordinates/latlon/internal/pipes/index.js +46 -0
  67. package/dist/coordinates/latlon/internal/pipes/index.js.map +1 -0
  68. package/dist/coordinates/latlon/internal/pipes/simpler.d.ts +15 -0
  69. package/dist/coordinates/latlon/internal/pipes/simpler.js +6 -0
  70. package/dist/coordinates/latlon/internal/pipes/simpler.js.map +1 -0
  71. package/dist/coordinates/latlon/internal/violation.d.ts +3 -0
  72. package/dist/coordinates/latlon/internal/violation.js +6 -0
  73. package/dist/coordinates/latlon/internal/violation.js.map +1 -0
  74. package/dist/coordinates/mgrs/parser.d.ts +7 -0
  75. package/dist/coordinates/mgrs/parser.js +45 -0
  76. package/dist/coordinates/mgrs/parser.js.map +1 -0
  77. package/dist/coordinates/mgrs/system.d.ts +8 -0
  78. package/dist/coordinates/mgrs/system.js +25 -0
  79. package/dist/coordinates/mgrs/system.js.map +1 -0
  80. package/dist/coordinates/utm/parser.d.ts +7 -0
  81. package/dist/coordinates/utm/parser.js +38 -0
  82. package/dist/coordinates/utm/parser.js.map +1 -0
  83. package/dist/coordinates/utm/system.d.ts +8 -0
  84. package/dist/coordinates/utm/system.js +25 -0
  85. package/dist/coordinates/utm/system.js.map +1 -0
  86. package/dist/index.d.ts +10 -2
  87. package/dist/index.js +6 -2
  88. package/dist/patterning.d.ts +63 -0
  89. package/dist/patterning.js +16 -0
  90. package/dist/patterning.js.map +1 -0
  91. package/package.json +15 -10
  92. package/dist/coordinates/__fixtures__/index.d.ts +0 -6
  93. package/dist/coordinates/__fixtures__/index.js +0 -39
  94. package/dist/coordinates/__fixtures__/index.js.map +0 -1
  95. package/dist/coordinates/configurations.d.ts +0 -8
  96. package/dist/coordinates/configurations.js +0 -15
  97. package/dist/coordinates/configurations.js.map +0 -1
  98. package/dist/coordinates/index.d.ts +0 -2
  99. package/dist/coordinates/index.js +0 -4
  100. package/dist/coordinates/index.js.map +0 -1
  101. package/dist/coordinates/match.d.ts +0 -35
  102. package/dist/coordinates/match.js +0 -23
  103. package/dist/coordinates/match.js.map +0 -1
  104. package/dist/coordinates/normalize.d.ts +0 -3
  105. package/dist/coordinates/normalize.js +0 -27
  106. package/dist/coordinates/normalize.js.map +0 -1
  107. package/dist/coordinates/regex.d.ts +0 -128
  108. package/dist/coordinates/regex.js +0 -10
  109. package/dist/coordinates/regex.js.map +0 -1
  110. package/dist/coordinates/utils.d.ts +0 -6
  111. package/dist/coordinates/utils.js +0 -28
  112. package/dist/coordinates/utils.js.map +0 -1
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @accelint/geo
2
+
3
+ ⚠️ Under Construction ⚠️
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Computes the Cartesian product of multiple arrays.
3
+ *
4
+ * @template T
5
+ * the type of elements in the input arrays.
6
+ * @param {...T[][]} all
7
+ * a variadic number of arrays to compute the Cartesian product of.
8
+ * @returns {T[][]}
9
+ * An array containing all possible combinations of elements from the input
10
+ * arrays, where each combination is represented as an array.
11
+ *
12
+ * @remarks
13
+ * pure function
14
+ *
15
+ * @example
16
+ * const result = cartesian([1, 2], ['a', 'b']);
17
+ * // result: [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]
18
+ */
19
+ declare function cartesian<T>(...all: T[][]): T[][];
20
+
21
+ export { cartesian };
@@ -0,0 +1,11 @@
1
+ // src/cartesian.ts
2
+ function cartesian(...all) {
3
+ return all.reduce(
4
+ (results, entries) => results.map((result) => entries.map((entry) => result.concat([entry]))).reduce((sub, res) => sub.concat(res), []),
5
+ [[]]
6
+ );
7
+ }
8
+
9
+ export { cartesian };
10
+ //# sourceMappingURL=cartesian.js.map
11
+ //# sourceMappingURL=cartesian.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cartesian.ts"],"names":[],"mappings":";AA+BO,SAAS,aAAgB,GAAmB,EAAA;AACjD,EAAA,OAAO,GAAI,CAAA,MAAA;AAAA,IACT,CAAC,OAAA,EAAS,OACR,KAAA,OAAA,CACG,GAAI,CAAA,CAAC,MAAW,KAAA,OAAA,CAAQ,GAAI,CAAA,CAAC,KAAU,KAAA,MAAA,CAAO,MAAO,CAAA,CAAC,KAAK,CAAC,CAAC,CAAC,CAC9D,CAAA,MAAA,CAAO,CAAC,GAAA,EAAK,GAAQ,KAAA,GAAA,CAAI,MAAO,CAAA,GAAG,CAAG,EAAA,EAAE,CAAA;AAAA,IAC7C,CAAC,EAAE;AAAA,GACL;AACF","file":"cartesian.js","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 * Computes the Cartesian product of multiple arrays.\n *\n * @template T\n * the type of elements in the input arrays.\n * @param {...T[][]} all\n * a variadic number of arrays to compute the Cartesian product of.\n * @returns {T[][]}\n * An array containing all possible combinations of elements from the input\n * arrays, where each combination is represented as an array.\n *\n * @remarks\n * pure function\n *\n * @example\n * const result = cartesian([1, 2], ['a', 'b']);\n * // result: [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]\n */\nexport function cartesian<T>(...all: T[][]): T[][] {\n return all.reduce<T[][]>(\n (results, entries) =>\n results\n .map((result) => entries.map((entry) => result.concat([entry])))\n .reduce((sub, res) => sub.concat(res), []),\n [[]],\n );\n}\n"]}
@@ -0,0 +1,72 @@
1
+ import { Format } from './latlon/internal/index.js';
2
+ import { CoordinateSystem } from './latlon/internal/coordinate-system.js';
3
+ import './latlon/internal/parse.js';
4
+ import './latlon/internal/lexer.js';
5
+
6
+ type Coordinate = {
7
+ /** {@interitDoc Formatter} */
8
+ dd: Formatter;
9
+ /** {@interitDoc Formatter} */
10
+ ddm: Formatter;
11
+ /** {@interitDoc Formatter} */
12
+ dms: Formatter;
13
+ /** {@interitDoc Formatter} */
14
+ mgrs: Formatter;
15
+ /** {@interitDoc Formatter} */
16
+ utm: Formatter;
17
+ errors: string[];
18
+ raw: CoordinateInternalValue;
19
+ valid: boolean;
20
+ };
21
+ type CoordinateInternalValue = {
22
+ LAT: number;
23
+ LON: number;
24
+ };
25
+ /**
26
+ * Output a string value of a coordinate using an available system. The
27
+ * original value is preserved without conversion to an internal
28
+ * representation - Decimal Degrees - to prevent the possibility of
29
+ * rounding errors. All alternative values are computed from a common
30
+ * internal value to reduce complexity.
31
+ *
32
+ * @remarks
33
+ * pure function
34
+ *
35
+ * @example
36
+ * const create = createCoordinate(coordinateSystems.dd, 'LATLON')
37
+ * const coord = create('89.765432109 / 123.456789012')
38
+ *
39
+ * // honors the instantiation format 'LATLON'
40
+ * coord.dd() === '89.765432109 N / 123.456789012 E'
41
+ * coord.ddm() === '89 45.92592654 N / 123 27.40734072 E'
42
+ * coord.dms() === '89 45 55.5555924 N / 123 27 24.4404432 E'
43
+ *
44
+ * // change format to 'LONLAT'
45
+ * coord.dms('LONLAT') === '123 27 24.4404432 E / 89 45 55.5555924 N'
46
+ */
47
+ type Formatter = (f?: Format) => string;
48
+ declare const coordinateSystems: Readonly<{
49
+ readonly dd: CoordinateSystem;
50
+ readonly ddm: CoordinateSystem;
51
+ readonly dms: CoordinateSystem;
52
+ readonly mgrs: CoordinateSystem;
53
+ readonly utm: CoordinateSystem;
54
+ }>;
55
+ /**
56
+ * Create a coordinate object enabling: lexing, parsing, validation, and
57
+ * formatting in alternative systems and formats. The system and format will be
58
+ * used for validation and eventually for output as defaults if no alternatives
59
+ * are provided.
60
+ *
61
+ * @param initSystem dd, ddm, dms, mgrs, or utm of coordinateSystems
62
+ *
63
+ * @remarks
64
+ * pure function
65
+ *
66
+ * @example
67
+ * const create = createCoordinate(coordinateSystems.dd, 'LATLON')
68
+ * const create = createCoordinate(coordinateSystems.ddm, 'LONLAT')
69
+ */
70
+ declare function createCoordinate(initSystem?: CoordinateSystem, initFormat?: Format): (input: string) => Readonly<Coordinate>;
71
+
72
+ export { coordinateSystems, createCoordinate };
@@ -0,0 +1,87 @@
1
+ import { systemDecimalDegrees } from './latlon/decimal-degrees/system.js';
2
+ import { systemDegreesDecimalMinutes } from './latlon/degrees-decimal-minutes/system.js';
3
+ import { systemDegreesMinutesSeconds } from './latlon/degrees-minutes-seconds/system.js';
4
+ import { FORMATS_DEFAULT, SYMBOLS } from './latlon/internal/index.js';
5
+ import { createCache } from './latlon/internal/create-cache.js';
6
+ import { systemMGRS } from './mgrs/system.js';
7
+ import { systemUTM } from './utm/system.js';
8
+
9
+ // src/coordinates/coordinate.ts
10
+ var coordinateSystems = Object.freeze({
11
+ dd: systemDecimalDegrees,
12
+ ddm: systemDegreesDecimalMinutes,
13
+ dms: systemDegreesMinutesSeconds,
14
+ mgrs: systemMGRS,
15
+ utm: systemUTM
16
+ });
17
+ var freezeCoordinate = (errors, to, raw, valid) => Object.freeze({
18
+ dd: (format) => to(systemDecimalDegrees, format),
19
+ ddm: (format) => to(systemDegreesDecimalMinutes, format),
20
+ dms: (format) => to(systemDegreesMinutesSeconds, format),
21
+ mgrs: (format) => to(systemMGRS, format),
22
+ errors,
23
+ raw,
24
+ valid
25
+ });
26
+ function createCoordinate(initSystem = coordinateSystems.dd, initFormat = FORMATS_DEFAULT) {
27
+ return (input) => {
28
+ let tokens;
29
+ let errors;
30
+ try {
31
+ [tokens, errors] = initSystem.parse(initFormat, input);
32
+ if (errors.length) {
33
+ throw errors;
34
+ }
35
+ } catch (errors2) {
36
+ return freezeCoordinate(
37
+ errors2,
38
+ () => "",
39
+ {},
40
+ false
41
+ );
42
+ }
43
+ const cachedValues = {
44
+ [initSystem.name]: createCache(
45
+ initFormat,
46
+ // because mgrs doesn't have two formats: LATLON v LONLAT
47
+ initSystem.name === systemMGRS.name ? input : tokens.join(" ")
48
+ )
49
+ };
50
+ const raw = Object.fromEntries([
51
+ [
52
+ initFormat.slice(0, 3),
53
+ initSystem.toFloat(
54
+ tokens.slice(0, tokens.indexOf(SYMBOLS.DIVIDER))
55
+ )
56
+ ],
57
+ [
58
+ initFormat.slice(3),
59
+ initSystem.toFloat(
60
+ tokens.slice(1 + tokens.indexOf(SYMBOLS.DIVIDER))
61
+ )
62
+ ]
63
+ ]);
64
+ function to(system = initSystem, format = initFormat) {
65
+ const key = system.name;
66
+ if (!cachedValues[key]?.[format]) {
67
+ cachedValues[key] = {
68
+ ...cachedValues[key],
69
+ // use the Format to build the object, correctly pairing the halves of
70
+ // the coordinate value with their labels
71
+ [format]: system.toFormat(
72
+ format,
73
+ [format.slice(0, 3), format.slice(3)].map(
74
+ (key2) => raw[key2]
75
+ )
76
+ )
77
+ };
78
+ }
79
+ return cachedValues[key][format];
80
+ }
81
+ return freezeCoordinate([], to, raw, true);
82
+ };
83
+ }
84
+
85
+ export { coordinateSystems, createCoordinate };
86
+ //# sourceMappingURL=coordinate.js.map
87
+ //# sourceMappingURL=coordinate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/coordinates/coordinate.ts"],"names":["errors","key"],"mappings":"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","file":"coordinate.js","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 { systemDecimalDegrees } from './latlon/decimal-degrees/system';\nimport { systemDegreesDecimalMinutes } from './latlon/degrees-decimal-minutes/system';\nimport { systemDegreesMinutesSeconds } from './latlon/degrees-minutes-seconds/system';\nimport {\n type Axes,\n type Errors,\n FORMATS_DEFAULT,\n type Format,\n SYMBOLS,\n} from './latlon/internal';\nimport type { CoordinateSystem } from './latlon/internal/coordinate-system';\nimport {\n type CoordinateCache,\n createCache,\n} from './latlon/internal/create-cache';\nimport type { Tokens } from './latlon/internal/lexer';\nimport { systemMGRS } from './mgrs/system';\nimport { systemUTM } from './utm/system';\n\ntype Coordinate = {\n /** {@interitDoc Formatter} */\n dd: Formatter;\n /** {@interitDoc Formatter} */\n ddm: Formatter;\n /** {@interitDoc Formatter} */\n dms: Formatter;\n /** {@interitDoc Formatter} */\n mgrs: Formatter;\n /** {@interitDoc Formatter} */\n utm: Formatter;\n errors: string[];\n raw: CoordinateInternalValue;\n valid: boolean;\n};\n\n// biome-ignore lint/style/useNamingConvention: consistency with Axes type\ntype CoordinateInternalValue = { LAT: number; LON: number };\n\n/**\n * Output a string value of a coordinate using an available system. The\n * original value is preserved without conversion to an internal\n * representation - Decimal Degrees - to prevent the possibility of\n * rounding errors. All alternative values are computed from a common\n * internal value to reduce complexity.\n *\n * @remarks\n * pure function\n *\n * @example\n * const create = createCoordinate(coordinateSystems.dd, 'LATLON')\n * const coord = create('89.765432109 / 123.456789012')\n *\n * // honors the instantiation format 'LATLON'\n * coord.dd() === '89.765432109 N / 123.456789012 E'\n * coord.ddm() === '89 45.92592654 N / 123 27.40734072 E'\n * coord.dms() === '89 45 55.5555924 N / 123 27 24.4404432 E'\n *\n * // change format to 'LONLAT'\n * coord.dms('LONLAT') === '123 27 24.4404432 E / 89 45 55.5555924 N'\n */\ntype Formatter = (f?: Format) => string;\n\ntype ToFloatArg = Parameters<CoordinateSystem['toFloat']>[0];\n\ntype OutputCache = Record<keyof typeof coordinateSystems, CoordinateCache>;\n\nexport const coordinateSystems = Object.freeze({\n dd: systemDecimalDegrees,\n ddm: systemDegreesDecimalMinutes,\n dms: systemDegreesMinutesSeconds,\n mgrs: systemMGRS,\n utm: systemUTM,\n} as const);\n\nconst freezeCoordinate = (\n errors: Coordinate['errors'],\n to: (s?: CoordinateSystem, f?: Format) => string,\n raw: CoordinateInternalValue,\n valid: Coordinate['valid'],\n) =>\n Object.freeze({\n dd: (format?: Format) => to(systemDecimalDegrees, format),\n ddm: (format?: Format) => to(systemDegreesDecimalMinutes, format),\n dms: (format?: Format) => to(systemDegreesMinutesSeconds, format),\n mgrs: (format?: Format) => to(systemMGRS, format),\n errors,\n raw,\n valid,\n } as Coordinate);\n\n/**\n * Create a coordinate object enabling: lexing, parsing, validation, and\n * formatting in alternative systems and formats. The system and format will be\n * used for validation and eventually for output as defaults if no alternatives\n * are provided.\n *\n * @param initSystem dd, ddm, dms, mgrs, or utm of coordinateSystems\n *\n * @remarks\n * pure function\n *\n * @example\n * const create = createCoordinate(coordinateSystems.dd, 'LATLON')\n * const create = createCoordinate(coordinateSystems.ddm, 'LONLAT')\n */\nexport function createCoordinate(\n initSystem: CoordinateSystem = coordinateSystems.dd,\n initFormat: Format = FORMATS_DEFAULT,\n) {\n return (input: string) => {\n let tokens: Tokens;\n let errors: Errors;\n\n try {\n [tokens, errors] = initSystem.parse(initFormat, input);\n\n if (errors.length) {\n throw errors;\n }\n } catch (errors) {\n return freezeCoordinate(\n errors as Coordinate['errors'],\n () => '',\n {} as CoordinateInternalValue,\n false,\n );\n }\n\n // start with the original value for the original system in the original format\n // other values will be computed as needed and cached per request\n const cachedValues = {\n [initSystem.name]: createCache(\n initFormat,\n // because mgrs doesn't have two formats: LATLON v LONLAT\n initSystem.name === systemMGRS.name ? input : tokens.join(' '),\n ),\n } as OutputCache;\n\n // Create the \"internal\" representation - Decimal Degrees - for\n // consistency and ease of computation; all systems expect to\n // start from a common starting point to reduce complexity.\n const raw = Object.fromEntries([\n [\n initFormat.slice(0, 3),\n initSystem.toFloat(\n tokens.slice(0, tokens.indexOf(SYMBOLS.DIVIDER)) as ToFloatArg,\n ),\n ],\n [\n initFormat.slice(3),\n initSystem.toFloat(\n tokens.slice(1 + tokens.indexOf(SYMBOLS.DIVIDER)) as ToFloatArg,\n ),\n ],\n ]) as CoordinateInternalValue;\n\n function to(\n system: CoordinateSystem = initSystem,\n format: Format = initFormat,\n ) {\n const key = system.name as keyof typeof coordinateSystems;\n\n if (!cachedValues[key]?.[format]) {\n // cache \"miss\" - fill the missing value in the cache before returning it\n\n // update the cache to include the newly computed value\n cachedValues[key] = {\n ...cachedValues[key],\n // use the Format to build the object, correctly pairing the halves of\n // the coordinate value with their labels\n [format]: system.toFormat(\n format,\n ([format.slice(0, 3), format.slice(3)] as Axes[]).map(\n (key) => raw[key],\n ) as [number, number],\n ),\n };\n }\n\n return cachedValues[key][format];\n }\n\n return freezeCoordinate([] as Coordinate['errors'], to, raw, true);\n };\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import { Format } from '../internal/index.js';
2
+ import { ParseResults } from '../internal/parse.js';
3
+ import '../internal/lexer.js';
4
+
5
+ /** Parse a Decimal Degrees coordinate. */
6
+ declare const parseDecimalDegrees: (format: Format, input: string) => ParseResults;
7
+
8
+ export { parseDecimalDegrees };
@@ -0,0 +1,77 @@
1
+ import * as Patterning from '@/patterning.js';
2
+ import { PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS, BEARINGS, LIMITS } from '../internal/index.js';
3
+ import { createParser } from '../internal/parse-format.js';
4
+
5
+ // src/coordinates/latlon/decimal-degrees/parser.ts
6
+ var checks = {
7
+ deg: (deg, limit) => {
8
+ if (Number.parseFloat(deg) > limit) {
9
+ return `Degrees value (${deg}) exceeds max value (${limit}).`;
10
+ }
11
+ },
12
+ min: (val) => {
13
+ if (val.includes(SYMBOLS.MINUTES)) {
14
+ return `Seconds indicator (${SYMBOLS.MINUTES}) not valid in Decimal Degrees.`;
15
+ }
16
+ },
17
+ sec: (val) => {
18
+ if (val.includes(SYMBOLS.SECONDS)) {
19
+ return `Seconds indicator (${SYMBOLS.SECONDS}) not valid in Decimal Degrees.`;
20
+ }
21
+ }
22
+ };
23
+ var formats = {
24
+ LATLON: Patterning.fromTemplate(
25
+ PARTIAL_PATTERNS,
26
+ `degLatDec NS ${SYMBOLS.DIVIDER} degLonDec EW`
27
+ ),
28
+ LONLAT: Patterning.fromTemplate(
29
+ PARTIAL_PATTERNS,
30
+ `degLonDec EW ${SYMBOLS.DIVIDER} degLatDec NS`
31
+ )
32
+ };
33
+ function identifyErrors(format) {
34
+ return (arg, i) => {
35
+ if (!arg) {
36
+ return [[], ["Invalid coordinate value."]];
37
+ }
38
+ let { bear, deg } = arg;
39
+ deg ??= "0";
40
+ let isNegative = SYMBOL_PATTERNS.NEGATIVE_SIGN.test(deg) ? 1 : 0;
41
+ const bearingOptions = BEARINGS[format][i];
42
+ if (!bear || isNegative) {
43
+ bear = bearingOptions[isNegative];
44
+ deg = Math.abs(Number.parseFloat(deg)).toString();
45
+ isNegative = 0;
46
+ }
47
+ const errors = [
48
+ ...[checks.deg(deg, LIMITS[format][i] ?? 0)],
49
+ ...[checks.min([bear, deg].join(""))],
50
+ ...[checks.sec([bear, deg].join(""))]
51
+ ].filter(Boolean);
52
+ return errors.length ? [[], errors] : [[deg, bear], []];
53
+ };
54
+ }
55
+ function identifyPieces(half) {
56
+ if (half.length > 2 || half.length < 1) {
57
+ return;
58
+ }
59
+ const places = { bear: "", deg: "" };
60
+ return half.reduce((acc, token) => {
61
+ if (SYMBOL_PATTERNS.NSEW.test(token) && !acc.bear) {
62
+ acc.bear ||= token;
63
+ } else {
64
+ acc.deg ||= token;
65
+ }
66
+ return acc;
67
+ }, places);
68
+ }
69
+ var parseDecimalDegrees = createParser({
70
+ formats,
71
+ identifyErrors,
72
+ identifyPieces
73
+ });
74
+
75
+ export { parseDecimalDegrees };
76
+ //# sourceMappingURL=parser.js.map
77
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/coordinates/latlon/decimal-degrees/parser.ts"],"names":[],"mappings":"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","file":"parser.js","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 * as Patterning from '@/patterning';\n\nimport {\n BEARINGS,\n type Format,\n LIMITS,\n PARTIAL_PATTERNS,\n SYMBOLS,\n SYMBOL_PATTERNS,\n} from '../internal';\nimport type { ParseResults } from '../internal/parse';\nimport { createParser } from '../internal/parse-format';\n\ntype DecimalDegrees = {\n bear: string;\n deg: string;\n};\n\nconst checks = {\n deg: (deg: string, limit: number) => {\n if (Number.parseFloat(deg) > limit) {\n return `Degrees value (${deg}) exceeds max value (${limit}).`;\n }\n },\n min: (val: string) => {\n if (val.includes(SYMBOLS.MINUTES)) {\n return `Seconds indicator (${SYMBOLS.MINUTES}) not valid in Decimal Degrees.`;\n }\n },\n sec: (val: string) => {\n if (val.includes(SYMBOLS.SECONDS)) {\n return `Seconds indicator (${SYMBOLS.SECONDS}) not valid in Decimal Degrees.`;\n }\n },\n};\n\nconst formats = {\n LATLON: Patterning.fromTemplate(\n PARTIAL_PATTERNS,\n `degLatDec NS ${SYMBOLS.DIVIDER} degLonDec EW`,\n ),\n LONLAT: Patterning.fromTemplate(\n PARTIAL_PATTERNS,\n `degLonDec EW ${SYMBOLS.DIVIDER} degLatDec NS`,\n ),\n};\n\nfunction identifyErrors(format: Format) {\n return (arg: DecimalDegrees | undefined, i: number) => {\n if (!arg) {\n return [[], ['Invalid coordinate value.']] as ParseResults;\n }\n\n let { bear, deg } = arg;\n\n deg ??= '0';\n\n let isNegative: 0 | 1 = SYMBOL_PATTERNS.NEGATIVE_SIGN.test(deg) ? 1 : 0;\n const bearingOptions = BEARINGS[format][i] as [string, string];\n\n if (!bear || isNegative) {\n bear = bearingOptions[isNegative];\n deg = Math.abs(Number.parseFloat(deg)).toString();\n isNegative = 0;\n }\n\n const errors = [\n ...[checks.deg(deg, LIMITS[format][i] ?? 0)],\n ...[checks.min([bear, deg].join(''))],\n ...[checks.sec([bear, deg].join(''))],\n ].filter(Boolean);\n\n return (errors.length ? [[], errors] : [[deg, bear], []]) as ParseResults;\n };\n}\n\nfunction identifyPieces(half: string[]) {\n if (half.length > 2 || half.length < 1) {\n return;\n }\n\n const places = { bear: '', deg: '' };\n\n return half.reduce((acc, token) => {\n if (SYMBOL_PATTERNS.NSEW.test(token) && !acc.bear) {\n acc.bear ||= token;\n } else {\n acc.deg ||= token;\n }\n\n return acc;\n }, places);\n}\n\n/** Parse a Decimal Degrees coordinate. */\nexport const parseDecimalDegrees = createParser<DecimalDegrees>({\n formats,\n identifyErrors,\n identifyPieces,\n});\n"]}
@@ -0,0 +1,8 @@
1
+ import { CoordinateSystem } from '../internal/coordinate-system.js';
2
+ import '../internal/index.js';
3
+ import '../internal/parse.js';
4
+ import '../internal/lexer.js';
5
+
6
+ declare const systemDecimalDegrees: CoordinateSystem;
7
+
8
+ export { systemDecimalDegrees };
@@ -0,0 +1,21 @@
1
+ import { BEARINGS, SYMBOLS, SYMBOL_PATTERNS } from '../internal/index.js';
2
+ import { parseDecimalDegrees } from './parser.js';
3
+
4
+ // src/coordinates/latlon/decimal-degrees/system.ts
5
+ var systemDecimalDegrees = {
6
+ name: "Decimal Degrees",
7
+ parse: parseDecimalDegrees,
8
+ toFloat(arg) {
9
+ const [num, bear] = arg;
10
+ return Number.parseFloat(num) * (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1);
11
+ },
12
+ toFormat(format, [left, right]) {
13
+ return [left, right].map(
14
+ (num, index) => `${Math.abs(num)} ${BEARINGS[format][index][+(num < 0)]}`
15
+ ).join(` ${SYMBOLS.DIVIDER} `);
16
+ }
17
+ };
18
+
19
+ export { systemDecimalDegrees };
20
+ //# sourceMappingURL=system.js.map
21
+ //# sourceMappingURL=system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/coordinates/latlon/decimal-degrees/system.ts"],"names":[],"mappings":";;;;AAwBO,IAAM,oBAAyC,GAAA;AAAA,EACpD,IAAM,EAAA,iBAAA;AAAA,EAEN,KAAO,EAAA,mBAAA;AAAA,EAEP,QAAQ,GAAK,EAAA;AACX,IAAM,MAAA,CAAC,GAAK,EAAA,IAAI,CAAI,GAAA,GAAA;AAEpB,IACE,OAAA,MAAA,CAAO,WAAW,GAAG,CAAA,IACpB,gBAAgB,iBAAkB,CAAA,IAAA,CAAK,IAAI,CAAA,GAAI,EAAK,GAAA,CAAA,CAAA;AAAA,GAEzD;AAAA,EAEA,QAAS,CAAA,MAAA,EAAgB,CAAC,IAAA,EAAM,KAAK,CAAqB,EAAA;AACxD,IAAO,OAAA,CAAC,IAAM,EAAA,KAAK,CAChB,CAAA,GAAA;AAAA,MACC,CAAC,GAAK,EAAA,KAAA,KACJ,CAAG,EAAA,IAAA,CAAK,IAAI,GAAG,CAAC,CAAI,CAAA,EAAA,QAAA,CAAS,MAAM,CAAE,CAAA,KAAc,EAAE,EAAE,GAAA,GAAM,EAAE,CAAC,CAAA;AAAA,KAEnE,CAAA,IAAA,CAAK,CAAI,CAAA,EAAA,OAAA,CAAQ,OAAO,CAAG,CAAA,CAAA,CAAA;AAAA;AAElC","file":"system.js","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 {\n BEARINGS,\n type Compass,\n type Format,\n SYMBOLS,\n SYMBOL_PATTERNS,\n} from '../internal';\nimport type { CoordinateSystem } from '../internal/coordinate-system';\n\nimport { parseDecimalDegrees } from './parser';\n\nexport const systemDecimalDegrees: CoordinateSystem = {\n name: 'Decimal Degrees',\n\n parse: parseDecimalDegrees,\n\n toFloat(arg) {\n const [num, bear] = arg as [string, Compass];\n\n return (\n Number.parseFloat(num) *\n (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)\n );\n },\n\n toFormat(format: Format, [left, right]: [number, number]) {\n return [left, right]\n .map(\n (num, index) =>\n `${Math.abs(num)} ${BEARINGS[format][index as 0 | 1][+(num < 0)]}`,\n )\n .join(` ${SYMBOLS.DIVIDER} `);\n },\n};\n"]}
@@ -0,0 +1,8 @@
1
+ import { Format } from '../internal/index.js';
2
+ import { ParseResults } from '../internal/parse.js';
3
+ import '../internal/lexer.js';
4
+
5
+ /** Parse a Degrees Decimal Minutes coordinate. */
6
+ declare const parseDegreesDecimalMinutes: (format: Format, input: string) => ParseResults;
7
+
8
+ export { parseDegreesDecimalMinutes };
@@ -0,0 +1,86 @@
1
+ import * as Patterning from '@/patterning.js';
2
+ import { PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS, BEARINGS, LIMITS } from '../internal/index.js';
3
+ import { inRange } from '../internal/in-range.js';
4
+ import { createParser } from '../internal/parse-format.js';
5
+
6
+ // src/coordinates/latlon/degrees-decimal-minutes/parser.ts
7
+ var checks = {
8
+ deg: (deg, limit) => {
9
+ if (Number.parseFloat(deg) > limit) {
10
+ return `Degrees value (${deg}) exceeds max value (${limit}).`;
11
+ }
12
+ if (/\./.test(deg)) {
13
+ return `Degrees value (${deg}) must not include decimal value.`;
14
+ }
15
+ },
16
+ min: (min) => inRange("Minutes", min, 59.999999999),
17
+ sec: (val) => {
18
+ if (val.includes(SYMBOLS.SECONDS)) {
19
+ return `Seconds indicator (${SYMBOLS.SECONDS}) not valid in Degree Decimal Minutes.`;
20
+ }
21
+ }
22
+ };
23
+ var formats = {
24
+ LATLON: Patterning.fromTemplate(
25
+ PARTIAL_PATTERNS,
26
+ `degLat minDec NS ${SYMBOLS.DIVIDER} degLon minDec EW`
27
+ ),
28
+ LONLAT: Patterning.fromTemplate(
29
+ PARTIAL_PATTERNS,
30
+ `degLon minDec EW ${SYMBOLS.DIVIDER} degLat minDec NS`
31
+ )
32
+ };
33
+ function identifyErrors(format) {
34
+ return (arg, i) => {
35
+ if (!arg) {
36
+ return [[], ["Invalid coordinate value."]];
37
+ }
38
+ let { bear, deg, min } = arg;
39
+ deg ??= "0";
40
+ min ??= "0";
41
+ let isNegative = SYMBOL_PATTERNS.NEGATIVE_SIGN.test(deg) ? 1 : 0;
42
+ const bearingOptions = BEARINGS[format][i];
43
+ if (!bear || isNegative) {
44
+ bear = bearingOptions[isNegative];
45
+ deg = Math.abs(Number.parseFloat(deg)).toString();
46
+ isNegative = 0;
47
+ }
48
+ const errors = [
49
+ ...[checks.deg(deg, LIMITS[format][i] ?? 0)],
50
+ ...[checks.min(min)],
51
+ ...[checks.sec([bear, deg, min].join(""))]
52
+ ].filter(Boolean);
53
+ return errors.length ? [[], errors] : [[deg, min, bear], []];
54
+ };
55
+ }
56
+ function identifyPieces(half) {
57
+ if (half.length < 1 || half.length > 3) {
58
+ return;
59
+ }
60
+ const asString = half.join(" ");
61
+ const places = { bear: "", deg: "", min: "" };
62
+ const keys = ["deg", "min"];
63
+ const test = (r, b, v) => r.test(v) || r.test(asString) && b;
64
+ return half.reduce((acc, token, i, { length }) => {
65
+ if (test(SYMBOL_PATTERNS.NSEW, i === length - 1, token)) {
66
+ acc.bear ||= token;
67
+ } else if (test(SYMBOL_PATTERNS.DEGREES, i === 0, token)) {
68
+ acc.deg ||= token;
69
+ } else if (test(SYMBOL_PATTERNS.MINUTES, i === 1, token)) {
70
+ acc.min ||= token;
71
+ } else {
72
+ const key = keys.find((k) => !acc[k]);
73
+ acc[key] = token;
74
+ }
75
+ return acc;
76
+ }, places);
77
+ }
78
+ var parseDegreesDecimalMinutes = createParser({
79
+ formats,
80
+ identifyErrors,
81
+ identifyPieces
82
+ });
83
+
84
+ export { parseDegreesDecimalMinutes };
85
+ //# sourceMappingURL=parser.js.map
86
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/coordinates/latlon/degrees-decimal-minutes/parser.ts"],"names":[],"mappings":"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","file":"parser.js","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 * as Patterning from '@/patterning';\n\nimport {\n BEARINGS,\n type Format,\n LIMITS,\n PARTIAL_PATTERNS,\n SYMBOLS,\n SYMBOL_PATTERNS,\n} from '../internal';\nimport { inRange } from '../internal/in-range';\nimport type { ParseResults } from '../internal/parse';\nimport { createParser } from '../internal/parse-format';\n\ntype DegreesDecimalMinutes = {\n bear: string;\n deg: string;\n min: string;\n};\n\nconst checks = {\n deg: (deg: string, limit: number) => {\n if (Number.parseFloat(deg) > limit) {\n return `Degrees value (${deg}) exceeds max value (${limit}).`;\n }\n\n if (/\\./.test(deg)) {\n return `Degrees value (${deg}) must not include decimal value.`;\n }\n },\n min: (min: string) => inRange('Minutes', min, 59.999999999),\n sec: (val: string) => {\n if (val.includes(SYMBOLS.SECONDS)) {\n return `Seconds indicator (${SYMBOLS.SECONDS}) not valid in Degree Decimal Minutes.`;\n }\n },\n};\n\nconst formats = {\n LATLON: Patterning.fromTemplate(\n PARTIAL_PATTERNS,\n `degLat minDec NS ${SYMBOLS.DIVIDER} degLon minDec EW`,\n ),\n LONLAT: Patterning.fromTemplate(\n PARTIAL_PATTERNS,\n `degLon minDec EW ${SYMBOLS.DIVIDER} degLat minDec NS`,\n ),\n};\n\nfunction identifyErrors(format: Format) {\n return (arg: DegreesDecimalMinutes | undefined, i: number) => {\n if (!arg) {\n return [[], ['Invalid coordinate value.']] as ParseResults;\n }\n\n let { bear, deg, min } = arg;\n\n deg ??= '0';\n min ??= '0';\n\n let isNegative: 0 | 1 = SYMBOL_PATTERNS.NEGATIVE_SIGN.test(deg) ? 1 : 0;\n const bearingOptions = BEARINGS[format][i] as [string, string];\n\n if (!bear || isNegative) {\n bear = bearingOptions[isNegative];\n deg = Math.abs(Number.parseFloat(deg)).toString();\n isNegative = 0;\n }\n\n const errors = [\n ...[checks.deg(deg, LIMITS[format][i] ?? 0)],\n ...[checks.min(min)],\n ...[checks.sec([bear, deg, min].join(''))],\n ].filter(Boolean);\n\n return (\n errors.length ? [[], errors] : [[deg, min, bear], []]\n ) as ParseResults;\n };\n}\n\nfunction identifyPieces(half: string[]) {\n if (half.length < 1 || half.length > 3) {\n return;\n }\n\n const asString = half.join(' ');\n const places = { bear: '', deg: '', min: '' };\n const keys = ['deg', 'min'] as (keyof typeof places)[];\n const test = (r: RegExp, b: boolean, v: string) =>\n r.test(v) || (r.test(asString) && b);\n\n return half.reduce((acc, token, i, { length }) => {\n if (test(SYMBOL_PATTERNS.NSEW, i === length - 1, token)) {\n acc.bear ||= token;\n } else if (test(SYMBOL_PATTERNS.DEGREES, i === 0, token)) {\n acc.deg ||= token;\n } else if (test(SYMBOL_PATTERNS.MINUTES, i === 1, token)) {\n acc.min ||= token;\n } else {\n const key = keys.find((k) => !acc[k]);\n\n acc[key as keyof typeof acc] = token;\n }\n\n return acc;\n }, places);\n}\n\n/** Parse a Degrees Decimal Minutes coordinate. */\nexport const parseDegreesDecimalMinutes = createParser<DegreesDecimalMinutes>({\n formats,\n identifyErrors,\n identifyPieces,\n});\n"]}
@@ -0,0 +1,8 @@
1
+ import { CoordinateSystem } from '../internal/coordinate-system.js';
2
+ import '../internal/index.js';
3
+ import '../internal/parse.js';
4
+ import '../internal/lexer.js';
5
+
6
+ declare const systemDegreesDecimalMinutes: CoordinateSystem;
7
+
8
+ export { systemDegreesDecimalMinutes };
@@ -0,0 +1,26 @@
1
+ import { BEARINGS, SYMBOLS, SYMBOL_PATTERNS } from '../internal/index.js';
2
+ import { parseDegreesDecimalMinutes } from './parser.js';
3
+
4
+ // src/coordinates/latlon/degrees-decimal-minutes/system.ts
5
+ var systemDegreesDecimalMinutes = {
6
+ name: "Degrees Decimal Minutes",
7
+ parse: parseDegreesDecimalMinutes,
8
+ toFloat(arg) {
9
+ const [degrees, minutes, bear] = arg;
10
+ return Number.parseFloat(
11
+ ((Number.parseFloat(degrees) + Number.parseFloat(minutes) / 60) * (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)).toFixed(9)
12
+ );
13
+ },
14
+ toFormat(format, [left, right]) {
15
+ return [left, right].map((num, index) => {
16
+ const abs = Math.abs(num);
17
+ const deg = Math.floor(abs);
18
+ const min = Number.parseFloat(((abs - deg) * 60).toFixed(9));
19
+ return `${deg} ${min} ${BEARINGS[format][index][+(num < 0)]}`;
20
+ }).join(` ${SYMBOLS.DIVIDER} `);
21
+ }
22
+ };
23
+
24
+ export { systemDegreesDecimalMinutes };
25
+ //# sourceMappingURL=system.js.map
26
+ //# sourceMappingURL=system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/coordinates/latlon/degrees-decimal-minutes/system.ts"],"names":[],"mappings":";;;;AAwBO,IAAM,2BAAgD,GAAA;AAAA,EAC3D,IAAM,EAAA,yBAAA;AAAA,EAEN,KAAO,EAAA,0BAAA;AAAA,EAEP,QAAQ,GAAK,EAAA;AACX,IAAA,MAAM,CAAC,OAAA,EAAS,OAAS,EAAA,IAAI,CAAI,GAAA,GAAA;AAEjC,IAAA,OAAO,MAAO,CAAA,UAAA;AAAA,MAAA,CAAA,CAET,OAAO,UAAW,CAAA,OAAO,CAAI,GAAA,MAAA,CAAO,WAAW,OAAO,CAAA,GAAI,EAC1D,KAAA,eAAA,CAAgB,kBAAkB,IAAK,CAAA,IAAI,IAAI,EAAK,GAAA,CAAA,CAAA,EACrD,QAAQ,CAAC;AAAA,KACb;AAAA,GACF;AAAA,EAEA,QAAS,CAAA,MAAA,EAAgB,CAAC,IAAA,EAAM,KAAK,CAAqB,EAAA;AACxD,IAAA,OAAO,CAAC,IAAM,EAAA,KAAK,EAChB,GAAI,CAAA,CAAC,KAAK,KAAU,KAAA;AACnB,MAAM,MAAA,GAAA,GAAM,IAAK,CAAA,GAAA,CAAI,GAAG,CAAA;AACxB,MAAM,MAAA,GAAA,GAAM,IAAK,CAAA,KAAA,CAAM,GAAG,CAAA;AAC1B,MAAM,MAAA,GAAA,GAAM,OAAO,UAAa,CAAA,CAAA,CAAA,GAAA,GAAM,OAAO,EAAI,EAAA,OAAA,CAAQ,CAAC,CAAC,CAAA;AAE3D,MAAA,OAAO,CAAG,EAAA,GAAG,CAAI,CAAA,EAAA,GAAG,CAAI,CAAA,EAAA,QAAA,CAAS,MAAM,CAAA,CAAE,KAAc,CAAA,CAAE,EAAE,GAAA,GAAM,EAAE,CAAC,CAAA,CAAA;AAAA,KACrE,CACA,CAAA,IAAA,CAAK,CAAI,CAAA,EAAA,OAAA,CAAQ,OAAO,CAAG,CAAA,CAAA,CAAA;AAAA;AAElC","file":"system.js","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 {\n BEARINGS,\n type Compass,\n type Format,\n SYMBOLS,\n SYMBOL_PATTERNS,\n} from '../internal';\nimport type { CoordinateSystem } from '../internal/coordinate-system';\n\nimport { parseDegreesDecimalMinutes } from './parser';\n\nexport const systemDegreesDecimalMinutes: CoordinateSystem = {\n name: 'Degrees Decimal Minutes',\n\n parse: parseDegreesDecimalMinutes,\n\n toFloat(arg) {\n const [degrees, minutes, bear] = arg as [string, string, Compass];\n\n return Number.parseFloat(\n (\n (Number.parseFloat(degrees) + Number.parseFloat(minutes) / 60) *\n (SYMBOL_PATTERNS.NEGATIVE_BEARINGS.test(bear) ? -1 : 1)\n ).toFixed(9),\n );\n },\n\n toFormat(format: Format, [left, right]: [number, number]) {\n return [left, right]\n .map((num, index) => {\n const abs = Math.abs(num);\n const deg = Math.floor(abs);\n const min = Number.parseFloat(((abs - deg) * 60).toFixed(9));\n\n return `${deg} ${min} ${BEARINGS[format][index as 0 | 1][+(num < 0)]}`;\n })\n .join(` ${SYMBOLS.DIVIDER} `);\n },\n};\n"]}
@@ -0,0 +1,8 @@
1
+ import { Format } from '../internal/index.js';
2
+ import { ParseResults } from '../internal/parse.js';
3
+ import '../internal/lexer.js';
4
+
5
+ /** Parse a Degrees Minutes Seconds coordinate. */
6
+ declare const parseDegreesMinutesSeconds: (format: Format, input: string) => ParseResults;
7
+
8
+ export { parseDegreesMinutesSeconds };
@@ -0,0 +1,85 @@
1
+ import * as Patterning from '@/patterning.js';
2
+ import { PARTIAL_PATTERNS, SYMBOLS, SYMBOL_PATTERNS, BEARINGS, LIMITS } from '../internal/index.js';
3
+ import { inRange } from '../internal/in-range.js';
4
+ import { createParser } from '../internal/parse-format.js';
5
+
6
+ // src/coordinates/latlon/degrees-minutes-seconds/parser.ts
7
+ var checks = {
8
+ deg: (deg, limit) => {
9
+ if (Number.parseFloat(deg) > limit) {
10
+ return `Degrees value (${deg}) exceeds max value (${limit}).`;
11
+ }
12
+ if (/\./.test(deg)) {
13
+ return `Degrees value (${deg}) must not include decimal value.`;
14
+ }
15
+ },
16
+ min: (min) => inRange("Minutes", min, 59),
17
+ sec: (sec) => inRange("Seconds", sec, 59.999999999)
18
+ };
19
+ var formats = {
20
+ LATLON: Patterning.fromTemplate(
21
+ PARTIAL_PATTERNS,
22
+ `degLat min secDec NS ${SYMBOLS.DIVIDER} degLon min secDec EW`
23
+ ),
24
+ LONLAT: Patterning.fromTemplate(
25
+ PARTIAL_PATTERNS,
26
+ `degLon min secDec EW ${SYMBOLS.DIVIDER} degLat min secDec NS`
27
+ )
28
+ };
29
+ function identifyErrors(format) {
30
+ return (arg, i) => {
31
+ if (!arg) {
32
+ return [[], ["Invalid coordinate value."]];
33
+ }
34
+ let { bear, deg, min, sec } = arg;
35
+ deg ??= "0";
36
+ min ||= "0";
37
+ sec ||= "0";
38
+ let isNegative = SYMBOL_PATTERNS.NEGATIVE_SIGN.test(deg) ? 1 : 0;
39
+ const bearingOptions = BEARINGS[format][i];
40
+ if (!bear || isNegative) {
41
+ bear = bearingOptions[isNegative];
42
+ deg = Math.abs(Number.parseFloat(deg)).toString();
43
+ isNegative = 0;
44
+ }
45
+ const errors = [
46
+ ...[checks.deg(deg, LIMITS[format][i] ?? 0)],
47
+ ...[checks.min(min)],
48
+ ...[checks.sec(sec)]
49
+ ].filter(Boolean);
50
+ return errors.length ? [[], errors] : [[deg, min, sec, bear], []];
51
+ };
52
+ }
53
+ function identifyPieces(half) {
54
+ if (half.length < 1 || half.length > 4) {
55
+ return;
56
+ }
57
+ const asString = half.join(" ");
58
+ const places = { bear: "", deg: "", min: "", sec: "" };
59
+ const keys = ["deg", "min", "sec"];
60
+ const test = (r, b, v) => r.test(v) || r.test(asString) && b;
61
+ return half.reduce((acc, token, i, { length }) => {
62
+ if (test(SYMBOL_PATTERNS.NSEW, i === length - 1, token)) {
63
+ acc.bear ||= token;
64
+ } else if (test(SYMBOL_PATTERNS.DEGREES, i === 0, token)) {
65
+ acc.deg ||= token;
66
+ } else if (test(SYMBOL_PATTERNS.MINUTES, i === 1, token)) {
67
+ acc.min ||= token;
68
+ } else if (test(SYMBOL_PATTERNS.SECONDS, i === 2, token)) {
69
+ acc.sec ||= token;
70
+ } else {
71
+ const key = keys.find((k) => !acc[k]);
72
+ acc[key] = token;
73
+ }
74
+ return acc;
75
+ }, places);
76
+ }
77
+ var parseDegreesMinutesSeconds = createParser({
78
+ formats,
79
+ identifyErrors,
80
+ identifyPieces
81
+ });
82
+
83
+ export { parseDegreesMinutesSeconds };
84
+ //# sourceMappingURL=parser.js.map
85
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/coordinates/latlon/degrees-minutes-seconds/parser.ts"],"names":[],"mappings":"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","file":"parser.js","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 * as Patterning from '@/patterning';\n\nimport {\n BEARINGS,\n type Format,\n LIMITS,\n PARTIAL_PATTERNS,\n SYMBOLS,\n SYMBOL_PATTERNS,\n} from '../internal';\nimport { inRange } from '../internal/in-range';\nimport type { ParseResults } from '../internal/parse';\nimport { createParser } from '../internal/parse-format';\n\ntype DegreesMinutesSeconds = {\n bear: string;\n deg: string;\n min: string;\n sec: string;\n};\n\nconst checks = {\n deg: (deg: string, limit: number) => {\n if (Number.parseFloat(deg) > limit) {\n return `Degrees value (${deg}) exceeds max value (${limit}).`;\n }\n\n if (/\\./.test(deg)) {\n return `Degrees value (${deg}) must not include decimal value.`;\n }\n },\n min: (min: string) => inRange('Minutes', min, 59),\n sec: (sec: string) => inRange('Seconds', sec, 59.999999999),\n};\n\nconst formats = {\n LATLON: Patterning.fromTemplate(\n PARTIAL_PATTERNS,\n `degLat min secDec NS ${SYMBOLS.DIVIDER} degLon min secDec EW`,\n ),\n LONLAT: Patterning.fromTemplate(\n PARTIAL_PATTERNS,\n `degLon min secDec EW ${SYMBOLS.DIVIDER} degLat min secDec NS`,\n ),\n};\n\nfunction identifyErrors(format: Format) {\n return (arg: DegreesMinutesSeconds | undefined, i: number) => {\n if (!arg) {\n return [[], ['Invalid coordinate value.']] as ParseResults;\n }\n\n let { bear, deg, min, sec } = arg;\n\n deg ??= '0';\n // NOTE: need `||=` not `??=` because empty-string is not nullish\n min ||= '0';\n sec ||= '0';\n\n let isNegative: 0 | 1 = SYMBOL_PATTERNS.NEGATIVE_SIGN.test(deg) ? 1 : 0;\n const bearingOptions = BEARINGS[format][i] as [string, string];\n\n if (!bear || isNegative) {\n bear = bearingOptions[isNegative];\n deg = Math.abs(Number.parseFloat(deg)).toString();\n isNegative = 0;\n }\n\n const errors = [\n ...[checks.deg(deg, LIMITS[format][i] ?? 0)],\n ...[checks.min(min)],\n ...[checks.sec(sec)],\n ].filter(Boolean);\n\n return (\n errors.length ? [[], errors] : [[deg, min, sec, bear], []]\n ) as ParseResults;\n };\n}\n\nfunction identifyPieces(half: string[]) {\n if (half.length < 1 || half.length > 4) {\n return;\n }\n\n const asString = half.join(' ');\n const places = { bear: '', deg: '', min: '', sec: '' };\n const keys = ['deg', 'min', 'sec'] as (keyof typeof places)[];\n const test = (r: RegExp, b: boolean, v: string) =>\n r.test(v) || (r.test(asString) && b);\n\n return half.reduce((acc, token, i, { length }) => {\n if (test(SYMBOL_PATTERNS.NSEW, i === length - 1, token)) {\n acc.bear ||= token;\n } else if (test(SYMBOL_PATTERNS.DEGREES, i === 0, token)) {\n acc.deg ||= token;\n } else if (test(SYMBOL_PATTERNS.MINUTES, i === 1, token)) {\n acc.min ||= token;\n } else if (test(SYMBOL_PATTERNS.SECONDS, i === 2, token)) {\n acc.sec ||= token;\n } else {\n const key = keys.find((k) => !acc[k]);\n\n acc[key as keyof typeof acc] = token;\n }\n\n return acc;\n }, places);\n}\n\n/** Parse a Degrees Minutes Seconds coordinate. */\nexport const parseDegreesMinutesSeconds = createParser<DegreesMinutesSeconds>({\n formats,\n identifyErrors,\n identifyPieces,\n});\n"]}