Skip to content

Commit

Permalink
feat(hex): the equals() function and hex method can now compare diffe…
Browse files Browse the repository at this point in the history
…rent kinds of hex coordinates

equals() no longer requires both parameters to be the same kind of hex coordinates (axial or offset)
  • Loading branch information
flauwekeul committed Apr 24, 2021
1 parent ca41673 commit 5dc14d0
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 30 deletions.
18 changes: 10 additions & 8 deletions src/hex/functions/createHexPrototype.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { Ellipse } from '../../../dist'
import { BoundingBox, HexCoordinates, HexPrototype, Orientation } from '../types'
import { BoundingBox, Hex, HexPrototype, Orientation } from '../types'
import { cloneHex } from './cloneHex'
import { corners } from './corners'
import { createHex } from './createHex'
import { createHexPrototype } from './createHexPrototype'
import { equals } from './equals'

jest.mock('./cloneHex')
jest.mock('./corners')
jest.mock('./equals')

test('returns the default hex prototype when no options are passed', () => {
const prototype = createHexPrototype()
Expand Down Expand Up @@ -146,12 +144,16 @@ test('returns the hex prototype with corners getter', () => {
expect(corners).toBeCalledWith(prototype)
})

test('returns the hex prototype with equals method', () => {
const prototype = createHexPrototype()
const coordinates: HexCoordinates = { q: 1, r: 2 }
prototype.equals(coordinates)
describe('equals()', () => {
test('returns the hex prototype with equals method', () => {
const prototype = createHexPrototype()
expect(prototype.equals.call({ q: 1, r: 2 } as Hex, { q: 1, r: 2 })).toBe(true)
})

expect(equals).toBeCalledWith(prototype, coordinates)
test('accepts offset coordinates', () => {
const prototype = createHexPrototype()
expect(prototype.equals.call({ q: 1, r: 2 } as Hex, { col: 1, row: 2 })).toBe(true)
})
})

test('returns the hex prototype with toString method', () => {
Expand Down
5 changes: 3 additions & 2 deletions src/hex/functions/createHexPrototype.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isFunction, isObject, isPoint } from '../../utils'
import { isFunction, isObject, isOffset, isPoint } from '../../utils'
import { BoundingBox, Ellipse, Hex, HexPrototype, HexSettings, Orientation, Point } from '../types'
import { center } from './center'
import { cloneHex } from './cloneHex'
Expand All @@ -9,6 +9,7 @@ import { hexToOffset } from './hexToOffset'
import { hexToPoint } from './hexToPoint'
import { isFlat } from './isFlat'
import { isPointy } from './isPointy'
import { offsetToCube } from './offsetToCube'
import { toString } from './toString'
import { width } from './width'

Expand All @@ -31,7 +32,7 @@ export const createHexPrototype = <T extends Hex>(
return cloneHex(this, newProps)
},
equals(coordinates) {
return equals(this, coordinates)
return equals(this, isOffset(coordinates) ? offsetToCube(coordinates, this) : coordinates)
},
toString() {
return toString(this)
Expand Down
14 changes: 14 additions & 0 deletions src/hex/functions/equals.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
import { equals } from './equals'

test('returns whether the 2 passed offset coordinates are the same', () => {
expect(equals({ col: 1, row: 2 }, { col: 1, row: 2 })).toBe(true)
expect(equals({ col: 1, row: 2 }, { col: 3, row: 4 })).toBe(false)
})

test('throws when offset coordinates and non-offset coordinates are passed', () => {
expect(() => equals({ col: 1, row: 2 }, { q: 1, r: 2 } as never)).toThrowError(
`Can't compare coordinates where one are offset coordinates. Either pass two offset coordinates or two axial/cube coordinates. Received: {"col":1,"row":2} and {"q":1,"r":2}`,
)
})

test('returns whether the 2 passed axial coordinates are the same', () => {
expect(equals({ q: 1, r: 2 }, { q: 1, r: 2 })).toBe(true)
expect(equals({ q: 1, r: 2 }, { q: 3, r: 4 })).toBe(false)

expect(equals([1, 2], [1, 2])).toBe(true)
expect(equals([1, 2], [3, 4])).toBe(false)
})
42 changes: 22 additions & 20 deletions src/hex/functions/equals.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { isAxial, isTuple } from '../../utils'
import { AxialCoordinates, HexCoordinates, OffsetCoordinates, TupleCoordinates } from '../types'
import { isOffset, isTuple, tupleToCube } from '../../utils'
import { CubeCoordinates, HexCoordinates, OffsetCoordinates } from '../types'

// todo: a and b shouldn't have to be the same kind of coordinates
export const equals = (a: HexCoordinates, b: HexCoordinates) =>
// when the 2nd coordinates is axial, assume the first is too
// when equals() is used as a hex method, the 1st coordinates is that of the hex itself which is always axial
isAxial(b)
? equalsAxial(a as AxialCoordinates, b)
: isTuple(a)
? equalsTuple(a, b as TupleCoordinates)
: equalsOffset(a as OffsetCoordinates, b as OffsetCoordinates)
export function equals(
a: Exclude<HexCoordinates, OffsetCoordinates>,
b: Exclude<HexCoordinates, OffsetCoordinates>,
): boolean
export function equals(a: OffsetCoordinates, b: OffsetCoordinates): boolean
export function equals(a: HexCoordinates, b: HexCoordinates) {
if (isOffset(a) && isOffset(b)) {
return a.col === b.col && a.row === b.row
}

function equalsAxial(a: AxialCoordinates, b: AxialCoordinates) {
return a.q === b.q && a.r === b.r
}

function equalsOffset(a: OffsetCoordinates, b: OffsetCoordinates) {
return a.col === b.col && a.row === b.row
}
// can't use isOffset() because that also checks in the prototype chain and that would always return true for hexes
if (Object.prototype.hasOwnProperty.call(a, 'col') || Object.prototype.hasOwnProperty.call(b, 'col')) {
throw new Error(
`Can't compare coordinates where one are offset coordinates. Either pass two offset coordinates or two axial/cube coordinates. Received: ${JSON.stringify(
a,
)} and ${JSON.stringify(b)}`,
)
}

function equalsTuple(a: TupleCoordinates, b: TupleCoordinates) {
return a[0] === b[0] && a[1] === b[1]
const cubeA = (isTuple(a) ? tupleToCube(a) : a) as CubeCoordinates
const cubeB = (isTuple(b) ? tupleToCube(b) : b) as CubeCoordinates
return cubeA.q === cubeB.q && cubeA.r === cubeB.r
}

0 comments on commit 5dc14d0

Please sign in to comment.