All files / core/systems/mgrs system.ts

94.44% Statements 17/18
100% Branches 6/6
87.5% Functions 7/8
94.44% Lines 17/18

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              14x         1058x 1058x 1058x   2116x     1058x             14x 9022x     1004x                 14x   14x   7x   7x   4x         14x         14x                           14x                    
import { Array, Option, pipe } from 'effect'
 
import { compact, makeParser } from '../parser'
import type { Formatter, Grid, Parser } from '../types'
import { mgrsGrid, mgrsSquareOutline } from './grid'
import { fromMgrs, isMgrs, toMgrs, toMgrsParts } from './mgrs'
 
export const formatter: Formatter = {
  id: 'MGRS',
  label: 'MGRS',
  maybeGridId: Option.some('Mgrs'),
  format: (point, { mgrsPrecision }) => {
    const parts = toMgrsParts(point, mgrsPrecision)
    const gzd = `${parts.zone ?? ''}${parts.band} ${parts.square}`
    const digits = pipe(
      [parts.easting, parts.northing],
      Array.filter(part => part !== ''),
      Array.join(' '),
    )
    return {
      lines: [gzd, digits === '' ? '100 km square' : digits],
      copyText: digits === '' ? gzd : `${gzd} ${digits}`,
    }
  },
}
 
export const parser: Parser = makeParser('MGRS', text =>
  pipe(
    compact(text),
    Option.liftPredicate(isMgrs),
    Option.map(reference => ({
      kind: 'MGRS',
      point: fromMgrs(reference).center,
      maybeBounds: Option.none(),
    })),
  ),
)
 
/** Outline the square at the chosen precision, down to 100 m; finer squares are too small to see. */
const MIN_OUTLINE_PRECISION = 3
 
const cueSquareOutline: Grid['maybeCueOutline'] = Option.some(
  (point, { mgrsPrecision }) =>
    pipe(
      mgrsPrecision,
      Option.liftPredicate(precision => precision <= MIN_OUTLINE_PRECISION),
      Option.flatMap(precision =>
        Option.fromNullishOr(mgrsSquareOutline(toMgrs(point, precision))),
      ),
    ),
)
 
const MGRS_COLORS: Grid['colors'] = {
  onDark: [76, 139, 245, 130],
  onLight: [24, 90, 200, 150],
}
 
export const grid: Grid = {
  id: 'Mgrs',
  label: 'MGRS',
  description: 'MGRS grid lines and squares, from zoom 5',
  colors: MGRS_COLORS,
  isEnabledByDefault: true,
  build: mgrsGrid,
  maybeCueOutline: cueSquareOutline,
}
 
/**
 * MGRS as on a nautical chart (AGeoP-21 B.6.6): ticks on the map edges, labelled with their
 * grid digits, and small crosses at the grid intersections, so the chart stays readable.
 */
export const ticksGrid: Grid = {
  id: 'MgrsTicks',
  label: 'MGRS ticks',
  description:
    'MGRS as on a nautical chart: ticks on the map edges, labelled with their grid digits, and crosses at the intersections',
  colors: MGRS_COLORS,
  isEnabledByDefault: false,
  build: (view, zoom) => mgrsGrid(view, zoom, undefined, 'Ticks'),
  maybeCueOutline: cueSquareOutline,
}