TrainsAndRoads/interface/types/Piece.ts

116 lines
3.3 KiB
TypeScript

import { Direction, rotateDirection } from "../constants/Direction";
import { TrackType } from "../constants/TrackType";
import { Cell } from "./Cell";
import { InternalNode } from "./InternalNode";
import { PlacedPiece } from "./PlacedPiece";
import { InternalNodeType } from "../constants/InternalNodeType";
export interface PieceProps {
readonly useInternalTracks: boolean;
readonly internalNodeType?: InternalNodeType;
readonly trackDefinitions: {
readonly startPoint: Direction;
readonly endPoint?: Direction;
readonly type: TrackType;
}[];
}
type Track = {
readonly joinedPoints: {
readonly firstPoint: Direction;
readonly secondPoint: Direction | InternalNode;
};
readonly type: TrackType;
};
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(
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,
};
}),
);
}
}
rotate(rotation: 0 | 90 | 180 | 270): Piece {
return new Piece({
useInternalTracks: this.internalNode !== undefined,
internalNodeType: this.internalNode?.type,
trackDefinitions: Array.from(this.tracks).map((track) => {
if (track.joinedPoints.secondPoint instanceof InternalNode) {
return {
type: track.type,
startPoint: rotateDirection(
track.joinedPoints.firstPoint,
rotation,
),
};
} else {
return {
type: track.type,
startPoint: rotateDirection(
track.joinedPoints.firstPoint,
rotation,
),
endPoint: rotateDirection(track.joinedPoints.secondPoint, rotation),
};
}
}),
});
}
toPlacedPiece(cell: Cell) {
return new PlacedPiece(
new Set(
Array.from(this.tracks).map((track) => {
return {
nodes: {
firstNode: cell.getNodeAt(track.joinedPoints.firstPoint),
secondNode:
track.joinedPoints.secondPoint instanceof InternalNode
? (track.joinedPoints.secondPoint as InternalNode)
: cell.getNodeAt(track.joinedPoints.secondPoint as Direction),
},
type: track.type,
};
}),
),
this.internalNode,
cell,
);
}
}