From 8ab51d1453b7c9b8a18c945cd63dc71bcd4cae50 Mon Sep 17 00:00:00 2001 From: Jorge Leitao Date: Sun, 28 Jan 2024 19:47:33 +0100 Subject: [PATCH] Improved --- examples/country.md | 7 ++-- examples/country.rs | 92 +++++++++++++++++++++++++++++++++++---------- src/consumption.csv | 1 + 3 files changed, 78 insertions(+), 22 deletions(-) diff --git a/examples/country.md b/examples/country.md index 7ab1623..0916d5c 100644 --- a/examples/country.md +++ b/examples/country.md @@ -7,10 +7,10 @@ of {country.plural} that every day act to reduce their emissions. Of these, * {number_of_legs_less_300km} trips were less than 300 km[^4] and could have been replaced by - a limusine or first class train ticket, which would have emitted ~17x less CO2[^5]. + a limusine or first class train ticket, which would have emitted ~{ratio_train_300km.claim}x less CO2[^5]. * {number_of_legs_more_300km} trips[^4] could have been replaced by a first class ticket on a commercial aircraft, which would have emitted - ~{ratio_commercial_300km}x less CO2[^1]. + ~{ratio_commercial_300km.claim}x less CO2[^6]. The use of private jets by billionaires and large companies alike is an insult to {country.plural} and {country.possessive} companies alike that are doing everything they can @@ -24,4 +24,5 @@ to reduce emissions. [^2]: {citizen_years.source} - retrieved on {citizen_years.date} [^3]: {number_of_private_jets.source} on {number_of_private_jets.date} [^4]: {number_of_legs.source} - retrieved on {number_of_legs.date} -[^5]: 10x vs a commercial flight[^1] plus 7x vs a train, as per https://ourworldindata.org/travel-carbon-footprint (UK data, vary by country) - retrieved on 2024-01-20 +[^5]: {ratio_train_300km.source} - retrieved on {ratio_train_300km.date} +[^6]: {ratio_commercial_300km.source} - retrieved on {ratio_commercial_300km.date} diff --git a/examples/country.rs b/examples/country.rs index 7c0d758..36f1b80 100644 --- a/examples/country.rs +++ b/examples/country.rs @@ -1,11 +1,14 @@ -use std::{collections::HashMap, error::Error}; +use std::{collections::HashMap, error::Error, sync::Arc}; use clap::Parser; use futures::{StreamExt, TryStreamExt}; use num_format::{Locale, ToFormattedString}; use simple_logger::SimpleLogger; -use flights::{emissions, load_aircrafts, load_private_jet_types, Class, Fact, Leg, Position}; +use flights::{ + emissions, leg_co2_kg, load_aircraft_consumption, load_aircrafts, load_private_jet_types, + AircraftTypeConsumptions, Class, Fact, Leg, Position, +}; use time::Date; fn render(context: &Context) -> Result<(), Box> { @@ -43,7 +46,8 @@ pub struct Context { pub citizen_years: Fact, pub number_of_legs_less_300km: String, pub number_of_legs_more_300km: String, - pub ratio_commercial_300km: String, + pub ratio_commercial_300km: Fact, + pub ratio_train_300km: Fact, } #[derive(clap::ValueEnum, Debug, Clone)] @@ -217,6 +221,40 @@ async fn legs( } } +fn private_emissions( + legs: &HashMap<(Arc, String), Vec>, + consumptions: &AircraftTypeConsumptions, + filter: impl Fn(&&Leg) -> bool + Copy, +) -> f64 { + legs.iter() + .map(|((_, model), legs)| { + legs.iter() + .filter(filter) + .map(|leg| { + leg_co2_kg( + consumptions.get(model).expect(model).gph as f64, + leg.duration(), + ) / 1000.0 + }) + .sum::() + }) + .sum::() +} + +fn commercial_emissions( + legs: &HashMap<(Arc, String), Vec>, + filter: impl Fn(&&Leg) -> bool + Copy, +) -> f64 { + legs.iter() + .map(|(_, legs)| { + legs.iter() + .filter(filter) + .map(|leg| emissions(leg.from().pos(), leg.to().pos(), Class::First) / 1000.0) + .sum::() + }) + .sum::() +} + #[tokio::main] async fn main() -> Result<(), Box> { SimpleLogger::new() @@ -243,6 +281,7 @@ async fn main() -> Result<(), Box> { // load datasets to memory let aircrafts = load_aircrafts(client.as_ref()).await?; let types = load_private_jet_types()?; + let consumptions = load_aircraft_consumption()?; let private_jets = aircrafts .into_iter() @@ -263,7 +302,7 @@ async fn main() -> Result<(), Box> { let legs = private_jets.iter().map(|(_, aircraft)| async { legs(from, to, &aircraft.icao_number, cli.location, client) .await - .map(|legs| (aircraft.icao_number.clone(), legs)) + .map(|legs| ((aircraft.icao_number.clone(), aircraft.model.clone()), legs)) }); let legs = futures::stream::iter(legs) @@ -292,20 +331,12 @@ async fn main() -> Result<(), Box> { date: now.to_string(), }; - let commercial_emissions_tons = legs - .iter() - .map(|(_, legs)| { - legs.iter() - .map(|leg| emissions(leg.from().pos(), leg.to().pos(), Class::First) / 1000.0) - .sum::() - }) - .sum::(); - let commercial_to_private_ratio = 10.0; - let emissions_tons_value = commercial_emissions_tons * commercial_to_private_ratio; + let emissions_value_tons = private_emissions(&legs, &consumptions, |_| true); + let emissions_tons = Fact { - claim: (emissions_tons_value as usize).to_formatted_string(&Locale::en), - source: format!("Commercial flights would have emitted {commercial_emissions_tons:.1} tons of CO2e (based on [myclimate.org](https://www.myclimate.org/en/information/about-myclimate/downloads/flight-emission-calculator/) - retrieved on 2023-10-19). Private jets emit 5-14x times. 10x was used based on [transportenvironment.org](https://www.transportenvironment.org/discover/private-jets-can-the-super-rich-supercharge-zero-emission-aviation/)"), - date: "2023-10-05, from 2021-05-27".to_string(), + claim: (emissions_value_tons as usize).to_formatted_string(&Locale::en), + source: "See [methodology M-7](https://github.com/jorgecardleitao/private-jets/blob/main/methodology.md)".to_string(), + date: time::OffsetDateTime::now_utc().date().to_string(), }; let short_legs = legs @@ -317,9 +348,31 @@ async fn main() -> Result<(), Box> { .map(|(_, legs)| legs.iter().filter(|leg| leg.distance() >= 300.0).count()) .sum::(); + let emissions_short_legs = + private_emissions(&legs, &consumptions, |leg| leg.distance() < 300.0); + let commercial_emissions_short = commercial_emissions(&legs, |leg| leg.distance() < 300.0); + + let short_ratio = emissions_short_legs / commercial_emissions_short; + let ratio_train_300km = Fact { + claim: (short_ratio + 7.0) as usize, + source: format!("{}x in comparison to a commercial flight[^1][^6] plus 7x of a commercial flight in comparison to a train, as per https://ourworldindata.org/travel-carbon-footprint (UK data, vary by country) - retrieved on 2024-01-20", short_ratio as usize), + date: now.to_string() + }; + + // compute emissions for the >300km legs, so we can compare with emissions from commercial flights + let emissions_long_legs = + private_emissions(&legs, &consumptions, |leg| leg.distance() >= 300.0); + let commercial_emissions_long = commercial_emissions(&legs, |leg| leg.distance() >= 300.0); + + let ratio_commercial_300km = Fact { + claim: (emissions_long_legs / commercial_emissions_long) as usize, + source: "Commercial flight emissions based on [myclimate.org](https://www.myclimate.org/en/information/about-myclimate/downloads/flight-emission-calculator/) - retrieved on 2023-10-19".to_string(), + date: now.to_string(), + }; + let citizen_emissions_tons = cli.country.emissions(); - let citizen_years = (emissions_tons_value / citizen_emissions_tons.claim) as usize; + let citizen_years = (emissions_value_tons / citizen_emissions_tons.claim) as usize; let citizen_years = Fact { claim: citizen_years.to_formatted_string(&Locale::en), source: citizen_emissions_tons.source, @@ -340,7 +393,8 @@ async fn main() -> Result<(), Box> { citizen_years, number_of_legs_less_300km: short_legs.to_formatted_string(&Locale::en), number_of_legs_more_300km: long_legs.to_formatted_string(&Locale::en), - ratio_commercial_300km: format!("{:.0}", commercial_to_private_ratio), + ratio_commercial_300km, + ratio_train_300km, }; render(&context)?; diff --git a/src/consumption.csv b/src/consumption.csv index 4543ecf..3314b3f 100644 --- a/src/consumption.csv +++ b/src/consumption.csv @@ -17,6 +17,7 @@ C700 316 https://www.guardianjet.com/jet-aircraft-online-tools/aircraft-brochure C25M 134 https://www.guardianjet.com/jet-aircraft-online-tools/aircraft-brochure.cfm?m=Cessna/Textron-Citation-M2-182 2024-01-26 C510 90 https://www.guardianjet.com/jet-aircraft-online-tools/aircraft-brochure.cfm?m=Cessna/Textron-Mustang-81 2024-01-26 C680 281 https://www.guardianjet.com/jet-aircraft-online-tools/aircraft-brochure.cfm?m=Cessna/Textron-Sovereign-82 2024-01-26 +C650 241 https://www.jetcraft.com/jetstream/2018/07/cessna-citation-iii-overview-1983-1991/ 2024-01-28 C56X 386 https://www.guardianjet.com/jet-aircraft-online-tools/aircraft-brochure.cfm?m=Cessna/Textron-Citation-X-86 2024-01-26 C550 116 https://www.flyingmag.com/gear-mods-refurbish-citation-iis-sierra-style/ (775 pounds/h) 2024-01-26 FA10 274 https://jetadvisors.com/jet/falcon-10/ 2024-01-26