- 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
63 lines
2.3 KiB
Rust
63 lines
2.3 KiB
Rust
//! Command dispatch and shared helpers.
|
|
//!
|
|
//! Provides the `run_analysis` orchestration function and `load_my_cars_or_warn`
|
|
//! helper used by all command handlers.
|
|
|
|
pub mod all;
|
|
pub mod best;
|
|
pub mod details;
|
|
pub mod fetch;
|
|
pub mod improve;
|
|
pub mod track;
|
|
pub mod trash;
|
|
pub mod wishlist;
|
|
|
|
use std::sync::Arc;
|
|
|
|
use top_drives::{
|
|
compute_car_counts, load_my_cars_data, AnalysisContext, AppError, CarCounts, MyCarsData,
|
|
};
|
|
|
|
use crate::parsing::parse_all_times;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helper: load my_cars.json with graceful degradation
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Loads user car data, printing a warning and returning empty data if the file is missing.
|
|
///
|
|
/// Only `MissingFile` errors are gracefully degraded — parse errors and other
|
|
/// failures are propagated to the caller, because running analysis with
|
|
/// silently-corrupted ownership data would produce misleading results.
|
|
pub fn load_my_cars_or_warn(path: &str) -> Result<MyCarsData, AppError> {
|
|
match load_my_cars_data(path) {
|
|
Ok(data) => Ok(data),
|
|
Err(AppError::MissingFile(msg)) => {
|
|
eprintln!("Warning: {msg}");
|
|
eprintln!(" Analysis will run without ownership data.");
|
|
Ok(MyCarsData::default())
|
|
}
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Analysis orchestration
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Common analysis setup: loads user data, parses all timing files, and computes car counts.
|
|
///
|
|
/// Returns the analysis context (for stdout commands) and the aggregated car counts
|
|
/// (for CSV output commands). The car list is stored inside `CarCounts`.
|
|
pub async fn run_analysis(
|
|
my_data: &MyCarsData,
|
|
cars_db_path: &str,
|
|
times_dir: &str,
|
|
) -> Result<(AnalysisContext, CarCounts), AppError> {
|
|
let ctx = AnalysisContext::new();
|
|
let owned = Arc::new(my_data.owned.clone());
|
|
let car_list = parse_all_times(owned, &ctx, cars_db_path, times_dir).await?;
|
|
// Move only owned_configs; construct a new MyCarsData to transfer ownership.
|
|
let counts = compute_car_counts(&ctx, car_list, my_data.owned_configs.clone());
|
|
Ok((ctx, counts))
|
|
}
|