fuzzy-rater
Version:
Tooling for fuzzily rating text according to some query
170 lines • 15.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getNodesFromIDs = exports.createID = exports.getReachableNodes = exports.getAvailableTransitionCharacter = exports.getRemainingTransition = exports.getCharacterTransition = exports.convertNFATemplateToDFATemplate = void 0;
function convertNFATemplateToDFATemplate(nodes, getMeta) {
const nodeMap = new Map(nodes.map(node => [node.ID, node]));
const outMap = new Map();
// Get the initial nodes
const { nodes: initNodes } = getReachableNodes(nodeMap, nodes.filter(({ initial }) => initial));
const initState = createID(initNodes);
// Iteratively keep adding nodes and their transitions
const stack = [initNodes];
let set;
while ((set = stack.shift())) {
const nodes = set;
// First make sure the node doesn't exist yet
const ID = createID(nodes);
if (outMap.has(ID))
continue;
// Figure out all transitions
const transitionChars = getAvailableTransitionCharacter(nodes);
const characterTransitions = transitionChars.map(char => {
const { transition, to } = getCharacterTransition(nodeMap, nodes, char, getMeta === null || getMeta === void 0 ? void 0 : getMeta.transitionMeta);
stack.push(to);
return transition;
});
const { transition: remainingTransition, to } = getRemainingTransition(nodeMap, nodes, getMeta === null || getMeta === void 0 ? void 0 : getMeta.transitionMeta);
stack.push(to);
// Create and store the node
const node = {
ID,
transitions: [...characterTransitions, remainingTransition],
metadata: getMeta
? { sources: nodes, ...getMeta.nodeMeta(nodes) }
: { sources: nodes },
};
outMap.set(ID, node);
}
// Return the dfa template
return { nodes: Array.from(outMap.values()), initial: initState };
}
exports.convertNFATemplateToDFATemplate = convertNFATemplateToDFATemplate;
/**
* Creates a transition, given a character and the node sets to transition from
* @param template All the nfa input nodes
* @param nodes The current state
* @param char The character to transition on
* @param getMeta An optional function to get extra metadata for the transition
* @returns The transition for this character
*/
function getCharacterTransition(template, nodes, char, getMeta) {
const transitions = [];
// Obtain the transitions for each node for this character
nodes.forEach(node => {
const charTransitions = node.transitions.filter(({ type, character }) => type == "character" && character == char);
let nodeTransitions;
if (charTransitions.length > 0) {
nodeTransitions = charTransitions;
}
else {
nodeTransitions = node.transitions.filter(({ type }) => type == "remaining");
}
nodeTransitions.forEach(transition => transitions.push({ from: node.ID, ...transition }));
});
// Get the ID of the end of the transition
const toNodesDirect = transitions.map(transition => transition.to);
const { nodes: toNodes, emptyTransitions } = getReachableNodes(template, getNodesFromIDs(template, toNodesDirect));
const to = createID(toNodes);
// Construct the transition
const sources = [...transitions, ...emptyTransitions];
return {
transition: {
to,
type: "character",
character: char,
metadata: getMeta
? { sources, ...getMeta(sources) }
: { sources },
},
to: toNodes,
};
}
exports.getCharacterTransition = getCharacterTransition;
/**
* Retrieves the transition for all characters for which no specific transition exists
* @param template All the nfa input nodes
* @param nodes The current state
* @param getMeta An optional function to get extra metadata for the transition
* @returns The transition for the remaining characters
*/
function getRemainingTransition(template, nodes, getMeta) {
const transitions = [];
// Obtain the transitions for each node for this character
nodes.forEach(node => {
const remainingTransitions = node.transitions.filter(({ type }) => type == "remaining");
remainingTransitions.forEach(transition => transitions.push({ from: node.ID, ...transition }));
});
// Get the ID of the end of the transition
const toNodesDirect = transitions.map(transition => transition.to);
const { nodes: toNodes, emptyTransitions } = getReachableNodes(template, getNodesFromIDs(template, toNodesDirect));
const to = createID(toNodes);
// Construct the transition
const sources = [...transitions, ...emptyTransitions];
return {
transition: {
to,
type: "remaining",
metadata: getMeta
? { sources, ...getMeta(sources) }
: { sources },
},
to: toNodes,
};
}
exports.getRemainingTransition = getRemainingTransition;
/**
* Retrieves the transition characters found in the given set of nodes
* @param nodes The nodes in which to look for transition characters
* @returns The transition character set
*/
function getAvailableTransitionCharacter(nodes) {
return Array.from(new Set(nodes
.flatMap(({ transitions }) => transitions)
.filter(({ type }) => type == "character")
.map(({ character }) => character)
.filter((char) => !!char)));
}
exports.getAvailableTransitionCharacter = getAvailableTransitionCharacter;
/**
* Checks what nodes are reachable with the given set, by using empty transitions
* @param template All the nfa input nodes
* @param nodes The nodes to get the closure of, (may include duplicates, which will be removed)
* @returns The reach of these nodes
*/
function getReachableNodes(template, nodes) {
const reachableNodes = new Set(nodes);
const emptyTransitions = [];
for (let node of reachableNodes) {
const nodeEmptyTransitions = node.transitions.filter(({ type }) => type == "empty");
const transitionNodes = getNodesFromIDs(template, nodeEmptyTransitions.map(({ to }) => to));
transitionNodes.forEach(node => reachableNodes.add(node));
nodeEmptyTransitions.forEach(transition => emptyTransitions.push({ from: node.ID, ...transition }));
}
return {
nodes: Array.from(reachableNodes),
emptyTransitions: Array.from(emptyTransitions),
};
}
exports.getReachableNodes = getReachableNodes;
/**
* Creates an ID to uniquely define a set of nodes, no matter what the order is
* @param nodes The nodes to create the ID for
* @returns The created ID
*/
function createID(nodes) {
const IDs = nodes.map(node => (typeof node == "string" ? node : node.ID));
const sorted = IDs.sort();
return `{${sorted.join(",")}}`;
}
exports.createID = createID;
/**
* Retrieves nodes given the list of IDs
* @param map The map of items that the nodes are in
* @param IDs The IDs of the nodes to retrieve
* @returns The nodes
*/
function getNodesFromIDs(map, IDs) {
return IDs.map(ID => map.get(ID)).filter((n) => !!n);
}
exports.getNodesFromIDs = getNodesFromIDs;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udmVydE5GQVRlbXBsYXRlVG9ERkFUZW1wbGF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9ERkEvTkZBREZBL2NvbnZlcnRORkFUZW1wbGF0ZVRvREZBVGVtcGxhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBaUNBLFNBQWdCLCtCQUErQixDQUMzQyxLQUFtQyxFQUNuQyxPQUEwQztJQUUxQyxNQUFNLE9BQU8sR0FBRyxJQUFJLEdBQUcsQ0FDbkIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUNyQyxDQUFDO0lBQ0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQXFDLENBQUM7SUFFNUQsd0JBQXdCO0lBQ3hCLE1BQU0sRUFBQyxLQUFLLEVBQUUsU0FBUyxFQUFDLEdBQUcsaUJBQWlCLENBQ3hDLE9BQU8sRUFDUCxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBQyxPQUFPLEVBQUMsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQ3ZDLENBQUM7SUFDRixNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFdEMsc0RBQXNEO0lBQ3RELE1BQU0sS0FBSyxHQUFpQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3hELElBQUksR0FBMkMsQ0FBQztJQUNoRCxPQUFPLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFO1FBQzFCLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQztRQUVsQiw2Q0FBNkM7UUFDN0MsTUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNCLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFBRSxTQUFTO1FBRTdCLDZCQUE2QjtRQUM3QixNQUFNLGVBQWUsR0FBRywrQkFBK0IsQ0FB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