From 219d2e46cac7672d9661c2da5647f36e8da40838 Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <quaritsch@ivt.tugraz.at>
Date: Mon, 12 Dec 2022 18:56:42 +0100
Subject: [PATCH] more work on implementing writing CIF results. OVC lorry and
 buses work (except summary) calculation of CD/CS weighting is only a dummy
 implementation

---
 VectoCommon/VectoCommon/Utils/SI.cs           | 112 +++++++
 .../Utils/SIConvertExtensionMethods.cs        | 110 ++++++-
 .../Models/Declaration/DeclarationData.cs     |  56 +++-
 .../VectoCore/OutputData/DeclarationReport.cs |  41 +++
 .../OutputData/IModalDataContainer.cs         |   3 +-
 .../ModalDataPostprocessingCorrection.cs      |   7 +-
 .../VectoCore/OutputData/OvcResultEntry.cs    |  46 +++
 .../CIFNinjectModule.cs                       |  40 ++-
 .../ResultWriter/CO2Writer.cs                 |  75 +++++
 .../ResultWriter/ElectricEnergyWriter.cs      |  87 ++++++
 .../ResultWriter/FuelConsumptionWriter.cs     | 114 +++++++
 .../ResultWriter/IResultsWriter.cs            | 141 ++++++---
 .../ResultWriter/ResultGoupWriter.cs          | 290 ++++++++++++++----
 .../OutputData/XML/XMLDeclarationReport.cs    |  10 +-
 .../Reports/TestXMLResultsWriting.cs          |  56 +++-
 .../VectoCoreTest/Utils/ConvertedSITest.cs    | 196 ++++++++++++
 16 files changed, 1241 insertions(+), 143 deletions(-)
 create mode 100644 VectoCore/VectoCore/OutputData/OvcResultEntry.cs
 create mode 100644 VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/CO2Writer.cs
 create mode 100644 VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/ElectricEnergyWriter.cs
 create mode 100644 VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/FuelConsumptionWriter.cs
 create mode 100644 VectoCore/VectoCoreTest/Utils/ConvertedSITest.cs

diff --git a/VectoCommon/VectoCommon/Utils/SI.cs b/VectoCommon/VectoCommon/Utils/SI.cs
index 1557949c4a..cdc2711263 100644
--- a/VectoCommon/VectoCommon/Utils/SI.cs
+++ b/VectoCommon/VectoCommon/Utils/SI.cs
@@ -512,6 +512,11 @@ namespace TUGraz.VectoCommon.Utils
 		{
 			return SIBase<CubicMeterPerSecond>.Create(m3.Val * ps.Value());
 		}
+
+		public static CubicMeterPerMeter operator /(CubicMeter m3, Meter m)
+		{
+			return SIBase<CubicMeterPerMeter>.Create(m3.Value() / m.Value());
+		}
 	}
 
 	public class CubicMeterPerSecond : SIBase<CubicMeterPerSecond>
@@ -533,6 +538,42 @@ namespace TUGraz.VectoCommon.Utils
 		}
 	}
 
+	public class CubicMeterPerMeter : SIBase<CubicMeterPerMeter>
+	{
+		private static readonly int[] Units = { 0, 2, 0, 0, 0, 0, 0 };
+
+		[DebuggerHidden]
+		private CubicMeterPerMeter(double value) : base(value, Units) { }
+
+		public static CubicMeterPerKilogramMeter operator /(CubicMeterPerMeter m3pm, Kilogram kg)
+		{
+			return SIBase<CubicMeterPerKilogramMeter>.Create(m3pm.Value() / kg.Value());
+		}
+
+		public static CubicMeterPerCubicMeterMeter operator /(CubicMeterPerMeter m3pm, CubicMeter m3)
+		{
+			return SIBase<CubicMeterPerCubicMeterMeter>.Create(m3pm.Value() / m3.Value());
+		}
+	}
+
+	public class CubicMeterPerKilogramMeter : SIBase<CubicMeterPerKilogramMeter>
+	{
+		private static readonly int[] Units = { -1, 2, 0, 0, 0, 0, 0 };
+
+		[DebuggerHidden]
+		private CubicMeterPerKilogramMeter(double value)
+			: base(value, Units) { }
+	}
+
+	public class CubicMeterPerCubicMeterMeter : SIBase<CubicMeterPerCubicMeterMeter>
+	{
+		private static readonly int[] Units = { 0, -1, 0, 0, 0, 0, 0 };
+
+		[DebuggerHidden]
+		private CubicMeterPerCubicMeterMeter(double value)
+			: base(value, Units) { }
+	}
+
 	/// <summary>
 	/// SI Class for Kilogram Square Meter [kgm^2].
 	/// </summary>
@@ -618,6 +659,39 @@ namespace TUGraz.VectoCommon.Utils
 		{
 			return SIBase<Kilogram>.Create(ws.Val * kpws.Value());
 		}
+
+		public static WattSecondPerMeter operator /(WattSecond wattSecond, Meter m)
+		{
+			return SIBase<WattSecondPerMeter>.Create(wattSecond.Val / m.Value());
+		}
+
+		
+	}
+
+	public class WattSecondPerMeter : SIBase<WattSecondPerMeter>
+	{
+		private static readonly int[] Units = { 1, 1, -2, 0, 0, 0, 0 };
+
+		[DebuggerHidden]
+		private WattSecondPerMeter(double val) : base(val, Units) { }
+
+		public static WattSecondPerMeterKilogram operator /(WattSecondPerMeter wattSecond, Kilogram kg)
+		{
+			return SIBase<WattSecondPerMeterKilogram>.Create(wattSecond.Val / kg.Value());
+		}
+
+		public static WattSecondPerCubicMeterMeter operator /(WattSecondPerMeter wattSecond, CubicMeter m3)
+		{
+			return SIBase<WattSecondPerCubicMeterMeter>.Create(wattSecond.Val / m3.Value());
+		}
+	}
+
+	public class WattSecondPerCubicMeterMeter : SIBase<WattSecondPerCubicMeterMeter>
+	{
+		private static readonly int[] Units = { 1, -2, -2, 0, 0, 0, 0 };
+
+		[DebuggerHidden]
+		private WattSecondPerCubicMeterMeter(double val) : base(val, Units) { }
 	}
 
 	public class WattSecondPerCubicMeter : SIBase<WattSecondPerCubicMeter>
@@ -628,6 +702,14 @@ namespace TUGraz.VectoCommon.Utils
 		private WattSecondPerCubicMeter(double val) : base(val, Units) { }
 	}
 
+	public class WattSecondPerMeterKilogram : SIBase<WattSecondPerMeterKilogram>
+	{
+		private static readonly int[] Units = { 0, 1, -2, 0, 0, 0, 0 };
+
+		[DebuggerHidden]
+		private WattSecondPerMeterKilogram(double val) : base(val, Units) { }
+	}
+
 	public class WattPerKelvinSquareMeter : SIBase<WattPerKelvinSquareMeter>
 	{
 		private static readonly int[] Units = { 1, 0, -3, 0, -1, 0, 0 };
@@ -845,6 +927,36 @@ namespace TUGraz.VectoCommon.Utils
 		{
 			return SIBase<KilogramPerMeter>.Create(jpm.Val / jpkg.Value());
 		}
+
+		public static JoulePerCubicMeterMeter operator /(JoulePerMeter jpm, CubicMeter m3)
+		{
+			return SIBase<JoulePerCubicMeterMeter>.Create(jpm.Val / m3.Value());
+		}
+
+		public static JoulePerKilogramMeter operator /(JoulePerMeter jpm, Kilogram kg)
+		{
+			return SIBase<JoulePerKilogramMeter>.Create(jpm.Val / kg.Value());
+		}
+	}
+
+	public class JoulePerCubicMeterMeter : SIBase<JoulePerCubicMeterMeter>
+	{
+		private static readonly int[] Units = { 1, -2, -2, 0, 0, 0, 0 };
+
+		[DebuggerHidden]
+		private JoulePerCubicMeterMeter(double val) : base(val, Units) { }
+
+		public override string UnitString => "J/m³-m";
+	}
+
+	public class JoulePerKilogramMeter : SIBase<JoulePerKilogramMeter>
+	{
+		private static readonly int[] Units = { 0, 1, -2, 0, 0, 0, 0 };
+
+		[DebuggerHidden]
+		private JoulePerKilogramMeter(double val) : base(val, Units) { }
+
+		public override string UnitString => "J/kg-m";
 	}
 
 	/// <summary>
diff --git a/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs b/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs
index ab74fef586..a8eb5e8a58 100644
--- a/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs
+++ b/VectoCommon/VectoCommon/Utils/SIConvertExtensionMethods.cs
@@ -114,8 +114,14 @@ namespace TUGraz.VectoCommon.Utils
 	public static class SIConvertExtensionMethods
 	{
 		private const int Kilo = 1000;
+		private const double Mega = 1e6;
 		private const int SecondsPerHour = 60 * 60;
-		
+		private const int SecondsPerMinute = 60 * 60;
+		const int CubicMeterToLiter = 10 * 10 * 10;
+		const int CubicMeterToCubicCentimeter = 100 * 100 * 100;
+		const int MeterTo100KiloMeter = 100 * Kilo;
+		const int KilogrammToTon = Kilo;
+
 		public static ConvertedSI ConvertToGramm(this Kilogram value)
 		{
 			return new ConvertedSI(value.Value() * Kilo, "g");
@@ -133,20 +139,25 @@ namespace TUGraz.VectoCommon.Utils
 			return value == null ? null : new ConvertedSI(value.Value() * Kilo * Kilo, "g/km");
 		}
 
+		public static ConvertedSI ConvertToGrammPerPassengerKilometer(this KilogramPerMeter value)
+		{
+			return value == null ? null : new ConvertedSI(value.Value() * Kilo * Kilo, "g/p-km");
+		}
+
 		public static ConvertedSI ConvertToKiloWattHourPerKiloMeter(this JoulePerMeter value)
 		{
-			return new ConvertedSI(value.Value() / 3600, "kWh/km");
+			return new ConvertedSI(value.Value() / SecondsPerHour, "kWh/km");
 		}
 
 
         public static ConvertedSI ConvertToGramPerKiloWattHour(this SpecificFuelConsumption value)
 		{
-			return new ConvertedSI(value.Value() * 3600e6, "g/kWh");
+			return new ConvertedSI(value.Value() * SecondsPerHour * Mega, "g/kWh");
 		}
 
 		public static ConvertedSI ConvertToGramPerKiloWattHour(this KilogramPerWattSecond value)
 		{
-			return new ConvertedSI(value.Value() * 3600e6, "g/kWh");
+			return new ConvertedSI(value.Value() * SecondsPerHour *Mega, "g/kWh");
 		}
 
 		public static ConvertedSI ConvertToLiterPer100Kilometer(this VolumePerMeter value)
@@ -156,17 +167,11 @@ namespace TUGraz.VectoCommon.Utils
 		
 		public static ConvertedSI ConvertToLiterPer100TonKiloMeter(this VolumePerMeterMass value)
 		{
-			const int CubicMeterToLiter = 10 * 10 * 10;
-			const int MeterTo100KiloMeter = 100 * Kilo;
-			const int KilogrammToTon = Kilo;
-
 			return value == null ? null  : new ConvertedSI(value.Value() * CubicMeterToLiter * (MeterTo100KiloMeter * KilogrammToTon), "l/100tkm");
 		}
 
 		public static ConvertedSI ConvertToLiterPerCubicMeter100KiloMeter(this VolumePerMeterVolume value)
 		{
-			const int CubicMeterToLiter = 10 * 10 * 10;
-			const int MeterTo100KiloMeter = 100 * Kilo;
 			return new ConvertedSI(value.Value() * CubicMeterToLiter * MeterTo100KiloMeter, "l/100m³-km");
 		}
 
@@ -182,7 +187,7 @@ namespace TUGraz.VectoCommon.Utils
 
 		public static ConvertedSI ConvertToCubicCentiMeter(this CubicMeter value)
 		{
-			return new ConvertedSI(value.Value() * 100 * 100 * 100, "cm³");
+			return new ConvertedSI(value.Value() * CubicMeterToCubicCentimeter, "cm³");
 		}
 
 		public static ConvertedSI ConvertToGrammPerCubicMeterKiloMeter(this KilogramPerMeterCubicMeter value)
@@ -199,6 +204,46 @@ namespace TUGraz.VectoCommon.Utils
 		{
 			return new ConvertedSI(value.Value() / Kilo / SecondsPerHour, "kWh");
 		}
+
+		public static ConvertedSI ConvertToKiloWattHourPerKiloMeter(this WattSecondPerMeter value)
+		{
+			return new ConvertedSI(value.Value() / Kilo / SecondsPerHour * Kilo, "kWh/km");
+		}
+
+		public static ConvertedSI ConvertToKiloWattHourPerPassengerKiloMeter(this WattSecondPerMeter value)
+		{
+			return new ConvertedSI(value.Value() / Kilo / SecondsPerHour * Kilo, "kWh/p-km");
+		}
+
+		public static ConvertedSI ConvertToKiloWattHourPerTonKiloMeter(this WattSecondPerMeterKilogram value)
+		{
+			return new ConvertedSI(value.Value() / Kilo / SecondsPerHour * Kilo * KilogrammToTon, "kWh/t-km");
+		}
+
+		public static ConvertedSI ConvertToKiloWattHourPerCubicMeterKiloMeter(this WattSecondPerCubicMeterMeter value)
+		{
+			return new ConvertedSI(value.Value() / Kilo / SecondsPerHour * Kilo, "kWh/m³-km");
+		}
+
+		public static ConvertedSI ConvertToMegaJoulePerKiloMeter(this WattSecondPerMeter value)
+		{
+			return new ConvertedSI(value.Value() / Mega * Kilo, "MJ/km");
+		}
+		public static ConvertedSI ConvertToMegaJoulePerPassengerKiloMeter(this WattSecondPerMeter value)
+		{
+			return new ConvertedSI(value.Value() / Mega * Kilo, "MJ/p-km");
+		}
+
+		public static ConvertedSI ConvertToMegaJoulePerTonKiloMeter(this WattSecondPerMeterKilogram value)
+		{
+			return new ConvertedSI(value.Value() / Mega * Kilo * KilogrammToTon, "MJ/t-km");
+		}
+
+		public static ConvertedSI ConvertToMegaJoulePerCubicMeterKiloMeter(this WattSecondPerCubicMeterMeter value)
+		{
+			return new ConvertedSI(value.Value() / Mega * Kilo , "MJ/m³-km");
+		}
+
 		public static ConvertedSI ConvertToWattHour(this WattSecond value)
 		{
 			return new ConvertedSI(value.Value() / SecondsPerHour, "Wh");
@@ -225,7 +270,7 @@ namespace TUGraz.VectoCommon.Utils
 
 		public static ConvertedSI ConvertToCubicDeziMeter(this CubicMeter value)
 		{
-			return new ConvertedSI(value.Value() * 10 * 10 * 10, "dm^3");
+			return new ConvertedSI(value.Value() * CubicMeterToLiter, "dm^3");
 		}
 		public static ConvertedSI ConvertToMilliMeter(this Meter value)
 		{
@@ -244,17 +289,52 @@ namespace TUGraz.VectoCommon.Utils
 
 		public static ConvertedSI ConvertToMinutes(this Second sec)
 		{
-			return new ConvertedSI(sec.Value() / 60.0, "min");
+			return new ConvertedSI(sec.Value() / SecondsPerMinute, "min");
 		}
 
 		public static ConvertedSI ConvertToNlPerMin(this NormLiterPerSecond nlps)
 		{
-			return new ConvertedSI(nlps.Value() * 60.0, "Nl/min");
+			return new ConvertedSI(nlps.Value() * SecondsPerMinute, "Nl/min");
 		}
 
 		public static ConvertedSI ConvertToMegaJoulePerKilometer(this JoulePerMeter jpm)
 		{
-			return new ConvertedSI(jpm.Value() * 1e-3, "MJ/km");
+			return new ConvertedSI(jpm.Value() / Mega * Kilo, "MJ/km");
+		}
+
+		public static ConvertedSI ConvertToMegaJoulePerPassengerKilometer(this JoulePerMeter jpm)
+		{
+			return new ConvertedSI(jpm.Value() / Mega * Kilo, "MJ/p-km");
+		}
+
+		public static ConvertedSI ConvertToMegaJoulePerTonKiloMeter(this JoulePerKilogramMeter jpkgm)
+		{
+			return new ConvertedSI(jpkgm.Value() /Mega * Kilo * Kilo, "MJ/t-km");
+		}
+
+		public static ConvertedSI ConvertToMegaJoulePerCubicMeterKiloMeter(this JoulePerCubicMeterMeter jpm3m)
+		{
+			return new ConvertedSI(jpm3m.Value() / Mega * Kilo, "MJ/m³-km");
+		}
+
+		public static ConvertedSI ConvertToLiterPer100KiloMeter(this CubicMeterPerMeter jpm3m)
+		{
+			return new ConvertedSI(jpm3m.Value() * CubicMeterToLiter * MeterTo100KiloMeter, "l/100km");
+		}
+
+		public static ConvertedSI ConvertToLiterPerPassengerKiloMeter(this CubicMeterPerMeter jpm3m)
+		{
+			return new ConvertedSI(jpm3m.Value() * CubicMeterToLiter * Kilo, "l/p-km");
+		}
+
+		public static ConvertedSI ConvertToLiterPerTonKiloMeter(this CubicMeterPerKilogramMeter m3pkmm)
+		{
+			return new ConvertedSI(m3pkmm.Value() * CubicMeterToLiter * Kilo * Kilo, "l/t-km");
+		}
+
+		public static ConvertedSI ConvertToLiterPerCubicMeterKiloMeter(this CubicMeterPerCubicMeterMeter m3pm3m)
+		{
+			return new ConvertedSI(m3pm3m.Value() * CubicMeterToLiter * Kilo, "l/m³-km");
 		}
 
 		public static Meter ConvertToMeter(this ConvertedSI mm)
diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
index 2d35df18df..4888611995 100644
--- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
+++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
@@ -52,10 +52,12 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine;
 using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox;
 using TUGraz.VectoCore.Utils;
 using TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.HVAC;
+using TUGraz.VectoCore.Models.Simulation.Impl;
+using TUGraz.VectoCore.OutputData;
 
 namespace TUGraz.VectoCore.Models.Declaration
 {
-    public static class DeclarationData
+	public static class DeclarationData
 	{
 		/// <summary>
 		/// The standard acceleration for gravity on earth.
@@ -412,19 +414,19 @@ namespace TUGraz.VectoCore.Models.Declaration
 				}
 			}
 
-            public static double CalculateCOP(Watt coolingPwrDriver, double copDriver, Watt coolingPwrPass, double copPass)
-            {
-                if (coolingPwrDriver.IsGreater(0) && copDriver.IsEqual(0)) {
-                    copDriver = copPass;
-                }
-                if (coolingPwrDriver.IsEqual(0) && coolingPwrPass.IsEqual(0)) {
-                    return 1.0;
-                }
-                return (coolingPwrDriver * copDriver + coolingPwrPass * copPass) /
-                        (coolingPwrDriver + coolingPwrPass);
-            }
-
-            public static Meter CorrectionLengthDrivetrainVolume(VehicleCode? vehicleCode, bool? lowEntry, int numAxles, bool articulated)
+			public static double CalculateCOP(Watt coolingPwrDriver, double copDriver, Watt coolingPwrPass, double copPass)
+			{
+				if (coolingPwrDriver.IsGreater(0) && copDriver.IsEqual(0)) {
+					copDriver = copPass;
+				}
+				if (coolingPwrDriver.IsEqual(0) && coolingPwrPass.IsEqual(0)) {
+					return 1.0;
+				}
+				return (coolingPwrDriver * copDriver + coolingPwrPass * copPass) /
+						(coolingPwrDriver + coolingPwrPass);
+			}
+
+			public static Meter CorrectionLengthDrivetrainVolume(VehicleCode? vehicleCode, bool? lowEntry, int numAxles, bool articulated)
 			{
 				if ((vehicleCode == VehicleCode.CE || vehicleCode == VehicleCode.CG) && (bool)lowEntry) {
 					switch (numAxles) {
@@ -1366,5 +1368,31 @@ namespace TUGraz.VectoCore.Models.Declaration
 				}
 			}
 		}
+
+		public static IWeightedResult CalculateWeightedResult(IResultEntry cdResult, IResultEntry csResult)
+		{
+			if (cdResult.Status != VectoRun.Status.Success || csResult.Status != VectoRun.Status.Success) {
+				return null;
+			}
+			// ToDo MQ 2022-12-12: add correct calculation method!
+			return new WeightedResult(cdResult) {
+				AverageSpeed = cdResult.AverageSpeed,
+				FuelConsumption = cdResult.FuelData.Select(x => Tuple.Create(x,
+						(cdResult.FuelConsumptionFinal(x.FuelType).TotalFuelConsumptionCorrected +
+						csResult.FuelConsumptionFinal(x.FuelType).TotalFuelConsumptionCorrected) / 2.0))
+					.ToDictionary(x => x.Item1, x => x.Item2),
+				ElectricEnergyConsumption = (cdResult.ElectricEnergyConsumption + csResult.ElectricEnergyConsumption) / 2.0,
+				CO2Total = (cdResult.CO2Total + csResult.CO2Total) / 2.0,
+				ActualChargeDepletingRange = cdResult.Distance,
+				EquivalentAllElectricRange = cdResult.Distance,
+				ZeroCO2EmissionsRange = cdResult.Distance,
+				UtilityFactor = 1
+			};
+		}
+
+		public static IWeightedResult CalculateWeightedSummary(IList<IResultEntry> entries)
+		{
+			throw new NotImplementedException();
+		}
 	}
 }
diff --git a/VectoCore/VectoCore/OutputData/DeclarationReport.cs b/VectoCore/VectoCore/OutputData/DeclarationReport.cs
index 5db09426db..c8ae48ad8c 100644
--- a/VectoCore/VectoCore/OutputData/DeclarationReport.cs
+++ b/VectoCore/VectoCore/OutputData/DeclarationReport.cs
@@ -101,6 +101,8 @@ namespace TUGraz.VectoCore.OutputData
 
 		IFuelConsumptionCorrection FuelConsumptionFinal(FuelType fuelType);
 
+		WattSecond ElectricEnergyConsumption { get; }
+
 		Kilogram CO2Total { get; }
 		Kilogram Payload { get; set; }
 		Kilogram TotalVehicleMass { get; set; }
@@ -118,6 +120,45 @@ namespace TUGraz.VectoCore.OutputData
 		string StackTrace { get; }
 	}
 
+	public interface IWeightedResult
+	{
+		MeterPerSecond AverageSpeed { get; }
+
+		Meter Distance { get; }
+
+		Kilogram Payload { get; }
+
+		CubicMeter CargoVolume { get; }
+
+		double? PassengerCount { get; }
+
+		IDictionary<IFuelProperties, Kilogram> FuelConsumption { get; }
+
+		WattSecond ElectricEnergyConsumption { get; }
+
+		Kilogram CO2Total { get; }
+
+		Meter ActualChargeDepletingRange { get; }
+
+		Meter EquivalentAllElectricRange { get; }
+
+		Meter ZeroCO2EmissionsRange { get; }
+
+		double UtilityFactor { get; }
+	}
+
+	public interface IOVCResultEntry 
+	{
+
+		IResultEntry ChargeDepletingResult { get; }
+
+		IResultEntry ChargeSustainingResult { get; }
+
+		IWeightedResult Weighted { get; }
+
+	}
+
+
 	/// <summary>
 	/// Class for creating a declaration report.
 	/// </summary>
diff --git a/VectoCore/VectoCore/OutputData/IModalDataContainer.cs b/VectoCore/VectoCore/OutputData/IModalDataContainer.cs
index 8a46eeec85..f4a9b5e201 100644
--- a/VectoCore/VectoCore/OutputData/IModalDataContainer.cs
+++ b/VectoCore/VectoCore/OutputData/IModalDataContainer.cs
@@ -176,7 +176,8 @@ namespace TUGraz.VectoCore.OutputData
 		KilogramPerMeter KilogramCO2PerMeter { get; }
 		Dictionary<FuelType, IFuelConsumptionCorrection> FuelCorrection { get; }
 		Kilogram CO2Total { get; }
-		Joule EnergyConsumptionTotal { get; }
+		Joule FuelEnergyConsumptionTotal { get; }
+		WattSecond ElectricEnergyConsumption { get; }
 	}
 
 	public interface IFuelConsumptionCorrection
diff --git a/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs b/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs
index 036b17face..4de8e0946b 100644
--- a/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs
+++ b/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs
@@ -392,7 +392,7 @@ namespace TUGraz.VectoCore.OutputData
 			}
 		}
 
-		public Joule EnergyConsumptionTotal
+		public Joule FuelEnergyConsumptionTotal
 		{
 			get
 			{
@@ -401,6 +401,8 @@ namespace TUGraz.VectoCore.OutputData
 			}
 		}
 
+		public WattSecond ElectricEnergyConsumption { get; }
+
 		public Second ICEOffTimeStandstill { get; set; }
 		public WattSecond EnergyAuxICEOffStandstill { get; set; }
 		public WattSecond EnergyAuxICEOffStandstill_UF {
@@ -562,7 +564,8 @@ namespace TUGraz.VectoCore.OutputData
 		public KilogramPerMeter KilogramCO2PerMeter => 0.SI<KilogramPerMeter>();
 		public Dictionary<FuelType, IFuelConsumptionCorrection> FuelCorrection => new Dictionary<FuelType, IFuelConsumptionCorrection>();
 		public Kilogram CO2Total => 0.SI<Kilogram>();
-		public Joule EnergyConsumptionTotal => 0.SI<Joule>();
+		public Joule FuelEnergyConsumptionTotal => 0.SI<Joule>();
+		public WattSecond ElectricEnergyConsumption => 0.SI<WattSecond>();
 
 		#endregion
 	}
diff --git a/VectoCore/VectoCore/OutputData/OvcResultEntry.cs b/VectoCore/VectoCore/OutputData/OvcResultEntry.cs
new file mode 100644
index 0000000000..a6ba1c2efd
--- /dev/null
+++ b/VectoCore/VectoCore/OutputData/OvcResultEntry.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+using TUGraz.VectoCommon.BusAuxiliaries;
+using TUGraz.VectoCommon.Utils;
+
+namespace TUGraz.VectoCore.OutputData
+{
+	public class OvcResultEntry : IOVCResultEntry
+	{
+		#region Implementation of IOVCResultEntry
+
+		public IResultEntry ChargeDepletingResult { get; internal set; }
+		public IResultEntry ChargeSustainingResult { get; internal set; }
+
+		public IWeightedResult Weighted { get; internal set; }
+
+		#endregion
+	}
+
+	public class WeightedResult : IWeightedResult
+	{
+		public WeightedResult(IResultEntry cdResult)
+		{
+			ChargeDepletingResult = cdResult;
+		}
+
+		protected IResultEntry ChargeDepletingResult;
+
+		#region Implementation of IWeightedResult
+
+		public Meter Distance => ChargeDepletingResult.Distance;
+		public Kilogram Payload => ChargeDepletingResult.Payload;
+		public CubicMeter CargoVolume => ChargeDepletingResult.CargoVolume;
+		public double? PassengerCount => ChargeDepletingResult.PassengerCount;
+		public MeterPerSecond AverageSpeed { get; internal set; }
+
+		public IDictionary<IFuelProperties, Kilogram> FuelConsumption { get; internal set; }
+		public WattSecond ElectricEnergyConsumption { get; internal set; }
+		public Kilogram CO2Total { get; internal set; }
+		public Meter ActualChargeDepletingRange { get; internal set; }
+		public Meter EquivalentAllElectricRange { get; internal set; }
+		public Meter ZeroCO2EmissionsRange { get; internal set; }
+		public double UtilityFactor { get; internal set; }
+
+		#endregion
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFNinjectModule.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFNinjectModule.cs
index 1e093da01f..5028fb0a44 100644
--- a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFNinjectModule.cs
+++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/CIFNinjectModule.cs
@@ -444,6 +444,8 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 
 			Bind<ICifResultsWriterFactory>().ToFactory().InSingletonScope();
 
+			// -- Lorry
+
 			Bind<IResultGroupWriter>().To<LorryOVCResultWriter>().When(AccessedViaCIFResultsWriterFactory)
 				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetLorryOVCSuccessResultWriter());
 			Bind<IResultGroupWriter>().To<ErrorResultWriter>().When(AccessedViaCIFResultsWriterFactory)
@@ -452,19 +454,53 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 			Bind<IResultGroupWriter>().To<ResultMissionWriter>().When(AccessedViaCIFResultsWriterFactory)
 				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetMissionWriter());
 			Bind<IResultGroupWriter>().To<ResultSimulationParameterLorryWriter>().When(AccessedViaCIFResultsWriterFactory)
-				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetSimulationParameterWriter());
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetLorrySimulationParameterWriter());
 
 			Bind<IResultGroupWriter>().To<LorryOVCChargeDepletingWriter>().When(AccessedViaCIFResultsWriterFactory)
 				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetLorryOVCResultWriterChargeDepleting());
 			Bind<IResultGroupWriter>().To<LorryOVCChargeSustainingWriter>().When(AccessedViaCIFResultsWriterFactory)
 				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetLorryOVCResultWriterChargeSustaining());
+			Bind<IResultGroupWriter>().To<LorryOVCTotalWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetLorryOVCSummaryWriter());
 
 
 			Bind<IFuelConsumptionWriter>().To<LorryFuelConsumptionWriter>().When(AccessedViaCIFResultsWriterFactory)
 				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetFuelConsumptionLorry());
-
 			Bind<IResultGroupWriter>().To<LorryElectricEnergyConsumptionWriter>().When(AccessedViaCIFResultsWriterFactory)
 				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetElectricEnergyConsumptionLorry());
+			Bind<ICO2Writer>().To<LorryCO2Writer>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetCO2ResultLorry());
+
+			Bind<ICifSummaryWriter>().To<LorryOVCCifSummaryWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetLorryOVCCifSummaryWriter());
+
+
+			// -- Bus
+
+			Bind<IResultGroupWriter>().To<BusOVCTotalWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetBusOVCSuccessResultWriter());
+			Bind<IResultGroupWriter>().To<ErrorResultWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetBusOVCErrorResultWriter());
+
+			Bind<IResultGroupWriter>().To<ResultSimulationParameterBusWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetBusSimulationParameterWriter());
+
+			Bind<IResultGroupWriter>().To<BusOVCChargeDepletingWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetBusOVCResultWriterChargeDepleting());
+			Bind<IResultGroupWriter>().To<BusOVCChargeSustainingWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetBusOVCResultWriterChargeSustaining());
+			Bind<IResultGroupWriter>().To<BusOVCSummaryWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetBusOVCSummaryWriter());
+
+			Bind<IFuelConsumptionWriter>().To<BusFuelConsumptionWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetFuelConsumptionBus());
+			Bind<IResultGroupWriter>().To<BusElectricEnergyConsumptionWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetElectricEnergyConsumptionBus());
+			Bind<ICO2Writer>().To<BusCO2Writer>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetCO2ResultBus());
+
+			Bind<ICifSummaryWriter>().To<BusOVCCifSummaryWriter>().When(AccessedViaCIFResultsWriterFactory)
+				.NamedLikeFactoryMethod((ICifResultsWriterFactory c) => c.GetBusOVCCifSummaryWriter());
 
 		}
 
diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/CO2Writer.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/CO2Writer.cs
new file mode 100644
index 0000000000..bcd6e02204
--- /dev/null
+++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/CO2Writer.cs
@@ -0,0 +1,75 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+using TUGraz.VectoCommon.Resources;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile.CustomerInformationFile_0_9.ResultWriter
+{
+	public abstract class CO2WriterBase : AbstractResultWriter, ICO2Writer
+	{
+		protected CO2WriterBase(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Implementation of IFuelConsumptionWriter
+
+		public XElement[] GetElement(IResultEntry entry)
+		{
+			return GetFuelConsumption(entry.CO2Total, entry.Distance, entry.Payload, entry.CargoVolume, entry.PassengerCount).Select(x =>
+				new XElement(Cif + XMLNames.Report_Results_CO2, XMLHelper.ValueAsUnit(x, 3, 1))).ToArray();
+		}
+
+		protected abstract IList<ConvertedSI> GetFuelConsumption(Kilogram co2, Meter distance, Kilogram payload, CubicMeter volume, double? passengers);
+
+		#endregion
+
+		#region Overrides of AbstractResultWriter
+
+		public virtual XElement[] GetElement(IOVCResultEntry ovcEntry)
+		{
+			var entry = ovcEntry.Weighted;
+			return GetFuelConsumption(entry.CO2Total, entry.Distance, entry.Payload, entry.CargoVolume, entry.PassengerCount).Select(x =>
+				new XElement(Cif + XMLNames.Report_Results_CO2, XMLHelper.ValueAsUnit(x, 3, 1))).ToArray();
+		}
+
+		#endregion
+
+	}
+
+	public class LorryCO2Writer : CO2WriterBase
+	{
+		public LorryCO2Writer(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+
+		#region Overrides of FuelConsumptionWriterBase
+
+		protected override IList<ConvertedSI> GetFuelConsumption(Kilogram CO2Total, Meter distance, Kilogram payload, CubicMeter volume, double? passengers)
+		{
+			return new[] {
+				(CO2Total / distance).ConvertToGrammPerKiloMeter(),
+				(CO2Total / distance / payload).ConvertToGrammPerTonKilometer(),
+				(CO2Total / distance / volume).ConvertToGrammPerCubicMeterKiloMeter(),
+			};
+		}
+
+		#endregion
+	}
+
+	public class BusCO2Writer : CO2WriterBase
+	{
+		public BusCO2Writer(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+
+		#region Overrides of FuelConsumptionWriterBase
+
+		protected override IList<ConvertedSI> GetFuelConsumption(Kilogram CO2Total, Meter distance, Kilogram payload, CubicMeter volume, double? passengers)
+		{
+			return new[] {
+				(CO2Total / distance).ConvertToGrammPerKiloMeter(),
+				(CO2Total / distance / passengers.Value).ConvertToGrammPerPassengerKilometer(),
+			};
+		}
+
+		#endregion
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/ElectricEnergyWriter.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/ElectricEnergyWriter.cs
new file mode 100644
index 0000000000..8f741e25e1
--- /dev/null
+++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/ElectricEnergyWriter.cs
@@ -0,0 +1,87 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+using TUGraz.VectoCommon.Resources;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile.CustomerInformationFile_0_9.
+	ResultWriter
+{
+
+	public abstract class ElectricEnergyConsumptionWriterBase : AbstractResultGroupWriter
+	{
+		public ElectricEnergyConsumptionWriterBase(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Overrides of AbstractResultWriter
+
+		public override XElement GetElement(IResultEntry entry)
+		{
+			return new XElement(Cif + "ElectricEnergy",
+				GetEnergyConsumption(entry.ElectricEnergyConsumption, entry.Distance, entry.Payload, entry.CargoVolume,
+					entry.PassengerCount).Select(x =>
+					new XElement(Cif + XMLNames.Report_Result_EnergyConsumption, XMLHelper.ValueAsUnit(x, 3, 1)))
+			);
+		}
+
+		public override XElement GetElement(IOVCResultEntry ovcEntry)
+		{
+			var entry = ovcEntry.Weighted;
+			return new XElement(Cif + "ElectricEnergy",
+				GetEnergyConsumption(entry.ElectricEnergyConsumption, entry.Distance, entry.Payload, entry.CargoVolume,
+					entry.PassengerCount).Select(x =>
+					new XElement(Cif + XMLNames.Report_Result_EnergyConsumption, XMLHelper.ValueAsUnit(x, 3, 1)))
+			);
+
+		}
+
+		protected abstract IList<ConvertedSI> GetEnergyConsumption(WattSecond elEnergy, Meter distance,
+			Kilogram payload, CubicMeter volume, double? passengers);
+
+		#endregion
+	}
+
+	public class LorryElectricEnergyConsumptionWriter : ElectricEnergyConsumptionWriterBase
+	{
+		public LorryElectricEnergyConsumptionWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Overrides of ElectricEnergyConsumptionWriterBase
+
+		protected override IList<ConvertedSI> GetEnergyConsumption(WattSecond elEnergy, Meter distance,
+			Kilogram payload, CubicMeter volume, double? passengers)
+		{
+			return new[] {
+				(elEnergy / distance).ConvertToKiloWattHourPerKiloMeter(),
+				(elEnergy / distance / payload).ConvertToKiloWattHourPerTonKiloMeter(),
+				(elEnergy / distance / volume).ConvertToKiloWattHourPerCubicMeterKiloMeter(),
+
+				(elEnergy / distance).ConvertToMegaJoulePerKiloMeter(),
+				(elEnergy / distance / payload).ConvertToMegaJoulePerTonKiloMeter(),
+				(elEnergy / distance / volume).ConvertToMegaJoulePerCubicMeterKiloMeter(),
+			};
+		}
+
+		#endregion
+	}
+
+	public class BusElectricEnergyConsumptionWriter : ElectricEnergyConsumptionWriterBase
+	{
+		public BusElectricEnergyConsumptionWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Overrides of ElectricEnergyConsumptionWriterBase
+
+		protected override IList<ConvertedSI> GetEnergyConsumption(WattSecond elEnergy, Meter distance,
+			Kilogram payload, CubicMeter volume, double? passengers)
+		{
+			return new[] {
+				(elEnergy / distance).ConvertToKiloWattHourPerKiloMeter(),
+				(elEnergy / distance / passengers.Value).ConvertToKiloWattHourPerPassengerKiloMeter(),
+
+				(elEnergy / distance).ConvertToMegaJoulePerKiloMeter(),
+				(elEnergy / distance / passengers.Value).ConvertToMegaJoulePerPassengerKiloMeter(),
+			};
+		}
+
+		#endregion
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/FuelConsumptionWriter.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/FuelConsumptionWriter.cs
new file mode 100644
index 0000000000..4a805402cf
--- /dev/null
+++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/FuelConsumptionWriter.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml.Linq;
+using TUGraz.VectoCommon.BusAuxiliaries;
+using TUGraz.VectoCommon.Models;
+using TUGraz.VectoCommon.Resources;
+using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile.CustomerInformationFile_0_9.ResultWriter
+{
+	public abstract class FuelConsumptionWriterBase : AbstractResultGroupWriter, IFuelConsumptionWriter
+	{
+		protected FuelConsumptionWriterBase(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Implementation of IFuelConsumptionWriter
+
+		public XElement GetElement(IResultEntry entry, IFuelConsumptionCorrection fc)
+		{
+			return new XElement(Cif + XMLNames.Report_Results_Fuel,
+				new XAttribute(XMLNames.Report_Results_Fuel_Type_Attr, fc.Fuel.FuelType.ToXMLFormat()),
+				GetFuelConsumption(fc.TotalFuelConsumptionCorrected, fc.Fuel, entry.Distance, entry.Payload, entry.CargoVolume, entry.PassengerCount).Select(x => new XElement(Cif + XMLNames.Report_Results_FuelConsumption, XMLHelper.ValueAsUnit(x, 3, 1)))
+			);
+		}
+
+		public XElement GetElement(IWeightedResult entry, IFuelProperties fuel, Kilogram consumption)
+		{
+			return new XElement(Cif + XMLNames.Report_Results_Fuel,
+				new XAttribute(XMLNames.Report_Results_Fuel_Type_Attr, fuel.FuelType.ToXMLFormat()),
+				GetFuelConsumption(consumption, fuel, entry.Distance, entry.Payload, entry.CargoVolume, entry.PassengerCount).Select(x => new XElement(Cif + XMLNames.Report_Results_FuelConsumption, XMLHelper.ValueAsUnit(x, 3, 1)))
+			);
+		}
+
+		protected abstract IList<ConvertedSI> GetFuelConsumption(Kilogram fc,
+			IFuelProperties fuel, Meter distance, Kilogram payload, CubicMeter volume,
+			double? passenger);
+
+		#endregion
+
+		#region Overrides of AbstractResultWriter
+
+		public override XElement GetElement(IResultEntry entry)
+		{
+			throw new NotImplementedException();
+		}
+
+		#endregion
+
+	}
+
+	public class LorryFuelConsumptionWriter : FuelConsumptionWriterBase
+	{
+		public LorryFuelConsumptionWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+
+		#region Overrides of FuelConsumptionWriterBase
+
+		protected override IList<ConvertedSI> GetFuelConsumption(Kilogram fc, IFuelProperties fuel, Meter distance, Kilogram payload, CubicMeter volume, double? passenger)
+		{
+			var retVal =  new List<ConvertedSI> {
+				(fc / distance).ConvertToGrammPerKiloMeter(),
+				(fc / distance /payload).ConvertToGrammPerTonKilometer(),
+				(fc / distance / volume).ConvertToGrammPerCubicMeterKiloMeter(),
+
+				(fc * fuel.LowerHeatingValueVecto / distance).ConvertToMegaJoulePerKilometer(),
+				(fc * fuel.LowerHeatingValueVecto / distance / payload).ConvertToMegaJoulePerTonKiloMeter(),
+				(fc * fuel.LowerHeatingValueVecto / distance / volume).ConvertToMegaJoulePerCubicMeterKiloMeter(),
+			};
+
+			if (fuel.FuelDensity != null) {
+				retVal.AddRange(new[] {
+					(fc / fuel.FuelDensity / distance).ConvertToLiterPer100KiloMeter(),
+					(fc / fuel.FuelDensity / distance / payload).ConvertToLiterPerTonKiloMeter(),
+					(fc / fuel.FuelDensity / distance /volume).ConvertToLiterPerCubicMeterKiloMeter(),
+				});
+			}
+
+			return retVal;
+		}
+
+		#endregion
+	}
+
+	public class BusFuelConsumptionWriter : FuelConsumptionWriterBase
+	{
+		public BusFuelConsumptionWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+
+		#region Overrides of FuelConsumptionWriterBase
+
+		protected override IList<ConvertedSI> GetFuelConsumption(Kilogram fc, IFuelProperties fuel, Meter distance, Kilogram payload, CubicMeter volume, double? passenger)
+		{
+			var retVal = new List<ConvertedSI> {
+				(fc / distance).ConvertToGrammPerKiloMeter(),
+				(fc / distance / passenger.Value).ConvertToGrammPerPassengerKilometer(),
+
+				(fc * fuel.LowerHeatingValueVecto / distance).ConvertToMegaJoulePerKilometer(),
+				(fc * fuel.LowerHeatingValueVecto / distance / passenger.Value).ConvertToMegaJoulePerPassengerKilometer(),
+			};
+
+			if (fuel.FuelDensity != null) {
+				retVal.AddRange(new[] {
+					(fc / fuel.FuelDensity / distance).ConvertToLiterPer100KiloMeter(),
+					(fc / fuel.FuelDensity / distance / passenger.Value).ConvertToLiterPerPassengerKiloMeter(),
+				});
+			}
+
+			return retVal;
+		}
+
+		#endregion
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/IResultsWriter.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/IResultsWriter.cs
index ccf51c6b46..624cf0dba3 100644
--- a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/IResultsWriter.cs
+++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/IResultsWriter.cs
@@ -2,12 +2,15 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Xml.Linq;
+using TUGraz.VectoCommon.BusAuxiliaries;
 using TUGraz.VectoCommon.Exceptions;
 using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Resources;
 using TUGraz.VectoCommon.Utils;
+using TUGraz.VectoCore.Models.Declaration;
 using TUGraz.VectoCore.Models.Simulation.Data;
 using TUGraz.VectoCore.Models.Simulation.Impl;
+using TUGraz.VectoCore.Utils;
 
 namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile.CustomerInformationFile_0_9.ResultWriter
 {
@@ -20,26 +23,65 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 	{
 		XElement GetElement(IResultEntry entry);
 
-		XElement GetElement(Tuple<IResultEntry, IResultEntry> entry);
+		XElement GetElement(IOVCResultEntry entry);
 	}
 
 	public interface IFuelConsumptionWriter
 	{
 		XElement GetElement(IResultEntry entry, IFuelConsumptionCorrection fuelConsumptionCorrection);
+		XElement GetElement(IWeightedResult entry, IFuelProperties fuel, Kilogram consumption);
+
+	}
+
+	public interface ICO2Writer
+	{
+		XElement[] GetElement(IResultEntry entry);
+
+		XElement[] GetElement(IOVCResultEntry entry);
 	}
+
+	public interface ICifSummaryWriter
+	{
+		XElement GetElement(IList<IResultEntry> entries);
+
+		XElement GetElement(IList<IOVCResultEntry> entries);
+	}
+
+
 	public interface ICifResultsWriterFactory
 	{
+		IResultGroupWriter GetLorryOVCSuccessResultWriter();
 		IResultGroupWriter GetLorryOVCErrorResultWriter();
 
-		IResultGroupWriter GetLorryOVCSuccessResultWriter();
+		IResultGroupWriter GetBusOVCSuccessResultWriter();
+		IResultGroupWriter GetBusOVCErrorResultWriter();
+
 		IResultGroupWriter GetMissionWriter();
-		IResultGroupWriter GetSimulationParameterWriter();
+		IResultGroupWriter GetLorrySimulationParameterWriter();
 		IResultGroupWriter GetLorryOVCResultWriterChargeDepleting();
 		IResultGroupWriter GetLorryOVCResultWriterChargeSustaining();
+		IResultGroupWriter GetLorryOVCSummaryWriter();
 		IFuelConsumptionWriter GetFuelConsumptionLorry();
 		IResultGroupWriter GetElectricEnergyConsumptionLorry();
+		ICO2Writer GetCO2ResultLorry();
+
+		ICifSummaryWriter GetLorryOVCCifSummaryWriter();
+
+
+		IResultGroupWriter GetBusSimulationParameterWriter();
+		IResultGroupWriter GetBusOVCResultWriterChargeDepleting();
+		IResultGroupWriter GetBusOVCResultWriterChargeSustaining();
+		IResultGroupWriter GetBusOVCSummaryWriter();
+
+		IFuelConsumptionWriter GetFuelConsumptionBus();
+		IResultGroupWriter GetElectricEnergyConsumptionBus();
+		ICO2Writer GetCO2ResultBus();
+
+		ICifSummaryWriter GetBusOVCCifSummaryWriter();
+
 	}
 
+
 	public abstract class AbstractResultsWriter : IResultsWriter
 	{
 		protected static readonly XNamespace Cif = "urn:tugraz:ivt:VectoAPI:CustomerOutput:v0.9";
@@ -62,56 +104,64 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 
 		#endregion
 
-		protected List<Tuple<IResultEntry, IResultEntry>> GetOrderedResultsOVC(List<IResultEntry> results)
+		protected List<IOVCResultEntry> GetOrderedResultsOVC(List<IResultEntry> results)
 		{
 			if (!results.All(x => x.OVCMode.IsOneOf(VectoRunData.OvcHevMode.ChargeSustaining, VectoRunData.OvcHevMode.ChargeDepleting))) {
 				throw new VectoException(
 					"Simulation runs for OVC vehicles must be either Charge Sustaining or Charge Depleting!");
 			}
 
-			var retVal = new List<Tuple<IResultEntry, IResultEntry>>(results.Count / 2);
+			var retVal = new List<IOVCResultEntry>(results.Count / 2);
 			var cdEntries = results.Where(x => x.OVCMode == VectoRunData.OvcHevMode.ChargeSustaining)
 				.OrderBy(x => x.VehicleClass)
 				.ThenBy(x => x.FuelMode)
 				.ThenBy(x => x.Mission)
 				.ThenBy(x => x.LoadingType)
 				.ToList();
-			foreach (var entry in cdEntries) {
-				var match = results.FirstOrDefault(x => x.OVCMode != entry.OVCMode &&
-														x.VehicleClass == entry.VehicleClass &&
-														x.FuelMode == entry.FuelMode &&
-														x.Mission == entry.Mission &&
-														x.LoadingType == entry.LoadingType);
-				if (match == null) {
+			foreach (var cdEntry in cdEntries) {
+				var csEntry = results.FirstOrDefault(x => x.OVCMode != cdEntry.OVCMode &&
+														x.VehicleClass == cdEntry.VehicleClass &&
+														x.FuelMode == cdEntry.FuelMode &&
+														x.Mission == cdEntry.Mission &&
+														x.LoadingType == cdEntry.LoadingType);
+				if (csEntry == null) {
 					throw new VectoException(
-						$"no matching result for {entry.Mission}, {entry.LoadingType}, {entry.FuelMode} found!");
+						$"no matching result for {cdEntry.Mission}, {cdEntry.LoadingType}, {cdEntry.FuelMode} found!");
 				}
-				retVal.Add(Tuple.Create(entry, match));
-			}
-			return retVal;
-		}
 
-		protected XElement GetSummary(List<Tuple<IResultEntry, IResultEntry>> orderedResults)
-		{
-			var allSuccess = orderedResults.All(x =>
-				x.Item1.Status == VectoRun.Status.Success && x.Item2.Status == VectoRun.Status.Success);
-			if (!allSuccess) {
-				// do not write summary unless all simulation runs are successful!
-				return null;
+				var combined = new OvcResultEntry() {
+					ChargeSustainingResult = csEntry,
+					ChargeDepletingResult = cdEntry,
+					Weighted = DeclarationData.CalculateWeightedResult(cdEntry, csEntry)
+				};
+				retVal.Add(combined);
 			}
-			//throw new NotImplementedException();
-			return null;
+			return retVal;
 		}
 
-		protected XElement GetSummary(List<IResultEntry> results)
-		{
-			var allSuccess = results.All(x => x.Status == VectoRun.Status.Success);
-			if (!allSuccess) {
-				// do not write summary unless all simulation runs are successful!
-				return null;
-			}
-			throw new NotImplementedException();
-		}
+		//protected XElement GetSummary(List<IOVCResultEntry> orderedResults)
+		//{
+		//	var allSuccess = orderedResults.All(x =>
+		//		x.ChargeDepletingResult.Status == VectoRun.Status.Success && x.ChargeSustainingResult.Status == VectoRun.Status.Success);
+		//	if (!allSuccess) {
+		//		// do not write summary unless all simulation runs are successful!
+		//		return null;
+		//	}
+
+		//	return null;
+		//	//return new XElement(Cif + "Summary", 
+		//	//	new XElement(Cif + XMLNames.Report_ResultEntry_AverageSpeed, XMLHelper.ValueAsUnit()))
+		//}
+
+		//protected XElement GetSummary(List<IResultEntry> results)
+		//{
+		//	var allSuccess = results.All(x => x.Status == VectoRun.Status.Success);
+		//	if (!allSuccess) {
+		//		// do not write summary unless all simulation runs are successful!
+		//		return null;
+		//	}
+		//	throw new NotImplementedException();
+		//}
 	}
 
 	public class CIFResultsWriter
@@ -137,10 +187,12 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 				return new XElement(Cif + "Results",
 					new XElement(Cif + XMLNames.Report_Result_Status, allSuccess ? "success" : "error"),
 					ordered.Select(x =>
-						x.Item1.Status == VectoRun.Status.Success && x.Item2.Status == VectoRun.Status.Success
+						x.ChargeDepletingResult.Status == VectoRun.Status.Success &&
+						x.ChargeSustainingResult.Status == VectoRun.Status.Success
 							? _cifFactory.GetLorryOVCSuccessResultWriter().GetElement(x)
 							: _cifFactory.GetLorryOVCErrorResultWriter().GetElement(x)),
-					GetSummary(ordered));
+					_cifFactory.GetLorryOVCCifSummaryWriter().GetElement(ordered)
+				);
 			}
 
 			
@@ -168,6 +220,21 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 		public class HEVOVCBus : AbstractResultsWriter
 		{
 			public HEVOVCBus(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+			public override XElement GenerateResults(List<IResultEntry> results)
+			{
+				var ordered = GetOrderedResultsOVC(results);
+				var allSuccess = results.All(x => x.Status == VectoRun.Status.Success);
+				return new XElement(Cif + "Results",
+					new XElement(Cif + XMLNames.Report_Result_Status, allSuccess ? "success" : "error"),
+					ordered.Select(x =>
+						x.ChargeDepletingResult.Status == VectoRun.Status.Success &&
+						x.ChargeSustainingResult.Status == VectoRun.Status.Success
+							? _cifFactory.GetBusOVCSuccessResultWriter().GetElement(x)
+							: _cifFactory.GetBusOVCErrorResultWriter().GetElement(x)),
+					_cifFactory.GetBusOVCCifSummaryWriter().GetElement(ordered)
+				);
+			}
 		}
 
 		public class PEVBus : AbstractResultsWriter
diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/ResultGoupWriter.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/ResultGoupWriter.cs
index 16fb1ba350..136c2c8a26 100644
--- a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/ResultGoupWriter.cs
+++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/CustomerInformationFile_0_9/ResultWriter/ResultGoupWriter.cs
@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Xml.Linq;
+using TUGraz.VectoCommon.BusAuxiliaries;
 using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Resources;
 using TUGraz.VectoCommon.Utils;
@@ -13,8 +14,7 @@ using TUGraz.VectoCore.Utils;
 namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile.CustomerInformationFile_0_9.
 	ResultWriter
 {
-
-	public abstract class AbstractResultWriter : IResultGroupWriter
+	public abstract class AbstractResultWriter
 	{
 		protected static readonly XNamespace Cif = "urn:tugraz:ivt:VectoAPI:CustomerOutput:v0.9";
 		protected static readonly XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
@@ -25,46 +25,33 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 		{
 			_cifFactory = cifFactory;
 		}
+	}
+
+
+
+    public abstract class AbstractResultGroupWriter : AbstractResultWriter, IResultGroupWriter
+	{
+		protected AbstractResultGroupWriter(ICifResultsWriterFactory cifFactory): base(cifFactory) {}
 
 		#region Implementation of IResultGroupWriter
 
 		public abstract XElement GetElement(IResultEntry entry);
 
-		public virtual XElement GetElement(Tuple<IResultEntry, IResultEntry> entry)
+		public virtual XElement GetElement(IOVCResultEntry entry)
 		{
 			throw new NotImplementedException();
 		}
 
-		#endregion
-
-		protected XElement[] GetCO2Lorry(IResultEntry entry)
-		{
-			return new[] {
-				new XElement(Cif + XMLNames.Report_Results_CO2,
-					new XAttribute(XMLNames.Report_Results_Unit_Attr, "g/km"),
-					(entry.CO2Total / entry.Distance).ConvertToGrammPerKiloMeter().ToMinSignificantDigits(3, 2)),
-				new XElement(Cif + XMLNames.Report_Results_CO2,
-					new XAttribute(XMLNames.Report_Results_Unit_Attr, "g/km"),
-					(entry.CO2Total / entry.Distance / entry.Payload).ConvertToGrammPerTonKilometer().ToMinSignificantDigits(3, 2)),
-				new XElement(Cif + XMLNames.Report_Results_CO2,
-					new XAttribute(XMLNames.Report_Results_Unit_Attr, "g/km"),
-					(entry.CO2Total / entry.Distance / entry.CargoVolume).ConvertToGrammPerCubicMeterKiloMeter().ToMinSignificantDigits(3, 2)),
-			};
-		}
+        #endregion
 	}
 
-	public class ErrorResultWriter : AbstractResultWriter
+	public class ErrorResultWriter : AbstractResultGroupWriter
 	{
 		public ErrorResultWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
 
 
 		#region Overrides of AbstractResultWriter
 
-		// <n1:Mission>longhaul</n1:Mission>
-		//<n1:SimulationParameters>
-		//<TotalVehicleMass unit = "kg" > 7800 </ TotalVehicleMass >
-		//< Payload unit="kg">2300</Payload>
-		//</n1:SimulationParameters>
 		public override XElement GetElement(IResultEntry entry)
 		{
 			if (entry.Status == VectoRun.Status.Success) {
@@ -74,15 +61,15 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 				new XAttribute(XMLNames.Report_Result_Status_Attr, "error"),
 				new XAttribute(xsi + "type", "ResultErrorType"),
 				_cifFactory.GetMissionWriter().GetElement(entry),
-				_cifFactory.GetSimulationParameterWriter().GetElement(entry),
+				_cifFactory.GetLorrySimulationParameterWriter().GetElement(entry),
 				new XElement(Cif + XMLNames.Report_Results_Error, entry.Error),
 				new XElement(Cif + XMLNames.Report_Results_ErrorDetails, entry.StackTrace)
 				);
 		}
 
-		public override XElement GetElement(Tuple<IResultEntry, IResultEntry> entry)
+		public override XElement GetElement(IOVCResultEntry entry)
 		{
-			var errorEntry = new[] {entry.Item1, entry.Item2}.FirstOrDefault(x => x.Status != VectoRun.Status.Success);
+			var errorEntry = new[] {entry.ChargeSustainingResult, entry.ChargeDepletingResult}.FirstOrDefault(x => x.Status != VectoRun.Status.Success);
 			if (errorEntry == null) {
 				throw new Exception("At least one entry needs to be unsuccessful!");
 			}
@@ -90,7 +77,7 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 				new XAttribute(XMLNames.Report_Result_Status_Attr, "error"),
 				new XAttribute(xsi + "type", "ResultErrorType"),
 				_cifFactory.GetMissionWriter().GetElement(errorEntry),
-				_cifFactory.GetSimulationParameterWriter().GetElement(errorEntry),
+				_cifFactory.GetLorrySimulationParameterWriter().GetElement(errorEntry),
 				new XElement(Cif + XMLNames.Report_Results_Error, errorEntry.Error),
 				new XElement(Cif + XMLNames.Report_Results_ErrorDetails, errorEntry.StackTrace)
 			);
@@ -99,7 +86,7 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 		#endregion
 	}
 
-	public class ResultMissionWriter : AbstractResultWriter
+	public class ResultMissionWriter : AbstractResultGroupWriter
 	{
 		public ResultMissionWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
 
@@ -113,7 +100,7 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 		#endregion
 	}
 
-	public class ResultSimulationParameterLorryWriter : AbstractResultWriter
+	public class ResultSimulationParameterLorryWriter : AbstractResultGroupWriter
 	{
 		public ResultSimulationParameterLorryWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
 
@@ -131,7 +118,7 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 		#endregion
 	}
 
-	public class LorryOVCResultWriter : AbstractResultWriter
+	public class LorryOVCResultWriter : AbstractResultGroupWriter
 	{
 
 		public LorryOVCResultWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
@@ -143,24 +130,24 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 			throw new NotImplementedException();
 		}
 
-		public override XElement GetElement(Tuple<IResultEntry, IResultEntry> entry)
+		public override XElement GetElement(IOVCResultEntry entry)
 		{
-			var cs = new[] { entry.Item1, entry.Item2 }.FirstOrDefault(x => x.OVCMode == VectoRunData.OvcHevMode.ChargeSustaining);
-			var cd = new[] { entry.Item1, entry.Item2 }.FirstOrDefault(x => x.OVCMode == VectoRunData.OvcHevMode.ChargeDepleting);
 			return new XElement(Cif + XMLNames.Report_Result_Result,
 				new XAttribute(XMLNames.Report_Result_Status_Attr, "success"),
 				new XAttribute(xsi + "type", "ResultSuccessOVCHEVType"),
-				_cifFactory.GetMissionWriter().GetElement(entry.Item1),
-				_cifFactory.GetSimulationParameterWriter().GetElement(entry.Item1),
-				_cifFactory.GetLorryOVCResultWriterChargeDepleting().GetElement(cd),
-				_cifFactory.GetLorryOVCResultWriterChargeSustaining().GetElement(cs)
+				_cifFactory.GetMissionWriter().GetElement(entry.ChargeDepletingResult),
+				_cifFactory.GetLorrySimulationParameterWriter().GetElement(entry.ChargeDepletingResult),
+				_cifFactory.GetLorryOVCResultWriterChargeDepleting().GetElement(entry.ChargeDepletingResult),
+				_cifFactory.GetLorryOVCResultWriterChargeSustaining().GetElement(entry.ChargeSustainingResult),
+				_cifFactory.GetLorryOVCSummaryWriter().GetElement(entry)
 			);
 		}
 
 		#endregion
 	}
 
-	public class LorryOVCChargeDepletingWriter : AbstractResultWriter
+
+	public class LorryOVCChargeDepletingWriter : AbstractResultGroupWriter
 	{
 		public LorryOVCChargeDepletingWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
 
@@ -174,7 +161,7 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 				entry.FuelData.Select(f =>
 					_cifFactory.GetFuelConsumptionLorry().GetElement(entry, entry.FuelConsumptionFinal(f.FuelType))),
 				_cifFactory.GetElectricEnergyConsumptionLorry().GetElement(entry),
-				GetCO2Lorry(entry)
+				_cifFactory.GetCO2ResultLorry().GetElement(entry)
 			);
 		}
 
@@ -182,7 +169,7 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 		#endregion
 	}
 
-	public class LorryOVCChargeSustainingWriter : AbstractResultWriter
+	public class LorryOVCChargeSustainingWriter : AbstractResultGroupWriter
 	{
 		public LorryOVCChargeSustainingWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
 
@@ -195,64 +182,233 @@ namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformation
 				new XElement(Cif + XMLNames.Report_ResultEntry_AverageSpeed, XMLHelper.ValueAsUnit(entry.AverageSpeed, XMLNames.Unit_kmph, 1)),
 				entry.FuelData.Select(f =>
 					_cifFactory.GetFuelConsumptionLorry().GetElement(entry, entry.FuelConsumptionFinal(f.FuelType))),
-				GetCO2Lorry(entry)
+				_cifFactory.GetCO2ResultLorry().GetElement(entry)
+			//GetCO2Result(entry)
 			);
 		}
 
 		#endregion
 	}
 
-	public class LorryFuelConsumptionWriter : AbstractResultWriter, IFuelConsumptionWriter
+
+	public abstract class OVCTotalWriterBase : AbstractResultGroupWriter
 	{
-		public LorryFuelConsumptionWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+		protected OVCTotalWriterBase(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
 
-		#region Implementation of IFuelConsumptionWriter
+		#region Overrides of AbstractResultWriter
 
-		public XElement GetElement(IResultEntry entry, IFuelConsumptionCorrection fc)
+		public override XElement GetElement(IResultEntry entry)
 		{
-			return new XElement(Cif + XMLNames.Report_Results_Fuel,
-				new XAttribute(XMLNames.Report_Results_Fuel_Type_Attr, fc.Fuel.FuelType.ToXMLFormat()),
-				new XElement(Cif + XMLNames.Report_Results_FuelConsumption,
-					XMLHelper.ValueAsUnit(
-						(fc.TotalFuelConsumptionCorrected / entry.Distance).ConvertToGrammPerKiloMeter(), 3, 1)
-				),
-				new XElement(Cif + XMLNames.Report_Results_FuelConsumption,
-					XMLHelper.ValueAsUnit(
-						(fc.TotalFuelConsumptionCorrected / entry.Distance / entry.Payload)
-						.ConvertToGrammPerTonKilometer(), 3, 1)
-				),
-				new XElement(Cif + XMLNames.Report_Results_FuelConsumption,
-					XMLHelper.ValueAsUnit(
-						(fc.TotalFuelConsumptionCorrected / entry.Distance / entry.CargoVolume)
-						.ConvertToGrammPerCubicMeterKiloMeter(), 3, 1)
-				)
+			throw new NotImplementedException();
+		}
+
+		public override XElement GetElement(IOVCResultEntry entry)
+		{
+			var total = entry.Weighted;
+			return new XElement(Cif + "Total",
+				new XElement(Cif + XMLNames.Report_ResultEntry_AverageSpeed,
+					XMLHelper.ValueAsUnit(total.AverageSpeed, "km/h", 1)),
+				GetFuelConsumption(entry), 
+				GetElectricConsumption(entry),
+				GetCO2(entry),
+				new XElement(Cif + "ActualChargeDepletingRange",
+					XMLHelper.ValueAsUnit(total.ActualChargeDepletingRange.ConvertToKiloMeter())),
+				new XElement(Cif + "EquivalentAllElectricRange",
+					XMLHelper.ValueAsUnit(total.EquivalentAllElectricRange.ConvertToKiloMeter())),
+				new XElement(Cif + "ZeroCO2EmissionsRange",
+					XMLHelper.ValueAsUnit(total.ZeroCO2EmissionsRange.ConvertToKiloMeter())),
+				new XElement(Cif + "UtilityFactor", total.UtilityFactor.ToXMLFormat(3))
 			);
 		}
 
+		protected abstract XElement[] GetFuelConsumption(IOVCResultEntry entry);
+
 		#endregion
 
-		#region Overrides of AbstractResultWriter
+		protected abstract XElement GetElectricConsumption(IOVCResultEntry entry);
+
+		protected abstract XElement[] GetCO2(IOVCResultEntry entry);
+
+	}
+
+	public class LorryOVCTotalWriter : OVCTotalWriterBase
+	{
+		public LorryOVCTotalWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Overrides of OVCSummaryWriterBase
+
+		protected override XElement[] GetFuelConsumption(IOVCResultEntry entry)
+		{
+			return entry.Weighted.FuelConsumption.Select(e =>
+					_cifFactory.GetFuelConsumptionLorry().GetElement(entry.Weighted, e.Key, e.Value)).ToArray();
+		}
+
+		protected override XElement GetElectricConsumption(IOVCResultEntry entry)
+		{
+			return _cifFactory.GetElectricEnergyConsumptionLorry().GetElement(entry);
+		}
+
+		protected override XElement[] GetCO2(IOVCResultEntry entry)
+		{
+			return _cifFactory.GetCO2ResultLorry().GetElement(entry);
+		}
+
+		#endregion
+	}
+
+
+	public abstract class CifSummaryWriterBase : AbstractResultWriter, ICifSummaryWriter
+	{
+		protected CifSummaryWriterBase(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Implementation of ICifSummaryWriter
+
+		public XElement GetElement(IList<IResultEntry> entries)
+		{
+			var weighted = DeclarationData.CalculateWeightedSummary(entries);
+			//return new XElement(
+			//	GetSummary(weighted),
+			//	weighted.FuelConsumption.Select(x => _cifFactory.GetFuelConsumptionLorry().GetElement(weighted, x.Key, x.Value)),
+			//	_cifFactory.GetElectricEnergyConsumptionLorry().GetElement(weighted),
+			//	_cifFactory.GetCO2ResultLorry().GetElement(weighted),
+			//	);
+			return null;
+		}
+
+		public XElement GetElement(IList<IOVCResultEntry> entries)
+		{
+			return null;
+		}
+
+		#endregion
+	}
+
+	public class LorryOVCCifSummaryWriter : CifSummaryWriterBase
+	{
+		public LorryOVCCifSummaryWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+	}
+
+
+	// -----------------
+	// bus
+
+	public class BusOVCTotalWriter : AbstractResultGroupWriter
+	{
+
+		public BusOVCTotalWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Implementation of IResultGroupWriter
 
 		public override XElement GetElement(IResultEntry entry)
 		{
 			throw new NotImplementedException();
 		}
 
+		public override XElement GetElement(IOVCResultEntry entry)
+		{
+			return new XElement(Cif + XMLNames.Report_Result_Result,
+				new XAttribute(XMLNames.Report_Result_Status_Attr, "success"),
+				new XAttribute(xsi + "type", "ResultSuccessOVCHEVType"),
+				_cifFactory.GetMissionWriter().GetElement(entry.ChargeDepletingResult),
+				_cifFactory.GetBusSimulationParameterWriter().GetElement(entry.ChargeDepletingResult),
+				_cifFactory.GetBusOVCResultWriterChargeDepleting().GetElement(entry.ChargeDepletingResult),
+				_cifFactory.GetBusOVCResultWriterChargeSustaining().GetElement(entry.ChargeSustainingResult),
+				_cifFactory.GetBusOVCSummaryWriter().GetElement(entry)
+			);
+		}
+
 		#endregion
 	}
 
-	public class LorryElectricEnergyConsumptionWriter : AbstractResultWriter
+	public class ResultSimulationParameterBusWriter : AbstractResultGroupWriter
 	{
-		public LorryElectricEnergyConsumptionWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+		public ResultSimulationParameterBusWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
 
 		#region Overrides of AbstractResultWriter
 
 		public override XElement GetElement(IResultEntry entry)
 		{
-			return null;
+			return new XElement(Cif + XMLNames.Report_ResultEntry_SimulationParameters,
+				new XElement(Cif + XMLNames.Report_ResultEntry_TotalVehicleMass,
+					XMLHelper.ValueAsUnit(entry.TotalVehicleMass, XMLNames.Unit_kg)),
+				new XElement(Cif + XMLNames.Report_Result_MassPassengers,
+					XMLHelper.ValueAsUnit(entry.Payload, XMLNames.Unit_kg)),
+				new XElement(Cif + XMLNames.Report_Result_PassengerCount,
+					(entry.PassengerCount ?? double.NaN).ToXMLFormat(2))
+			);
+		}
+
+		#endregion
+	}
+
+	public class BusOVCChargeDepletingWriter : AbstractResultGroupWriter
+	{
+		public BusOVCChargeDepletingWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Overrides of AbstractResultWriter
+
+		public override XElement GetElement(IResultEntry entry)
+		{
+			return new XElement(Cif + "OVCMode",
+				new XAttribute("type", "charge depleting"),
+				new XElement(Cif + XMLNames.Report_ResultEntry_AverageSpeed, XMLHelper.ValueAsUnit(entry.AverageSpeed, XMLNames.Unit_kmph, 1)),
+				entry.FuelData.Select(f =>
+					_cifFactory.GetFuelConsumptionBus().GetElement(entry, entry.FuelConsumptionFinal(f.FuelType))),
+				_cifFactory.GetElectricEnergyConsumptionBus().GetElement(entry),
+				_cifFactory.GetCO2ResultBus().GetElement(entry)
+			);
+		}
+		#endregion
+	}
+
+	public class BusOVCChargeSustainingWriter : AbstractResultGroupWriter
+	{
+		public BusOVCChargeSustainingWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Overrides of AbstractResultWriter
+
+		public override XElement GetElement(IResultEntry entry)
+		{
+			return new XElement(Cif + "OVCMode",
+				new XAttribute("type", "charge depleting"),
+				new XElement(Cif + XMLNames.Report_ResultEntry_AverageSpeed, XMLHelper.ValueAsUnit(entry.AverageSpeed, XMLNames.Unit_kmph, 1)),
+				entry.FuelData.Select(f =>
+					_cifFactory.GetFuelConsumptionBus().GetElement(entry, entry.FuelConsumptionFinal(f.FuelType))),
+				_cifFactory.GetCO2ResultBus().GetElement(entry)
+			);
 		}
 
 		#endregion
 	}
+
+	public class BusOVCSummaryWriter : OVCTotalWriterBase
+	{
+		public BusOVCSummaryWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+
+		#region Overrides of OVCSummaryWriterBase
+
+		protected override XElement[] GetFuelConsumption(IOVCResultEntry entry)
+		{
+			return entry.Weighted.FuelConsumption.Select(e =>
+				_cifFactory.GetFuelConsumptionBus().GetElement(entry.Weighted, e.Key, e.Value)).ToArray();
+		}
+
+		protected override XElement GetElectricConsumption(IOVCResultEntry entry)
+		{
+			return _cifFactory.GetElectricEnergyConsumptionBus().GetElement(entry);
+		}
+
+		protected override XElement[] GetCO2(IOVCResultEntry entry)
+		{
+			return _cifFactory.GetCO2ResultBus().GetElement(entry);
+		}
+
+		#endregion
+	}
+
+	public class BusOVCCifSummaryWriter : CifSummaryWriterBase
+	{
+		public BusOVCCifSummaryWriter(ICifResultsWriterFactory cifFactory) : base(cifFactory) { }
+	}
 }
 
diff --git a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs
index 345942aba5..9a9ab06805 100644
--- a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs
+++ b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs
@@ -100,7 +100,9 @@ namespace TUGraz.VectoCore.OutputData.XML
 				return CorrectedFinalFuelConsumption[fuelType];
 			}
 
-            public Kilogram CO2Total { get; private set; }
+			public WattSecond ElectricEnergyConsumption { get; private set; }
+
+			public Kilogram CO2Total { get; private set; }
 
 			public Dictionary<FuelType, IFuelConsumptionCorrection> CorrectedFinalFuelConsumption { get; private set; }
 
@@ -175,9 +177,11 @@ namespace TUGraz.VectoCore.OutputData.XML
 
 				CorrectedFinalFuelConsumption = data.CorrectedModalData.FuelCorrection;
 				CO2Total = data.CorrectedModalData.CO2Total;
-				EnergyConsumptionTotal = data.CorrectedModalData.EnergyConsumptionTotal;
+				EnergyConsumptionTotal = data.CorrectedModalData.FuelEnergyConsumptionTotal;
+				ElectricEnergyConsumption = data.CorrectedModalData.ElectricEnergyConsumption;
+
 
-				var gbxOutSignal = runData.Retarder.Type == RetarderType.TransmissionOutputRetarder
+                var gbxOutSignal = runData.Retarder.Type == RetarderType.TransmissionOutputRetarder
 					? ModalResultField.P_retarder_in
 					: (runData.AngledriveData == null ? ModalResultField.P_axle_in : ModalResultField.P_angle_in);
 				var eGbxIn = data.TimeIntegral<WattSecond>(ModalResultField.P_gbx_in, x => x > 0);
diff --git a/VectoCore/VectoCoreTest/Reports/TestXMLResultsWriting.cs b/VectoCore/VectoCoreTest/Reports/TestXMLResultsWriting.cs
index 96c6afebec..155d37952a 100644
--- a/VectoCore/VectoCoreTest/Reports/TestXMLResultsWriting.cs
+++ b/VectoCore/VectoCoreTest/Reports/TestXMLResultsWriting.cs
@@ -110,6 +110,55 @@ public class TestXMLResultsWriting
 		Assert.IsTrue(validator.ValidateXML(XmlDocumentType.CustomerReport), validator.ValidationError);
 	}
 
+
+	[
+		TestCase(VectoSimulationJobType.ParallelHybridVehicle, true, false, false, TestName = "ReportResult_WritingResults: CompletedBus HEV OVC ERROR"),
+
+		TestCase(VectoSimulationJobType.ParallelHybridVehicle, true, false, true, TestName = "ReportResult_WritingResults: CompletedBus HEV OVC"),
+		TestCase(VectoSimulationJobType.ParallelHybridVehicle, true, true, true, TestName = "ReportResult_WritingResults: CompletedBus HEV exempted"),
+	]
+	public void TestReportResult_WritingResults_CompletedBus(VectoSimulationJobType jobType, bool ovc, bool exempted, bool success)
+	{
+		var vehicleCategory = VehicleCategory.HeavyBusCompletedVehicle;
+		var ovcmode = ovc ? VectoRunData.OvcHevMode.ChargeDepleting : VectoRunData.OvcHevMode.NotApplicable;
+		var runData = GetMockRunData(vehicleCategory, jobType, ovc, exempted, ovcmode);
+		var modData = GetMockModData(success ? VectoRun.Status.Success : VectoRun.Status.Aborted);
+
+		var resultEntries = new List<IResultEntry>();
+
+		var resultEntry = GetResultEntry(runData);
+		resultEntry.SetResultData(runData, modData, 1);
+		resultEntries.Add(resultEntry);
+
+		if (ovc) {
+			var run2 = GetMockRunData(vehicleCategory, jobType, true, exempted, VectoRunData.OvcHevMode.ChargeSustaining);
+			var res2 = GetResultEntry(run2);
+			res2.SetResultData(run2, modData, 1);
+			resultEntries.Add(res2);
+		}
+
+		var resultsWriter = _reportResultsFactory.GetCIFResultsWriter(
+			runData.VehicleData.VehicleCategory.GetVehicleType(),
+			runData.JobType, runData.VehicleData.OffVehicleCharging, runData.Exempted);
+
+		var results = resultsWriter.GenerateResults(resultEntries);
+
+		Assert.NotNull(results);
+
+		var doc = CreateXmlDocument(results);
+		var validator = GetValidator(doc);
+
+		var m = new MemoryStream();
+		var writer = new XmlTextWriter(m, Encoding.UTF8) { Formatting = Formatting.Indented };
+		doc.WriteTo(writer);
+		writer.Flush();
+		m.Flush();
+		m.Seek(0, SeekOrigin.Begin);
+		Console.WriteLine(new StreamReader(m).ReadToEnd());
+
+		Assert.IsTrue(validator.ValidateXML(XmlDocumentType.CustomerReport), validator.ValidationError);
+	}
+
 	private static XMLDeclarationReport.ResultEntry GetResultEntry(VectoRunData runData)
 	{
 		var resultEntry = new XMLDeclarationReport.ResultEntry() {
@@ -121,6 +170,7 @@ public class TestXMLResultsWriting
 			TotalVehicleMass = runData.VehicleData.TotalVehicleMass,
 			CargoVolume = runData.VehicleData.CargoVolume,
 			VehicleClass = runData.VehicleData.VehicleClass,
+			PassengerCount = runData.VehicleData.PassengerCount,
 		};
 		return resultEntry;
 	}
@@ -180,8 +230,10 @@ public class TestXMLResultsWriting
 
 		fc.Setup(x => x.Fuel).Returns(FuelData.Diesel);
 		fc.Setup(x => x.TotalFuelConsumptionCorrected).Returns(31.SI<Kilogram>());
+		fc.Setup(x => x.EnergyDemand).Returns(31.SI<Kilogram>() * FuelData.Diesel.LowerHeatingValueVecto);
 		mc.Setup(x => x.CO2Total).Returns(20.SI<Kilogram>());
-		mc.Setup(x => x.EnergyConsumptionTotal).Returns(1e9.SI<Joule>());
+		mc.Setup(x => x.FuelEnergyConsumptionTotal).Returns(1e9.SI<Joule>());
+		mc.Setup(x => x.ElectricEnergyConsumption).Returns(200.SI(Unit.SI.Mega.Joule).Cast<WattSecond>());
 
 
 
@@ -203,6 +255,7 @@ public class TestXMLResultsWriting
 				CurbMass = 7600.SI<Kilogram>(),
 				Loading = 5000.SI<Kilogram>(),
 				CargoVolume = 20.SI<CubicMeter>(),
+				PassengerCount = 20,
 				VehicleClass = VehicleClass.Class5,
 				VehicleCategory = vehicleCategory,
 				OffVehicleCharging = offVehicleCharging
@@ -219,7 +272,6 @@ public class TestXMLResultsWriting
 			Retarder = new RetarderData() {
 				Type = RetarderType.None,
 			},
-			
 		};
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCoreTest/Utils/ConvertedSITest.cs b/VectoCore/VectoCoreTest/Utils/ConvertedSITest.cs
new file mode 100644
index 0000000000..0e7fde04d6
--- /dev/null
+++ b/VectoCore/VectoCoreTest/Utils/ConvertedSITest.cs
@@ -0,0 +1,196 @@
+using NUnit.Framework;
+using TUGraz.VectoCommon.Utils;
+
+namespace TUGraz.VectoCore.Tests.Utils;
+
+[TestFixture]
+[Parallelizable(ParallelScope.All)]
+public class ConvertedSITest
+{
+
+	[Test]
+	public void ConvertedSITest_ConvertToLiterPer100KiloMeter()
+	{
+		var fcLiter = 5.0;
+		var distanceKm = 100.0;
+		CubicMeter fc = fcLiter.SI(Unit.SI.Liter).Cast<CubicMeter>();
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+
+		var converted = (fc / distance).ConvertToLiterPer100KiloMeter();
+
+		Assert.AreEqual(fcLiter / distanceKm * 100, converted.Value, 1e-6);
+		Assert.AreEqual("l/100km", converted.Units);
+	}
+
+	[Test]
+	public void ConvertedSITest_ConvertToLiterPerTonKiloMeter()
+	{
+		var fcLiter = 5.0;
+		var distanceKm = 100.0;
+		var payloadTon = 2;
+		CubicMeter fc = fcLiter.SI(Unit.SI.Liter).Cast<CubicMeter>();
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+		Kilogram payload = payloadTon.SI(Unit.SI.Ton).Cast<Kilogram>();
+
+		var converted = (fc / distance / payload).ConvertToLiterPerTonKiloMeter();
+
+		Assert.AreEqual(fcLiter / distanceKm / payloadTon, converted.Value, 1e-6);
+		Assert.AreEqual("l/t-km", converted.Units);
+	}
+
+	[Test]
+	public void ConvertedSITest_ConvertToLiterPerCubicMeterKiloMeter()
+	{
+		var fcLiter = 5.0;
+		var distanceKm = 100.0;
+		var cargo = 10;
+		CubicMeter fc = fcLiter.SI(Unit.SI.Liter).Cast<CubicMeter>();
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+		CubicMeter cargoVolume = cargo.SI(Unit.SI.Cubic.Meter).Cast<CubicMeter>();
+
+		var converted = (fc / distance / cargoVolume).ConvertToLiterPerCubicMeterKiloMeter();
+
+		Assert.AreEqual(fcLiter / distanceKm / cargo, converted.Value, 1e-6);
+		Assert.AreEqual("l/m³-km", converted.Units);
+	}
+
+	[Test]
+	public void ConvertedSITest_J_ConvertToMegaJoulePerCubicMeterKiloMeter()
+	{
+		var ecMj = 200.0;
+		var distanceKm = 100.0;
+		var cargo = 10;
+		Joule ec = ecMj.SI(Unit.SI.Mega.Joule).Cast<Joule>();
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+		CubicMeter cargoVolume = cargo.SI(Unit.SI.Cubic.Meter).Cast<CubicMeter>();
+
+		var converted = (ec / distance / cargoVolume).ConvertToMegaJoulePerCubicMeterKiloMeter();
+
+		Assert.AreEqual(ecMj / distanceKm / cargo, converted.Value, 1e-6);
+		Assert.AreEqual("MJ/m³-km", converted.Units);
+	}
+
+	[Test]
+	public void ConvertedSITest_ConvertToMegaJoulePerTonKiloMeter()
+	{
+		var ecMj = 200.0;
+		var distanceKm = 100.0;
+		var payloadTon = 2.5;
+		Joule ec = ecMj.SI(Unit.SI.Mega.Joule).Cast<Joule>();
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+		Kilogram payload = payloadTon.SI(Unit.SI.Ton).Cast<Kilogram>();
+
+		var converted = (ec / distance / payload).ConvertToMegaJoulePerTonKiloMeter();
+
+		Assert.AreEqual(ecMj / distanceKm / payloadTon, converted.Value, 1e-6);
+		Assert.AreEqual("MJ/t-km", converted.Units);
+	}
+
+	[Test]
+	public void ConvertedSITest_ConvertToMegaJoulePerKilometer()
+	{
+		var ecMj = 200.0;
+		var distanceKm = 100.0;
+		Joule ec = ecMj.SI(Unit.SI.Mega.Joule).Cast<Joule>();
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+
+		var converted = (ec / distance).ConvertToMegaJoulePerKilometer();
+
+		Assert.AreEqual(ecMj / distanceKm, converted.Value, 1e-6);
+		Assert.AreEqual("MJ/km", converted.Units);
+	}
+
+
+	[Test]
+	public void ConvertedSITest_ConvertToKiloWattHourPerKiloMeter()
+	{
+		var ec_kWh = 200.0;
+		var distanceKm = 100.0;
+		WattSecond ec = ec_kWh.SI(Unit.SI.Kilo.Watt.Hour).Cast<WattSecond>();
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+
+		var converted = (ec / distance).ConvertToKiloWattHourPerKiloMeter();
+
+		Assert.AreEqual(ec_kWh / distanceKm, converted.Value, 1e-6);
+		Assert.AreEqual("kWh/km", converted.Units);
+	}
+
+	[Test]
+	public void ConvertedSITest_ConvertToKiloWattHourPerTonKiloMeter()
+	{
+		var ec_kWh = 200.0;
+		var distanceKm = 100.0;
+		var payloadTon = 2.5;
+		WattSecond ec = ec_kWh.SI(Unit.SI.Kilo.Watt.Hour).Cast<WattSecond>();
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+		Kilogram payload = payloadTon.SI(Unit.SI.Ton).Cast<Kilogram>();
+
+		var converted = (ec / distance / payload).ConvertToKiloWattHourPerTonKiloMeter();
+
+		Assert.AreEqual(ec_kWh / distanceKm / payloadTon, converted.Value, 1e-6);
+		Assert.AreEqual("kWh/t-km", converted.Units);
+	}
+
+	[Test]
+	public void ConvertedSITest_ConvertToKiloWattHourPerCubicMeterKiloMeter()
+	{
+		var ec_kWh = 200.0;
+		var distanceKm = 100.0;
+		var cargo = 10;
+		WattSecond ec = ec_kWh.SI(Unit.SI.Kilo.Watt.Hour).Cast<WattSecond>();
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+		CubicMeter cargoVolume = cargo.SI(Unit.SI.Cubic.Meter).Cast<CubicMeter>();
+
+		var converted = (ec / distance / cargoVolume).ConvertToKiloWattHourPerCubicMeterKiloMeter();
+
+		Assert.AreEqual(ec_kWh / distanceKm / cargo, converted.Value, 1e-6);
+		Assert.AreEqual("kWh/m³-km", converted.Units);
+	}
+
+	[Test]
+	public void ConvertedSITest_Ws_ConvertToMegaJoulePerKiloMeter()
+	{
+		var ec_MJ = 200.0;
+		var distanceKm = 100.0;
+		WattSecond ec = ec_MJ.SI(Unit.SI.Mega.Joule).Cast<WattSecond>();
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+
+		var converted = (ec / distance).ConvertToMegaJoulePerKiloMeter();
+
+		Assert.AreEqual(ec_MJ / distanceKm, converted.Value, 1e-6);
+		Assert.AreEqual("MJ/km", converted.Units);
+	}
+
+	[Test]
+	public void ConvertedSITest_Ws_ConvertToMegaJoulePerTonKiloMeter()
+	{
+		var ec_MJ = 200.0;
+		var distanceKm = 100.0;
+		WattSecond ec = ec_MJ.SI(Unit.SI.Mega.Joule).Cast<WattSecond>();
+		var payloadTon = 2.5;
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+		Kilogram payload = payloadTon.SI(Unit.SI.Ton).Cast<Kilogram>();
+
+		var converted = (ec / distance / payload).ConvertToMegaJoulePerTonKiloMeter();
+
+		Assert.AreEqual(ec_MJ / distanceKm / payloadTon, converted.Value, 1e-6);
+		Assert.AreEqual("MJ/t-km", converted.Units);
+	}
+
+	[Test]
+	public void ConvertedSITest_Ws_ConvertToMegaJoulePerCubicMeterKiloMeter()
+	{
+		var ec_MJ = 200.0;
+		var distanceKm = 100.0;
+		WattSecond ec = ec_MJ.SI(Unit.SI.Mega.Joule).Cast<WattSecond>();
+		var cargo = 10;
+		Meter distance = distanceKm.SI(Unit.SI.Kilo.Meter).Cast<Meter>();
+		CubicMeter cargoVolume = cargo.SI(Unit.SI.Cubic.Meter).Cast<CubicMeter>();
+
+		var converted = (ec / distance / cargoVolume).ConvertToMegaJoulePerCubicMeterKiloMeter();
+
+		Assert.AreEqual(ec_MJ / distanceKm / cargo, converted.Value, 1e-6);
+		Assert.AreEqual("MJ/m³-km", converted.Units);
+	}
+}
+
-- 
GitLab