const DROLLERIES: &[&[&str]] = &[
&[" (\\_/)", "(='.'=)", "(\")_(\")"],
&[" /\\_/\\", "( o.o )", " > ^ <"],
&["{O,o}", "|)``)", "-\"-\"-"],
&["><(((°>"],
&["<:3 )~~"],
&[" _", " (@)__", "_(___)>"],
&["(o>", "//\\", "V_/_"],
&[" ❧", " |", "~|~", " |"],
];
fn count() -> usize {
DROLLERIES.len()
}
pub(crate) fn max_width() -> usize {
DROLLERIES
.iter()
.flat_map(|d| d.iter())
.map(|l| crate::illuminate::display_width(l))
.max()
.unwrap_or(0)
}
fn splitmix(seed: u64, n: u64) -> u64 {
let mut z = seed.wrapping_add(n.wrapping_mul(0x9E37_79B9_7F4A_7C15));
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
}
pub(crate) fn pick(seed: u64, n: u64) -> Vec<String> {
let i = (splitmix(seed, n) % count() as u64) as usize;
DROLLERIES[i].iter().map(|s| s.to_string()).collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn repertoire_is_non_empty() {
assert!(count() > 0);
assert!(max_width() > 0);
}
#[test]
fn pick_is_deterministic() {
assert_eq!(pick(0, 0), pick(0, 0));
assert_eq!(pick(42, 7), pick(42, 7));
}
#[test]
fn pick_always_returns_a_figure() {
for n in 0..100u64 {
assert!(!pick(3, n).is_empty());
}
}
}