diff --git a/README.md b/README.md index 0c93046..ceb8ddc 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ See [`methodology.md`](./methodology.md) for details of what it does and where d It is supported by an S3 Blob storage container for caching data, thereby reducing its impact to [https://adsbexchange.com/](https://adsbexchange.com/). +![Design](./design.drawio.png) + ## Risk and impact This code performs API calls to [https://adsbexchange.com/](https://adsbexchange.com/), diff --git a/design.drawio.png b/design.drawio.png new file mode 100644 index 0000000..141b69b Binary files /dev/null and b/design.drawio.png differ diff --git a/methodology.md b/methodology.md index c1d56db..a14e740 100644 --- a/methodology.md +++ b/methodology.md @@ -233,40 +233,3 @@ constraints: ``` Source code is available at [src/bin/etl_legs.rs](./src/bin/etl_legs.rs). - -### M-emissions-private-jet: Emissions of a private jet over a leg - -This was performed automatically by the program and consisted in the following calculation: - -``` -leg emissions [kg CO2e] = - consumption [gallon/h] - x liters / gallons [L/gallon] - x liters to kg of jet fuel [L/kg] - x emissions per kg [kg CO2 / kg jet fuel] - x Radiative Forcing index [kg CO2e / kg CO2] - x Life-cycle emissions [kg CO2e / kg CO2e] - x leg time [h] -``` - -Where: - -* `consumption` is obtained via the methodology `M-6` in this document. -* `liters / gallons = 3.78541 [L/gallon]`, as specified in [NIST's guide to SI](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication811e2008.pdf) -* `liters to kg of jet fuel = 0.8 [kg/L]`, as [recommended by ICAO](https://data.icao.int/newDataPlus/content/docs/glossary.pdf) -* `emissions per kg = 3.16 [kg CO2 / kg jet fuel]`, as used on [ICAO Carbon Emissions Calculator Methodology, v12 from Sep. 2023](https://applications.icao.int/icec/Methodology%20ICAO%20Carbon%20Calculator_v12-2023.pdf) -* `Radiative Forcing index = 3 [kg CO2e / kg CO2]`, as concluded in [The contribution of global aviation to anthropogenic climate forcing for 2000 to 2018](https://www.sciencedirect.com/science/article/pii/S1352231020305689), from 2021. -* `Life-cycle emissions = 1.68 [kg CO2e / kg CO2e]`, [Life Cycle Greenhouse Gas Emissions from Alternative Jet Fuels v1.2](https://web.mit.edu/aeroastro/partner/reports/proj28/partner-proj28-2010-001.pdf) from 2010-06, accessed 2024-01-28. -* `leg time [h]` is obtained by computing duration of the leg, as identified via the methodology `M-identify-legs` in this document. - -#### Per passager - -``` -leg emissions/person [kg CO2e/person] = - leg emissions [kg CO2e] - x occupancy [1/person] -``` - -where -* `leg emissions [kg CO2e]` is as computed above -* `occupancy = 0.23 [1/person] = 1/4.3 [1/person]` obtained from [Average number of passengers per flight who flew private worldwide from 2016 to 2019](https://www.statista.com/statistics/1171518/private-jet-per-flight/), where there were 4.3 passagers per flight in 2019, accessed 2024-01-28. diff --git a/src/bin/etl_legs.rs b/src/bin/etl_legs.rs index 28df5c1..fc002ec 100644 --- a/src/bin/etl_legs.rs +++ b/src/bin/etl_legs.rs @@ -6,10 +6,15 @@ use std::{ use clap::Parser; use futures::{StreamExt, TryStreamExt}; +use itertools::Itertools; use serde::{de::DeserializeOwned, Serialize}; use simple_logger::SimpleLogger; -use flights::{aircraft::Aircraft, fs::BlobStorageProvider, Position}; +use flights::{ + aircraft::{Aircraft, Aircrafts}, + fs::BlobStorageProvider, + Position, +}; static DATABASE_ROOT: &'static str = "leg/v2/"; static DATABASE: &'static str = "leg/v2/data/"; @@ -192,7 +197,7 @@ async fn etl_task( } async fn aggregate( - required: HashMap<(Arc, time::Date), Arc>, + required: HashMap<(Arc, time::Date), Aircraft>, client: &dyn BlobStorageProvider, ) -> Result<(), Box> { let all_completed = list(client).await?; @@ -261,6 +266,26 @@ async fn aggregate( Ok(()) } +async fn private_jets( + client: &dyn BlobStorageProvider, + country: Option<&str>, +) -> Result> { + // load datasets to memory + let aircrafts = flights::aircraft::read(time::macros::date!(2023 - 11 - 06), client).await?; + let models = flights::load_private_jet_models()?; + + Ok(aircrafts + .into_iter() + // its primary use is to be a private jet + .filter(|(_, a)| models.contains_key(&a.model)) + .filter(|(_, a)| { + country + .map(|country| a.country.as_deref() == Some(country)) + .unwrap_or(true) + }) + .collect()) +} + #[tokio::main(flavor = "multi_thread")] async fn main() -> Result<(), Box> { SimpleLogger::new() @@ -275,8 +300,27 @@ async fn main() -> Result<(), Box> { let client = &client; log::info!("computing required tasks..."); - let required = - flights::private_jets_in_month((2019..2025).rev(), maybe_country, client).await?; + let private_jets = private_jets(client, maybe_country).await?; + + let months = (2019..2024) + .cartesian_product(1..=12u8) + .map(|(year, month)| { + time::Date::from_calendar_date(year, time::Month::try_from(month).unwrap(), 1) + .expect("day 1 never errors") + }) + .collect::>(); + + let required = private_jets + .into_iter() + .map(|(icao, aircraft)| { + months + .clone() + .into_iter() + .map(move |date| ((icao.clone(), date), aircraft.clone())) + }) + .flatten() + .collect::>(); + log::info!("required : {}", required.len()); log::info!("computing completed tasks...");