1use std::time::{Duration, SystemTime, UNIX_EPOCH};
2
3use strm_privacy_driver::StrmPrivacyValue;
4use uuid::Uuid;
5
6use crate::data_manipulation::anonymizable::QuasiIdentifierType::Integer;
7use crate::data_manipulation::anonymizable::QuasiIdentifierTypes::{Interval, Nominal};
8use crate::data_manipulation::anonymizable::{
9 Anonymizable, QuasiIdentifierTypes, SensitiveAttribute,
10};
11
12impl StrmPrivacyValue for MuellerStream {
13 const STRM_SCHEMA_REF: &'static str = "diff_priv/mueller-steps/1.0.0";
14 const STRM_SCHEMA: &'static str = r#"
15{"type":"record","name":"MuellerStream","namespace":"diff_priv.MuellerSteps.v1_0_0","fields":[{"name":"strmMeta","type":{"type":"record","name":"strmMeta","namespace":"diff_priv.MuellerSteps.v1_0_0.strmmeta","fields":[{"name":"eventContractRef","type":"string"},{"name":"nonce","type":["null","int"],"default":null},{"name":"timestamp","type":["null","long"],"default":null},{"name":"keyLink","type":["null","string"],"default":null},{"name":"billingId","type":["null","string"],"default":null},{"name":"consentLevels","type":{"type":"array","items":"int"}}]}},{"name":"id","type":"string","doc":"id"},{"name":"gender","type":["null","string"],"doc":"gender of the user","default":null},{"name":"age","type":["null","int"],"doc":"the URL of the current page","default":null},{"name":"run_id","type":["null","int"],"doc":"the id of the run session","default":null},{"name":"running","type":["null","boolean"],"doc":"if the user is running","default":null},{"name":"speed","type":["null","float"],"doc":"the speed of the user","default":null},{"name":"duration","type":["null","float"],"doc":"duration of the step","default":null},{"name":"distance","type":["null","float"],"doc":"distance travaled","default":null},{"name":"side","type":["null","string"],"doc":"which foot","default":null},{"name":"bout","type":["null","int"],"doc":"doc","default":null},{"name":"freq","type":["null","float"],"doc":"which foot","default":null},{"name":"walk_ratio","type":["null","float"],"doc":"which foot","default":null},{"name":"start","type":["null","string"],"doc":"start of step","default":null},{"name":"end","type":["null","string"],"doc":"end of step","default":null}]}
16 "#;
17}
18
19#[derive(Debug, PartialEq, Clone, serde::Deserialize, serde::Serialize)]
20#[serde(default)]
21pub struct StrmMeta {
22 #[serde(rename = "eventContractRef")]
23 pub event_contract_ref: String,
24 pub nonce: Option<i32>,
25 pub timestamp: Option<i64>,
26 #[serde(rename = "keyLink")]
27 pub key_link: Option<String>,
28 #[serde(rename = "billingId")]
29 pub billing_id: Option<String>,
30 #[serde(rename = "consentLevels")]
31 pub consent_levels: Vec<i32>,
32}
33
34impl Default for StrmMeta {
35 fn default() -> StrmMeta {
36 StrmMeta {
37 event_contract_ref: "diff_priv/mueller-steps/1.0.0".to_string(),
38 nonce: None,
39 timestamp: None,
40 key_link: None,
41 billing_id: None,
42 consent_levels: vec![],
43 }
44 }
45}
46
47#[derive(Debug, PartialEq, Clone, serde::Deserialize, serde::Serialize)]
48#[serde(default)]
49pub struct MuellerStream {
50 #[serde(rename = "strmMeta")]
51 pub strm_meta: StrmMeta,
52 pub id: String,
53 pub gender: Option<String>,
54 pub age: Option<i32>,
55 pub run_id: Option<i32>,
56 pub running: Option<bool>,
57 pub speed: Option<f32>,
58 pub duration: Option<f32>,
59 pub distance: Option<f32>,
60 pub side: Option<String>,
61 pub bout: Option<i32>,
62 pub freq: Option<f32>,
63 pub walk_ratio: Option<f32>,
64 pub start: Option<String>,
65 pub end: Option<String>,
66 #[serde(skip_deserializing, default = "default_time")]
67 pub time_generated: SystemTime,
68}
69
70fn default_time() -> SystemTime {
71 SystemTime::now()
72}
73
74impl Default for MuellerStream {
75 fn default() -> MuellerStream {
76 MuellerStream {
77 strm_meta: StrmMeta::default(),
78 id: String::default(),
79 gender: None,
80 age: None,
81 run_id: None,
82 running: None,
83 speed: None,
84 duration: None,
85 distance: None,
86 side: None,
87 bout: None,
88 freq: None,
89 walk_ratio: None,
90 start: None,
91 end: None,
92 time_generated: SystemTime::now(),
93 }
94 }
95}
96
97impl Anonymizable for MuellerStream {
98 fn quasi_identifiers(&self) -> Vec<QuasiIdentifierTypes> {
99 let age = Interval((Integer(self.age.unwrap()), Integer(33), Integer(85), 1));
100 let gender_string = self.gender.as_ref().unwrap();
101 let gender = match gender_string.as_str() {
102 "male" => (0, 1, 1),
103 "female" => (1, 1, 1),
104 _ => panic!("Not all categories covered"),
105 };
106
107 let gender = Nominal(gender);
108
109 vec![age, gender]
110 }
111
112 fn update_quasi_identifiers(&self, mut qi: Vec<QuasiIdentifierTypes>) -> Self {
113 let mut update = self.clone();
114 let gender_qi = qi.pop().unwrap().extract_value();
115 let age_qi = qi.pop().unwrap().extract_value();
116
117 match gender_qi {
118 Integer(0) => update.gender = Some(String::from("male")),
119 Integer(1) => update.gender = Some(String::from("female")),
120 _ => panic!("Not all categories covered"),
121 }
122
123 if let Integer(age) = age_qi {
124 update.age = Some(age)
125 }
126
127 update
128 }
129
130 fn sensitive_value(&self) -> SensitiveAttribute {
131 SensitiveAttribute::String(self.id.to_owned())
132 }
133
134 fn extract_string_values(&self, _uuid: Uuid, _dr: f64) -> Vec<String> {
135 todo!()
136 }
137
138 fn get_timestamp(&self) -> SystemTime {
139 self.time_generated
140 }
141}