116 lines
3.3 KiB
TypeScript
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,
|
|
);
|
|
}
|
|
}
|