ares/cli_pretty_printing/
mod.rs

1/// By having all of our print statements in one file it allows us to align what they look like
2/// and make sure each one is up to our standards. Previously a rogue print statement that went off at an edge case
3/// would look a bit ugly and not the same UI as others.
4/// We can also do things like check for logic or share information / functions which would be a bit messy in the main code.
5use crate::DecoderResult;
6
7/// The output function is used to print the output of the program.
8/// If the API mode is on, it will not print.
9pub fn program_exiting_successful_decoding(result: DecoderResult) {
10    let config = crate::config::get_config();
11    if config.api_mode {
12        return;
13    }
14    let plaintext = result.text;
15    // calculate path
16    let decoded_path = result
17        .path
18        .iter()
19        .map(|c| c.decoder)
20        .collect::<Vec<_>>()
21        .join(" → ");
22
23    let decoded_path_coloured = ansi_term::Colour::Yellow.bold().paint(&decoded_path);
24    let decoded_path_string = if !decoded_path.contains('→') {
25        // handles case where only 1 decoder is used
26        format!("the decoder used is {}", decoded_path_coloured)
27    } else {
28        format!("the decoders used are {}", decoded_path_coloured)
29    };
30    println!(
31        "The plaintext is: \n{}\nand {}",
32        ansi_term::Colour::Yellow.bold().paint(&plaintext[0]),
33        decoded_path_string
34    );
35}
36
37/// The output function is used to print the output of the program.
38pub fn decoded_how_many_times(depth: u32) {
39    let config = crate::config::get_config();
40    if config.api_mode {
41        return;
42    }
43
44    // Gets how many decoders we have
45    // Then we add 25 for Caesar
46    let decoders = crate::filtration_system::filter_and_get_decoders(&DecoderResult::default());
47    let decoded_times_int = depth * (decoders.components.len() as u32 + 25);
48    let decoded_times_str = format!("{} times", decoded_times_int);
49
50    let time_took = calculate_time_took(decoded_times_int);
51
52    // TODO add colour to the times
53    println!("\n🄳 Ares has decoded {} times.\nIf you would have used Ciphey, it would have taken you {}\n", decoded_times_str, time_took);
54}
55
56/// Whenever the human checker checks for text, this function is run.
57/// The human checker checks to see if API mdoe is runnign inside of it
58/// rather than doing it here at the printing level
59pub fn human_checker_check(description: &str, text: &str) {
60    println!(
61        "šŸ•µļø I think the plaintext is {}.\nPossible plaintext: '{}' (y/N): ",
62        ansi_term::Colour::Yellow.bold().paint(description),
63        ansi_term::Colour::Yellow.bold().paint(text)
64    )
65}
66
67/// When Ares has failed to decode something, print this message
68pub fn failed_to_decode() {
69    let config = crate::config::get_config();
70    if config.api_mode {
71        return;
72    }
73
74    println!("ā›”ļø Ares has failed to decode the text.");
75    println!("If you want more help, please ask in #coded-messages in our Discord http://discord.skerritt.blog");
76}
77/// Calculate how long it would take to decode this in Ciphey
78fn calculate_time_took(decoded_times_int: u32) -> String {
79    // TODO if we grab how long the programs been running for (see timer) we can make some nice stats like:
80    // * How many decodings / second we did
81    // * How much longer it'd take in Ciphey
82    // We'll guess Ciphey can do 8 a second. No science here, it's arbitrary based on my opinion
83    let ciphey_decodings_a_second = 5;
84    // Calculate how long it'd take in Ciphey
85    let ciphey_how_long_to_decode_in_seconds = decoded_times_int / ciphey_decodings_a_second;
86    if ciphey_how_long_to_decode_in_seconds > 60 {
87        // If it took
88        if ciphey_how_long_to_decode_in_seconds / 60 == 1 {
89            // Handle case where it's each 1 minute
90            // TODO 1 minutes is still broken for me
91            format!("{} minute", ciphey_how_long_to_decode_in_seconds / 60)
92        } else {
93            // 1.26 minutes sounds good in English
94            // So we do not need to handle special case here
95            format!("{} minutes", ciphey_how_long_to_decode_in_seconds / 60)
96        }
97    } else {
98        format!("{} seconds", ciphey_how_long_to_decode_in_seconds)
99    }
100}
101
102/// Every second the timer ticks once
103/// If the timer hits our countdown, we exit the program.
104/// This function prints the countdown to let the user know the program is still running.
105pub fn countdown_until_program_ends(seconds_spent_running: u32, duration: u32) {
106    let config = crate::config::get_config();
107    if config.api_mode {
108        return;
109    }
110    if seconds_spent_running % 5 == 0 && seconds_spent_running != 0 {
111        let time_left = duration - seconds_spent_running;
112        if time_left == 0 {
113            return;
114        }
115        println!(
116            "{} seconds have passed. {} remaining",
117            seconds_spent_running, time_left
118        );
119    }
120}
121
122/// The input given to Ares is already plaintext
123/// So we do not need to do anything
124pub fn return_early_because_input_text_is_plaintext() {
125    let config = crate::config::get_config();
126    if config.api_mode {
127        return;
128    }
129    println!("Your input text is the plaintext 🄳");
130}
131
132/// The user has provided both textual input and file input
133/// # Panics
134/// This function panics and is only used in the CLI.
135pub fn panic_failure_both_input_and_fail_provided() {
136    let config = crate::config::get_config();
137    if config.api_mode {
138        return;
139    }
140    panic!("Failed -- both file and text were provided. Please only use one.")
141}
142
143/// The user has not provided any input.
144/// # Panics
145/// This function panics and is only used in the CLI.
146pub fn panic_failure_no_input_provided() {
147    let config = crate::config::get_config();
148    if config.api_mode {
149        return;
150    }
151    panic!("Failed -- no input was provided. Please use -t for text or -f for files.")
152}