use rand::thread_rng;
use crate::entropy::Entropy;
use crate::prelude::*;
use crate::probability::Probability;
#[derive(Debug)]
pub struct FixedWordSetProvider<P>
where
P: WordProvider,
{
provider: P,
words: usize,
}
impl<P> FixedWordSetProvider<P>
where
P: WordProvider,
{
pub fn new(provider: P, words: usize) -> Self {
if words == 0 {
panic!("cannot construct FixedWordSetProvider that obtains zero words");
}
Self { provider, words }
}
}
impl<P> HasEntropy for FixedWordSetProvider<P>
where
P: WordProvider,
{
fn entropy(&self) -> Entropy {
self.provider.entropy() * self.words as f64
}
}
impl<P> WordSetProvider for FixedWordSetProvider<P>
where
P: WordProvider,
{
fn words(&self) -> Vec<String> {
let mut res: Vec<String> = vec![];
for _ in 0..self.words {
res.push(self.provider.word());
}
res
}
}
#[derive(Debug)]
pub struct WordCapitalizer {
first: Probability,
all: Probability,
}
impl WordCapitalizer {
pub fn new(first: Probability, all: Probability) -> Self {
Self { first, all }
}
}
impl HasEntropy for WordCapitalizer {
fn entropy(&self) -> Entropy {
if let Probability::Always = self.all {
Entropy::zero()
} else {
self.first.entropy() + self.all.entropy()
}
}
}
impl WordStyler for WordCapitalizer {
fn style_word(&self, mut word: String) -> String {
if word.is_empty() {
return word;
}
let mut rng = thread_rng();
if self.first.gen_bool(&mut rng) {
let first = word
.chars()
.map(|c| c.to_uppercase().to_string())
.next()
.unwrap_or_else(String::new);
let rest: String = word.chars().skip(1).collect();
word = first + &rest;
}
if self.all.gen_bool(&mut rng) {
word = word.to_uppercase();
}
word
}
}