mod words;
use rand::Rng;
pub use words::{gen_word, WordType};
fn string_cleanup(mut s: String) -> String {
if let Some(c) = s.get_mut(0..1) {
let me = unsafe { c.as_bytes_mut() };
me[0].make_ascii_uppercase()
};
let len = s.len().max(1);
if let Some(x) = s.get_mut(len - 1..len) {
let me = unsafe { x.as_bytes_mut() };
me[0] = b'.'
};
s
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Structure {
AdjectivesNounVerbAdverbs,
AdjectivesNounAdverbsVerb,
AdjectivesNounVerbAdverbsAdjectivesNoun,
AdjectivesNounVerbAdverbsNounAdjectives,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct SentenceConfig {
adjectives: u16, adverbs: u16, structure: Structure, plural: bool, on_adjectives: u16, on_plural: bool, }
pub struct SentenceConfigBuilder {
adjectives: u16, adverbs: u16, structure: Structure, plural: bool, on_adjectives: u16, on_plural: bool, }
impl SentenceConfigBuilder {
pub fn new() -> Self {
SentenceConfigBuilder::default()
}
pub fn random() -> Self {
use Structure::*;
let mut rng = rand::thread_rng();
SentenceConfigBuilder {
adjectives: rng.gen_range(1..=3),
adverbs: rng.gen_range(0..=2),
structure: {
let options = [
AdjectivesNounVerbAdverbs,
AdjectivesNounAdverbsVerb,
AdjectivesNounVerbAdverbsAdjectivesNoun,
AdjectivesNounVerbAdverbsNounAdjectives,
];
options[rng.gen_range(0..options.len())]
},
plural: rng.gen_range(0..=1) == 1,
on_adjectives: rng.gen_range(1..=3),
on_plural: rng.gen_range(0..=1) == 1,
}
}
pub fn adjectives(mut self, n: u16) -> Self {
self.adjectives = n;
self
}
pub fn adverbs(mut self, n: u16) -> Self {
self.adverbs = n;
self
}
pub fn structure(mut self, n: Structure) -> Self {
self.structure = n;
self
}
pub fn plural(mut self, n: bool) -> Self {
self.plural = n;
self
}
pub fn on_adjectives(mut self, n: u16) -> Self {
self.on_adjectives = n;
self
}
pub fn on_plural(mut self, n: bool) -> Self {
self.on_plural = n;
self
}
pub fn build(self) -> SentenceConfig {
let Self {
adjectives,
adverbs,
structure,
plural,
on_adjectives,
on_plural,
} = self;
SentenceConfig {
adjectives,
adverbs,
structure,
plural,
on_adjectives,
on_plural,
}
}
}
impl Default for SentenceConfigBuilder {
fn default() -> Self {
SentenceConfigBuilder {
adjectives: 2,
adverbs: 1,
structure: Structure::AdjectivesNounVerbAdverbs,
plural: true,
on_adjectives: 2,
on_plural: false,
}
}
}
pub fn gen_sentence(config: SentenceConfig) -> String {
let tokens = gen_structure(config);
let mut sentence = String::with_capacity((tokens.len() + 1) * 5);
for token in tokens {
sentence.push_str(&gen_word(token));
sentence.push(' ');
}
sentence = string_cleanup(sentence);
sentence
}
pub fn gen_structure(config: SentenceConfig) -> Vec<WordType> {
use Structure::*;
let words = (config.adverbs + config.adjectives + config.on_adjectives) as usize + 3;
let mut tokens: Vec<WordType> = Vec::with_capacity(words);
if !config.plural || rand::thread_rng().gen_range(0..=1) == 1 {
tokens.push(WordType::The)
}
tokens.append(&mut WordType::adjective_mul(config.adjectives));
tokens.push(if config.plural {
WordType::PluralNoun
} else {
WordType::SingularNoun
});
match config.structure {
AdjectivesNounVerbAdverbs => {
tokens.push(if config.plural {
WordType::Verb
} else {
WordType::NoSingularVerb
}); for _ in 0..config.adverbs {
tokens.push(WordType::Adverb)
} }
AdjectivesNounAdverbsVerb => {
for _ in 0..config.adverbs {
tokens.push(WordType::Adverb)
} tokens.push(if config.plural {
WordType::Verb
} else {
WordType::NoSingularVerb
}); }
AdjectivesNounVerbAdverbsAdjectivesNoun => {
tokens.push(if config.plural {
WordType::Verb
} else {
WordType::NoSingularVerb
}); for _ in 0..config.adverbs {
tokens.push(WordType::Adverb)
} if !config.on_plural || rand::thread_rng().gen_range(0..=1) == 1 {
tokens.push(WordType::The)
}
tokens.append(&mut WordType::adjective_mul(config.on_adjectives));
tokens.push(if config.plural {
WordType::PluralNoun
} else {
WordType::SingularNoun
});
}
AdjectivesNounVerbAdverbsNounAdjectives => {
for _ in 0..config.adverbs {
tokens.push(WordType::Adverb)
} tokens.push(if config.plural {
WordType::Verb
} else {
WordType::NoSingularVerb
}); if !config.on_plural || rand::thread_rng().gen_range(0..=1) == 1 {
tokens.push(WordType::The)
}
tokens.append(&mut WordType::adjective_mul(config.on_adjectives));
tokens.push(if config.plural {
WordType::PluralNoun
} else {
WordType::SingularNoun
});
}
};
tokens
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn show_result() {
let sc = SentenceConfigBuilder::default().build();
let sentence = gen_sentence(sc);
assert!(sentence.chars().next().unwrap().is_uppercase());
assert_eq!(sentence.chars().last().unwrap(), '.');
println!("{}", sentence);
}
}