src/lib/utils/portClassifier.ts and src/lib/services/VoyageSegmentService.ts produces per-leg covered CO₂ figures used everywhere in the app — fleet ETS dashboard, vessel detail voyages table, EU ETS report.
Port classification
A port is classified EU/EEA if its UN/LOCODE country code (the first two letters) matches one of these 30 codes:Voyage type from leg endpoints
Coverage factors
Applied only to emissions at sea during the leg:Port emissions: per-record classification
Emissions while at port are not tied to the voyage type. They’re classified by the actual port LOCODE on each record:- EU port → 100% covered
- Non-EU port → 0% covered
Phase-in factor by year
Final formula
DEFAULT_EUA_PRICE.
Voyage segmentation (BOSP-based)
TheextractVoyageLegs() function walks consumption records chronologically and creates a new leg whenever it encounters a BOSP (Beginning of Sea Passage) event. Records before the first BOSP are buffered and attached to the first leg.
This means:
- A voyage with 4 BOSP events produces 4 legs
- Repeated voyage numbers (e.g.
99W, 99E, 99W) are split into segments (99W-1,99E-1,99W-2) - Coverage is applied per leg, not per voyage
Implementation
src/lib/utils/portClassifier.ts—isEUPort,determineVoyageType,getETSCoverageFactor,getETSPhaseInFactor,extractVoyageLegs,calculateLegsETSEmissionssrc/lib/services/VoyageSegmentService.ts— orchestration layer used across pages and reports
Reference
- Directive 2003/87/EC (consolidated) — EU ETS directive
- Directive (EU) 2023/959 — Amendment bringing maritime into ETS
- Regulation (EU) 2015/757 (consolidated) — MRV (data feed)
- DNV — EU ETS Maritime overview
- CE Delft technical report