Initial commit
Next.js + Express event management app for Hope Family Church.
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
/** Levenshtein edit distance between two strings */
|
||||
export function editDistance(a: string, b: string): number {
|
||||
const m = a.length, n = b.length;
|
||||
const dp: number[] = Array(n + 1).fill(0).map((_, j) => j);
|
||||
for (let i = 1; i <= m; i++) {
|
||||
let prev = dp[0];
|
||||
dp[0] = i;
|
||||
for (let j = 1; j <= n; j++) {
|
||||
const temp = dp[j];
|
||||
dp[j] = a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
|
||||
prev = temp;
|
||||
}
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/** Return a score 0–1 for how well a user matches a search query */
|
||||
export function scoreUser(u: any, raw: string): number {
|
||||
const q = raw.toLowerCase().trim();
|
||||
if (!q || q.length < 2) return 0;
|
||||
|
||||
const name = (u.name || "").toLowerCase();
|
||||
const email = (u.email || "").toLowerCase();
|
||||
const phone = (u.phoneNumber || "").replace(/\D/g, "");
|
||||
const qPhone = q.replace(/\D/g, "");
|
||||
|
||||
let best = 0;
|
||||
|
||||
// Exact substring matches — highest priority
|
||||
if (name.includes(q)) best = Math.max(best, 1.0);
|
||||
if (email.includes(q)) best = Math.max(best, 0.95);
|
||||
if (qPhone.length >= 3 && phone.includes(qPhone)) best = Math.max(best, 0.95);
|
||||
|
||||
// Word-level starts-with (handles partial first/last name)
|
||||
const words = name.split(/\s+/);
|
||||
if (words.some((w: string) => w.startsWith(q))) best = Math.max(best, 0.85);
|
||||
|
||||
// Fuzzy edit-distance against each name word
|
||||
const maxDist = q.length <= 4 ? 1 : q.length <= 7 ? 2 : 3;
|
||||
for (const w of words) {
|
||||
const slice = w.slice(0, q.length + 2); // compare against similar-length slice
|
||||
const d = editDistance(q, slice);
|
||||
if (d <= maxDist) best = Math.max(best, 0.75 - d * 0.15);
|
||||
}
|
||||
// Also fuzzy against the full name (catches "jhn smth" → "john smith")
|
||||
const nameSlice = name.slice(0, q.length + 4);
|
||||
const fullDist = editDistance(q, nameSlice);
|
||||
if (fullDist <= maxDist + 1) best = Math.max(best, 0.6 - fullDist * 0.12);
|
||||
|
||||
return best;
|
||||
}
|
||||
Reference in New Issue
Block a user