debug overhaul, fixes stringifying over-recursion

This commit is contained in:
Emmaline Autumn 2025-02-15 18:33:19 -07:00
parent ffa2ef97e0
commit 8bd2c30108
5 changed files with 101 additions and 48 deletions

View File

@ -1,4 +1,6 @@
import { TrackSegment } from "../track/system.ts"; import { TrackSegment } from "../track/system.ts";
import { Train, TrainCar } from "../train/train.ts";
import { InputManager } from "./input.ts";
type ContextStore = Record<string, any>; type ContextStore = Record<string, any>;
@ -85,33 +87,59 @@ if (debug) {
function safeStringify(obj: any) { function safeStringify(obj: any) {
const seen = new WeakSet(); const seen = new WeakSet();
return JSON.stringify(obj, (key, value) => { return JSON.stringify(obj, (key, value) => {
if (value instanceof Map) {
const val: Record<string, unknown> = {};
for (const [k, v] of value) {
if (typeof k !== "string") continue;
val[k] = v;
}
return val;
}
if (value instanceof Set) {
return Array.from(value);
}
if (value instanceof TrackSegment) {
return {
...value,
frontNeighbours: value.frontNeighbours.map((n) => n.id),
backNeighbours: value.backNeighbours.map((n) => n.id),
};
}
if (typeof value === "object" && value !== null) { if (typeof value === "object" && value !== null) {
if (seen.has(value)) { if (seen.has(value)) {
return "[Circular]"; // Replace circular references return "[Circular]"; // Replace circular references
} }
seen.add(value); seen.add(value);
} }
if (value instanceof Map) {
const val: Record<string, unknown> = {};
for (const [k, v] of value) {
if (typeof k !== "string") continue;
val[k] = v;
}
seen.add(value);
return val;
}
if (value instanceof Set) {
seen.add(value);
value = Array.from(value);
return value;
}
if (value instanceof TrackSegment) {
seen.add(value);
const val = { ...value };
(val as any).frontNeighbours = value.frontNeighbours.map((n) => n.id);
(val as any).backNeighbours = value.backNeighbours.map((n) => n.id);
return val;
}
// if (value instanceof Train) {
// const val = { ...value };
// // val.segments = value.segments.map((s) => s.id);
// delete (val as any).path;
// delete (val as any).nodes;
// delete (val as any).cars;
// delete (val as any).t;
// // val.t
// // val.
// return null;
// }
// if (value instanceof InputManager) {
// return {};
// }
// if (value instanceof TrainCar) {
// const val = { ...value };
// return val;
// }
return value; return value;
}, 2); }, 2);
} }

View File

@ -24,7 +24,7 @@ const doodler = new ZoomableDoodler({
(doodler as any as { ctx: CanvasRenderingContext2D }).ctx (doodler as any as { ctx: CanvasRenderingContext2D }).ctx
.imageSmoothingEnabled = false; .imageSmoothingEnabled = false;
// doodler.minScale = 0.1; // doodler.minScale = 0.1;
// (doodler as any).scale = doodler.maxScale; (doodler as any).scale = 3.14;
const colors = [ const colors = [
"red", "red",
@ -41,7 +41,11 @@ setDefaultContext({
inputManager, inputManager,
doodler, doodler,
resources, resources,
debug: false, debug: {
track: false,
train: false,
path: false,
},
colors, colors,
}); });

View File

@ -4,33 +4,37 @@ import { getContextItem, setDefaultContext } from "../lib/context.ts";
import { clamp } from "../math/clamp.ts"; import { clamp } from "../math/clamp.ts";
export class TrackSystem { export class TrackSystem {
private segments: Map<string, TrackSegment> = new Map(); private _segments: Map<string, TrackSegment> = new Map();
private doodler: Doodler; private doodler: Doodler;
constructor(segments: TrackSegment[]) { constructor(segments: TrackSegment[]) {
this.doodler = getContextItem<Doodler>("doodler"); this.doodler = getContextItem<Doodler>("doodler");
for (const segment of segments) { for (const segment of segments) {
this.segments.set(segment.id, segment); this._segments.set(segment.id, segment);
} }
} }
getSegment(id: string) {
return this._segments.get(id);
}
get firstSegment() { get firstSegment() {
return this.segments.values().next().value; return this._segments.values().next().value;
} }
get lastSegment() { get lastSegment() {
return this.segments.values().toArray().pop(); return this._segments.values().toArray().pop();
} }
optimize(percent: number) { optimize(percent: number) {
console.log("Optimizing track", percent * 100 / 4); console.log("Optimizing track", percent * 100 / 4);
for (const segment of this.segments.values()) { for (const segment of this._segments.values()) {
segment.recalculateRailPoints(Math.round(percent * 100 / 4)); segment.recalculateRailPoints(Math.round(percent * 100 / 4));
} }
} }
recalculateAll() { recalculateAll() {
for (const segment of this.segments.values()) { for (const segment of this._segments.values()) {
segment.recalculateRailPoints(); segment.recalculateRailPoints();
segment.length = segment.calculateApproxLength(); segment.length = segment.calculateApproxLength();
} }
@ -38,11 +42,11 @@ export class TrackSystem {
registerSegment(segment: TrackSegment) { registerSegment(segment: TrackSegment) {
segment.setTrack(this); segment.setTrack(this);
this.segments.set(segment.id, segment); this._segments.set(segment.id, segment);
} }
unregisterSegment(segment: TrackSegment) { unregisterSegment(segment: TrackSegment) {
this.segments.delete(segment.id); this._segments.delete(segment.id);
for (const s of this.segments.values()) { for (const s of this._segments.values()) {
s.backNeighbours = s.backNeighbours.filter((n) => n !== segment); s.backNeighbours = s.backNeighbours.filter((n) => n !== segment);
s.frontNeighbours = s.frontNeighbours.filter((n) => n !== segment); s.frontNeighbours = s.frontNeighbours.filter((n) => n !== segment);
} }
@ -52,7 +56,7 @@ export class TrackSystem {
} }
draw(showControls = false) { draw(showControls = false) {
for (const [i, segment] of this.segments.entries()) { for (const [i, segment] of this._segments.entries()) {
segment.draw(showControls); segment.draw(showControls);
} }
@ -85,7 +89,7 @@ export class TrackSystem {
endArray: End[] = []; endArray: End[] = [];
findEnds() { findEnds() {
for (const segment of this.segments.values()) { for (const segment of this._segments.values()) {
if (this.ends.has(segment)) continue; if (this.ends.has(segment)) continue;
const ends: [End, End] = [ const ends: [End, End] = [
{ {
@ -109,14 +113,14 @@ export class TrackSystem {
serialize() { serialize() {
return JSON.stringify( return JSON.stringify(
this.segments.values().map((s) => s.serialize()).toArray(), this._segments.values().map((s) => s.serialize()).toArray(),
); );
} }
copy() { copy() {
const track = new TrackSystem([]); const track = new TrackSystem([]);
for (const segment of this.segments.values()) { for (const segment of this._segments.values()) {
track.segments.set(segment.id, segment.copy()); track._segments.set(segment.id, segment.copy());
} }
return track; return track;
} }
@ -127,19 +131,19 @@ export class TrackSystem {
const neighborMap = new Map<string, [string[], string[]]>(); const neighborMap = new Map<string, [string[], string[]]>();
for (const segment of data) { for (const segment of data) {
track.segments.set(segment.id, TrackSegment.deserialize(segment)); track._segments.set(segment.id, TrackSegment.deserialize(segment));
neighborMap.set(segment.id, [segment.fNeighbors, segment.bNeighbors]); neighborMap.set(segment.id, [segment.fNeighbors, segment.bNeighbors]);
} }
for (const segment of track.segments.values()) { for (const segment of track._segments.values()) {
segment.setTrack(track); segment.setTrack(track);
const neighbors = neighborMap.get(segment.id); const neighbors = neighborMap.get(segment.id);
if (neighbors) { if (neighbors) {
segment.backNeighbours = neighbors[1].map((id) => segment.backNeighbours = neighbors[1].map((id) =>
track.segments.get(id) track._segments.get(id)
).filter((s) => s) as TrackSegment[]; ).filter((s) => s) as TrackSegment[];
segment.frontNeighbours = neighbors[0].map((id) => segment.frontNeighbours = neighbors[0].map((id) =>
track.segments.get(id) track._segments.get(id)
).filter((s) => s) as TrackSegment[]; ).filter((s) => s) as TrackSegment[];
} }
} }
@ -148,7 +152,7 @@ export class TrackSystem {
} }
translate(v: Vector) { translate(v: Vector) {
for (const segment of this.segments.values()) { for (const segment of this._segments.values()) {
segment.translate(v); segment.translate(v);
} }
} }

View File

@ -3,7 +3,7 @@ import { Follower } from "../physics/follower.ts";
import { Mover } from "../physics/mover.ts"; import { Mover } from "../physics/mover.ts";
import { getContext, getContextItem } from "../lib/context.ts"; import { getContext, getContextItem } from "../lib/context.ts";
import { Doodler, Vector } from "@bearmetal/doodler"; import { Doodler, Vector } from "@bearmetal/doodler";
import { Spline, TrackSegment } from "../track/system.ts"; import { Spline, TrackSegment, TrackSystem } from "../track/system.ts";
import { ResourceManager } from "../lib/resources.ts"; import { ResourceManager } from "../lib/resources.ts";
import { map } from "../math/lerp.ts"; import { map } from "../math/lerp.ts";
@ -107,9 +107,9 @@ export class Train {
// } // }
draw() { draw() {
const ctx = getContext(); const debug = getContextItem<Debug>("debug");
if (ctx.debug) { const doodler = getContextItem<Doodler>("doodler");
const doodler = getContextItem<Doodler>("doodler"); if (debug.path) {
// doodler.drawLine(this.path.points, { // doodler.drawLine(this.path.points, {
// color: "red", // color: "red",
// weight: 3, // weight: 3,
@ -124,6 +124,16 @@ export class Train {
doodler.drawCircle(p.p, 2, { color, weight: .5 }); doodler.drawCircle(p.p, 2, { color, weight: .5 });
} }
} }
if (debug.train) {
const track = getContextItem<TrackSystem>("track");
for (const segmentId of this.segments) {
const segment = track.getSegment(segmentId);
segment &&
doodler.drawBezier(...segment.points, { color: "red", weight: 3 });
}
}
for (const car of this.cars) { for (const car of this.cars) {
car.draw(); car.draw();
} }
@ -185,8 +195,8 @@ export class TrainCar {
); );
}); });
const ctx = getContext(); const debug = getContextItem<Debug>("debug");
if (ctx.debug) { if (debug.car) {
doodler.drawLine(this.points, { doodler.drawLine(this.points, {
color: "blue", color: "blue",
weight: 3, weight: 3,

View File

@ -15,4 +15,11 @@ declare global {
bNeighbors: string[]; bNeighbors: string[];
fNeighbors: string[]; fNeighbors: string[];
}; };
type Debug = {
track: boolean;
train: boolean;
car: boolean;
path: boolean;
};
} }