' Copyright 2014 European Union. ' Licensed under the EUPL (the 'Licence'); ' ' * You may not use this work except in compliance with the Licence. ' * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl ' * Unless required by applicable law or agreed to in writing, ' software distributed under the Licence is distributed on an "AS IS" basis, ' WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ' ' See the LICENSE.txt for the specific language governing permissions and limitations. Imports System.Collections.Generic Public Class cVSUM Private Const FormatVersion As Short = 1 Private VSUMpath As String Private Fvsum As System.IO.StreamWriter Private HeadInitialized As Boolean Private VSUMentries As Dictionary(Of String, cVSUMentry) Private VSUMentryList As List(Of String) 'Wird benötigt weil Dictionary nicht sortiert ist 'Needed because Dictionary is not sorted Private vsumJSON As JSON Private ResList As List(Of Dictionary(Of String, Object)) Public Sub New() HeadInitialized = False VSUMpath = "" End Sub Public Function VSUMhead() As String Dim s As New System.Text.StringBuilder Dim key As String Dim First As Boolean First = True For Each key In VSUMentryList If Not First Then s.Append(",") If DEV.AdvFormat Then s.Append(VSUMentries(key).Head) Else s.Append(VSUMentries(key).Head & " " & VSUMentries(key).Unit) End If First = False Next Return s.ToString End Function Public Function VSUMunit() As String Dim s As New System.Text.StringBuilder Dim key As String Dim First As Boolean First = True For Each key In VSUMentryList If Not First Then s.Append(",") s.Append(VSUMentries(key).Unit) First = False Next Return s.ToString End Function Public Function VSUMline() As String Dim VSUMentry As cVSUMentry Dim s As New System.Text.StringBuilder Dim t1 As Integer Dim Vquer As Single Dim Squer As Single Dim sum As Double Dim t As Integer Dim key As String Dim First As Boolean For Each VSUMentry In VSUMentries.Values VSUMentry.ValueString = Nothing Next t1 = MODdata.tDim 'Vehicle type-independent VSUMentries("\\T").ValueString = (t1 + 1) 'Length, Speed, Slope If Not VEC.EngOnly Then 'Average-Speed. calculation If DRI.Vvorg Then sum = 0 For t = 0 To t1 sum += MODdata.Vh.V(t) Next Vquer = 3.6 * sum / (t1 + 1) Squer = (Vquer * (t1 + 1) / 3600) VSUMentries("\\S").ValueString = Squer VSUMentries("\\V").ValueString = Vquer 'altitude change VSUMentries("\\G").ValueString = MODdata.Vh.AltIntp(Vquer * (t1 + 1) / 3.6, False) - MODdata.Vh.AltIntp(0, False) End If 'Auxiliary energy consumption If VEC.AuxDef Then For Each key In VEC.AuxPaths.Keys sum = 0 For t = 0 To t1 sum += MODdata.Paux(key)(t) Next VSUMentries("\\Eaux_" & UCase(key)).ValueString = sum / 3600 Next End If End If 'FC If MODdata.FCerror Then VSUMentries("FC_h").ValueString = "ERROR" If Not VEC.EngOnly Then VSUMentries("FC_km").ValueString = "ERROR" If MODdata.FCAUXcSet Then VSUMentries("FC-AUXc_h").ValueString = "ERROR" If Not VEC.EngOnly Then VSUMentries("FC-AUXc_km").ValueString = "ERROR" End If If Cfg.DeclMode Then VSUMentries("FC-WHTCc_h").ValueString = "ERROR" If Not VEC.EngOnly Then VSUMentries("FC-WHTCc_km").ValueString = "ERROR" End If Else VSUMentries("FC_h").ValueString = MODdata.FCavg If Not VEC.EngOnly And DRI.Vvorg Then 'AA - Output Bus Auxiliary values to text files If (Not VEC Is Nothing AndAlso VEC.AuxiliaryAssembly <> "CLASSIC") Then Dim FCgKm As Single = MODdata.AA_TotalCycleFC_Grams(MODdata.AA_TotalCycleFC_Grams.Count - 1) / Squer '[g/km] VSUMentries("FC_km").ValueString = FCgKm VSUMentries("FC-Final_km").ValueString = FCgKm Dim FCFinallKm As Single = ((MODdata.AA_TotalCycleFC_Litres(MODdata.AA_TotalCycleFC_Litres.Count - 1) * 100) / Squer) '[l/100km] VSUMentries("FCl_km").ValueString = FCFinallKm Dim CO2km As Single = Cfg.CO2perFC * FCgKm '[g/km] VSUMentries("CO2_km").ValueString = CO2km If VEH.Loading > 0 Then VSUMentries("CO2_tkm").ValueString = CO2km / (VEH.Loading / 1000) '[g/tkm] VSUMentries("FCl_tkm").ValueString = FCFinallKm / (VEH.Loading / 1000) '[l/100tkm] End If Else VSUMentries("FC_km").ValueString = (MODdata.FCavg / Vquer) VSUMentries("FCl_km").ValueString = (100 * MODdata.FCavgFinal / Vquer) / (Cfg.FuelDens * 1000) '[l/100km] VSUMentries("CO2_km").ValueString = Cfg.CO2perFC * (MODdata.FCavgFinal / Vquer) '[g/km] If VEH.Loading > 0 Then VSUMentries("CO2_tkm").ValueString = (Cfg.CO2perFC * (MODdata.FCavgFinal / Vquer)) / (VEH.Loading / 1000) '[g/tkm] VSUMentries("FCl_tkm").ValueString = ((100 * MODdata.FCavgFinal / Vquer) / (Cfg.FuelDens * 1000)) / (VEH.Loading / 1000) '[l/100tkm] End If VSUMentries("FC-Final_km").ValueString = (MODdata.FCavgFinal / Vquer) End If End If If MODdata.FCAUXcSet Then VSUMentries("FC-AUXc_h").ValueString = MODdata.FCavgAUXc If Not VEC.EngOnly Then VSUMentries("FC-AUXc_km").ValueString = (MODdata.FCavgAUXc / Vquer) End If If Cfg.DeclMode Then VSUMentries("FC-WHTCc_h").ValueString = MODdata.FCavgWHTCc If Not VEC.EngOnly Then VSUMentries("FC-WHTCc_km").ValueString = (MODdata.FCavgWHTCc / Vquer) End If End If 'Power, Revolutions 'Ppos sum = 0 For t = 0 To t1 sum += Math.Max(0, MODdata.Pe(t)) Next VSUMentries("\\Ppos").ValueString = (sum / (t1 + 1)) 'Pneg sum = 0 For t = 0 To t1 sum += Math.Min(0, MODdata.Pe(t)) Next VSUMentries("\\Pneg").ValueString = (sum / (t1 + 1)) 'Only Entire-vehicle (not EngOnly) If Not VEC.EngOnly Then 'PwheelPos sum = 0 For t = 0 To t1 sum += Math.Max(0, MODdata.Psum(t)) Next VSUMentries("\\PwheelPos").ValueString = (sum / (t1 + 1)) 'Pbrake-norm sum = 0 For t = 0 To t1 sum += MODdata.Pbrake(t) Next VSUMentries("\\Pbrake").ValueString = (sum / (t1 + 1)) 'Eair sum = 0 For t = 0 To t1 sum += MODdata.Pair(t) Next VSUMentries("\\Eair").ValueString = (-sum / 3600) 'Eroll sum = 0 For t = 0 To t1 sum += MODdata.Proll(t) Next VSUMentries("\\Eroll").ValueString = (-sum / 3600) 'Egrad sum = 0 For t = 0 To t1 sum += MODdata.Pstg(t) Next VSUMentries("\\Egrad").ValueString = (-sum / 3600) 'Eacc sum = 0 For t = 0 To t1 sum += MODdata.Pa(t) + MODdata.PaGB(t) + MODdata.PaEng(t) Next VSUMentries("\\Eacc").ValueString = (-sum / 3600) 'Eaux sum = 0 For t = 0 To t1 sum += MODdata.PauxSum(t) Next VSUMentries("\\Eaux").ValueString = (-sum / 3600) 'Ebrake sum = 0 For t = 0 To t1 sum += MODdata.Pbrake(t) Next VSUMentries("\\Ebrake").ValueString = (sum / 3600) 'Etransm sum = 0 For t = 0 To t1 sum += MODdata.PlossDiff(t) + MODdata.PlossGB(t) Next VSUMentries("\\Etransm").ValueString = (-sum / 3600) 'Retarder sum = 0 For t = 0 To t1 sum += MODdata.PlossRt(t) Next VSUMentries("\\Eretarder").ValueString = (-sum / 3600) 'TC Losses sum = 0 For t = 0 To t1 sum += MODdata.PlossTC(t) Next VSUMentries("\\Etorqueconv").ValueString = (-sum / 3600) 'Masse, Loading VSUMentries("\\Mass").ValueString = (VEH.Mass + VEH.MassExtra) VSUMentries("\\Loading").ValueString = VEH.Loading 'CylceKin For Each VSUMentry In MODdata.CylceKin.VSUMentries VSUMentries("\\" & VSUMentry.Head).ValueString = MODdata.CylceKin.GetValueString(VSUMentry.Head) Next 'EposICE sum = 0 For t = 0 To t1 sum += Math.Max(0, MODdata.Pe(t)) Next VSUMentries("\\EposICE").ValueString = (sum / 3600) 'EnegICE sum = 0 For t = 0 To t1 sum += Math.Min(0, MODdata.Pe(t)) Next VSUMentries("\\EnegICE").ValueString = (sum / 3600) End If 'Create Output-string: First = True For Each key In VSUMentryList If Not First Then s.Append(",") s.Append(VSUMentries(key).ValueString) First = False Next Return s.ToString End Function Private Function HeadInit() As Boolean Dim MsgSrc As String MsgSrc = "SUMALL/Output" 'Open file Try Fvsum = My.Computer.FileSystem.OpenTextFileWriter(VSUMpath, True, FileFormat) Fvsum.AutoFlush = True Catch ex As Exception WorkerMsg(tMsgID.Err, "Cannot access .vsum file (" & VSUMpath & ")", MsgSrc) Return False End Try '*** Header / Units If DEV.AdvFormat Then Fvsum.WriteLine("Job,Input File,Cycle," & VSUMhead()) Fvsum.WriteLine("[-],[-],[-]," & VSUMunit()) Else Fvsum.WriteLine("Job [-],Input File [-],Cycle [-]," & VSUMhead()) End If 'Close file (will open after each job) Fvsum.Close() HeadInitialized = True Return True End Function Public Function WriteVSUM(ByVal NrOfRunStr As String, ByVal JobFilename As String, ByVal CycleFilename As String, ByVal AbortedByError As Boolean) As Boolean Dim str As String Dim MsgSrc As String Dim dic As Dictionary(Of String, Object) Dim dic0 As Dictionary(Of String, Object) Dim dic1 As Dictionary(Of String, Object) Dim ls0 As List(Of Dictionary(Of String, Object)) Dim key As String MsgSrc = "SUMALL/Output" If Not HeadInitialized Then If Not HeadInit() Then Return False End If 'JSON dic = New Dictionary(Of String, Object) 'Open file Try Fvsum = My.Computer.FileSystem.OpenTextFileWriter(VSUMpath, True, FileFormat) Fvsum.AutoFlush = True Catch ex As Exception WorkerMsg(tMsgID.Err, "Cannot access .vsum file (" & VSUMpath & ")", MsgSrc) Return False End Try str = NrOfRunStr & "," & JobFilename & "," & CycleFilename & "," dic.Add("Job", JobFilename) If Cfg.DeclMode Then If Not Declaration.CurrentMission Is Nothing Then dic.Add("Cycle", Declaration.CurrentMission.NameStr) dic.Add("Loading", ConvLoading(Declaration.CurrentLoading)) Else dic.Add("Cycle", CycleFilename) dic.Add("Loading", ConvLoading(tLoading.UserDefLoaded)) End If If AbortedByError Then Fvsum.WriteLine(str & "Aborted due to Error!") dic.Add("AbortedByError", True) Else Fvsum.WriteLine(str & VSUMline()) dic.Add("AbortedByError", False) dic1 = New Dictionary(Of String, Object) For Each key In VSUMentryList dic0 = New Dictionary(Of String, Object) dic0.Add("Value", VSUMentries(key).ValueString) dic0.Add("Unit", VSUMentries(key).Unit) If VSUMentries(key).Multi Then If dic1.ContainsKey(VSUMentries(key).Head) Then ls0 = dic1(VSUMentries(key).Head) Else ls0 = New List(Of Dictionary(Of String, Object)) dic1.Add(VSUMentries(key).Head, ls0) End If ls0.Add(dic0) Else dic1.Add(VSUMentries(key).Head, dic0) End If Next dic.Add("Results", dic1) End If ResList.Add(dic) 'Close file Fvsum.Close() Fvsum = Nothing Return True End Function Public Function WriteJSON() As Boolean vsumJSON.Content("Body").add("Results", ResList) Try Return vsumJSON.WriteFile(VSUMpath & ".json") Catch ex As Exception Return False End Try End Function Private Sub AddToVSUM(ByVal IDstring As String, ByVal Head As String, ByVal Unit As String, Optional Multi As Boolean = False) If Not VSUMentries.ContainsKey(IDstring) Then VSUMentries.Add(IDstring, New cVSUMentry(Head, Unit)) VSUMentryList.Add(IDstring) If Multi Then VSUMentries(IDstring).Multi = True End If End Sub Public Function Init(ByVal JobFile As String) As Boolean Dim JobFiles As New List(Of String) Dim str As String Dim str1 As String Dim file As New cFile_V3 Dim VEC0 As cVECTO Dim MAP0 As cMAP Dim ENG0 As cENG Dim HEVorEVdone As Boolean Dim EVdone As Boolean Dim EngOnly As Boolean Dim NonEngOnly As Boolean Dim VSUMentry As cVSUMentry Dim CylceKin As cCycleKin Dim i1 As Integer Dim i2 As Integer Dim iDim As Integer Dim dic As Dictionary(Of String, Object) Dim MsgSrc As String MsgSrc = "SUMALL/Init" 'Check if file exists If Not IO.File.Exists(JobFile) Then WorkerMsg(tMsgID.Err, "Job file not found! (" & JobFile & ")", MsgSrc) Return False End If 'Define Output-path If Cfg.BatchMode Then Select Case UCase(Cfg.BATCHoutpath) Case sKey.JobPath VSUMpath = fFileWoExt(JobFile) & "_BATCH.vsum" Case Else VSUMpath = Cfg.BATCHoutpath & fFILE(JobFile, False) & "_BATCH.vsum" End Select Else VSUMpath = fFileWoExt(JobFile) & ".v2.vsum" End If 'Open file Try 'Open file Fvsum = My.Computer.FileSystem.OpenTextFileWriter(VSUMpath, False, FileFormat) Fvsum.AutoFlush = True Catch ex As Exception WorkerMsg(tMsgID.Err, "Cannot write to .vsum file (" & VSUMpath & ")", MsgSrc) Return False End Try 'JSON vsumJSON = New JSON dic = New Dictionary(Of String, Object) dic.Add("CreatedBy", Lic.LicString & " (" & Lic.GUID & ")") dic.Add("Date", Now.ToString) dic.Add("AppVersion", VECTOvers) dic.Add("FileVersion", FormatVersion) vsumJSON.Content.Add("Header", dic) vsumJSON.Content.Add("Body", New Dictionary(Of String, Object)) dic = New Dictionary(Of String, Object) dic.Add("Air Density [kg/m3]", Cfg.AirDensity) dic.Add("CO2/FC [-]", Cfg.CO2perFC) dic.Add("Fuel Density [kg/l]", Cfg.FuelDens) dic.Add("Distance Correction", Cfg.DistCorr) vsumJSON.Content("Body").add("Settings", dic) ResList = New List(Of Dictionary(Of String, Object)) 'Info If DEV.AdvFormat Then Fvsum.WriteLine("VECTO " & VECTOvers) Fvsum.WriteLine(Now.ToString) Fvsum.WriteLine("Input File: " & JobFile) End If 'Close file (will open after each job) Fvsum.Close() 'Add file to signing list Lic.FileSigning.AddFile(VSUMpath) Lic.FileSigning.AddFile(VSUMpath & ".json") VSUMentries = New Dictionary(Of String, cVSUMentry) VSUMentryList = New List(Of String) For Each str In JobFileList JobFiles.Add(fFileRepl(str)) Next '********************** Create VSUM-Entries '********************** EVdone = False HEVorEVdone = False EngOnly = False NonEngOnly = False 'Vehicle type-independent AddToVSUM("\\T", "time", "[s]") For Each str In JobFiles VEC0 = New cVECTO VEC0.FilePath = str Try If Not VEC0.ReadFile Then WorkerMsg(tMsgID.Err, "Can't read .vecto file '" & str & "' !", MsgSrc) Return False End If Catch ex As Exception WorkerMsg(tMsgID.Err, "File read error! (" & str & ")", MsgSrc) Return False End Try If VEC0.EngOnly Then If Not EngOnly Then 'nothing... EngOnly = True End If Else If Not NonEngOnly Then AddToVSUM("\\S", "distance", "[km]") AddToVSUM("\\V", "speed", "[km/h]") AddToVSUM("\\G", "∆altitude", "[m]") NonEngOnly = True End If 'Auxiliary energy consumption If VEC0.AuxDef Then For Each str1 In VEC0.AuxPaths.Keys AddToVSUM("\\Eaux_" & UCase(str1), "Eaux_" & str1, "[kWh]") Next End If End If 'Conventional vehicles ... AddToVSUM("\\Ppos", "Ppos", "[kW]") AddToVSUM("\\Pneg", "Pneg", "[kW]") 'From the Engine-Map ENG0 = New cENG ENG0.FilePath = VEC0.PathENG Try If Not ENG0.ReadFile Then WorkerMsg(tMsgID.Err, "File read error! (" & VEC0.PathENG & ")", MsgSrc) Return False End If Catch ex As Exception WorkerMsg(tMsgID.Err, "File read error! (" & VEC0.PathENG & ")", MsgSrc) Return False End Try MAP0 = New cMAP MAP0.FilePath = ENG0.PathMAP Try If Not MAP0.ReadFile(True) Then WorkerMsg(tMsgID.Err, "File read error! (" & ENG0.PathMAP & ")", MsgSrc) Return False End If Catch ex As Exception WorkerMsg(tMsgID.Err, "File read error! (" & ENG0.PathMAP & ")", MsgSrc) Return False End Try AddToVSUM("FC_h", "FC-Map", "[g/h]", True) AddToVSUM("FC-AUXc_h", "FC-AUXc", "[g/h]", True) AddToVSUM("FC-WHTCc_h", "FC-WHTCc", "[g/h]", True) If Not VEC0.EngOnly Then AddToVSUM("FC_km", "FC-Map", "[g/km]", True) AddToVSUM("FC-AUXc_km", "FC-AUXc", "[g/km]", True) AddToVSUM("FC-WHTCc_km", "FC-WHTCc", "[g/km]", True) AddToVSUM("CO2_km", "CO2", "[g/km]", True) AddToVSUM("CO2_tkm", "CO2", "[g/tkm]", True) AddToVSUM("FC-Final_km", "FC-Final", "[g/km]", True) AddToVSUM("FCl_km", "FC-Final", "[l/100km]", True) AddToVSUM("FCl_tkm", "FC-Final", "[l/100tkm]", True) End If Next If EngOnly Then 'currently nothing End If If NonEngOnly Then 'Vehicle-related fields AddToVSUM("\\PwheelPos", "PwheelPos", "[kW]") AddToVSUM("\\Pbrake", "P_brake_loss", "[kW]") AddToVSUM("\\EposICE", "EposICE", "[kWh]") AddToVSUM("\\EnegICE", "EnegICE", "[kWh]") AddToVSUM("\\Eair", "Eair", "[kWh]") AddToVSUM("\\Eroll", "Eroll", "[kWh]") AddToVSUM("\\Egrad", "Egrad", "[kWh]") AddToVSUM("\\Eacc", "Eacc", "[kWh]") AddToVSUM("\\Eaux", "Eaux", "[kWh]") AddToVSUM("\\Ebrake", "Ebrake", "[kWh]") AddToVSUM("\\Etransm", "Etransm", "[kWh]") AddToVSUM("\\Eretarder", "Eretarder", "[kWh]") AddToVSUM("\\Etorqueconv", "Etorqueconv", "[kWh]") AddToVSUM("\\Mass", "Mass", "[kg]") AddToVSUM("\\Loading", "Loading", "[kg]") 'CylceKin CylceKin = New cCycleKin For Each VSUMentry In CylceKin.VSUMentries AddToVSUM("\\" & VSUMentry.Head, VSUMentry.Head, VSUMentry.Unit) Next End If If( Not VEC is Nothing AndAlso VEC.AuxiliaryAssembly<>"CLASSIC") then 'Advanced Auxiliaries I.E. Bus Auxiliaries. AddToVSUM("\\AA_FC_LHR","AA FC L/H","L/R",false) AddToVSUM("\\AA_FC_GHR","AA FC G/H","G/R",false) End if 'Sort iDim = VSUMentryList.Count - 1 For i1 = 0 To iDim - 1 str = VSUMentries(VSUMentryList(i1)).Head For i2 = i1 + 1 To iDim If VSUMentries(VSUMentryList(i2)).Head = str Then VSUMentryList.Insert(i1 + 1, VSUMentryList(i2)) VSUMentryList.RemoveAt(i2 + 1) End If Next Next 'Sort Aux For i1 = 0 To iDim - 1 str = VSUMentries(VSUMentryList(i1)).Head If str.Length > 4 AndAlso Left(str, 4) = "Eaux" Then For i2 = i1 + 1 To iDim If VSUMentries(VSUMentryList(i2)).Head.Length > 4 AndAlso Left(VSUMentries(VSUMentryList(i2)).Head, 4) = "Eaux" Then VSUMentryList.Insert(i1 + 1, VSUMentryList(i2)) VSUMentryList.RemoveAt(i2 + 1) End If Next End If Next Return True End Function Public ReadOnly Property VSUMfile As String Get Return VSUMpath End Get End Property End Class Public Class cVSUMentry Public Head As String Public Unit As String Public MyVal As Object Public Multi As Boolean Public Sub New(ByVal HeadStr As String, ByVal UnitStr As String) Head = HeadStr Unit = UnitStr MyVal = Nothing Multi = False End Sub Public Property ValueString As Object Get If MyVal Is Nothing Then Return "-" Else Return MyVal End If End Get Set(value As Object) MyVal = value End Set End Property End Class