diff --git a/src/map.js b/src/map.js new file mode 100644 index 0000000..fcd12c8 --- /dev/null +++ b/src/map.js @@ -0,0 +1,35 @@ +const ACT1_LAYOUT = [ + "encounter", + "encounter", + "campfire", + "encounter", + "elite", + "encounter", + "campfire", + "encounter", + "elite", + "boss", +]; + +export function createMap() { + return { + nodes: ACT1_LAYOUT.map((type, id) => ({ id, type, cleared: false })), + currentNode: 0, + }; +} + +export function advanceMap(map) { + const last = map.nodes.length - 1; + const nodes = map.nodes.map((n, i) => + i === map.currentNode ? { ...n, cleared: true } : n, + ); + return { + ...map, + nodes, + currentNode: Math.min(map.currentNode + 1, last), + }; +} + +export function getCurrentNode(map) { + return map.nodes[map.currentNode]; +} diff --git a/src/map.test.js b/src/map.test.js new file mode 100644 index 0000000..e7aba6e --- /dev/null +++ b/src/map.test.js @@ -0,0 +1,81 @@ +import { describe, expect, test } from "bun:test"; +import { advanceMap, createMap, getCurrentNode } from "./map.js"; + +describe("createMap", () => { + test("returns 10 nodes", () => { + const map = createMap(); + expect(map.nodes).toHaveLength(10); + }); + + test("first node is encounter, last node is boss", () => { + const map = createMap(); + expect(map.nodes[0].type).toBe("encounter"); + expect(map.nodes[9].type).toBe("boss"); + }); + + test("contains expected node type counts", () => { + const map = createMap(); + const types = map.nodes.map((n) => n.type); + expect(types.filter((t) => t === "encounter")).toHaveLength(5); + expect(types.filter((t) => t === "campfire")).toHaveLength(2); + expect(types.filter((t) => t === "elite")).toHaveLength(2); + expect(types.filter((t) => t === "boss")).toHaveLength(1); + }); + + test("all nodes start cleared: false", () => { + const map = createMap(); + expect(map.nodes.every((n) => n.cleared === false)).toBe(true); + }); + + test("each node has sequential id 0-9", () => { + const map = createMap(); + map.nodes.forEach((n, i) => { + expect(n.id).toBe(i); + }); + }); + + test("currentNode starts at 0", () => { + const map = createMap(); + expect(map.currentNode).toBe(0); + }); +}); + +describe("advanceMap", () => { + test("marks current node cleared and increments currentNode", () => { + const map = createMap(); + const next = advanceMap(map); + expect(next.nodes[0].cleared).toBe(true); + expect(next.currentNode).toBe(1); + }); + + test("does not mutate the input map", () => { + const map = createMap(); + advanceMap(map); + expect(map.nodes[0].cleared).toBe(false); + expect(map.currentNode).toBe(0); + }); + + test("does not go past last node (index 9)", () => { + let map = createMap(); + for (let i = 0; i < 10; i++) { + map = advanceMap(map); + } + expect(map.currentNode).toBe(9); + }); +}); + +describe("getCurrentNode", () => { + test("returns the node at currentNode index", () => { + const map = createMap(); + const node = getCurrentNode(map); + expect(node).toBe(map.nodes[map.currentNode]); + expect(node.id).toBe(0); + expect(node.type).toBe("encounter"); + }); + + test("returns correct node after advancing", () => { + const map = advanceMap(createMap()); + const node = getCurrentNode(map); + expect(node.id).toBe(1); + }); +});