Skip to content

Commit f3d12e0

Browse files
committed
Start new API for specifying nodes
Docs aren't updated yet
1 parent 27f4c77 commit f3d12e0

File tree

15 files changed

+733
-336
lines changed

15 files changed

+733
-336
lines changed

src/Building.test.ts

Lines changed: 340 additions & 143 deletions
Large diffs are not rendered by default.

src/Building.ts

Lines changed: 35 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import { Hallway } from "./Hallway";
2-
import { Room } from "./Room";
3-
import { getGraph, getShortestPath, isConnectedGraph } from "./graph";
2+
import { ForkableRoom } from "./ForkableRoom";
3+
import {
4+
getShortestPath,
5+
isConnectedGraph,
6+
isConnectionStairs,
7+
getGraph,
8+
} from "./graph";
49
import { isLeftOrRight } from "./Direction";
10+
import { ForkNode } from "./ForkNode";
11+
import { StairNode } from "./StairNode";
512

613
/**
714
* @ignore
@@ -51,7 +58,10 @@ function format(str: string, { capitalize = true, periods = false }) {
5158
* Continue, then turn left into room C
5259
* ```
5360
*/
54-
export class Building {
61+
export class Building<
62+
ForkName extends string = string,
63+
StairName extends string = string
64+
> {
5565
/**
5666
* The graph that is generated from the nodes in the [[hallways]] and the
5767
* [[hallwayConnections]] and [[stairConnections]] between them
@@ -72,18 +82,14 @@ export class Building {
7282
* in the building. Each connection is an array of node IDs that starts at the
7383
* bottom floor and goes to the top floor.
7484
*/
75-
constructor(
76-
readonly hallways: Hallway[],
77-
readonly hallwayConnections: [string, string][] = [],
78-
readonly stairConnections: string[][] = []
79-
) {
85+
constructor(readonly hallways: Hallway<ForkName, StairName>[]) {
8086
const hallwayNodes = this.hallways.map(h => {
8187
return h.nodes;
8288
});
83-
this.graph = getGraph(hallwayNodes, stairConnections, hallwayConnections);
89+
this.graph = getGraph(hallwayNodes);
8490
this.roomsList = hallways
8591
.flatMap(h => h.partList)
86-
.filter((a): a is Room => "name" in a && a.name != null)
92+
.filter((a): a is ForkableRoom<ForkName> => "name" in a && a.name != null)
8793
.flatMap(r => r.aliases.concat(r.name!))
8894
.sort();
8995
}
@@ -107,39 +113,25 @@ export class Building {
107113
* is the index of the hallway where the node is located, and
108114
* the second element is the index of the node in the hallway
109115
*/
110-
protected getHallwayIndexAndIndexFromNode(nodeId: string): [number, number] {
116+
protected getHallwayIndexAndIndexFromNode(
117+
nodeId: ForkNode<ForkName> | StairNode<StairName>
118+
): [number, number] {
111119
const inds = this.hallways.map(h =>
112-
h.partList.findIndex(r => "nodeId" in r && r.nodeId === nodeId)
120+
h.partList.findIndex(
121+
r =>
122+
"nodeId" in r && JSON.stringify(r.nodeId) === JSON.stringify(nodeId)
123+
)
113124
);
114125
const hallwayInd = inds.findIndex(a => a !== -1);
115126
return [hallwayInd, inds[hallwayInd]];
116127
}
117128

118-
/**
119-
* @param id1
120-
* @param id2
121-
* @return Is the connection between these two nodes
122-
* a Stairs connection? (as opposed to a Fork)
123-
*/
124-
protected isConnectionStairs(id1: string, id2: string): boolean {
125-
return (
126-
this.stairConnections.findIndex(
127-
arr => arr.includes(id1) && arr.includes(id2)
128-
) != -1
129-
);
130-
}
131-
132129
protected getStairConnectionInstruction(
133-
id1: string,
134-
id2: string,
130+
id1: StairNode<StairName>,
131+
id2: StairNode<StairName>,
135132
numFlights: number
136133
): string {
137-
const goingUp = this.stairConnections.find(
138-
arr =>
139-
arr.includes(id1) &&
140-
arr.includes(id2) &&
141-
arr.indexOf(id2) > arr.indexOf(id1)
142-
);
134+
const goingUp = id2.floor > id1.floor;
143135
const maybeS = numFlights > 1 ? "s" : "";
144136
return `go ${
145137
goingUp ? "up" : "down"
@@ -208,12 +200,7 @@ export class Building {
208200
const [prevHallwayInd, prevInd] = this.getHallwayIndexAndIndexFromNode(
209201
shortest[i - 1]
210202
);
211-
if (
212-
this.isConnectionStairs(
213-
shortest[i - 1],
214-
shortest[i]
215-
) /* going up or down stairs */
216-
) {
203+
if (isConnectionStairs(shortest[i]) /* going up or down stairs */) {
217204
directions += this.hallways[currentHallwayInd].getDirectionsFromIndices(
218205
currentInd,
219206
prevInd,
@@ -223,12 +210,13 @@ export class Building {
223210
entranceWasStraight,
224211
}
225212
);
226-
const numStairFlights = Math.ceil(
227-
this.graph[shortest[i - 1]][shortest[i]]
213+
const numStairFlights = Math.abs(
214+
(shortest[i - 1] as StairNode<StairName>).floor -
215+
(shortest[i] as StairNode<StairName>).floor
228216
);
229217
directions += this.getStairConnectionInstruction(
230-
shortest[i - 1],
231-
shortest[i],
218+
shortest[i - 1] as StairNode<StairName>,
219+
shortest[i] as StairNode<StairName>,
232220
numStairFlights
233221
);
234222
[currentHallwayInd, currentInd] = this.getHallwayIndexAndIndexFromNode(
@@ -246,7 +234,9 @@ export class Building {
246234
}
247235
);
248236
entranceWasStraight = !isLeftOrRight(
249-
(<Room>this.hallways[currentHallwayInd].partList[prevInd]).side
237+
(this.hallways[currentHallwayInd].partList[prevInd] as ForkableRoom<
238+
ForkName
239+
>).side
250240
);
251241
[currentHallwayInd, currentInd] = [hallwayInd, ind];
252242
}

src/Fork.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { Direction } from "./Direction";
2-
import { Room } from "./Room";
2+
import { ForkableRoom } from "./ForkableRoom";
3+
import { ForkNode } from "./ForkNode";
34

45
/**
56
* A Fork represents a connection between 2 [[Hallway]]s on the same
67
* floor. You can connect the [[Fork]]s of 2 hallways by
78
* adding to the `hallwayConnections` argument of the [[Hallway]]
89
* constructor.
910
*/
10-
export class Fork extends Room {
11+
export class Fork<ForkName extends string> extends ForkableRoom<ForkName> {
1112
/**
1213
*
1314
* @param side - The side of the [[Hallway]] that this [[Fork]] is on
@@ -21,7 +22,7 @@ export class Fork extends Room {
2122
*/
2223
constructor(
2324
side: Direction,
24-
nodeId: string,
25+
nodeId: ForkNode<ForkName>,
2526
public destinationName: string,
2627
edgeLengthFromPreviousNodeInHallway: number | undefined = 1
2728
) {

src/ForkNode.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export interface ReversedConnection<ForkName extends string> {
2+
readonly _type: "ReversedConnection";
3+
readonly name: ForkName;
4+
}
5+
6+
export function reverseConnection<ForkName extends string>(
7+
name: ForkName
8+
): ForkNode<ForkName> {
9+
return { _type: "ReversedConnection", name };
10+
}
11+
12+
export type ForkNode<ForkName extends string> =
13+
| ReversedConnection<ForkName>
14+
| ForkName;

src/ForkableRoom.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { HallwayElement } from "./HallwayElement";
2+
import { Direction } from "./Direction";
3+
import { ForkNode } from "./ForkNode";
4+
5+
export class ForkableRoom<ForkName extends string> extends HallwayElement {
6+
readonly nodeId: ForkNode<ForkName> | undefined;
7+
8+
constructor(
9+
name?: (string | null) | undefined,
10+
side: Direction = Direction.LEFT,
11+
{
12+
edgeLengthFromPreviousNodeInHallway,
13+
prefix = "room",
14+
aliases = [],
15+
nodeId,
16+
}: {
17+
prefix?: string;
18+
aliases?: string[];
19+
edgeLengthFromPreviousNodeInHallway?: number | null;
20+
nodeId?: ForkNode<ForkName>;
21+
} = {}
22+
) {
23+
super(name, side, {
24+
edgeLengthFromPreviousNodeInHallway,
25+
prefix,
26+
aliases,
27+
});
28+
this.nodeId = nodeId;
29+
}
30+
}

src/Hallway.ts

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
import { Room } from "./Room";
1+
import { ForkableRoom } from "./ForkableRoom";
22
import { Turn } from "./Turn";
3+
import { Stairs } from "./Stairs";
4+
import { ForkNode } from "./ForkNode";
5+
import { StairNode } from "./StairNode";
36

47
/**
58
* This class represents a single hallway. The hallway may have turns,
69
* but if you need a fork, you need to add another [[Hallway]] to the list
710
* and connect them with 2 [[Fork]]s.
811
*/
9-
export class Hallway {
12+
export class Hallway<ForkName extends string, StairName extends string> {
1013
/**
1114
*
1215
* @param partList - An array of every [[Room]] or [[Turn]] in the hallway.
@@ -15,7 +18,10 @@ export class Hallway {
1518
* consistent with the direction you choose as forward.
1619
* @param name - The name of this [[Hallway]].
1720
*/
18-
constructor(public partList: (Room | Turn)[], public name?: string | null) {}
21+
constructor(
22+
public partList: (ForkableRoom<ForkName> | Stairs<StairName> | Turn)[],
23+
public name?: string | null
24+
) {}
1925

2026
/**
2127
* @param - name The name of the room
@@ -36,33 +42,38 @@ export class Hallway {
3642
* @param roomInd - The index of the room in the hallway
3743
* @returns The id of the "closest" node to the room in the hallway
3844
*/
39-
idOfClosestNodeToIndex(roomInd: number): string {
45+
idOfClosestNodeToIndex(
46+
roomInd: number
47+
): ForkNode<ForkName> | StairNode<StairName> {
4048
let closestNodeInd: number;
4149
this.partList.forEach((r, currentInd) => {
4250
if (
4351
"nodeId" in r &&
44-
r.nodeId &&
52+
r.nodeId != null &&
4553
(closestNodeInd === undefined ||
4654
Math.abs(currentInd - roomInd) < Math.abs(closestNodeInd - roomInd))
4755
) {
4856
closestNodeInd = currentInd;
4957
}
5058
});
5159

52-
const closest = this.partList[closestNodeInd!];
53-
return (closest as Room).nodeId!;
60+
const closest = this.partList[closestNodeInd!] as
61+
| ForkableRoom<ForkName>
62+
| Stairs<StairName>;
63+
return closest.nodeId!;
5464
}
5565

5666
get nodes(): {
57-
nodeId: string;
67+
nodeId: ForkNode<ForkName> | StairNode<StairName>;
5868
edgeLengthFromPreviousNodeInHallway: number;
5969
}[] {
6070
return this.partList
6171
.filter(
62-
(r): r is Room & { nodeId: string } => "nodeId" in r && r.nodeId != null
72+
(r): r is ForkableRoom<ForkName> | Stairs<StairName> =>
73+
"nodeId" in r && r.nodeId != null
6374
)
6475
.map(({ nodeId, edgeLengthFromPreviousNodeInHallway }) => ({
65-
nodeId,
76+
nodeId: nodeId!,
6677
edgeLengthFromPreviousNodeInHallway:
6778
edgeLengthFromPreviousNodeInHallway == null
6879
? 1
@@ -98,9 +109,13 @@ export class Hallway {
98109
entranceWasStraight: boolean;
99110
}
100111
): string {
101-
const fromRoom = this.partList[from] as Room;
112+
const fromRoom = this.partList[from] as
113+
| ForkableRoom<ForkName>
114+
| Stairs<StairName>;
102115

103-
const toRoom = this.partList[to] as Room;
116+
const toRoom = this.partList[to] as
117+
| ForkableRoom<ForkName>
118+
| Stairs<StairName>;
104119

105120
if (from === to) {
106121
return `Bruh. You at ${fromRoom.fullName}\n`;
@@ -122,7 +137,10 @@ export class Hallway {
122137
prevInd >= 0 &&
123138
prevInd < this.partList.length &&
124139
this.partList[i - forwardOrBackward];
125-
ret += current.onPass(forwardOrBackward, prevRoom as Room);
140+
ret += current.onPass(
141+
forwardOrBackward,
142+
prevRoom as ForkableRoom<ForkName> | Stairs<StairName>
143+
);
126144
}
127145

128146
ret += toRoom.onArrive(forwardOrBackward, isEndOfDirections);

0 commit comments

Comments
 (0)