diff --git a/Cargo.toml b/Cargo.toml index 8853415..27989c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,4 @@ tokio = { version = "1.44.1", features = ["full"] } serde_json = "1.0.140" futures = "0.3.31" once_cell = "1.20.2" +serde = { version = "1.0.210", features = ["derive"] } diff --git a/src/records.rs b/src/records.rs index 6b8e4eb..fa4e8a8 100644 --- a/src/records.rs +++ b/src/records.rs @@ -1,6 +1,8 @@ use std::collections::HashMap; use std::env; use std::fs; +use std::fs::File; +use std::io::BufReader; use std::sync::Mutex; use tokio::sync::Semaphore; @@ -13,7 +15,12 @@ use once_cell::sync::Lazy; use reqwest::get; use serde_json::Value; +use serde::Deserialize; +#[derive(Debug, Deserialize)] +struct Card { + cardId: String, +} #[derive(Debug, Clone)] struct Car { rid: String, @@ -21,6 +28,7 @@ struct Car { only_name: String, year: u16, rq: u8, + guid: String, } #[derive(Debug, Clone)] struct BestCarRecord { @@ -31,6 +39,7 @@ struct BestCarRecord { rq: u8, config: String, time: f64, + owned: bool, } type TripletKey = (String, u8, String); // (Track ID, RQ, Surface) static BEST_CARS: Lazy>>> = @@ -54,7 +63,11 @@ async fn main() { } "best" => { parse_all_times().await; - print_best_cars(); + print_best_cars(false); + } + "missing" => { + parse_all_times().await; + print_best_cars(true); } "details" => { parse_all_times().await; @@ -104,7 +117,7 @@ fn print_best_times() { } } } -fn print_best_cars() { +fn print_best_cars(filter_out_owned: bool) { let best_cars = BEST_CARS.lock().unwrap(); let mut car_count: HashMap = HashMap::new(); @@ -123,10 +136,12 @@ fn print_best_cars() { 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 { - println!( - "{},{},{},{},{}", - car_record.rq, car_record.brand, car_record.only_name, car_record.year, count - ); + if ! (filter_out_owned && car_record.owned) { + println!( + "{},{},{},{},{}", + car_record.rq, car_record.brand, car_record.only_name, car_record.year, count + ); + } } } fn print_best_car(track: &String, condition: &String, rq: &String) { @@ -159,6 +174,8 @@ fn print_best_car(track: &String, condition: &String, rq: &String) { } async fn parse_car_times(car: Car) { + let my_cars = get_my_car_list(); + let file_name = car.rid.to_owned() + ".json"; let local_file_path = "times/".to_owned() + file_name.as_str(); let file_content = fs::read_to_string(local_file_path); @@ -187,6 +204,8 @@ async fn parse_car_times(car: Car) { time = 2000.0 / time; } + let owned = my_cars.contains(&car.guid); + // Insert into the database if time > 1.2 && no_down_votes { update_best_car( @@ -201,6 +220,7 @@ async fn parse_car_times(car: Car) { rq: car.rq, config: config.clone(), time, + owned, }, ); } @@ -293,6 +313,7 @@ fn get_car_list() -> Vec { only_name: String::from(car["onlyName"].as_str().unwrap_or("No Name")), year: car["year"].as_u64().unwrap_or(1900) as u16, rq: car["rq"].as_u64().unwrap_or(200) as u8, + guid: String::from(car["guid"].as_str().unwrap_or("No GUID")), }; car_list.push(new_car); @@ -300,6 +321,16 @@ fn get_car_list() -> Vec { car_list } +fn get_my_car_list() -> Vec { + let file = File::open("my_cars.json").expect("Could not read my cars file."); + let reader = BufReader::new(file); + let json: Value = serde_json::from_reader(reader).expect("Could not extract JSON from my cars file."); + + let deck_json = json.get("playerDeck").ok_or("Missing 'playerDeck'"); + let cards: Vec = serde_json::from_value(deck_json.clone().expect("Could not extract cards.").clone()).expect("Could not extract cards."); + + cards.into_iter().map(|card| card.cardId).collect() +} async fn get_tracks_file() { println!("Fetching tracks file..."); get_file("https://github.com/TiagoXavi/topdrives-records/raw/refs/heads/main/src/database/tracks_repo.json","tracks_repo.json").await; @@ -316,7 +347,7 @@ async fn get_file(file_url: &str, local_file_path: &str) { .expect("Unable to write file!"); } Err(error) => { - println!("Failed to fetch the file. Status: {}", error.to_string()); + eprintln!("Failed to fetch the file. Status: {}", error.to_string()); } } }