All files / core/systems registry.ts

100% Statements 15/15
100% Branches 0/0
100% Functions 8/8
100% Lines 12/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90                                          14x                                       14x                           14x                       14x 69505x     14x       2650x   14x 6x   54x             14x 4778x  
/**
 * The coordinate systems the app knows about. To add a system, give it a folder that exports
 * a Formatter, Parser or Grid, then list it here. Nothing else in the app names a system.
 */
import { Array, Option, Record, pipe } from 'effect'
 
import * as Angles from './angles'
import * as Ecef from './ecef'
import * as Gars from './gars'
import * as Geohash from './geohash'
import * as Georef from './georef'
import * as Graticule from './graticule'
import * as Maidenhead from './maidenhead'
import * as Mgrs from './mgrs'
import * as PlusCode from './plusCode'
import * as Tile from './tile'
import type { Formatter, Grid, ParseResult, Parser } from './types'
import * as Utm from './utm'
import * as WebMercator from './webMercator'
 
/** Readout columns, left to right. */
export const formatters: ReadonlyArray<Formatter> = [
  Angles.ddFormatter,
  Angles.dmsFormatter,
  Angles.ddmFormatter,
  Utm.formatter,
  Mgrs.formatter,
  Gars.formatter,
  Georef.formatter,
  PlusCode.formatter,
  Geohash.formatter,
  Maidenhead.formatter,
  Tile.formatter,
  WebMercator.formatter,
  Ecef.formatter,
]
 
/**
 * Tried in order; the first match wins. GEOREF comes before Geohash, whose alphabet accepts
 * GEOREF letters, and Geohash is last because it accepts the most text.
 */
export const parsers: ReadonlyArray<Parser> = [
  Utm.utmParser,
  Utm.upsParser,
  Gars.parser,
  Mgrs.parser,
  Maidenhead.parser,
  PlusCode.parser,
  Tile.parser,
  Angles.parser,
  Georef.parser,
  Geohash.parser,
]
 
/** Drawn in order, so later grids sit on top; their labels win collisions. */
export const grids: ReadonlyArray<Grid> = [
  Graticule.grid,
  Angles.ddmGrid,
  Tile.grid,
  PlusCode.grid,
  Georef.grid,
  Gars.grid,
  Utm.grid,
  Mgrs.grid,
  Mgrs.ticksGrid,
]
 
export const parseCoordinate = (text: string): Option.Option<ParseResult> =>
  Array.findFirst(parsers, parser => parser.parse(text))
 
/** Whether a grid is on; a grid the toggles do not list (newer than saved settings) uses its default. */
export const isGridEnabled = (
  toggles: Readonly<Record<string, boolean>>,
  grid: Grid,
): boolean =>
  Option.getOrElse(Record.get(toggles, grid.id), () => grid.isEnabledByDefault)
 
export const defaultGridToggles = (): Record<string, boolean> =>
  pipe(
    grids,
    Array.map((grid): readonly [string, boolean] => [
      grid.id,
      grid.isEnabledByDefault,
    ]),
    Record.fromEntries,
  )
 
export const findGrid = (gridId: string): Option.Option<Grid> =>
  Array.findFirst(grids, ({ id }) => id === gridId)