diff --git a/src/grid/functions/at.ts b/src/grid/functions/at.ts index ca4e0d51..104d3253 100644 --- a/src/grid/functions/at.ts +++ b/src/grid/functions/at.ts @@ -1,8 +1,8 @@ import { createHex, Hex, HexCoordinates } from '../../hex' -import { GridGeneratorFunction } from '../types' +import { Traverser } from '../types' -export const at = (coordinates: HexCoordinates): GridGeneratorFunction => - function* (currentHex) { +export const at = (coordinates: HexCoordinates): Traverser => + function* next(currentHex) { // todo: make createHex accept hex instances or use cloneHex()? yield createHex(Object.getPrototypeOf(currentHex), coordinates) } diff --git a/src/grid/functions/move.ts b/src/grid/functions/move.ts index 4864153c..6b135bdf 100644 --- a/src/grid/functions/move.ts +++ b/src/grid/functions/move.ts @@ -1,10 +1,10 @@ import { createHex, Hex } from '../../hex' import { DIRECTION_COORDINATES } from '../constants' -import { CompassDirection, GridGeneratorFunction } from '../types' +import { CompassDirection, Traverser } from '../types' // todo: also accept a string and/or number for direction -export const move = (direction: CompassDirection): GridGeneratorFunction => - function* (currentHex) { +export const move = (direction: CompassDirection): Traverser => + function* next(currentHex) { const { q, r } = DIRECTION_COORDINATES[direction] const nextCoordinates = { q: currentHex.q + q, r: currentHex.r + r } // todo: make createHex accept hex instances or use cloneHex()? diff --git a/src/grid/functions/repeat.ts b/src/grid/functions/repeat.ts index b2f4c2a9..3246c505 100644 --- a/src/grid/functions/repeat.ts +++ b/src/grid/functions/repeat.ts @@ -1,9 +1,9 @@ import { Hex } from '../../hex' -import { GridGeneratorFunction } from '../types' +import { Traverser } from '../types' // todo: looks a lot like Grid.traverse() -export const repeat = (amount: number, command: GridGeneratorFunction): GridGeneratorFunction => - function* (currentHex) { +export const repeat = (amount: number, command: Traverser): Traverser => + function* next(currentHex) { let nextHex = currentHex for (let i = 0; i < amount; i++) { const hexes = command(nextHex) diff --git a/src/grid/grid.ts b/src/grid/grid.ts index 16f7b2f5..38e4fe71 100644 --- a/src/grid/grid.ts +++ b/src/grid/grid.ts @@ -1,21 +1,24 @@ import { equals, Hex, HexCoordinates } from '../hex' import { rectangle, RectangleOptions } from './functions' -import { GridGenerator, GridGeneratorFunction } from './types' +import { GridGenerator, Traverser } from './types' + +interface InternalTraverser { + (this: Grid): GridGenerator +} // eslint-disable-next-line @typescript-eslint/no-empty-function function* infiniteTraverser(): GridGenerator {} // fixme: there's a lot of duplicate iteration, use a cache (or memoisation?) export class Grid { - static of(hexPrototype: T, traverser?: GridGeneratorFunction) { + static of(hexPrototype: T, traverser?: InternalTraverser) { return new Grid(hexPrototype, traverser) } - constructor(public hexPrototype: T, private traverser: GridGeneratorFunction = infiniteTraverser) {} + constructor(public hexPrototype: T, private traverser: InternalTraverser = infiniteTraverser) {} [Symbol.iterator]() { - // todo: {} as T is a bit hacky, but making it an optional parameter is meh - return this.traverser({} as T) + return this.traverser() } has(coordinates: HexCoordinates) { @@ -31,7 +34,6 @@ export class Grid { } clone(traverser = this.traverser) { - // todo: maybe not bind and pass grid to traverser? Tried this, but it results in a "Maximum call stack size exceeded" error return Grid.of(this.hexPrototype, traverser.bind(this)) } @@ -40,33 +42,28 @@ export class Grid { return this.clone(() => rectangle(this.hexPrototype, options)) } - // inspired by https://github.com/ReactiveX/rxjs/blob/master/src/internal/util/pipe.ts - // pipe(...fns: GridOperator[]): Grid { - // return ((grid: Grid) => fns.reduce((prev, fn) => fn(prev), grid))(this) - // } - // fixme: use generic functions for these kinds of operations // something like https://github.com/benji6/imlazy or https://github.com/lodash/lodash/wiki/FP-Guide each(fn: (hex: T) => void) { - const traverser = function* (this: Grid) { + const each: InternalTraverser = function* () { for (const hex of this) { fn(hex) yield hex } } - return this.clone(traverser) + return this.clone(each) } map(fn: (hex: T) => T) { - const traverser = function* (this: Grid) { + const map: InternalTraverser = function* () { for (const hex of this) { yield fn(hex) } } - return this.clone(traverser) + return this.clone(map) } - // todo: other/more args? + // todo: alias to take or takeUntil? run(stopFn: (hex: T) => boolean = () => false) { for (const hex of this) { if (stopFn(hex)) { @@ -76,14 +73,13 @@ export class Grid { return this // or clone()? todo: when to return clone and when not? } - traverse(...commands: GridGeneratorFunction[]) { + traverse(...commands: Traverser[]) { if (commands.length === 0) { return this // or clone()? todo: when to return clone and when not? } - // todo: {} as T is a bit hacky, but making it an optional parameter is meh - let currentHex = this.traverser({} as T).next().value || ({ q: 0, r: 0 } as T) + let currentHex = this.traverser().next().value || ({ q: 0, r: 0 } as T) - const traverser = function* (this: Grid) { + function* traverse(this: Grid) { for (const command of commands) { const hexes = command(currentHex) for (const hex of hexes) { @@ -96,6 +92,6 @@ export class Grid { } } } - return this.clone(traverser) + return this.clone(traverse) } } diff --git a/src/grid/types.ts b/src/grid/types.ts index befea274..9db14a37 100644 --- a/src/grid/types.ts +++ b/src/grid/types.ts @@ -22,6 +22,6 @@ export type CompassDirection = PointyCompassDirection | FlatCompassDirection export type GridGenerator = Generator -export interface GridGeneratorFunction { +export interface Traverser { (currentHex: T): GridGenerator }