Re-structure pieces builder and add include first pieces batch

pull/7/head
MiguelMLorente 2024-12-01 12:30:59 +01:00
parent 7354586ef5
commit 406e4d2f75
8 changed files with 273 additions and 46 deletions

View File

@ -13,5 +13,7 @@ module.exports = {
jest: true,
},
ignorePatterns: [".eslintrc.js", "dist/"],
rules: {},
rules: {
"@typescript-eslint/no-non-null-assertion": "off",
},
};

View File

@ -0,0 +1,4 @@
export enum InternalNodeType {
NONE = "NONE",
STATION = "STATION",
}

View File

@ -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, Piece> = {
[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,
};

View File

@ -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!;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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 Track = {
readonly joinedPoints: {
readonly firstPoint: Direction;
readonly secondPoint: Direction | InternalNode;
};
type: TrackType;
}>;
internalNodes: Set<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<Track>;
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(
trackDefinitions.map((track) => {
if (!track.isInternal && !track.endPoint) {
throw Error("Missing direction for non-internal track");
}
pieceProps.trackDefinitions.map((trackDefinition) => {
return {
joinedPoints: {
firstPoint: track.startPoint,
secondPoint: track.isInternal
? internalNode
: (track.endPoint as Direction),
firstPoint: trackDefinition.startPoint,
secondPoint: this.internalNode!,
},
type: track.type,
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,
};
}),
);
}
}
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,
);
}

View File

@ -11,7 +11,7 @@ export class PlacedPiece {
};
type: TrackType;
}>;
internalNodes: Set<InternalNode>;
internalNode?: InternalNode;
cell: Cell;
constructor(
@ -19,11 +19,11 @@ export class PlacedPiece {
nodes: { firstNode: Node; secondNode: Node };
type: TrackType;
}>,
internalNodes: Set<InternalNode>,
internalNodes: InternalNode | undefined,
cell: Cell,
) {
this.tracks = tracks;
this.internalNodes = internalNodes;
this.internalNode = internalNodes;
this.cell = cell;
}
}