84 lines
2.5 KiB
JavaScript
84 lines
2.5 KiB
JavaScript
"use strict";
|
|
/**
|
|
* StateGraph — manages known states and transitions between them.
|
|
* Uses BFS ordering by default for exploration scheduling.
|
|
*/
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.StateGraph = void 0;
|
|
class StateGraph {
|
|
constructor() {
|
|
this.states = new Map();
|
|
this.transitions = [];
|
|
/** Insertion order for BFS */
|
|
this.insertionOrder = [];
|
|
}
|
|
addState(state) {
|
|
if (!this.states.has(state.id)) {
|
|
this.states.set(state.id, state);
|
|
this.insertionOrder.push(state.id);
|
|
}
|
|
else {
|
|
// Update visit count on revisit
|
|
const existing = this.states.get(state.id);
|
|
this.states.set(state.id, { ...existing, visitCount: existing.visitCount + 1 });
|
|
}
|
|
}
|
|
hasState(stateId) {
|
|
return this.states.has(stateId);
|
|
}
|
|
getState(stateId) {
|
|
return this.states.get(stateId);
|
|
}
|
|
incrementVisit(stateId) {
|
|
const state = this.states.get(stateId);
|
|
if (state) {
|
|
this.states.set(stateId, { ...state, visitCount: state.visitCount + 1 });
|
|
}
|
|
}
|
|
recordTransition(fromId, action, toId) {
|
|
this.transitions.push({
|
|
fromId,
|
|
action,
|
|
toId,
|
|
timestamp: Date.now(),
|
|
});
|
|
}
|
|
/** Returns all states that have never been visited (visitCount === 0) */
|
|
getUnvisited() {
|
|
return this.insertionOrder
|
|
.map((id) => this.states.get(id))
|
|
.filter((s) => s.visitCount === 0);
|
|
}
|
|
/** BFS heuristic: returns the oldest unvisited state, or null if none */
|
|
getNextToExplore() {
|
|
const unvisited = this.getUnvisited();
|
|
return unvisited.length > 0 ? unvisited[0] : null;
|
|
}
|
|
getAllStates() {
|
|
return this.insertionOrder.map((id) => this.states.get(id));
|
|
}
|
|
getTransitions() {
|
|
return [...this.transitions];
|
|
}
|
|
toJSON() {
|
|
return {
|
|
stateCount: this.states.size,
|
|
transitionCount: this.transitions.length,
|
|
states: this.getAllStates().map((s) => ({
|
|
id: s.id,
|
|
url: s.url,
|
|
title: s.title,
|
|
visitCount: s.visitCount,
|
|
})),
|
|
transitions: this.transitions.map((t) => ({
|
|
fromId: t.fromId,
|
|
toId: t.toId,
|
|
actionId: t.action.id,
|
|
actionType: t.action.type,
|
|
timestamp: t.timestamp,
|
|
})),
|
|
};
|
|
}
|
|
}
|
|
exports.StateGraph = StateGraph;
|