feat: add normalized config tracking and improve command
- Add normalize_to_final_build() to map tune configs to final builds (323/233/332) - Add normalized_config field to BestCarRecord - Change CarCounts.by_rid key from String to (String, String) for per-config tracking - Change CarCounts.guid_to_rid to HashMap<String, HashSet<(String, String)>> - Extract owned tune configs from my_cars.json (engineMajor/weightMajor/chassisMajor) - Add improve command: owned cars not yet at final build, sorted by track count - Strip version prefixes (v2c_/v1c_) from config keys at parse time - Update dedup check in update_best_car to consider normalized_config - Add atomic_write helper for safe CSV output - Delete completed plans/code-review-v2.md - Apply rustfmt formatting across codebase
This commit is contained in:
parent
67a79f190a
commit
bf21d3d1f6
25 changed files with 735 additions and 759 deletions
|
|
@ -2,19 +2,19 @@
|
|||
|
||||
use proptest::prelude::*;
|
||||
|
||||
use top_drives::{compare_cars, compute_car_counts, AnalysisContext, Car};
|
||||
use top_drives::test_utils::{make_car, make_record};
|
||||
use top_drives::{compare_cars, compute_car_counts, empty_my_data, AnalysisContext, Car};
|
||||
|
||||
/// Generate arbitrary Car instances for property testing.
|
||||
fn car_strategy() -> impl Strategy<Value = Car> {
|
||||
(
|
||||
"[a-zA-Z]{2,10}", // rid
|
||||
"[a-zA-Z]{2,15}", // brand
|
||||
"[a-zA-Z0-9 ]{2,20}", // only_name
|
||||
1950u16..2030, // year
|
||||
10u8..113, // rq
|
||||
any::<bool>(), // prize
|
||||
"[a-zA-Z0-9_]{3,20}", // guid
|
||||
"[a-zA-Z]{2,10}", // rid
|
||||
"[a-zA-Z]{2,15}", // brand
|
||||
"[a-zA-Z0-9 ]{2,20}", // only_name
|
||||
1950u16..2030, // year
|
||||
10u8..113, // rq
|
||||
any::<bool>(), // prize
|
||||
"[a-zA-Z0-9_]{3,20}", // guid
|
||||
)
|
||||
.prop_map(|(rid, brand, only_name, year, rq, prize, guid)| Car {
|
||||
rid,
|
||||
|
|
@ -177,7 +177,7 @@ proptest! {
|
|||
cars in proptest::collection::vec(car_strategy(), 0..20)
|
||||
) {
|
||||
let ctx = AnalysisContext::default();
|
||||
let counts = compute_car_counts(&ctx, cars.clone());
|
||||
let counts = compute_car_counts(&ctx, cars.clone(), empty_my_data());
|
||||
// No best_cars entries → every car has 0 wins → by_rid is empty
|
||||
assert_eq!(counts.by_rid.len(), 0);
|
||||
// guid_to_rid is also empty since no car won any track
|
||||
|
|
@ -212,9 +212,9 @@ proptest! {
|
|||
}
|
||||
|
||||
let car_list = vec![make_car(&rid, rq, &guid)];
|
||||
let counts = compute_car_counts(&ctx, car_list);
|
||||
let counts = compute_car_counts(&ctx, car_list, empty_my_data());
|
||||
|
||||
let entry = counts.by_rid.get(&rid);
|
||||
let entry = counts.by_rid.get(&(rid.clone(), "332".to_string()));
|
||||
assert!(entry.is_some(), "car should appear in by_rid");
|
||||
let (_, count) = entry.unwrap();
|
||||
assert_eq!(*count, n_tracks, "count should match number of tracks");
|
||||
|
|
@ -240,9 +240,9 @@ proptest! {
|
|||
);
|
||||
|
||||
let car_list = vec![make_car(&rid, rq, &guid)];
|
||||
let counts = compute_car_counts(&ctx, car_list);
|
||||
let counts = compute_car_counts(&ctx, car_list, empty_my_data());
|
||||
|
||||
let (record, _) = counts.by_rid.get(&rid).unwrap();
|
||||
let (record, _) = counts.by_rid.get(&(rid, "332".to_string())).unwrap();
|
||||
assert_eq!(record.owned, owned, "owned flag should propagate");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue