fix(rust): first-max tie-breaking in dir matching + python-style score rounding
Two divergences found by diffing the Rust sorter plan against the python reference on a real 14k-file tree (both 99.82% identical): - compute_match_name used max_by (LAST max) where python max() keeps the FIRST; a same-faction dir hit and a cross-faction hit scored equally and the wrong entry won (25 Deathwatch files). - --json score used round() instead of round_ties_even(), printing 0.813 where python prints 0.812. After the fix the plans are identical: 14025/14025 targets, kinds and scores, zero differences.
This commit is contained in:
@@ -538,7 +538,7 @@ fn cmd_sorter(args: &SorterArgs) -> anyhow::Result<()> {
|
||||
"subfaction": i.subfaction,
|
||||
"class": i.klass,
|
||||
"unit": i.unit,
|
||||
"score": (i.match_score * 1000.0).round() / 1000.0,
|
||||
"score": (i.match_score * 1000.0).round_ties_even() / 1000.0,
|
||||
"kind": i.match_kind,
|
||||
"inner_count": i.inner_names.len(),
|
||||
"target": i.target
|
||||
|
||||
@@ -906,16 +906,22 @@ fn compute_match_name(
|
||||
}
|
||||
}
|
||||
let cands: Vec<(f64, usize, bool)> = [same, other].into_iter().flatten().collect();
|
||||
if !cands.is_empty() {
|
||||
let normals: Vec<&(f64, usize, bool)> = cands.iter().filter(|c| !c.2).collect();
|
||||
let winner = if normals.is_empty() {
|
||||
cands.iter().max_by(|a, b| a.0.total_cmp(&b.0)).unwrap()
|
||||
} else {
|
||||
normals.iter().max_by(|a, b| a.0.total_cmp(&b.0)).unwrap()
|
||||
};
|
||||
return Some(winner.clone());
|
||||
if cands.is_empty() {
|
||||
return None;
|
||||
}
|
||||
None
|
||||
// python `max(normals or cands, key=score)` keeps the FIRST
|
||||
// maximum; a normal (non-weak) candidate always beats a weak one.
|
||||
let has_normal = cands.iter().any(|c| !c.2);
|
||||
let mut winner: Option<(f64, usize, bool)> = None;
|
||||
for c in &cands {
|
||||
if has_normal && c.2 {
|
||||
continue;
|
||||
}
|
||||
if winner.as_ref().is_none_or(|w| c.0 > w.0) {
|
||||
winner = Some(c.clone());
|
||||
}
|
||||
}
|
||||
return winner;
|
||||
} else {
|
||||
pool_best(clean, &pool, ctx, threshold, cache)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user