diff --git a/VectoCommon/VectoHashingTest/VectoHashTest.cs b/VectoCommon/VectoHashingTest/VectoHashTest.cs index 2a6c5c43ea742558568b64662e0cb0bc01664fb7..a38bbeacaa4f12c341bbeb90019ade3c44ff749a 100644 --- a/VectoCommon/VectoHashingTest/VectoHashTest.cs +++ b/VectoCommon/VectoHashingTest/VectoHashTest.cs @@ -29,430 +29,430 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ -using System; -using System.IO; -using System.Linq; -using System.Text; -using System.Xml; -using System.Xml.Linq; -using System.Xml.Schema; -using NUnit.Framework; -using TUGraz.VectoCore.Utils; -using TUGraz.VectoHashing; -using VectoHashingTest.Utils; -using Assert = NUnit.Framework.Assert; - -namespace VectoHashingTest -{ - [TestFixture] - public class VectoHashTest - { - public const string ReferenceXMLEngine = @"Testdata\XML\Reference\vecto_engine-sample.xml"; - public const string ReferenceXMLVehicle = @"Testdata\XML\Reference\vecto_vehicle-sample_FULL.xml"; - - [TestCase] - public void TestComponentsEngineFile() - { - var h = VectoHash.Load(ReferenceXMLEngine); - var components = h.GetContainigComponents().ToList(); - - Assert.AreEqual(1, components.Count); - Assert.AreEqual(VectoComponents.Engine, components[0]); - } - - [TestCase] - public void TestComponentsVehicleFile() - { - var h = VectoHash.Load(ReferenceXMLVehicle); - var components = h.GetContainigComponents().ToList(); - - Assert.AreEqual(10, components.Count); - } - - [TestCase(ReferenceXMLEngine, VectoComponents.Engine, BasicHasingTests.HashEngineXML)] - public void TestHashComputationSelected(string file, VectoComponents component, string expectedHash) - { - var h = VectoHash.Load(file); - var hash = h.ComputeHash(component); - - Assert.AreEqual(expectedHash, hash); - } - - [TestCase(ReferenceXMLVehicle, BasicHasingTests.HashVehicleXML), - TestCase(ReferenceXMLEngine, BasicHasingTests.HashEngineXML)] - public void TestHashComputation(string file, string expectedHash) - { - var h = VectoHash.Load(file); - var hash = h.ComputeHash(); - - Assert.AreEqual(expectedHash, hash); - } - - [TestCase(ReferenceXMLEngine)] - public void TestHashComputationInvalidComponent(string file) - { - var h = VectoHash.Load(file); - AssertHelper.Exception<Exception>(() => h.ComputeHash(VectoComponents.Gearbox), "Component Gearbox not found"); - } - - [TestCase(ReferenceXMLEngine)] - public void TestReadHashInvalidComponent(string file) - { - var h = VectoHash.Load(file); - AssertHelper.Exception<Exception>(() => h.ReadHash(VectoComponents.Gearbox), "Component Gearbox not found"); - } - - [TestCase(ReferenceXMLVehicle, VectoComponents.Engine, "e0c253b643f7f8f09b963aca4a264d06fbfa599f"), - TestCase(ReferenceXMLVehicle, VectoComponents.Gearbox, "d14189366134120e08fa3f2c6e3328dd13c08a23")] - public void TestReadHash(string file, VectoComponents component, string expectedHash) - { - var h = VectoHash.Load(file); - var existingHash = h.ReadHash(component); - - Assert.AreEqual(expectedHash, existingHash); - } - - [TestCase(ReferenceXMLVehicle, VectoComponents.Tyre, 0, "5074334bb2c090c5e258e9a664f5d19689a3f13d"), - TestCase(ReferenceXMLVehicle, VectoComponents.Tyre, 1, "6074334bb2c090c5e258e9a664f5d19689a3f13d")] - public void TestReadHashIdx(string file, VectoComponents component, int index, string expectedHash) - { - var h = VectoHash.Load(file); - var existingHash = h.ReadHash(component, index); - - Assert.AreEqual(expectedHash, existingHash); - } - - [TestCase] - public void TestReadTyres1Index() - { - var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle1.xml"; - var h = VectoHash.Load(file); - var expectedHash = new[] { - "5074334bb2c090c5e258e9a664f5d19689a3f13d", - "6074334bb2c090c5e258e9a664f5d19689a3f13d", - "6074334bb2c090c5e258e9a664f5d19689a3f13d" - }; - - for (int i = 0; i < expectedHash.Length; i++) { - var existingHash = h.ReadHash(VectoComponents.Tyre, i); - - Assert.AreEqual(expectedHash[i], existingHash); - } - } - - [TestCase] - public void TestReadTyres2Index() - { - var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle2.xml"; - var h = VectoHash.Load(file); - var expectedHash = new[] { - "5074334bb2c090c5e258e9a664f5d19689a3f13d", - "5074334bb2c090c5e258e9a664f5d19689a3f13d", - "6074334bb2c090c5e258e9a664f5d19689a3f13d" - }; - - for (int i = 0; i < expectedHash.Length; i++) { - var existingHash = h.ReadHash(VectoComponents.Tyre, i); - - Assert.AreEqual(expectedHash[i], existingHash); - } - - AssertHelper.Exception<Exception>(() => h.ReadHash(VectoComponents.Tyre, 3), - "index exceeds number of components found! index: 3, #components: 3"); - } - - [TestCase] - public void TestComputeTyres1Index() - { - var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle1.xml"; - var h = VectoHash.Load(file); - - var hash1 = h.ComputeHash(VectoComponents.Tyre, 1); - var hash2 = h.ComputeHash(VectoComponents.Tyre, 2); - - Assert.AreEqual(hash1, hash2); - - AssertHelper.Exception<Exception>(() => h.ComputeHash(VectoComponents.Tyre, 3), - "index exceeds number of components found! index: 3, #components: 3"); - } - - [TestCase] - public void TestComputeTyres2Index() - { - var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle2.xml"; - var h = VectoHash.Load(file); - - var hash1 = h.ComputeHash(VectoComponents.Tyre, 0); - var hash2 = h.ComputeHash(VectoComponents.Tyre, 1); - - Assert.AreEqual(hash1, hash2); - - AssertHelper.Exception<Exception>(() => h.ComputeHash(VectoComponents.Tyre, 3), - "index exceeds number of components found! index: 3, #components: 3"); - } - - [TestCase("vecto_vehicle-sample_FULL_Comments.xml", BasicHasingTests.HashVehicleXML), - TestCase("vecto_vehicle-sample_FULL_Entry_Order.xml", BasicHasingTests.HashVehicleXML), - TestCase("vecto_vehicle-sample_FULL_Newlines_Linux_LF.xml", BasicHasingTests.HashVehicleXML), - TestCase("vecto_vehicle-sample_FULL_Newlines_Mac_CR.xml", BasicHasingTests.HashVehicleXML), - TestCase("vecto_vehicle-sample_FULL_Newlines_Windows_CRLF.xml", BasicHasingTests.HashVehicleXML), - TestCase("vecto_engine-sample Encoding ISO 8859-15.xml", BasicHasingTests.HashEngineXML), - TestCase("vecto_engine-sample Encoding UTF-8 BOM.xml", BasicHasingTests.HashEngineXML), - TestCase("vecto_engine-sample Encoding UTF-8.xml", BasicHasingTests.HashEngineXML), - TestCase("vecto_engine-sample Encoding UTF-16 BE BOM.xml", BasicHasingTests.HashEngineXML), - TestCase("vecto_engine-sample Encoding UTF-16 LE.xml", BasicHasingTests.HashEngineXML), - TestCase("vecto_engine-sample Encoding windows-1292.xml", BasicHasingTests.HashEngineXML), - TestCase("vecto_engine-sample_Whitespaces.xml", BasicHasingTests.HashEngineXML), - ] - public void TestHashComputationVariations(string file, string expectedHash) - { - var h = VectoHash.Load(@"Testdata\XML\Variations\" + file); - var hash = h.ComputeHash(); - - Assert.AreEqual(expectedHash, hash); - } - - - [TestCase(@"Testdata\XML\Validation\vecto_engine_valid.xml"), - TestCase(@"Testdata\XML\Validation\vecto_gearbox_valid.xml")] - public void TestValidation(string file) - { - var h = VectoHash.Load(file); - Assert.IsTrue(h.ValidateHash()); - } - - [TestCase(@"Testdata\XML\Validation\vecto_engine_invalid.xml"), - TestCase(@"Testdata\XML\Validation\vecto_gearbox_invalid.xml")] - public void TestValidationInvalid(string file) - { - var h = VectoHash.Load(file); - Assert.IsFalse(h.ValidateHash()); - } - - [TestCase(VectoComponents.Engine), - TestCase(VectoComponents.Gearbox), - ] - public void TestValidationComponentValid(VectoComponents component) - { - var file = @"Testdata\XML\Validation\vecto_vehicle_components_valid-engine_gbx.xml"; - var h = VectoHash.Load(file); - - Assert.IsTrue(h.ValidateHash(component)); - } - - [TestCase(VectoComponents.Engine), - TestCase(VectoComponents.Gearbox), - TestCase(VectoComponents.Axlegear), - TestCase(VectoComponents.Angledrive), - TestCase(VectoComponents.Retarder), - TestCase(VectoComponents.TorqueConverter), - TestCase(VectoComponents.Tyre), - TestCase(VectoComponents.Airdrag), - ] - public void TestValidationComponentInvalid(VectoComponents component) - { - var file = @"Testdata\XML\Validation\vecto_vehicle_components_invalid.xml"; - var h = VectoHash.Load(file); - - Assert.IsFalse(h.ValidateHash(component)); - } - - [TestCase(@"Testdata\XML\ToHash\vecto_engine-input.xml"), - TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml"), - TestCase(@"Testdata\XML\ToHash\vecto_gearbox-input.xml")] - public void TestAddHash(string file) - { - var destination = Path.GetFileNameWithoutExtension(file) + "_hashed.xml"; - - var h = VectoHash.Load(file); - var r = h.AddHash(); - - var writer = new XmlTextWriter(destination, Encoding.UTF8); - r.WriteTo(writer); - writer.Flush(); - writer.Close(); - - var h2 = VectoHash.Load(destination); - Assert.IsTrue(h2.ValidateHash()); - } - - [TestCase(@"Testdata\XML\ToHash\vecto_engine_withhash-input.xml", "input data already contains a signature element"), - TestCase(@"Testdata\XML\ToHash\vecto_vehicle-sample.xml", "adding hash for Vehicle is not supported"), - TestCase(@"Testdata\XML\ToHash\vecto_gearbox-input_nodata.xml", "'Data' element for component 'Gearbox' not found!"), - TestCase(@"Testdata\XML\ToHash\multiple_components.xml", "input must not contain multiple components!"), - ] - public void TestAddHashException(string file, string expectedExceptionMsg) - { - var destination = Path.GetFileNameWithoutExtension(file) + "_hashed.xml"; - - var h = VectoHash.Load(file); - AssertHelper.Exception<Exception>(() => { var r = h.AddHash(); }, expectedExceptionMsg); - } - - [TestCase] - public void TestDuplicateSigElement() - { - var filename = @"Testdata\XML\Invalid\duplicate-sig.xml"; - var h = VectoHash.Load(filename); - - AssertHelper.Exception<Exception>(() => { var r = h.ReadHash(); }, "Multiple DigestValue elements found!"); - } - - - [TestCase()] - public void TestLoadFromStream() - { - var fs = new FileStream(BasicHasingTests.ReferenceXMLVehicle, FileMode.Open); - var h = VectoHash.Load(fs); - - var hash = h.ComputeHash(); - Assert.AreEqual(BasicHasingTests.HashVehicleXML, hash); - fs.Close(); - } - - [TestCase(WhitespaceHandling.All), - TestCase(WhitespaceHandling.None), - TestCase(WhitespaceHandling.Significant)] - public void TestLoadXmlDocument(WhitespaceHandling whitespace) - { - var xml = new XmlDocument(); - var reader = new XmlTextReader(BasicHasingTests.ReferenceXMLVehicle); - reader.WhitespaceHandling = whitespace; - xml.Load(reader); - var h = VectoHash.Load(xml); - - var hash = h.ComputeHash(); - Assert.AreEqual(BasicHasingTests.HashVehicleXML, hash); - } - - [TestCase(@"Testdata\XML\ToHash\vecto_engine-input.xml"), - TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml"), - TestCase(@"Testdata\XML\ToHash\vecto_gearbox-input.xml")] - public void TestHashedComponentIsValid(string file) - { - var destination = Path.GetFileNameWithoutExtension(file) + "_hashed.xml"; - - var h = VectoHash.Load(file); - var r = h.AddHash(); - - var writer = new XmlTextWriter(destination, Encoding.UTF8); - r.WriteTo(writer); - writer.Flush(); - writer.Close(); - - var h2 = VectoHash.Load(destination); - Assert.IsTrue(h2.ValidateHash()); - - // re-load generated XML and perform XSD validation - var settings = new XmlReaderSettings() { - ValidationType = ValidationType.Schema, - ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema | - //XmlSchemaValidationFlags.ProcessSchemaLocation | - XmlSchemaValidationFlags.ReportValidationWarnings - }; - settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); - settings.Schemas.Add(GetXMLSchema(false)); - var xmlValidator = XmlReader.Create(destination, settings); - var xmlDoc = XDocument.Load(xmlValidator); - } - - - [TestCase("vecto_vehicle-namespace_prefix.xml", BasicHasingTests.HashVehicleXML)] - public void TestNamespacePrefixVariations(string file, string expectedHash) - { - var h = VectoHash.Load(@"Testdata\XML\Variations\" + file); - var hash = h.ComputeHash(); - - Assert.AreEqual(expectedHash, hash); - } - - [TestCase()] - public void TestInvalidXMLAsFile() - { - var file = @"Testdata\XML\Invalid\invalid-comp.xml"; - - AssertHelper.Exception<Exception>(() => VectoHash.Load(file), "failed to read XML document"); - } - - [TestCase()] - public void TestInvalidXMLAsStream() - { - var file = @"Testdata\XML\Invalid\invalid-comp.xml"; - var stream = File.Open(file, FileMode.Open); - AssertHelper.Exception<Exception>(() => VectoHash.Load(stream), "failed to read XML document"); - } - - [TestCase()] - public void TestComputeHashNoComponentInXML() - { - var xml = @"<VectoInputDeclaration/>"; - var stream = new MemoryStream(); - var writer = new StreamWriter(stream); - writer.Write(xml); - writer.Flush(); - stream.Seek(0, SeekOrigin.Begin); - - var h = VectoHash.Load(stream); - AssertHelper.Exception<Exception>(() => h.ComputeHash(), "No component found"); - } - - [TestCase()] - public void TestReadHashNoComponentInXML() - { - var xml = @"<VectoInputDeclaration/>"; - var stream = new MemoryStream(); - var writer = new StreamWriter(stream); - writer.Write(xml); - writer.Flush(); - stream.Seek(0, SeekOrigin.Begin); - - var h = VectoHash.Load(stream); - AssertHelper.Exception<Exception>(() => h.ReadHash(), "No component found"); - } - - [TestCase(VectoComponents.Engine, "ENG-"), - TestCase(VectoComponents.Gearbox, "GBX-"), - TestCase(VectoComponents.Axlegear, "AXL-"), - TestCase(VectoComponents.Retarder, "RET-"), - TestCase(VectoComponents.TorqueConverter, "TC-"), - TestCase(VectoComponents.Angledrive, "ANGL-"), - TestCase(VectoComponents.Airdrag, "AD-"), - TestCase(VectoComponents.Tyre, "TYRE-"), - ] - public void TestIdPrefix(VectoComponents component, string expectedPrefix) - { - Assert.AreEqual(expectedPrefix, component.HashIdPrefix()); - } - - [TestCase()] - public void TestInvalidComponentXMLName() - { - AssertHelper.Exception<ArgumentOutOfRangeException>(() => ((VectoComponents)9999).XMLElementName()); - } - - [TestCase()] - public void TestInvalidComponentPrefix() - { - AssertHelper.Exception<ArgumentOutOfRangeException>(() => ((VectoComponents)9999).HashIdPrefix()); - } - - private static XmlSchemaSet GetXMLSchema(bool job) - { - var resource = RessourceHelper.LoadResourceAsStream(RessourceHelper.ResourceType.XMLSchema, - job ? "VectoInput.xsd" : "VectoComponent.xsd"); - var xset = new XmlSchemaSet() { XmlResolver = new XmlResourceResolver() }; - var reader = XmlReader.Create(resource, new XmlReaderSettings(), "schema://"); - xset.Add(XmlSchema.Read(reader, null)); - xset.Compile(); - return xset; - } - - private static void ValidationCallBack(object sender, ValidationEventArgs args) - { - if (args.Severity == XmlSeverityType.Error) { - throw new Exception(string.Format("Validation error: {0}" + Environment.NewLine + - "Line: {1}", args.Message, args.Exception.LineNumber)); - } - } - } +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Schema; +using NUnit.Framework; +using TUGraz.VectoCore.Utils; +using TUGraz.VectoHashing; +using VectoHashingTest.Utils; +using Assert = NUnit.Framework.Assert; + +namespace VectoHashingTest +{ + [TestFixture] + public class VectoHashTest + { + public const string ReferenceXMLEngine = @"Testdata\XML\Reference\vecto_engine-sample.xml"; + public const string ReferenceXMLVehicle = @"Testdata\XML\Reference\vecto_vehicle-sample_FULL.xml"; + + [TestCase] + public void TestComponentsEngineFile() + { + var h = VectoHash.Load(ReferenceXMLEngine); + var components = h.GetContainigComponents().ToList(); + + Assert.AreEqual(1, components.Count); + Assert.AreEqual(VectoComponents.Engine, components[0]); + } + + [TestCase] + public void TestComponentsVehicleFile() + { + var h = VectoHash.Load(ReferenceXMLVehicle); + var components = h.GetContainigComponents().ToList(); + + Assert.AreEqual(10, components.Count); + } + + [TestCase(ReferenceXMLEngine, VectoComponents.Engine, BasicHasingTests.HashEngineXML)] + public void TestHashComputationSelected(string file, VectoComponents component, string expectedHash) + { + var h = VectoHash.Load(file); + var hash = h.ComputeHash(component); + + Assert.AreEqual(expectedHash, hash); + } + + [TestCase(ReferenceXMLVehicle, BasicHasingTests.HashVehicleXML), + TestCase(ReferenceXMLEngine, BasicHasingTests.HashEngineXML)] + public void TestHashComputation(string file, string expectedHash) + { + var h = VectoHash.Load(file); + var hash = h.ComputeHash(); + + Assert.AreEqual(expectedHash, hash); + } + + [TestCase(ReferenceXMLEngine)] + public void TestHashComputationInvalidComponent(string file) + { + var h = VectoHash.Load(file); + AssertHelper.Exception<Exception>(() => h.ComputeHash(VectoComponents.Gearbox), "Component Gearbox not found"); + } + + [TestCase(ReferenceXMLEngine)] + public void TestReadHashInvalidComponent(string file) + { + var h = VectoHash.Load(file); + AssertHelper.Exception<Exception>(() => h.ReadHash(VectoComponents.Gearbox), "Component Gearbox not found"); + } + + [TestCase(ReferenceXMLVehicle, VectoComponents.Engine, "e0c253b643f7f8f09b963aca4a264d06fbfa599f"), + TestCase(ReferenceXMLVehicle, VectoComponents.Gearbox, "d14189366134120e08fa3f2c6e3328dd13c08a23")] + public void TestReadHash(string file, VectoComponents component, string expectedHash) + { + var h = VectoHash.Load(file); + var existingHash = h.ReadHash(component); + + Assert.AreEqual(expectedHash, existingHash); + } + + [TestCase(ReferenceXMLVehicle, VectoComponents.Tyre, 0, "5074334bb2c090c5e258e9a664f5d19689a3f13d"), + TestCase(ReferenceXMLVehicle, VectoComponents.Tyre, 1, "6074334bb2c090c5e258e9a664f5d19689a3f13d")] + public void TestReadHashIdx(string file, VectoComponents component, int index, string expectedHash) + { + var h = VectoHash.Load(file); + var existingHash = h.ReadHash(component, index); + + Assert.AreEqual(expectedHash, existingHash); + } + + [TestCase] + public void TestReadTyres1Index() + { + var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle1.xml"; + var h = VectoHash.Load(file); + var expectedHash = new[] { + "5074334bb2c090c5e258e9a664f5d19689a3f13d", + "6074334bb2c090c5e258e9a664f5d19689a3f13d", + "6074334bb2c090c5e258e9a664f5d19689a3f13d" + }; + + for (int i = 0; i < expectedHash.Length; i++) { + var existingHash = h.ReadHash(VectoComponents.Tyre, i); + + Assert.AreEqual(expectedHash[i], existingHash); + } + } + + [TestCase] + public void TestReadTyres2Index() + { + var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle2.xml"; + var h = VectoHash.Load(file); + var expectedHash = new[] { + "5074334bb2c090c5e258e9a664f5d19689a3f13d", + "5074334bb2c090c5e258e9a664f5d19689a3f13d", + "6074334bb2c090c5e258e9a664f5d19689a3f13d" + }; + + for (int i = 0; i < expectedHash.Length; i++) { + var existingHash = h.ReadHash(VectoComponents.Tyre, i); + + Assert.AreEqual(expectedHash[i], existingHash); + } + + AssertHelper.Exception<Exception>(() => h.ReadHash(VectoComponents.Tyre, 3), + "index exceeds number of components found! index: 3, #components: 3"); + } + + [TestCase] + public void TestComputeTyres1Index() + { + var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle1.xml"; + var h = VectoHash.Load(file); + + var hash1 = h.ComputeHash(VectoComponents.Tyre, 1); + var hash2 = h.ComputeHash(VectoComponents.Tyre, 2); + + Assert.AreEqual(hash1, hash2); + + AssertHelper.Exception<Exception>(() => h.ComputeHash(VectoComponents.Tyre, 3), + "index exceeds number of components found! index: 3, #components: 3"); + } + + [TestCase] + public void TestComputeTyres2Index() + { + var file = @"Testdata\XML\ToHash\vecto_vehicle-sample_3axle2.xml"; + var h = VectoHash.Load(file); + + var hash1 = h.ComputeHash(VectoComponents.Tyre, 0); + var hash2 = h.ComputeHash(VectoComponents.Tyre, 1); + + Assert.AreEqual(hash1, hash2); + + AssertHelper.Exception<Exception>(() => h.ComputeHash(VectoComponents.Tyre, 3), + "index exceeds number of components found! index: 3, #components: 3"); + } + + [TestCase("vecto_vehicle-sample_FULL_Comments.xml", BasicHasingTests.HashVehicleXML), + TestCase("vecto_vehicle-sample_FULL_Entry_Order.xml", BasicHasingTests.HashVehicleXML), + TestCase("vecto_vehicle-sample_FULL_Newlines_Linux_LF.xml", BasicHasingTests.HashVehicleXML), + TestCase("vecto_vehicle-sample_FULL_Newlines_Mac_CR.xml", BasicHasingTests.HashVehicleXML), + TestCase("vecto_vehicle-sample_FULL_Newlines_Windows_CRLF.xml", BasicHasingTests.HashVehicleXML), + TestCase("vecto_engine-sample Encoding ISO 8859-15.xml", BasicHasingTests.HashEngineXML), + TestCase("vecto_engine-sample Encoding UTF-8 BOM.xml", BasicHasingTests.HashEngineXML), + TestCase("vecto_engine-sample Encoding UTF-8.xml", BasicHasingTests.HashEngineXML), + TestCase("vecto_engine-sample Encoding UTF-16 BE BOM.xml", BasicHasingTests.HashEngineXML), + TestCase("vecto_engine-sample Encoding UTF-16 LE.xml", BasicHasingTests.HashEngineXML), + TestCase("vecto_engine-sample Encoding windows-1292.xml", BasicHasingTests.HashEngineXML), + TestCase("vecto_engine-sample_Whitespaces.xml", BasicHasingTests.HashEngineXML), + ] + public void TestHashComputationVariations(string file, string expectedHash) + { + var h = VectoHash.Load(@"Testdata\XML\Variations\" + file); + var hash = h.ComputeHash(); + + Assert.AreEqual(expectedHash, hash); + } + + + [TestCase(@"Testdata\XML\Validation\vecto_engine_valid.xml"), + TestCase(@"Testdata\XML\Validation\vecto_gearbox_valid.xml")] + public void TestValidation(string file) + { + var h = VectoHash.Load(file); + Assert.IsTrue(h.ValidateHash()); + } + + [TestCase(@"Testdata\XML\Validation\vecto_engine_invalid.xml"), + TestCase(@"Testdata\XML\Validation\vecto_gearbox_invalid.xml")] + public void TestValidationInvalid(string file) + { + var h = VectoHash.Load(file); + Assert.IsFalse(h.ValidateHash()); + } + + [TestCase(VectoComponents.Engine), + TestCase(VectoComponents.Gearbox), + ] + public void TestValidationComponentValid(VectoComponents component) + { + var file = @"Testdata\XML\Validation\vecto_vehicle_components_valid-engine_gbx.xml"; + var h = VectoHash.Load(file); + + Assert.IsTrue(h.ValidateHash(component)); + } + + [TestCase(VectoComponents.Engine), + TestCase(VectoComponents.Gearbox), + TestCase(VectoComponents.Axlegear), + TestCase(VectoComponents.Angledrive), + TestCase(VectoComponents.Retarder), + TestCase(VectoComponents.TorqueConverter), + TestCase(VectoComponents.Tyre), + TestCase(VectoComponents.Airdrag), + ] + public void TestValidationComponentInvalid(VectoComponents component) + { + var file = @"Testdata\XML\Validation\vecto_vehicle_components_invalid.xml"; + var h = VectoHash.Load(file); + + Assert.IsFalse(h.ValidateHash(component)); + } + + [TestCase(@"Testdata\XML\ToHash\vecto_engine-input.xml"), + TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml"), + TestCase(@"Testdata\XML\ToHash\vecto_gearbox-input.xml")] + public void TestAddHash(string file) + { + var destination = Path.GetFileNameWithoutExtension(file) + "_hashed.xml"; + + var h = VectoHash.Load(file); + var r = h.AddHash(); + + var writer = new XmlTextWriter(destination, Encoding.UTF8); + r.WriteTo(writer); + writer.Flush(); + writer.Close(); + + var h2 = VectoHash.Load(destination); + Assert.IsTrue(h2.ValidateHash()); + } + + [TestCase(@"Testdata\XML\ToHash\vecto_engine_withhash-input.xml", "input data already contains a signature element"), + TestCase(@"Testdata\XML\ToHash\vecto_vehicle-sample.xml", "adding hash for Vehicle is not supported"), + TestCase(@"Testdata\XML\ToHash\vecto_gearbox-input_nodata.xml", "'Data' element for component 'Gearbox' not found!"), + TestCase(@"Testdata\XML\ToHash\multiple_components.xml", "input must not contain multiple components!"), + ] + public void TestAddHashException(string file, string expectedExceptionMsg) + { + var destination = Path.GetFileNameWithoutExtension(file) + "_hashed.xml"; + + var h = VectoHash.Load(file); + AssertHelper.Exception<Exception>(() => { var r = h.AddHash(); }, expectedExceptionMsg); + } + + [TestCase] + public void TestDuplicateSigElement() + { + var filename = @"Testdata\XML\Invalid\duplicate-sig.xml"; + var h = VectoHash.Load(filename); + + AssertHelper.Exception<Exception>(() => { var r = h.ReadHash(); }, "Multiple DigestValue elements found!"); + } + + + [TestCase()] + public void TestLoadFromStream() + { + var fs = new FileStream(BasicHasingTests.ReferenceXMLVehicle, FileMode.Open); + var h = VectoHash.Load(fs); + + var hash = h.ComputeHash(); + Assert.AreEqual(BasicHasingTests.HashVehicleXML, hash); + fs.Close(); + } + + [TestCase(WhitespaceHandling.All), + TestCase(WhitespaceHandling.None), + TestCase(WhitespaceHandling.Significant)] + public void TestLoadXmlDocument(WhitespaceHandling whitespace) + { + var xml = new XmlDocument(); + var reader = new XmlTextReader(BasicHasingTests.ReferenceXMLVehicle); + reader.WhitespaceHandling = whitespace; + xml.Load(reader); + var h = VectoHash.Load(xml); + + var hash = h.ComputeHash(); + Assert.AreEqual(BasicHasingTests.HashVehicleXML, hash); + } + + [TestCase(@"Testdata\XML\ToHash\vecto_engine-input.xml"), + TestCase(@"Testdata\XML\ToHash\vecto_engine_withid-input.xml"), + TestCase(@"Testdata\XML\ToHash\vecto_gearbox-input.xml")] + public void TestHashedComponentIsValid(string file) + { + var destination = Path.GetFileNameWithoutExtension(file) + "_hashed.xml"; + + var h = VectoHash.Load(file); + var r = h.AddHash(); + + var writer = new XmlTextWriter(destination, Encoding.UTF8); + r.WriteTo(writer); + writer.Flush(); + writer.Close(); + + var h2 = VectoHash.Load(destination); + Assert.IsTrue(h2.ValidateHash()); + + // re-load generated XML and perform XSD validation + var settings = new XmlReaderSettings() { + ValidationType = ValidationType.Schema, + ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema | + //XmlSchemaValidationFlags.ProcessSchemaLocation | + XmlSchemaValidationFlags.ReportValidationWarnings + }; + settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); + settings.Schemas.Add(GetXMLSchema(false)); + var xmlValidator = XmlReader.Create(destination, settings); + var xmlDoc = XDocument.Load(xmlValidator); + } + + + [TestCase("vecto_vehicle-namespace_prefix.xml", BasicHasingTests.HashVehicleXML)] + public void TestNamespacePrefixVariations(string file, string expectedHash) + { + var h = VectoHash.Load(@"Testdata\XML\Variations\" + file); + var hash = h.ComputeHash(); + + Assert.AreEqual(expectedHash, hash); + } + + [TestCase()] + public void TestInvalidXMLAsFile() + { + var file = @"Testdata\XML\Invalid\invalid-comp.xml"; + + AssertHelper.Exception<Exception>(() => VectoHash.Load(file), "failed to read XML document"); + } + + [TestCase()] + public void TestInvalidXMLAsStream() + { + var file = @"Testdata\XML\Invalid\invalid-comp.xml"; + var stream = File.Open(file, FileMode.Open); + AssertHelper.Exception<Exception>(() => VectoHash.Load(stream), "failed to read XML document"); + } + + [TestCase()] + public void TestComputeHashNoComponentInXML() + { + var xml = @"<VectoInputDeclaration/>"; + var stream = new MemoryStream(); + var writer = new StreamWriter(stream); + writer.Write(xml); + writer.Flush(); + stream.Seek(0, SeekOrigin.Begin); + + var h = VectoHash.Load(stream); + AssertHelper.Exception<Exception>(() => h.ComputeHash(), "No component found"); + } + + [TestCase()] + public void TestReadHashNoComponentInXML() + { + var xml = @"<VectoInputDeclaration/>"; + var stream = new MemoryStream(); + var writer = new StreamWriter(stream); + writer.Write(xml); + writer.Flush(); + stream.Seek(0, SeekOrigin.Begin); + + var h = VectoHash.Load(stream); + AssertHelper.Exception<Exception>(() => h.ReadHash(), "No component found"); + } + + [TestCase(VectoComponents.Engine, "ENG-"), + TestCase(VectoComponents.Gearbox, "GBX-"), + TestCase(VectoComponents.Axlegear, "AXL-"), + TestCase(VectoComponents.Retarder, "RET-"), + TestCase(VectoComponents.TorqueConverter, "TC-"), + TestCase(VectoComponents.Angledrive, "ANGL-"), + TestCase(VectoComponents.Airdrag, "AD-"), + TestCase(VectoComponents.Tyre, "TYRE-"), + ] + public void TestIdPrefix(VectoComponents component, string expectedPrefix) + { + Assert.AreEqual(expectedPrefix, component.HashIdPrefix()); + } + + [TestCase()] + public void TestInvalidComponentXMLName() + { + AssertHelper.Exception<ArgumentOutOfRangeException>(() => ((VectoComponents)9999).XMLElementName()); + } + + [TestCase()] + public void TestInvalidComponentPrefix() + { + AssertHelper.Exception<ArgumentOutOfRangeException>(() => ((VectoComponents)9999).HashIdPrefix()); + } + + private static XmlSchemaSet GetXMLSchema(bool job) + { + var resource = RessourceHelper.LoadResourceAsStream(RessourceHelper.ResourceType.XMLSchema, + job ? "VectoInput.xsd" : "VectoComponent.xsd"); + var xset = new XmlSchemaSet() { XmlResolver = new XmlResourceResolver() }; + var reader = XmlReader.Create(resource, new XmlReaderSettings(), "schema://"); + xset.Add(XmlSchema.Read(reader, null)); + xset.Compile(); + return xset; + } + + private static void ValidationCallBack(object sender, ValidationEventArgs args) + { + if (args.Severity == XmlSeverityType.Error) { + throw new Exception(string.Format("Validation error: {0}" + Environment.NewLine + + "Line: {1}", args.Message, args.Exception.LineNumber)); + } + } + } } \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs index 7a69faf093e6c94035e30fd0dcd67f9ff55a6667..10c29e57190056f883d4a4147a85447b36f5b292 100644 --- a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs @@ -29,566 +29,566 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ -using System; -using System.Data; -using System.Linq; -using System.Runtime.CompilerServices; -using TUGraz.VectoCommon.Models; -using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore.Configuration; -using TUGraz.VectoCore.Models.Declaration; -using TUGraz.VectoCore.Models.Simulation.Data; -using TUGraz.VectoCore.Models.SimulationComponent.Data; - -// ReSharper disable MemberCanBePrivate.Global -- used by API! - -namespace TUGraz.VectoCore.OutputData -{ - public delegate void WriteSumData(IModalDataContainer data); - - /// <summary> - /// Class for the sum file in vecto. - /// </summary> - public class SummaryDataContainer : LoggingObject, IDisposable - { - // ReSharper disable InconsistentNaming - public const string INTERNAL_PREFIX = "INTERNAL"; - public const string SORT = INTERNAL_PREFIX + " Sorting"; - public const string JOB = "Job [-]"; - public const string INPUTFILE = "Input File [-]"; - public const string CYCLE = "Cycle [-]"; - public const string STATUS = "Status"; - public const string CURB_MASS = "Chassis curb mass [kg]"; - public const string LOADING = "Loading [kg]"; - - public const string VEHICLE_MANUFACTURER = "Vehicle manufacturer [-]"; - public const string VIN_NUMBER = "VIN number"; - public const string VEHICLE_MODEL = "Vehicle model [-]"; - - public const string ENGINE_MANUFACTURER = "Engine manufacturer [-]"; - public const string ENGINE_MODEL = "Engine model [-]"; - public const string ENGINE_FUEL_TYPE = "Engine fuel type [-]"; - public const string ENGINE_WHTC_URBAN = "Engine WHTCUrban"; - public const string ENGINE_WHTC_RURAL = "Engine WHTCRural"; - public const string ENGINE_WHTC_MOTORWAY = "Engine WHTCMotorway"; - public const string ENGINE_BF_COLD_HOT = "Engine BFColdHot"; - public const string ENGINE_CF_REG_PER = "Engine CFRegPer"; - public const string ENGINE_ACTUAL_CORRECTION_FACTOR = "Engine actual CF"; - public const string ENGINE_RATED_POWER = "Engine rated power [kW]"; - public const string ENGINE_IDLING_SPEED = "Engine idling speed [rpm]"; - public const string ENGINE_RATED_SPEED = "Engine rated speed [rpm]"; - public const string ENGINE_DISPLACEMENT = "Engine displacement [ccm]"; - - public const string ROLLING_RESISTANCE_COEFFICIENT_W_TRAILER = "total RRC [-]"; - public const string ROLLING_RESISTANCE_COEFFICIENT_WO_TRAILER = "weighted RRC w/o trailer [-]"; - - public const string GEARBOX_MANUFACTURER = "Gearbox manufacturer [-]"; - public const string GEARBOX_MODEL = "Gearbox model [-]"; - public const string GEARBOX_TYPE = "Gearbox type [-]"; - public const string GEAR_RATIO_FIRST_GEAR = "Gear ratio first gear [-]"; - public const string GEAR_RATIO_LAST_GEAR = "Gear ratio last gear [-]"; - - public const string TORQUECONVERTER_MANUFACTURER = "Torque converter manufacturer [-]"; - public const string TORQUECONVERTER_MODEL = "Torque converter model [-]"; - - public const string RETARDER_MANUFACTURER = "Retarder manufacturer [-]"; - public const string RETARDER_MODEL = "Retarder model [-]"; - public const string RETARDER_TYPE = "Retarder type [-]"; - - public const string ANGLEDRIVE_MANUFACTURER = "Angledrive manufacturer [-]"; - public const string ANGLEDRIVE_MODEL = "Angledrive model [-]"; - public const string ANGLEDRIVE_RATIO = "Angledrive ratio [-]"; - - public const string AXLE_MANUFACTURER = "Axle manufacturer [-]"; - public const string AXLE_MODEL = "Axle model [-]"; - public const string AXLE_RATIO = "Axle gear ratio [-]"; - - public const string AUX_TECH_FORMAT = "Auxiliary technology {0} [-]"; - - public const string HDV_CO2_VEHICLE_CLASS = "HDV CO2 vehicle class [-]"; - public const string TOTAL_VEHICLE_MASS = "Total vehicle mass [kg]"; - public const string CD_x_A = "CdxA [m²]"; - //public const string ROLLING_RESISTANCE_COEFFICIENT = "weighed RRC [-]"; - public const string R_DYN = "r_dyn [m]"; - - public const string CARGO_VOLUME = "Cargo Volume [m³]"; - public const string TIME = "time [s]"; - public const string DISTANCE = "distance [km]"; - public const string SPEED = "speed [km/h]"; - public const string ALTITUDE_DELTA = "altitudeDelta [m]"; - - public const string FCMAP_H = "FC-Map [g/h]"; - public const string FCMAP_KM = "FC-Map [g/km]"; - public const string FCAUXC_H = "FC-AUXc [g/h]"; - public const string FCAUXC_KM = "FC-AUXc [g/km]"; - public const string FCWHTCC_H = "FC-WHTCc [g/h]"; - public const string FCWHTCC_KM = "FC-WHTCc [g/km]"; - public const string FCAAUX_H = "FC-AAUX [g/h]"; - public const string FCAAUX_KM = "FC-AAUX [g/km]"; - - public const string FCFINAL_H = "FC-Final [g/h]"; - public const string FCFINAL_KM = "FC-Final [g/km]"; - public const string FCFINAL_LITERPER100KM = "FC-Final [l/100km]"; - public const string FCFINAL_LITERPER100TKM = "FC-Final [l/100tkm]"; - public const string FCFINAL_LiterPer100M3KM = "FC-Final [l/100m³km]"; - - public const string CO2_KM = "CO2 [g/km]"; - public const string CO2_TKM = "CO2 [g/tkm]"; - public const string CO2_M3KM = "CO2 [g/m³km]"; - - public const string P_WHEEL_POS = "P_wheel_in_pos [kW]"; - public const string P_FCMAP_POS = "P_fcmap_pos [kW]"; - - public const string E_FORMAT = "E_{0} [kWh]"; - public const string E_AUX_FORMAT = "E_aux_{0} [kWh]"; - public const string E_AUX = "E_aux_sum [kWh]"; - - public const string E_AIR = "E_air [kWh]"; - public const string E_ROLL = "E_roll [kWh]"; - public const string E_GRAD = "E_grad [kWh]"; - public const string E_VEHICLE_INERTIA = "E_vehi_inertia [kWh]"; - public const string E_POWERTRAIN_INERTIA = "E_powertrain_inertia [kWh]"; - public const string E_BRAKE = "E_brake [kWh]"; - public const string E_GBX_LOSS = "E_gbx_loss [kWh]"; - public const string E_SHIFT_LOSS = "E_shift_loss [kWh]"; - public const string E_AXL_LOSS = "E_axl_loss [kWh]"; - public const string E_RET_LOSS = "E_ret_loss [kWh]"; - public const string E_TC_LOSS = "E_tc_loss [kWh]"; - public const string E_ANGLE_LOSS = "E_angle_loss [kWh]"; - public const string E_CLUTCH_LOSS = "E_clutch_loss [kWh]"; - public const string E_FCMAP_POS = "E_fcmap_pos [kWh]"; - public const string E_FCMAP_NEG = "E_fcmap_neg [kWh]"; - - public const string ACC = "a [m/s^2]"; - public const string ACC_POS = "a_pos [m/s^2]"; - public const string ACC_NEG = "a_neg [m/s^2]"; - - public const string ACC_TIMESHARE = "AccelerationTimeShare [%]"; - public const string DEC_TIMESHARE = "DecelerationTimeShare [%]"; - public const string CRUISE_TIMESHARE = "CruiseTimeShare [%]"; - public const string STOP_TIMESHARE = "StopTimeShare [%]"; - - public const string MAX_SPEED = "max. speed [km/h"; - public const string MAX_ACCELERATION = "max. acc [m/s²]"; - public const string MAX_DECELERATION = "max. dec [m/s²]"; - public const string AVG_ENGINE_SPEED = "n_eng_avg [rpm]"; - public const string MAX_ENGINE_SPEED = "n_eng_max [rpm]"; - public const string NUM_GEARSHIFTS = "gear shifts [-]"; - public const string ENGINE_FULL_LOAD_TIME_SHARE = "Engine max. Load time share [%]"; - public const string COASTING_TIME_SHARE = "CoastingTimeShare [%]"; - public const string BRAKING_TIME_SHARE = "BrakingTImeShare [%]"; - - public const string TIME_SHARE_PER_GEAR_FORMAT = "Gear {0} TimeShare [%]"; - - // ReSharper restore InconsistentNaming - - internal readonly DataTable Table; - private readonly ISummaryWriter _sumWriter; - - - protected SummaryDataContainer() {} - - /// <summary> - /// Initializes a new instance of the <see cref="SummaryDataContainer"/> class. - /// </summary> - /// <param name="writer"></param> - public SummaryDataContainer(ISummaryWriter writer) - { - _sumWriter = writer; - - Table = new DataTable(); - - Table.Columns.AddRange(new[] { - Tuple.Create(SORT, typeof(int)), - Tuple.Create(JOB, typeof(string)), - Tuple.Create(INPUTFILE, typeof(string)), - Tuple.Create(CYCLE, typeof(string)), - Tuple.Create(STATUS, typeof(string)), - Tuple.Create(VEHICLE_MANUFACTURER, typeof(string)), - Tuple.Create(VIN_NUMBER, typeof(string)), - Tuple.Create(VEHICLE_MODEL, typeof(string)), - Tuple.Create(HDV_CO2_VEHICLE_CLASS, typeof(string)), - Tuple.Create(CURB_MASS, typeof(SI)), - Tuple.Create(LOADING, typeof(SI)), - Tuple.Create(TOTAL_VEHICLE_MASS, typeof(SI)), - Tuple.Create(ENGINE_MANUFACTURER, typeof(string)), - Tuple.Create(ENGINE_MODEL, typeof(string)), - Tuple.Create(ENGINE_FUEL_TYPE, typeof(string)), - Tuple.Create(ENGINE_RATED_POWER, typeof(SI)), - Tuple.Create(ENGINE_IDLING_SPEED, typeof(SI)), - Tuple.Create(ENGINE_RATED_SPEED, typeof(SI)), - Tuple.Create(ENGINE_DISPLACEMENT, typeof(SI)), - Tuple.Create(ENGINE_WHTC_URBAN, typeof(double)), - Tuple.Create(ENGINE_WHTC_RURAL, typeof(double)), - Tuple.Create(ENGINE_WHTC_MOTORWAY, typeof(double)), - Tuple.Create(ENGINE_BF_COLD_HOT, typeof(double)), - Tuple.Create(ENGINE_CF_REG_PER, typeof(double)), - Tuple.Create(ENGINE_ACTUAL_CORRECTION_FACTOR, typeof(double)), - Tuple.Create(CD_x_A, typeof(SI)), - Tuple.Create(ROLLING_RESISTANCE_COEFFICIENT_W_TRAILER, typeof(double)), - Tuple.Create(ROLLING_RESISTANCE_COEFFICIENT_WO_TRAILER, typeof(double)), - Tuple.Create(R_DYN, typeof(SI)), - Tuple.Create(GEARBOX_MANUFACTURER, typeof(string)), - Tuple.Create(GEARBOX_MODEL, typeof(string)), - Tuple.Create(GEARBOX_TYPE, typeof(string)), - Tuple.Create(GEAR_RATIO_FIRST_GEAR, typeof(SI)), - Tuple.Create(GEAR_RATIO_LAST_GEAR, typeof(SI)), - Tuple.Create(TORQUECONVERTER_MANUFACTURER, typeof(string)), - Tuple.Create(TORQUECONVERTER_MODEL, typeof(string)), - Tuple.Create(RETARDER_MANUFACTURER, typeof(string)), - Tuple.Create(RETARDER_MODEL, typeof(string)), - Tuple.Create(RETARDER_TYPE, typeof(string)), - Tuple.Create(ANGLEDRIVE_MANUFACTURER, typeof(string)), - Tuple.Create(ANGLEDRIVE_MODEL, typeof(string)), - Tuple.Create(ANGLEDRIVE_RATIO, typeof(string)), - Tuple.Create(AXLE_MANUFACTURER, typeof(string)), - Tuple.Create(AXLE_MODEL, typeof(string)), - Tuple.Create(AXLE_RATIO, typeof(SI)), - Tuple.Create(string.Format(AUX_TECH_FORMAT, Constants.Auxiliaries.IDs.SteeringPump), typeof(string)), - Tuple.Create(string.Format(AUX_TECH_FORMAT, Constants.Auxiliaries.IDs.Fan), typeof(string)), - Tuple.Create(string.Format(AUX_TECH_FORMAT, Constants.Auxiliaries.IDs.HeatingVentilationAirCondition), - typeof(string)), - Tuple.Create(string.Format(AUX_TECH_FORMAT, Constants.Auxiliaries.IDs.PneumaticSystem), typeof(string)), - Tuple.Create(string.Format(AUX_TECH_FORMAT, Constants.Auxiliaries.IDs.ElectricSystem), typeof(string)), - }.Select(x => new DataColumn(x.Item1, x.Item2)).ToArray()); - - Table.Columns.AddRange(new[] { - CARGO_VOLUME, - TIME, DISTANCE, - SPEED, ALTITUDE_DELTA, - FCMAP_H, FCMAP_KM, - FCAUXC_H, FCAUXC_KM, - FCWHTCC_H, FCWHTCC_KM, - FCAAUX_H, FCAAUX_KM, - FCFINAL_H, FCFINAL_KM, - FCFINAL_LITERPER100KM, FCFINAL_LITERPER100TKM, FCFINAL_LiterPer100M3KM, - CO2_KM, CO2_TKM, CO2_M3KM, - P_WHEEL_POS, P_FCMAP_POS, - E_FCMAP_POS, E_FCMAP_NEG, E_POWERTRAIN_INERTIA, - E_AUX, E_CLUTCH_LOSS, E_TC_LOSS, E_SHIFT_LOSS, E_GBX_LOSS, - E_RET_LOSS, E_ANGLE_LOSS, E_AXL_LOSS, E_BRAKE, E_VEHICLE_INERTIA, E_AIR, E_ROLL, E_GRAD, - ACC, ACC_POS, ACC_NEG, ACC_TIMESHARE, DEC_TIMESHARE, CRUISE_TIMESHARE, STOP_TIMESHARE, - MAX_SPEED, MAX_ACCELERATION, MAX_DECELERATION, AVG_ENGINE_SPEED, MAX_ENGINE_SPEED, NUM_GEARSHIFTS, - ENGINE_FULL_LOAD_TIME_SHARE, COASTING_TIME_SHARE, BRAKING_TIME_SHARE - }.Select(x => new DataColumn(x, typeof(SI))).ToArray()); - } - - /// <summary> - /// Finishes the summary data container (writes the data to the sumWriter). - /// </summary> - public virtual void Finish() - { - if (_sumWriter != null) { - var view = new DataView(Table, "", SORT, DataViewRowState.CurrentRows).ToTable(); - var toRemove = - view.Columns.Cast<DataColumn>().Where(column => column.ColumnName.StartsWith(INTERNAL_PREFIX)).ToList(); - foreach (var dataColumn in toRemove) { - view.Columns.Remove(dataColumn); - } - _sumWriter.WriteSumData(view); - } - } - - /// <summary> - /// Writes the result of one run into the summary data container. - /// </summary> - [MethodImpl(MethodImplOptions.Synchronized)] - //public virtual void Write(IModalDataContainer modData, string jobFileName, string jobName, string cycleFileName, - // Kilogram vehicleMass, Kilogram vehicleLoading, CubicMeter cargoVolume, uint gearCount) - public virtual void Write(IModalDataContainer modData, int jobNr, int runNr, VectoRunData runData) - { - var row = Table.NewRow(); - Table.Rows.Add(row); - - row[SORT] = jobNr * 1000 + runNr; - row[JOB] = string.Format("{0}-{1}", jobNr, runNr); //ReplaceNotAllowedCharacters(current); - row[INPUTFILE] = ReplaceNotAllowedCharacters(runData.JobName); - row[CYCLE] = ReplaceNotAllowedCharacters(runData.Cycle.Name + Constants.FileExtensions.CycleFile); - - row[STATUS] = modData.RunStatus; - - var vehicleLoading = 0.SI<Kilogram>(); - var cargoVolume = 0.SI<CubicMeter>(); - uint gearCount = 0u; - if (runData.Cycle.CycleType != CycleType.EngineOnly) { - row[VEHICLE_MANUFACTURER] = runData.VehicleData.Manufacturer; - row[VIN_NUMBER] = runData.VehicleData.VIN; - row[VEHICLE_MODEL] = runData.VehicleData.ModelName; - - row[HDV_CO2_VEHICLE_CLASS] = runData.VehicleData.VehicleClass.GetClassNumber(); - row[CURB_MASS] = runData.VehicleData.CurbWeight; - // - (runData.VehicleData.BodyAndTrailerWeight ?? 0.SI<Kilogram>()); - row[LOADING] = runData.VehicleData.Loading; - row[CARGO_VOLUME] = runData.VehicleData.CargoVolume; - - row[TOTAL_VEHICLE_MASS] = runData.VehicleData.TotalVehicleWeight; - row[ENGINE_MANUFACTURER] = runData.EngineData.Manufacturer; - row[ENGINE_MODEL] = runData.EngineData.ModelName; - row[ENGINE_FUEL_TYPE] = runData.EngineData.FuelType.GetLabel(); - row[ENGINE_RATED_POWER] = runData.EngineData.RatedPowerDeclared != null - ? runData.EngineData.RatedPowerDeclared.ConvertTo().Kilo.Watt - : runData.EngineData.FullLoadCurves[0].MaxPower.ConvertTo().Kilo.Watt; - row[ENGINE_IDLING_SPEED] = runData.EngineData.IdleSpeed.AsRPM.SI<Scalar>(); - row[ENGINE_RATED_SPEED] = runData.EngineData.RatedSpeedDeclared != null - ? runData.EngineData.RatedSpeedDeclared.AsRPM.SI<Scalar>() - : runData.EngineData.FullLoadCurves[0].RatedSpeed.AsRPM.SI<Scalar>(); - row[ENGINE_DISPLACEMENT] = runData.EngineData.Displacement.ConvertTo().Cubic.Centi.Meter; - - row[ENGINE_WHTC_URBAN] = runData.EngineData.WHTCUrban; - row[ENGINE_WHTC_RURAL] = runData.EngineData.WHTCRural; - row[ENGINE_WHTC_MOTORWAY] = runData.EngineData.WHTCMotorway; - row[ENGINE_BF_COLD_HOT] = runData.EngineData.ColdHotCorrectionFactor; - row[ENGINE_CF_REG_PER] = runData.EngineData.CorrectionFactorRegPer; - row[ENGINE_ACTUAL_CORRECTION_FACTOR] = runData.EngineData.FuelConsumptionCorrectionFactor; - - row[CD_x_A] = runData.AirdragData.CrossWindCorrectionCurve.AirDragArea; - - row[ROLLING_RESISTANCE_COEFFICIENT_WO_TRAILER] = - runData.VehicleData.RollResistanceCoefficientWithoutTrailer; - row[ROLLING_RESISTANCE_COEFFICIENT_W_TRAILER] = - runData.VehicleData.TotalRollResistanceCoefficient; - - row[R_DYN] = runData.VehicleData.DynamicTyreRadius; - - row[GEARBOX_MANUFACTURER] = runData.GearboxData.Manufacturer; - row[GEARBOX_MODEL] = runData.GearboxData.ModelName; - row[GEARBOX_TYPE] = runData.GearboxData.Type; - if (runData.GearboxData.Type.AutomaticTransmission()) { - row[GEAR_RATIO_FIRST_GEAR] = runData.GearboxData.Gears.Count > 0 - ? (double.IsNaN(runData.GearboxData.Gears.First().Value.Ratio) - ? runData.GearboxData.Gears.First().Value.TorqueConverterRatio.SI<Scalar>() - : runData.GearboxData.Gears.First().Value.Ratio.SI<Scalar>()) - : 0.SI<Scalar>(); - row[GEAR_RATIO_LAST_GEAR] = runData.GearboxData.Gears.Count > 0 - ? runData.GearboxData.Gears.Last().Value.Ratio.SI<Scalar>() - : 0.SI<Scalar>(); - row[TORQUECONVERTER_MANUFACTURER] = runData.GearboxData.TorqueConverterData.Manufacturer; - row[TORQUECONVERTER_MODEL] = runData.GearboxData.TorqueConverterData.ModelName; - } else { - row[GEAR_RATIO_FIRST_GEAR] = runData.GearboxData.Gears.Count > 0 - ? runData.GearboxData.Gears.First().Value.Ratio.SI<Scalar>() - : 0.SI<Scalar>(); - row[GEAR_RATIO_LAST_GEAR] = runData.GearboxData.Gears.Count > 0 - ? runData.GearboxData.Gears.Last().Value.Ratio.SI<Scalar>() - : 0.SI<Scalar>(); - row[TORQUECONVERTER_MANUFACTURER] = "n.a."; - row[TORQUECONVERTER_MODEL] = "n.a."; - } - row[RETARDER_TYPE] = runData.Retarder.Type.GetLabel(); - if (runData.Retarder.Type.IsDedicatedComponent()) { - row[RETARDER_MANUFACTURER] = runData.Retarder.Manufacturer; - row[RETARDER_MODEL] = runData.Retarder.ModelName; - } else { - row[RETARDER_MANUFACTURER] = "n.a."; - row[RETARDER_MODEL] = "n.a."; - } - - if (runData.AngledriveData != null) { - row[ANGLEDRIVE_MANUFACTURER] = runData.AngledriveData.Manufacturer; - row[ANGLEDRIVE_MODEL] = runData.AngledriveData.ModelName; - row[ANGLEDRIVE_RATIO] = runData.AngledriveData.Angledrive.Ratio; - } else { - row[ANGLEDRIVE_MANUFACTURER] = "n.a."; - row[ANGLEDRIVE_MODEL] = "n.a."; - row[ANGLEDRIVE_RATIO] = "n.a."; - } - - row[AXLE_MANUFACTURER] = runData.AxleGearData.Manufacturer; - row[AXLE_MODEL] = runData.AxleGearData.ModelName; - row[AXLE_RATIO] = runData.AxleGearData.AxleGear.Ratio.SI<Scalar>(); - - foreach (var aux in runData.Aux) { - if (aux.ID == Constants.Auxiliaries.IDs.PTOConsumer || aux.ID == Constants.Auxiliaries.IDs.PTOTransmission) { - continue; - } - var colName = string.Format(AUX_TECH_FORMAT, aux.ID); - - if (!Table.Columns.Contains(colName)) { - var col = Table.Columns.Add(colName, typeof(string)); - // move the new column to correct position - col.SetOrdinal(Table.Columns[CARGO_VOLUME].Ordinal); - } - - row[colName] = aux.Technology == null ? "" : string.Join("; ", aux.Technology); - } - - cargoVolume = runData.VehicleData.CargoVolume; - vehicleLoading = runData.VehicleData.Loading; - gearCount = (uint)runData.GearboxData.Gears.Count; - } - - - var totalTime = modData.Duration(); - row[TIME] = totalTime; - - var distance = modData.Distance(); - if (distance != null) { - row[DISTANCE] = distance.ConvertTo().Kilo.Meter; - } - - var speed = modData.Speed(); - if (speed != null) { - row[SPEED] = speed.ConvertTo().Kilo.Meter.Per.Hour; - } - - row[ALTITUDE_DELTA] = modData.AltitudeDelta(); - - row[FCMAP_H] = modData.FCMapPerSecond().ConvertTo().Gramm.Per.Hour; - var fcMapPerMeter = modData.FCMapPerMeter(); - if (fcMapPerMeter != null) { - row[FCMAP_KM] = fcMapPerMeter.ConvertTo().Gramm.Per.Kilo.Meter; - } - - row[FCAUXC_H] = modData.FuelConsumptionAuxStartStopPerSecond().ConvertTo().Gramm.Per.Hour; - var fuelConsumptionAuxStartStopCorrected = modData.FuelConsumptionAuxStartStop(); - if (fuelConsumptionAuxStartStopCorrected != null) { - row[FCAUXC_KM] = fuelConsumptionAuxStartStopCorrected.ConvertTo().Gramm.Per.Kilo.Meter; - } - - row[FCWHTCC_H] = modData.FuelConsumptionWHTCPerSecond().ConvertTo().Gramm.Per.Hour; - var fuelConsumptionWHTCCorrected = modData.FuelConsumptionWHTC(); - if (fuelConsumptionWHTCCorrected != null) { - row[FCWHTCC_KM] = fuelConsumptionWHTCCorrected.ConvertTo().Gramm.Per.Kilo.Meter; - } - - row[FCAAUX_H] = modData.FuelConsumptionAAUXPerSecond().ConvertTo().Gramm.Per.Hour; - var fuelConsumptionAaux = modData.FuelConsumptionAAUX(); - if (fuelConsumptionAaux != null) { - row[FCAAUX_KM] = fuelConsumptionAaux.ConvertTo().Gramm.Per.Kilo.Meter; - } - - row[FCFINAL_H] = modData.FuelConsumptionFinalPerSecond().ConvertTo().Gramm.Per.Hour; - var fcfinal = modData.FuelConsumptionFinal(); - if (fcfinal != null) { - row[FCFINAL_KM] = fcfinal.ConvertTo().Gramm.Per.Kilo.Meter; - } - - var fcPer100lkm = modData.FuelConsumptionFinalLiterPer100Kilometer(); - row[FCFINAL_LITERPER100KM] = fcPer100lkm; - if (vehicleLoading != null && !vehicleLoading.IsEqual(0) && fcPer100lkm != null) { - row[FCFINAL_LITERPER100TKM] = fcPer100lkm / - vehicleLoading.ConvertTo().Ton; - } - if (cargoVolume > 0 && fcPer100lkm != null) { - row[FCFINAL_LiterPer100M3KM] = fcPer100lkm / cargoVolume; - } - - var kilogramPerMeter = modData.CO2PerMeter(); - if (kilogramPerMeter != null) { - row[CO2_KM] = kilogramPerMeter.ConvertTo().Gramm.Per.Kilo.Meter; - if (vehicleLoading != null && !vehicleLoading.IsEqual(0)) { - row[CO2_TKM] = kilogramPerMeter.ConvertTo().Gramm.Per.Kilo.Meter / vehicleLoading.ConvertTo().Ton; - } - if (cargoVolume > 0) { - row[CO2_M3KM] = kilogramPerMeter.ConvertTo().Gramm.Per.Kilo.Meter / cargoVolume; - } - } - - row[P_WHEEL_POS] = modData.PowerWheelPositive().ConvertTo().Kilo.Watt; - - row[P_FCMAP_POS] = modData.TotalPowerEnginePositiveAverage().ConvertTo().Kilo.Watt; - - foreach (var aux in modData.Auxiliaries) { - string colName; - if (aux.Key == Constants.Auxiliaries.IDs.PTOConsumer || aux.Key == Constants.Auxiliaries.IDs.PTOTransmission) { - colName = string.Format(E_FORMAT, aux.Key); - } else { - colName = string.Format(E_AUX_FORMAT, aux.Key); - } - - if (!Table.Columns.Contains(colName)) { - var col = Table.Columns.Add(colName, typeof(SI)); - // move the new column to correct position - col.SetOrdinal(Table.Columns[E_AUX].Ordinal); - } - - row[colName] = modData.AuxiliaryWork(aux.Value).ConvertTo().Kilo.Watt.Hour; - } - - row[E_FCMAP_POS] = modData.TotalEngineWorkPositive().ConvertTo().Kilo.Watt.Hour; - row[E_FCMAP_NEG] = -modData.TotalEngineWorkNegative().ConvertTo().Kilo.Watt.Hour; - row[E_POWERTRAIN_INERTIA] = modData.PowerAccelerations().ConvertTo().Kilo.Watt.Hour; - row[E_AUX] = modData.WorkAuxiliaries().ConvertTo().Kilo.Watt.Hour; - row[E_CLUTCH_LOSS] = modData.WorkClutch().ConvertTo().Kilo.Watt.Hour; - row[E_TC_LOSS] = modData.WorkTorqueConverter().ConvertTo().Kilo.Watt.Hour; - row[E_SHIFT_LOSS] = modData.WorkGearshift().ConvertTo().Kilo.Watt.Hour; - row[E_GBX_LOSS] = modData.WorkGearbox().ConvertTo().Kilo.Watt.Hour; - row[E_RET_LOSS] = modData.WorkRetarder().ConvertTo().Kilo.Watt.Hour; - row[E_AXL_LOSS] = modData.WorkAxlegear().ConvertTo().Kilo.Watt.Hour; - row[E_ANGLE_LOSS] = modData.WorkAngledrive().ConvertTo().Kilo.Watt.Hour; - row[E_BRAKE] = modData.WorkTotalMechanicalBrake().ConvertTo().Kilo.Watt.Hour; - row[E_VEHICLE_INERTIA] = modData.WorkVehicleInertia().ConvertTo().Kilo.Watt.Hour; - row[E_AIR] = modData.WorkAirResistance().ConvertTo().Kilo.Watt.Hour; - row[E_ROLL] = modData.WorkRollingResistance().ConvertTo().Kilo.Watt.Hour; - row[E_GRAD] = modData.WorkRoadGradientResistance().ConvertTo().Kilo.Watt.Hour; - - //var acc = modData.AccelerationPer3Seconds(); - - - row[ACC] = modData.AccelerationAverage(); - row[ACC_POS] = modData.AccelerationsPositive(); - row[ACC_NEG] = modData.AccelerationsNegative(); - var accTimeShare = modData.AccelerationTimeShare(); - row[ACC_TIMESHARE] = accTimeShare; - var decTimeShare = modData.DecelerationTimeShare(); - row[DEC_TIMESHARE] = decTimeShare; - var cruiseTimeShare = modData.CruiseTimeShare(); - row[CRUISE_TIMESHARE] = cruiseTimeShare; - var stopTimeShare = modData.StopTimeShare(); - row[STOP_TIMESHARE] = stopTimeShare; - - row[MAX_SPEED] = modData.MaxSpeed().AsKmph.SI<Scalar>(); - row[MAX_ACCELERATION] = modData.MaxAcceleration(); - row[MAX_DECELERATION] = modData.MaxDeceleration(); - row[AVG_ENGINE_SPEED] = modData.AvgEngineSpeed().AsRPM.SI<Scalar>(); - row[MAX_ENGINE_SPEED] = modData.MaxEngineSpeed().AsRPM.SI<Scalar>(); - - row[ENGINE_FULL_LOAD_TIME_SHARE] = modData.EngineMaxLoadTimeShare(); - row[COASTING_TIME_SHARE] = modData.CoastingTimeShare(); - row[BRAKING_TIME_SHARE] = modData.BrakingTimeShare(); - - if (gearCount <= 0) { - return; - } - - row[NUM_GEARSHIFTS] = modData.GearshiftCount(); - var timeSharePerGear = modData.TimeSharePerGear(gearCount); - - for (uint i = 0; i <= gearCount; i++) { - var colName = string.Format(TIME_SHARE_PER_GEAR_FORMAT, i); - if (!Table.Columns.Contains(colName)) { - Table.Columns.Add(colName, typeof(SI)); - } - row[colName] = timeSharePerGear[i]; - } - if (accTimeShare != null && decTimeShare != null && cruiseTimeShare != null) { - var shareSum = accTimeShare + decTimeShare + cruiseTimeShare + stopTimeShare; - if (!shareSum.IsEqual(100)) { - Log.Error( - "Sumfile Error: driving behavior timeshares must sum up to 100%: acc: {0}%, dec: {1}%, cruise: {2}%, stop: {3}%, sum: {4}%", - accTimeShare.ToOutputFormat(1, null, false), decTimeShare.ToOutputFormat(1, null, false), - cruiseTimeShare.ToOutputFormat(1, null, false), stopTimeShare.ToOutputFormat(1, null, false), - shareSum.ToOutputFormat(1, null, false)); - } - } - } - - private static string ReplaceNotAllowedCharacters(string text) - { - return text.Replace('#', '_').Replace(',', '_').Replace('\n', '_').Replace('\r', '_'); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected void Dispose(bool disposing) - { - if (disposing) { - Table.Dispose(); - } - } - } +using System; +using System.Data; +using System.Linq; +using System.Runtime.CompilerServices; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Configuration; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data; + +// ReSharper disable MemberCanBePrivate.Global -- used by API! + +namespace TUGraz.VectoCore.OutputData +{ + public delegate void WriteSumData(IModalDataContainer data); + + /// <summary> + /// Class for the sum file in vecto. + /// </summary> + public class SummaryDataContainer : LoggingObject, IDisposable + { + // ReSharper disable InconsistentNaming + public const string INTERNAL_PREFIX = "INTERNAL"; + public const string SORT = INTERNAL_PREFIX + " Sorting"; + public const string JOB = "Job [-]"; + public const string INPUTFILE = "Input File [-]"; + public const string CYCLE = "Cycle [-]"; + public const string STATUS = "Status"; + public const string CURB_MASS = "Chassis curb mass [kg]"; + public const string LOADING = "Loading [kg]"; + + public const string VEHICLE_MANUFACTURER = "Vehicle manufacturer [-]"; + public const string VIN_NUMBER = "VIN number"; + public const string VEHICLE_MODEL = "Vehicle model [-]"; + + public const string ENGINE_MANUFACTURER = "Engine manufacturer [-]"; + public const string ENGINE_MODEL = "Engine model [-]"; + public const string ENGINE_FUEL_TYPE = "Engine fuel type [-]"; + public const string ENGINE_WHTC_URBAN = "Engine WHTCUrban"; + public const string ENGINE_WHTC_RURAL = "Engine WHTCRural"; + public const string ENGINE_WHTC_MOTORWAY = "Engine WHTCMotorway"; + public const string ENGINE_BF_COLD_HOT = "Engine BFColdHot"; + public const string ENGINE_CF_REG_PER = "Engine CFRegPer"; + public const string ENGINE_ACTUAL_CORRECTION_FACTOR = "Engine actual CF"; + public const string ENGINE_RATED_POWER = "Engine rated power [kW]"; + public const string ENGINE_IDLING_SPEED = "Engine idling speed [rpm]"; + public const string ENGINE_RATED_SPEED = "Engine rated speed [rpm]"; + public const string ENGINE_DISPLACEMENT = "Engine displacement [ccm]"; + + public const string ROLLING_RESISTANCE_COEFFICIENT_W_TRAILER = "total RRC [-]"; + public const string ROLLING_RESISTANCE_COEFFICIENT_WO_TRAILER = "weighted RRC w/o trailer [-]"; + + public const string GEARBOX_MANUFACTURER = "Gearbox manufacturer [-]"; + public const string GEARBOX_MODEL = "Gearbox model [-]"; + public const string GEARBOX_TYPE = "Gearbox type [-]"; + public const string GEAR_RATIO_FIRST_GEAR = "Gear ratio first gear [-]"; + public const string GEAR_RATIO_LAST_GEAR = "Gear ratio last gear [-]"; + + public const string TORQUECONVERTER_MANUFACTURER = "Torque converter manufacturer [-]"; + public const string TORQUECONVERTER_MODEL = "Torque converter model [-]"; + + public const string RETARDER_MANUFACTURER = "Retarder manufacturer [-]"; + public const string RETARDER_MODEL = "Retarder model [-]"; + public const string RETARDER_TYPE = "Retarder type [-]"; + + public const string ANGLEDRIVE_MANUFACTURER = "Angledrive manufacturer [-]"; + public const string ANGLEDRIVE_MODEL = "Angledrive model [-]"; + public const string ANGLEDRIVE_RATIO = "Angledrive ratio [-]"; + + public const string AXLE_MANUFACTURER = "Axle manufacturer [-]"; + public const string AXLE_MODEL = "Axle model [-]"; + public const string AXLE_RATIO = "Axle gear ratio [-]"; + + public const string AUX_TECH_FORMAT = "Auxiliary technology {0} [-]"; + + public const string HDV_CO2_VEHICLE_CLASS = "HDV CO2 vehicle class [-]"; + public const string TOTAL_VEHICLE_MASS = "Total vehicle mass [kg]"; + public const string CD_x_A = "CdxA [m²]"; + //public const string ROLLING_RESISTANCE_COEFFICIENT = "weighed RRC [-]"; + public const string R_DYN = "r_dyn [m]"; + + public const string CARGO_VOLUME = "Cargo Volume [m³]"; + public const string TIME = "time [s]"; + public const string DISTANCE = "distance [km]"; + public const string SPEED = "speed [km/h]"; + public const string ALTITUDE_DELTA = "altitudeDelta [m]"; + + public const string FCMAP_H = "FC-Map [g/h]"; + public const string FCMAP_KM = "FC-Map [g/km]"; + public const string FCAUXC_H = "FC-AUXc [g/h]"; + public const string FCAUXC_KM = "FC-AUXc [g/km]"; + public const string FCWHTCC_H = "FC-WHTCc [g/h]"; + public const string FCWHTCC_KM = "FC-WHTCc [g/km]"; + public const string FCAAUX_H = "FC-AAUX [g/h]"; + public const string FCAAUX_KM = "FC-AAUX [g/km]"; + + public const string FCFINAL_H = "FC-Final [g/h]"; + public const string FCFINAL_KM = "FC-Final [g/km]"; + public const string FCFINAL_LITERPER100KM = "FC-Final [l/100km]"; + public const string FCFINAL_LITERPER100TKM = "FC-Final [l/100tkm]"; + public const string FCFINAL_LiterPer100M3KM = "FC-Final [l/100m³km]"; + + public const string CO2_KM = "CO2 [g/km]"; + public const string CO2_TKM = "CO2 [g/tkm]"; + public const string CO2_M3KM = "CO2 [g/m³km]"; + + public const string P_WHEEL_POS = "P_wheel_in_pos [kW]"; + public const string P_FCMAP_POS = "P_fcmap_pos [kW]"; + + public const string E_FORMAT = "E_{0} [kWh]"; + public const string E_AUX_FORMAT = "E_aux_{0} [kWh]"; + public const string E_AUX = "E_aux_sum [kWh]"; + + public const string E_AIR = "E_air [kWh]"; + public const string E_ROLL = "E_roll [kWh]"; + public const string E_GRAD = "E_grad [kWh]"; + public const string E_VEHICLE_INERTIA = "E_vehi_inertia [kWh]"; + public const string E_POWERTRAIN_INERTIA = "E_powertrain_inertia [kWh]"; + public const string E_BRAKE = "E_brake [kWh]"; + public const string E_GBX_LOSS = "E_gbx_loss [kWh]"; + public const string E_SHIFT_LOSS = "E_shift_loss [kWh]"; + public const string E_AXL_LOSS = "E_axl_loss [kWh]"; + public const string E_RET_LOSS = "E_ret_loss [kWh]"; + public const string E_TC_LOSS = "E_tc_loss [kWh]"; + public const string E_ANGLE_LOSS = "E_angle_loss [kWh]"; + public const string E_CLUTCH_LOSS = "E_clutch_loss [kWh]"; + public const string E_FCMAP_POS = "E_fcmap_pos [kWh]"; + public const string E_FCMAP_NEG = "E_fcmap_neg [kWh]"; + + public const string ACC = "a [m/s^2]"; + public const string ACC_POS = "a_pos [m/s^2]"; + public const string ACC_NEG = "a_neg [m/s^2]"; + + public const string ACC_TIMESHARE = "AccelerationTimeShare [%]"; + public const string DEC_TIMESHARE = "DecelerationTimeShare [%]"; + public const string CRUISE_TIMESHARE = "CruiseTimeShare [%]"; + public const string STOP_TIMESHARE = "StopTimeShare [%]"; + + public const string MAX_SPEED = "max. speed [km/h"; + public const string MAX_ACCELERATION = "max. acc [m/s²]"; + public const string MAX_DECELERATION = "max. dec [m/s²]"; + public const string AVG_ENGINE_SPEED = "n_eng_avg [rpm]"; + public const string MAX_ENGINE_SPEED = "n_eng_max [rpm]"; + public const string NUM_GEARSHIFTS = "gear shifts [-]"; + public const string ENGINE_FULL_LOAD_TIME_SHARE = "Engine max. Load time share [%]"; + public const string COASTING_TIME_SHARE = "CoastingTimeShare [%]"; + public const string BRAKING_TIME_SHARE = "BrakingTImeShare [%]"; + + public const string TIME_SHARE_PER_GEAR_FORMAT = "Gear {0} TimeShare [%]"; + + // ReSharper restore InconsistentNaming + + internal readonly DataTable Table; + private readonly ISummaryWriter _sumWriter; + + + protected SummaryDataContainer() {} + + /// <summary> + /// Initializes a new instance of the <see cref="SummaryDataContainer"/> class. + /// </summary> + /// <param name="writer"></param> + public SummaryDataContainer(ISummaryWriter writer) + { + _sumWriter = writer; + + Table = new DataTable(); + + Table.Columns.AddRange(new[] { + Tuple.Create(SORT, typeof(int)), + Tuple.Create(JOB, typeof(string)), + Tuple.Create(INPUTFILE, typeof(string)), + Tuple.Create(CYCLE, typeof(string)), + Tuple.Create(STATUS, typeof(string)), + Tuple.Create(VEHICLE_MANUFACTURER, typeof(string)), + Tuple.Create(VIN_NUMBER, typeof(string)), + Tuple.Create(VEHICLE_MODEL, typeof(string)), + Tuple.Create(HDV_CO2_VEHICLE_CLASS, typeof(string)), + Tuple.Create(CURB_MASS, typeof(SI)), + Tuple.Create(LOADING, typeof(SI)), + Tuple.Create(TOTAL_VEHICLE_MASS, typeof(SI)), + Tuple.Create(ENGINE_MANUFACTURER, typeof(string)), + Tuple.Create(ENGINE_MODEL, typeof(string)), + Tuple.Create(ENGINE_FUEL_TYPE, typeof(string)), + Tuple.Create(ENGINE_RATED_POWER, typeof(SI)), + Tuple.Create(ENGINE_IDLING_SPEED, typeof(SI)), + Tuple.Create(ENGINE_RATED_SPEED, typeof(SI)), + Tuple.Create(ENGINE_DISPLACEMENT, typeof(SI)), + Tuple.Create(ENGINE_WHTC_URBAN, typeof(double)), + Tuple.Create(ENGINE_WHTC_RURAL, typeof(double)), + Tuple.Create(ENGINE_WHTC_MOTORWAY, typeof(double)), + Tuple.Create(ENGINE_BF_COLD_HOT, typeof(double)), + Tuple.Create(ENGINE_CF_REG_PER, typeof(double)), + Tuple.Create(ENGINE_ACTUAL_CORRECTION_FACTOR, typeof(double)), + Tuple.Create(CD_x_A, typeof(SI)), + Tuple.Create(ROLLING_RESISTANCE_COEFFICIENT_W_TRAILER, typeof(double)), + Tuple.Create(ROLLING_RESISTANCE_COEFFICIENT_WO_TRAILER, typeof(double)), + Tuple.Create(R_DYN, typeof(SI)), + Tuple.Create(GEARBOX_MANUFACTURER, typeof(string)), + Tuple.Create(GEARBOX_MODEL, typeof(string)), + Tuple.Create(GEARBOX_TYPE, typeof(string)), + Tuple.Create(GEAR_RATIO_FIRST_GEAR, typeof(SI)), + Tuple.Create(GEAR_RATIO_LAST_GEAR, typeof(SI)), + Tuple.Create(TORQUECONVERTER_MANUFACTURER, typeof(string)), + Tuple.Create(TORQUECONVERTER_MODEL, typeof(string)), + Tuple.Create(RETARDER_MANUFACTURER, typeof(string)), + Tuple.Create(RETARDER_MODEL, typeof(string)), + Tuple.Create(RETARDER_TYPE, typeof(string)), + Tuple.Create(ANGLEDRIVE_MANUFACTURER, typeof(string)), + Tuple.Create(ANGLEDRIVE_MODEL, typeof(string)), + Tuple.Create(ANGLEDRIVE_RATIO, typeof(string)), + Tuple.Create(AXLE_MANUFACTURER, typeof(string)), + Tuple.Create(AXLE_MODEL, typeof(string)), + Tuple.Create(AXLE_RATIO, typeof(SI)), + Tuple.Create(string.Format(AUX_TECH_FORMAT, Constants.Auxiliaries.IDs.SteeringPump), typeof(string)), + Tuple.Create(string.Format(AUX_TECH_FORMAT, Constants.Auxiliaries.IDs.Fan), typeof(string)), + Tuple.Create(string.Format(AUX_TECH_FORMAT, Constants.Auxiliaries.IDs.HeatingVentilationAirCondition), + typeof(string)), + Tuple.Create(string.Format(AUX_TECH_FORMAT, Constants.Auxiliaries.IDs.PneumaticSystem), typeof(string)), + Tuple.Create(string.Format(AUX_TECH_FORMAT, Constants.Auxiliaries.IDs.ElectricSystem), typeof(string)), + }.Select(x => new DataColumn(x.Item1, x.Item2)).ToArray()); + + Table.Columns.AddRange(new[] { + CARGO_VOLUME, + TIME, DISTANCE, + SPEED, ALTITUDE_DELTA, + FCMAP_H, FCMAP_KM, + FCAUXC_H, FCAUXC_KM, + FCWHTCC_H, FCWHTCC_KM, + FCAAUX_H, FCAAUX_KM, + FCFINAL_H, FCFINAL_KM, + FCFINAL_LITERPER100KM, FCFINAL_LITERPER100TKM, FCFINAL_LiterPer100M3KM, + CO2_KM, CO2_TKM, CO2_M3KM, + P_WHEEL_POS, P_FCMAP_POS, + E_FCMAP_POS, E_FCMAP_NEG, E_POWERTRAIN_INERTIA, + E_AUX, E_CLUTCH_LOSS, E_TC_LOSS, E_SHIFT_LOSS, E_GBX_LOSS, + E_RET_LOSS, E_ANGLE_LOSS, E_AXL_LOSS, E_BRAKE, E_VEHICLE_INERTIA, E_AIR, E_ROLL, E_GRAD, + ACC, ACC_POS, ACC_NEG, ACC_TIMESHARE, DEC_TIMESHARE, CRUISE_TIMESHARE, STOP_TIMESHARE, + MAX_SPEED, MAX_ACCELERATION, MAX_DECELERATION, AVG_ENGINE_SPEED, MAX_ENGINE_SPEED, NUM_GEARSHIFTS, + ENGINE_FULL_LOAD_TIME_SHARE, COASTING_TIME_SHARE, BRAKING_TIME_SHARE + }.Select(x => new DataColumn(x, typeof(SI))).ToArray()); + } + + /// <summary> + /// Finishes the summary data container (writes the data to the sumWriter). + /// </summary> + public virtual void Finish() + { + if (_sumWriter != null) { + var view = new DataView(Table, "", SORT, DataViewRowState.CurrentRows).ToTable(); + var toRemove = + view.Columns.Cast<DataColumn>().Where(column => column.ColumnName.StartsWith(INTERNAL_PREFIX)).ToList(); + foreach (var dataColumn in toRemove) { + view.Columns.Remove(dataColumn); + } + _sumWriter.WriteSumData(view); + } + } + + /// <summary> + /// Writes the result of one run into the summary data container. + /// </summary> + [MethodImpl(MethodImplOptions.Synchronized)] + //public virtual void Write(IModalDataContainer modData, string jobFileName, string jobName, string cycleFileName, + // Kilogram vehicleMass, Kilogram vehicleLoading, CubicMeter cargoVolume, uint gearCount) + public virtual void Write(IModalDataContainer modData, int jobNr, int runNr, VectoRunData runData) + { + var row = Table.NewRow(); + Table.Rows.Add(row); + + row[SORT] = jobNr * 1000 + runNr; + row[JOB] = string.Format("{0}-{1}", jobNr, runNr); //ReplaceNotAllowedCharacters(current); + row[INPUTFILE] = ReplaceNotAllowedCharacters(runData.JobName); + row[CYCLE] = ReplaceNotAllowedCharacters(runData.Cycle.Name + Constants.FileExtensions.CycleFile); + + row[STATUS] = modData.RunStatus; + + var vehicleLoading = 0.SI<Kilogram>(); + var cargoVolume = 0.SI<CubicMeter>(); + uint gearCount = 0u; + if (runData.Cycle.CycleType != CycleType.EngineOnly) { + row[VEHICLE_MANUFACTURER] = runData.VehicleData.Manufacturer; + row[VIN_NUMBER] = runData.VehicleData.VIN; + row[VEHICLE_MODEL] = runData.VehicleData.ModelName; + + row[HDV_CO2_VEHICLE_CLASS] = runData.VehicleData.VehicleClass.GetClassNumber(); + row[CURB_MASS] = runData.VehicleData.CurbWeight; + // - (runData.VehicleData.BodyAndTrailerWeight ?? 0.SI<Kilogram>()); + row[LOADING] = runData.VehicleData.Loading; + row[CARGO_VOLUME] = runData.VehicleData.CargoVolume; + + row[TOTAL_VEHICLE_MASS] = runData.VehicleData.TotalVehicleWeight; + row[ENGINE_MANUFACTURER] = runData.EngineData.Manufacturer; + row[ENGINE_MODEL] = runData.EngineData.ModelName; + row[ENGINE_FUEL_TYPE] = runData.EngineData.FuelType.GetLabel(); + row[ENGINE_RATED_POWER] = runData.EngineData.RatedPowerDeclared != null + ? runData.EngineData.RatedPowerDeclared.ConvertTo().Kilo.Watt + : runData.EngineData.FullLoadCurves[0].MaxPower.ConvertTo().Kilo.Watt; + row[ENGINE_IDLING_SPEED] = runData.EngineData.IdleSpeed.AsRPM.SI<Scalar>(); + row[ENGINE_RATED_SPEED] = runData.EngineData.RatedSpeedDeclared != null + ? runData.EngineData.RatedSpeedDeclared.AsRPM.SI<Scalar>() + : runData.EngineData.FullLoadCurves[0].RatedSpeed.AsRPM.SI<Scalar>(); + row[ENGINE_DISPLACEMENT] = runData.EngineData.Displacement.ConvertTo().Cubic.Centi.Meter; + + row[ENGINE_WHTC_URBAN] = runData.EngineData.WHTCUrban; + row[ENGINE_WHTC_RURAL] = runData.EngineData.WHTCRural; + row[ENGINE_WHTC_MOTORWAY] = runData.EngineData.WHTCMotorway; + row[ENGINE_BF_COLD_HOT] = runData.EngineData.ColdHotCorrectionFactor; + row[ENGINE_CF_REG_PER] = runData.EngineData.CorrectionFactorRegPer; + row[ENGINE_ACTUAL_CORRECTION_FACTOR] = runData.EngineData.FuelConsumptionCorrectionFactor; + + row[CD_x_A] = runData.AirdragData.CrossWindCorrectionCurve.AirDragArea; + + row[ROLLING_RESISTANCE_COEFFICIENT_WO_TRAILER] = + runData.VehicleData.RollResistanceCoefficientWithoutTrailer; + row[ROLLING_RESISTANCE_COEFFICIENT_W_TRAILER] = + runData.VehicleData.TotalRollResistanceCoefficient; + + row[R_DYN] = runData.VehicleData.DynamicTyreRadius; + + row[GEARBOX_MANUFACTURER] = runData.GearboxData.Manufacturer; + row[GEARBOX_MODEL] = runData.GearboxData.ModelName; + row[GEARBOX_TYPE] = runData.GearboxData.Type; + if (runData.GearboxData.Type.AutomaticTransmission()) { + row[GEAR_RATIO_FIRST_GEAR] = runData.GearboxData.Gears.Count > 0 + ? (double.IsNaN(runData.GearboxData.Gears.First().Value.Ratio) + ? runData.GearboxData.Gears.First().Value.TorqueConverterRatio.SI<Scalar>() + : runData.GearboxData.Gears.First().Value.Ratio.SI<Scalar>()) + : 0.SI<Scalar>(); + row[GEAR_RATIO_LAST_GEAR] = runData.GearboxData.Gears.Count > 0 + ? runData.GearboxData.Gears.Last().Value.Ratio.SI<Scalar>() + : 0.SI<Scalar>(); + row[TORQUECONVERTER_MANUFACTURER] = runData.GearboxData.TorqueConverterData.Manufacturer; + row[TORQUECONVERTER_MODEL] = runData.GearboxData.TorqueConverterData.ModelName; + } else { + row[GEAR_RATIO_FIRST_GEAR] = runData.GearboxData.Gears.Count > 0 + ? runData.GearboxData.Gears.First().Value.Ratio.SI<Scalar>() + : 0.SI<Scalar>(); + row[GEAR_RATIO_LAST_GEAR] = runData.GearboxData.Gears.Count > 0 + ? runData.GearboxData.Gears.Last().Value.Ratio.SI<Scalar>() + : 0.SI<Scalar>(); + row[TORQUECONVERTER_MANUFACTURER] = "n.a."; + row[TORQUECONVERTER_MODEL] = "n.a."; + } + row[RETARDER_TYPE] = runData.Retarder.Type.GetLabel(); + if (runData.Retarder.Type.IsDedicatedComponent()) { + row[RETARDER_MANUFACTURER] = runData.Retarder.Manufacturer; + row[RETARDER_MODEL] = runData.Retarder.ModelName; + } else { + row[RETARDER_MANUFACTURER] = "n.a."; + row[RETARDER_MODEL] = "n.a."; + } + + if (runData.AngledriveData != null) { + row[ANGLEDRIVE_MANUFACTURER] = runData.AngledriveData.Manufacturer; + row[ANGLEDRIVE_MODEL] = runData.AngledriveData.ModelName; + row[ANGLEDRIVE_RATIO] = runData.AngledriveData.Angledrive.Ratio; + } else { + row[ANGLEDRIVE_MANUFACTURER] = "n.a."; + row[ANGLEDRIVE_MODEL] = "n.a."; + row[ANGLEDRIVE_RATIO] = "n.a."; + } + + row[AXLE_MANUFACTURER] = runData.AxleGearData.Manufacturer; + row[AXLE_MODEL] = runData.AxleGearData.ModelName; + row[AXLE_RATIO] = runData.AxleGearData.AxleGear.Ratio.SI<Scalar>(); + + foreach (var aux in runData.Aux) { + if (aux.ID == Constants.Auxiliaries.IDs.PTOConsumer || aux.ID == Constants.Auxiliaries.IDs.PTOTransmission) { + continue; + } + var colName = string.Format(AUX_TECH_FORMAT, aux.ID); + + if (!Table.Columns.Contains(colName)) { + var col = Table.Columns.Add(colName, typeof(string)); + // move the new column to correct position + col.SetOrdinal(Table.Columns[CARGO_VOLUME].Ordinal); + } + + row[colName] = aux.Technology == null ? "" : string.Join("; ", aux.Technology); + } + + cargoVolume = runData.VehicleData.CargoVolume; + vehicleLoading = runData.VehicleData.Loading; + gearCount = (uint)runData.GearboxData.Gears.Count; + } + + + var totalTime = modData.Duration(); + row[TIME] = totalTime; + + var distance = modData.Distance(); + if (distance != null) { + row[DISTANCE] = distance.ConvertTo().Kilo.Meter; + } + + var speed = modData.Speed(); + if (speed != null) { + row[SPEED] = speed.ConvertTo().Kilo.Meter.Per.Hour; + } + + row[ALTITUDE_DELTA] = modData.AltitudeDelta(); + + row[FCMAP_H] = modData.FCMapPerSecond().ConvertTo().Gramm.Per.Hour; + var fcMapPerMeter = modData.FCMapPerMeter(); + if (fcMapPerMeter != null) { + row[FCMAP_KM] = fcMapPerMeter.ConvertTo().Gramm.Per.Kilo.Meter; + } + + row[FCAUXC_H] = modData.FuelConsumptionAuxStartStopPerSecond().ConvertTo().Gramm.Per.Hour; + var fuelConsumptionAuxStartStopCorrected = modData.FuelConsumptionAuxStartStop(); + if (fuelConsumptionAuxStartStopCorrected != null) { + row[FCAUXC_KM] = fuelConsumptionAuxStartStopCorrected.ConvertTo().Gramm.Per.Kilo.Meter; + } + + row[FCWHTCC_H] = modData.FuelConsumptionWHTCPerSecond().ConvertTo().Gramm.Per.Hour; + var fuelConsumptionWHTCCorrected = modData.FuelConsumptionWHTC(); + if (fuelConsumptionWHTCCorrected != null) { + row[FCWHTCC_KM] = fuelConsumptionWHTCCorrected.ConvertTo().Gramm.Per.Kilo.Meter; + } + + row[FCAAUX_H] = modData.FuelConsumptionAAUXPerSecond().ConvertTo().Gramm.Per.Hour; + var fuelConsumptionAaux = modData.FuelConsumptionAAUX(); + if (fuelConsumptionAaux != null) { + row[FCAAUX_KM] = fuelConsumptionAaux.ConvertTo().Gramm.Per.Kilo.Meter; + } + + row[FCFINAL_H] = modData.FuelConsumptionFinalPerSecond().ConvertTo().Gramm.Per.Hour; + var fcfinal = modData.FuelConsumptionFinal(); + if (fcfinal != null) { + row[FCFINAL_KM] = fcfinal.ConvertTo().Gramm.Per.Kilo.Meter; + } + + var fcPer100lkm = modData.FuelConsumptionFinalLiterPer100Kilometer(); + row[FCFINAL_LITERPER100KM] = fcPer100lkm; + if (vehicleLoading != null && !vehicleLoading.IsEqual(0) && fcPer100lkm != null) { + row[FCFINAL_LITERPER100TKM] = fcPer100lkm / + vehicleLoading.ConvertTo().Ton; + } + if (cargoVolume > 0 && fcPer100lkm != null) { + row[FCFINAL_LiterPer100M3KM] = fcPer100lkm / cargoVolume; + } + + var kilogramPerMeter = modData.CO2PerMeter(); + if (kilogramPerMeter != null) { + row[CO2_KM] = kilogramPerMeter.ConvertTo().Gramm.Per.Kilo.Meter; + if (vehicleLoading != null && !vehicleLoading.IsEqual(0)) { + row[CO2_TKM] = kilogramPerMeter.ConvertTo().Gramm.Per.Kilo.Meter / vehicleLoading.ConvertTo().Ton; + } + if (cargoVolume > 0) { + row[CO2_M3KM] = kilogramPerMeter.ConvertTo().Gramm.Per.Kilo.Meter / cargoVolume; + } + } + + row[P_WHEEL_POS] = modData.PowerWheelPositive().ConvertTo().Kilo.Watt; + + row[P_FCMAP_POS] = modData.TotalPowerEnginePositiveAverage().ConvertTo().Kilo.Watt; + + foreach (var aux in modData.Auxiliaries) { + string colName; + if (aux.Key == Constants.Auxiliaries.IDs.PTOConsumer || aux.Key == Constants.Auxiliaries.IDs.PTOTransmission) { + colName = string.Format(E_FORMAT, aux.Key); + } else { + colName = string.Format(E_AUX_FORMAT, aux.Key); + } + + if (!Table.Columns.Contains(colName)) { + var col = Table.Columns.Add(colName, typeof(SI)); + // move the new column to correct position + col.SetOrdinal(Table.Columns[E_AUX].Ordinal); + } + + row[colName] = modData.AuxiliaryWork(aux.Value).ConvertTo().Kilo.Watt.Hour; + } + + row[E_FCMAP_POS] = modData.TotalEngineWorkPositive().ConvertTo().Kilo.Watt.Hour; + row[E_FCMAP_NEG] = -modData.TotalEngineWorkNegative().ConvertTo().Kilo.Watt.Hour; + row[E_POWERTRAIN_INERTIA] = modData.PowerAccelerations().ConvertTo().Kilo.Watt.Hour; + row[E_AUX] = modData.WorkAuxiliaries().ConvertTo().Kilo.Watt.Hour; + row[E_CLUTCH_LOSS] = modData.WorkClutch().ConvertTo().Kilo.Watt.Hour; + row[E_TC_LOSS] = modData.WorkTorqueConverter().ConvertTo().Kilo.Watt.Hour; + row[E_SHIFT_LOSS] = modData.WorkGearshift().ConvertTo().Kilo.Watt.Hour; + row[E_GBX_LOSS] = modData.WorkGearbox().ConvertTo().Kilo.Watt.Hour; + row[E_RET_LOSS] = modData.WorkRetarder().ConvertTo().Kilo.Watt.Hour; + row[E_AXL_LOSS] = modData.WorkAxlegear().ConvertTo().Kilo.Watt.Hour; + row[E_ANGLE_LOSS] = modData.WorkAngledrive().ConvertTo().Kilo.Watt.Hour; + row[E_BRAKE] = modData.WorkTotalMechanicalBrake().ConvertTo().Kilo.Watt.Hour; + row[E_VEHICLE_INERTIA] = modData.WorkVehicleInertia().ConvertTo().Kilo.Watt.Hour; + row[E_AIR] = modData.WorkAirResistance().ConvertTo().Kilo.Watt.Hour; + row[E_ROLL] = modData.WorkRollingResistance().ConvertTo().Kilo.Watt.Hour; + row[E_GRAD] = modData.WorkRoadGradientResistance().ConvertTo().Kilo.Watt.Hour; + + //var acc = modData.AccelerationPer3Seconds(); + + + row[ACC] = modData.AccelerationAverage(); + row[ACC_POS] = modData.AccelerationsPositive(); + row[ACC_NEG] = modData.AccelerationsNegative(); + var accTimeShare = modData.AccelerationTimeShare(); + row[ACC_TIMESHARE] = accTimeShare; + var decTimeShare = modData.DecelerationTimeShare(); + row[DEC_TIMESHARE] = decTimeShare; + var cruiseTimeShare = modData.CruiseTimeShare(); + row[CRUISE_TIMESHARE] = cruiseTimeShare; + var stopTimeShare = modData.StopTimeShare(); + row[STOP_TIMESHARE] = stopTimeShare; + + row[MAX_SPEED] = modData.MaxSpeed().AsKmph.SI<Scalar>(); + row[MAX_ACCELERATION] = modData.MaxAcceleration(); + row[MAX_DECELERATION] = modData.MaxDeceleration(); + row[AVG_ENGINE_SPEED] = modData.AvgEngineSpeed().AsRPM.SI<Scalar>(); + row[MAX_ENGINE_SPEED] = modData.MaxEngineSpeed().AsRPM.SI<Scalar>(); + + row[ENGINE_FULL_LOAD_TIME_SHARE] = modData.EngineMaxLoadTimeShare(); + row[COASTING_TIME_SHARE] = modData.CoastingTimeShare(); + row[BRAKING_TIME_SHARE] = modData.BrakingTimeShare(); + + if (gearCount <= 0) { + return; + } + + row[NUM_GEARSHIFTS] = modData.GearshiftCount(); + var timeSharePerGear = modData.TimeSharePerGear(gearCount); + + for (uint i = 0; i <= gearCount; i++) { + var colName = string.Format(TIME_SHARE_PER_GEAR_FORMAT, i); + if (!Table.Columns.Contains(colName)) { + Table.Columns.Add(colName, typeof(SI)); + } + row[colName] = timeSharePerGear[i]; + } + if (accTimeShare != null && decTimeShare != null && cruiseTimeShare != null) { + var shareSum = accTimeShare + decTimeShare + cruiseTimeShare + stopTimeShare; + if (!shareSum.IsEqual(100)) { + Log.Error( + "Sumfile Error: driving behavior timeshares must sum up to 100%: acc: {0}%, dec: {1}%, cruise: {2}%, stop: {3}%, sum: {4}%", + accTimeShare.ToOutputFormat(1, null, false), decTimeShare.ToOutputFormat(1, null, false), + cruiseTimeShare.ToOutputFormat(1, null, false), stopTimeShare.ToOutputFormat(1, null, false), + shareSum.ToOutputFormat(1, null, false)); + } + } + } + + private static string ReplaceNotAllowedCharacters(string text) + { + return text.Replace('#', '_').Replace(',', '_').Replace('\n', '_').Replace('\r', '_'); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected void Dispose(bool disposing) + { + if (disposing) { + Table.Dispose(); + } + } + } } \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/Reports/ModDataTest.cs b/VectoCore/VectoCoreTest/Reports/ModDataTest.cs index 5ed3af872f8f3e5b03d2f8f18c1ea0d7d75a19d0..660c3311774a1ec69c9a3647edf6765bd8c858cb 100644 --- a/VectoCore/VectoCoreTest/Reports/ModDataTest.cs +++ b/VectoCore/VectoCoreTest/Reports/ModDataTest.cs @@ -29,475 +29,480 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using NUnit.Framework; -using TUGraz.VectoCommon.InputData; -using TUGraz.VectoCommon.Models; -using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore.Configuration; -using TUGraz.VectoCore.InputData.FileIO.JSON; -using TUGraz.VectoCore.Models.Simulation.Data; -using TUGraz.VectoCore.Models.Simulation.Impl; -using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; -using TUGraz.VectoCore.Models.SimulationComponent.Impl; -using TUGraz.VectoCore.OutputData; -using TUGraz.VectoCore.OutputData.FileIO; -using TUGraz.VectoCore.Tests.Integration; -using TUGraz.VectoCore.Tests.Utils; -using Assert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert; - -namespace TUGraz.VectoCore.Tests.Reports -{ - [TestFixture] - public class ModDataTest - { - [TestCase()] - public void ModDataIntegritySimpleTest() - { - var cycleData = new[] { - // <s>,<v>,<grad>,<stop> - " 0, 20, 0, 0", - " 100, 60, 0, 0", - "1000, 60, 0, 0", - "1500, 40, 1, 0", - "2000, 50,-1, 0", - "2500, 0, 0, 2" - }; - var cycle = SimpleDrivingCycles.CreateCycleData(cycleData); - var sumData = new SummaryDataContainer(null); - var run = Truck40tPowerTrain.CreateEngineeringRun(cycle, "Truck_ModDataIntegrity.vmod"); - - var engineData = MockSimulationDataFactory.CreateEngineDataFromFile(Truck40tPowerTrain.EngineFile, 0); - - // get a reference to the mod-data because the modaldata container clears it after simulation - var modData = ((ModalDataContainer)run.GetContainer().ModalData).Data; - var auxKeys = ((ModalDataContainer)run.GetContainer().ModalData).Auxiliaries; - - run.Run(); - Assert.IsTrue(run.FinishedWithoutErrors); - - AssertModDataIntegrity(modData, auxKeys, cycle.Entries.Last().Distance, engineData.ConsumptionMap); - } - - [TestCase(@"TestData\Integration\DeclarationMode\Class2_RigidTruck_4x2\Class2_RigidTruck_DECL.vecto")] - public void TestFullCycleModDataIntegrityDeclMT(string jobName) - { - RunSimulation(jobName, ExecutionMode.Declaration); - } - - [TestCase(@"TestData\Integration\EngineeringMode\Class2_RigidTruck_4x2\Class2_RigidTruck_ENG.vecto"), - TestCase(@"TestData\Integration\EngineeringMode\Class5_Tractor_4x2\Class5_Tractor_ENG.vecto"), - TestCase(@"TestData\Integration\EngineeringMode\Class9_RigidTruck_6x2_PTO\Class9_RigidTruck_ENG_PTO.vecto"),] - public void TestFullCycleModDataIntegrityMT(string jobName) - { - RunSimulation(jobName, ExecutionMode.Engineering); - } - - private static void RunSimulation(string jobName, ExecutionMode mode) - { - var fileWriter = new FileOutputWriter(jobName); - var sumData = new SummaryDataContainer(fileWriter); - - var jobContainer = new JobContainer(sumData); - var inputData = JSONInputDataFactory.ReadJsonJob(jobName); - - var runsFactory = new SimulatorFactory(mode, inputData, fileWriter) { WriteModalResults = true }; - - jobContainer.AddRuns(runsFactory); - var modData = new List<Tuple<ModalResults, Meter>>(); - foreach (var run in jobContainer.Runs) { - modData.Add(Tuple.Create(((ModalDataContainer)run.Run.GetContainer().ModalData).Data, - ((DistanceBasedDrivingCycle)((VehicleContainer)run.Run.GetContainer()).DrivingCycle).Data.Entries.Last() - .Distance)); - } - var auxKeys = - new Dictionary<string, DataColumn>( - ((ModalDataContainer)jobContainer.Runs.First().Run.GetContainer().ModalData).Auxiliaries); - jobContainer.Execute(); - jobContainer.WaitFinished(); - - // mod files will be stored in e.g. - // VectoCoreTest\bin\Debug\TestData\Integration\EngineeringMode\Class2_RigidTruck_4x2\Class2_RigidTruck_ENG.vecto_00.vmod - //fileWriter.WriteModData(Path.GetFileName(jobName), "0", "0", modData[0].Item1); - //fileWriter.WriteModData(Path.GetFileName(jobName), "1", "1", modData[1].Item1); - - foreach (var modalResults in modData) { - AssertModDataIntegrity(modalResults.Item1, auxKeys, modalResults.Item2, - FuelConsumptionMapReader.Create(((IEngineeringInputDataProvider)inputData).EngineInputData.FuelConsumptionMap)); - } - - AssertSumDataIntegrity(sumData, mode); - } - - private static void AssertSumDataIntegrity(SummaryDataContainer sumData, ExecutionMode mode) - { - Assert.IsTrue(sumData.Table.Rows.Count > 0); - - var ptoTransmissionColumn = - sumData.Table.Columns.Contains(string.Format(SummaryDataContainer.E_FORMAT, - Constants.Auxiliaries.IDs.PTOTransmission)) - ? string.Format(SummaryDataContainer.E_FORMAT, Constants.Auxiliaries.IDs.PTOTransmission) - : null; - var ptoConsumerColumn = - sumData.Table.Columns.Contains(string.Format(SummaryDataContainer.E_FORMAT, Constants.Auxiliaries.IDs.PTOConsumer)) - ? string.Format(SummaryDataContainer.E_FORMAT, Constants.Auxiliaries.IDs.PTOConsumer) - : null; - - foreach (DataRow row in sumData.Table.Rows) { - var inputFile = row[SummaryDataContainer.INPUTFILE].ToString(); - var cycle = row[SummaryDataContainer.CYCLE].ToString(); - var loading = row[SummaryDataContainer.LOADING].ToString(); - var eFcMapPos = ((SI)row[SummaryDataContainer.E_FCMAP_POS]).Value(); - var eFcMapNeg = ((SI)row[SummaryDataContainer.E_FCMAP_NEG]).Value(); - var ePowertrainInertia = ((SI)row[SummaryDataContainer.E_POWERTRAIN_INERTIA]).Value(); - var eAux = ((SI)row[SummaryDataContainer.E_AUX]).Value(); - var eClutchLoss = ((SI)row[SummaryDataContainer.E_CLUTCH_LOSS]).Value(); - var eTcLoss = ((SI)row[SummaryDataContainer.E_TC_LOSS]).Value(); - //var eShiftLoss = ((SI)row[SummaryDataContainer.E_SHIFT_LOSS]).Value(); - var eGbxLoss = ((SI)row[SummaryDataContainer.E_GBX_LOSS]).Value(); - var eRetLoss = ((SI)row[SummaryDataContainer.E_RET_LOSS]).Value(); - var eAngleLoss = ((SI)row[SummaryDataContainer.E_ANGLE_LOSS]).Value(); - var eAxlLoss = ((SI)row[SummaryDataContainer.E_AXL_LOSS]).Value(); - var eBrakeLoss = ((SI)row[SummaryDataContainer.E_BRAKE]).Value(); - var eVehInertia = ((SI)row[SummaryDataContainer.E_VEHICLE_INERTIA]).Value(); - var eAir = ((SI)row[SummaryDataContainer.E_AIR]).Value(); - var eRoll = ((SI)row[SummaryDataContainer.E_ROLL]).Value(); - var eGrad = ((SI)row[SummaryDataContainer.E_GRAD]).Value(); - var cargoVolume = mode == ExecutionMode.Engineering ? 0 : ((SI)row[SummaryDataContainer.CARGO_VOLUME]).Value(); - - var loadingValue = ((SI)row[SummaryDataContainer.LOADING]).Value() / 1000; - var fcPer100km = ((SI)row[SummaryDataContainer.FCFINAL_LITERPER100KM]).Value(); - var fcPerVolume = mode == ExecutionMode.Engineering - ? 0 - : ((SI)row[SummaryDataContainer.FCFINAL_LiterPer100M3KM]).Value(); - var fcPerLoad = loadingValue > 0 ? ((SI)row[SummaryDataContainer.FCFINAL_LITERPER100TKM]).Value() : 0; - var co2Per100km = ((SI)row[SummaryDataContainer.CO2_KM]).Value(); - var co2PerVolume = mode == ExecutionMode.Engineering ? 0 : ((SI)row[SummaryDataContainer.CO2_M3KM]).Value(); - var co2PerLoad = loadingValue > 0 ? ((SI)row[SummaryDataContainer.CO2_TKM]).Value() : 0; - - var ePTOtransm = ptoTransmissionColumn != null ? ((SI)row[ptoTransmissionColumn]).Value() : 0; - var ePTOconsumer = ptoConsumerColumn != null ? ((SI)row[ptoConsumerColumn]).Value() : 0; - - // E_fcmap_pos = E_fcmap_neg + E_powertrain_inertia + E_aux_xxx + E_aux_sum + E_clutch_loss + E_tc_loss + E_gbx_loss + E_shift_loss + E_ret_loss + E_angle_loss + E_axl_loss + E_brake + E_vehicle_inertia + E_air + E_roll + E_grad + E_PTO_CONSUM + E_PTO_TRANSM - Assert.AreEqual(eFcMapPos, - eFcMapNeg + ePowertrainInertia + eAux + eClutchLoss + eTcLoss + eGbxLoss + eRetLoss + eAngleLoss + - eAxlLoss + eBrakeLoss + eVehInertia + eAir + eRoll + eGrad + ePTOconsumer + ePTOtransm, 1e-5, - "input file: {0} cycle: {1} loading: {2}", - inputFile, cycle, loading); - - var pFcmapPos = ((SI)row[SummaryDataContainer.P_FCMAP_POS]).Value(); - var time = ((SI)row[SummaryDataContainer.TIME]).Value(); - - // E_fcmap_pos = P_fcmap_pos * t - Assert.AreEqual(eFcMapPos, pFcmapPos * (time / 3600), 1e-3, "input file: {0} cycle: {1} loading: {2}", inputFile, - cycle, loading); - - if (cargoVolume > 0) { - Assert.AreEqual(fcPerVolume, fcPer100km / cargoVolume, 1e-3, "input file: {0} cycle: {1} loading: {2}", inputFile, - cycle, loading); - - Assert.AreEqual(co2PerVolume, co2Per100km / cargoVolume, 1e-3, "input file: {0} cycle: {1} loading: {2}", - inputFile, - cycle, loading); - } - - if (loadingValue > 0) { - Assert.AreEqual(co2PerLoad, co2Per100km / loadingValue, 1e-3, "input file: {0} cycle: {1} loading: {2}", - inputFile, cycle, loading); - Assert.AreEqual(fcPerLoad, fcPer100km / loadingValue, 1e-3, "input file: {0} cycle: {1} loading: {2}", - inputFile, cycle, loading); - } - - var stopTimeShare = ((SI)row[SummaryDataContainer.STOP_TIMESHARE]).Value(); - var accTimeShare = ((SI)row[SummaryDataContainer.ACC_TIMESHARE]).Value(); - var decTimeShare = ((SI)row[SummaryDataContainer.DEC_TIMESHARE]).Value(); - var cruiseTimeShare = ((SI)row[SummaryDataContainer.CRUISE_TIMESHARE]).Value(); - - Assert.AreEqual(100, stopTimeShare + accTimeShare + decTimeShare + cruiseTimeShare, 1e-3, - "input file: {0} cycle: {1} loading: {2}", inputFile, cycle, loading); - - Assert.IsTrue(((SI)row[SummaryDataContainer.ACC_POS]).Value() > 0); - Assert.IsTrue(((SI)row[SummaryDataContainer.ACC_NEG]).Value() < 0); - } - } - - private static void AssertModDataIntegrity(ModalResults modData, Dictionary<string, DataColumn> auxKeys, - Meter totalDistance, FuelConsumptionMap consumptionMap) - { - Assert.IsTrue(modData.Rows.Count > 0); - - var ptoTransmissionColumn = auxKeys.ContainsKey(Constants.Auxiliaries.IDs.PTOTransmission) - ? auxKeys[Constants.Auxiliaries.IDs.PTOTransmission] - : null; - var ptoConsumerColumn = auxKeys.ContainsKey(Constants.Auxiliaries.IDs.PTOConsumer) - ? auxKeys[Constants.Auxiliaries.IDs.PTOConsumer] - : null; - foreach (DataRow row in modData.Rows) { - if (totalDistance.IsEqual(((Meter)row[(int)ModalResultField.dist]))) { - continue; - } - var gear = (uint)row[(int)ModalResultField.Gear]; - var time = (Second)row[(int)ModalResultField.time]; - - var distance = (Meter)row[(int)ModalResultField.dist]; - var tqEngFcmap = (NewtonMeter)row[(int)ModalResultField.T_eng_fcmap]; - var nEngFcMap = (PerSecond)row[(int)ModalResultField.n_eng_avg]; - - // check fuel consumption interpolation - var fuelConsumption = (SI)row[(int)ModalResultField.FCMap]; - Assert.AreEqual(fuelConsumption.Value(), - consumptionMap.GetFuelConsumption(tqEngFcmap, nEngFcMap).Value.Value(), 1E-3, "time: {0} distance: {1}", - time, distance); - - // check P_eng_FCmap = T_eng_fcmap * n_eng - var pEngFcmap = (SI)row[(int)ModalResultField.P_eng_fcmap]; - Assert.AreEqual(pEngFcmap.Value(), (tqEngFcmap * nEngFcMap).Value(), 1E-3, "time: {0} distance: {1}", time, - distance); - - var pWheelIn = (Watt)row[(int)ModalResultField.P_wheel_in]; - var pAir = (Watt)row[(int)ModalResultField.P_air]; - var pRoll = (Watt)row[(int)ModalResultField.P_roll]; - var pGrad = (Watt)row[(int)ModalResultField.P_slope]; - var pVehInertia = (Watt)row[(int)ModalResultField.P_veh_inertia]; - var pTrac = (Watt)row[(int)ModalResultField.P_trac]; - - // P_eng_out = P_wheel + P_lossgearbox + P_lossaxle + P_lossretarder + P_agbx + Pa_eng + P_aux - P_brake_loss - var pEngOut = (Watt)row[(int)ModalResultField.P_eng_out]; - var pLossGbx = (Watt)row[(int)ModalResultField.P_gbx_loss]; - var pGbxIn = (Watt)row[(int)ModalResultField.P_gbx_in]; - var pLossAxle = (Watt)row[(int)ModalResultField.P_axle_loss]; - var pLossAngle = row[(int)ModalResultField.P_angle_loss] is DBNull - ? 0.SI<Watt>() - : (Watt)row[(int)ModalResultField.P_angle_loss]; - var pAxleIn = (Watt)row[(int)ModalResultField.P_axle_in]; - var pLossRet = (Watt)row[(int)ModalResultField.P_ret_loss]; - var pRetIn = (Watt)row[(int)ModalResultField.P_retarder_in]; - var pGbxInertia = (Watt)row[(int)ModalResultField.P_gbx_inertia]; - var pShiftLoss = row[(int)ModalResultField.P_gbx_shift_loss] is DBNull - ? 0.SI<Watt>() - : (Watt)row[(int)ModalResultField.P_gbx_shift_loss]; - var pEngInertia = (Watt)row[(int)ModalResultField.P_eng_inertia]; - var pAux = - (Watt)(row[(int)ModalResultField.P_aux] != DBNull.Value ? row[(int)ModalResultField.P_aux] : 0.SI<Watt>()); - var pBrakeLoss = (Watt)row[(int)ModalResultField.P_brake_loss]; - var pBrakeIn = (Watt)row[(int)ModalResultField.P_brake_in]; - - var pWheelInertia = (Watt)row[(int)ModalResultField.P_wheel_inertia]; - var pPTOconsumer = ptoConsumerColumn == null || row[ptoConsumerColumn.ColumnName] is DBNull - ? 0.SI<Watt>() - : (Watt)row[ptoConsumerColumn.ColumnName]; - var pPTOtransm = ptoTransmissionColumn == null || row[ptoTransmissionColumn.ColumnName] is DBNull - ? 0.SI<Watt>() - : (Watt)row[ptoTransmissionColumn.ColumnName]; - // P_trac = P_veh_inertia + P_roll + P_air + P_slope - Assert.AreEqual(pTrac.Value(), (pAir + pRoll + pGrad + pVehInertia).Value(), 1E-3, "time: {0} distance: {1}", time, - distance); - - // P_wheel_in = P_trac + P_wheel_inertia - Assert.AreEqual(pWheelIn.Value(), (pTrac + pWheelInertia).Value(), 1E-3, "time: {0} distance: {1}", time, - distance); - - Assert.AreEqual(pBrakeIn.Value(), (pWheelIn + pBrakeLoss).Value(), 1E-3, "time: {0} distance: {1}", time, - distance); - - Assert.AreEqual(pAxleIn.Value(), (pBrakeIn + pLossAxle).Value(), 1E-3, "time: {0} distance: {1}", time, distance); - - Assert.AreEqual(pRetIn.Value(), (pAxleIn + pLossRet).Value(), 1E-3, "time: {0} distance: {1}", time, distance); - - var pClutchLoss = (Watt)(row[(int)ModalResultField.P_clutch_loss] != DBNull.Value - ? row[(int)ModalResultField.P_clutch_loss] - : 0.SI<Watt>()); - - var pClutchOut = row[(int)ModalResultField.P_clutch_out]; - if (pClutchOut != DBNull.Value) { - Assert.AreEqual(pGbxIn.Value(), (pClutchOut as Watt).Value(), 1E-3, "time: {0} distance: {1}", time, distance); - Assert.AreEqual(pEngOut.Value(), (pClutchOut as Watt + pClutchLoss).Value(), 1E-3, "time: {0} distance: {1}", - time, distance); - } - - var pTC_Loss = (Watt)(row[(int)ModalResultField.P_TC_loss] != DBNull.Value - ? row[(int)ModalResultField.P_TC_loss] - : 0.SI<Watt>()); - - var pTCOut = row[(int)ModalResultField.P_clutch_out]; - if (pTCOut != DBNull.Value) { - Assert.AreEqual(pGbxIn.Value(), (pTCOut as Watt).Value(), 1E-3, "time: {0} distance: {1}", time, distance); - //Assert.AreEqual(pEngOut.Value(), (pTCOut as Watt + pTC_Loss).Value(), 1E-3, "time: {0} distance: {1}", - // time, distance); - } - - Assert.IsTrue(pLossGbx.IsGreaterOrEqual(pShiftLoss + pGbxInertia), "time: {0} distance: {1}", time, - distance); - - Assert.AreEqual(pGbxIn.Value(), (pRetIn + pLossGbx + pGbxInertia).Value(), gear != 0 ? 1E-3 : 0.5, - "time: {0} distance: {1}", time, - distance); - - // P_eng_fcmap = P_eng_out + P_AUX + P_eng_inertia ( + P_PTO_Transm + P_PTO_Consumer ) - Assert.AreEqual(pEngFcmap.Value(), (pEngOut + pAux + pEngInertia + pPTOtransm + pPTOconsumer).Value(), 0.5, - "time: {0} distance: {1}", time, distance); - - // P_eng_fcmap = sum(Losses Powertrain) - var pLossTot = pClutchLoss + pTC_Loss + pLossGbx + pLossRet + pGbxInertia + pLossAngle + pLossAxle + pBrakeLoss + - pWheelInertia + pAir + pRoll + pGrad + pVehInertia + pPTOconsumer + pPTOtransm; - var pEngFcmapCalc = (pLossTot + pEngInertia + pAux).Value(); - Assert.AreEqual(pEngFcmap.Value(), pEngFcmapCalc, 0.5, "time: {0} distance: {1}", time, distance); - - Assert.AreEqual(pEngFcmap.Value(), - (pTrac + pWheelInertia + pBrakeLoss + pLossAxle + pLossRet + pLossGbx + pGbxInertia + pEngInertia + pAux + - pClutchLoss + pTC_Loss + pPTOtransm + pPTOconsumer).Value(), 0.5, "time: {0} distance: {1}", time, distance); - } - } - - [ - TestCase(@"TestData\Integration\EngineeringMode\CityBus_AT\CityBus_AT_Ser.vecto"), - TestCase(@"TestData\Integration\EngineeringMode\CityBus_AT\CityBus_AT_PS.vecto")] - public void TestFullCycleModDataIntegrityAT(string jobName) - { - var fileWriter = new FileOutputWriter(jobName); - var sumData = new SummaryDataContainer(fileWriter); - - var jobContainer = new JobContainer(sumData); - var inputData = JSONInputDataFactory.ReadJsonJob(jobName); - - var runsFactory = - new SimulatorFactory(ExecutionMode.Engineering, inputData, fileWriter) { WriteModalResults = true }; - - jobContainer.AddRuns(runsFactory); - var modData = new List<Tuple<ModalResults, Meter>>(); - foreach (var run in jobContainer.Runs) { - modData.Add(Tuple.Create(((ModalDataContainer)run.Run.GetContainer().ModalData).Data, - ((DistanceBasedDrivingCycle)((VehicleContainer)run.Run.GetContainer()).DrivingCycle).Data.Entries.Last() - .Distance)); - } - var auxKeys = - new Dictionary<string, DataColumn>( - ((ModalDataContainer)jobContainer.Runs.First().Run.GetContainer().ModalData).Auxiliaries); - jobContainer.Execute(); - jobContainer.WaitFinished(); - - foreach (var modalResults in modData) { - AssertModDataIntegrityAT(modalResults.Item1, auxKeys, modalResults.Item2, - FuelConsumptionMapReader.Create(((IEngineeringInputDataProvider)inputData).EngineInputData.FuelConsumptionMap)); - } - - AssertSumDataIntegrity(sumData, ExecutionMode.Engineering); - } - - private static void AssertModDataIntegrityAT(ModalResults modData, Dictionary<string, DataColumn> auxKeys, - Meter totalDistance, FuelConsumptionMap consumptionMap) - { - Assert.IsTrue(modData.Rows.Count > 0); - - var ptoTransmissionColumn = auxKeys.ContainsKey(Constants.Auxiliaries.IDs.PTOTransmission) - ? auxKeys[Constants.Auxiliaries.IDs.PTOTransmission] - : null; - var ptoConsumerColumn = auxKeys.ContainsKey(Constants.Auxiliaries.IDs.PTOConsumer) - ? auxKeys[Constants.Auxiliaries.IDs.PTOConsumer] - : null; - foreach (DataRow row in modData.Rows) { - if (totalDistance.IsEqual(((Meter)row[(int)ModalResultField.dist]))) { - continue; - } - var gear = (uint)row[(int)ModalResultField.Gear]; - var time = (Second)row[(int)ModalResultField.time]; - - var distance = (Meter)row[(int)ModalResultField.dist]; - var tqEngFcmap = (NewtonMeter)row[(int)ModalResultField.T_eng_fcmap]; - var nEngFcMap = (PerSecond)row[(int)ModalResultField.n_eng_avg]; - - // check fuel consumption interpolation - var fuelConsumption = (SI)row[(int)ModalResultField.FCMap]; - Assert.AreEqual(fuelConsumption.Value(), - consumptionMap.GetFuelConsumption(tqEngFcmap, nEngFcMap).Value.Value(), 1E-3, "time: {0} distance: {1}", - time, distance); - - // check P_eng_FCmap = T_eng_fcmap * n_eng - var pEngFcmap = (SI)row[(int)ModalResultField.P_eng_fcmap]; - Assert.AreEqual(pEngFcmap.Value(), (tqEngFcmap * nEngFcMap).Value(), 1E-3, "time: {0} distance: {1}", time, - distance); - - var pWheelIn = (Watt)row[(int)ModalResultField.P_wheel_in]; - var pAir = (Watt)row[(int)ModalResultField.P_air]; - var pRoll = (Watt)row[(int)ModalResultField.P_roll]; - var pGrad = (Watt)row[(int)ModalResultField.P_slope]; - var pVehInertia = (Watt)row[(int)ModalResultField.P_veh_inertia]; - var pTrac = (Watt)row[(int)ModalResultField.P_trac]; - - // Pe_eng = P_wheel + P_lossgearbox + P_lossaxle + P_lossretarder + P_agbx + Pa_eng + P_aux - P_brake_loss - var pEngOut = (Watt)row[(int)ModalResultField.P_eng_out]; - var pLossGbx = (Watt)row[(int)ModalResultField.P_gbx_loss]; - var pGbxIn = (Watt)row[(int)ModalResultField.P_gbx_in]; - var pLossAxle = (Watt)row[(int)ModalResultField.P_axle_loss]; - var pLossAngle = row[(int)ModalResultField.P_angle_loss] is DBNull - ? 0.SI<Watt>() - : (Watt)row[(int)ModalResultField.P_angle_loss]; - var pAxleIn = (Watt)row[(int)ModalResultField.P_axle_in]; - var pLossRet = (Watt)row[(int)ModalResultField.P_ret_loss]; - var pRetIn = (Watt)row[(int)ModalResultField.P_retarder_in]; - var pGbxInertia = (Watt)row[(int)ModalResultField.P_gbx_inertia]; - var pShiftLoss = row[(int)ModalResultField.P_gbx_shift_loss] is DBNull - ? 0.SI<Watt>() - : (Watt)row[(int)ModalResultField.P_gbx_shift_loss]; - var pEngInertia = (Watt)row[(int)ModalResultField.P_eng_inertia]; - var pAux = - (Watt)(row[(int)ModalResultField.P_aux] != DBNull.Value ? row[(int)ModalResultField.P_aux] : 0.SI<Watt>()); - var pBrakeLoss = (Watt)row[(int)ModalResultField.P_brake_loss]; - var pBrakeIn = (Watt)row[(int)ModalResultField.P_brake_in]; - var pTcLoss = (Watt)row[(int)ModalResultField.P_TC_loss]; - var pTcOut = (Watt)row[(int)ModalResultField.P_TC_out]; - var pWheelInertia = (Watt)row[(int)ModalResultField.P_wheel_inertia]; - var pPTOconsumer = ptoConsumerColumn == null || row[ptoConsumerColumn] is DBNull - ? 0.SI<Watt>() - : (Watt)row[ptoConsumerColumn]; - var pPTOtransm = ptoTransmissionColumn == null || row[ptoTransmissionColumn] is DBNull - ? 0.SI<Watt>() - : (Watt)row[ptoTransmissionColumn]; - // P_trac = P_veh_inertia + P_roll + P_air + P_slope - Assert.AreEqual(pTrac.Value(), (pAir + pRoll + pGrad + pVehInertia).Value(), 1E-3, "time: {0} distance: {1}", time, - distance); - - // P_wheel_in = P_trac + P_wheel_inertia - Assert.AreEqual(pWheelIn.Value(), (pTrac + pWheelInertia).Value(), 1E-3, "time: {0} distance: {1}", time, - distance); - - Assert.AreEqual(pBrakeIn.Value(), (pWheelIn + pBrakeLoss).Value(), 1E-3, "time: {0} distance: {1}", time, - distance); - - Assert.AreEqual(pAxleIn.Value(), (pBrakeIn + pLossAxle).Value(), 1E-3, "time: {0} distance: {1}", time, distance); - - Assert.AreEqual(pRetIn.Value(), (pAxleIn + pLossRet).Value(), 1E-3, "time: {0} distance: {1}", time, distance); - - Assert.AreEqual(pGbxIn.Value(), pTcOut.Value(), 1E-3, "time: {0} distance: {1}", time, distance); - - Assert.AreEqual(pEngOut.Value(), (pTcOut + pTcLoss).Value(), 1E-3, - "time: {0} distance: {1}", time, distance); - - // P_eng_fcmap = P_eng_out + P_AUX + P_eng_inertia ( + P_PTO_Transm + P_PTO_Consumer ) - Assert.AreEqual(pEngFcmap.Value(), (pEngOut + pAux + pEngInertia + pPTOtransm + pPTOconsumer).Value(), 1E-3, - "time: {0} distance: {1}", time, - distance); - - // P_eng_fcmap = sum(Losses Powertrain) - var pLossTot = pTcLoss + pLossGbx + pLossRet + pGbxInertia + pLossAngle + pLossAxle + pBrakeLoss + - pWheelInertia + pAir + pRoll + pGrad + pVehInertia + pPTOconsumer + pPTOtransm; - - Assert.AreEqual(pEngFcmap.Value(), (pLossTot + pEngInertia + pAux).Value(), 1E-3, "time: {0} distance: {1}", time, - distance); - - Assert.IsTrue(pLossGbx.IsGreaterOrEqual(pShiftLoss + pGbxInertia), "time: {0} distance: {1}", time, - distance); - - Assert.AreEqual(pGbxIn.Value(), (pRetIn + pLossGbx + pGbxInertia).Value(), gear != 0 ? 1E-3 : 0.5, - "time: {0} distance: {1}", time, - distance); - Assert.AreEqual(pEngFcmap.Value(), - (pTrac + pWheelInertia + pBrakeLoss + pLossAxle + pLossRet + pLossGbx + pGbxInertia + pEngInertia + pAux + - pTcLoss + pPTOtransm + pPTOconsumer).Value(), 0.5, "time: {0} distance: {1}", time, distance); - } - } - } +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using NUnit.Framework; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Configuration; +using TUGraz.VectoCore.InputData.FileIO.JSON; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.OutputData; +using TUGraz.VectoCore.OutputData.FileIO; +using TUGraz.VectoCore.Tests.Integration; +using TUGraz.VectoCore.Tests.Utils; +using Assert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert; + +namespace TUGraz.VectoCore.Tests.Reports +{ + [TestFixture] + public class ModDataTest + { + [TestCase()] + public void ModDataIntegritySimpleTest() + { + var cycleData = new[] { + // <s>,<v>,<grad>,<stop> + " 0, 20, 0, 0", + " 100, 60, 0, 0", + "1000, 60, 0, 0", + "1500, 40, 1, 0", + "2000, 50,-1, 0", + "2500, 0, 0, 2" + }; + var cycle = SimpleDrivingCycles.CreateCycleData(cycleData); + var sumData = new SummaryDataContainer(null); + var run = Truck40tPowerTrain.CreateEngineeringRun(cycle, "Truck_ModDataIntegrity.vmod"); + + var engineData = MockSimulationDataFactory.CreateEngineDataFromFile(Truck40tPowerTrain.EngineFile, 0); + + // get a reference to the mod-data because the modaldata container clears it after simulation + var modData = ((ModalDataContainer)run.GetContainer().ModalData).Data; + var auxKeys = ((ModalDataContainer)run.GetContainer().ModalData).Auxiliaries; + + run.Run(); + Assert.IsTrue(run.FinishedWithoutErrors); + + AssertModDataIntegrity(modData, auxKeys, cycle.Entries.Last().Distance, engineData.ConsumptionMap); + } + + [TestCase(@"TestData\Integration\DeclarationMode\Class2_RigidTruck_4x2\Class2_RigidTruck_DECL.vecto")] + public void TestFullCycleModDataIntegrityDeclMT(string jobName) + { + RunSimulation(jobName, ExecutionMode.Declaration); + } + + [TestCase(@"TestData\Integration\EngineeringMode\Class2_RigidTruck_4x2\Class2_RigidTruck_ENG.vecto"), + TestCase(@"TestData\Integration\EngineeringMode\Class5_Tractor_4x2\Class5_Tractor_ENG.vecto"), + TestCase(@"TestData\Integration\EngineeringMode\Class9_RigidTruck_6x2_PTO\Class9_RigidTruck_ENG_PTO.vecto"),] + public void TestFullCycleModDataIntegrityMT(string jobName) + { + RunSimulation(jobName, ExecutionMode.Engineering); + } + + private static void RunSimulation(string jobName, ExecutionMode mode) + { + var fileWriter = new FileOutputWriter(jobName); + var sumData = new SummaryDataContainer(fileWriter); + + var jobContainer = new JobContainer(sumData); + var inputData = JSONInputDataFactory.ReadJsonJob(jobName); + + var runsFactory = new SimulatorFactory(mode, inputData, fileWriter) { WriteModalResults = true }; + + jobContainer.AddRuns(runsFactory); + var modData = new List<Tuple<ModalResults, Meter>>(); + foreach (var run in jobContainer.Runs) { + modData.Add(Tuple.Create(((ModalDataContainer)run.Run.GetContainer().ModalData).Data, + ((DistanceBasedDrivingCycle)((VehicleContainer)run.Run.GetContainer()).DrivingCycle).Data.Entries.Last() + .Distance)); + } + var auxKeys = + new Dictionary<string, DataColumn>( + ((ModalDataContainer)jobContainer.Runs.First().Run.GetContainer().ModalData).Auxiliaries); + jobContainer.Execute(); + jobContainer.WaitFinished(); + + // mod files will be stored in e.g. + // VectoCoreTest\bin\Debug\TestData\Integration\EngineeringMode\Class2_RigidTruck_4x2\Class2_RigidTruck_ENG.vecto_00.vmod + //fileWriter.WriteModData(Path.GetFileName(jobName), "0", "0", modData[0].Item1); + //fileWriter.WriteModData(Path.GetFileName(jobName), "1", "1", modData[1].Item1); + + foreach (var modalResults in modData) { + AssertModDataIntegrity(modalResults.Item1, auxKeys, modalResults.Item2, + FuelConsumptionMapReader.Create(((IEngineeringInputDataProvider)inputData).EngineInputData.FuelConsumptionMap)); + } + + AssertSumDataIntegrity(sumData, mode); + } + + private static void AssertSumDataIntegrity(SummaryDataContainer sumData, ExecutionMode mode) + { + Assert.IsTrue(sumData.Table.Rows.Count > 0); + + var ptoTransmissionColumn = + sumData.Table.Columns.Contains(string.Format(SummaryDataContainer.E_FORMAT, + Constants.Auxiliaries.IDs.PTOTransmission)) + ? string.Format(SummaryDataContainer.E_FORMAT, Constants.Auxiliaries.IDs.PTOTransmission) + : null; + var ptoConsumerColumn = + sumData.Table.Columns.Contains(string.Format(SummaryDataContainer.E_FORMAT, Constants.Auxiliaries.IDs.PTOConsumer)) + ? string.Format(SummaryDataContainer.E_FORMAT, Constants.Auxiliaries.IDs.PTOConsumer) + : null; + + foreach (DataRow row in sumData.Table.Rows) { + var inputFile = row[SummaryDataContainer.INPUTFILE].ToString(); + var cycle = row[SummaryDataContainer.CYCLE].ToString(); + var loading = row[SummaryDataContainer.LOADING].ToString(); + var eFcMapPos = ((SI)row[SummaryDataContainer.E_FCMAP_POS]).Value(); + var eFcMapNeg = ((SI)row[SummaryDataContainer.E_FCMAP_NEG]).Value(); + var ePowertrainInertia = ((SI)row[SummaryDataContainer.E_POWERTRAIN_INERTIA]).Value(); + var eAux = ((SI)row[SummaryDataContainer.E_AUX]).Value(); + var eClutchLoss = ((SI)row[SummaryDataContainer.E_CLUTCH_LOSS]).Value(); + var eTcLoss = ((SI)row[SummaryDataContainer.E_TC_LOSS]).Value(); + //var eShiftLoss = ((SI)row[SummaryDataContainer.E_SHIFT_LOSS]).Value(); + var eGbxLoss = ((SI)row[SummaryDataContainer.E_GBX_LOSS]).Value(); + var eRetLoss = ((SI)row[SummaryDataContainer.E_RET_LOSS]).Value(); + var eAngleLoss = ((SI)row[SummaryDataContainer.E_ANGLE_LOSS]).Value(); + var eAxlLoss = ((SI)row[SummaryDataContainer.E_AXL_LOSS]).Value(); + var eBrakeLoss = ((SI)row[SummaryDataContainer.E_BRAKE]).Value(); + var eVehInertia = ((SI)row[SummaryDataContainer.E_VEHICLE_INERTIA]).Value(); + var eAir = ((SI)row[SummaryDataContainer.E_AIR]).Value(); + var eRoll = ((SI)row[SummaryDataContainer.E_ROLL]).Value(); + var eGrad = ((SI)row[SummaryDataContainer.E_GRAD]).Value(); + var cargoVolume = mode == ExecutionMode.Engineering ? 0 : ((SI)row[SummaryDataContainer.CARGO_VOLUME]).Value(); + + var loadingValue = ((SI)row[SummaryDataContainer.LOADING]).Value() / 1000; + var fcPer100km = ((SI)row[SummaryDataContainer.FCFINAL_LITERPER100KM]).Value(); + var fcPerVolume = mode == ExecutionMode.Engineering + ? 0 + : ((SI)row[SummaryDataContainer.FCFINAL_LiterPer100M3KM]).Value(); + var fcPerLoad = loadingValue > 0 ? ((SI)row[SummaryDataContainer.FCFINAL_LITERPER100TKM]).Value() : 0; + var co2Per100km = ((SI)row[SummaryDataContainer.CO2_KM]).Value(); + var co2PerVolume = mode == ExecutionMode.Engineering ? 0 : ((SI)row[SummaryDataContainer.CO2_M3KM]).Value(); + var co2PerLoad = loadingValue > 0 ? ((SI)row[SummaryDataContainer.CO2_TKM]).Value() : 0; + + var ePTOtransm = ptoTransmissionColumn != null ? ((SI)row[ptoTransmissionColumn]).Value() : 0; + var ePTOconsumer = ptoConsumerColumn != null ? ((SI)row[ptoConsumerColumn]).Value() : 0; + + // E_fcmap_pos = E_fcmap_neg + E_powertrain_inertia + E_aux_xxx + E_aux_sum + E_clutch_loss + E_tc_loss + E_gbx_loss + E_shift_loss + E_ret_loss + E_angle_loss + E_axl_loss + E_brake + E_vehicle_inertia + E_air + E_roll + E_grad + E_PTO_CONSUM + E_PTO_TRANSM + Assert.AreEqual(eFcMapPos, + eFcMapNeg + ePowertrainInertia + eAux + eClutchLoss + eTcLoss + eGbxLoss + eRetLoss + eAngleLoss + + eAxlLoss + eBrakeLoss + eVehInertia + eAir + eRoll + eGrad + ePTOconsumer + ePTOtransm, 1e-5, + "input file: {0} cycle: {1} loading: {2}", + inputFile, cycle, loading); + + var pFcmapPos = ((SI)row[SummaryDataContainer.P_FCMAP_POS]).Value(); + var time = ((SI)row[SummaryDataContainer.TIME]).Value(); + + // E_fcmap_pos = P_fcmap_pos * t + Assert.AreEqual(eFcMapPos, pFcmapPos * (time / 3600), 1e-3, "input file: {0} cycle: {1} loading: {2}", inputFile, + cycle, loading); + + if (cargoVolume > 0) { + Assert.AreEqual(fcPerVolume, fcPer100km / cargoVolume, 1e-3, "input file: {0} cycle: {1} loading: {2}", inputFile, + cycle, loading); + + Assert.AreEqual(co2PerVolume, co2Per100km / cargoVolume, 1e-3, "input file: {0} cycle: {1} loading: {2}", + inputFile, + cycle, loading); + } + + if (loadingValue > 0) { + Assert.AreEqual(co2PerLoad, co2Per100km / loadingValue, 1e-3, "input file: {0} cycle: {1} loading: {2}", + inputFile, cycle, loading); + Assert.AreEqual(fcPerLoad, fcPer100km / loadingValue, 1e-3, "input file: {0} cycle: {1} loading: {2}", + inputFile, cycle, loading); + } + + var stopTimeShare = ((SI)row[SummaryDataContainer.STOP_TIMESHARE]).Value(); + var accTimeShare = ((SI)row[SummaryDataContainer.ACC_TIMESHARE]).Value(); + var decTimeShare = ((SI)row[SummaryDataContainer.DEC_TIMESHARE]).Value(); + var cruiseTimeShare = ((SI)row[SummaryDataContainer.CRUISE_TIMESHARE]).Value(); + + Assert.AreEqual(100, stopTimeShare + accTimeShare + decTimeShare + cruiseTimeShare, 1e-3, + "input file: {0} cycle: {1} loading: {2}", inputFile, cycle, loading); + + Assert.IsTrue(((SI)row[SummaryDataContainer.ACC_POS]).Value() > 0); + Assert.IsTrue(((SI)row[SummaryDataContainer.ACC_NEG]).Value() < 0); + + var gearshifts = ((SI)row[SummaryDataContainer.NUM_GEARSHIFTS]).Value(); + Assert.IsTrue(gearshifts > 0); + + //var acc = ((SI)row[SummaryDataContainer.ACC]).Value(); + } + } + + private static void AssertModDataIntegrity(ModalResults modData, Dictionary<string, DataColumn> auxKeys, + Meter totalDistance, FuelConsumptionMap consumptionMap) + { + Assert.IsTrue(modData.Rows.Count > 0); + + var ptoTransmissionColumn = auxKeys.ContainsKey(Constants.Auxiliaries.IDs.PTOTransmission) + ? auxKeys[Constants.Auxiliaries.IDs.PTOTransmission] + : null; + var ptoConsumerColumn = auxKeys.ContainsKey(Constants.Auxiliaries.IDs.PTOConsumer) + ? auxKeys[Constants.Auxiliaries.IDs.PTOConsumer] + : null; + foreach (DataRow row in modData.Rows) { + if (totalDistance.IsEqual(((Meter)row[(int)ModalResultField.dist]))) { + continue; + } + var gear = (uint)row[(int)ModalResultField.Gear]; + var time = (Second)row[(int)ModalResultField.time]; + + var distance = (Meter)row[(int)ModalResultField.dist]; + var tqEngFcmap = (NewtonMeter)row[(int)ModalResultField.T_eng_fcmap]; + var nEngFcMap = (PerSecond)row[(int)ModalResultField.n_eng_avg]; + + // check fuel consumption interpolation + var fuelConsumption = (SI)row[(int)ModalResultField.FCMap]; + Assert.AreEqual(fuelConsumption.Value(), + consumptionMap.GetFuelConsumption(tqEngFcmap, nEngFcMap).Value.Value(), 1E-3, "time: {0} distance: {1}", + time, distance); + + // check P_eng_FCmap = T_eng_fcmap * n_eng + var pEngFcmap = (SI)row[(int)ModalResultField.P_eng_fcmap]; + Assert.AreEqual(pEngFcmap.Value(), (tqEngFcmap * nEngFcMap).Value(), 1E-3, "time: {0} distance: {1}", time, + distance); + + var pWheelIn = (Watt)row[(int)ModalResultField.P_wheel_in]; + var pAir = (Watt)row[(int)ModalResultField.P_air]; + var pRoll = (Watt)row[(int)ModalResultField.P_roll]; + var pGrad = (Watt)row[(int)ModalResultField.P_slope]; + var pVehInertia = (Watt)row[(int)ModalResultField.P_veh_inertia]; + var pTrac = (Watt)row[(int)ModalResultField.P_trac]; + + // P_eng_out = P_wheel + P_lossgearbox + P_lossaxle + P_lossretarder + P_agbx + Pa_eng + P_aux - P_brake_loss + var pEngOut = (Watt)row[(int)ModalResultField.P_eng_out]; + var pLossGbx = (Watt)row[(int)ModalResultField.P_gbx_loss]; + var pGbxIn = (Watt)row[(int)ModalResultField.P_gbx_in]; + var pLossAxle = (Watt)row[(int)ModalResultField.P_axle_loss]; + var pLossAngle = row[(int)ModalResultField.P_angle_loss] is DBNull + ? 0.SI<Watt>() + : (Watt)row[(int)ModalResultField.P_angle_loss]; + var pAxleIn = (Watt)row[(int)ModalResultField.P_axle_in]; + var pLossRet = (Watt)row[(int)ModalResultField.P_ret_loss]; + var pRetIn = (Watt)row[(int)ModalResultField.P_retarder_in]; + var pGbxInertia = (Watt)row[(int)ModalResultField.P_gbx_inertia]; + var pShiftLoss = row[(int)ModalResultField.P_gbx_shift_loss] is DBNull + ? 0.SI<Watt>() + : (Watt)row[(int)ModalResultField.P_gbx_shift_loss]; + var pEngInertia = (Watt)row[(int)ModalResultField.P_eng_inertia]; + var pAux = + (Watt)(row[(int)ModalResultField.P_aux] != DBNull.Value ? row[(int)ModalResultField.P_aux] : 0.SI<Watt>()); + var pBrakeLoss = (Watt)row[(int)ModalResultField.P_brake_loss]; + var pBrakeIn = (Watt)row[(int)ModalResultField.P_brake_in]; + + var pWheelInertia = (Watt)row[(int)ModalResultField.P_wheel_inertia]; + var pPTOconsumer = ptoConsumerColumn == null || row[ptoConsumerColumn.ColumnName] is DBNull + ? 0.SI<Watt>() + : (Watt)row[ptoConsumerColumn.ColumnName]; + var pPTOtransm = ptoTransmissionColumn == null || row[ptoTransmissionColumn.ColumnName] is DBNull + ? 0.SI<Watt>() + : (Watt)row[ptoTransmissionColumn.ColumnName]; + // P_trac = P_veh_inertia + P_roll + P_air + P_slope + Assert.AreEqual(pTrac.Value(), (pAir + pRoll + pGrad + pVehInertia).Value(), 1E-3, "time: {0} distance: {1}", time, + distance); + + // P_wheel_in = P_trac + P_wheel_inertia + Assert.AreEqual(pWheelIn.Value(), (pTrac + pWheelInertia).Value(), 1E-3, "time: {0} distance: {1}", time, + distance); + + Assert.AreEqual(pBrakeIn.Value(), (pWheelIn + pBrakeLoss).Value(), 1E-3, "time: {0} distance: {1}", time, + distance); + + Assert.AreEqual(pAxleIn.Value(), (pBrakeIn + pLossAxle).Value(), 1E-3, "time: {0} distance: {1}", time, distance); + + Assert.AreEqual(pRetIn.Value(), (pAxleIn + pLossRet).Value(), 1E-3, "time: {0} distance: {1}", time, distance); + + var pClutchLoss = (Watt)(row[(int)ModalResultField.P_clutch_loss] != DBNull.Value + ? row[(int)ModalResultField.P_clutch_loss] + : 0.SI<Watt>()); + + var pClutchOut = row[(int)ModalResultField.P_clutch_out]; + if (pClutchOut != DBNull.Value) { + Assert.AreEqual(pGbxIn.Value(), (pClutchOut as Watt).Value(), 1E-3, "time: {0} distance: {1}", time, distance); + Assert.AreEqual(pEngOut.Value(), (pClutchOut as Watt + pClutchLoss).Value(), 1E-3, "time: {0} distance: {1}", + time, distance); + } + + var pTC_Loss = (Watt)(row[(int)ModalResultField.P_TC_loss] != DBNull.Value + ? row[(int)ModalResultField.P_TC_loss] + : 0.SI<Watt>()); + + var pTCOut = row[(int)ModalResultField.P_clutch_out]; + if (pTCOut != DBNull.Value) { + Assert.AreEqual(pGbxIn.Value(), (pTCOut as Watt).Value(), 1E-3, "time: {0} distance: {1}", time, distance); + //Assert.AreEqual(pEngOut.Value(), (pTCOut as Watt + pTC_Loss).Value(), 1E-3, "time: {0} distance: {1}", + // time, distance); + } + + Assert.IsTrue(pLossGbx.IsGreaterOrEqual(pShiftLoss + pGbxInertia), "time: {0} distance: {1}", time, + distance); + + Assert.AreEqual(pGbxIn.Value(), (pRetIn + pLossGbx + pGbxInertia).Value(), gear != 0 ? 1E-3 : 0.5, + "time: {0} distance: {1}", time, + distance); + + // P_eng_fcmap = P_eng_out + P_AUX + P_eng_inertia ( + P_PTO_Transm + P_PTO_Consumer ) + Assert.AreEqual(pEngFcmap.Value(), (pEngOut + pAux + pEngInertia + pPTOtransm + pPTOconsumer).Value(), 0.5, + "time: {0} distance: {1}", time, distance); + + // P_eng_fcmap = sum(Losses Powertrain) + var pLossTot = pClutchLoss + pTC_Loss + pLossGbx + pLossRet + pGbxInertia + pLossAngle + pLossAxle + pBrakeLoss + + pWheelInertia + pAir + pRoll + pGrad + pVehInertia + pPTOconsumer + pPTOtransm; + var pEngFcmapCalc = (pLossTot + pEngInertia + pAux).Value(); + Assert.AreEqual(pEngFcmap.Value(), pEngFcmapCalc, 0.5, "time: {0} distance: {1}", time, distance); + + Assert.AreEqual(pEngFcmap.Value(), + (pTrac + pWheelInertia + pBrakeLoss + pLossAxle + pLossRet + pLossGbx + pGbxInertia + pEngInertia + pAux + + pClutchLoss + pTC_Loss + pPTOtransm + pPTOconsumer).Value(), 0.5, "time: {0} distance: {1}", time, distance); + } + } + + [ + TestCase(@"TestData\Integration\EngineeringMode\CityBus_AT\CityBus_AT_Ser.vecto"), + TestCase(@"TestData\Integration\EngineeringMode\CityBus_AT\CityBus_AT_PS.vecto")] + public void TestFullCycleModDataIntegrityAT(string jobName) + { + var fileWriter = new FileOutputWriter(jobName); + var sumData = new SummaryDataContainer(fileWriter); + + var jobContainer = new JobContainer(sumData); + var inputData = JSONInputDataFactory.ReadJsonJob(jobName); + + var runsFactory = + new SimulatorFactory(ExecutionMode.Engineering, inputData, fileWriter) { WriteModalResults = true }; + + jobContainer.AddRuns(runsFactory); + var modData = new List<Tuple<ModalResults, Meter>>(); + foreach (var run in jobContainer.Runs) { + modData.Add(Tuple.Create(((ModalDataContainer)run.Run.GetContainer().ModalData).Data, + ((DistanceBasedDrivingCycle)((VehicleContainer)run.Run.GetContainer()).DrivingCycle).Data.Entries.Last() + .Distance)); + } + var auxKeys = + new Dictionary<string, DataColumn>( + ((ModalDataContainer)jobContainer.Runs.First().Run.GetContainer().ModalData).Auxiliaries); + jobContainer.Execute(); + jobContainer.WaitFinished(); + + foreach (var modalResults in modData) { + AssertModDataIntegrityAT(modalResults.Item1, auxKeys, modalResults.Item2, + FuelConsumptionMapReader.Create(((IEngineeringInputDataProvider)inputData).EngineInputData.FuelConsumptionMap)); + } + + AssertSumDataIntegrity(sumData, ExecutionMode.Engineering); + } + + private static void AssertModDataIntegrityAT(ModalResults modData, Dictionary<string, DataColumn> auxKeys, + Meter totalDistance, FuelConsumptionMap consumptionMap) + { + Assert.IsTrue(modData.Rows.Count > 0); + + var ptoTransmissionColumn = auxKeys.ContainsKey(Constants.Auxiliaries.IDs.PTOTransmission) + ? auxKeys[Constants.Auxiliaries.IDs.PTOTransmission] + : null; + var ptoConsumerColumn = auxKeys.ContainsKey(Constants.Auxiliaries.IDs.PTOConsumer) + ? auxKeys[Constants.Auxiliaries.IDs.PTOConsumer] + : null; + foreach (DataRow row in modData.Rows) { + if (totalDistance.IsEqual(((Meter)row[(int)ModalResultField.dist]))) { + continue; + } + var gear = (uint)row[(int)ModalResultField.Gear]; + var time = (Second)row[(int)ModalResultField.time]; + + var distance = (Meter)row[(int)ModalResultField.dist]; + var tqEngFcmap = (NewtonMeter)row[(int)ModalResultField.T_eng_fcmap]; + var nEngFcMap = (PerSecond)row[(int)ModalResultField.n_eng_avg]; + + // check fuel consumption interpolation + var fuelConsumption = (SI)row[(int)ModalResultField.FCMap]; + Assert.AreEqual(fuelConsumption.Value(), + consumptionMap.GetFuelConsumption(tqEngFcmap, nEngFcMap).Value.Value(), 1E-3, "time: {0} distance: {1}", + time, distance); + + // check P_eng_FCmap = T_eng_fcmap * n_eng + var pEngFcmap = (SI)row[(int)ModalResultField.P_eng_fcmap]; + Assert.AreEqual(pEngFcmap.Value(), (tqEngFcmap * nEngFcMap).Value(), 1E-3, "time: {0} distance: {1}", time, + distance); + + var pWheelIn = (Watt)row[(int)ModalResultField.P_wheel_in]; + var pAir = (Watt)row[(int)ModalResultField.P_air]; + var pRoll = (Watt)row[(int)ModalResultField.P_roll]; + var pGrad = (Watt)row[(int)ModalResultField.P_slope]; + var pVehInertia = (Watt)row[(int)ModalResultField.P_veh_inertia]; + var pTrac = (Watt)row[(int)ModalResultField.P_trac]; + + // Pe_eng = P_wheel + P_lossgearbox + P_lossaxle + P_lossretarder + P_agbx + Pa_eng + P_aux - P_brake_loss + var pEngOut = (Watt)row[(int)ModalResultField.P_eng_out]; + var pLossGbx = (Watt)row[(int)ModalResultField.P_gbx_loss]; + var pGbxIn = (Watt)row[(int)ModalResultField.P_gbx_in]; + var pLossAxle = (Watt)row[(int)ModalResultField.P_axle_loss]; + var pLossAngle = row[(int)ModalResultField.P_angle_loss] is DBNull + ? 0.SI<Watt>() + : (Watt)row[(int)ModalResultField.P_angle_loss]; + var pAxleIn = (Watt)row[(int)ModalResultField.P_axle_in]; + var pLossRet = (Watt)row[(int)ModalResultField.P_ret_loss]; + var pRetIn = (Watt)row[(int)ModalResultField.P_retarder_in]; + var pGbxInertia = (Watt)row[(int)ModalResultField.P_gbx_inertia]; + var pShiftLoss = row[(int)ModalResultField.P_gbx_shift_loss] is DBNull + ? 0.SI<Watt>() + : (Watt)row[(int)ModalResultField.P_gbx_shift_loss]; + var pEngInertia = (Watt)row[(int)ModalResultField.P_eng_inertia]; + var pAux = + (Watt)(row[(int)ModalResultField.P_aux] != DBNull.Value ? row[(int)ModalResultField.P_aux] : 0.SI<Watt>()); + var pBrakeLoss = (Watt)row[(int)ModalResultField.P_brake_loss]; + var pBrakeIn = (Watt)row[(int)ModalResultField.P_brake_in]; + var pTcLoss = (Watt)row[(int)ModalResultField.P_TC_loss]; + var pTcOut = (Watt)row[(int)ModalResultField.P_TC_out]; + var pWheelInertia = (Watt)row[(int)ModalResultField.P_wheel_inertia]; + var pPTOconsumer = ptoConsumerColumn == null || row[ptoConsumerColumn] is DBNull + ? 0.SI<Watt>() + : (Watt)row[ptoConsumerColumn]; + var pPTOtransm = ptoTransmissionColumn == null || row[ptoTransmissionColumn] is DBNull + ? 0.SI<Watt>() + : (Watt)row[ptoTransmissionColumn]; + // P_trac = P_veh_inertia + P_roll + P_air + P_slope + Assert.AreEqual(pTrac.Value(), (pAir + pRoll + pGrad + pVehInertia).Value(), 1E-3, "time: {0} distance: {1}", time, + distance); + + // P_wheel_in = P_trac + P_wheel_inertia + Assert.AreEqual(pWheelIn.Value(), (pTrac + pWheelInertia).Value(), 1E-3, "time: {0} distance: {1}", time, + distance); + + Assert.AreEqual(pBrakeIn.Value(), (pWheelIn + pBrakeLoss).Value(), 1E-3, "time: {0} distance: {1}", time, + distance); + + Assert.AreEqual(pAxleIn.Value(), (pBrakeIn + pLossAxle).Value(), 1E-3, "time: {0} distance: {1}", time, distance); + + Assert.AreEqual(pRetIn.Value(), (pAxleIn + pLossRet).Value(), 1E-3, "time: {0} distance: {1}", time, distance); + + Assert.AreEqual(pGbxIn.Value(), pTcOut.Value(), 1E-3, "time: {0} distance: {1}", time, distance); + + Assert.AreEqual(pEngOut.Value(), (pTcOut + pTcLoss).Value(), 1E-3, + "time: {0} distance: {1}", time, distance); + + // P_eng_fcmap = P_eng_out + P_AUX + P_eng_inertia ( + P_PTO_Transm + P_PTO_Consumer ) + Assert.AreEqual(pEngFcmap.Value(), (pEngOut + pAux + pEngInertia + pPTOtransm + pPTOconsumer).Value(), 1E-3, + "time: {0} distance: {1}", time, + distance); + + // P_eng_fcmap = sum(Losses Powertrain) + var pLossTot = pTcLoss + pLossGbx + pLossRet + pGbxInertia + pLossAngle + pLossAxle + pBrakeLoss + + pWheelInertia + pAir + pRoll + pGrad + pVehInertia + pPTOconsumer + pPTOtransm; + + Assert.AreEqual(pEngFcmap.Value(), (pLossTot + pEngInertia + pAux).Value(), 1E-3, "time: {0} distance: {1}", time, + distance); + + Assert.IsTrue(pLossGbx.IsGreaterOrEqual(pShiftLoss + pGbxInertia), "time: {0} distance: {1}", time, + distance); + + Assert.AreEqual(pGbxIn.Value(), (pRetIn + pLossGbx + pGbxInertia).Value(), gear != 0 ? 1E-3 : 0.5, + "time: {0} distance: {1}", time, + distance); + Assert.AreEqual(pEngFcmap.Value(), + (pTrac + pWheelInertia + pBrakeLoss + pLossAxle + pLossRet + pLossGbx + pGbxInertia + pEngInertia + pAux + + pTcLoss + pPTOtransm + pPTOconsumer).Value(), 0.5, "time: {0} distance: {1}", time, distance); + } + } + } } \ No newline at end of file