fix: default to first disposition when text lists two, e.g. "X (Y)"
Some sources list two dispositions together (a team template noting a secondary/alternate, e.g. "Purge the Foe (Reconnaissance)"). Split on the separators that join them and match segment-by-segment left to right, so the first one listed wins instead of whichever scored closer across the combined string. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+19
-5
@@ -143,9 +143,9 @@ const normalizeDispositionText = s => String(s || "").trim().toLowerCase().repla
|
||||
// drop "and"/"the" (e.g. "Take Hold") still line up: "Take and Hold" -> "take hold".
|
||||
const dispositionCore = canonical => normalizeDispositionText(canonical).replace(/\b(and|the)\b/g, "").replace(/\s+/g, " ").trim();
|
||||
|
||||
// Nearest canonical disposition, or null if nothing is close enough to be
|
||||
// confident it's a typo/abbreviation rather than unrelated text.
|
||||
// Two ways to match:
|
||||
// Nearest canonical disposition for a single (already-normalized) segment, or
|
||||
// null if nothing is close enough to be confident it's a typo/abbreviation
|
||||
// rather than unrelated text. Two ways to match:
|
||||
// - Prefix: shorthand like "Recon" or "Disrupt" that's a truncation, not a
|
||||
// typo, so Levenshtein distance alone would score it as far away. Gated
|
||||
// to 3+ chars so short unrelated words can't collide (the five names'
|
||||
@@ -153,8 +153,7 @@ const dispositionCore = canonical => normalizeDispositionText(canonical).replace
|
||||
// - Levenshtein: everything else, e.g. "Priority Assests". Threshold scales
|
||||
// with name length (~25%) so a short unrelated line doesn't accidentally
|
||||
// match "Disruption".
|
||||
function closestDisposition(name) {
|
||||
const norm = normalizeDispositionText(name);
|
||||
function matchDispositionSegment(norm) {
|
||||
if (!norm) return null;
|
||||
let best = null, bestDist = Infinity;
|
||||
for (const canonical of CANONICAL_DISPOSITIONS) {
|
||||
@@ -168,6 +167,21 @@ function closestDisposition(name) {
|
||||
return bestDist <= threshold ? best : null;
|
||||
}
|
||||
|
||||
// Some sources list two dispositions together, e.g. "Purge the Foe
|
||||
// (Reconnaissance)" (a team template noting a secondary/alternate) or
|
||||
// "Take and Hold / Priority Assets". Split on the separators that join them
|
||||
// and match segment-by-segment left to right, so whichever is listed first
|
||||
// wins rather than whichever happens to score closer across the whole string.
|
||||
function closestDisposition(name) {
|
||||
const raw = String(name || "");
|
||||
const segments = raw.split(/[()\/|,;]+|\s+vs\.?\s+/i).map(s => s.trim()).filter(Boolean);
|
||||
for (const seg of segments.length ? segments : [raw]) {
|
||||
const match = matchDispositionSegment(normalizeDispositionText(seg));
|
||||
if (match) return match;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const correctDisposition = name => closestDisposition(name) || name;
|
||||
|
||||
// The vocabulary of disposition names is whatever this event's own roster
|
||||
|
||||
Reference in New Issue
Block a user