The groups a memory's picture is looked for in first, when there are too many pictures to put in one question.
A group is a category of the allowlist (the pack's own README names them), holding the admitted icons that depict a thing. Nothing here is invented: a category appears when the allowlist has an admitted picture of a thing under it, and its members are exactly those pictures.
7use std::fmt;
9use crate::{IconId, Verdict, allowlist};
What each category holds, in words Jev can choose between. A category the allowlist gains later has no entry until somebody writes one; it is still a group, described by its own name (a test lists the ones without).
13const DESCRIPTIONS: &[(&str, &str)] = &[ 14 ("Animals", "animals, pets and other creatures"), 15 ("Dinosaurs", "dinosaurs"), 16 ("Fruits, Vegetables and other Ingredients", "fruit, vegetables and other things to cook with or snack on"), 17 ("Food and Drinks", "meals, sweets, snacks, desserts and drinks"), 18 ("Objects", "everyday things: vehicles, buildings, toys, instruments, devices, weather, holidays and gifts"), 19 ("Logos", "the logos of apps, websites and companies"), 20 ("Games", "characters from video games"), 21 ("Pokemons", "Pokemon characters"), 22 ("Memes", "internet meme characters"), 23];
How many of a group's pictures its description names.
26const EXAMPLES: usize = 6;
A group of pictures: one category of the allowlist that has an admitted picture of a thing.
32impl IconGroup {
The group called name (a category's name), if it has a picture to offer.
Every group, in the order of the allowlist.
The group an icon belongs to, if it depicts a thing.
The category's name: what Jev is offered as the option.
The group's pictures, in the order of the allowlist.
What Jev is told the group holds: the description, then a few of its pictures by name.
65 pub fn describe(&self) -> String { 66 let what = DESCRIPTIONS.iter().find(|(n, _)| *n == self.0).map_or_else(|| self.0.to_lowercase(), |(_, d)| (*d).to_owned()); 67 let members = self.members(); 68 let examples: Vec<String> = members.iter().take(EXAMPLES).map(|m| m.as_str().replace('-', " ")).collect(); 69 format!("pictures of {what}, {} in all, such as {}", members.len(), examples.join(", ")) 70 }
The groups that have no description of their own yet (empty when every category is described).
78impl fmt::Display for IconGroup { 79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 80 f.write_str(self.0) 81 } 82} 83 84#[cfg(test)] 85mod tests { 86 use super::*; 87 88 #[test] 89 fn the_groups_are_the_categories_with_a_picture_of_a_thing_and_hold_exactly_those_pictures() { 90 let groups = IconGroup::all(); 91 assert!(!groups.iter().any(|g| g.name() == "UI"), "interface icons are no group"); 92 let total: usize = groups.iter().map(|g| g.members().len()).sum(); 93 assert_eq!(total, IconId::all().filter(IconId::depicts_a_thing).count(), "every picture of a thing is in exactly one group"); 94 for g in &groups { 95 assert!(!g.members().is_empty(), "{g}"); 96 assert!(g.members().iter().all(|m| IconGroup::of(m) == Some(*g))); 97 assert_eq!(IconGroup::new(g.name()), Some(*g)); 98 } 99 assert_eq!(IconGroup::new("UI"), None); 100 assert_eq!(IconGroup::of(&IconId::new("cat").unwrap()).unwrap().name(), "Animals"); 101 assert_eq!(IconGroup::of(&IconId::new("arrow-up").unwrap()), None); 102 } 103 104 #[test] 105 fn every_group_is_described() { 106 assert!(IconGroup::undescribed().is_empty(), "describe: {:?}", IconGroup::undescribed()); 107 let d = IconGroup::new("Dinosaurs").unwrap().describe(); 108 assert!(d.contains("dinosaurs") && d.contains("4 in all") && d.contains("t rex"), "{d}"); 109 } 110}