From dfc5cdd7cfc9d6635fa6a86e375b6e651265de77 Mon Sep 17 00:00:00 2001 From: TolaMironcenko Date: Fri, 21 Nov 2025 12:15:50 +0700 Subject: [PATCH] initial commit --- .cargo/config.toml | 6 + .gitignore | 1 + Cargo.lock | 233 ++++ Cargo.toml | 8 + src/main.rs | 549 ++++++++ words.txt | 3000 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 3797 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs create mode 100644 words.txt diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..1025267 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,6 @@ +[profile.release] +opt-level = "z" +lto = true +codegen-units = 1 +panic = "abort" +strip = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a53a9e5 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,233 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "cc" +version = "1.2.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "ncurses" +version = "5.101.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2c5d34d72657dc4b638a1c25d40aae81e4f1c699062f72f467237920752032" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "pancurses" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0352975c36cbacb9ee99bfb709b9db818bed43af57751797f8633649759d13db" +dependencies = [ + "libc", + "log", + "ncurses", + "pdcurses-sys", + "winreg", +] + +[[package]] +name = "pdcurses-sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084dd22796ff60f1225d4eb6329f33afaf4c85419d51d440ab6b8c6f4529166b" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "typing-test" +version = "0.1.0" +dependencies = [ + "pancurses", + "rand", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winreg" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" +dependencies = [ + "winapi", +] + +[[package]] +name = "zerocopy" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43fa6694ed34d6e57407afbccdeecfa268c470a7d2a5b0cf49ce9fcc345afb90" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c640b22cd9817fae95be82f0d2f90b11f7605f6c319d16705c459b27ac2cbc26" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..54093af --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "typing-test" +version = "0.1.0" +edition = "2024" + +[dependencies] +pancurses = "0.17" +rand = "0.8" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d27b452 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,549 @@ +use pancurses::{ + A_BOLD, A_REVERSE, COLOR_PAIR, Input, Window, curs_set, endwin, init_pair, initscr, noecho, + start_color, +}; +use rand::seq::SliceRandom; +use std::collections::VecDeque; +use std::fs::File; +use std::io::{self, BufRead}; +use std::time::{SystemTime, UNIX_EPOCH}; + +const TYPED_COLOR: i16 = 1; +const UNTYPED_COLOR: i16 = 2; +const MISTAKE_COLOR: i16 = 3; +const SELECTED_COLOR: i16 = 4; + +#[derive(Debug, Clone, Copy)] +enum TestType { + Time(f64), // Duration in seconds + Words(usize), // Number of words +} + +#[derive(Debug)] +struct Test { + pos: usize, + start_time: u128, + finish_time: Option, + keystrokes_count: usize, + correct_keystrokes: usize, + type_tape: VecDeque, + tape: VecDeque, + mistakes: usize, + test_type: TestType, + words_typed: usize, // For word count mode +} + +impl Test { + fn new(test_type: TestType) -> Self { + Test { + pos: 0, + start_time: SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis(), + finish_time: None, + keystrokes_count: 0, + correct_keystrokes: 0, + type_tape: VecDeque::with_capacity(256), + tape: VecDeque::with_capacity(256), + mistakes: 0, + test_type, + words_typed: 0, + } + } + + fn finish(&mut self) { + self.finish_time = Some( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis(), + ); + } + + fn duration(&self) -> f64 { + let end_time = match self.finish_time { + Some(t) => t, + None => SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis(), + }; + (end_time - self.start_time) as f64 / 1000.0 + } + + fn wpm(&self) -> f64 { + let duration = self.duration(); + if duration == 0.0 { + return 0.0; + } + (self.correct_keystrokes as f64 / duration) * 60.0 / 5.0 + } + + fn accuracy(&self) -> f64 { + if self.keystrokes_count == 0 { + return 100.0; + } + (self.correct_keystrokes as f64 / self.keystrokes_count as f64) * 100.0 + } + + fn write(&mut self, ch: char) { + if self.finish_time.is_some() { + return; + } + + self.keystrokes_count += 1; + + if let Some(&expected) = self.tape.front() { + if ch == expected { + self.correct_keystrokes += 1; + self.type_tape.push_back(ch); + self.tape.pop_front(); + self.pos += 1; + + // Check if we completed a word (space character) + if ch == ' ' { + self.words_typed += 1; + } + + // Check completion condition + match self.test_type { + TestType::Time(_) => { + // Time-based test - no early completion + } + TestType::Words(word_count) => { + if self.words_typed >= word_count { + self.finish(); + } + } + } + } else { + self.mistakes += 1; + // Don't finish test on mistake, just count it + } + } + } + + fn backspace(&mut self) { + if self.finish_time.is_some() || self.type_tape.is_empty() { + return; + } + + if let Some(last_char) = self.type_tape.pop_back() { + self.tape.push_front(last_char); + self.pos -= 1; + // Don't decrease keystrokes_count for backspace, but adjust correct count + if self.correct_keystrokes > 0 { + self.correct_keystrokes -= 1; + } + + // If we're removing a space, decrement words_typed + if last_char == ' ' && self.words_typed > 0 { + self.words_typed -= 1; + } + } + } + + fn is_running(&self) -> bool { + if self.finish_time.is_some() { + return false; + } + + match self.test_type { + TestType::Time(duration) => self.duration() < duration, + TestType::Words(word_count) => self.words_typed < word_count, + } + } + + fn get_progress(&self) -> (String, String) { + match self.test_type { + TestType::Time(duration) => { + let remaining = duration - self.duration(); + let progress = format!("Time: {:.1}s", remaining.max(0.0)); + let target = format!("Target: {:.0}s", duration); + (progress, target) + } + TestType::Words(word_count) => { + let progress = format!("Words: {}/{}", self.words_typed, word_count); + let target = format!("Target: {} words", word_count); + (progress, target) + } + } + } + + fn render(&self, window: &Window) { + let (_max_y, max_x) = window.get_max_yx(); + let cc = (max_x / 2) as i32; + + // Show progress based on test type + let (progress_str, target_str) = self.get_progress(); + window.mv(5, cc - (progress_str.len() as i32 / 2)); + window.addstr(&progress_str); + + window.mv(4, cc - (target_str.len() as i32 / 2)); + window.addstr(&target_str); + + let typed_len = self.type_tape.len().min(cc as usize - 1); + let untyped_len = (cc - 1) as usize; + + let typed_str: String = self + .type_tape + .iter() + .skip(self.type_tape.len().saturating_sub(typed_len)) + .take(typed_len) + .collect(); + + let untyped_str: String = self.tape.iter().take(untyped_len).collect(); + + window.attron(COLOR_PAIR(UNTYPED_COLOR as u32)); + window.mv(10, cc); + window.addstr(&untyped_str); + window.attroff(COLOR_PAIR(UNTYPED_COLOR as u32)); + + window.attron(COLOR_PAIR(TYPED_COLOR as u32)); + let typed_pos = cc - typed_len as i32; + window.mv(10, typed_pos); + window.addstr(&typed_str); + window.attroff(COLOR_PAIR(TYPED_COLOR as u32)); + + // Show current character with highlight + window.attron(A_REVERSE | A_BOLD); + if let Some(&ch) = self.tape.front() { + window.mv(9, cc); + window.addch('|'); + window.mv(10, cc); + window.addch(ch); + window.mv(11, cc); + window.addch('|'); + } + window.attroff(A_REVERSE | A_BOLD); + + // Show stats + let wpm_str = format!("WPM: {:.1}", self.wpm()); + let accuracy_str = format!("Accuracy: {:.1}%", self.accuracy()); + let mistakes_str = format!("Mistakes: {}", self.mistakes); + + window.mv(7, cc - 15); + window.addstr(&wpm_str); + window.mv(7, cc + 2); + window.addstr(&accuracy_str); + window.mv(8, cc - 8); + window.addstr(&mistakes_str); + + // Show instructions + window.mv(12, cc - 15); + window.addstr("Press ESC to return to menu"); + } + + fn show_result(&self, window: &Window) { + window.clear(); + let (max_y, max_x) = window.get_max_yx(); + let cc = (max_x / 2) as i32; + let lc = (max_y / 2) as i32; + + // Draw box + for i in 0..max_x { + window.mv(0, i); + window.addch('#'); + window.mv(max_y - 1, i); + window.addch('#'); + } + for i in 0..max_y { + window.mv(i, 0); + window.addch('#'); + window.mv(i, max_x - 1); + window.addch('#'); + } + + let wpm_str = format!("{:.1}", self.wpm()); + let time_str = format!("{:.1}", self.duration()); + let keystrokes_str = format!("{}", self.keystrokes_count); + let accuracy_str = format!("{:.1}%", self.accuracy()); + let mistakes_str = format!("{}", self.mistakes); + + // Show test type in results + let test_type_str = match self.test_type { + TestType::Time(duration) => format!("{:.0} seconds", duration), + TestType::Words(word_count) => format!("{} words", word_count), + }; + + window.mv(lc - 4, cc - 3); + window.addstr("Test Type: "); + window.mv(lc - 4, cc + 3); + window.addstr(&test_type_str); + + window.mv(lc - 3, cc - 3); + window.addstr("WPM : "); + window.mv(lc - 3, cc + 3); + window.addstr(&wpm_str); + + window.mv(lc - 2, cc - 4); + window.addstr("Time : "); + window.mv(lc - 2, cc + 3); + window.addstr(&time_str); + + window.mv(lc - 1, cc - 10); + window.addstr("Keystrokes : "); + window.mv(lc - 1, cc + 3); + window.addstr(&keystrokes_str); + + window.mv(lc, cc - 10); + window.addstr("Accuracy : "); + window.mv(lc, cc + 3); + window.addstr(&accuracy_str); + + window.mv(lc + 1, cc - 10); + window.addstr("Mistakes : "); + window.mv(lc + 1, cc + 3); + window.addstr(&mistakes_str); + + window.mv(lc + 3, cc - 15); + window.addstr("Press 'R' to restart or 'M' to return to menu"); + + window.mv(lc + 4, cc - 10); + window.addstr("Press 'Q' to quit the program"); + + window.refresh(); + } +} + +fn read_words() -> io::Result> { + let file = File::open("words.txt")?; + let words: Vec = io::BufReader::new(file) + .lines() + .filter_map(Result::ok) + .collect(); + Ok(words) +} + +fn show_test_menu(window: &Window) -> Option { + let time_options = [ + ("15 seconds", TestType::Time(15.0)), + ("30 seconds", TestType::Time(30.0)), + ("1 minute", TestType::Time(60.0)), + ("2 minutes", TestType::Time(120.0)), + ("5 minutes", TestType::Time(300.0)), + ]; + + let word_options = [ + ("15 words", TestType::Words(15)), + ("30 words", TestType::Words(30)), + ("60 words", TestType::Words(60)), + ("120 words", TestType::Words(120)), + ("240 words", TestType::Words(240)), + ]; + + let mut selected = 2; // Default to 1 minute + let mut in_time_mode = true; + + loop { + window.clear(); + let (max_y, max_x) = window.get_max_yx(); + let cc = (max_x / 2) as i32; + let lc = (max_y / 2) as i32; + + // Draw box + for i in 0..max_x { + window.mv(0, i); + window.addch('#'); + window.mv(max_y - 1, i); + window.addch('#'); + } + for i in 0..max_y { + window.mv(i, 0); + window.addch('#'); + window.mv(i, max_x - 1); + window.addch('#'); + } + + window.mv(lc - 7, cc - 10); + window.addstr("Select Test Type and Duration"); + + // Show mode selection + window.mv(lc - 5, cc - 15); + if in_time_mode { + window.attron(COLOR_PAIR(SELECTED_COLOR as u32)); + window.addstr("> Time Mode <"); + window.attroff(COLOR_PAIR(SELECTED_COLOR as u32)); + window.mv(lc - 5, cc + 3); + window.addstr("Word Mode"); + } else { + window.mv(lc - 5, cc - 15); + window.addstr("Time Mode"); + window.attron(COLOR_PAIR(SELECTED_COLOR as u32)); + window.mv(lc - 5, cc + 3); + window.addstr("> Word Mode <"); + window.attroff(COLOR_PAIR(SELECTED_COLOR as u32)); + } + + // Show options based on mode + let options = if in_time_mode { + &time_options + } else { + &word_options + }; + + for (i, (name, _)) in options.iter().enumerate() { + let y = lc - 3 + i as i32; + if i == selected { + window.attron(COLOR_PAIR(SELECTED_COLOR as u32)); + window.mv(y, cc - 8); + window.addstr(&format!("> {} <", name)); + window.attroff(COLOR_PAIR(SELECTED_COLOR as u32)); + } else { + window.mv(y, cc - 6); + window.addstr(name); + } + } + + window.mv(lc + 3, cc - 20); + window.addstr("Use LEFT/RIGHT to switch mode, UP/DOWN to select"); + window.mv(lc + 4, cc - 15); + window.addstr("ENTER to confirm, Q to quit"); + + window.refresh(); + + match window.getch() { + Some(Input::KeyUp) => { + if selected > 0 { + selected -= 1; + } + } + Some(Input::KeyDown) => { + if selected < options.len() - 1 { + selected += 1; + } + } + Some(Input::KeyLeft) | Some(Input::KeyRight) => { + in_time_mode = !in_time_mode; + selected = 2; // Reset to middle option when switching modes + } + Some(Input::Character('\n')) | Some(Input::Character('\r')) => { + let options = if in_time_mode { + &time_options + } else { + &word_options + }; + return Some(options[selected].1); + } + Some(Input::Character('q')) | Some(Input::Character('Q')) => { + return None; + } + _ => {} + } + } +} + +fn run_typing_test( + words: &Vec, + window: &Window, + test_type: TestType, +) -> io::Result> { + let mut test = Test::new(test_type); + + // Fill initial tape + while test.tape.len() < 200 { + if let Some(word) = words.choose(&mut rand::thread_rng()) { + test.tape.extend(word.chars()); + test.tape.push_back(' '); + } + } + + while test.is_running() { + window.clear(); + + // Add more words if needed (only for time-based tests) + if let TestType::Time(_) = test.test_type { + while test.tape.len() < 100 { + if let Some(word) = words.choose(&mut rand::thread_rng()) { + test.tape.extend(word.chars()); + test.tape.push_back(' '); + } + } + } + + test.render(&window); + window.refresh(); + + match window.getch() { + Some(Input::Character(ch)) => { + match ch { + '\x1b' => return Ok(Some(false)), // ESC to return to menu + '\x7f' | '\x08' => test.backspace(), // backspace + _ => test.write(ch), + } + } + Some(Input::KeyResize) => { + // Handle terminal resize + } + _ => {} + } + } + + // Test finished - show results + test.show_result(&window); + + // Wait for user input to restart or quit + loop { + match window.getch() { + Some(Input::Character('r')) | Some(Input::Character('R')) => return Ok(Some(true)), + Some(Input::Character('m')) | Some(Input::Character('M')) => return Ok(Some(false)), + Some(Input::Character('q')) | Some(Input::Character('Q')) => return Ok(None), + _ => {} + } + } +} + +fn main() -> io::Result<()> { + let words = read_words()?; + if words.is_empty() { + eprintln!("No words found in words.txt"); + return Ok(()); + } + + let window = initscr(); + noecho(); + curs_set(0); + window.keypad(true); + start_color(); + init_pair(TYPED_COLOR, pancurses::COLOR_WHITE, pancurses::COLOR_BLACK); + init_pair( + UNTYPED_COLOR, + pancurses::COLOR_GREEN, + pancurses::COLOR_BLACK, + ); + init_pair(MISTAKE_COLOR, pancurses::COLOR_RED, pancurses::COLOR_WHITE); + init_pair( + SELECTED_COLOR, + pancurses::COLOR_BLACK, + pancurses::COLOR_WHITE, + ); + + // Main loop - show menu and run tests + loop { + // Show test selection menu + let test_type = match show_test_menu(&window) { + Some(test_type) => test_type, + None => break, // User chose to quit + }; + + // Run typing test + match run_typing_test(&words, &window, test_type)? { + Some(true) => { + // Restart with same test type + continue; + } + Some(false) => { + // Return to menu + continue; + } + None => { + // Quit + break; + } + } + } + + endwin(); + Ok(()) +} diff --git a/words.txt b/words.txt new file mode 100644 index 0000000..29eb4e8 --- /dev/null +++ b/words.txt @@ -0,0 +1,3000 @@ +a +abandon +ability +able +abortion +about +above +abroad +absence +absolute +absolutely +absorb +abuse +academic +accept +access +accident +accompany +accomplish +according +account +accurate +accuse +achieve +achievement +acid +acknowledge +acquire +across +act +action +active +activist +activity +actor +actress +actual +actually +ad +adapt +add +addition +additional +address +adequate +adjust +adjustment +administration +administrator +admire +admission +admit +adolescent +adopt +adult +advance +advanced +advantage +adventure +advertising +advice +advise +adviser +advocate +affair +affect +afford +afraid +African +African-American +after +afternoon +again +against +age +agency +agenda +agent +aggressive +ago +agree +agreement +agricultural +ah +ahead +aid +aide +AIDS +aim +air +aircraft +airline +airport +album +alcohol +alive +all +alliance +allow +ally +almost +alone +along +already +also +alter +alternative +although +always +AM +amazing +American +among +amount +analysis +analyst +analyze +ancient +and +anger +angle +angry +animal +anniversary +announce +annual +another +answer +anticipate +anxiety +any +anybody +anymore +anyone +anything +anyway +anywhere +apart +apartment +apparent +apparently +appeal +appear +appearance +apple +application +apply +appoint +appointment +appreciate +approach +appropriate +approval +approve +approximately +Arab +architect +area +argue +argument +arise +arm +armed +army +around +arrange +arrangement +arrest +arrival +arrive +art +article +artist +artistic +as +Asian +aside +ask +asleep +aspect +assault +assert +assess +assessment +asset +assign +assignment +assist +assistance +assistant +associate +association +assume +assumption +assure +at +athlete +athletic +atmosphere +attach +attack +attempt +attend +attention +attitude +attorney +attract +attractive +attribute +audience +author +authority +auto +available +average +avoid +award +aware +awareness +away +awful +baby +back +background +bad +badly +bag +bake +balance +ball +ban +band +bank +bar +barely +barrel +barrier +base +baseball +basic +basically +basis +basket +basketball +bathroom +battery +battle +be +beach +bean +bear +beat +beautiful +beauty +because +become +bed +bedroom +beer +before +begin +beginning +behavior +behind +being +belief +believe +bell +belong +below +belt +bench +bend +beneath +benefit +beside +besides +best +bet +better +between +beyond +Bible +big +bike +bill +billion +bind +biological +bird +birth +birthday +bit +bite +black +blade +blame +blanket +blind +block +blood +blow +blue +board +boat +body +bomb +bombing +bond +bone +book +boom +boot +border +born +borrow +boss +both +bother +bottle +bottom +boundary +bowl +box +boy +boyfriend +brain +branch +brand +bread +break +breakfast +breast +breath +breathe +brick +bridge +brief +briefly +bright +brilliant +bring +British +broad +broken +brother +brown +brush +buck +budget +build +building +bullet +bunch +burden +burn +bury +bus +business +busy +but +butter +button +buy +buyer +by +cabin +cabinet +cable +cake +calculate +call +camera +camp +campaign +campus +can +Canadian +cancer +candidate +cap +capability +capable +capacity +capital +captain +capture +car +carbon +card +care +career +careful +carefully +carrier +carry +case +cash +cast +cat +catch +category +Catholic +cause +ceiling +celebrate +celebration +celebrity +cell +center +central +century +CEO +ceremony +certain +certainly +chain +chair +chairman +challenge +chamber +champion +championship +chance +change +changing +channel +chapter +character +characteristic +characterize +charge +charity +chart +chase +cheap +check +cheek +cheese +chef +chemical +chest +chicken +chief +child +childhood +Chinese +chip +chocolate +choice +cholesterol +choose +Christian +Christmas +church +cigarette +circle +circumstance +cite +citizen +city +civil +civilian +claim +class +classic +classroom +clean +clear +clearly +client +climate +climb +clinic +clinical +clock +close +closely +closer +clothes +clothing +cloud +club +clue +cluster +coach +coal +coalition +coast +coat +code +coffee +cognitive +cold +collapse +colleague +collect +collection +collective +college +colonial +color +column +combination +combine +come +comedy +comfort +comfortable +command +commander +comment +commercial +commission +commit +commitment +committee +common +communicate +communication +community +company +compare +comparison +compete +competition +competitive +competitor +complain +complaint +complete +completely +complex +complicated +component +compose +composition +comprehensive +computer +concentrate +concentration +concept +concern +concerned +concert +conclude +conclusion +concrete +condition +conduct +conference +confidence +confident +confirm +conflict +confront +confusion +Congress +congressional +connect +connection +consciousness +consensus +consequence +conservative +consider +considerable +consideration +consist +consistent +constant +constantly +constitute +constitutional +construct +construction +consultant +consume +consumer +consumption +contact +contain +container +contemporary +content +contest +context +continue +continued +contract +contrast +contribute +contribution +control +controversial +controversy +convention +conventional +conversation +convert +conviction +convince +cook +cookie +cooking +cool +cooperation +cop +cope +copy +core +corn +corner +corporate +corporation +correct +correspondent +cost +cotton +couch +could +council +counselor +count +counter +country +county +couple +courage +course +court +cousin +cover +coverage +cow +crack +craft +crash +crazy +cream +create +creation +creative +creature +credit +crew +crime +criminal +crisis +criteria +critic +critical +criticism +criticize +crop +cross +crowd +crucial +cry +cultural +culture +cup +curious +current +currently +curriculum +custom +customer +cut +cycle +dad +daily +damage +dance +danger +dangerous +dare +dark +darkness +data +date +daughter +day +dead +deal +dealer +dear +death +debate +debt +decade +decide +decision +deck +declare +decline +decrease +deep +deeply +deer +defeat +defend +defendant +defense +defensive +deficit +define +definitely +definition +degree +delay +deliver +delivery +demand +democracy +Democrat +democratic +demonstrate +demonstration +deny +department +depend +dependent +depending +depict +depression +depth +deputy +derive +describe +description +desert +deserve +design +designer +desire +desk +desperate +despite +destroy +destruction +detail +detailed +detect +determine +develop +developing +development +device +devote +dialogue +die +diet +differ +difference +different +differently +difficult +difficulty +dig +digital +dimension +dining +dinner +direct +direction +directly +director +dirt +dirty +disability +disagree +disappear +disaster +discipline +discourse +discover +discovery +discrimination +discuss +discussion +disease +dish +dismiss +disorder +display +dispute +distance +distant +distinct +distinction +distinguish +distribute +distribution +district +diverse +diversity +divide +division +divorce +DNA +do +doctor +document +dog +domestic +dominant +dominate +door +double +doubt +down +downtown +dozen +draft +drag +drama +dramatic +dramatically +draw +drawing +dream +dress +drink +drive +driver +drop +drug +dry +due +during +dust +duty +each +eager +ear +early +earn +earnings +earth +ease +easily +east +eastern +easy +eat +economic +economics +economist +economy +edge +edition +editor +educate +education +educational +educator +effect +effective +effectively +efficiency +efficient +effort +egg +eight +either +elderly +elect +election +electric +electricity +electronic +element +elementary +eliminate +elite +else +elsewhere +e-mail +embrace +emerge +emergency +emission +emotion +emotional +emphasis +emphasize +employ +employee +employer +employment +empty +enable +encounter +encourage +end +enemy +energy +enforcement +engage +engine +engineer +engineering +English +enhance +enjoy +enormous +enough +ensure +enter +enterprise +entertainment +entire +entirely +entrance +entry +environment +environmental +episode +equal +equally +equipment +era +error +escape +especially +essay +essential +essentially +establish +establishment +estate +estimate +etc +ethics +ethnic +European +evaluate +evaluation +even +evening +event +eventually +ever +every +everybody +everyday +everyone +everything +everywhere +evidence +evolution +evolve +exact +exactly +examination +examine +example +exceed +excellent +except +exception +exchange +exciting +executive +exercise +exhibit +exhibition +exist +existence +existing +expand +expansion +expect +expectation +expense +expensive +experience +experiment +expert +explain +explanation +explode +explore +explosion +expose +exposure +express +expression +extend +extension +extensive +extent +external +extra +extraordinary +extreme +extremely +eye +fabric +face +facility +fact +factor +factory +faculty +fade +fail +failure +fair +fairly +faith +fall +false +familiar +family +famous +fan +fantasy +far +farm +farmer +fashion +fast +fat +fate +father +fault +favor +favorite +fear +feature +federal +fee +feed +feel +feeling +fellow +female +fence +few +fewer +fiber +fiction +field +fifteen +fifth +fifty +fight +fighter +fighting +figure +file +fill +film +final +finally +finance +financial +find +finding +fine +finger +finish +fire +firm +first +fish +fishing +fit +fitness +five +fix +flag +flame +flat +flavor +flee +flesh +flight +float +floor +flow +flower +fly +focus +folk +follow +following +food +foot +football +for +force +foreign +forest +forever +forget +form +formal +formation +former +formula +forth +fortune +forward +found +foundation +founder +four +fourth +frame +framework +free +freedom +freeze +French +frequency +frequent +frequently +fresh +friend +friendly +friendship +from +front +fruit +frustration +fuel +full +fully +fun +function +fund +fundamental +funding +funeral +funny +furniture +furthermore +future +gain +galaxy +gallery +game +gang +gap +garage +garden +garlic +gas +gate +gather +gay +gaze +gear +gender +gene +general +generally +generate +generation +genetic +gentleman +gently +German +gesture +get +ghost +giant +gift +gifted +girl +girlfriend +give +given +glad +glance +glass +global +glove +go +goal +God +gold +golden +golf +good +government +governor +grab +grade +gradually +graduate +grain +grand +grandfather +grandmother +grant +grass +grave +gray +great +greatest +green +grocery +ground +group +grow +growing +growth +guarantee +guard +guess +guest +guide +guideline +guilty +gun +guy +habit +habitat +hair +half +hall +hand +handful +handle +hang +happen +happy +hard +hardly +hat +hate +have +he +head +headline +headquarters +health +healthy +hear +hearing +heart +heat +heaven +heavily +heavy +heel +height +helicopter +hell +hello +help +helpful +her +here +heritage +hero +herself +hey +hi +hide +high +highlight +highly +highway +hill +him +himself +hip +hire +his +historian +historic +historical +history +hit +hold +hole +holiday +holy +home +homeless +honest +honey +honor +hope +horizon +horror +horse +hospital +host +hot +hotel +hour +house +household +housing +how +however +huge +human +humor +hundred +hungry +hunter +hunting +hurt +husband +hypothesis +I +ice +idea +ideal +identification +identify +identity +ie +if +ignore +ill +illegal +illness +illustrate +image +imagination +imagine +immediate +immediately +immigrant +immigration +impact +implement +implication +imply +importance +important +impose +impossible +impress +impression +impressive +improve +improvement +in +incentive +incident +include +including +income +incorporate +increase +increased +increasing +increasingly +incredible +indeed +independence +independent +index +Indian +indicate +indication +individual +industrial +industry +infant +infection +inflation +influence +inform +information +ingredient +initial +initially +initiative +injury +inner +innocent +inquiry +inside +insight +insist +inspire +install +instance +instead +institution +institutional +instruction +instructor +instrument +insurance +intellectual +intelligence +intend +intense +intensity +intention +interaction +interest +interested +interesting +internal +international +Internet +interpret +interpretation +intervention +interview +into +introduce +introduction +invasion +invest +investigate +investigation +investigator +investment +investor +invite +involve +involved +involvement +Iraqi +Irish +iron +Islamic +island +Israeli +issue +it +Italian +item +its +itself +jacket +jail +Japanese +jet +Jew +Jewish +job +join +joint +joke +journal +journalist +journey +joy +judge +judgment +juice +jump +junior +jury +just +justice +justify +keep +key +kick +kid +kill +killer +killing +kind +king +kiss +kitchen +knee +knife +knock +know +knowledge +lab +label +labor +laboratory +lack +lady +lake +land +landscape +language +lap +large +largely +last +late +later +Latin +latter +laugh +launch +law +lawn +lawsuit +lawyer +lay +layer +lead +leader +leadership +leading +leaf +league +lean +learn +learning +least +leather +leave +left +leg +legacy +legal +legend +legislation +legitimate +lemon +length +less +lesson +let +letter +level +liberal +library +license +lie +life +lifestyle +lifetime +lift +light +like +likely +limit +limitation +limited +line +link +lip +list +listen +literally +literary +literature +little +live +living +load +loan +local +locate +location +lock +long +long-term +look +loose +lose +loss +lost +lot +lots +loud +love +lovely +lover +low +lower +luck +lucky +lunch +lung +machine +mad +magazine +mail +main +mainly +maintain +maintenance +major +majority +make +maker +makeup +male +mall +man +manage +management +manager +manner +manufacturer +manufacturing +many +map +margin +mark +market +marketing +marriage +married +marry +mask +mass +massive +master +match +material +math +matter +may +maybe +mayor +me +meal +mean +meaning +meanwhile +measure +measurement +meat +mechanism +media +medical +medication +medicine +medium +meet +meeting +member +membership +memory +mental +mention +menu +mere +merely +mess +message +metal +meter +method +Mexican +middle +might +military +milk +million +mind +mine +minister +minor +minority +minute +miracle +mirror +miss +missile +mission +mistake +mix +mixture +mm-hmm +mode +model +moderate +modern +modest +mom +moment +money +monitor +month +mood +moon +moral +more +moreover +morning +mortgage +most +mostly +mother +motion +motivation +motor +mount +mountain +mouse +mouth +move +movement +movie +Mr +Mrs +Ms +much +multiple +murder +muscle +museum +music +musical +musician +Muslim +must +mutual +my +myself +mystery +myth +naked +name +narrative +narrow +nation +national +native +natural +naturally +nature +near +nearby +nearly +necessarily +necessary +neck +need +negative +negotiate +negotiation +neighbor +neighborhood +neither +nerve +nervous +net +network +never +nevertheless +new +newly +news +newspaper +next +nice +night +nine +no +nobody +nod +noise +nomination +none +nonetheless +nor +normal +normally +north +northern +nose +not +note +nothing +notice +notion +novel +now +nowhere +n't +nuclear +number +numerous +nurse +nut +object +objective +obligation +observation +observe +observer +obtain +obvious +obviously +occasion +occasionally +occupation +occupy +occur +ocean +odd +odds +of +off +offense +offensive +offer +office +officer +official +often +oh +oil +ok +okay +old +Olympic +on +once +one +ongoing +onion +online +only +onto +open +opening +operate +operating +operation +operator +opinion +opponent +opportunity +oppose +opposite +opposition +option +or +orange +order +ordinary +organic +organization +organize +orientation +origin +original +originally +other +others +otherwise +ought +our +ourselves +out +outcome +outside +oven +over +overall +overcome +overlook +owe +own +owner +pace +pack +package +page +pain +painful +paint +painter +painting +pair +pale +Palestinian +palm +pan +panel +pant +paper +parent +park +parking +part +participant +participate +participation +particular +particularly +partly +partner +partnership +party +pass +passage +passenger +passion +past +patch +path +patient +pattern +pause +pay +payment +PC +peace +peak +peer +penalty +people +pepper +per +perceive +percentage +perception +perfect +perfectly +perform +performance +perhaps +period +permanent +permission +permit +person +personal +personality +personally +personnel +perspective +persuade +pet +phase +phenomenon +philosophy +phone +photo +photograph +photographer +phrase +physical +physically +physician +piano +pick +picture +pie +piece +pile +pilot +pine +pink +pipe +pitch +place +plan +plane +planet +planning +plant +plastic +plate +platform +play +player +please +pleasure +plenty +plot +plus +PM +pocket +poem +poet +poetry +point +pole +police +policy +political +politically +politician +politics +poll +pollution +pool +poor +pop +popular +population +porch +port +portion +portrait +portray +pose +position +positive +possess +possibility +possible +possibly +post +pot +potato +potential +potentially +pound +pour +poverty +powder +power +powerful +practical +practice +pray +prayer +precisely +predict +prefer +preference +pregnancy +pregnant +preparation +prepare +prescription +presence +present +presentation +preserve +president +presidential +press +pressure +pretend +pretty +prevent +previous +previously +price +pride +priest +primarily +primary +prime +principal +principle +print +prior +priority +prison +prisoner +privacy +private +probably +problem +procedure +proceed +process +produce +producer +product +production +profession +professional +professor +profile +profit +program +progress +project +prominent +promise +promote +prompt +proof +proper +properly +property +proportion +proposal +propose +proposed +prosecutor +prospect +protect +protection +protein +protest +proud +prove +provide +provider +province +provision +psychological +psychologist +psychology +public +publication +publicly +publish +publisher +pull +punishment +purchase +pure +purpose +pursue +push +put +qualify +quality +quarter +quarterback +question +quick +quickly +quiet +quietly +quit +quite +quote +race +racial +radical +radio +rail +rain +raise +range +rank +rapid +rapidly +rare +rarely +rate +rather +rating +ratio +raw +reach +react +reaction +read +reader +reading +ready +real +reality +realize +really +reason +reasonable +recall +receive +recent +recently +recipe +recognition +recognize +recommend +recommendation +record +recording +recover +recovery +recruit +red +reduce +reduction +refer +reference +reflect +reflection +reform +refugee +refuse +regard +regarding +regardless +regime +region +regional +register +regular +regularly +regulate +regulation +reinforce +reject +relate +relation +relationship +relative +relatively +relax +release +relevant +relief +religion +religious +rely +remain +remaining +remarkable +remember +remind +remote +remove +repeat +repeatedly +replace +reply +report +reporter +represent +representation +representative +Republican +reputation +request +require +requirement +research +researcher +resemble +reservation +resident +resist +resistance +resolution +resolve +resort +resource +respect +respond +respondent +response +responsibility +responsible +rest +restaurant +restore +restriction +result +retain +retire +retirement +return +reveal +revenue +review +revolution +rhythm +rice +rich +rid +ride +rifle +right +ring +rise +risk +river +road +rock +role +roll +romantic +roof +room +root +rope +rose +rough +roughly +round +route +routine +row +rub +rule +run +running +rural +rush +Russian +sacred +sad +safe +safety +sake +salad +salary +sale +sales +salt +same +sample +sanction +sand +satellite +satisfaction +satisfy +sauce +save +saving +say +scale +scandal +scared +scenario +scene +schedule +scheme +scholar +scholarship +school +science +scientific +scientist +scope +score +scream +screen +script +sea +search +season +seat +second +secret +secretary +section +sector +secure +security +see +seed +seek +seem +segment +seize +select +selection +self +sell +Senate +senator +send +senior +sense +sensitive +sentence +separate +sequence +series +serious +seriously +serve +service +session +set +setting +settle +settlement +seven +several +severe +sex +sexual +shade +shadow +shake +shall +shape +share +sharp +she +sheet +shelf +shell +shelter +shift +shine +ship +shirt +shit +shock +shoe +shoot +shooting +shop +shopping +shore +short +shortly +shot +should +shoulder +shout +show +shower +shrug +shut +sick +side +sigh +sight +sign +signal +significance +significant +significantly +silence +silent +silver +similar +similarly +simple +simply +sin +since +sing +singer +single +sink +sir +sister +sit +site +situation +six +size +ski +skill +skin +sky +slave +sleep +slice +slide +slight +slightly +slip +slow +slowly +small +smart +smell +smile +smoke +smooth +snap +snow +so +so-called +soccer +social +society +soft +software +soil +solar +soldier +solid +solution +solve +some +somebody +somehow +someone +something +sometimes +somewhat +somewhere +son +song +soon +sophisticated +sorry +sort +soul +sound +soup +source +south +southern +Soviet +space +Spanish +speak +speaker +special +specialist +species +specific +specifically +speech +speed +spend +spending +spin +spirit +spiritual +split +spokesman +sport +spot +spread +spring +square +squeeze +stability +stable +staff +stage +stair +stake +stand +standard +standing +star +stare +start +state +statement +station +statistics +status +stay +steady +steal +steel +step +stick +still +stir +stock +stomach +stone +stop +storage +store +storm +story +straight +strange +stranger +strategic +strategy +stream +street +strength +strengthen +stress +stretch +strike +string +strip +stroke +strong +strongly +structure +struggle +student +studio +study +stuff +stupid +style +subject +submit +subsequent +substance +substantial +succeed +success +successful +successfully +such +sudden +suddenly +sue +suffer +sufficient +sugar +suggest +suggestion +suicide +suit +summer +summit +sun +super +supply +support +supporter +suppose +supposed +Supreme +sure +surely +surface +surgery +surprise +surprised +surprising +surprisingly +surround +survey +survival +survive +survivor +suspect +sustain +swear +sweep +sweet +swim +swing +switch +symbol +symptom +system +table +tablespoon +tactic +tail +take +tale +talent +talk +tall +tank +tap +tape +target +task +taste +tax +taxpayer +tea +teach +teacher +teaching +team +tear +teaspoon +technical +technique +technology +teen +teenager +telephone +telescope +television +tell +temperature +temporary +ten +tend +tendency +tennis +tension +tent +term +terms +terrible +territory +terror +terrorism +terrorist +test +testify +testimony +testing +text +than +thank +thanks +that +the +theater +their +them +theme +themselves +then +theory +therapy +there +therefore +these +they +thick +thin +thing +think +thinking +third +thirty +this +those +though +thought +thousand +threat +threaten +three +throat +through +throughout +throw +thus +ticket +tie +tight +time +tiny +tip +tire +tired +tissue +title +to +tobacco +today +toe +together +tomato +tomorrow +tone +tongue +tonight +too +tool +tooth +top +topic +toss +total +totally +touch +tough +tour +tourist +tournament +toward +towards +tower +town +toy +trace +track +trade +tradition +traditional +traffic +tragedy +trail +train +training +transfer +transform +transformation +transition +translate +transportation +travel +treat +treatment +treaty +tree +tremendous +trend +trial +tribe +trick +trip +troop +trouble +truck +true +truly +trust +truth +try +tube +tunnel +turn +TV +twelve +twenty +twice +twin +two +type +typical +typically +ugly +ultimate +ultimately +unable +uncle +under +undergo +understand +understanding +unfortunately +uniform +union +unique +unit +United +universal +universe +university +unknown +unless +unlike +unlikely +until +unusual +up +upon +upper +urban +urge +us +use +used +useful +user +usual +usually +utility +vacation +valley +valuable +value +variable +variation +variety +various +vary +vast +vegetable +vehicle +venture +version +versus +very +vessel +veteran +via +victim +victory +video +view +viewer +village +violate +violation +violence +violent +virtually +virtue +virus +visible +vision +visit +visitor +visual +vital +voice +volume +volunteer +vote +voter +vs +vulnerable +wage +wait +wake +walk +wall +wander +want +war +warm +warn +warning +wash +waste +watch +water +wave +way +we +weak +wealth +wealthy +weapon +wear +weather +wedding +week +weekend +weekly +weigh +weight +welcome +welfare +well +west +western +wet +what +whatever +wheel +when +whenever +where +whereas +whether +which +while +whisper +white +who +whole +whom +whose +why +wide +widely +widespread +wife +wild +will +willing +win +wind +window +wine +wing +winner +winter +wipe +wire +wisdom +wise +wish +with +withdraw +within +without +witness +woman +wonder +wonderful +wood +wooden +word +work +worker +working +works +workshop +world +worried +worry +worth +would +wound +wrap +write +writer +writing +wrong +yard +yeah +year +yell +yellow +yes +yesterday +yet +yield +you +young +your +yours +yourself +youth +zone