Skip to content

Commit 867a4f1

Browse files
authored
Merge pull request #116 from sine-fdn/martin/pact-data-model-update
Martin/pact data model update
2 parents 60cb034 + cb8ccb6 commit 867a4f1

File tree

5 files changed

+222
-414
lines changed

5 files changed

+222
-414
lines changed

gen/Cargo.lock

+32-31
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gen/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9-
pact-data-model = { git = "https://github.com/sine-fdn/pact-data-model.git" }
9+
pact-data-model = { git = "https://github.com/sine-fdn/pact-data-model.git", branch = "extensions-type" }
1010
chrono = { version = "0.4", features = ["serde"] }
1111
schemars = { version = "0.8", features = ["chrono"] }
1212
serde = { version = "1.0.203", features = ["derive"] }

gen/src/data_gen.rs

+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
use pact_data_model::{CharacterizationFactors, ProductFootprint, WrappedDecimal};
2+
use quickcheck::*;
3+
use rust_decimal::Decimal;
4+
use schemars::JsonSchema;
5+
use serde::{Deserialize, Serialize};
6+
7+
use crate::pact_integration::to_pcf;
8+
use crate::{
9+
GlecDistance, Hoc, HocCo2eIntensityThroughput, NonEmptyVec, PactMappedFields,
10+
ShipmentFootprint, Tce, Toc,
11+
};
12+
13+
#[derive(Debug, Serialize, Deserialize, JsonSchema, PartialEq, Clone)]
14+
#[serde(rename_all = "camelCase", untagged)]
15+
pub enum ILeapType {
16+
ShipmentFootprint(ShipmentFootprint),
17+
Toc(Toc),
18+
Hoc(Hoc),
19+
}
20+
21+
impl From<&ILeapType> for PactMappedFields {
22+
fn from(ileap_type: &ILeapType) -> Self {
23+
match ileap_type {
24+
ILeapType::ShipmentFootprint(shipment_footprint) => shipment_footprint.into(),
25+
ILeapType::Toc(toc) => toc.into(),
26+
ILeapType::Hoc(hoc) => hoc.into(),
27+
}
28+
}
29+
}
30+
31+
// TODO: invert logic to generate a list of HOCs and TOCs and only then generate TCEs, improving
32+
// readability and demo data quality, as suggested by Martin.
33+
pub fn gen_rnd_demo_data(size: u8) -> Vec<ProductFootprint<ILeapType>> {
34+
let mut og = Gen::new(size as usize);
35+
36+
let mut shipment_footprints = vec![];
37+
let mut tocs = vec![];
38+
let mut hocs = vec![];
39+
40+
let num_of_shipments = u8::arbitrary(&mut og) % size + 1;
41+
for _ in 0..num_of_shipments {
42+
let mut ship_foot = ShipmentFootprint::arbitrary(&mut og);
43+
44+
let mut tces: Vec<Tce> = vec![];
45+
let mut prev_tces: Vec<String> = vec![];
46+
47+
let mut i = 0;
48+
let limit = u8::arbitrary(&mut og) % size + 1;
49+
// TODO: improve code through pair programming with Martin.
50+
loop {
51+
let mut tce = Tce::arbitrary(&mut og);
52+
53+
if let Some(prev_tce) = tces.last() {
54+
// Updates prevTceIds for the current TCE
55+
prev_tces.push(prev_tce.tce_id.clone());
56+
tce.prev_tce_ids = Some(prev_tces.clone());
57+
58+
// Avoids having two HOCs follow one another
59+
if prev_tce.hoc_id.is_some() && tce.hoc_id.is_some() {
60+
tce = Tce::arbitrary(&mut og);
61+
}
62+
};
63+
64+
if i == 0 || i == limit - 1 && tce.hoc_id.is_some() {
65+
tce = Tce::arbitrary(&mut og);
66+
}
67+
68+
if tce.hoc_id.is_some() {
69+
// Avoids having an HOC as the first or the last TCE
70+
71+
let mut hoc = Hoc::arbitrary(&mut og);
72+
hoc.co2e_intensity_throughput = HocCo2eIntensityThroughput::Tonnes;
73+
74+
hoc.hoc_id = tce.hoc_id.clone().unwrap();
75+
76+
tce.hoc_id = Some(hoc.hoc_id.clone());
77+
78+
tce.distance = GlecDistance::Actual(Decimal::from(0).into());
79+
tce.transport_activity = Decimal::from(0).into();
80+
81+
tce.co2e_wtw =
82+
WrappedDecimal::from((hoc.co2e_intensity_wtw.0 * tce.mass.0).round_dp(2));
83+
tce.co2e_ttw =
84+
WrappedDecimal::from((hoc.co2e_intensity_ttw.0 * tce.mass.0).round_dp(2));
85+
86+
let hoc = to_pcf(
87+
ILeapType::Hoc(hoc),
88+
"SINE Foundation",
89+
"urn:sine:example",
90+
Some(vec![CharacterizationFactors::Ar6]),
91+
);
92+
93+
hocs.push(hoc);
94+
}
95+
96+
if tce.toc_id.is_some() {
97+
let mut toc = Toc::arbitrary(&mut og);
98+
toc.toc_id = tce.toc_id.clone().unwrap();
99+
100+
tce.transport_activity = (tce.mass.0 * tce.distance.get_distance())
101+
.round_dp(2)
102+
.into();
103+
104+
tce.toc_id = Some(toc.toc_id.clone());
105+
106+
tce.co2e_wtw = WrappedDecimal::from(
107+
(toc.co2e_intensity_wtw.0 * tce.transport_activity.0).round_dp(2),
108+
);
109+
tce.co2e_ttw = WrappedDecimal::from(
110+
(toc.co2e_intensity_ttw.0 * tce.transport_activity.0).round_dp(2),
111+
);
112+
113+
let toc = to_pcf(
114+
ILeapType::Toc(toc),
115+
"SINE Foundation",
116+
"urn:sine:example",
117+
Some(vec![CharacterizationFactors::Ar6]),
118+
);
119+
120+
tocs.push(toc.clone());
121+
}
122+
123+
tce.shipment_id.clone_from(&ship_foot.shipment_id);
124+
125+
tces.push(tce);
126+
127+
i += 1;
128+
if i == limit {
129+
break;
130+
}
131+
}
132+
133+
ship_foot.tces = NonEmptyVec::from(tces);
134+
135+
let ship_foot = to_pcf(
136+
ILeapType::ShipmentFootprint(ship_foot),
137+
"SINE Foundation",
138+
"urn:sine:example",
139+
Some(vec![CharacterizationFactors::Ar6]),
140+
);
141+
142+
shipment_footprints.push(ship_foot);
143+
}
144+
145+
vec![shipment_footprints, tocs, hocs]
146+
.into_iter()
147+
.flatten()
148+
.collect()
149+
}
150+
151+
#[cfg(test)]
152+
mod tests {
153+
use super::*;
154+
155+
#[test]
156+
fn test_gen_rnd_demo_data() {
157+
let footprints = gen_rnd_demo_data(10);
158+
159+
for footprint in footprints.iter() {
160+
if let Some(extensions) = &footprint.extensions {
161+
for extension in extensions.iter() {
162+
if let ILeapType::ShipmentFootprint(ship_foot) = &extension.data {
163+
for tce in ship_foot.tces.0.iter() {
164+
assert!(
165+
tce.toc_id.is_some() ^ tce.hoc_id.is_some(),
166+
"Either tocId or hocId, but not both, must be provided."
167+
);
168+
}
169+
}
170+
}
171+
}
172+
}
173+
174+
println!("{footprints:#?}");
175+
}
176+
}

0 commit comments

Comments
 (0)