diff options
| author | kboz <kutayboz@gmail.com> | 2026-04-24 01:11:23 +0200 |
|---|---|---|
| committer | kboz <kutayboz@gmail.com> | 2026-04-24 01:11:23 +0200 |
| commit | 29c4b57db9a34e0f815d93cac6a2cae543778a93 (patch) | |
| tree | 68628e0b67353bcf74b5c516e5a2f0893cd598b7 /rust_backend/src | |
| parent | e43c98997b0de6a8da989f68d97f1d4f7fb7bb6f (diff) | |
| download | haul-master.tar.gz | |
- Added a 2026 copyright statement under the original creator's in `license.md` to properly establish new fork logic.
- Updated `readme.md` to explicitly state this repository is a maintained fork.
- Eliminated the `rust_backend/` directory, Actix codebase, and its associated launch configurations.
- Purged all references specifying a Python/Rust/React tri-split from `AGENTS.md` and the frontend `.instructions.md` configuration.
Co-authored-by: Copilot <copilot@github.com>
Diffstat (limited to 'rust_backend/src')
| -rw-r--r-- | rust_backend/src/eve_api.rs | 319 | ||||
| -rw-r--r-- | rust_backend/src/eve_service.rs | 42 | ||||
| -rw-r--r-- | rust_backend/src/main.rs | 95 | ||||
| -rw-r--r-- | rust_backend/src/manager.rs | 90 | ||||
| -rw-r--r-- | rust_backend/src/market/mod.rs | 3 | ||||
| -rw-r--r-- | rust_backend/src/market/order.rs | 83 | ||||
| -rw-r--r-- | rust_backend/src/market/trade.rs | 63 | ||||
| -rw-r--r-- | rust_backend/src/pathfinding/graph.rs | 7 | ||||
| -rw-r--r-- | rust_backend/src/pathfinding/mod.rs | 15 | ||||
| -rw-r--r-- | rust_backend/src/pathfinding/models.rs | 86 | ||||
| -rw-r--r-- | rust_backend/src/pathfinding/parser.rs | 46 | ||||
| -rw-r--r-- | rust_backend/src/route.rs | 108 |
12 files changed, 0 insertions, 957 deletions
diff --git a/rust_backend/src/eve_api.rs b/rust_backend/src/eve_api.rs deleted file mode 100644 index 18e1007..0000000 --- a/rust_backend/src/eve_api.rs +++ /dev/null @@ -1,319 +0,0 @@ -use dotenv::dotenv; -use std::env; -use std::error::Error; -use std::fs::{self, File}; -use std::io::{self, Read, Write}; -use std::path::Path; -use std::time::{SystemTime, UNIX_EPOCH, Duration}; -use std::sync::Arc; - -use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; -use tokio::{task, time}; -use tokio::sync::Semaphore; - - -use crate::pathfinding::Location; -use crate::market::Order; - -const TOKEN_FILE: &str = "token.json"; - -use std::sync::Mutex; - - -#[derive(Deserialize, Serialize, Clone)] -struct TokenData { - access_token: String, - refresh_token: String, - expires_at: u64, -} - -#[derive(Deserialize)] -struct TokenResponse { - access_token: String, - refresh_token: String, - expires_in: u64, -} - -pub struct EveApiClient { - client_id: String, - client_secret: String, - character_id: String, - redirect_url: String, - access_token: Mutex<Option<String>>, - expires_at: Mutex<Option<u64>>, -} - - -impl EveApiClient { - pub fn new() -> Result<Self, Box<dyn Error>> { - dotenv().ok(); - - let client_id = env::var("CLIENT_ID").map_err(|e| format!("CLIENT_ID error: {}", e))?; - let client_secret = env::var("CLIENT_SECRET").map_err(|e| format!("CLIENT_SECRET error: {}", e))?; - let character_id = env::var("CHARACTER_ID").map_err(|e| format!("CHARACTER_ID error: {}", e))?; - let redirect_url = env::var("REDIRECT_URL").map_err(|e| format!("REDIRECT_URL error: {}", e))?; - - let token_data = match Self::load_token_from_file() { - Ok(data) => Some(data), - Err(_) => None, - }; - - Ok(EveApiClient { - client_id, - client_secret, - character_id, - redirect_url, - access_token: Mutex::new(token_data.clone().map(|data| data.access_token)), - expires_at: Mutex::new(token_data.map(|data| data.expires_at)), - }) - } - - pub fn get_authorization_url(&self) -> String { - let auth_url = format!( - "https://login.eveonline.com/v2/oauth/authorize/?response_type=code&client_id={}&redirect_uri={}&scope={}", - self.client_id, - self.redirect_url, - "esi-assets.read_assets.v1 esi-location.read_location.v1 esi-location.read_online.v1 esi-ui.open_window.v1 esi-ui.write_waypoint.v1".replace(" ", "%20") - ); - auth_url - } - - pub async fn exchange_code_for_token(&self, code: &str) -> Result<(), Box<dyn Error>> { - let client = reqwest::Client::new(); - let res = client - .post("https://login.eveonline.com/v2/oauth/token") - .form(&[ - ("client_id", self.client_id.as_str()), - ("client_secret", self.client_secret.as_str()), - ("code", code), - ("redirect_uri", self.redirect_url.as_str()), - ("grant_type", "authorization_code"), - ]) - .send() - .await; - - let res = match res { - Ok(response) => response, - Err(e) => return Err(Box::new(e)), - }; - - let token_response: TokenResponse = match res.json().await { - Ok(data) => data, - Err(e) => return Err(Box::new(e)), - }; - - let expires_at = SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time went backwards") // Handle this error as per your need - .as_secs() + token_response.expires_in; - - let token_data = TokenData { - access_token: token_response.access_token, - refresh_token: token_response.refresh_token, - expires_at, - }; - - if let Err(e) = Self::save_token_to_file(&token_data) { - return Err(e); - } - - let mut token = self.access_token.lock().unwrap(); - *token = Some(token_data.access_token); - - Ok(()) - } - - pub async fn refresh_access_token(&self) -> Result<(), Box<dyn Error>> { - let token_data = match Self::load_token_from_file() { - Ok(data) => data, - Err(_) => return Err("Failed to load token data".into()), - }; - - - let client = reqwest::Client::new(); - let res = client - .post("https://login.eveonline.com/v2/oauth/token") // Replace with the actual token endpoint - .form(&[ - ("client_id", self.client_id.as_str()), - ("client_secret", self.client_secret.as_str()), - ("refresh_token", token_data.refresh_token.as_str()), - ("grant_type", "refresh_token"), - ]) - .send() - .await?; - - let refreshed_token_response: TokenResponse = res.json().await?; - - let current_timestamp = SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_secs(); - - let new_expires_at = current_timestamp + refreshed_token_response.expires_in; - - let new_token_data = TokenData { - access_token: refreshed_token_response.access_token, - refresh_token: refreshed_token_response.refresh_token, - expires_at: new_expires_at, - }; - - Self::save_token_to_file(&new_token_data)?; - - let mut access_token = self.access_token.lock().unwrap(); - *access_token = Some(new_token_data.access_token); - let mut expires_at = self.expires_at.lock().unwrap(); - *expires_at = Some(new_expires_at); - - Ok(()) - } - - - pub async fn request_location(&self) -> Result<Location, Box<dyn Error>> { - self.ensure_valid_token().await?; - - let url = format!("https://esi.evetech.net/latest/characters/{}/location/", self.character_id); - - println!("{:?}", url); - - let client = reqwest::Client::new(); - - let response = client.get(url) - .bearer_auth(self.get_access_token().unwrap()) - .send() - .await?; - - println!("{:?}", response); - - if response.status().is_success() { - let data = response.json::<Location>().await?; - Ok(data) - } else { - Err(Box::new(response.error_for_status().unwrap_err())) - } - } - - pub async fn request_order_metadata(&self, region: u64) -> Result<(u64, DateTime<Utc>), Box<dyn Error>> { - let url = format!("https://esi.evetech.net/latest/markets/{}/orders/?datasource=tranquility&order_type=all&page=1", region); - - let client = reqwest::Client::new(); - let response = client.get(&url) - .send() - .await - .map_err(|e| e.to_string())?; - - let x_pages = match response.headers().get("x-pages") { - Some(x_pages_value) => { - match x_pages_value.to_str() { - Ok(value_str) => { - match value_str.parse::<u64>() { - Ok(value) => value, - Err(_) => return Err("Failed to parse x-pages value into u64".into()), - } - } - Err(_) => return Err("Invalid x-pages header value".into()), - } - } - None => return Err("X-Pages header not found".into()), - }; - - let expiry_unix_time = match response.headers().get("expires") { - Some(expiry_value) => { - match expiry_value.to_str() { - Ok(value_str) => { - match DateTime::parse_from_rfc2822(value_str) { - Ok(expiry_date) => expiry_date.with_timezone(&Utc), - Err(_) => return Err("Failed to parse expiry date".into()), - } - } - Err(_) => return Err("Invalid expiry header value".into()), - } - } - None => return Err("Expires header not found".into()), - }; - - Ok((x_pages, expiry_unix_time)) - } - - - - pub async fn request_orders(&self, region: u64) -> Result<(Vec<Order>, DateTime<Utc>), Box<dyn Error>> { - let (x_pages, expiry) = self.request_order_metadata(region).await?; - - let client = reqwest::Client::builder() - .timeout(Duration::from_secs(30)) - .build()?; - - let semaphore = Arc::new(Semaphore::new(10)); - let mut tasks = Vec::new(); - - for page in 1..=x_pages { - let permit = semaphore.clone().acquire_owned().await?; - let client = client.clone(); - let url = format!("https://esi.evetech.net/latest/markets/{}/orders/?datasource=tranquility&order_type=all&page={}", region, page); - - let task = task::spawn(async move { - time::sleep(Duration::from_millis(20)).await; - let response = client.get(&url).send().await?; - println!("{:?}", &url); - drop(permit); - response.error_for_status()?.json::<Vec<Order>>().await - }); - - tasks.push(task); - } - - let mut orders = Vec::new(); - for task in tasks { - match task.await { - Ok(result) => match result { - Ok(mut page_orders) => orders.append(&mut page_orders), - Err(e) => return Err(Box::new(e)), - }, - Err(e) => return Err(Box::new(e)), - } - } - - Ok((orders, expiry)) - } - - pub async fn ensure_valid_token(&self) -> Result<(), Box<dyn Error>> { - let current_timestamp = SystemTime::now() - .duration_since(UNIX_EPOCH) - .map_err(|e| format!("System time error: {}", e))? - .as_secs(); - - let should_refresh = { - let expires_at = self.expires_at.lock().unwrap(); - let expires_at_value = expires_at.unwrap_or(0); - current_timestamp > expires_at_value - }; - - if should_refresh { - self.refresh_access_token().await?; - } - - Ok(()) - } - pub fn get_access_token(&self) -> Option<String> { - let token = self.access_token.lock().unwrap(); - token.clone() - } - - pub fn save_token_to_file(token_data: &TokenData) -> Result<(), Box<dyn Error>> { - let token_json = serde_json::to_string(token_data)?; - fs::write(Path::new(TOKEN_FILE), token_json)?; - Ok(()) - } - - fn load_token_from_file() -> Result<TokenData, Box<dyn Error>> { - let token_json = match fs::read_to_string(Path::new(TOKEN_FILE)) { - Ok(content) => content, - Err(_) => return Err("Unable to read token file".into()), - }; - let token_data: TokenData = serde_json::from_str(&token_json)?; - Ok(token_data) - } - - -} diff --git a/rust_backend/src/eve_service.rs b/rust_backend/src/eve_service.rs deleted file mode 100644 index c831847..0000000 --- a/rust_backend/src/eve_service.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::eve_api::EveApiClient; -use crate::pathfinding::Location; -use crate::market::Orders; - -use std::error::Error; - -pub struct EveService { - client: EveApiClient, -} - -impl EveService { - pub fn new() -> Result<Self, Box<dyn Error>> { - let eve_api_client = EveApiClient::new()?; - Ok(EveService { client: eve_api_client, }) - } - - pub fn get_authorization_url(&self) -> String { - self.client.get_authorization_url() - } - - pub async fn exchange_code_for_token(&self, code: &str) -> Result<(), Box<dyn Error>> { - self.client.exchange_code_for_token(code).await - } - - pub async fn location(&self) -> Result<Location, Box<dyn Error>> { - self.client.request_location().await.map_err(|e| e.into()) - } - - pub async fn updated_orders(&self, current_orders: &Orders) -> Result<Orders, Box<dyn Error>> { - let mut region_orders = Orders::new(); - - let regions = current_orders.expired_regions(); - - for ®ion in regions.iter() { - let (orders, expiry) = self.client.request_orders(region).await?; - region_orders.insert(region, orders, expiry); - } - - Ok(region_orders) - - } -} diff --git a/rust_backend/src/main.rs b/rust_backend/src/main.rs deleted file mode 100644 index 4a2e086..0000000 --- a/rust_backend/src/main.rs +++ /dev/null @@ -1,95 +0,0 @@ -mod manager; -mod eve_service; -mod eve_api; -mod pathfinding; -mod market; - -use manager::Manager; - -use actix_web::{web, App, HttpServer, Responder, HttpResponse, http::header}; -use std::sync::Mutex; -use tokio::sync::watch; -use serde::Deserialize; - - -async fn index() -> impl Responder { - "Hi" -} - -async fn location(manager: web::Data<Manager>) -> impl Responder { - match manager.location() { - Some(location) => { - let station_id = location.station_id.map_or("None".to_string(), |id| id.to_string()); - let structure_id = location.structure_id.map_or("None".to_string(), |id| id.to_string()); - format!( - "Current location: Solar System ID: {}, Station ID: {}, Structure ID: {}", - location.solar_system_id, station_id, structure_id - ) - }, - None => "No location available".to_string(), - } -} - -async fn orders(manager: web::Data<Manager>) -> impl Responder { - let orders = manager.orders(); - HttpResponse::Ok().json(orders) -} - -async fn start_oauth(manager: web::Data<Manager>) -> HttpResponse { - let auth_url = manager.get_authorization_url(); - HttpResponse::Found() - .append_header((header::LOCATION, auth_url.as_str())) - .finish() -} - -#[derive(Deserialize)] -struct AuthCode { - code: String, -} - -async fn oauth_callback( - query: web::Query<AuthCode>, - manager: web::Data<Manager>, -) -> HttpResponse { - match manager.exchange_code_for_token(&query.code).await { - Ok(_) => HttpResponse::Ok().body("Token exchange successful"), - Err(e) => HttpResponse::InternalServerError().body(format!("Error: {}", e)), - } -} - -#[actix_web::main] -async fn main() -> std::io::Result<()> { - let manager = web::Data::new(Manager::new()); - - - let manager_clone = manager.clone(); - let (shutdown_tx, shutdown_rx) = watch::channel(false); - - let manager_handle = tokio::spawn(async move { - manager_clone.run(shutdown_rx).await; - }); - - let server = HttpServer::new(move || { - App::new() - .app_data(manager.clone()) - .route("/", web::get().to(index)) - .route("/location", web::get().to(location)) - .route("/orders", web::get().to(orders)) - .route("/start_oauth", web::get().to(start_oauth)) - .route("/oauth_callback", web::get().to(oauth_callback)) - }) - .bind("127.0.0.1:8080")? - .run(); - - ctrlc::set_handler(move || { - let _ = shutdown_tx.send(true); - }) - .expect("Error setting Ctrl-C handler"); - - tokio::select! { - _ = server => {}, - _ = manager_handle => {}, - } - - Ok(()) -} diff --git a/rust_backend/src/manager.rs b/rust_backend/src/manager.rs deleted file mode 100644 index b9cbe08..0000000 --- a/rust_backend/src/manager.rs +++ /dev/null @@ -1,90 +0,0 @@ -use std::sync::Mutex; -use tokio::sync::watch; - -use std::error::Error; - -use crate::eve_service::EveService; -use crate::pathfinding::{Location, build}; -use crate::market::{Order, Orders}; - -pub struct Manager { - // route_state: Mutex<Route> - // route_info_state: Mutex<RouteInfo> - orders_state: Mutex<Orders>, - location: Mutex<Option<Location>>, - // log_state: Mutex<Log> - eve_service: EveService, - -} - -impl Manager { - pub fn new() -> Manager { - - build(); - - Manager { - location: Mutex::new( None ), - eve_service: EveService::new().expect("Manager to generate EveService"), - orders_state: Mutex::new( Orders::new() ), - } - - } - - pub async fn run(&self, shutdown_signal: watch::Receiver<bool>) { - loop { - tokio::time::sleep(tokio::time::Duration::from_secs(10)).await; - if *shutdown_signal.borrow() { - println!("Manager task is shutting down."); - break; - } - - match self.eve_service.location().await { - Ok(result) => { - match self.location.lock() { - Ok(mut location) => *location = Some(result), - Err(e) => eprintln!("Error locking location mutex: {}", e), - } - } - Err(e) => { - eprintln!("Error fetching location {}", e); - } - } - - - let orders_clone = match self.orders_state.lock() { - Ok(orders_lock) => orders_lock.clone(), - Err(e) => { - eprintln!("Error locking orders_state mutex: {}", e); - continue; - } - }; - - match self.eve_service.updated_orders(&orders_clone).await { - Ok(updated_orders) => { - match self.orders_state.lock() { - Ok(mut orders_state) => orders_state.update(updated_orders), - Err(e) => eprintln!("Error locking orders_state mutex: {}", e), - } - } - Err(e) => eprintln!("Error updating orders: {}", e), - } - } - } - pub fn get_authorization_url(&self) -> String { - self.eve_service.get_authorization_url() - } - - pub async fn exchange_code_for_token(&self, code: &str) -> Result<(), Box<dyn Error>> { - self.eve_service.exchange_code_for_token(code).await - } - - pub fn location(&self) -> Option<Location> { - let location = self.location.lock().unwrap(); - location.clone() - } - - pub fn orders(&self) -> Vec<Order> { - let orders = self.orders_state.lock().unwrap(); - orders.orders() - } -}
\ No newline at end of file diff --git a/rust_backend/src/market/mod.rs b/rust_backend/src/market/mod.rs deleted file mode 100644 index 16d1f37..0000000 --- a/rust_backend/src/market/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod order; - -pub use order::{Order, Orders};
\ No newline at end of file diff --git a/rust_backend/src/market/order.rs b/rust_backend/src/market/order.rs deleted file mode 100644 index 6dbbcf6..0000000 --- a/rust_backend/src/market/order.rs +++ /dev/null @@ -1,83 +0,0 @@ -use std::error::Error; -use std::collections::HashMap; - -use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; - -use crate::eve_service::EveService; - - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct Order { - duration: u64, - is_buy_order: bool, - issued: DateTime<Utc>, - location_id: u64, - min_volume: u64, - order_id: u64, - price: f64, - range: String, - system_id: u64, - type_id: u64, - volume_remain: u64, - volume_total: u64 -} - -const REGIONS: [u64; 1] = [10000033]; - -#[derive(Clone, Serialize)] -pub struct Orders { - region_orders: HashMap<u64, Vec<Order>>, - expiry_times: HashMap<u64, DateTime<Utc>>, // region_id to expiration time -} - - -impl Orders { - pub fn new() -> Self { - Orders { - region_orders: HashMap::new(), - expiry_times: HashMap::new(), - } - } - - pub fn insert(&mut self, region: u64, orders: Vec<Order>, expiry: DateTime<Utc>) { - self.region_orders.insert(region, orders); - self.expiry_times.insert(region, expiry); - } - - pub fn expired_regions(&self) -> Vec<u64> { - let current_time = Utc::now(); - - println!("expiry: {:?}, time now: {:?}", &self.expiry_times, ¤t_time); - - let mut expired: Vec<u64> = self.expiry_times.iter() - .filter(|&(_region_id, &expiry_time)| expiry_time < current_time) - .map(|(®ion_id, _)| region_id) - .collect(); - - for ®ion in REGIONS.iter() { - if !self.expiry_times.contains_key(®ion) { - expired.push(region); - } - } - - - expired - - } - - pub fn update(&mut self, updated_orders: Orders) { - for (key, value) in updated_orders.region_orders { - self.region_orders.insert(key, value); - - if let Some(expiry_time) = updated_orders.expiry_times.get(&key) { - self.expiry_times.insert(key, *expiry_time); - } - } - } - - - pub fn orders(&self) -> Vec<Order> { - self.region_orders.values().flat_map(|orders| orders.clone()).collect() - } -}
\ No newline at end of file diff --git a/rust_backend/src/market/trade.rs b/rust_backend/src/market/trade.rs deleted file mode 100644 index 362acbf..0000000 --- a/rust_backend/src/market/trade.rs +++ /dev/null @@ -1,63 +0,0 @@ -use crate::order::Order; - -pub struct Trade<'a> { - from: &'a Order, - to: &'a Order, - quantity: usize, - gross_profit: f64, -} - -const TAX_RATE: f64 = 0.08 - -impl<'a> Trade<'a> { - pub fn new(from: &'a Order, to: &'a Order, quantity: usize) -> Self { - Self { from, to, quantity } - } - - pub fn create_trades(sell_orders: &'a [Order], buy_orders: &'a [Order]) -> Vec<Trade<'a>> { - let mut trades: Vec<Trade<'a>> = Vec::new(); - let mut grouped_orders: HashMap<i32, (Vec<&'a Order>, Vec<&'a Order>)> = HashMap::new(); - - // Grouping sell orders - for order in sell_orders { - grouped_orders.entry(order.type_id) - .or_insert((Vec::new(), Vec::new())) - .0 - .push(order); - } - - // Grouping buy orders - for order in buy_orders { - grouped_orders.entry(order.type_id) - .or_insert((Vec::new(), Vec::new())) - .1 - .push(order); - } - - // Iterating over each type_id's sell and buy orders to create trades - for (_type_id, (sells, buys)) in grouped_orders { - for &sell_order in sells { - for &buy_order in buys { - let quantity = std::cmp::min(sell_order.volume_remain, buy_order.volume_remain); - let gross_profit = quantity as f64 * (buy_order.price * (1-TAX_RATE) - sell_order.price); - - if gross_profit <= 0.0 { - continue; - } - - let trade = Trade::new( - sell_order, - buy_order, - quantity, - gross_profit, - ); - - trades.push(trade); - } - } - } - - trades - } - -} diff --git a/rust_backend/src/pathfinding/graph.rs b/rust_backend/src/pathfinding/graph.rs deleted file mode 100644 index 0352007..0000000 --- a/rust_backend/src/pathfinding/graph.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::pathfinding::models::{MapNode, Graph}; - -use std::collections::HashMap; - -pub fn generate_graph(stations: &Vec<MapNode>) -> Graph { - HashMap::new() -}
\ No newline at end of file diff --git a/rust_backend/src/pathfinding/mod.rs b/rust_backend/src/pathfinding/mod.rs deleted file mode 100644 index 32c2831..0000000 --- a/rust_backend/src/pathfinding/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -mod models; -mod parser; -mod graph; -pub use models::{Location, Graph}; - - -use crate::pathfinding::parser::parse_stations; -use crate::pathfinding::graph::generate_graph; - -pub fn build() { - let stations = parse_stations().unwrap(); - let gates_connnections = parse_gate_connections().unwrap() - let graph = generate_graph(&stations, &gates_connnections); - -} diff --git a/rust_backend/src/pathfinding/models.rs b/rust_backend/src/pathfinding/models.rs deleted file mode 100644 index 4bbc580..0000000 --- a/rust_backend/src/pathfinding/models.rs +++ /dev/null @@ -1,86 +0,0 @@ -use serde::{Deserialize, Deserializer, Serialize}; -use std::str::FromStr; -use std::collections::HashMap; - - -#[derive(Deserialize, Serialize, Clone)] -pub struct Location { - pub solar_system_id: i32, - pub station_id: Option<i32>, - pub structure_id: Option<i32>, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct RawNode { - pub itemID: u64, - pub typeID: u64, - pub groupID: u64, - #[serde(deserialize_with = "deserialize_optional_u64")] - pub solarSystemID: Option<u64>, - #[serde(deserialize_with = "deserialize_optional_u64")] - pub constellationID: Option<u64>, - #[serde(deserialize_with = "deserialize_optional_u64")] - pub regionID: Option<u64>, - #[serde(deserialize_with = "deserialize_optional_u64")] - pub orbitID: Option<u64>, - pub x: Option<f64>, - pub y: Option<f64>, - pub z: Option<f64>, - #[serde(deserialize_with = "deserialize_optional_f64")] - pub radius: Option<f64>, - pub itemName: Option<String>, - #[serde(deserialize_with = "deserialize_optional_f64")] - pub security: Option<f64>, -} - - -fn deserialize_optional_u64<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error> -where - D: Deserializer<'de>, -{ - let s: Option<String> = Option::deserialize(deserializer)?; - match s.as_deref() { - Some("None") | Some("") => Ok(None), // Handle "None" and empty strings - Some(str_val) => u64::from_str(str_val) - .map(Some) - .map_err(serde::de::Error::custom), - None => Ok(None), - } -} - -fn deserialize_optional_f64<'de, D>(deserializer: D) -> Result<Option<f64>, D::Error> -where - D: Deserializer<'de>, -{ - let s: Option<String> = Option::deserialize(deserializer)?; - match s.as_deref() { - Some("None") | Some("") => Ok(None), // Handle "None" and empty strings - Some(str_val) => str_val.parse::<f64>() - .map(Some) - .map_err(serde::de::Error::custom), - None => Ok(None), - } -} - -#[derive(Debug)] -pub struct MapNode { - pub item_id: u64, - pub is_station: bool, - pub solar_system_id: u64, - pub region_id: u64, - pub x: f64, - pub y: f64, - pub z: f64, - pub name: String, - pub security: f64, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct Connection { - stargate_id: u64, - destination_id: u64, -} - - - -pub type Graph = HashMap<u64, Vec<u64>>;
\ No newline at end of file diff --git a/rust_backend/src/pathfinding/parser.rs b/rust_backend/src/pathfinding/parser.rs deleted file mode 100644 index 955a448..0000000 --- a/rust_backend/src/pathfinding/parser.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::error::Error; -use std::fs::File; -use csv; - -use crate::pathfinding::models::{RawNode, MapNode}; - -pub fn parse_stations() -> Result<Vec<MapNode>, Box<dyn Error>> { - let file_path = "../mapDenormalize.csv"; - let file = File::open(file_path)?; - - let mut rdr = csv::Reader::from_reader(file); - - let mut raw_nodes: Vec<RawNode> = Vec::new(); - for result in rdr.deserialize() { - match result { - Ok(node) => raw_nodes.push(node), - Err(e) => println!("Error deserializing record: {}", e), - } - } - - println!("raw nodes: {:?}", raw_nodes.len()); - - let processed_nodes: Vec<MapNode> = raw_nodes.into_iter() - .filter(|node| [15, 10].contains(&node.groupID)) - .map(|node| MapNode { - item_id: node.itemID, - is_station: node.groupID == 15, - solar_system_id: node.solarSystemID.unwrap_or_default(), - region_id: node.regionID.unwrap_or_default(), - x: node.x.unwrap_or_default(), - y: node.y.unwrap_or_default(), - z: node.z.unwrap_or_default(), - name: node.itemName.unwrap_or_default(), - security: node.security.unwrap_or_default(), - }) - .collect(); - - println!("processed nodes: {:?}", processed_nodes.len()); - - - Ok(processed_nodes) -} - -pub fn parse_gate_connections() -> Result<Vec<u64, u64>, Box<dyn Error>> { - unimplemented!(); -}
\ No newline at end of file diff --git a/rust_backend/src/route.rs b/rust_backend/src/route.rs deleted file mode 100644 index a2c477e..0000000 --- a/rust_backend/src/route.rs +++ /dev/null @@ -1,108 +0,0 @@ -use std::collections::HashMap; - -struct Item { - profit: f32, - cost: f32, - cargo: f32, - quantity: usize, -} - -#[derive(PartialEq, Eq, Hash, Clone)] -struct DiscreteState { - cost: isize, - cargo: isize, -} - -type StateMap = HashMap<DiscreteState, (f32, Vec<(usize, usize)>)>; - -fn discretize(value: f32, precision: f32) -> isize { - (value / precision).round() as isize -} - -fn knapsack(items: &[Item], max_cost: f32, max_cargo: f32) -> (f32, Vec<(usize, usize)>) { - let mut best_state: StateMap = HashMap::new(); - let precision = 0.01; // Define the precision level for discretization - best_state.insert(DiscreteState { cost: 0, cargo: 0 }, (0.0, vec![])); - - for (index, item) in items.iter().enumerate() { - let mut new_state = best_state.clone(); - - for (&DiscreteState { cost: current_cost, cargo: current_cargo }, &(current_profit, ref indices)) in &best_state { - let max_quantity_cost = ((max_cost - current_cost as f32 * precision) / item.cost).floor() as usize; - let max_quantity_cargo = ((max_cargo - current_cargo as f32 * precision) / item.cargo).floor() as usize; - - let quantity = *[ - item.quantity, - max_quantity_cost, - max_quantity_cargo, - ] - .iter() - .min() - .unwrap(); - - if quantity == 0 { - continue; - } - - let total_cost = discretize(current_cost as f32 * precision + item.cost * (quantity as f32), precision); - let total_cargo = discretize(current_cargo as f32 * precision + item.cargo * (quantity as f32), precision); - let total_profit = current_profit + item.profit * (quantity as f32); - - let mut new_indices = indices.clone(); - new_indices.push((index, quantity)); - - new_state - .entry(DiscreteState { cost: total_cost, cargo: total_cargo }) - .and_modify(|(existing_profit, existing_indices)| { - if *existing_profit < total_profit { - *existing_profit = total_profit; - *existing_indices = new_indices.clone(); - } - }) - .or_insert((total_profit, new_indices)); - } - - best_state = new_state; - } - - best_state.values().max_by(|&(p1, _), &(p2, _)| p1.partial_cmp(&p2).unwrap()).unwrap_or(&(0.0, vec![])).clone() -} - -fn main() { - // Example usage with some items defined - let items = vec![ - Item { - profit: 60.0, - cost: 0.1, - cargo: 0.2, - quantity: 100, - }, - Item { - profit: 100.0, - cost: 0.2, - cargo: 0.5, - quantity: 50, - }, - Item { - profit: 100.0, - cost: 0.1, - cargo: 0.5, - quantity: 50, - }, - Item { - profit: 100.0, - cost: 0.2, - cargo: 0.3, - quantity: 50, - }, - ]; - - let max_cost = 50.0; - let max_cargo = 50.0; - - let (max_profit, item_selections) = knapsack(&items, max_cost, max_cargo); - println!("Maximum profit: {}", max_profit); - for (index, quantity) in item_selections { - println!("Item {} taken with quantity: {}", index, quantity); - } -} |
