diff_priv/data_manipulation/
mueller.rs

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}