You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
52 lines
1.4 KiB
52 lines
1.4 KiB
import type { MothershipAddressCandidate } from "@/lib/frontend/types";
|
|
|
|
/** 从候选列表中按门牌号/城市/街道词打分,避免误选 Bridge 等歧义项 */
|
|
export function pickBestMothershipCandidate(
|
|
candidates: MothershipAddressCandidate[],
|
|
draft: { street: string; city: string; state: string },
|
|
): MothershipAddressCandidate | undefined {
|
|
if (!candidates.length) {
|
|
return undefined;
|
|
}
|
|
const streetNum = draft.street.match(/^\d+/)?.[0];
|
|
const city = draft.city.trim().toLowerCase();
|
|
const state = draft.state.trim().toLowerCase();
|
|
const streetWords = draft.street
|
|
.toLowerCase()
|
|
.split(/\s+/)
|
|
.filter((w) => w.length > 2 && !/^(st|street|ave|avenue|rd|road|blvd|dr|drive)$/i.test(w));
|
|
|
|
let best = candidates[0]!;
|
|
let bestScore = -1;
|
|
for (const candidate of candidates) {
|
|
const label = (
|
|
candidate.display_label ||
|
|
candidate.formatted_address ||
|
|
""
|
|
).toLowerCase();
|
|
let score = 0;
|
|
if (streetNum && label.includes(streetNum)) {
|
|
score += 12;
|
|
}
|
|
if (city && label.includes(city)) {
|
|
score += 6;
|
|
}
|
|
if (state && label.includes(state)) {
|
|
score += 3;
|
|
}
|
|
for (const word of streetWords) {
|
|
if (label.includes(word)) {
|
|
score += 2;
|
|
}
|
|
}
|
|
if (/\bbridge\b/.test(label) && !/\bbridge\b/i.test(draft.street)) {
|
|
score -= 20;
|
|
}
|
|
if (score > bestScore) {
|
|
bestScore = score;
|
|
best = candidate;
|
|
}
|
|
}
|
|
return best;
|
|
}
|