"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spread = (this && this.__spread) || function () { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; if (m) return m.call(o); return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; }; Object.defineProperty(exports, "__esModule", { value: true }); var utils_1 = require("./utils"); var actions_1 = require("./actions"); var environment_1 = require("./environment"); var EMPTY_MAP = {}; function getNodes(node) { var states = node.states; var nodes = utils_1.keys(states).reduce(function (accNodes, stateKey) { var subState = states[stateKey]; var subNodes = getNodes(states[stateKey]); accNodes.push.apply(accNodes, __spread([subState], subNodes)); return accNodes; }, []); return nodes; } exports.getNodes = getNodes; function getEventEdges(node, event) { var transitions = node.definition.on[event]; return utils_1.flatten(transitions.map(function (transition) { var targets = transition.target ? [].concat(transition.target) : undefined; if (!targets) { return [ { source: node, target: node, event: event, actions: transition.actions ? transition.actions.map(utils_1.getActionType) : [], cond: transition.cond, transition: transition } ]; } return targets .map(function (target) { try { var targetNode = target ? node.getRelativeStateNodes(target, undefined, false)[0] : node; return { source: node, target: targetNode, event: event, actions: transition.actions ? transition.actions.map(utils_1.getActionType) : [], cond: transition.cond, transition: transition }; } catch (e) { // tslint:disable-next-line:no-console if (!environment_1.IS_PRODUCTION) { utils_1.warn(e, "Target '" + target + "' not found on '" + node.id + "'"); } return undefined; } }) .filter(function (maybeEdge) { return maybeEdge !== undefined; }); })); } exports.getEventEdges = getEventEdges; function getEdges(node, options) { var e_1, _a, e_2, _b, e_3, _c; var _d = (options || {}).depth, depth = _d === void 0 ? null : _d; var edges = []; if (node.states && depth === null) { try { for (var _e = __values(utils_1.keys(node.states)), _f = _e.next(); !_f.done; _f = _e.next()) { var stateKey = _f.value; edges.push.apply(edges, __spread(getEdges(node.states[stateKey]))); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_f && !_f.done && (_a = _e.return)) _a.call(_e); } finally { if (e_1) throw e_1.error; } } } else if (depth && depth > 0) { try { for (var _g = __values(utils_1.keys(node.states)), _h = _g.next(); !_h.done; _h = _g.next()) { var stateKey = _h.value; edges.push.apply(edges, __spread(getEdges(node.states[stateKey], { depth: depth - 1 }))); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_h && !_h.done && (_b = _g.return)) _b.call(_g); } finally { if (e_2) throw e_2.error; } } } try { for (var _j = __values(utils_1.keys(node.on)), _k = _j.next(); !_k.done; _k = _j.next()) { var event_1 = _k.value; edges.push.apply(edges, __spread(getEventEdges(node, event_1))); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_k && !_k.done && (_c = _j.return)) _c.call(_j); } finally { if (e_3) throw e_3.error; } } return edges; } exports.getEdges = getEdges; function adjacencyMap(node, context) { var adjacency = {}; var events = node.events; function findAdjacencies(stateValue) { var e_4, _a; var stateKey = JSON.stringify(stateValue); if (adjacency[stateKey]) { return; } adjacency[stateKey] = {}; try { for (var events_1 = __values(events), events_1_1 = events_1.next(); !events_1_1.done; events_1_1 = events_1.next()) { var event_2 = events_1_1.value; var nextState = node.transition(stateValue, event_2, context); adjacency[stateKey][event_2] = { state: nextState.value }; findAdjacencies(nextState.value); } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (events_1_1 && !events_1_1.done && (_a = events_1.return)) _a.call(events_1); } finally { if (e_4) throw e_4.error; } } } findAdjacencies(node.initialState.value); return adjacency; } exports.adjacencyMap = adjacencyMap; function deserializeStateString(valueContextString) { var _a = __read(valueContextString.split(' | '), 2), valueString = _a[0], contextString = _a[1]; return { value: JSON.parse(valueString), context: contextString === undefined ? undefined : JSON.parse(contextString) }; } exports.deserializeStateString = deserializeStateString; function serializeState(state) { var value = state.value, context = state.context; return context === undefined ? JSON.stringify(value) : JSON.stringify(value) + ' | ' + JSON.stringify(context); } exports.serializeState = serializeState; function serializeEvent(event) { return JSON.stringify(event); } exports.serializeEvent = serializeEvent; function deserializeEventString(eventString) { return JSON.parse(eventString); } exports.deserializeEventString = deserializeEventString; var defaultValueAdjMapOptions = { events: {}, filter: function () { return true; }, formatContext: function (c) { return c; }, stateSerializer: serializeState, eventSerializer: serializeEvent }; function getValueAdjacencyMap(node, options) { var e_5, _a; var optionsWithDefaults = __assign({}, defaultValueAdjMapOptions, options); var filter = optionsWithDefaults.filter, stateSerializer = optionsWithDefaults.stateSerializer, eventSerializer = optionsWithDefaults.eventSerializer; var events = {}; try { for (var _b = __values(node.events), _c = _b.next(); !_c.done; _c = _b.next()) { var event_3 = _c.value; events[event_3] = [event_3]; } } catch (e_5_1) { e_5 = { error: e_5_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_5) throw e_5.error; } } Object.assign(events, optionsWithDefaults.events); var adjacency = {}; function findAdjacencies(state) { var e_6, _a; var nextEvents = state.nextEvents; var stateHash = stateSerializer(state); if (adjacency[stateHash]) { return; } adjacency[stateHash] = {}; var potentialEvents = utils_1.flatten(nextEvents.map(function (nextEvent) { return events[nextEvent] || []; })).map(function (event) { return actions_1.toEventObject(event); }); try { for (var potentialEvents_1 = __values(potentialEvents), potentialEvents_1_1 = potentialEvents_1.next(); !potentialEvents_1_1.done; potentialEvents_1_1 = potentialEvents_1.next()) { var event_4 = potentialEvents_1_1.value; var nextState = void 0; try { nextState = node.transition(state, event_4); } catch (e) { throw new Error("Unable to transition from state " + stateSerializer(state) + " on event " + eventSerializer(event_4) + ": " + e.message); } if ((!filter || filter(nextState)) && stateHash !== stateSerializer(nextState)) { adjacency[stateHash][eventSerializer(event_4)] = nextState; findAdjacencies(nextState); } } } catch (e_6_1) { e_6 = { error: e_6_1 }; } finally { try { if (potentialEvents_1_1 && !potentialEvents_1_1.done && (_a = potentialEvents_1.return)) _a.call(potentialEvents_1); } finally { if (e_6) throw e_6.error; } } } findAdjacencies(node.initialState); return adjacency; } exports.getValueAdjacencyMap = getValueAdjacencyMap; function getShortestPaths(machine, options) { var e_7, _a, e_8, _b; if (!machine.states) { // return EMPTY_MAP; return EMPTY_MAP; } var optionsWithDefaults = __assign({ events: {}, stateSerializer: serializeState, eventSerializer: serializeEvent }, options); var adjacency = getValueAdjacencyMap(machine, optionsWithDefaults); // weight, state, event var weightMap = new Map(); var stateMap = new Map(); var initialVertex = optionsWithDefaults.stateSerializer(machine.initialState); stateMap.set(initialVertex, machine.initialState); weightMap.set(initialVertex, [0, undefined, undefined]); var unvisited = new Set(); var visited = new Set(); unvisited.add(initialVertex); while (unvisited.size > 0) { try { for (var unvisited_1 = __values(unvisited), unvisited_1_1 = unvisited_1.next(); !unvisited_1_1.done; unvisited_1_1 = unvisited_1.next()) { var vertex = unvisited_1_1.value; var _c = __read(weightMap.get(vertex), 1), weight = _c[0]; try { for (var _d = __values(utils_1.keys(adjacency[vertex])), _e = _d.next(); !_e.done; _e = _d.next()) { var event_5 = _e.value; var nextState = adjacency[vertex][event_5]; var nextVertex = optionsWithDefaults.stateSerializer(nextState); stateMap.set(nextVertex, nextState); if (!weightMap.has(nextVertex)) { weightMap.set(nextVertex, [weight + 1, vertex, event_5]); } else { var _f = __read(weightMap.get(nextVertex), 1), nextWeight = _f[0]; if (nextWeight > weight + 1) { weightMap.set(nextVertex, [weight + 1, vertex, event_5]); } } if (!visited.has(nextVertex)) { unvisited.add(nextVertex); } } } catch (e_8_1) { e_8 = { error: e_8_1 }; } finally { try { if (_e && !_e.done && (_b = _d.return)) _b.call(_d); } finally { if (e_8) throw e_8.error; } } visited.add(vertex); unvisited.delete(vertex); } } catch (e_7_1) { e_7 = { error: e_7_1 }; } finally { try { if (unvisited_1_1 && !unvisited_1_1.done && (_a = unvisited_1.return)) _a.call(unvisited_1); } finally { if (e_7) throw e_7.error; } } } var pathMap = {}; weightMap.forEach(function (_a, stateSerial) { var _b = __read(_a, 3), weight = _b[0], fromState = _b[1], fromEvent = _b[2]; pathMap[stateSerial] = { state: stateMap.get(stateSerial), weight: weight, path: (function () { if (!fromState) { return []; } return pathMap[fromState].path.concat({ state: stateMap.get(fromState), event: deserializeEventString(fromEvent) }); })() }; }); return pathMap; } exports.getShortestPaths = getShortestPaths; // export function getShortestValuePaths< // TContext = DefaultContext, // TEvent extends EventObject = EventObject // >( // machine: StateNode, // options: ValueAdjMapOptions = defaultValueAdjMapOptions // ): PathMap { // if (!machine.states) { // return EMPTY_MAP; // } // const adjacency = getValueAdjacencyMap(machine, options); // const pathMap: PathMap = {}; // const visited: Set = new Set(); // function util(state: State): PathMap { // const stateKey = serializeState(state); // visited.add(stateKey); // const eventMap = adjacency[stateKey]; // for (const eventType of keys(eventMap)) { // const { value, context } = eventMap[eventType]; // if (!value) { // continue; // } // const nextState = State.from(value, context); // const nextStateId = serializeState(nextState); // if ( // !pathMap[nextStateId] || // pathMap[nextStateId].length > pathMap[stateKey].length + 1 // ) { // pathMap[nextStateId] = [ // ...(pathMap[stateKey] || []), // { // state: { value, context: state.context }, // event: deserializeEventString(eventType) as TEvent // } // ]; // } // if (visited.has(nextStateId)) { // continue; // } // util(nextState); // } // return pathMap; // } // util(machine.initialState); // return pathMap; // } // export function getShortestPathsAsArray< // TContext = DefaultContext, // TEvent extends EventObject = EventObject // >( // machine: StateNode // ): Array> { // const result = getShortestValuePaths( // machine, // defaultValueAdjMapOptions // ); // return keys(result).map(key => ({ // state: JSON.parse(key), // path: result[key] // })); // } function getSimplePaths(machine, options) { var e_9, _a; if (!machine.states) { return EMPTY_MAP; } var adjacency = getValueAdjacencyMap(machine, options); var stateMap = new Map(); var visited = new Set(); var path = []; var paths = {}; function util(fromStateSerial, toStateSerial) { var e_10, _a; visited.add(fromStateSerial); if (fromStateSerial === toStateSerial) { if (!paths[toStateSerial]) { paths[toStateSerial] = { state: stateMap.get(toStateSerial), paths: [] }; } paths[toStateSerial].paths.push(__spread(path)); } else { try { for (var _b = __values(utils_1.keys(adjacency[fromStateSerial])), _c = _b.next(); !_c.done; _c = _b.next()) { var subEvent = _c.value; var nextState = adjacency[fromStateSerial][subEvent]; if (!nextState) { continue; } var nextStateSerial = serializeState(nextState); stateMap.set(nextStateSerial, nextState); if (!visited.has(nextStateSerial)) { path.push({ state: stateMap.get(fromStateSerial), event: deserializeEventString(subEvent) }); util(nextStateSerial, toStateSerial); } } } catch (e_10_1) { e_10 = { error: e_10_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_10) throw e_10.error; } } } path.pop(); visited.delete(fromStateSerial); } var initialStateSerial = serializeState(machine.initialState); stateMap.set(initialStateSerial, machine.initialState); try { for (var _b = __values(utils_1.keys(adjacency)), _c = _b.next(); !_c.done; _c = _b.next()) { var nextStateSerial = _c.value; util(initialStateSerial, nextStateSerial); } } catch (e_9_1) { e_9 = { error: e_9_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_9) throw e_9.error; } } return paths; } exports.getSimplePaths = getSimplePaths; function getSimplePathsAsArray(machine, options) { var result = getSimplePaths(machine, options); return utils_1.keys(result).map(function (key) { return result[key]; }); } exports.getSimplePathsAsArray = getSimplePathsAsArray; //# sourceMappingURL=graph.js.map