mirror of
https://github.com/samsonjs/spirit-tracker.git
synced 2026-04-27 15:07:43 +00:00
sku updates
This commit is contained in:
parent
198d3abe19
commit
a154e7d284
1 changed files with 38 additions and 10 deletions
|
|
@ -49,40 +49,68 @@ function similarityScore(aName, bName) {
|
||||||
const b = normSearchText(bName);
|
const b = normSearchText(bName);
|
||||||
if (!a || !b) return 0;
|
if (!a || !b) return 0;
|
||||||
|
|
||||||
const A = new Set(tokenizeQuery(a));
|
const aToks = tokenizeQuery(a);
|
||||||
const B = new Set(tokenizeQuery(b));
|
const bToks = tokenizeQuery(b);
|
||||||
|
if (!aToks.length || !bToks.length) return 0;
|
||||||
|
|
||||||
|
const aFirst = aToks[0] || "";
|
||||||
|
const bFirst = bToks[0] || "";
|
||||||
|
const firstMatch = aFirst && bFirst && aFirst === bFirst ? 1 : 0;
|
||||||
|
|
||||||
|
// Compare tails (everything after first token)
|
||||||
|
const A = new Set(aToks.slice(1));
|
||||||
|
const B = new Set(bToks.slice(1));
|
||||||
let inter = 0;
|
let inter = 0;
|
||||||
for (const w of A) if (B.has(w)) inter++;
|
for (const w of A) if (B.has(w)) inter++;
|
||||||
const denom = Math.max(1, Math.max(A.size, B.size));
|
const denom = Math.max(1, Math.max(A.size, B.size));
|
||||||
const overlap = inter / denom;
|
const overlapTail = inter / denom;
|
||||||
|
|
||||||
const d = levenshtein(a, b);
|
const d = levenshtein(a, b);
|
||||||
const maxLen = Math.max(1, Math.max(a.length, b.length));
|
const maxLen = Math.max(1, Math.max(a.length, b.length));
|
||||||
const levSim = 1 - d / maxLen;
|
const levSim = 1 - d / maxLen;
|
||||||
|
|
||||||
return overlap * 2.2 + levSim * 1.0;
|
// Gate tail similarity hard unless first word matches
|
||||||
|
const gate = firstMatch ? 1.0 : 0.12;
|
||||||
|
|
||||||
|
return (
|
||||||
|
firstMatch * 3.0 + // first word dominates
|
||||||
|
overlapTail * 2.2 * gate + // tail matters mostly after first word match
|
||||||
|
levSim * (firstMatch ? 1.0 : 0.15) // edit-sim also mostly after first word match
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function fastSimilarityScore(aTokens, bTokens, aNormName, bNormName) {
|
function fastSimilarityScore(aTokens, bTokens, aNormName, bNormName) {
|
||||||
if (!aTokens.length || !bTokens.length) return 0;
|
if (!aTokens.length || !bTokens.length) return 0;
|
||||||
|
|
||||||
|
const aFirst = aTokens[0] || "";
|
||||||
|
const bFirst = bTokens[0] || "";
|
||||||
|
const firstMatch = aFirst && bFirst && aFirst === bFirst ? 1 : 0;
|
||||||
|
|
||||||
|
// Tail overlap only
|
||||||
|
const aTail = aTokens.slice(1);
|
||||||
|
const bTail = bTokens.slice(1);
|
||||||
|
|
||||||
let inter = 0;
|
let inter = 0;
|
||||||
const bSet = new Set(bTokens);
|
const bSet = new Set(bTail);
|
||||||
for (const t of aTokens) if (bSet.has(t)) inter++;
|
for (const t of aTail) if (bSet.has(t)) inter++;
|
||||||
|
|
||||||
const denom = Math.max(1, Math.max(aTokens.length, bTokens.length));
|
const denom = Math.max(1, Math.max(aTail.length, bTail.length));
|
||||||
const overlap = inter / denom;
|
const overlapTail = inter / denom;
|
||||||
|
|
||||||
|
// Existing prefix bonus, but only when first word matches
|
||||||
const a = String(aNormName || "");
|
const a = String(aNormName || "");
|
||||||
const b = String(bNormName || "");
|
const b = String(bNormName || "");
|
||||||
const pref =
|
const pref =
|
||||||
a.slice(0, 10) && b.slice(0, 10) && a.slice(0, 10) === b.slice(0, 10)
|
firstMatch && a.slice(0, 10) && b.slice(0, 10) && a.slice(0, 10) === b.slice(0, 10)
|
||||||
? 0.2
|
? 0.2
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
return overlap * 2.0 + pref;
|
const gate = firstMatch ? 1.0 : 0.12;
|
||||||
|
|
||||||
|
return firstMatch * 2.4 + overlapTail * 2.0 * gate + pref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ---------------- Store-overlap rule ---------------- */
|
/* ---------------- Store-overlap rule ---------------- */
|
||||||
|
|
||||||
function storesOverlap(aItem, bItem) {
|
function storesOverlap(aItem, bItem) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue