fuzzy-rater
Version:
Tooling for fuzzily rating text according to some query
164 lines • 10.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getID = exports.getTransitions = exports.createFuzzyNFATemplate = void 0;
/**
* Creates a new dfa template based on the query and max distance
* @param query The query to create a template for
* @param maxDistance The maximal allowed distance
* @param exitOnMatch Whether the NFA should exit out of the node after match
* @returns A dfa template
*/
function createFuzzyNFATemplate(query, maxDistance, exitOnMatch = false) {
const nodes = [];
// Add the initial node
nodes.push({
ID: getID(query, 0, -1),
initial: true,
transitions: [...getTransitions(query, maxDistance, 0, -1)],
metadata: {
matched: false,
searchIndex: 0,
distance: 0,
},
});
// Compute the grid of nodes
for (let dist = 0; dist <= maxDistance; dist++) {
for (let i = 0; i < query.length; i++) {
nodes.push({
ID: getID(query, dist, i),
initial: false,
transitions: [
...getTransitions(query, maxDistance, dist, i, exitOnMatch),
],
metadata: {
matched: i + 1 == query.length,
searchIndex: i + 1,
distance: dist,
},
});
}
}
return nodes;
}
exports.createFuzzyNFATemplate = createFuzzyNFATemplate;
/**
* Retrieves all the transitions for a given node
* @param query The query the transitions are for
* @param maxDist The maximal allowed distance
* @param dist The current distance
* @param index The index of character matched so far
* @param exitOnMatch Whether the NFA should exit out of the node after match
* @returns The set of transitions from this node
*/
function getTransitions(query, maxDist, dist, index, exitOnMatch = false) {
const nextIndex = index + 1;
const nextChar = query[nextIndex];
const transitions = [];
if (nextChar) {
// Literal character match
transitions.push({
to: getID(query, dist, nextIndex),
type: "character",
character: nextChar,
metadata: {
type: "match",
index: nextIndex,
character: nextChar,
},
});
if (dist < maxDist) {
// Skip query character
transitions.push({
to: getID(query, dist + 1, nextIndex),
type: "empty",
metadata: {
type: "skip",
index: nextIndex,
character: nextChar,
},
});
// Replace query character
transitions.push({
to: getID(query, dist + 1, nextIndex),
type: "remaining",
metadata: {
type: "replace",
index: nextIndex,
character: nextChar,
},
});
}
}
if (dist < maxDist && -1 < index && index < query.length - 1) {
// Insert random character in the query
transitions.push({
to: getID(query, dist + 1, index),
type: "remaining",
metadata: {
index: nextIndex,
type: "insert",
},
});
}
if (index == -1) {
// Match any number of characters before query (including the first character itself)
transitions.push({
to: getID(query, dist, index),
type: "remaining",
metadata: {
index: nextIndex,
type: "ignore",
},
});
transitions.push({
to: getID(query, dist, index),
type: "character",
character: nextChar,
metadata: {
index: nextIndex,
type: "ignore",
},
});
}
if (nextIndex == query.length) {
if (!exitOnMatch) {
// Match any number of characters after query
transitions.push({
to: getID(query, dist, index),
type: "remaining",
metadata: {
index: nextIndex,
type: "ignore",
},
});
}
else {
// Match any number of characters after query
transitions.push({
to: getID(query, 0, -1),
type: "empty",
metadata: {
index: nextIndex,
type: "restart",
},
});
}
}
return transitions;
}
exports.getTransitions = getTransitions;
/**
* Retrieves the ID for a node with the given data
* @param query The query the node is for
* @param dist The correctness distance the node is for
* @param index The character index matched by the node
* @returns THe ID for the node
*/
function getID(query, dist, index) {
return index == -1
? `start:${dist}`
: `${index}:${query.substring(0, index + 1)}-${dist}`;
// return `${index}:${dist}`;
}
exports.getID = getID;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlRnV6enlORkFUZW1wbGF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mdXp6eVJhdGUvd29yZE1hdGNoZXIvY3JlYXRlRnV6enlORkFUZW1wbGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFNQTs7Ozs7O0dBTUc7QUFDSCxTQUFnQixzQkFBc0IsQ0FDbEMsS0FBYSxFQUNiLFdBQW1CLEVBQ25CLGNBQXVCLEtBQUs7SUFFNUIsTUFBTSxLQUFLLEdBQUcsRUFHWCxDQUFDO0lBRUosdUJBQXVCO0lBQ3ZCLEtBQUssQ0FBQyxJQUFJLENBQUM7UUFDUCxFQUFFLEVBQUUsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDdkIsT0FBTyxFQUFFLElBQUk7UUFDYixXQUFXLEVBQUUsQ0FBQyxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNELFFBQVEsRUFBRTtZQUNOLE9BQU8sRUFBRSxLQUFLO1lBQ2QsV0FBVyxFQUFFLENBQUM7WUFDZCxRQUFRLEVBQUUsQ0FBQztTQUNkO0tBQ0osQ0FBQyxDQUFDO0lBRUgsNEJBQTRCO0lBQzVCLEtBQUssSUFBSSxJQUFJLEdBQUcsQ0FBQyxFQUFFLElBQUksSUFBSSxXQUFXLEVBQUUsSUFBSSxFQUFFLEVBQUU7UUFDNUMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDbkMsS0FBSyxDQUFDLElBQUksQ0FBQztnQkFDUCxFQUFFLEVBQUUsS0FBSyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUN6QixPQUFPLEVBQUUsS0FBSztnQkFDZCxXQUFXLEVBQUU7b0JBQ1QsR0FBRyxjQUFjLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVB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