Skip to content

Commit a958607

Browse files
committed
feat: use pact-data-model's generic-based ProductFootprint
1 parent 60cb034 commit a958607

File tree

5 files changed

+188
-383
lines changed

5 files changed

+188
-383
lines changed

gen/Cargo.lock

+1-1
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

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

0 commit comments

Comments
 (0)