///|
pub struct EmissionFactor {
pollutant : String
factor : Float
unit : String
source : String
} derive(Debug, Eq)
///|
pub fn emission_factor(
pollutant : String,
factor : Float,
unit : String,
source : String,
) -> EmissionFactor {
{ pollutant, factor, unit, source }
}
///|
pub struct Emission {
pollutant : String
amount : Float
unit : String
source : String
} derive(Debug, Eq)
///|
pub fn emission(
pollutant : String,
amount : Float,
unit : String,
source : String,
) -> Emission {
{ pollutant, amount, unit, source }
}
///|
pub fn Emission::is_valid(self : Emission) -> Bool {
self.pollutant.trim().length() > 0 && self.amount >= 0.0
}
///|
pub struct EnvironmentalInventory {
emissions : Array[Emission]
period : String
facility : String
} derive(Debug, Eq)
///|
pub fn environmental_inventory(
emissions : Array[Emission],
period : String,
facility : String,
) -> EnvironmentalInventory {
{ emissions, period, facility }
}
///|
pub fn EnvironmentalInventory::total(self : EnvironmentalInventory) -> Float {
let mut total : Float = 0.0
for item in self.emissions {
total = total + item.amount
}
total
}
///|
pub fn EnvironmentalInventory::pollutants(
self : EnvironmentalInventory,
) -> Array[String] {
let result : Array[String] = []
for item in self.emissions {
if !result.contains(item.pollutant) {
result.push(item.pollutant)
}
}
result
}
///|
pub fn EnvironmentalInventory::by_pollutant(
self : EnvironmentalInventory,
pollutant : String,
) -> Float {
let mut total : Float = 0.0
for item in self.emissions {
if item.pollutant == pollutant {
total = total + item.amount
}
}
total
}
///|
pub fn EnvironmentalInventory::table(
self : EnvironmentalInventory,
) -> ReportTable {
let rows : Array[Array[String]] = []
for pollutant in self.pollutants() {
rows.push([
pollutant,
"{self.by_pollutant(pollutant)}",
self.period,
self.facility,
])
}
table(["pollutant", "amount", "period", "facility"], rows)
}
///|
pub fn EnvironmentalInventory::valid(self : EnvironmentalInventory) -> Bool {
for item in self.emissions {
if !item.is_valid() {
return false
}
}
true
}
///|
pub fn carbon_emission(energy : Float, factor : EmissionFactor) -> Emission {
emission(factor.pollutant, energy * factor.factor, factor.unit, factor.source)
}
///|
pub fn emission_intensity(
emissions : EnvironmentalInventory,
production : Float,
) -> Float {
if production <= 0.0 {
0.0
} else {
emissions.total() / production
}
}
///|
pub fn reduction_target(baseline : Float, reduction : Float) -> Float {
baseline * (1.0 - clamp(reduction, 0.0, 1.0))
}
///|
pub fn reduction_achieved(baseline : Float, current : Float) -> Float {
if baseline <= 0.0 {
0.0
} else {
clamp((baseline - current) / baseline, 0.0, 1.0)
}
}
///|
pub fn environmental_gate(
inventory : EnvironmentalInventory,
maximum : Float,
) -> Bool {
inventory.valid() && inventory.total() <= maximum
}
///|
pub fn environmental_section(
inventory : EnvironmentalInventory,
) -> ReportSection {
{
title: "Environmental inventory",
kind: Safety,
body: inventory.table().to_markdown(),
}
}