1//! Small builders for the documents the laws merge. 2 3use std::collections::BTreeSet; 4 5use whiskers_core::{ChatState, Fact, Household, Kind, MemorySnapshot}; 6 7pub fn fact(gid: &str, text: &str) -> Fact { 8 Fact { 9 id: 0, 10 text: text.to_owned(), 11 learned_at_ms: 5, 12 kind: Kind::Other, 13 who: vec![], 14 place: None, 15 when: None, 16 pictures: vec![], 17 embedding: vec![], 18 gid: gid.to_owned(), 19 visibility: whiskers_core::Visibility::default(), 20 icon: None, 21 } 22} 23 24pub fn with_embedding(mut f: Fact, embedding: &[f32]) -> Fact { 25 f.embedding = embedding.to_vec(); 26 f 27} 28 29pub fn snapshot(facts: Vec<Fact>, forgotten: &[&str]) -> MemorySnapshot { 30 MemorySnapshot { facts, forgotten: forgotten.iter().map(|g| (*g).to_owned()).collect() } 31} 32 33/// A fact by identity: its gid, its words and its embedding (as bits, so it compares exactly). 34pub type FactGist = (String, String, Vec<u32>); 35 36/// What a snapshot says once the hub's own numbering and ordering are set aside: the facts by 37/// identity (with their words and whether they carry an embedding) and the forgotten identities. 38pub fn gist(s: &MemorySnapshot) -> (BTreeSet<FactGist>, BTreeSet<String>) { 39 ( 40 s.facts.iter().map(|f| (f.gid.clone(), f.text.clone(), f.embedding.iter().map(|x| x.to_bits()).collect())).collect(), 41 s.forgotten.iter().cloned().collect(), 42 ) 43} 44 45/// A household document, built through its JSON (its fields are private to the core, as they should 46/// be): the choices made at `config_ms` with a thinking allowance and a voice allowance, and the time 47/// each named device has spent on `day`. 48pub fn household(config_ms: u64, tokens: u64, voice_chars: u32, day: u32, used_ms: &[(&str, u64)]) -> Household { 49 let used: serde_json::Map<String, serde_json::Value> = used_ms.iter().map(|(d, ms)| ((*d).to_owned(), serde_json::json!(ms))).collect(); 50 serde_json::from_value(serde_json::json!({ 51 "config": { 52 "limits": { "daily_minutes": null, "quiet": null }, 53 "tokens": { "per_window": tokens, "window_hours": 5 }, 54 "keep_mic_open": false, 55 "voice_daily_chars": voice_chars, 56 "pin": null, 57 "child": null 58 }, 59 "config_updated_ms": config_ms, 60 "today": { "day": day, "used_ms": used, "extra_minutes": {} } 61 })) 62 .expect("a household document") 63} 64 65pub fn chat(version: u64, last_active_ms: u64, summary: &str) -> ChatState { 66 ChatState { summary: summary.to_owned(), turns: vec![], last_active_ms, version } 67} 68 69/// Every order of `items`. 70pub fn permutations<T: Clone>(items: &[T]) -> Vec<Vec<T>> { 71 if items.len() <= 1 { 72 return vec![items.to_vec()]; 73 } 74 let mut out = Vec::new(); 75 for i in 0..items.len() { 76 let mut rest = items.to_vec(); 77 let head = rest.remove(i); 78 for mut tail in permutations(&rest) { 79 tail.insert(0, head.clone()); 80 out.push(tail); 81 } 82 } 83 out 84}