whiskers.git / crates / whiskers-art / src / character.rs

Who there is: the three drawn characters (the grey cat, the ginger cat and the bunny) and the ten of the pack, as one closed list. The household's document, the chooser, the app and the site all read this list; none keeps its own. A character's scene in a mood is scene: drawn from this crate's data, or, for a pack character, a picture's place with the same shadow, body motion, mouth and weather round it.

6use whiskers_pet::Mood;
8use crate::node::Node;
9use crate::pack::{PACK, Pack};
10use crate::scene::{Mouth, Sleeps, assemble};

One of the drawn characters.

13#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
14pub enum Drawn {
15    Grey,
16    Ginger,
17    Bunny,
18}
20impl Drawn {
21    pub const ALL: [Drawn; 3] = [Drawn::Grey, Drawn::Ginger, Drawn::Bunny];
22
23    pub fn id(self) -> &'static str {
24        match self {
25            Drawn::Grey => "grey-cat",
26            Drawn::Ginger => "ginger-cat",
27            Drawn::Bunny => "bunny",
28        }
29    }
30
31    pub fn label(self) -> &'static str {
32        match self {
33            Drawn::Grey => "Grey",
34            Drawn::Ginger => "Ginger",
35            Drawn::Bunny => "Bunny",
36        }
37    }
38
39    pub fn kind(self) -> &'static str {
40        match self {
41            Drawn::Grey => "grey cat",
42            Drawn::Ginger => "ginger cat",
43            Drawn::Bunny => "rabbit",
44        }
45    }
46}

Who Whiskers can be.

49#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
50pub enum Character {
51    Drawn(Drawn),
52    Pack(&'static Pack),
53}
55impl PartialEq for Pack {
56    fn eq(&self, other: &Pack) -> bool {
57        self.id == other.id
58    }
59}
60impl Eq for Pack {}
61impl std::hash::Hash for Pack {
62    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
63        self.id.hash(state);
64    }
65}
66
67impl Character {

Every character, in the order the chooser steps through them: the drawn ones, then the pack.

69    pub fn all() -> Vec<Character> {
70        Drawn::ALL.into_iter().map(Character::Drawn).chain(PACK.iter().map(Character::Pack)).collect()
71    }

The id the household's document stores, which the page's signals use too.

74    pub fn id(self) -> &'static str {
75        match self {
76            Character::Drawn(d) => d.id(),
77            Character::Pack(p) => p.id,
78        }
79    }

The word on the picker's button.

82    pub fn label(self) -> &'static str {
83        match self {
84            Character::Drawn(d) => d.label(),
85            Character::Pack(p) => p.label,
86        }
87    }

What it is, for the picture's description.

90    pub fn kind(self) -> &'static str {
91        match self {
92            Character::Drawn(d) => d.kind(),
93            Character::Pack(p) => p.kind,
94        }
95    }

The character called id, or none.

98    pub fn parse(id: &str) -> Option<Character> {
99        Character::all().into_iter().find(|c| c.id() == id)
100    }

The character in mood, whole: shadow, body, mouth and weather. mouth matters only while speaking.

103    pub fn scene(self, mood: Mood, mouth: Option<Mouth>) -> Vec<Node> {
104        match self {
105            Character::Drawn(Drawn::Grey) => crate::scene::scene(mood, mouth),
106            Character::Drawn(Drawn::Ginger) => {
107                let body = if mood == Mood::Sleeping { crate::ginger::sleeping() } else { crate::ginger::standing(mood, mouth) };
108                assemble(mood, mouth, body, Sleeps::Flat)
109            }
110            Character::Drawn(Drawn::Bunny) => crate::scene::bunny_scene(mood, mouth),
111            Character::Pack(p) => crate::scene::pack_scene(p, mood, mouth),
112        }
113    }
114}
116#[cfg(test)]
117mod tests {
118    use super::*;
119
120    #[test]
121    fn there_are_thirteen_with_their_own_ids_and_the_drawn_ones_come_first() {
122        let all = Character::all();
123        assert_eq!(all.len(), 13);
124        let mut ids: Vec<_> = all.iter().map(|c| c.id()).collect();
125        assert_eq!(&ids[..3], ["grey-cat", "ginger-cat", "bunny"]);
126        ids.sort();
127        ids.dedup();
128        assert_eq!(ids.len(), 13);
129        for c in all {
130            assert_eq!(Character::parse(c.id()), Some(c));
131        }
132        assert_eq!(Character::parse("grey"), None);
133    }
134}