Corrected handling of tied times

This commit is contained in:
Jan-Peter von Hunnius 2025-05-29 10:47:05 +02:00
parent ad60ab1b11
commit 4e299db3c0

View file

@ -1,14 +1,19 @@
use futures::future::join_all;
use once_cell::sync::Lazy;
use reqwest::get;
use serde_json::Value;
use std::collections::HashMap; use std::collections::HashMap;
use std::env; use std::env;
use std::fs; use std::fs;
use std::sync::Mutex; use std::sync::Mutex;
use tokio::sync::Semaphore; use tokio::sync::Semaphore;
use tokio::task; use tokio::task;
use futures::future::join_all;
use once_cell::sync::Lazy;
use reqwest::get;
use serde_json::Value;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct Car { struct Car {
rid: String, rid: String,
@ -28,7 +33,7 @@ struct BestCarRecord {
time: f64, time: f64,
} }
type TripletKey = (String, u8, String); // (Track ID, RQ, Surface) type TripletKey = (String, u8, String); // (Track ID, RQ, Surface)
static BEST_CARS: Lazy<Mutex<HashMap<TripletKey, BestCarRecord>>> = static BEST_CARS: Lazy<Mutex<HashMap<TripletKey, Vec<BestCarRecord>>>> =
Lazy::new(|| Mutex::new(HashMap::new())); Lazy::new(|| Mutex::new(HashMap::new()));
#[tokio::main] #[tokio::main]
@ -81,7 +86,8 @@ fn print_best_times() {
sorted_keys.sort_by(|a, b| a.1.cmp(&b.1).then(a.0.cmp(&b.0))); // Sort by RQ, then Track ID sorted_keys.sort_by(|a, b| a.1.cmp(&b.1).then(a.0.cmp(&b.0))); // Sort by RQ, then Track ID
for key in sorted_keys { for key in sorted_keys {
let best_car = best_cars.get(key).unwrap(); if let Some(records) = best_cars.get(key) {
for best_car in records {
println!( println!(
"{},{},{},{},{},{},{},{},{}", "{},{},{},{},{},{},{},{},{}",
key.1, key.1,
@ -95,22 +101,26 @@ fn print_best_times() {
best_car.time best_car.time
); );
} }
}
}
} }
fn print_best_cars() { fn print_best_cars() {
let best_cars = BEST_CARS.lock().unwrap(); let best_cars = BEST_CARS.lock().unwrap();
let mut car_count: HashMap<String, (BestCarRecord, usize)> = HashMap::new(); let mut car_count: HashMap<String, (BestCarRecord, usize)> = HashMap::new();
// Count occurrences and store RQ // Count occurrences and store RQ
for (_key, best_car) in best_cars.iter() { for (_key, best_list) in best_cars.iter() {
for best_car in best_list {
let entry = car_count let entry = car_count
.entry(best_car.car_rid.clone()) .entry(best_car.car_rid.clone())
.or_insert((best_car.clone(), 0)); .or_insert((best_car.clone(), 0));
entry.1 += 1; entry.1 += 1;
} }
}
// Convert to vector and sort by RQ first, then name // Convert to vector and sort by RQ first, then name
let mut car_count_vec: Vec<_> = car_count.iter().collect(); let mut car_count_vec: Vec<_> = car_count.iter().collect();
car_count_vec.sort_by(|a, b| a.1.0.rq.cmp(&b.1.0.rq).then(a.0.cmp(&b.0))); car_count_vec.sort_by(|a, b| a.1 .0.rq.cmp(&b.1 .0.rq).then(a.0.cmp(&b.0)));
for (_car_rid, (car_record, count)) in car_count_vec { for (_car_rid, (car_record, count)) in car_count_vec {
println!( println!(
@ -121,14 +131,25 @@ fn print_best_cars() {
} }
fn print_best_car(track: &String, condition: &String, rq: &String) { fn print_best_car(track: &String, condition: &String, rq: &String) {
let best_cars = BEST_CARS.lock().unwrap(); let best_cars = BEST_CARS.lock().unwrap();
let key = (track.clone(), rq.parse::<u8>().unwrap_or(115), condition.clone()); let key = (
track.clone(),
rq.parse::<u8>().unwrap_or(115),
condition.clone(),
);
if let Some(best_car) = best_cars.get(&key) { if let Some(best_list) = best_cars.get(&key) {
for best_car in best_list {
println!( println!(
"Best car for Track: {}, Condition: {}, RQ: {} -> {} {} ({}) with time {:.2}", "Best car for Track: {}, Condition: {}, RQ: {} -> {} {} ({}) with time {:.2}",
track, condition, rq, track,
best_car.brand, best_car.only_name, best_car.year, best_car.time condition,
rq,
best_car.brand,
best_car.only_name,
best_car.year,
best_car.time
); );
}
} else { } else {
println!( println!(
"No best car found for Track: {}, Condition: {}, RQ: {}", "No best car found for Track: {}, Condition: {}, RQ: {}",
@ -192,15 +213,29 @@ async fn parse_car_times(car: Car) {
fn update_best_car(track_id: &str, car_rq: u8, surface: &str, new_record: BestCarRecord) { fn update_best_car(track_id: &str, car_rq: u8, surface: &str, new_record: BestCarRecord) {
let mut best_cars = BEST_CARS.lock().unwrap(); let mut best_cars = BEST_CARS.lock().unwrap();
for rq in car_rq..116 { for rq in car_rq..=115 {
let key = (track_id.to_string(), rq, surface.to_string()); let key = (track_id.to_string(), rq, surface.to_string());
if let Some(existing) = best_cars.get(&key) { match best_cars.get_mut(&key) {
if new_record.time < existing.time { Some(existing_list) => {
best_cars.insert(key, new_record.clone()); let best_time = existing_list.first().map(|r| r.time).unwrap_or(f64::MAX);
if new_record.time < best_time {
// Found better time → replace list
*existing_list = vec![new_record.clone()];
} else if (new_record.time - best_time).abs() < f64::EPSILON {
// Tie → add only if not already in the list
if !existing_list
.iter()
.any(|r| r.car_rid == new_record.car_rid)
{
existing_list.push(new_record.clone());
}
}
}
None => {
best_cars.insert(key, vec![new_record.clone()]);
} }
} else {
best_cars.insert(key, new_record.clone());
} }
} }
} }