Copied initial source

This commit is contained in:
Jan-Peter von Hunnius 2024-10-16 11:24:12 +02:00
commit 3a826e3903
2 changed files with 203 additions and 0 deletions

13
Cargo.toml Normal file
View file

@ -0,0 +1,13 @@
[package]
name = "top_drives_db"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
scraper = "0.20.0"
reqwest = "0.12.7"
#ureq = { version = "2.6"}
#native-tls = { version = "0.2.12", features = [] }
#html_parser = "0.7.0"
tokio = { version = "1.40.0", features = ["full"] }

190
src/main.rs Normal file
View file

@ -0,0 +1,190 @@
use scraper::{Html, Selector};
use std::collections::HashSet;
use std::env;
use std::str::FromStr;
use tokio;
struct Car {
class: String,
rq: u8,
manufacturer: String,
model: String,
year: u16,
// upgrade: String,
}
async fn get_page(url: &str) -> String {
match reqwest::Client::builder()
.danger_accept_invalid_certs(true)
.build()
.unwrap()
.get(url)
.send()
.await
{
Ok(response) => match response.text().await {
Ok(text) => text,
Err(error) => {
println!("Error getting content! Error: {}", error);
String::from("")
}
},
Err(error) => {
println!("Error getting content! Error: {}", error);
String::from("")
}
}
}
fn parse_best_car(text: String) -> Car {
let mut car = Car {
class: String::from("Z"),
rq: 0,
manufacturer: String::from(""),
model: String::from(""),
year: 1900,
// upgrade: String::from("000"),
};
let document = Html::parse_document(&text);
let manufacturer_selector = Selector::parse(".carList__item-manufacturer").unwrap();
car.manufacturer = String::from(match document.select(&manufacturer_selector).next() {
None => "",
Some(manufacturer) => manufacturer.text().collect::<Vec<_>>()[0],
});
let model_selector = Selector::parse(".carList__item-model").unwrap();
car.model = String::from(match document.select(&model_selector).next() {
None => "",
Some(model) => model.text().collect::<Vec<_>>()[0],
});
let year_selector = Selector::parse(".carList__item-year").unwrap();
car.year = u16::from_str(match document.select(&year_selector).next() {
None => "1900",
Some(year) => year.text().collect::<Vec<_>>()[0],
})
.unwrap();
let level_selector = Selector::parse(".carList__item-level").unwrap();
let rq_raw = document
.select(&level_selector)
.next()
.unwrap()
.inner_html();
let rq_fragment = Html::parse_document(rq_raw.trim());
let span_selector = Selector::parse("span").unwrap();
let mut element_iterator = rq_fragment.select(&span_selector);
let class = String::from(match element_iterator.next() {
None => "Z",
Some(class) => class.text().collect::<Vec<_>>()[0],
});
car.class = class.to_uppercase();
let rq = match element_iterator.next() {
None => "1900",
Some(rq) => rq.text().collect::<Vec<_>>()[0],
};
car.rq = u8::from_str(rq).unwrap();
/*
let upgrade_selector = Selector::parse(".carList__item-upgrade ").unwrap();
let upgrade_raw = match document.select(&upgrade_selector).next() {
None => "",
Some(model) => model.text().collect::<Vec<_>>()[0],
};
car.upgrade = String::from(upgrade_raw).trim().parse().unwrap();
*/
car
}
#[tokio::main]
async fn main() {
let args: Vec<_> = env::args().collect();
let mut min_track = 4;
let mut max_track = 278;
let min_rq = 10;
let mut max_rq = 113;
match args.len() {
1 => {}
2 => max_rq = parse_argument(&args, 1, 10, 113),
3 => {
max_rq = parse_argument(&args, 1, 10, 113);
min_track = parse_argument(&args, 2, 4, 278);
max_track = min_track;
}
4 => {
max_rq = parse_argument(&args, 1, 10, 113);
min_track = parse_argument(&args, 2, 4, 278);
max_track = parse_argument(&args, 3, 4, 278);
if max_track < min_track {
let temp = min_track;
min_track = max_track;
max_track = temp
}
}
_ => panic!("Too many arguemnts."),
}
let mut keepers: HashSet<String> = HashSet::new();
for track in min_track..max_track + 1 {
let best_car = get_best_car(track, 10).await;
if best_car.len() > 10 {
for level in min_rq..max_rq + 1 {
let best_car = get_best_car(track, level).await;
if best_car.len() > 10 {
// println!("Best Car under RQ {} for track {}: {}", level, track, best_car);
keepers.insert(best_car);
}
}
}
}
println!("Keepers:");
for car in keepers {
println!("{}", car);
}
}
fn parse_argument(args: &Vec<String>, index: usize, min: u16, max: u16) -> u16 {
match args[index].parse::<u16>() {
Ok(parsed_value) => {
if parsed_value >= min && parsed_value <= max {
parsed_value
} else {
panic!(
"Argument {} is out of range. Please provide a value between {} and {}.",
index, min, max
);
}
}
Err(_) => {
panic!("Argument {} could not be parsed. Please provide a positive integer value between {} and {}.", index, min, max)
}
}
}
async fn get_best_car(track: u16, max_level: u16) -> String {
let url = format!("https://topdrives.club/ajax/load-best-vehicles?sort_by=level&sortorder=desc&prize=all&level=10%3B{}&acceleration=1%3B50&grip=40%3B110&year=1900%3B2030&seats_count=1%3B9&track={}&page=0",
max_level, track);
// println!("Getting {}", url);
let text = get_page(&url).await;
if text.len() > 10 {
let best_car = parse_best_car(text);
format!(
// "{}{} {} {} {} {}",
"{}{} {} {} {}",
best_car.class,
best_car.rq,
best_car.manufacturer,
best_car.model,
best_car.year,
// best_car.upgrade,
)
} else {
String::from("")
}
}