From 8e400af0c03cf5011edd5124b23751ca32230260 Mon Sep 17 00:00:00 2001 From: Abbe Keultjes Date: Fri, 22 Jul 2022 22:00:33 +0200 Subject: [PATCH] feat(grid/traversers): add repeatWith traverser It's very similar to branch() but has the option to omit the hexes from the source traverser. Also, the name is a little better (hopefully) --- src/grid/functions/index.ts | 1 + src/grid/functions/repeatWith.ts | 25 +++++++++++++++++++++++++ src/grid/traversers/rays.ts | 3 ++- src/grid/traversers/rectangle.ts | 4 ++-- src/grid/traversers/spiral.ts | 4 ++-- 5 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 src/grid/functions/repeatWith.ts diff --git a/src/grid/functions/index.ts b/src/grid/functions/index.ts index 0492f780..619f862d 100644 --- a/src/grid/functions/index.ts +++ b/src/grid/functions/index.ts @@ -3,3 +3,4 @@ export * from './concat' export * from './distance' export * from './neighborOf' export * from './repeat' +export * from './repeatWith' diff --git a/src/grid/functions/repeatWith.ts b/src/grid/functions/repeatWith.ts new file mode 100644 index 00000000..ac9ba65b --- /dev/null +++ b/src/grid/functions/repeatWith.ts @@ -0,0 +1,25 @@ +import { Hex } from '../../hex' +import { Traverser } from '../types' +import { concat } from './concat' + +// todo: use in rays (if it still has right to exist) +// todo: probably move repeatWith, repeat and concat to grid/traversers/ +export function repeatWith( + sources: Traverser | Traverser[], + targets: Traverser | Traverser[], + // todo: isn't there a more elegant way than a config? + { includeSource = true } = {}, +): Traverser { + return function repeatWithTraverser(createHex, cursor) { + const hexes: T[] = [] + + for (const sourceCursor of concat(sources)(createHex, cursor)) { + if (includeSource) hexes.push(sourceCursor) + for (const hex of concat(targets)(createHex, sourceCursor)) { + hexes.push(hex) + } + } + + return hexes + } +} diff --git a/src/grid/traversers/rays.ts b/src/grid/traversers/rays.ts index 9895ffcc..fd1b930e 100644 --- a/src/grid/traversers/rays.ts +++ b/src/grid/traversers/rays.ts @@ -4,8 +4,9 @@ import { line } from './line' import { ring } from './ring' // todo: +// - remove this file? If not: refactor to use repeatWith()? // - add option for arc in degrees? -// - add to docs that duplicate hexes are returned (or make this configurable? Or add transformer that dedupes?) +// - add to docs that duplicate hexes are returned (or make this configurable? Or add transducer that dedupes?) export function rays(options: RaysWithLengthOptions): Traverser export function rays(options: RaysToHexOptions): Traverser export function rays({ diff --git a/src/grid/traversers/rectangle.ts b/src/grid/traversers/rectangle.ts index 36e13491..3d6737bb 100644 --- a/src/grid/traversers/rectangle.ts +++ b/src/grid/traversers/rectangle.ts @@ -1,7 +1,7 @@ import { Compass, CompassDirection } from '../../compass' import { Hex, HexCoordinates, hexToOffset, OffsetCoordinates } from '../../hex' import { isOffset, isTuple, tupleToCube } from '../../utils' -import { branch } from '../functions' +import { repeatWith } from '../functions' import { Traverser } from '../types' import { line } from './line' @@ -25,7 +25,7 @@ export function rectangle( ? optionsFromOpposingCorners(optionsOrCornerA as HexCoordinates, cornerB, createHex()) : (optionsOrCornerA as RectangleOptions) const firstHex = createHex(start ?? cursor) - const hexes = branch( + const hexes = repeatWith( line({ start: firstHex, direction: Compass.rotate(direction, 2), length: height }), line({ direction, length: width - 1 }), )(createHex, firstHex) diff --git a/src/grid/traversers/spiral.ts b/src/grid/traversers/spiral.ts index e616bfd1..73cd0f89 100644 --- a/src/grid/traversers/spiral.ts +++ b/src/grid/traversers/spiral.ts @@ -1,6 +1,6 @@ import { CompassDirection } from '../../compass' import { Hex, HexCoordinates } from '../../hex' -import { branch } from '../functions' +import { repeatWith } from '../functions' import { RotationLike, Traverser } from '../types' import { line } from './line' import { ring } from './ring' @@ -8,7 +8,7 @@ import { ring } from './ring' export function spiral({ radius, start, rotation }: SpiralOptions): Traverser { return function spiralTraverser(createHex, cursor) { const center = createHex(start ?? cursor) - return branch(line({ start, direction: CompassDirection.N, length: radius }), ring({ center, rotation }))( + return repeatWith(line({ start, direction: CompassDirection.N, length: radius }), ring({ center, rotation }))( createHex, cursor, )