From af295927b02dafd10e68e1d299033c3d480b318a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radli=C5=84ski=20Ignacy?= Date: Thu, 19 Oct 2023 08:34:21 +0200 Subject: [PATCH] add default dictionary to compiled binary (#31) * put default dictionary into rust codebase * fix tests * remove comment * update docs --- Cargo.toml | 1 - README.md | 21 +++++++++--------- src/config.rs | 31 +++++++++++++++------------ src/{dict/words.txt => dictionary.rs} | 6 ++++-- src/expected_input.rs | 16 ++++++++------ src/main.rs | 19 ++++++++-------- src/test_results.rs | 15 ++++++++----- 7 files changed, 61 insertions(+), 48 deletions(-) rename src/{dict/words.txt => dictionary.rs} (98%) diff --git a/Cargo.toml b/Cargo.toml index f946047..e9c4f50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,6 @@ name = "donkeytype" version = "0.1.0" edition = "2021" -rust-version = "1.70" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/README.md b/README.md index 7a2f385..1fb9ccf 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ a _very_ minimalistic _cli_ typing test. ![gif demonstraiting how the program works](https://github.com/radlinskii/donkeytype/assets/26116041/4c2a1b6d-e70e-4631-8438-9259cc780a36) - ## How it works When the program is run you will see the expected input displayed at the top of your terminal window. @@ -31,7 +30,6 @@ You can clone the repo, and run the main program with default configuration usin cargo run ``` - To view the history of results in a bar chart you can run: ```shell @@ -40,7 +38,6 @@ cargo run -- history picture demonstraiting bar chart with history data - To see all available options run: ```shell @@ -58,14 +55,16 @@ Configuration will grow when more features are added (_different modes_, _differ Default config looks like this: -| name | default value | type in JSON | description | -| ----------------- | ---------------------- | ------------ | ------------------------------------------------------------------------- | -| `duration` | `30` | number | duration of the test in seconds | -| `numbers` | `false` | boolean | flag indicating if numbers should be inserted in expected input | -| `numbers_ratio` | `0.05` if numbers=TRUE | number | ratio for putting numbers in the test | -| `uppercase` | `false` | boolean | flag indicating if uppercase letters should be inserted in expected input | -| `uppercase_ratio` | `0.25` | boolean | ratio for putting uppercase letters in test | -| `dictionary_path` | `"src/dict/words.txt"` | string | dictionary words to sample from while creating test's expected input | +| name | default value | type in JSON | description | +| ----------------- | --------------------------- | ------------ | -------------------------------------------------------------------------------------- | +| `duration` | `30` | number | duration of the test in seconds | +| `numbers` | `false` | boolean | flag indicating if numbers should be inserted in expected input | +| `numbers_ratio` | `0.05` (if numbers=TRUE) | number | ratio for putting numbers in the test | +| `uppercase` | `false` | boolean | flag indicating if uppercase letters should be inserted in expected input | +| `uppercase_ratio` | `0.15` | boolean | ratio for putting uppercase letters in test | +| `dictionary_path` | `None` (builtin dictionary) | string | path to file with dictionary words to sample from while creating test's expected input | +| `save_results` | `true` | boolean | flag indicating if results should be saved to a file | +| `dictionary_path` | `"src/dict/words.txt"` | string | dictionary words to sample from while creating test's expected input | > NOTE: If provided `numbers_ratio` is not between `0` to `1.0`, Default `numbers_ratio = 0.05` will be used. > Same happens with `uppercase_ratio`. diff --git a/src/config.rs b/src/config.rs index bfff9a9..975bbef 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,15 +2,15 @@ //! //! Default options of configuration are: //! -//! | name | default value | type in JSON | description | -//! | ----------------- | ---------------------- | ------------ | ------------------------------------------------------------------------- | -//! | `duration` | `30` | number | duration of the test in seconds | -//! | `numbers` | `false` | boolean | flag indicating if numbers should be inserted in expected input | -//! | `numbers_ratio` | `0.05` if numbers=TRUE | number | ratio for putting numbers in the test | -//! | `uppercase` | `false` | boolean | flag indicating if uppercase letters should be inserted in expected input | -//! | `uppercase_ratio` | `0.15` | boolean | ratio for putting uppercase letters in test | -//! | `dictionary_path` | `"src/dict/words.txt"` | string | dictionary words to sample from while creating test's expected input | -//! | `save_results` | `true` | boolean | flag indicating if results should be saved to a file | +//! | name | default value | type in JSON | description | +//! | ----------------- | ---------------------------- | ------------ | --------------------------------------------------------------------------------------- | +//! | `duration` | `30` | number | duration of the test in seconds | +//! | `numbers` | `false` | boolean | flag indicating if numbers should be inserted in expected input | +//! | `numbers_ratio` | `0.05` (if numbers=TRUE) | number | ratio for putting numbers in the test | +//! | `uppercase` | `false` | boolean | flag indicating if uppercase letters should be inserted in expected input | +//! | `uppercase_ratio` | `0.15` | boolean | ratio for putting uppercase letters in test | +//! | `dictionary_path` | `None` (builtin dictionary) | string | path to file with dictionary words to sample from while creating test's expected input | +//! | `save_results` | `true` | boolean | flag indicating if results should be saved to a file | //! //! NOTE: If provided `numbers_ratio` is not between `0` to `1.0`, Default `numbers_ratio = 0.05` will be used. //! NOTE: If provided `uppercase_ratio` is not between `0` to `1.0`, Default `numbers_ratio = 0.15` will be used. @@ -64,7 +64,7 @@ pub struct Config { pub duration: Duration, pub numbers: bool, pub numbers_ratio: f64, - pub dictionary_path: PathBuf, + pub dictionary_path: Option, pub uppercase: bool, pub uppercase_ratio: f64, pub colors: ColorScheme, @@ -101,7 +101,7 @@ impl Config { duration: Duration::from_secs(30), numbers: false, numbers_ratio: 0.05, - dictionary_path: PathBuf::from("src/dict/words.txt"), + dictionary_path: None, uppercase: false, uppercase_ratio: 0.15, colors: ColorScheme::default(), @@ -159,7 +159,7 @@ fn augment_config_with_config_file(config: &mut Config, mut config_file: fs::Fil } if let Some(dictionary_path) = config_from_file.dictionary_path { - config.dictionary_path = PathBuf::from(dictionary_path); + config.dictionary_path = Some(PathBuf::from(dictionary_path)); } if let Some(uppercase) = config_from_file.uppercase { @@ -221,7 +221,7 @@ fn augment_config_with_args(config: &mut Config, args: Args) { config.duration = Duration::from_secs(duration); } if let Some(dictionary_path) = args.dictionary_path { - config.dictionary_path = PathBuf::from(dictionary_path); + config.dictionary_path = Some(PathBuf::from(dictionary_path)); } if let Some(uppercase_flag) = args.uppercase { config.uppercase = uppercase_flag @@ -338,7 +338,10 @@ mod tests { assert_eq!(config.duration, Duration::from_secs(20)); assert_eq!(config.numbers, false); assert_eq!(config.numbers_ratio, 0.05); - assert_eq!(config.dictionary_path, PathBuf::from("/etc/dict/words")); + assert_eq!( + config.dictionary_path, + Some(PathBuf::from("/etc/dict/words")) + ); assert_eq!(config.save_results, true); } } diff --git a/src/dict/words.txt b/src/dictionary.rs similarity index 98% rename from src/dict/words.txt rename to src/dictionary.rs index 5168228..85751d8 100644 --- a/src/dict/words.txt +++ b/src/dictionary.rs @@ -1,4 +1,6 @@ -the +//! module with words used to generate expected input + +pub const WORDS: &str = "the of to and @@ -997,4 +999,4 @@ meant quotient teeth shell -neck +neck"; diff --git a/src/expected_input.rs b/src/expected_input.rs index c7d0c86..22d8c2b 100644 --- a/src/expected_input.rs +++ b/src/expected_input.rs @@ -13,6 +13,7 @@ use rand::{seq::SliceRandom, thread_rng, Rng}; use std::io::Read; use crate::config::Config; +use crate::dictionary; use crate::helpers::split_by_char_index; /// Struct used by runner to hold generate the text used for validation and as a placeholder @@ -28,11 +29,14 @@ impl ExpectedInput { /// then replace some words with numbers if specified in config /// then save one long string to memory pub fn new(config: &Config) -> Result { - let mut file = std::fs::File::open(config.dictionary_path.clone()) - .context("Unable to open dictionary file")?; - let mut str = String::new(); - file.read_to_string(&mut str) - .context("Unable to read dictionary file")?; + let mut str = dictionary::WORDS.to_string(); + if let Some(dictionary_path) = &config.dictionary_path { + str = String::from(""); + let mut file = + std::fs::File::open(dictionary_path).context("Unable to open dictionary file")?; + file.read_to_string(&mut str) + .context("Unable to read dictionary file")?; + } let mut rng = thread_rng(); let mut str_vec = str.split("\n").collect::>(); @@ -158,7 +162,7 @@ mod tests { duration: Duration::from_secs(30), numbers: false, numbers_ratio: 0.05, - dictionary_path: config_file.path().to_path_buf(), + dictionary_path: Some(config_file.path().to_path_buf()), uppercase: false, uppercase_ratio: 0.45, colors: ColorScheme::default(), diff --git a/src/main.rs b/src/main.rs index 79e2710..7b359d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,15 +18,15 @@ //! //! Default options of configuration are: //! -//! | name | default value | type in JSON | description | -//! | ----------------- | ---------------------- | ------------ | ------------------------------------------------------------------------- | -//! | `duration` | `30` | number | duration of the test in seconds | -//! | `numbers` | `false` | boolean | flag indicating if numbers should be inserted in expected input | -//! | `numbers_ratio` | `0.05` if numbers=TRUE | number | ratio for putting numbers in the test | -//! | `uppercase` | `false` | boolean | flag indicating if uppercase letters should be inserted in expected input | -//! | `uppercase_ratio` | `0.15` | boolean | ratio for putting uppercase letters in test | -//! | `dictionary_path` | `"src/dict/words.txt"` | string | dictionary words to sample from while creating test's expected input | -//! | `save_results` | `true` | boolean | flag indicating if results should be saved to a file | +//! | name | default value | type in JSON | description | +//! | ----------------- | ---------------------------- | ------------ | --------------------------------------------------------------------------------------- | +//! | `duration` | `30` | number | duration of the test in seconds | +//! | `numbers` | `false` | boolean | flag indicating if numbers should be inserted in expected input | +//! | `numbers_ratio` | `0.05` (if numbers=TRUE) | number | ratio for putting numbers in the test | +//! | `uppercase` | `false` | boolean | flag indicating if uppercase letters should be inserted in expected input | +//! | `uppercase_ratio` | `0.15` | boolean | ratio for putting uppercase letters in test | +//! | `dictionary_path` | `None` (builtin dictionary) | string | path to file with dictionary words to sample from while creating test's expected input | +//! | `save_results` | `true` | boolean | flag indicating if results should be saved to a file | //! //! NOTE: If provided `numbers_ratio` is not between `0` to `1.0`, Default `numbers_ratio = 0.05` will be used. //! NOTE: If provided `uppercase_ratio` is not between `0` to `1.0`, Default `numbers_ratio = 0.15` will be used. @@ -69,6 +69,7 @@ mod args; mod color_scheme; mod config; +mod dictionary; mod expected_input; mod helpers; mod runner; diff --git a/src/test_results.rs b/src/test_results.rs index b968bee..b77f361 100644 --- a/src/test_results.rs +++ b/src/test_results.rs @@ -84,6 +84,15 @@ impl Stats { impl TestResults { /// creates TestResults object from Stats and Config pub fn new(stats: Stats, config: Config, completed: bool) -> Self { + fn get_dictionary_path(dictionary_path: Option) -> Option { + if let Some(path) = dictionary_path { + if let Some(str) = path.to_str() { + return Some(str.to_string()); + } + } + Some("default_dictionary".to_string()) + } + TestResults { local_datetime: Local::now(), // stats @@ -100,11 +109,7 @@ impl TestResults { duration: Some(config.duration.as_secs()), numbers: Some(config.numbers), numbers_ratio: Some(config.numbers_ratio), - dictionary_path: if let Some(str) = config.dictionary_path.to_str() { - Some(str.to_string()) - } else { - None - }, + dictionary_path: get_dictionary_path(config.dictionary_path), uppercase: Some(config.uppercase), uppercase_ratio: Some(config.uppercase_ratio),