Skip to content

Commit 070daa6

Browse files
committed
feat: one-way hallways
1 parent de3feb6 commit 070daa6

File tree

4 files changed

+70
-40
lines changed

4 files changed

+70
-40
lines changed

src/Building.test.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,6 @@ describe("accessibility", () => {
539539
});
540540
});
541541

542-
/*
543542
describe("one-way hallways", () => {
544543
const hallway10 = [
545544
new Stairs(RIGHT, onFloor("b", 1)),
@@ -661,11 +660,17 @@ describe("one-way hallways", () => {
661660
assertValidBuilding(building);
662661

663662
expect(building.getDirections("101", "103")).toMatchInlineSnapshot(`
664-
"Turn left out of room 101
665-
Continue, then turn left into room 103"
663+
"Turn right out of room 101
664+
Continue, then turn left into the stairs
665+
Go up 1 floor of stairs
666+
Turn right out of the stairs
667+
Continue, then turn right into the 11s
668+
Continue, then turn right into the stairs
669+
Go down 1 floor of stairs
670+
Turn left out of the stairs
671+
Continue, then after entering the 10s, turn left
672+
Continue, then turn right into room 103"
666673
`);
667-
668-
fail("snapshot above is wrong");
669674
});
670675

671676
test("unconnected one-way building 1", () => {
@@ -688,7 +693,6 @@ describe("one-way hallways", () => {
688693
});
689694
});
690695

691-
describe("one-way connections", () => {});
692-
*/
696+
// describe("one-way connections", () => {});
693697

694698
// TODO: add tests with SimpleHallway and rooms that are nodes

src/Building.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { Hallway } from "./Hallway";
22
import { Room } from "./Room";
3-
import { getShortestPath, isConnectedGraph, getGraph } from "./graph";
3+
import {
4+
getShortestPath,
5+
isConnectedGraph,
6+
getGraph,
7+
HallConnectorsStructures,
8+
} from "./graph";
49
import { isLeftOrRight } from "./Direction";
510
import { ForkNode } from "./ForkNode";
611
import { StairNode } from "./StairNode";
@@ -73,12 +78,18 @@ export class Building<
7378
.map(nodeId => nodeId.name)
7479
)
7580
) {
76-
const hallwayNodes = this.hallways.map(h => {
77-
return h.nodes.filter(
78-
({ nodeId }) =>
79-
nodeId instanceof BasicRoomNode ||
80-
allowedConnections.includes(nodeId.name)
81-
);
81+
const hallwayNodes: HallConnectorsStructures<
82+
ForkName,
83+
StairName
84+
> = this.hallways.map(h => {
85+
return {
86+
nodes: h.nodes.filter(
87+
({ nodeId }) =>
88+
nodeId instanceof BasicRoomNode ||
89+
allowedConnections.includes(nodeId.name)
90+
),
91+
oneWay: h.oneWay,
92+
};
8293
});
8394
this.graph = getGraph(hallwayNodes);
8495
this.roomsList = hallways

src/Hallway.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import { Room } from "./Room";
22
import { Turn } from "./Turn";
33
import { Stairs } from "./Stairs";
4-
import { ForkNode } from "./ForkNode";
5-
import { StairNode } from "./StairNode";
64
import { Node, isConnectorNode } from "./node";
7-
import { BasicRoomNode } from "./BasicRoomNode";
8-
import { Fork } from "./Fork";
5+
6+
export type OneWay = "forward" | "backward" | false;
97

108
/**
119
* This class represents a single hallway. The hallway may have turns,
@@ -14,6 +12,7 @@ import { Fork } from "./Fork";
1412
*/
1513
export class Hallway<ForkName extends string, StairName extends string> {
1614
readonly allowFrontConnectionsInMiddle: boolean;
15+
readonly oneWay: OneWay;
1716

1817
/**
1918
*
@@ -24,14 +23,22 @@ export class Hallway<ForkName extends string, StairName extends string> {
2423
* @param allowFrontConnectionsInMiddle - If true, this hallway may have
2524
* [[Rooms]] and [[Stairs]] that are not at the ends of the hallway, but are
2625
* marked as FRONT. This is used by [[isValidBuilding]].
26+
* @param oneWay - false if you can travel both ways in this hallway.
27+
* "forward" if you can only travel from the first to the last element of this
28+
* hallway. "backward" if you can only travel from the last element to the first.
2729
*/
2830
constructor(
2931
public partList: (Room<ForkName> | Stairs<StairName> | Turn)[],
3032
{
3133
allowFrontConnectionsInMiddle = false,
32-
}: { allowFrontConnectionsInMiddle?: boolean } = {}
34+
oneWay = false,
35+
}: {
36+
allowFrontConnectionsInMiddle?: boolean;
37+
oneWay?: OneWay;
38+
} = {}
3339
) {
3440
this.allowFrontConnectionsInMiddle = allowFrontConnectionsInMiddle;
41+
this.oneWay = oneWay;
3542
}
3643

3744
/**

src/graph.ts

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@ import dijkstra from "dijkstrajs";
33
import { ForkNode, reverseConnection } from "./ForkNode";
44
import { StairNode, onFloor } from "./StairNode";
55
import { serializeNode, nodeFromString, Node } from "./node";
6+
import { OneWay } from "./Hallway";
7+
8+
export type HallConnectorsStructures<
9+
ForkName extends string,
10+
StairName extends string
11+
> = {
12+
nodes: {
13+
nodeId: Node<ForkName, StairName>;
14+
edgeLengthFromPreviousNodeInHallway: number;
15+
}[];
16+
oneWay: OneWay;
17+
}[];
618

719
/**
820
* @ignore
@@ -11,12 +23,10 @@ function getHallwayConnections<
1123
ForkName extends string,
1224
StairName extends string
1325
>(
14-
hallConnections: {
15-
nodeId: Node<ForkName, StairName>;
16-
edgeLengthFromPreviousNodeInHallway: number;
17-
}[][]
26+
hallConnections: HallConnectorsStructures<ForkName, StairName>
1827
): [string, string][] {
1928
return hallConnections
29+
.map(hallway => hallway.nodes)
2030
.flat()
2131
.map(thing => thing.nodeId)
2232
.filter(
@@ -32,12 +42,10 @@ function getHallwayConnections<
3242

3343
/** @ignore */
3444
function getStairConnections<ForkName extends string, StairName extends string>(
35-
hallConnections: {
36-
nodeId: Node<ForkName, StairName>;
37-
edgeLengthFromPreviousNodeInHallway: number;
38-
}[][]
45+
hallConnections: HallConnectorsStructures<ForkName, StairName>
3946
): string[][] {
4047
const stairNodes = hallConnections
48+
.map(hallway => hallway.nodes)
4149
.flat()
4250
.map(thing => thing.nodeId)
4351
.filter((st): st is StairNode<StairName> => st instanceof StairNode);
@@ -59,30 +67,30 @@ function getStairConnections<ForkName extends string, StairName extends string>(
5967
* @returns The graph to be used by getShortestPath
6068
*/
6169
export function getGraph<ForkName extends string, StairName extends string>(
62-
hallConnectorsStructures: {
63-
nodeId: Node<ForkName, StairName>;
64-
edgeLengthFromPreviousNodeInHallway: number;
65-
}[][]
70+
hallConnectorsStructures: HallConnectorsStructures<ForkName, StairName>
6671
) {
67-
const hallConnectors = hallConnectorsStructures.map(hall =>
68-
hall.map(({ nodeId, edgeLengthFromPreviousNodeInHallway }) => ({
69-
nodeId: serializeNode(nodeId),
70-
edgeLengthFromPreviousNodeInHallway,
71-
}))
72-
);
72+
const hallConnectors = hallConnectorsStructures.map(hall => ({
73+
oneWay: hall.oneWay,
74+
nodes: hall.nodes.map(
75+
({ nodeId, edgeLengthFromPreviousNodeInHallway }) => ({
76+
nodeId: serializeNode(nodeId),
77+
edgeLengthFromPreviousNodeInHallway,
78+
})
79+
),
80+
}));
7381
const stairConnections = getStairConnections(hallConnectorsStructures);
7482
const hallwayConnections = getHallwayConnections(hallConnectorsStructures);
7583

7684
const graph: dijkstra.Graph = {};
77-
hallConnectors.forEach(hall => {
85+
hallConnectors.forEach(({ oneWay, nodes: hall }) => {
7886
hall.forEach((node, ind) => {
7987
const id = node.nodeId;
8088
const edgesTo: { [key: string]: number } = {};
81-
if (ind != 0) {
89+
if (ind !== 0 && oneWay !== "forward") {
8290
edgesTo[hall[ind - 1].nodeId] =
8391
hall[ind].edgeLengthFromPreviousNodeInHallway;
8492
}
85-
if (ind != hall.length - 1) {
93+
if (ind !== hall.length - 1 && oneWay !== "backward") {
8694
edgesTo[hall[ind + 1].nodeId] =
8795
hall[ind + 1].edgeLengthFromPreviousNodeInHallway;
8896
}

0 commit comments

Comments
 (0)