fix(scheduling): exclude near-qualified vehicles from rescue candidates
For rescue_hopeless (换走) scenario, filter out inventory candidates where totalMileage/yearTarget >= 80%. These are already near target and swapping them in adds no value. Instead, prioritize candidates with biggest mileage gaps — they benefit most from accumulating any mileage, even at a low-mileage customer. Before: showed 粤AGR6869 (93% done, 缺口 1990) as "可达标" — pointless After: shows 浙FF58720 (0% done, 缺口 60000) — genuinely needs mileage Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -76,13 +76,21 @@ export function generateSuggestions(
|
||||
const suggestions: SchedulingSuggestion[] = [];
|
||||
|
||||
// --- rescue_hopeless (high priority) ---
|
||||
// For this scenario: take the hopeless car away to a high-mileage customer,
|
||||
// and give the low-mileage customer a replacement from inventory.
|
||||
// Exclude near-qualified candidates (completionRate >= 80%) — no point swapping
|
||||
// in a car that's basically already at target.
|
||||
// Instead, pick cars with BIG gaps: they benefit from any mileage, even at a low customer.
|
||||
for (const vehicle of hopeless) {
|
||||
const candidates: CandidateVehicle[] = inventoryVehicles
|
||||
.filter(
|
||||
(inv) =>
|
||||
isTypeCompatible(vehicle.vehicleType, inv.vehicleType) &&
|
||||
inv.region === vehicle.region,
|
||||
)
|
||||
.filter((inv) => {
|
||||
if (!isTypeCompatible(vehicle.vehicleType, inv.vehicleType)) return false;
|
||||
if (inv.region !== vehicle.region) return false;
|
||||
// Exclude near-qualified: yearTarget known and already >= 80% done
|
||||
const effectiveTarget = inv.yearTarget ?? vehicle.yearTarget;
|
||||
if (effectiveTarget > 0 && inv.totalMileage / effectiveTarget >= 0.8) return false;
|
||||
return true;
|
||||
})
|
||||
.map((inv) => {
|
||||
const effectiveTarget = inv.yearTarget ?? vehicle.yearTarget;
|
||||
const mileageGap = Math.max(0, effectiveTarget - inv.totalMileage);
|
||||
@@ -105,10 +113,8 @@ export function generateSuggestions(
|
||||
};
|
||||
})
|
||||
.sort((a, b) => {
|
||||
if (a.canQualifyAfterSwap !== b.canQualifyAfterSwap)
|
||||
return a.canQualifyAfterSwap ? -1 : 1;
|
||||
// For hopeless: prefer already-qualified inventory, then highest completion
|
||||
return b.completionRate - a.completionRate;
|
||||
// Prefer biggest gap first — these benefit most from any mileage
|
||||
return b.mileageGap - a.mileageGap;
|
||||
})
|
||||
.slice(0, 5);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user