diff --git a/src/commands/derive_db.rs b/src/commands/derive_db.rs index 0e1d9e8..408cc12 100644 --- a/src/commands/derive_db.rs +++ b/src/commands/derive_db.rs @@ -3,7 +3,7 @@ use log::info; use crate::{ data::{ - database, + database::Database, maps::{link_map::LinkMap, page_map::PageMap}, parsers::{links, pages, redirects}, }, @@ -112,7 +112,8 @@ fn derive_db_command(args: DeriveDbArgs) { .with_finish_message("Serialized and written to file") .build(); spinner.enable_background(); - database::serialize(output.as_str(), &links, &lookup); + Database::new(links, lookup).to_file(output.as_str()); + spinner.finish(); } } diff --git a/src/commands/interactive.rs b/src/commands/interactive.rs index 4ce7190..beaae2e 100644 --- a/src/commands/interactive.rs +++ b/src/commands/interactive.rs @@ -3,7 +3,7 @@ use clap::Args; use crate::{ data::{ algorithm::bfs, - database, + database::Database, maps::page_map::{PageMap, PageMapResult}, }, indication::ProgressBuilder, @@ -27,20 +27,23 @@ impl ArgExecutor for InteractiveArgs { fn interactive_cmd(args: &InteractiveArgs) { let db = args.db.to_string(); - let spinner = ProgressBuilder::spinner() - .with_message("📝 Deserializing DB") - .build(); - spinner.enable_background(); - let data = database::deserialize(&db); - spinner.finish(); + let db = { + let spinner = ProgressBuilder::spinner() + .with_message("📝 Deserializing DB") + .build(); + spinner.enable_background(); + let data = Database::from_file(&db); + spinner.finish(); + data + }; println!( "Usage: Enter a start page and a target page to find the shortest path between them If you want to exit press ctrl+d or ctrl+c\n" ); - let links = data.links; - let lookup = data.pages; + let links = db.links; + let lookup = db.pages; fn page_input_loop(prompt: &str, pages: &PageMap) -> Option { loop { @@ -75,12 +78,12 @@ If you want to exit press ctrl+d or ctrl+c\n" let end = end.unwrap(); let (path, time) = { - let time_before = std::time::Instant::now(); let spinner = ProgressBuilder::spinner() .with_message("Searching for path") .build(); spinner.enable_background(); + let time_before = std::time::Instant::now(); let path = bfs::find_shortest_path(start.id, end.id, &links); let time = time_before.elapsed().as_millis(); diff --git a/src/data/algorithm/bfs.rs b/src/data/algorithm/bfs.rs index fa3e4dd..7002f1f 100644 --- a/src/data/algorithm/bfs.rs +++ b/src/data/algorithm/bfs.rs @@ -4,6 +4,21 @@ use log::debug; use crate::data::maps::link_map::LinkMap; +fn rebuild_path(predecessors: HashMap, start: i32, end: i32) -> Vec { + let mut out_path = VecDeque::new(); + out_path.push_front(end); + let mut at = end; + while let Some(&node) = predecessors.get(&at) { + if at == start { + break; + } + out_path.push_front(node); + at = node; + } + + Vec::from(out_path) +} + pub fn find_shortest_path(start: i32, end: i32, links: &LinkMap) -> Option> { if start == end { return Some(vec![start]); @@ -12,6 +27,7 @@ pub fn find_shortest_path(start: i32, end: i32, links: &LinkMap) -> Option Option Option { - pub links: &'a LinkMap, - pub pages: &'a PageMap, -} - -#[derive(Deserialize)] +#[derive(Serialize, Deserialize)] pub struct Database { pub links: LinkMap, pub pages: PageMap, } -pub fn serialize(outfile: &str, links: &LinkMap, pages: &PageMap) { - let db = SerializerDatabase { links, pages }; +impl Database { + pub fn new(links: LinkMap, pages: PageMap) -> Self { + Self { links, pages } + } - let file = std::fs::File::create(outfile).unwrap(); - let writer = std::io::BufWriter::new(file); + pub fn to_file(&self, outfile: &str) { + let file = std::fs::File::create(outfile).unwrap(); + let writer = std::io::BufWriter::new(file); - ciborium::into_writer(&db, writer).expect("Error writing db"); -} + ciborium::into_writer(self, writer).expect("Error writing db"); + } -pub fn deserialize(infile: &str) -> Database { - let file = std::fs::File::open(infile).unwrap(); - let reader = std::io::BufReader::new(file); + pub fn from_file(infile: &str) -> Database { + let file = std::fs::File::open(infile).unwrap(); + let reader = std::io::BufReader::new(file); - ciborium::from_reader(reader).expect("Error reading db") + ciborium::from_reader(reader).expect("Error reading db") + } } diff --git a/src/indication.rs b/src/indication.rs index 9dae94a..64f13dd 100644 --- a/src/indication.rs +++ b/src/indication.rs @@ -1,9 +1,8 @@ -#![allow(dead_code)] // todo: remove this when tests are implemented use std::time::Duration; use indicatif::{ProgressBar, ProgressStyle}; -fn progressbar_template(len: u64) -> ProgressBar { +fn progressbar(len: u64) -> ProgressBar { let pb = ProgressBar::new(len); pb.set_style( ProgressStyle::with_template( @@ -45,7 +44,7 @@ impl ProgressReporter { finish_message: &'static str, len: u64, ) -> Self { - let progress = progressbar_template(len); + let progress = progressbar(len); progress.set_prefix(format!("[{}/{}]", step, steps)); progress.set_message(message.clone()); @@ -73,6 +72,7 @@ impl ProgressReporter { } } + #[cfg(test)] pub fn new_empty() -> Self { Self { progress: None, @@ -106,6 +106,7 @@ impl ProgressReporter { enum ProgressType { Progress, Spinner, + #[cfg(test)] Empty, } @@ -119,6 +120,7 @@ pub struct ProgressBuilder { } impl ProgressBuilder { + #[cfg(test)] pub fn empty() -> Self { Self { bar_type: ProgressType::Empty, @@ -129,6 +131,7 @@ impl ProgressBuilder { step: None, } } + pub fn new() -> Self { Self { bar_type: ProgressType::Progress, @@ -172,6 +175,7 @@ impl ProgressBuilder { self } + #[cfg(test)] fn build_empty(self) -> ProgressReporter { ProgressReporter::new_empty() } @@ -192,8 +196,8 @@ impl ProgressBuilder { let finish_message = self.finish_message; let steps = self - .steps - .map(|steps| (steps, self.step.expect("only steps given, no step"))); + .step + .map(|step| (step, self.steps.expect("only step given, steps missing"))); ProgressReporter::new_spinner(message, finish_message, steps) } @@ -202,6 +206,7 @@ impl ProgressBuilder { match self.bar_type { ProgressType::Progress => self.build_progress(), ProgressType::Spinner => self.build_spinner(), + #[cfg(test)] ProgressType::Empty => self.build_empty(), } } diff --git a/src/main.rs b/src/main.rs index 19c7df1..567254b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use clap::{Parser, Subcommand}; +use clap::Parser; mod commands; mod data; @@ -11,32 +11,6 @@ struct Args { command: Option, } -#[derive(Subcommand, Debug)] -enum SubCommands { - DeriveDB { - /// Path to the page.sql file - #[arg(short, long)] - pages_sql: String, - - /// Path to the redirects.sql file - #[arg(short, long)] - redirects_sql: String, - - /// Path to the links.sql file - #[arg(short, long)] - links_sql: String, - - /// Output Path - #[arg(short, long)] - output: String, - }, - - Test { - #[arg(short, long)] - db: String, - }, -} - fn main() { env_logger::init(); let args = Args::parse();