Skip to content
Snippets Groups Projects
console.rs 5.72 KiB
Newer Older
y.zobus's avatar
y.zobus committed
use clap::Parser;
use structopt::StructOpt;
use rprompt::prompt_reply;
use std::path::Path;
use crate::{analyzer::AnalyzerType, error::OpossumError};
use strum::IntoEnumIterator;

type Result<T> = std::result::Result<T, OpossumError>;

/// Simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
pub struct Args {
    /// file path to buikd-filed of the optical setup, which should be read in 
    #[arg(short, long)]
    pub file_path: String,

    /// analyzer type that should be used to analyze the optical setup
    #[arg(short, long)]
    pub analyzer: String,

y.zobus's avatar
y.zobus committed
    /// destination directory of the report. if not defined, same directory as the filepath for the optical setup is used
y.zobus's avatar
y.zobus committed
    #[arg(short, long)]
y.zobus's avatar
y.zobus committed
    pub report_directory: String,
y.zobus's avatar
y.zobus committed
}
y.zobus's avatar
y.zobus committed


#[derive(Parser, StructOpt)]
pub struct PartialArgs {
    /// filepath of the opticscenery to read in 
    #[arg(short, long)]
    file_path: Option<String>,

    /// analyzer type that should be used to analyze the optical setup
    #[arg(short, long)]
    analyzer: Option<String>,
y.zobus's avatar
y.zobus committed

y.zobus's avatar
y.zobus committed
    /// destination directory of the report. if not defined, same directory as the filepath for the optical setup is used
y.zobus's avatar
y.zobus committed
    #[arg(short, long)]
y.zobus's avatar
y.zobus committed
    report_directory: Option<String>,
}
y.zobus's avatar
y.zobus committed

y.zobus's avatar
y.zobus committed
fn file_path_is_valid(path: &str) -> bool{
    Path::exists(Path::new(path)) && Path::is_file(Path::new(path)) && path.ends_with(".yaml")
}

fn eval_file_path(path: Option<String>, err_count:&mut usize) -> Result<String>{
    match path{
        Some(f) => {
            if file_path_is_valid(&f) {
                Ok(f)
            }
            else{
                user_prompt(&format!("Invalid file path: {}\nFile must be inside of an existing directory end end with .yaml!\n\nPlease insert valid file path!\n", f), "f", err_count)
            }
        },
        None => user_prompt("Insert path to optical-setup-description file:\n", "f", err_count)
    }
}

fn eval_analyzer_flag(analyzer_flag: Option<String>, err_count:&mut usize) -> Result<String>{
    match analyzer_flag{
        Some(flag) => {
            match flag.as_str() {
                "e" => Ok("energy".to_owned()),
                "p" => Ok("paraxial ray-tracing".to_owned()),
                _ => {
                    *err_count += 1;
                    user_prompt(&format!("Invalid analyzer flag: {}\n\nPlease choose an analyzer for your setup:\n", flag), "a", err_count)
                }
            }
        }
        None => user_prompt("Please choose an analyzer for your setup:\n", "a", err_count)       
    }
}

fn eval_report_directory(report_dir: Option<String>, err_count: &mut usize) -> Result<String>{
    match report_dir{
        Some(r) => {
            let r_path = Path::new(&r);
            if Path::exists(r_path){
                if r_path.ends_with("\\"){
                    Ok(r.to_owned())
                }
                else{
                    Ok(r + "\\")
                }
            }
            else if r == "" {
                Ok("".to_owned())
            }
            else{
                user_prompt(&format!("Invalid directory: {}\n\nPlease insert a valid directory or nothing to choose the same directory as the optical-setup file\n", r), "r", err_count)
            }
        },
        None => Ok("".to_owned())
    }
y.zobus's avatar
y.zobus committed
}

fn user_prompt(prompt: &str, check_flag: &str, err_count: &mut usize) -> Result<String>{
    if *err_count < 3{
        match check_flag{
            "f" => {
                let input: String = prompt_reply(prompt).unwrap();
y.zobus's avatar
y.zobus committed
                eval_file_path(Some(input), err_count)
y.zobus's avatar
y.zobus committed
            }
            "a" => 
            {
                let mut prompt_str = prompt.to_owned();
                for a_type in AnalyzerType::iter(){
                    prompt_str += match a_type {
                        AnalyzerType::Energy => "e for energy analysis\n",
                        AnalyzerType::ParAxialRayTrace=> "p for paraxial ray-tracing analysis\n", 
                    };
                }
                let input: String = prompt_reply(prompt_str).unwrap();

y.zobus's avatar
y.zobus committed
                eval_analyzer_flag(Some(input), err_count)
            }
            "r" => 
            {
                let input: String = prompt_reply(prompt).unwrap();
                eval_report_directory(Some(input), err_count)
y.zobus's avatar
y.zobus committed
            }
            _ => {
                Err(OpossumError::Console("Wrong check flag! This type of flag is not defined!".into()))
            }
        }
    }
    else{
        Err(OpossumError::Console("Too many wrong inputs! Program exits! Please type \"opossum.exe -h\" for help!".into()))
    }

}

impl TryFrom<PartialArgs> for Args{
    type Error = OpossumError;

    fn try_from(part_args: PartialArgs) -> Result<Args> {
        let mut err_count: usize = 0;

y.zobus's avatar
y.zobus committed
        let file_path = eval_file_path(part_args.file_path, &mut err_count)?;
y.zobus's avatar
y.zobus committed
        println!("{}", format!("Path to optical-setup file: {}\n", file_path));

y.zobus's avatar
y.zobus committed
        let analyzer = eval_analyzer_flag(part_args.analyzer, &mut err_count)?;
y.zobus's avatar
y.zobus committed
        println!("{}", format!("Chosen analysis: {}\n", analyzer));
y.zobus's avatar
y.zobus committed

        let report_directory = eval_report_directory(part_args.report_directory, &mut err_count)?;
        let report_directory = if report_directory.is_empty(){
            Path::parent(Path::new(&file_path))
                .unwrap()
                .to_str()
                .unwrap()
                .to_owned()
        }
        else{
            report_directory
        };
        println!("{}", format!("Report directory: {}\n", report_directory));
y.zobus's avatar
y.zobus committed
        
y.zobus's avatar
y.zobus committed
        Ok(Args{ file_path: file_path, analyzer: analyzer, report_directory: report_directory})
y.zobus's avatar
y.zobus committed
    }
}