From 6fab2d94a098674cff1156714601412110b069d2 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Sun, 1 Dec 2024 12:30:59 +0100 Subject: [PATCH] Re-structure pieces builder and add include first pieces batch --- interface/.eslintrc.js | 4 +- interface/constants/InternalNodeType.ts | 4 + interface/constants/Pieces.ts | 200 ++++++++++++++++++++++++ interface/types/Cell.ts | 2 +- interface/types/ExternalNode.ts | 2 +- interface/types/InternalNode.ts | 7 +- interface/types/Piece.ts | 94 ++++++----- interface/types/PlacedPiece.ts | 6 +- 8 files changed, 273 insertions(+), 46 deletions(-) create mode 100644 interface/constants/InternalNodeType.ts create mode 100644 interface/constants/Pieces.ts diff --git a/interface/.eslintrc.js b/interface/.eslintrc.js index 9700d32..5b53304 100644 --- a/interface/.eslintrc.js +++ b/interface/.eslintrc.js @@ -13,5 +13,7 @@ module.exports = { jest: true, }, ignorePatterns: [".eslintrc.js", "dist/"], - rules: {}, + rules: { + "@typescript-eslint/no-non-null-assertion": "off", + }, }; diff --git a/interface/constants/InternalNodeType.ts b/interface/constants/InternalNodeType.ts new file mode 100644 index 0000000..708179d --- /dev/null +++ b/interface/constants/InternalNodeType.ts @@ -0,0 +1,4 @@ +export enum InternalNodeType { + NONE = "NONE", + STATION = "STATION", +} diff --git a/interface/constants/Pieces.ts b/interface/constants/Pieces.ts new file mode 100644 index 0000000..2eb8c2e --- /dev/null +++ b/interface/constants/Pieces.ts @@ -0,0 +1,200 @@ +import { Piece } from "../types/Piece"; +import { Direction } from "./Direction"; +import { InternalNodeType } from "./InternalNodeType"; +import { TrackType } from "./TrackType"; + +const STRAIGHT_RAIL: Piece = new Piece({ + useInternalTracks: false, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + endPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + ], +}); + +const TURN_RAIL: Piece = new Piece({ + useInternalTracks: false, + trackDefinitions: [ + { + startPoint: Direction.SOUTH, + endPoint: Direction.EAST, + type: TrackType.RAIL, + }, + ], +}); +const FOUR_WAY_CROSS_RAIL: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.NONE, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.RAIL, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + ], +}); +const T_JUNCTION_RAIL: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.NONE, + trackDefinitions: [ + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.RAIL, + }, + ], +}); +const DEAD_END_STATION_RAIL: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + ], +}); +const TURN_RAIL_TO_ROAD: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + ], +}); +const T_JUNCTION_WITH_ROAD_ON_SIDE: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + ], +}); +const FOUR_WAY_WITH_ONE_ROAD: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + ], +}); +const T_JUNCTION_WITH_ROAD_AT_CENTER: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.NORTH, + type: TrackType.RAIL, + }, + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.SOUTH, + type: TrackType.RAIL, + }, + ], +}); +const STRAIGHT_TRACK_CHANGE: Piece = new Piece({ + useInternalTracks: true, + internalNodeType: InternalNodeType.STATION, + trackDefinitions: [ + { + startPoint: Direction.EAST, + type: TrackType.ROAD, + }, + { + startPoint: Direction.WEST, + type: TrackType.RAIL, + }, + ], +}); + +export enum PieceId { + P01 = "P01", + P02 = "P02", + P03 = "P03", + P04 = "P04", + P05 = "P05", + P06 = "P06", + P07 = "P07", + P08 = "P08", + P09 = "P09", + P10 = "P10", + P11 = "P11", + P12 = "P12", + P13 = "P13", + P14 = "P14", + P15 = "P15", + P16 = "P16", + P17 = "P17", + P18 = "P18", + P19 = "P19", + P20 = "P20", + P21 = "P21", + P22 = "P22", +} + +export const pieceMap: Record = { + [PieceId.P01]: STRAIGHT_RAIL, + [PieceId.P02]: TURN_RAIL, + [PieceId.P03]: FOUR_WAY_CROSS_RAIL, + [PieceId.P04]: T_JUNCTION_RAIL, + [PieceId.P05]: DEAD_END_STATION_RAIL, + [PieceId.P06]: TURN_RAIL_TO_ROAD, + [PieceId.P07]: T_JUNCTION_WITH_ROAD_ON_SIDE, + [PieceId.P08]: FOUR_WAY_WITH_ONE_ROAD, + [PieceId.P09]: T_JUNCTION_WITH_ROAD_AT_CENTER, + [PieceId.P10]: STRAIGHT_TRACK_CHANGE, +}; diff --git a/interface/types/Cell.ts b/interface/types/Cell.ts index 822ce34..8dc8236 100644 --- a/interface/types/Cell.ts +++ b/interface/types/Cell.ts @@ -19,6 +19,6 @@ export class Cell { public getNodeAt(direction: Direction): ExternalNode { const node = this.externalNodes.get(direction); if (!node) throw Error(`Could not find node at ${direction}`); - return this.externalNodes.get(direction) as ExternalNode; + return node!; } } diff --git a/interface/types/ExternalNode.ts b/interface/types/ExternalNode.ts index 78447d3..f23d312 100644 --- a/interface/types/ExternalNode.ts +++ b/interface/types/ExternalNode.ts @@ -24,6 +24,6 @@ export class ExternalNode { if (!this.border) { throw Error(`Missing border for node`); } - return (this.border as Border).traverseFrom(this); + return this.border.traverseFrom(this); } } diff --git a/interface/types/InternalNode.ts b/interface/types/InternalNode.ts index e60434b..f4826d6 100644 --- a/interface/types/InternalNode.ts +++ b/interface/types/InternalNode.ts @@ -1,11 +1,12 @@ import { randomUUID } from "crypto"; +import { InternalNodeType } from "../constants/InternalNodeType"; export class InternalNode { id: string; - type: string; + type: InternalNodeType; - constructor() { + constructor(type: InternalNodeType) { this.id = randomUUID(); - this.type = "STATION"; + this.type = type; } } diff --git a/interface/types/Piece.ts b/interface/types/Piece.ts index a1de677..dae249a 100644 --- a/interface/types/Piece.ts +++ b/interface/types/Piece.ts @@ -4,46 +4,66 @@ import { Cell } from "./Cell"; import { InternalNode } from "./InternalNode"; import { PlacedPiece } from "./PlacedPiece"; import { Node } from "./Node"; +import { InternalNodeType } from "../constants/InternalNodeType"; -export interface TrackProps { - startPoint: Direction; - endPoint?: Direction; - isInternal: boolean; - type: TrackType; +export interface PieceProps { + readonly useInternalTracks: boolean; + readonly internalNodeType?: InternalNodeType; + readonly trackDefinitions: { + readonly startPoint: Direction; + readonly endPoint?: Direction; + readonly type: TrackType; + }[]; } -export class Piece { - tracks: Set<{ - joinedPoints: { - firstPoint: Direction; - secondPoint: Direction | InternalNode; - }; - type: TrackType; - }>; - internalNodes: Set; +type Track = { + readonly joinedPoints: { + readonly firstPoint: Direction; + readonly secondPoint: Direction | InternalNode; + }; + readonly type: TrackType; +}; - constructor(hasInternalNode: boolean, trackDefinitions: TrackProps[]) { - const internalNode = new InternalNode(); - this.internalNodes = new Set(); - if (hasInternalNode) { - this.internalNodes.add(internalNode); +export class Piece { + readonly tracks: Set; + readonly internalNode?: InternalNode; + + constructor(pieceProps: PieceProps) { + if (pieceProps.useInternalTracks) { + if (!pieceProps.internalNodeType) { + throw Error( + "Expected to find internal node type when useInternalTracks is set", + ); + } + this.internalNode = new InternalNode(pieceProps.internalNodeType); + this.tracks = new Set( + pieceProps.trackDefinitions.map((trackDefinition) => { + return { + joinedPoints: { + firstPoint: trackDefinition.startPoint, + secondPoint: this.internalNode!, + }, + type: trackDefinition.type, + }; + }), + ); + } else { + this.internalNode = undefined; + this.tracks = new Set( + pieceProps.trackDefinitions.map((trackDefinition) => { + if (!trackDefinition.endPoint) { + throw Error("Missing end point for non-internal track"); + } + return { + joinedPoints: { + firstPoint: trackDefinition.startPoint, + secondPoint: trackDefinition.endPoint, + }, + type: trackDefinition.type, + }; + }), + ); } - this.tracks = new Set( - trackDefinitions.map((track) => { - if (!track.isInternal && !track.endPoint) { - throw Error("Missing direction for non-internal track"); - } - return { - joinedPoints: { - firstPoint: track.startPoint, - secondPoint: track.isInternal - ? internalNode - : (track.endPoint as Direction), - }, - type: track.type, - }; - }), - ); } toPlacedPiece(cell: Cell) { @@ -55,14 +75,14 @@ export class Piece { firstNode: cell.getNodeAt(track.joinedPoints.firstPoint), secondNode: track.joinedPoints.secondPoint instanceof Node - ? track.joinedPoints.secondPoint as Node + ? (track.joinedPoints.secondPoint as Node) : cell.getNodeAt(track.joinedPoints.secondPoint as Direction), }, type: track.type, }; }), ), - this.internalNodes, + this.internalNode, cell, ); } diff --git a/interface/types/PlacedPiece.ts b/interface/types/PlacedPiece.ts index e1e83b5..7582a42 100644 --- a/interface/types/PlacedPiece.ts +++ b/interface/types/PlacedPiece.ts @@ -11,7 +11,7 @@ export class PlacedPiece { }; type: TrackType; }>; - internalNodes: Set; + internalNode?: InternalNode; cell: Cell; constructor( @@ -19,11 +19,11 @@ export class PlacedPiece { nodes: { firstNode: Node; secondNode: Node }; type: TrackType; }>, - internalNodes: Set, + internalNodes: InternalNode | undefined, cell: Cell, ) { this.tracks = tracks; - this.internalNodes = internalNodes; + this.internalNode = internalNodes; this.cell = cell; } }