From 456cc372b9c5b0208de4fc970a98f9411f30c07d Mon Sep 17 00:00:00 2001
From: Michael Krisper <michael.krisper@tugraz.at>
Date: Wed, 29 Jul 2015 14:41:41 +0200
Subject: [PATCH] corrected AuxModData Test (works now with SI units in
 moddata)

---
 .../Simulation/Data/IModalDataWriter.cs       | 43 ++++--------
 .../Simulation/Data/SummaryFileWriter.cs      | 65 +++++++++++--------
 .../Impl/CombustionEngine.cs                  |  2 +-
 .../Impl/EngineOnlyDrivingCycle.cs            | 24 ++++++-
 .../Utils/IEnumberableExtensionMethods.cs     |  5 +-
 VectoCoreTest/Models/Simulation/AuxTests.cs   |  4 +-
 6 files changed, 79 insertions(+), 64 deletions(-)

diff --git a/VectoCore/Models/Simulation/Data/IModalDataWriter.cs b/VectoCore/Models/Simulation/Data/IModalDataWriter.cs
index 34a4d2f9c8..5eba8d3841 100644
--- a/VectoCore/Models/Simulation/Data/IModalDataWriter.cs
+++ b/VectoCore/Models/Simulation/Data/IModalDataWriter.cs
@@ -46,49 +46,30 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 
 	public static class ModalDataWriterExtensions
 	{
-		public static double? Max(this IModalDataWriter data, ModalResultField field)
+		public static SI Max(this IModalDataWriter data, ModalResultField field)
 		{
-			var val = data.GetValues<SI>(field).Max();
-			if (val != null) {
-				return val.Value();
-			}
-			return null;
+			return data.GetValues<SI>(field).Max();
 		}
-
-		public static double? Average(this IModalDataWriter data, ModalResultField field, Func<SI, bool> filter = null)
+		
+		public static SI Average(this IModalDataWriter data, ModalResultField field, Func<SI, bool> filter = null)
 		{
-			var val = data.GetValues<SI>(field).Where(filter ?? (x => x != null)).ToList();
-			if (val.Any()) {
-				return val.ToDouble().Average();
-			}
-			return null;
+			return data.GetValues<SI>(field).Average(filter);
 		}
 
-		public static double? Sum(this IModalDataWriter data, ModalResultField field, Func<SI, bool> filter = null)
+		public static SI Sum(this IModalDataWriter data, ModalResultField field, Func<SI, bool> filter = null)
 		{
-			var val = data.GetValues<SI>(field).Where(filter ?? (x => x != null)).ToList();
-			if (val.Any()) {
-				return val.ToDouble().Sum();
-			}
-			return null;
+			return data.GetValues<SI>(field).Where(filter ?? (x => x != null)).Sum();
 		}
 
-		public static double? Sum(this IModalDataWriter data, DataColumn col, Func<SI, bool> filter = null)
+		public static SI Sum(this IModalDataWriter data, DataColumn col, Func<SI, bool> filter = null)
 		{
-			var val = data.GetValues<SI>(col).Where(filter ?? (x => x != null)).ToList();
-			if (val.Any()) {
-				return val.ToDouble().Sum();
-			}
-			return null;
+			return data.GetValues<SI>(col).Where(filter ?? (x => x != null)).Sum();
 		}
 
-		public static double? Average(this IEnumerable<SI> self, Func<SI, bool> filter = null)
+		public static SI Average(this IEnumerable<SI> self, Func<SI, bool> filter = null)
 		{
-			var val = self.Where(filter ?? (x => x != null)).ToList();
-			if (val.Any()) {
-				return val.ToDouble().Average();
-			}
-			return null;
+			var values = self.Where(filter ?? (x => x != null)).ToList();
+			return values.Any() ? values.Sum() / values.Count : null;
 		}
 
 		public static object DefaultIfNull(this object self)
diff --git a/VectoCore/Models/Simulation/Data/SummaryFileWriter.cs b/VectoCore/Models/Simulation/Data/SummaryFileWriter.cs
index f74c6e4971..d68a5709a2 100644
--- a/VectoCore/Models/Simulation/Data/SummaryFileWriter.cs
+++ b/VectoCore/Models/Simulation/Data/SummaryFileWriter.cs
@@ -82,11 +82,9 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 
 			_table.Columns.AddRange(new[] {
 				TIME, DISTANCE, SPEED, ALTITUDE, PPOS, PNEG, FCMAP, FCMAPKM, FCAUXC, FCAUXCKM, FCWHTCC, FCWHTCCKM, PWHEELPOS, PBRAKE,
-				EPOSICE,
-				ENEGICE, EAIR, EROLL, EGRAD, EACC, EAUX, EBRAKE, ETRANSM, ERETARDER, MASS, LOADING, A, APOS, ANEG, PACC, PDEC,
-				PCRUISE, PSTOP, ETORQUECONV, CO2,
-				CO2T, FCFINAL, FCFINAL_LITER, FCFINAL_LITERPER100TKM, ACCNOISE
-			}.Select(x => new DataColumn(x, typeof(double))).ToArray());
+				EPOSICE, ENEGICE, EAIR, EROLL, EGRAD, EACC, EAUX, EBRAKE, ETRANSM, ERETARDER, MASS, LOADING, A, APOS, ANEG, PACC,
+				PDEC, PCRUISE, PSTOP, ETORQUECONV, CO2, CO2T, FCFINAL, FCFINAL_LITER, FCFINAL_LITERPER100TKM, ACCNOISE
+			}.Select(x => new DataColumn(x, typeof(SI))).ToArray());
 		}
 
 		protected internal void WriteEngineOnly(IModalDataWriter data, string jobFileName, string jobName,
@@ -97,11 +95,11 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 			row[INPUTFILE] = jobFileName;
 			row[CYCLE] = cycleFileName;
 			row[TIME] = data.GetValues<SI>(ModalResultField.time).Max();
-			row[PPOS] = data.GetValues<SI>(ModalResultField.Pe_eng).Where(x => x > 0).ToDouble().Average();
-			row[PNEG] = data.GetValues<SI>(ModalResultField.Pe_eng).Where(x => x < 0).ToDouble().Average();
-			row[FCMAP] = data.GetValues<SI>(ModalResultField.FCMap).ToDouble().Average();
-			row[FCAUXC] = data.GetValues<SI>(ModalResultField.FCAUXc).ToDouble().Average();
-			row[FCWHTCC] = data.GetValues<SI>(ModalResultField.FCWHTCc).ToDouble().Average();
+			row[PPOS] = data.GetValues<SI>(ModalResultField.Pe_eng).Where(x => x > 0).Average();
+			row[PNEG] = data.GetValues<SI>(ModalResultField.Pe_eng).Where(x => x < 0).Average();
+			row[FCMAP] = data.GetValues<SI>(ModalResultField.FCMap).Average();
+			row[FCAUXC] = data.GetValues<SI>(ModalResultField.FCAUXc).Average();
+			row[FCWHTCC] = data.GetValues<SI>(ModalResultField.FCWHTCc).Average();
 
 			WriteAuxiliaries(data, row);
 
@@ -112,11 +110,11 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 		{
 			_auxColumns = _auxColumns.Union(data.Auxiliaries.Select(kv => "Eaux_" + kv.Key + " [kwh]")).ToList();
 
-			double? sum = 0.0;
+			var sum = 0.SI<Watt>();
 			foreach (var aux in data.Auxiliaries) {
 				var colName = "Eaux_" + aux.Key + " [kWh]";
 				if (!_table.Columns.Contains(colName)) {
-					_table.Columns.Add(colName, typeof(double));
+					_table.Columns.Add(colName, typeof(SI));
 				}
 
 				var currentSum = data.Sum(aux.Value);
@@ -153,9 +151,19 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 			row[EGRAD] = data.Sum(ModalResultField.Pgrad).DefaultIfNull();
 			row[EAUX] = data.Sum(ModalResultField.Paux).DefaultIfNull();
 			row[EBRAKE] = data.Sum(ModalResultField.Pbrake).DefaultIfNull();
-			row[ETRANSM] = (data.Sum(ModalResultField.PlossDiff) + data.Sum(ModalResultField.PlossGB)).DefaultIfNull();
+
+			var plossdiff = data.Sum(ModalResultField.PlossDiff);
+			var plossgb = data.Sum(ModalResultField.PlossGB);
+			if ((plossdiff ?? plossgb) != null) {
+				row[ETRANSM] = plossdiff ?? 0.SI() + plossgb ?? 0.SI();
+			}
 			row[ERETARDER] = data.Sum(ModalResultField.PlossRetarder).DefaultIfNull();
-			row[EACC] = (data.Sum(ModalResultField.PaEng) + data.Sum(ModalResultField.PaGB)).DefaultIfNull();
+
+			var paeng = data.Sum(ModalResultField.PaEng);
+			var pagb = data.Sum(ModalResultField.PaGB);
+			if ((paeng ?? pagb) != null) {
+				row[EACC] = paeng ?? 0.SI() + pagb ?? 0.SI();
+			}
 
 			//todo altitude - calculate when reading the cycle file, add column for altitude
 			//row["∆altitude [m]"] = Data.Rows[Data.Rows.Count - 1].Field<double>("altitude") -
@@ -164,30 +172,35 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 			WriteAuxiliaries(data, row);
 
 			//todo get data from vehicle file
-			row[MASS] = vehicleMass == null ? "" : vehicleMass.Value().ToString(CultureInfo.InvariantCulture);
-			row[LOADING] = vehicleLoading == null ? "" : vehicleLoading.Value().ToString(CultureInfo.InvariantCulture);
+			if (vehicleMass != null) {
+				row[MASS] = vehicleMass;
+			}
+
+			if (vehicleLoading != null) {
+				row[LOADING] = vehicleLoading;
+			}
 
 			var dtValues = data.GetValues<SI>(ModalResultField.simulationInterval).ToList();
 			var accValues = data.GetValues<SI>(ModalResultField.acc);
 			var accelerations = CalculateAverageOverSeconds(dtValues, accValues).ToList();
 			if (accelerations.Any()) {
-				row[A] = accelerations.ToDouble().Average();
+				row[A] = accelerations.Average();
 			}
 
 			var acceleration3SecondAverage = Calculate3SecondAverage(accelerations).ToList();
-
-			row[APOS] = acceleration3SecondAverage.Average(x => x > 0.125).DefaultIfNull();
-			row[ANEG] = acceleration3SecondAverage.Average(x => x < -0.125).DefaultIfNull();
-			row[PACC] = 100.0 * acceleration3SecondAverage.Count(x => x > 0.125) / acceleration3SecondAverage.Count;
-			row[PDEC] = 100.0 * acceleration3SecondAverage.Count(x => x < -0.125) / acceleration3SecondAverage.Count;
-			row[PCRUISE] = 100.0 * acceleration3SecondAverage.Count(x => x < 0.125 && x > -0.125) /
-							acceleration3SecondAverage.Count;
-
+			if (acceleration3SecondAverage.Any()) {
+				row[APOS] = acceleration3SecondAverage.Average(x => x > 0.125).DefaultIfNull();
+				row[ANEG] = acceleration3SecondAverage.Average(x => x < -0.125).DefaultIfNull();
+				row[PACC] = 100.SI() * acceleration3SecondAverage.Count(x => x > 0.125) / acceleration3SecondAverage.Count;
+				row[PDEC] = 100.SI() * acceleration3SecondAverage.Count(x => x < -0.125) / acceleration3SecondAverage.Count;
+				row[PCRUISE] = 100.SI() * acceleration3SecondAverage.Count(x => x < 0.125 && x > -0.125) /
+								acceleration3SecondAverage.Count;
+			}
 			var pStopTime = data.GetValues<SI>(ModalResultField.v_act)
 				.Zip(dtValues, (velocity, dt) => new { velocity, dt })
 				.Where(x => x.velocity < 0.1)
 				.Sum(x => x.dt.Value());
-			row[PSTOP] = 100.0 * pStopTime / dtValues.ToDouble().Sum();
+			row[PSTOP] = 100 * pStopTime / dtValues.Sum();
 
 			_table.Rows.Add(row);
 		}
diff --git a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
index aa773d1fe7..c2145ebbbe 100644
--- a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
@@ -143,7 +143,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			} catch (VectoException ex) {
 				Log.WarnFormat("t: {0} - {1} n: {2} Tq: {3}", _currentState.AbsTime, ex.Message,
 					_currentState.EngineSpeed, _currentState.EngineTorque);
-				writer[ModalResultField.FCMap] = double.NaN;
+				writer[ModalResultField.FCMap] = double.NaN.SI();
 			}
 		}
 
diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs
index f715fd7965..59f17f910b 100644
--- a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using TUGraz.VectoCore.Exceptions;
 using TUGraz.VectoCore.Models.Connector.Ports;
 using TUGraz.VectoCore.Models.Connector.Ports.Impl;
@@ -17,10 +18,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 	{
 		protected DrivingCycleData Data;
 		private ITnOutPort _outPort;
+		private IEnumerator<DrivingCycleData.DrivingCycleEntry> RightSample { get; set; }
+		private IEnumerator<DrivingCycleData.DrivingCycleEntry> LeftSample { get; set; }
+
 
 		public EngineOnlySimulation(IVehicleContainer container, DrivingCycleData cycle) : base(container)
 		{
 			Data = cycle;
+			LeftSample = Data.Entries.GetEnumerator();
+			LeftSample.MoveNext();
+
+			RightSample = Data.Entries.GetEnumerator();
+			RightSample.MoveNext();
+			RightSample.MoveNext();
 		}
 
 		#region ITnInProvider
@@ -79,14 +89,22 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		protected override void DoWriteModalResults(IModalDataWriter writer) {}
 
-		protected override void DoCommitSimulationStep() {}
+		protected override void DoCommitSimulationStep()
+		{
+			LeftSample.MoveNext();
+			RightSample.MoveNext();
+		}
 
 		#endregion
 
 		public CycleData CycleData()
 		{
-			//todo EngineOnlyDrivingCycle.CycleData
-			throw new NotImplementedException();
+			return new CycleData {
+				AbsTime = LeftSample.Current.Time,
+				AbsDistance = null,
+				LeftSample = LeftSample.Current,
+				RightSample = RightSample.Current,
+			};
 		}
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/Utils/IEnumberableExtensionMethods.cs b/VectoCore/Utils/IEnumberableExtensionMethods.cs
index 137d2a6d96..eceae3b47a 100644
--- a/VectoCore/Utils/IEnumberableExtensionMethods.cs
+++ b/VectoCore/Utils/IEnumberableExtensionMethods.cs
@@ -42,9 +42,10 @@ namespace TUGraz.VectoCore.Utils
 			}
 		}
 
-		public static T Sum<T>(this IEnumerable<T> list) where T : SIBase<T>
+		public static SI Sum(this IEnumerable<SI> values)
 		{
-			return list.Aggregate((sum, current) => sum + current);
+			var valueList = values.ToList();
+			return valueList.Any() ? valueList.Aggregate((sum, current) => sum + current) : null;
 		}
 
 		public static Func<bool> Once()
diff --git a/VectoCoreTest/Models/Simulation/AuxTests.cs b/VectoCoreTest/Models/Simulation/AuxTests.cs
index 5ddece684b..ed96f9df3e 100644
--- a/VectoCoreTest/Models/Simulation/AuxTests.cs
+++ b/VectoCoreTest/Models/Simulation/AuxTests.cs
@@ -47,10 +47,12 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
 			var speed = 1400.RPMtoRad();
 			var torque = 500.SI<NewtonMeter>();
 			var t = 0.SI<Second>();
+			var dt = 1.SI<Second>();
 
 			for (var i = 0; i < data.Entries.Count; i++) {
 				aux.OutPort().Request(t, t, torque, speed);
-				container.CommitSimulationStep(t, t);
+				container.CommitSimulationStep(t, dt);
+				t += dt;
 			}
 
 			container.FinishSimulation();
-- 
GitLab