Added feature for missing cars

This commit is contained in:
Jan-Peter von Hunnius 2025-06-16 11:07:14 +02:00
parent 4e299db3c0
commit 48e623a1a3
2 changed files with 39 additions and 7 deletions

View file

@ -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"] }

View file

@ -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<Mutex<HashMap<TripletKey, Vec<BestCarRecord>>>> =
@ -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<String, (BestCarRecord, usize)> = 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<Car> {
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> {
car_list
}
fn get_my_car_list() -> Vec<String> {
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<Card> = 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());
}
}
}