1use crate::{q_hash, NQuin};
18
19pub const T_CONTEXT: u64 = q_hash("urn:qualia:context:temporal");
21pub const AGENT_CONTEXT: u64 = q_hash("urn:qualia:context:agent");
22
23pub const P_GENERATED_AT: u64 = q_hash("http://www.w3.org/ns/prov#generatedAtTime");
25pub const P_STARTED_AT: u64 = q_hash("http://www.w3.org/ns/prov#startedAtTime");
26pub const P_ENDED_AT: u64 = q_hash("http://www.w3.org/ns/prov#endedAtTime");
27pub const P_WAS_ATTRIBUTED_TO: u64 = q_hash("http://www.w3.org/ns/prov#wasAttributedTo");
28pub const P_WAS_GENERATED_BY: u64 = q_hash("http://www.w3.org/ns/prov#wasGeneratedBy");
29pub const P_WAS_INVALIDATED_BY: u64 = q_hash("http://www.w3.org/ns/prov#wasInvalidatedBy");
30pub const P_INVALIDATED_AT: u64 = q_hash("http://www.w3.org/ns/prov#invalidatedAtTime");
31pub const P_HAD_PRIMARY_SOURCE: u64 = q_hash("http://www.w3.org/ns/prov#hadPrimarySource");
32
33pub const P_DC_VALID: u64 = q_hash("http://purl.org/dc/terms/valid");
35pub const P_DC_CREATOR: u64 = q_hash("http://purl.org/dc/terms/creator");
36pub const P_DC_DATE: u64 = q_hash("http://purl.org/dc/terms/date");
37
38pub const P_RDF_TYPE: u64 = q_hash("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
40
41pub const C_COG_AGENT: u64 = q_hash("https://www.w3.org/community/cogai/ont#Agent");
43pub const C_COG_GOAL: u64 = q_hash("https://www.w3.org/community/cogai/ont#Goal");
44pub const C_COG_BELIEF: u64 = q_hash("https://www.w3.org/community/cogai/ont#Belief");
45pub const C_COG_PLAN: u64 = q_hash("https://www.w3.org/community/cogai/ont#Plan");
46pub const P_COG_HOLDS_BELIEF: u64 = q_hash("https://www.w3.org/community/cogai/ont#holdsBelief");
47pub const P_COG_HAS_GOAL: u64 = q_hash("https://www.w3.org/community/cogai/ont#hasGoal");
48pub const P_COG_HAS_PLAN: u64 = q_hash("https://www.w3.org/community/cogai/ont#hasPlan");
49
50pub const P_Q42_INFERENCE_AUTHORIZED_BY: u64 =
52 q_hash("urn:qualia:ontology:rights:inferenceAuthorizedBy");
53pub const P_Q42_PROVENANCE_CITATIONS: u64 =
54 q_hash("urn:qualia:ontology:rights:provenanceCitations");
55
56pub fn assert_temporal(
68 entity: u64,
69 t_valid_start: u64,
70 t_valid_end: Option<u64>,
71 t_assert: u64,
72 author_did: Option<u64>,
73) -> Vec<NQuin> {
74 let mut quins = Vec::with_capacity(4);
75 quins.push(make_temporal(entity, P_GENERATED_AT, t_assert));
76 quins.push(make_temporal(entity, P_STARTED_AT, t_valid_start));
77 if let Some(end) = t_valid_end {
78 quins.push(make_temporal(entity, P_ENDED_AT, end));
79 }
80 if let Some(did) = author_did {
81 quins.push(make_temporal(entity, P_WAS_ATTRIBUTED_TO, did));
82 }
83 quins
84}
85
86pub fn invalidate_entity(entity: u64, agent_did: u64, t_invalidate: u64) -> [NQuin; 2] {
88 [
89 make_temporal(entity, P_WAS_INVALIDATED_BY, agent_did),
90 make_temporal(entity, P_INVALIDATED_AT, t_invalidate),
91 ]
92}
93
94pub fn register_agent(did_hash: u64, ts: u64) -> NQuin {
98 NQuin {
99 subject: did_hash,
100 predicate: P_RDF_TYPE,
101 object: C_COG_AGENT,
102 context: AGENT_CONTEXT,
103 metadata: ts & 0xFFFF_FFFF, parity: 0,
105 }
106}
107
108pub fn write_goal(agent_did: u64, goal_hash: u64, ts: u64) -> [NQuin; 2] {
110 [
111 NQuin {
112 subject: goal_hash,
113 predicate: P_RDF_TYPE,
114 object: C_COG_GOAL,
115 context: AGENT_CONTEXT,
116 metadata: ts & 0xFFFF_FFFF,
117 parity: 0,
118 },
119 NQuin {
120 subject: agent_did,
121 predicate: P_COG_HAS_GOAL,
122 object: goal_hash,
123 context: AGENT_CONTEXT,
124 metadata: ts & 0xFFFF_FFFF,
125 parity: 0,
126 },
127 ]
128}
129
130pub fn write_belief(agent_did: u64, belief_hash: u64, t_assert: u64, t_valid: u64) -> [NQuin; 4] {
134 [
135 NQuin {
136 subject: belief_hash,
137 predicate: P_RDF_TYPE,
138 object: C_COG_BELIEF,
139 context: AGENT_CONTEXT,
140 metadata: t_assert & 0xFFFF_FFFF,
141 parity: 0,
142 },
143 NQuin {
144 subject: agent_did,
145 predicate: P_COG_HOLDS_BELIEF,
146 object: belief_hash,
147 context: AGENT_CONTEXT,
148 metadata: t_assert & 0xFFFF_FFFF,
149 parity: 0,
150 },
151 NQuin {
152 subject: belief_hash,
153 predicate: P_GENERATED_AT,
154 object: t_assert,
155 context: T_CONTEXT,
156 metadata: 0,
157 parity: 0,
158 },
159 NQuin {
160 subject: belief_hash,
161 predicate: P_STARTED_AT,
162 object: t_valid,
163 context: T_CONTEXT,
164 metadata: 0,
165 parity: 0,
166 },
167 ]
168}
169
170#[inline]
173fn make_temporal(subject: u64, predicate: u64, object: u64) -> NQuin {
174 NQuin {
175 subject,
176 predicate,
177 object,
178 context: T_CONTEXT,
179 metadata: 0,
180 parity: 0,
181 }
182}
183
184pub type TempQuins = Vec<NQuin>;
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194
195 #[test]
196 fn assert_temporal_all_fields() {
197 let qs = assert_temporal(0x1111, 1_000, Some(2_000), 3_000, Some(0xDEAD));
198 assert_eq!(qs.len(), 4);
199 assert_eq!(qs[0].predicate, P_GENERATED_AT);
200 assert_eq!(qs[0].object, 3_000);
201 assert_eq!(qs[1].predicate, P_STARTED_AT);
202 assert_eq!(qs[1].object, 1_000);
203 assert_eq!(qs[2].predicate, P_ENDED_AT);
204 assert_eq!(qs[2].object, 2_000);
205 assert_eq!(qs[3].predicate, P_WAS_ATTRIBUTED_TO);
206 assert_eq!(qs[3].object, 0xDEAD);
207 for q in &qs {
208 assert_eq!(q.context, T_CONTEXT);
209 }
210 }
211
212 #[test]
213 fn assert_temporal_no_end_no_author() {
214 let qs = assert_temporal(0x1234, 500, None, 600, None);
215 assert_eq!(qs.len(), 2);
216 }
217
218 #[test]
219 fn cogai_belief_has_temporal_and_agent_context() {
220 let qs = write_belief(0xAAAA, 0xBBBB, 9_000, 8_000);
221 let t_ctx: Vec<_> = qs.iter().filter(|q| q.context == T_CONTEXT).collect();
222 let a_ctx: Vec<_> = qs.iter().filter(|q| q.context == AGENT_CONTEXT).collect();
223 assert_eq!(t_ctx.len(), 2);
224 assert_eq!(a_ctx.len(), 2);
225 }
226
227 #[test]
228 fn all_predicate_hashes_distinct() {
229 let predicates = [
230 P_GENERATED_AT,
231 P_STARTED_AT,
232 P_ENDED_AT,
233 P_WAS_ATTRIBUTED_TO,
234 P_WAS_GENERATED_BY,
235 P_WAS_INVALIDATED_BY,
236 P_INVALIDATED_AT,
237 P_DC_VALID,
238 P_DC_CREATOR,
239 ];
240 let mut seen = std::collections::HashSet::new();
241 for p in &predicates {
242 assert!(seen.insert(p), "duplicate predicate hash: {p}");
243 }
244 }
245}