Skip to content

Commit 07af2ed

Browse files
authored
Merge pull request #48 from WalnutProgramming/one-way-hallways
Allow one-way hallways As part of this process, I had to make each room its own node (as opposed to only connections between hallways being nodes).
2 parents eaebd41 + 96c7a9c commit 07af2ed

11 files changed

+495
-123
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "room-finder",
3-
"version": "0.1.1",
3+
"version": "0.2.0-beta.2",
44
"repository": "github:WalnutProgramming/room-finder",
55
"homepage": "https://room-finder.walnut.direct/",
66
"license": "AGPL-3.0-only",

src/BasicRoomNode.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export class BasicRoomNode {
2+
readonly _type = "BasicRoomNode";
3+
readonly name: string;
4+
5+
constructor(name: string) {
6+
this.name = name;
7+
}
8+
}

src/Building.test.ts

+158-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
reverseConnection,
1010
onFloor,
1111
} from ".";
12-
import { isValidBuilding } from "./buildingValidity";
12+
import { assertValidBuilding, isValidBuilding } from "./buildingValidity";
1313

1414
const { RIGHT, LEFT, FRONT } = Direction;
1515

@@ -533,10 +533,166 @@ describe("accessibility", () => {
533533
expect.objectContaining({
534534
valid: false,
535535
reason:
536-
"The hallway at index 4 has no nodes (Forks or Stairs) to connect it to the rest of the building.",
536+
"The hallway at index 4 has no connector nodes (Forks or Stairs) to connect it to the rest of the building.",
537537
})
538538
);
539539
});
540540
});
541541

542+
describe("one-way hallways", () => {
543+
const hallway10 = [
544+
new Stairs(RIGHT, onFloor("b", 1)),
545+
new Room("101"),
546+
new Room("102"),
547+
new Room("103"),
548+
new Fork(RIGHT, "a", "the 11s"),
549+
];
550+
const hallway11 = [
551+
new Fork(FRONT, reverseConnection("a"), "the 10s"),
552+
new Room("111"),
553+
new Room("112"),
554+
new Room("113"),
555+
new Stairs(RIGHT, onFloor("c", 1)),
556+
];
557+
558+
const hallway20 = [
559+
new Stairs(RIGHT, onFloor("b", 2)),
560+
new Room("201"),
561+
new Room("202"),
562+
new Room("203"),
563+
new Fork(RIGHT, "e", "the 11s"),
564+
];
565+
const hallway21 = [
566+
new Fork(FRONT, reverseConnection("e"), "the 11s"),
567+
new Room("211"),
568+
new Room("212"),
569+
new Room("213"),
570+
new Stairs(RIGHT, onFloor("c", 2)),
571+
];
572+
573+
let controlAnswer: string | null;
574+
575+
test("control case", () => {
576+
const building = new Building([
577+
new Hallway(hallway10),
578+
new Hallway(hallway11),
579+
new Hallway(hallway20),
580+
new Hallway(hallway21),
581+
]);
582+
assertValidBuilding(building);
583+
584+
controlAnswer = building.getDirections("103", "111");
585+
586+
expect(controlAnswer).toMatchInlineSnapshot(`
587+
"Turn left out of room 103
588+
Continue, then turn right into the 11s
589+
Continue, then turn left into room 111"
590+
`);
591+
});
592+
593+
test("one-way hallway with same directions", () => {
594+
const building = new Building([
595+
new Hallway(hallway10, { oneWay: "forward" }),
596+
new Hallway(hallway11, { oneWay: "forward" }),
597+
new Hallway(hallway20),
598+
new Hallway(hallway21),
599+
]);
600+
assertValidBuilding(building);
601+
602+
expect(building.getDirections("103", "111")).toBe(controlAnswer);
603+
});
604+
605+
test("one-way hallway 1", () => {
606+
const building = new Building([
607+
new Hallway(hallway10, { oneWay: "backward" }),
608+
new Hallway(hallway11, { oneWay: "backward" }),
609+
new Hallway(hallway20),
610+
new Hallway(hallway21),
611+
]);
612+
assertValidBuilding(building);
613+
614+
expect(building.getDirections("103", "111")).not.toBe(controlAnswer);
615+
616+
expect(building.getDirections("103", "111")).toMatchInlineSnapshot(`
617+
"Turn right out of room 103
618+
Continue, then turn left into the stairs
619+
Go up 1 floor of stairs
620+
Turn right out of the stairs
621+
Continue, then turn right into the 11s
622+
Continue, then turn right into the stairs
623+
Go down 1 floor of stairs
624+
Turn left out of the stairs
625+
Continue, then turn right into room 111"
626+
`);
627+
});
628+
629+
test("one-way hallway 2", () => {
630+
const building = new Building([
631+
new Hallway(hallway10, { oneWay: "backward" }),
632+
new Hallway(hallway11),
633+
new Hallway(hallway20),
634+
new Hallway(hallway21),
635+
]);
636+
assertValidBuilding(building);
637+
638+
expect(building.getDirections("103", "111")).not.toBe(controlAnswer);
639+
640+
expect(building.getDirections("103", "111")).toMatchInlineSnapshot(`
641+
"Turn right out of room 103
642+
Continue, then turn left into the stairs
643+
Go up 1 floor of stairs
644+
Turn right out of the stairs
645+
Continue, then turn right into the 11s
646+
Continue, then turn right into the stairs
647+
Go down 1 floor of stairs
648+
Turn left out of the stairs
649+
Continue, then turn right into room 111"
650+
`);
651+
});
652+
653+
test("one-way hallway 3", () => {
654+
const building = new Building([
655+
new Hallway(hallway10, { oneWay: "backward" }),
656+
new Hallway(hallway11),
657+
new Hallway(hallway20),
658+
new Hallway(hallway21),
659+
]);
660+
assertValidBuilding(building);
661+
662+
expect(building.getDirections("101", "103")).toMatchInlineSnapshot(`
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"
673+
`);
674+
});
675+
676+
test("unconnected one-way building 1", () => {
677+
const building = new Building([
678+
new Hallway(hallway10, { oneWay: "backward" }),
679+
new Hallway(hallway11, { oneWay: "forward" }),
680+
new Hallway(hallway20),
681+
new Hallway(hallway21),
682+
]);
683+
expect(isValidBuilding(building).valid).toBe(false);
684+
});
685+
test("unconnected one-way building 2", () => {
686+
const building = new Building([
687+
new Hallway(hallway10, { oneWay: "forward" }),
688+
new Hallway(hallway11, { oneWay: "backward" }),
689+
new Hallway(hallway20),
690+
new Hallway(hallway21),
691+
]);
692+
expect(isValidBuilding(building).valid).toBe(false);
693+
});
694+
});
695+
696+
// describe("one-way connections", () => {});
697+
542698
// TODO: add tests with SimpleHallway and rooms that are nodes

src/Building.ts

+32-12
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
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";
7-
import { nodeToString } from "./node";
12+
import { serializeNode, Node } from "./node";
13+
import { BasicRoomNode } from "./BasicRoomNode";
814

915
/**
1016
* @ignore
@@ -61,15 +67,29 @@ export class Building<
6167
*/
6268
constructor(
6369
readonly hallways: Hallway<ForkName, StairName>[],
64-
readonly allowedConnections: (
65-
| ForkName
66-
| StairName
67-
)[] = hallways.flatMap(h => h.nodes.map(n => n.nodeId.name))
70+
readonly allowedConnections: (ForkName | StairName)[] = hallways.flatMap(
71+
h =>
72+
h.nodes
73+
.map(n => n.nodeId)
74+
.filter(
75+
(nodeId): nodeId is ForkNode<ForkName> | StairNode<StairName> =>
76+
!(nodeId instanceof BasicRoomNode)
77+
)
78+
.map(nodeId => nodeId.name)
79+
)
6880
) {
69-
const hallwayNodes = this.hallways.map(h => {
70-
return h.nodes.filter(({ nodeId }) =>
71-
allowedConnections.includes(nodeId.name)
72-
);
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+
};
7393
});
7494
this.graph = getGraph(hallwayNodes);
7595
this.roomsList = hallways
@@ -110,14 +130,14 @@ export class Building<
110130
* hallway
111131
*/
112132
private getHallwayIndexAndIndexFromNode(
113-
nodeId: ForkNode<ForkName> | StairNode<StairName>
133+
nodeId: Node<ForkName, StairName>
114134
): [number, number] {
115135
const inds = this.hallways.map(h =>
116136
h.partList.findIndex(
117137
r =>
118138
"nodeId" in r &&
119139
r.nodeId != null &&
120-
nodeToString(r.nodeId) === nodeToString(nodeId)
140+
serializeNode(r.nodeId) === serializeNode(nodeId)
121141
)
122142
);
123143
const hallwayInd = inds.findIndex(a => a !== -1);

0 commit comments

Comments
 (0)