All files / core/systems profiles.ts

100% Statements 21/21
100% Branches 0/0
100% Functions 12/12
100% Lines 19/19

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 91 92 93 94 95 96 97 98 99                    7x     7x                         7x                                                         7x     264x   3232x   2904x       7x 132x     7x 132x     7x 33x 33x 297x       491x               7x 5x   45x            
/**
 * Profiles for the three domains in AGeoP-21 Table B-1: Land, Maritime and Air. A profile picks
 * which grids are on when it is chosen, which readout columns and toolbar switches come first,
 * and which grids draw on top. Like the registry, this file may name systems.
 */
import { Array, Record, Schema, pipe } from 'effect'
 
import { formatters, grids } from './registry'
import type { Formatter, Grid } from './types'
 
export const ProfileId = Schema.Literals(['Land', 'Maritime', 'Air'])
export type ProfileId = typeof ProfileId.Type
 
export const DEFAULT_PROFILE: ProfileId = 'Land'
 
export interface Profile {
  readonly id: ProfileId
  readonly description: string
  /** Readout columns that come first, in this order; the rest keep registry order. */
  readonly leadingFormatterIds: ReadonlyArray<string>
  /** Toolbar switches that come first, in this order. These grids also draw on top, the first highest. */
  readonly leadingGridIds: ReadonlyArray<string>
  /** The grids that are on when the profile is chosen; every other grid is off. */
  readonly enabledGridIds: ReadonlyArray<string>
}
 
export const profiles: Record<ProfileId, Profile> = {
  // AGeoP-21 1.2.5: MGRS is the preferred position reporting system for ground forces.
  Land: {
    id: 'Land',
    description: 'MGRS and UTM first, with UTM zones and the MGRS grid',
    leadingFormatterIds: ['MGRS', 'UTM'],
    leadingGridIds: ['Mgrs', 'Gzd'],
    enabledGridIds: ['Graticule', 'Gzd', 'Mgrs'],
  },
  // AGeoP-21 B.6.6: nautical charts carry the military grid as edge ticks, not lines.
  Maritime: {
    id: 'Maritime',
    description:
      'Degrees and minutes and GARS first, with the chart grid and MGRS as edge ticks',
    leadingFormatterIds: ['DDM', 'GARS', 'MGRS'],
    leadingGridIds: ['Ddm', 'Gars', 'MgrsTicks'],
    enabledGridIds: ['Ddm', 'Gars', 'MgrsTicks'],
  },
  // AGeoP-21 B.7.2: GEOREF on aeronautical charts, GARS for deconfliction.
  Air: {
    id: 'Air',
    description: 'GEOREF and GARS first, with their grids and the graticule',
    leadingFormatterIds: ['GEOREF', 'GARS', 'MGRS', 'DDM'],
    leadingGridIds: ['Georef', 'Gars'],
    enabledGridIds: ['Graticule', 'Georef', 'Gars'],
  },
}
 
/** The items whose ids are listed first, in that order, then the rest in their own order. */
const leadingFirst = <A extends { readonly id: string }>(
  items: ReadonlyArray<A>,
  leadingIds: ReadonlyArray<string>,
): ReadonlyArray<A> => [
  ...Array.getSomes(
    Array.map(leadingIds, id => Array.findFirst(items, item => item.id === id)),
  ),
  ...Array.filter(items, item => !leadingIds.includes(item.id)),
]
 
/** Readout columns, left to right. */
export const formattersFor = (profileId: ProfileId): ReadonlyArray<Formatter> =>
  leadingFirst(formatters, profiles[profileId].leadingFormatterIds)
 
/** Toolbar switches, left to right. */
export const gridSwitchesFor = (profileId: ProfileId): ReadonlyArray<Grid> =>
  leadingFirst(grids, profiles[profileId].leadingGridIds)
 
/** Drawing order: the other grids in registry order, then the profile's grids with its first on top. */
export const gridDrawOrderFor = (profileId: ProfileId): ReadonlyArray<Grid> => {
  const { leadingGridIds } = profiles[profileId]
  return [
    ...Array.filter(grids, grid => !leadingGridIds.includes(grid.id)),
    ...Array.reverse(
      Array.getSomes(
        Array.map(leadingGridIds, id =>
          Array.findFirst(grids, grid => grid.id === id),
        ),
      ),
    ),
  ]
}
 
/** The toggle for every grid when the profile is chosen. */
export const gridTogglesFor = (profileId: ProfileId): Record<string, boolean> =>
  pipe(
    grids,
    Array.map((grid): readonly [string, boolean] => [
      grid.id,
      profiles[profileId].enabledGridIds.includes(grid.id),
    ]),
    Record.fromEntries,
  )