clone

an endless marble-race generator in the browser; the url is the seed, so every track can be shared

main
marbles / tests / classify_test.ts
classify_test.ts 4.6K
1/**2 * `classify()` against real Marble Kit file names. Every id below is an actual3 * `<pack>/Models/GLB format/*.glb` base name, so a regression here means the4 * pipeline is mislabelling shipped geometry.5 */6import { assertEquals } from "@std/assert";7import { classify } from "../src/shared/classify.ts";8import type { PieceClassification } from "../src/shared/types.ts";910/** Every flag off; a case only spells out what it expects to be set. */11const NONE: Omit<PieceClassification, "family"> = {12 solid: false,13 hole: false,14 wide: false,15 long: false,16 short: false,17 double: false,18 color: false,19 high: false,20 low: false,21 tier: null,22 size: null,23 chirality: null,24 span: null,25 count: null,26 segment: null,27};2829function check(30 id: string,31 family: string,32 set: Partial<Omit<PieceClassification, "family">> = {},33): void {34 assertEquals(classify(id), { family, ...NONE, ...set }, `classify(${id})`);35}3637Deno.test("classify: plain and modified straights", () => {38 check("straight", "straight");39 check("straight-hole", "straight", { hole: true });40 check("straight-wide", "straight", { wide: true });41 check("straight-wide-hole", "straight", { wide: true, hole: true });42});4344Deno.test("classify: corners, ends, tunnels, crosses", () => {45 check("corner", "corner");46 check("corner-solid", "corner", { solid: true });47 check("end-hole-rounded", "end", { hole: true });48 check("end-square", "end");49 check("tunnel", "tunnel");50 check("cross", "cross");51});5253Deno.test("classify: curves and bends carry size/width/solid", () => {54 check("curve", "curve");55 check("curve-wide-solid-large", "curve", {56 wide: true,57 solid: true,58 size: "large",59 });60 check("curve-wide-medium", "curve", { wide: true, size: "medium" });61 check("bend-medium", "bend", { size: "medium" });62 check("bend-solid-large", "bend", { solid: true, size: "large" });63});6465Deno.test("classify: s-curve is the one dashed family name", () => {66 check("s-curve-left", "s-curve", { chirality: "left" });67 check("s-curve-right-large", "s-curve", {68 chirality: "right",69 size: "large",70 });71 check("s-curve-short-left-b", "s-curve", {72 short: true,73 chirality: "left",74 tier: "b",75 });76});7778Deno.test("classify: helix span defaults to full", () => {79 check("helix-large-half-left", "helix", {80 size: "large",81 span: "half",82 chirality: "left",83 });84 check("helix-quarter-right", "helix", {85 span: "quarter",86 chirality: "right",87 });88 // A full helix carries no span token.89 check("helix-left", "helix", { span: "full", chirality: "left" });90});9192Deno.test("classify: splits", () => {93 check("split", "split");94 check("split-double-sides-solid", "split", { double: true, solid: true });95 check("split-large-solid-right", "split", {96 size: "large",97 solid: true,98 chirality: "right",99 });100});101102Deno.test("classify: height tiers on ramps, slants, bumps, waves", () => {103 check("ramp-long-solid-c", "ramp", { long: true, solid: true, tier: "c" });104 check("ramp-end-solid-b", "ramp", { solid: true, tier: "b" });105 check("slant-solid-long-d", "slant", { solid: true, long: true, tier: "d" });106 check("bump-solid-a", "bump", { solid: true, tier: "a" });107 check("wave-solid-b", "wave", { solid: true, tier: "b" });108});109110Deno.test("classify: funnels and fans", () => {111 check("funnel", "funnel");112 check("funnel-long", "funnel", { long: true });113 check("fan-standing-four", "fan", { count: "four" });114 check("fan-simple-two", "fan", { count: "two" });115});116117Deno.test("classify: support posts split count from stack segment", () => {118 check("support-color-two-top-double", "support", {119 color: true,120 count: "two",121 segment: "top-double",122 });123 check("support-single-top", "support", {124 count: "single",125 segment: "top",126 });127 check("support-four-bottom", "support", {128 count: "four",129 segment: "bottom",130 });131 check("support-color-single-middle", "support", {132 color: true,133 count: "single",134 segment: "middle",135 });136});137138Deno.test("classify: marbles, banners, trees", () => {139 check("marble-center-butterfly-low", "marble", { low: true });140 check("marble-high", "marble", { high: true });141 check("banner-hanging-double-high", "banner", { double: true, high: true });142 check("banner", "banner");143 check("tree-tall-large", "tree", { size: "large" });144 check("tree", "tree");145});146147Deno.test("classify: unrecognized leading token is family 'unknown'", () => {148 assertEquals(classify("sprocket").family, "unknown");149 assertEquals(classify("tree_oak").family, "unknown");150 assertEquals(classify("cliff_blockSlope_rock").family, "unknown");151});