Re-structure pieces builder and add include first pieces batch
parent
7354586ef5
commit
406e4d2f75
|
|
@ -13,5 +13,7 @@ module.exports = {
|
||||||
jest: true,
|
jest: true,
|
||||||
},
|
},
|
||||||
ignorePatterns: [".eslintrc.js", "dist/"],
|
ignorePatterns: [".eslintrc.js", "dist/"],
|
||||||
rules: {},
|
rules: {
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum InternalNodeType {
|
||||||
|
NONE = "NONE",
|
||||||
|
STATION = "STATION",
|
||||||
|
}
|
||||||
|
|
@ -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,
|
||||||
|
};
|
||||||
|
|
@ -19,6 +19,6 @@ export class Cell {
|
||||||
public getNodeAt(direction: Direction): ExternalNode {
|
public getNodeAt(direction: Direction): ExternalNode {
|
||||||
const node = this.externalNodes.get(direction);
|
const node = this.externalNodes.get(direction);
|
||||||
if (!node) throw Error(`Could not find node at ${direction}`);
|
if (!node) throw Error(`Could not find node at ${direction}`);
|
||||||
return this.externalNodes.get(direction) as ExternalNode;
|
return node!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,6 @@ export class ExternalNode {
|
||||||
if (!this.border) {
|
if (!this.border) {
|
||||||
throw Error(`Missing border for node`);
|
throw Error(`Missing border for node`);
|
||||||
}
|
}
|
||||||
return (this.border as Border).traverseFrom(this);
|
return this.border.traverseFrom(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import { randomUUID } from "crypto";
|
import { randomUUID } from "crypto";
|
||||||
|
import { InternalNodeType } from "../constants/InternalNodeType";
|
||||||
|
|
||||||
export class InternalNode {
|
export class InternalNode {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
type: InternalNodeType;
|
||||||
|
|
||||||
constructor() {
|
constructor(type: InternalNodeType) {
|
||||||
this.id = randomUUID();
|
this.id = randomUUID();
|
||||||
this.type = "STATION";
|
this.type = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,46 +4,66 @@ import { Cell } from "./Cell";
|
||||||
import { InternalNode } from "./InternalNode";
|
import { InternalNode } from "./InternalNode";
|
||||||
import { PlacedPiece } from "./PlacedPiece";
|
import { PlacedPiece } from "./PlacedPiece";
|
||||||
import { Node } from "./Node";
|
import { Node } from "./Node";
|
||||||
|
import { InternalNodeType } from "../constants/InternalNodeType";
|
||||||
|
|
||||||
export interface TrackProps {
|
export interface PieceProps {
|
||||||
startPoint: Direction;
|
readonly useInternalTracks: boolean;
|
||||||
endPoint?: Direction;
|
readonly internalNodeType?: InternalNodeType;
|
||||||
isInternal: boolean;
|
readonly trackDefinitions: {
|
||||||
type: TrackType;
|
readonly startPoint: Direction;
|
||||||
|
readonly endPoint?: Direction;
|
||||||
|
readonly type: TrackType;
|
||||||
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Piece {
|
type Track = {
|
||||||
tracks: Set<{
|
readonly joinedPoints: {
|
||||||
joinedPoints: {
|
readonly firstPoint: Direction;
|
||||||
firstPoint: Direction;
|
readonly secondPoint: Direction | InternalNode;
|
||||||
secondPoint: Direction | InternalNode;
|
|
||||||
};
|
};
|
||||||
type: TrackType;
|
readonly type: TrackType;
|
||||||
}>;
|
};
|
||||||
internalNodes: Set<InternalNode>;
|
|
||||||
|
|
||||||
constructor(hasInternalNode: boolean, trackDefinitions: TrackProps[]) {
|
export class Piece {
|
||||||
const internalNode = new InternalNode();
|
readonly tracks: Set<Track>;
|
||||||
this.internalNodes = new Set();
|
readonly internalNode?: InternalNode;
|
||||||
if (hasInternalNode) {
|
|
||||||
this.internalNodes.add(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(
|
this.tracks = new Set(
|
||||||
trackDefinitions.map((track) => {
|
pieceProps.trackDefinitions.map((trackDefinition) => {
|
||||||
if (!track.isInternal && !track.endPoint) {
|
|
||||||
throw Error("Missing direction for non-internal track");
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
joinedPoints: {
|
joinedPoints: {
|
||||||
firstPoint: track.startPoint,
|
firstPoint: trackDefinition.startPoint,
|
||||||
secondPoint: track.isInternal
|
secondPoint: this.internalNode!,
|
||||||
? internalNode
|
|
||||||
: (track.endPoint as Direction),
|
|
||||||
},
|
},
|
||||||
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) {
|
toPlacedPiece(cell: Cell) {
|
||||||
|
|
@ -55,14 +75,14 @@ export class Piece {
|
||||||
firstNode: cell.getNodeAt(track.joinedPoints.firstPoint),
|
firstNode: cell.getNodeAt(track.joinedPoints.firstPoint),
|
||||||
secondNode:
|
secondNode:
|
||||||
track.joinedPoints.secondPoint instanceof Node
|
track.joinedPoints.secondPoint instanceof Node
|
||||||
? track.joinedPoints.secondPoint as Node
|
? (track.joinedPoints.secondPoint as Node)
|
||||||
: cell.getNodeAt(track.joinedPoints.secondPoint as Direction),
|
: cell.getNodeAt(track.joinedPoints.secondPoint as Direction),
|
||||||
},
|
},
|
||||||
type: track.type,
|
type: track.type,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
this.internalNodes,
|
this.internalNode,
|
||||||
cell,
|
cell,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ export class PlacedPiece {
|
||||||
};
|
};
|
||||||
type: TrackType;
|
type: TrackType;
|
||||||
}>;
|
}>;
|
||||||
internalNodes: Set<InternalNode>;
|
internalNode?: InternalNode;
|
||||||
cell: Cell;
|
cell: Cell;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -19,11 +19,11 @@ export class PlacedPiece {
|
||||||
nodes: { firstNode: Node; secondNode: Node };
|
nodes: { firstNode: Node; secondNode: Node };
|
||||||
type: TrackType;
|
type: TrackType;
|
||||||
}>,
|
}>,
|
||||||
internalNodes: Set<InternalNode>,
|
internalNodes: InternalNode | undefined,
|
||||||
cell: Cell,
|
cell: Cell,
|
||||||
) {
|
) {
|
||||||
this.tracks = tracks;
|
this.tracks = tracks;
|
||||||
this.internalNodes = internalNodes;
|
this.internalNode = internalNodes;
|
||||||
this.cell = cell;
|
this.cell = cell;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue