From 884d90c739b9aa66053d7dc08a76a848811d587c Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <markus.quaritsch@tugraz.at> Date: Fri, 30 Sep 2016 10:15:58 +0200 Subject: [PATCH] vecto gui: open engine-only jobs, validate engine-only jobs on save; validate cycle data --- VECTO/GUI/VectoJobForm.vb | 22 +++++++++- VECTO/Input Files/Gearbox.vb | 6 +-- VECTO/Input Files/VectoJob.vb | 24 +++++++++++ VectoCommon/VectoCommon/Utils/Validation.cs | 10 +++-- .../Simulation/Impl/SimulatorFactory.cs | 2 +- .../Data/DrivingCycleData.cs | 41 +++++++++++++++++++ 6 files changed, 95 insertions(+), 10 deletions(-) diff --git a/VECTO/GUI/VectoJobForm.vb b/VECTO/GUI/VectoJobForm.vb index e1adc35097..fa1cf36958 100644 --- a/VECTO/GUI/VectoJobForm.vb +++ b/VECTO/GUI/VectoJobForm.vb @@ -398,6 +398,23 @@ Public Class VectoJobForm _basePath = Path.GetDirectoryName(file) 'Update Form + If inputData.JobInputData().EngineOnlyMode Then + TbENG.Text = GetRelativePath(inputData.EngineInputData.Source, _basePath) + CbEngOnly.Checked = True + Try + Dim sb As ICycleData + For Each sb In vectoJob.Cycles + Dim lv0 As ListViewItem = New ListViewItem + lv0.Text = GetRelativePath(sb.CycleData.Source, Path.GetDirectoryName(Path.GetFullPath(file))) 'sb.Name + LvCycles.Items.Add(lv0) + Next + Catch ex As Exception + End Try + CheckEngOnly() + Exit Sub + End If + CbEngOnly.Checked = False + CheckEngOnly() 'Files ----------------------------- TbVEH.Text = GetRelativePath(inputData.VehicleInputData.Source, _basePath) TbENG.Text = GetRelativePath(inputData.EngineInputData.Source, _basePath) @@ -480,8 +497,7 @@ Public Class VectoJobForm Next Catch ex As Exception End Try - CbEngOnly.Checked = vectoJob.EngineOnlyMode - + If driver.OverSpeedEcoRoll.Mode = DriverMode.EcoRoll Then RdEcoRoll.Checked = True ElseIf driver.OverSpeedEcoRoll.Mode = DriverMode.Overspeed Then @@ -528,6 +544,8 @@ Public Class VectoJobForm '------------------------------------------------------------- End Sub + + 'Save file Private Function VECTOsave(file As String) As Boolean Dim message As String = String.Empty diff --git a/VECTO/Input Files/Gearbox.vb b/VECTO/Input Files/Gearbox.vb index 44c79d2cb5..34825a8c40 100644 --- a/VECTO/Input Files/Gearbox.vb +++ b/VECTO/Input Files/Gearbox.vb @@ -393,7 +393,7 @@ Public Class Gearbox Dim gearDict As New TransmissionInputData With { .Ratio = GearRatios(i) } - If File.Exists(GearshiftFiles(i).OriginalPath) Then + If File.Exists(GearshiftFiles(i).FullPath) Then gearDict.ShiftPolygon = VectoCSVFile.Read(GearshiftFiles(i).FullPath) End If If Not String.IsNullOrWhiteSpace(MaxTorque(i)) AndAlso IsNumeric(MaxTorque(i)) Then @@ -432,7 +432,7 @@ Public Class Gearbox Public ReadOnly Property ShiftPolygon As TableData Implements ITorqueConverterEngineeringInputData.ShiftPolygon Get - Return VectoCSVFile.Read(TorqueConverterShiftPolygonFile) + Return VectoCSVFile.Read(Path.Combine(_myPath, TorqueConverterShiftPolygonFile)) End Get End Property @@ -507,7 +507,7 @@ Public Class Gearbox Public ReadOnly Property TCData As TableData Implements ITorqueConverterDeclarationInputData.TCData Get - Return VectoCSVFile.Read(_torqueConverterFile.OriginalPath) + Return VectoCSVFile.Read(_torqueConverterFile.FullPath) End Get End Property diff --git a/VECTO/Input Files/VectoJob.vb b/VECTO/Input Files/VectoJob.vb index deaeed50a9..7d0837fde7 100644 --- a/VECTO/Input Files/VectoJob.vb +++ b/VECTO/Input Files/VectoJob.vb @@ -614,6 +614,30 @@ Public Class VectoJob ExecutionModeServiceContainer) Dim mode As ExecutionMode = If(modeService Is Nothing, ExecutionMode.Declaration, modeService.Mode) + If mode = ExecutionMode.Engineering AndAlso vectoJob.EngineOnly Then + Return ValidateEngineOnlyJob(vectoJob, mode) + End If + + Return ValidateVehicleJob(vectoJob, mode) + End Function + + Private Shared Function ValidateEngineOnlyJob(vectoJob As VectoJob, executionMode As ExecutionMode) As ValidationResult + Dim result As IList(Of ValidationResult) = New List(Of ValidationResult) + + vectoJob._engineInputData = New JSONComponentInputData(vectoJob._engineFile.FullPath) + + If vectoJob._engineInputData.EngineInputData Is Nothing Then _ + result.Add(New ValidationResult("Engine File is missing or invalid")) + If result.Any() Then + Return _ + New ValidationResult("Vecto Job Configuration is invalid. ", result.Select(Function(r) r.ErrorMessage).ToList()) + End If + + Return ValidationResult.Success + End Function + + Private Shared Function ValidateVehicleJob(vectoJob As VectoJob, mode As ExecutionMode) As ValidationResult + Dim jobData As IEnumerable(Of VectoRunData) vectoJob._vehicleInputData = New JSONComponentInputData(vectoJob._vehicleFile.FullPath) diff --git a/VectoCommon/VectoCommon/Utils/Validation.cs b/VectoCommon/VectoCommon/Utils/Validation.cs index 2ab037be88..7a81b6f9b5 100644 --- a/VectoCommon/VectoCommon/Utils/Validation.cs +++ b/VectoCommon/VectoCommon/Utils/Validation.cs @@ -54,8 +54,9 @@ namespace TUGraz.VectoCommon.Utils /// <returns>Null, if the validation was successfull. Otherwise a list of ValidationResults with the ErrorMessages.</returns> public static IList<ValidationResult> Validate<T>(this T entity, ExecutionMode mode) { - if (entity == null) - return new[] { new ValidationResult(string.Format("null value given for {0}", typeof(T)))}; + if (entity == null) { + return new[] { new ValidationResult(string.Format("null value given for {0}", typeof(T))) }; + } var context = new ValidationContext(entity); context.ServiceContainer.AddService(typeof(ExecutionMode), new ExecutionModeServiceContainer(mode)); var results = new List<ValidationResult>(); @@ -200,11 +201,12 @@ namespace TUGraz.VectoCommon.Utils if (!results.Any()) { return ValidationResult.Success; } + var messages = results.Select(r => String.Join(", ", r.MemberNames.Distinct())); if (validationContext.MemberName == "Container" || validationContext.MemberName == "RunData") { - return new ValidationResult(string.Join("\n", results)); + return new ValidationResult(string.Join("\n", results), messages); } return new ValidationResult( - string.Format("{{{0}}} invalid: {1}", validationContext.DisplayName, string.Join("\n", results))); + string.Format("{{{0}}} invalid: {1}", validationContext.DisplayName, string.Join("\n", results)), messages); } return ValidationResult.Success; diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs b/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs index 8a0c5358ff..a7bcc05b48 100644 --- a/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs +++ b/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs @@ -161,7 +161,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl var validationErrors = run.Validate(_mode); if (validationErrors.Any()) { throw new VectoException("Validation of Run-Data Failed: " + - string.Join("\n", validationErrors.Select(r => r.ErrorMessage))); + string.Join("\n", validationErrors.Select(r => r.ErrorMessage + string.Join("; ", r.MemberNames)))); } yield return run; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs index cfbca148fa..6224c73025 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs @@ -31,8 +31,12 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Diagnostics; +using System.Linq; +using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Models.Simulation.Data; namespace TUGraz.VectoCore.Models.SimulationComponent.Data { @@ -54,6 +58,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data } } + [CustomValidation(typeof(DrivingCycleData), "ValidateCycleData")] public class DrivingCycleData : SimulationComponentData { internal DrivingCycleData() {} @@ -64,6 +69,42 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data public CycleType CycleType { get; internal set; } + // ReSharper disable once UnusedMember.Global -- used by Validation + public static ValidationResult ValidateCycleData(DrivingCycleData cycleData, ValidationContext validationContext) + { + var mode = GetExecutionMode(validationContext); + if (mode == ExecutionMode.Declaration) { + return ValidationResult.Success; + } + + var result = new List<string>(); + if (cycleData.CycleType.IsDistanceBased()) { + var cur = cycleData.Entries[0].Distance; + for (var i = 1; i < cycleData.Entries.Count; i++) { + if (cycleData.Entries[i].Distance < cur) { + result.Add( + string.Format("distance-based cycle is not increasing strictly monotonous. entry: {0}, s_{1}: {2} s_{0}: {3}", i, + i - 1, cycleData.Entries[i - 1].Distance, cycleData.Entries[i].Distance)); + } + cur = cycleData.Entries[i].Distance; + } + } else { + var cur = cycleData.Entries[0].Time; + for (var i = 1; i < cycleData.Entries.Count; i++) { + if (cycleData.Entries[i].Time < cur) { + result.Add( + string.Format("time-based cycle is not increasing strictly monotonous. entry: {0}, t_{1}: {2} t_{0}: {3}", i, + i - 1, cycleData.Entries[i - 1].Time, cycleData.Entries[i].Time)); + } + cur = cycleData.Entries[i].Time; + } + } + if (result.Any()) { + return new ValidationResult(string.Format("Validation of Cycle {0} failed", cycleData.Name), result); + } + return ValidationResult.Success; + } + [DebuggerDisplay( "s:{Distance}, t:{Time}, v:{VehicleTargetSpeed}, grad:{RoadGradient}, n:{AngularVelocity}, gear:{Gear}")] public class DrivingCycleEntry -- GitLab