1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use std::collections::HashMap;

use crate::{
    colors::ColorProvider,
    words::{FontProvider, FontSizeProvider, Word, WordsProvider},
};

pub struct DefaultWordProvider {
    words: Vec<Word>,
    cur_word: usize,
}

impl WordsProvider for DefaultWordProvider {
    fn get_next_word(&mut self) -> Option<Word> {
        if self.cur_word >= self.words.len() - 1 {
            return None;
        }

        self.cur_word += 1;

        Some(self.words[self.cur_word].clone())
    }
}

impl DefaultWordProvider {
    pub fn new<FSP, CP>(
        text: &str,
        font_size_provider: FSP,
        color_provider: &mut CP,
        fonts_provider: &FontProvider,
    ) -> DefaultWordProvider
    where
        FSP: FontSizeProvider,
        CP: ColorProvider,
    {
        let words: Vec<String> = text
            .replace(['.', ',', ';'], "")
            .split(' ')
            .map(|w| w.to_lowercase())
            .filter(|w| w.len() > 3)
            .collect();

        // TODO - filter

        let mut buffer: HashMap<String, Word> = HashMap::new();

        for text in words {
            if buffer.contains_key(&text) {
                let mut w = buffer.get(&text).unwrap().clone();
                w.count += 1;
                w.size = font_size_provider.get_font_size(&w);

                buffer.remove(&text);
                buffer.insert(text, w);
            } else {
                let mut word = Word::new(
                    &text,
                    crate::geometry::Orientation::random(),
                    color_provider.random_color(),
                    &fonts_provider.random_font_name(),
                    0,
                );

                word.size = font_size_provider.get_font_size(&word);

                buffer.insert(text, word);
            }
        }

        // Insert the biggest words first
        let mut list: Vec<Word> = buffer.into_values().collect();
        list.sort_by(|a, b| a.size.cmp(&b.size));
        list.reverse();

        DefaultWordProvider {
            words: list,
            cur_word: 0,
        }
    }
}