diff --git a/.gitignore b/.gitignore index 0f6e6ab57cf9b8b246b9e2d1b043dc98c6921f85..27fd0863a2fd6eb2ae4a79d091bdf46586f7da96 100644 --- a/.gitignore +++ b/.gitignore @@ -219,3 +219,4 @@ Documentation/VehiclesReleaseComparisonDeclarationMode/tmp/ /VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/tests.xml /VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/finalGroup41.VIF_Report_4.xml /VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/output +/Vecto3GUI2020Test/TestData/output diff --git a/Documentation/BusAuxCases with ESS_Formatted.xlsx b/Documentation/BusAuxCases with ESS_Formatted.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..6bdc87d0dc23f53c90b0c5e001b9061f2bb13a02 Binary files /dev/null and b/Documentation/BusAuxCases with ESS_Formatted.xlsx differ diff --git a/Documentation/User Manual/3-simulation-models/ADAS_EcoRoll.md b/Documentation/User Manual/3-simulation-models/ADAS_EcoRoll.md index f71eb6ae658cb4ff4e09d25c1f38e6a82a2c4daa..1efff08b14a8225ee4d0b37a3ffde9758f7d76d8 100644 --- a/Documentation/User Manual/3-simulation-models/ADAS_EcoRoll.md +++ b/Documentation/User Manual/3-simulation-models/ADAS_EcoRoll.md @@ -49,13 +49,12 @@ $E_{ICE,start} = E_{ICE,rampUp} / \eta_{alternator}^2$ $E_{ICE,start}$ is the amount of energy the combustion engine needs to provide to compensate the start up is the ramp-up energy multiplied by the efficiency of the alternator. $t_{ICE,start}$ is assumed to be 1 second and $\eta_{alternator}$ is 0.7. -###Utility Factor +###Auxiliaries and Utility Factor -Engine Stop/Start is usually not activated at every vehicle stop. This is considered in VECTO via a utility factor (e.g. 0.8). This utility factor (f) is applied for every engine stop as follows: - - - the auxiliary demand during engine stops is multiplied by the utility factor - - the fuel consumption FC_final during engine stop is the fuel consumption with the engine idling and all auxiliaires on multiplied by 1-f - - the energy demand for starting the engine is multiplied by the utility factor +During ICE-off phases the ICE is fully shut of in the simulation (.vmod data). However, in reality the ICE is not always switched off due to certain +boundary conditions (e.g. power demand from an auxiliary, temperature, etc.). This is considered in the [post-processing](#engine-fuel-consumption-correction). +Therefore, the demand for different auxiliaries is balanced in separate columns in the [.vmod](#modal-results-.vmod) file for the two cases a) ICE is really off, and b) ICE would be on. +This is done for the mechanical auxiliaries, bus-aux electric demand (all different cases like ES connected to the REESS, smart ES, conventional ES, and combinations thereof), bus-aux pneumatic system. A detailed description which auxiliary power demand is balanced in which columns can be found in [this spreadsheet](BusAuxCases with ESS_Formatted.xlsx) for all combinations of conventional vehicles, bus auxiliaries, and hybrid vehicles. <div class="declaration"> **Auxiliary energy demand** @@ -67,7 +66,12 @@ In Declaration Mode the energy demand of all auxiliaries except the engine cooli <div class="engineering"> **Auxiliary energy demand** -In Engineering Mode the energy demand of all auxiliaries is assumed to be drawn also during engine-off periods and the fuel consumption is corrected in a post-processing step. +In Engineering Mode the energy demand of the auxiliaries can be specified for the cases: + - ICE on + - ICE off, vehicle standstill + - ICE off, vehicle driving + + </div> @@ -167,7 +171,7 @@ In declaration mode, the whole long-haul cycle is considered as highway. Moreove 1. In a preprocessing step the road gradient where the vehicle would accelerate on its own is computed for certain velocities. If the vehicle is equipped with eco-roll the powertrain is declutched, otherwise the engine is in full drag. The slope is calculated for every simulated cycle as this values vary with the vehicle's payload, rolling resistance and air drag. 2. All positions in the driving cycle where the slope is lower than the road gradient required that the vehicle accelerates on its own are marked as potential candidates for PCC events. At this distance the vehicle's velocity shall be a minimum. Denoted as $x_{v_{low}}$. -3. For every potential PCC event, the end position is marked in the driving cycle. This is the first position in the driving cycle after $x_v_{low}}$ where the slope is greater than the road gradient required that the vehicle accelerates on its own. Latest at this position the vehicle shall reach the target velocity again. Denoted as $x_{end, max}$ +3. For every potential PCC event, the end position is marked in the driving cycle. This is the first position in the driving cycle after $x_{v_{low}}$ where the slope is greater than the road gradient required that the vehicle accelerates on its own. Latest at this position the vehicle shall reach the target velocity again. Denoted as $x_{end, max}$ 4. For every potential PCC event, the earliest start position is marked. This is calculated as $x_{start} = x_{v_{low}} - d_{preview}$. 5. For every potential PCC event, the vehicle's energy is calculated: $E(x_{v_{low}}) = m \cdot g \cdot h(x_{v{low}}) + \frac{m \cdot (v_{target}(x_{v_{low}}) - v_{neg})^2}{2}$ diff --git a/Documentation/User Manual/3-simulation-models/Engine_FC_Correction.md b/Documentation/User Manual/3-simulation-models/Engine_FC_Correction.md index cb1f6df41897422c52779397aeef4622d6f92f45..752b107ad8c20294ceace0201ecaa0abdd5c9c29 100644 --- a/Documentation/User Manual/3-simulation-models/Engine_FC_Correction.md +++ b/Documentation/User Manual/3-simulation-models/Engine_FC_Correction.md @@ -4,49 +4,181 @@ The final fuel consumption is corrected in a post-processing to reflect systems ###Engine Stop/Start Correction -As the energy demand of auxiliaries is modeled as an average power demand over the whole simulated cycle, the energy demand of certain auxiliaries during engine-off periods needs to be compensated during engine-on periods. This is done using the [Engine-Line approach](##engine-line-approach). The energy demand of the auxiliaries that shall be active also during engine-off periods as well as the energy demand for starting the engine is accumulated (see [Engine Stop/Start](#advanced-driver-assistant-systems-engine-stopstart), [Eco-Roll with Engine Stop/Start](#advanced-driver-assistant-systems-eco-roll), and [PCC with Eco-Roll and Engine Stop/Start](#advanced-driver-assistant-systems-predictive-cruise-control)) during the simulation. The final fuel consumption is corrected for this "missing" energy +As the energy demand of auxiliaries is modeled as an average power demand over the whole simulated cycle, the demand of certain auxiliaries during engine-off periods needs to be compensated during engine-on periods. This is done using the [Engine-Line approach](#engine-line-approach). -###Bus Auxiliaries Correction +During the simulation the combustion engine is allways off. In this phases the "missing" auxiliary demand is balanced in separate colums for the cases a) the ICE is really off, and b) the ICE would be on. This allows for an accurate correction of the fuel consumption taking into account that ESS is in reality not active in all possible cases due to e.g. auxiliary power demand, environmental conditions, etc. -**Electric System** +A general goal is that the actual auxiliary demand matches the target auxiliary demand over the cycle. So in case the ICE is off, some systems still consume electric energy but no electric energy is created during ICE-off phases. Or in case of bus auxiliaries the total air demand is pre-calculated and thus leading to an average air demand over the cycle. During ICE-off phases, however, no compressed air is generated. This 'missing' compressed air is corrected in the post-processing. -In case smart electrics are used the electric energy generated may be different from the electric energy consumed as the smart alternator may generate more electric power in drag situations. Moreover, the state of charge of a battery may be different at the end of the simulated cycle than at the beginning and thus the fuel consumption needs to be corrected. +A utility factor (UF) considers that the ICE is not off in all cases. Therefore the fuel consumption for compensating the missing auxiliary demand consists of two parts. The first part considers the fuel consumption required for the 'missing' auxiliary demand if the ICE is really off. Here the according auxiliary energy demand is multiplied by the utility factor and the engine line. The second part considers the fuel consumption in case the ICE would not be switched off. Here the 'missing' auxiliary energy demand is multiplied by (1 - utility factor) and the engine line and the idle fuel consumption is added for time periods the ICE would be on. -$\Delta E_\textrm{ES} = E_\textrm{ES,consumed} - E_\textrm{ES,generated} + (\textrm{SOC}_\textrm{start} - \textrm{SOC}_\textrm{end}) * \textrm{Capacity}_{\textrm{RESS}}$ +For the post-processing two different utility factors are considered. One for ICE-off phases during vehicle standstill and one for ICE-off phases during driving. -$E_\textrm{ES,mech,corr} = \Delta E_\textrm{ES} / \eta_\textrm{alternator} / \eta_\textrm{pulley}$ +####ICE Start -**Pneumatic System** +$\textrm{E\_ICE\_start} = \sum{\textrm{P\_ICE\_start} \cdot dt}$ -In case of smart pneumatics the total air generated may be different from the total air consumed by all pneumatic consumers as the smart compressor generates more compressed air in drag situations. The fuel energy difference is corrected according to the following equations: +$\textrm{FC\_ICE\_start} = \textrm{E\_ICE\_start} \cdot k_\textrm{engline}$ -$\Delta \textrm{Air} = \textrm{Air}_\textrm{consumed,total} - \textrm{Air}_\textrm{generated,total}$ +####Mechanical Auxiliaries -$k_\textrm{Air} = (E_\textrm{PS,generated} - E_\textrm{PS,off}) / (\textrm{Air}_\textrm{generated,total} - 0)$ +$\textrm{E\_aux\_ESS\_mech\_ICEoff\_standstill} = \sum_{\forall \textrm{v\_act}_i = 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_off} \cdot dt}$ -$E_\textrm{PS,corr} = k_\textrm{Air} * \Delta \textrm{Air}$ +$\textrm{E\_aux\_ESS\_mech\_ICEoff\_driving} = \sum_{\forall \textrm{v\_act}_i > 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_off} \cdot dt}$ -**Aux Heater** +$\textrm{E\_aux\_ESS\_mech\_ICEon\_standstill} = \sum_{\forall \textrm{v\_act}_i = 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_on} \cdot dt}$ + +$\textrm{E\_aux\_ESS\_mech\_ICEon\_driving} = \sum_{\forall \textrm{v\_act}_i > 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_on} \cdot dt}$ + + +$$ +\begin{align*} +\textbf{\textrm{FC\_ESS}} =\, & \textrm{FC\_ICE\_start} + \\ + & \textrm{E\_aux\_ESS\_mech\_ICEoff\_standstill} \cdot k_\textrm{engline} \cdot \textrm{UF}_\textrm{standstill} + \\ + & (\textrm{E\_aux\_ESS\_mech\_ICEon\_standstill} \cdot k_\textrm{engline} + \textrm{FC}(n_\textrm{idle}, 0) \cdot \textrm{t\_ICEoff\_standstill}) \cdot (1 - \textrm{UF}_\textrm{standstill}) \\ + & \textrm{E\_aux\_ESS\_mech\_ICEoff\_driving} \cdot k_\textrm{engline} \cdot \textrm{UF}_\textrm{driving} + \\ + & (\textrm{E\_aux\_ESS\_mech\_ICEon\_driving} \cdot k_\textrm{engline} + \textrm{FC}(n_\textrm{idle}, 0) \cdot \textrm{t\_ICEoff\_driving}) \cdot (1 - \textrm{UF}_\textrm{driving}) +\end{align*} +$$ + + +####Bus Auxiliaries Correction -- Electric System + +The bus auxiliaries electric system correction is used for conventional vehicles with ESS and buses with smart electric system in the same way. + +$\textrm{E\_BusAux\_ES\_consumed} = \sum{\textrm{P\_BusAux\_ES\_consumed} \cdot dt}$ + +$\textrm{E\_BusAux\_ES\_gen} = \sum{\textrm{P\_BusAux\_ES\_gen} \cdot dt}$ + +$\Delta\textrm{E\_BusAux\_ES\_mech} = (\textrm{E\_BusAux\_ES\_consumed} - \textrm{E\_BusAux\_ES\_gen}) / \textrm{AlternatorEfficiency} / \textrm{AlternatorGearEfficiency}$ + +$\textbf{\textrm{FC\_BusAux\_ES}} = \textrm{E\_BusAux\_ES} \cdot k_\textrm{engline}$ + +####Bus Auxiliaries Correction -- Electric System Supply from REESS + +$\textrm{E\_DCDC\_missing} = \textrm{P\_DCDC\_missing} \cdot dt$ + +$\textrm{E\_DCDC\_missing\_mech} = \textrm{E\_DCDC\_missing} / \textrm{DCDC\_ConverterEfficiency} / \eta_{\textrm{EM}_\textrm{chg}}$ + +$\textbf{\textrm{FC\_DCDCMissing}} = \textrm{E\_DCDC\_missing\_mech} \cdot k_\textrm{engline}$ + + +####Bus Auxiliaries Correction -- Pneumatic System + +For the pneumatic system the goal of the post-processing correction is that the correct amount of compressed air is generated, even when the ICE is off. As the average +air demand is calculated with an estimated cycle driving time, the first step is to correct the air demand using the actual cycle driving time. +The missing (or excessive) amout of air is transferred into mechanical energy demand using $k_\textrm{Air}$. This value depicts the delta energy demand for a certain delta compressed air. +$k_\textrm{Air}$ is derived from two points. on the one hand the compressor runs in idle mode, applying only the drag load and producing no compressed air and the second point is that the compressor +is always on, applying the always-on mechanical power demand and generating the maximum possible amount of compressed air. +The mechanical energy is then corrected using the engineline. + +$\textrm{E\_busAux\_PS\_drag} = \sum_{\textrm{Nl\_busAux\_consumed}_i = \textrm{Nl\_busAux\_gen}_i}{\textrm{P\_busAux\_PS\_drag}\cdot dt}$ + +$\textrm{E\_busAux\_PS\_alwaysOn} = \sum_{\textrm{Nl\_busAux\_consumed}_i = \textrm{Nl\_busAux\_gen}_i}{\textrm{P\_busAux\_PS\_alwaysOn} \cdot dt}$ + +$\textrm{Nl\_alwaysOn} = \sum_{\textrm{Nl\_busAux\_consumed}_i = \textrm{Nl\_busAux\_gen}_i}{\textrm{Nl\_busAux\_gen\_max}}$ + +$k_\textrm{Air} = \frac{\textrm{E\_busAux\_PS\_alwaysOn} - \textrm{E\_busAuxPS\_drag}}{\textrm{Nl\_alwaysOn} - 0}$ + + + + +$\textrm{CorrectedAirDemand} = \textrm{[Calculate Air demand with actual cycle time]}$ + +$\textrm{AirGenerated} = \sum{\textrm{Nl\_busAux\_PS\_gen}}$ + +$\Delta\textrm{Air} = \textrm{CorrectedAirDemand} - \textrm{AirGenerated}$ + +$\textrm{E\_busAux\_PS\_corr} = \Delta\textrm{Air} \cdot k_\textrm{Air}$ + +$\textrm{FC\_BusAux\_PS\_AirDemand} = \textrm{E\_busAux\_PS\_corr} \cdot k_\textrm{engline}$ + +$\textrm{FC\_BusAux\_PS\_Drag\_ICEoff\_driving} = \textrm{P\_PS\_drag}(n_\textrm{idle}) \cdot k_\textrm{engline} \cdot \textrm{t\_ICEoff\_driving} \cdot (1 - \textrm{UF}_\textrm{driving})$ + +$\textrm{FC\_BusAux\_PS\_Drag\_ICEoff\_standstill} = \textrm{P\_PS\_drag}(n_\textrm{idle}) \cdot k_\textrm{engline} \cdot \textrm{t\_ICEoff\_standstill} \cdot (1 - \textrm{UF}_\textrm{standstill})$ + + +$$ +\begin{align*} +\textbf{\textrm{FC\_BusAux\_PS}} =\, & \textrm{FC\_BusAux\_PS\_AirDemand} + \\ + & \textrm{FC\_BusAux\_PS\_Drag\_ICEoff\_driving} + \\ + & \textrm{FC\_busAux\_PS\_Drag\_ICEoff\_standstill} \\ +\end{align*} +$$ + + +####Bus Auxiliaries Correction -- Aux Heater + +The power demand for an additional fuel-fired heater is calculated in the post-processing. The HVAC steaty state model calculates the heating demand (weighted sum of different climatic conditions) and based on the engine's average waste heat over the cycle the power demand for the aux heater is calculated. The fuel consumption for the aux heater is only added for the main fuel: -The power demand for an additional fuel-fired heater is calculated in the post-processing. The HVAC steaty state model calculates the heating demand (weighted sum of different climatic conditions) and based on the engine's average waste heat over the cycle the power demand for the aux heater is calculated. $E_\textrm{ice,waste heat} = \sum_\textrm{fuels} FC_\textrm{final,sum}(fuel) * NCV_\textrm{fuel}$ $\overline{P}_\textrm{ice,waste heat} = E_\textrm{ice, waste heat} / t_\textrm{cycle}$ -$E_{auxHeater} = P_\textrm{HVACSSM,auxHtr}(\overline{P}_\textrm{ice,waste heat}) * t_\textrm{cycle}$ +$\textrm{E\_auxHeater} = \textrm{HVACSSM}_\textrm{AuxHtr}(\overline{P}_\textrm{ice,waste heat}) * t_\textrm{cycle}$ -###Engine-Line Approach +$\textbf{\textrm{FC\_BusAux\_AuxHeater}} = \textrm{E\_auxHeater} \cdot \textrm{NCV}_\textrm{main fuel}$ -The total fuel consumption is corrected in a post-processing step according to the *engine-line* approach. Therefore, for every engine operating point where the engine is switched on and has a positive fuel consumption the fuel consumption is plotted over the engine power. The slope (k) of the linear regression of the fuel consumption is used to compute the additional fuel that is needed for the energy demand during engine-off periods and engine starts. +####Waste Heat Recovery Systems - +$\textrm{E\_WHR\_mech} = \sum{\textrm{P\_WHR\_mech} \cdot dt}$ + +$\textrm{E\_WHR\_el} = \sum{\textrm{P\_WHR\_el} \cdot dt}$ + +$$ +\textrm{E\_WHR\_el\_mech} = \begin{cases} +\textrm{E\_WHR\_el} / \textrm{AlternatorEfficiency} & if conventional truck \\ +\textrm{E\_WHR\_el} / \eta_{\textrm{EM}_\textrm{chg}} & if bus with ES connected to REES and smart alternator \\ +\textrm{E\_WHR\_el} / \textrm{BusAlternatorEfficiency} & otherwise +\end{cases} +$$ + +$\textbf{\textrm{FC\_WHR}} = - (\textrm{E\_WHR\_mech} + \textrm{E\_WHR\_el\_mech}) \cdot k_\textrm{engline}$ + + +####Hybrid Vehicles: REESS SoC Correction -$\Delta FC = k * (E_\textrm{aux,ICE,off} + E_\textrm{ICE,start} - E_\textrm{WHR,corr}/\eta_\textrm{alternator}) + k * (E_\textrm{ES,mech,corr} + E_\textrm{PS,corr})$ +If the REESS Soc at the end of the simulation is higher than the initial SoC the correction is done according to: -The fuel consumption for the aux heater is only added for the main fuel: +$$ +\textbf{\textrm{FC\_SoC}} = -\frac{\Delta\textrm{E\_REESS} \cdot k_\textrm{engline}}{\eta_{\textrm{EM}_\textrm{chg}} \cdot \eta_{\textrm{REESS}_\textrm{chg}}} +$$ -$\Delta FC_\textrm{auxHeater} = E_\textrm{auxHeater} * NCV_\textrm{main fuel}$ -$FC_\textrm{final} = FC_\textrm{final,mod} + \Delta FC + \Delta FC_\textrm{auxHeater}$ +If the REESS Soc at the end of the simulation is lower than the initial SoC the correction is done according to: + +$$ +\textbf{\textrm{FC\_SoC}} = - \Delta\textrm{E\_REESS} \cdot k_\textrm{engline} \cdot \eta_{\textrm{EM}_\textrm{dischg}} \cdot \eta_{\textrm{REESS}_\textrm{dischg}} +$$ + + +$\eta_{\textrm{REESS}_\textrm{chg}} = \frac{\textrm{E\_REESS\_INT\_CHG}}{\textrm{E\_REEES\_T\_CHG}}$ + +$\eta_{\textrm{REESS}_\textrm{dischg}} = \frac{\textrm{E\_REESS\_INT\_DISCHG}}{\textrm{E\_REEES\_T\_DISCHG}}$ + + +###Corrected Total Fuel Consumption + +The final fuel consumption after all corrections are applied is calcualted as follows: + +$$ +\begin{align*} +\textrm{FC\_FINAL} =\;& \textrm{FC\_ModSum} \;+ \\ + & \textrm{FC\_ESS} \;+ \\ + & \textrm{FC\_DCDCMissing} \;+ \\ + & \textrm{FC\_BusAux\_PS} \;+ \\ + & \textrm{FC\_BusAux\_ES} \;+ \\ + & \textrm{FC\_WHR} \;+ \\ + & \textrm{FC\_BusAux\_AuxHeater} \;+ \\ + & \textrm{FC\_SoC} \\ +\end{align*} +$$ + + +###Engine-Line Approach + +The total fuel consumption is corrected in a post-processing step according to the *engine-line* approach. Therefore, for every engine operating point where the engine is on and has a positive fuel consumption the fuel consumption is plotted over the engine power. The slope (k) of the linear regression of the fuel consumption is used to compute the additional fuel that is needed for the energy demand during engine-off periods and engine starts. + + diff --git a/Documentation/User Manual/5-input-and-output-files/VMOD.md b/Documentation/User Manual/5-input-and-output-files/VMOD.md index 7d6cd4fe5d4af5f577f84fed80cb3f380211f78f..d63e31c687d83a80ce8259144b271dc9f095033d 100644 --- a/Documentation/User Manual/5-input-and-output-files/VMOD.md +++ b/Documentation/User Manual/5-input-and-output-files/VMOD.md @@ -33,14 +33,45 @@ $P_{avg} = \frac{1}{simulation interval} \int{P(t) dt}$. | Tq_drag | [Nm] | Engine's drag torque, interpolated from the full-load curve | | P_ice_fcmap | [kW] | Total power the engine has to provide, computed from n_eng_avg and T_eng_fcmap | | P_ice_full | [kW] | Engine's transient maximum power (see [transient full load](#engine-transient-full-load)) | +| P_ice_full_stat | [kW] | Engine's stationary maximum power | | P_ice_drag | [kW] | Engine's drag power | | P_ice_inertia | [kW] | Power loss/gain due to the engine's inertia | | P_ice_out | [kW] | Power provided at the engine's output shaft | +| P_REESS_T | [kW] | Electric power provided at the battery's connector | +| P_REESS_int | [kW] | Internal battery power | +| P_REESS_loss | [kW] | Losses of the battery due to its internal resistance. | +| P_REESS_charge_max | [kW] | Maximum power the battery can be charged with | +| P_REESS_discharge_max | [kW] | Maximum power the battery can provide | +| REESS SOC | [%] | The battery's current state of charge | +| U_REESS_T | [V] | Voltage at the battery's connector | +| U_0_REESS | [V] | Battery's internal voltage | +| I_REESS | [A] | Current charging/discharging the battery. | +| i_\<POS}-em | [-] | Ratio between drivetrain and electric motor shaft +| P_\<POS>\_out | [kW] | Power at the electric machine's output shaft (drivetrain) | +| P_\<POS>\_mech | [kW] | Mechanical power the electric machine applies to the drivetrain. Positive values mean that electric energy is generated while negative values mean that the electric machine drives the vehicle. | +| P_\<POS>\_in | [kW] | Power at the electric machine's input shaft (drivetrain) | +| P_\<POS>\_transm_loss | [kW] | Losses of the transmission stage inside the electric motor component | +| P_\<POS>-em_mech | [kW] | Power at the shaft of the electric motor at position *POS* | +| P_\<POS>-em_inertia_loss | [kW] | Inertia loses of the electric machine | +| P_\<POS>-em_mech_map | [kW] | Mechanical powerthe electric motor at position *POS* applies for driving or recuperation, including the electric motor's inertia | +| P_\<POS>-em_loss | [kW] | Losses in the electric machine due to converting electric power to mechanical power | +| P_\<POS>-em_el | [kW] | Electric power generated or consumed by the elctric machine | +| P_\<POS>\_loss | [kW] | The total sum of losses of the electric motor at position *POS*. Calcualted as the difference of mecanical power applied at the drivetrain and the electrical power drawn from the REESS. | +| n_\<POS>-em_avg | [rpm] | Angular speed of the electric motor at position *POS* | +| T_\<POS>-em | [Nm] | Torque at the shaft of electric motor at position *POS*. Positive values mean that the electric motor acts as generator, negative torque values mean that the electric motor propels the vehicle | +| T_\<POS>-em_map | [Nm] | Torque internal torque of the electric motor at posision *POS*. Takes into account the electric motor's intertia. Positive values mean that the electric motor acts as generator, negative torque values mean that the electric motor propels the vehicle | +| T_\<POS>-em_drive_max | [Nm] | Maximum torque the electric machine can apply to propel the vehicle. This already considers the maximum current the battery can provide | +| T_\<POS>-em_gen_max | [Nm] | Maximum torque the electric machine can apply to generate electric power. This already considers the maximum charge current the battery can handle. | +| P_\<POS>-em_drive_max | [kW] | Maximum power the electric motor can provide to drive the vehicle. This already considers the maximum electric power the battery can provide. | +| P_\<POS>-em_gen_max | [kW] | Maximum power the electric machine can generate. This already considers the maximum charge power the battery can handle. | +| EM_OVL-\<POS>-em | [%] | Used capacity of the thermal overload buffer of the thermal derating model | +| EM_\<POS>_off | [-] | Indicates if the electric motor at position *POS* is energized or not. | | P_clutch_loss | [kW] | Power loss in the clutch due to slipping when driving off | | P_clutch_out | [kW] | Power at the clutch's out shaft. P_clutch_out = P_eng_out - P_clutch_loss | | P_TC_out | [kW] | Power at the torque converter's out shaft. P_TC_out = P_eng_out - P_TC_loss | | P_TC_loss | [kW] | Power loss in the torque converter | -| P_aux | [kW] | Total power demand from the auxiliaries | +| P_aux_mech | [kW] | Total power demand from the mechanical auxiliaries | +| P_aux_el | [kW] | Total power demand from the electric auxiliaries connected to the REESS | | P_gbx_in | [kW] | Power at the gearbox' input shaft | | P_gbx_loss | [kW] | Power loss at the gearbox, interpolated from the loss-map + shift losses + inertia losses | | P_gbx_shift | [kW] | Power loss due to gearshifts (AT gearbox) | @@ -60,9 +91,10 @@ $P_{avg} = \frac{1}{simulation interval} \int{P(t) dt}$. | P_air | [kW] | Power loss due to air drag. | | P_roll | [kW] | Rolling resistance power loss. | | P_veh_inertia | [kW] | Power loss due to the vehicle's inertia | +| n_gbx_out_avg | [rpm] | Average angular speed at gearbox out shaft +| T_gbx_out | [Nm] | Torque at gearbox out shaft +| T_gbx_in | [Nm] | Torque at gearbox in shaft | P_busAux_ES_HVAC | [kW] | (Average) electric power demand for the HVAC system (mainly ventilation power) *(only in .vmod file if bus auxiliaries are used)* | -| P_PTO_RoadSweeping| [kW] | Power demand from the PTO in PTO mode 2. Only in engineering mode if PTO mode 2 is activated. | -| P_PTO_DuringDrive | [kW] | Power demand from the PTO cycle in PTO mode 3. Only in engineering mode if PTO mode 3 is activated. | | P_busAux_ES_other | [kW] | (Average) electric power demand for all other electric consumers (lights, radio, kitchen, ...) *(only in .vmod file if bus auxiliaries are used)* | | P_busAux_ES_consumer_sum | [kW] | (Average) total electric power demand of all electric consumers *(only in .vmod file if bus auxiliaries are used)* | | P_busAux_ES_mech | [kW] | (Average) mechanical power demand of all electric consumers (considering alternator efficiency and pulley efficiency) *(only in .vmod file if bus auxiliaries are used)* | @@ -76,13 +108,22 @@ $P_{avg} = \frac{1}{simulation interval} \int{P(t) dt}$. | P_busAux_PS_gen | [kW] | Mechanical power demand for the air compressor to produce Nl_busAux_gen air. *(only in .vmod file if bus auxiliaries are used)* | | P_busAux_PS_gen_max | [kW] | Mechanical power demand for the air compressor to produce the maximum air volume. (Used for correcting the total fuel consumption in case of smart pneumatic system) *(only in .vmod file if bus auxiliaries are used)* | | P_busAux_PS_gen_drag | [kW] | Mechanical power demand for the air compressor if no air is produced (compressor is in drag only, used for correcting the total fuel consumption in case of smart pneumatic system) *(only in .vmod file if bus auxiliaries are used)* | +| P_DC/DC_In | [kW] | Electrical power at the input (REESS side) of the DC/DC converter. *(only applicable in case the electric auxiliaries are connected to the high-voltage REESS, output is delayed by one simulation step)* | +| P_DC/DC_Out | [kW] | Electrical power at the output (REESS side) of the DC/DC converter. *(only applicable in case the electric auxiliaries are connected to the high-voltage REESS, output is delayed by one simulation step)* | +| P_DC/DC_missing | [kW] | Electrical power the DC/DC converter could not provide to the low-voltage auxiliaries becuase the REESS was already at its minimum SoC. This column is used in post-processing. | | P_aux_<XXX> | [kW] | Mechanical power demand for every individual auxiliary. Only if the run has auxiliaries. In case of fully electrical auxiliaries for trucks the electrical power demand is converted to mechanical power using the alternator efficiency. For Buses with fully electrical auxiliaries the consumer is connected to the electrical system and thus the according column reports 0 power demand. | +| T_max_propulsion | [Nm] | Maximum allowed propulsion torque at gearbox input shaft | | P_WHR_el | [kW] | Power generated by an electric WHR system, interpolated from WHR map. | | P_WHR_el_corr | [kW] | Power generated by an electric WHR system after applying | -| P_aux_ESS_mech | [kW] | Power demand of the auxiliaries considered during engine off periods, multiplied by the engine start/stop utility factor. The final fuel consumption (.vsum) is correctedd for this power demand in a [post-processing step](#engine-fuel-consumption-correction). This power demand has no influence on FC-Map. | +| P_WHR_mech | [kW] | Power generated by an mechanical WHR system, interpolated from WHR map. | +| P_WHR_mech_corr | [kW] | Power generated by an mechanical WHR system after applying | +| P_aux_ESS_mech_ICE_off | [kW] | Power demand of the auxiliaries 'missing' if the ICE is off.T he final fuel consumption (.vsum) is correctedd for this power demand in a [post-processing step](#engine-fuel-consumption-correction). This power demand has no influence on FC-Map. | +| P_aux_ESS_mech_ICE_on | [kW] | Power demand of the auxiliaries 'missing' in case the ICE would be on during actual ICE off periods. The final fuel consumption (.vsum) is correctedd for this power demand in a [post-processing step](#engine-fuel-consumption-correction). This power demand has no influence on FC-Map. | | P_ice_start | [kW] | Power demand for starting the engine after an engine-off period multiplied by the engine start/stop utility factor. P_ice_start = [E_ice_start](#advanced-driver-assistant-systems-eco-roll-engine-stopstart) / dt. The final fuel consumption (.vmod) is corrected for this power demand in a [post-processing step](#engine-fuel-consumption-correction). This power demand has no influence on FC-Map. | | P_PTO_consum | [kW] | Power demand from the PTO consumer. Only if the vehicle has a PTO consumer. | | P_PTO_transmission | [kW] | Power demand from the PTO transmission. Only if the vehicle has a PTO consumer. | +| P_PTO_RoadSweeping | [kW] | Power demand from the PTO in PTO mode 2. Only in engineering mode if PTO mode 2 is activated. | +| P_PTO_DuringDrive | [kW] | Power demand from the PTO cycle in PTO mode 3. Only in engineering mode if PTO mode 3 is activated. | | TCnu | [-] | Torque converter operating point: speed ratio | | TCmu | [-] | Torque converter operating point: torque ratio | | T_TC_out | [Nm] | Torque converter operating point: output torque | @@ -92,43 +133,11 @@ $P_{avg} = \frac{1}{simulation interval} \int{P(t) dt}$. | FC-Map<\_FuelName> | [g/h] | Fuel consumption interpolated from FC map. | | FC-NCVc<\_FuelName> | [g/h] | Fuel consumption corrected for different NCV values in VECTO and VECTO Engine (FC-NCVc = FC-Map * LowerHeatingValueVectoEngine(fuel) / LowerHeatingValueVecto(fuel) ) | | FC-WHTCc<\_FuelName> | [g/h] | Fuel consumption after [WHTC Correction](#engine-fuel-consumption-calculation) (FC-WHTCc = FC-NCVc * WHTCCorrectionFactor(cycle, fuel) ) | -| FC-AAUX<\_FuelName> | [g/h] | Fuel consumption computed by the AAUX module considering smart auxiliaries. (FC-AAUX = FC-WHTCc if the AAUX model is not used, otherwise the fuel consumption as calculated by the AAUX model) | -| FC-ESS<\_FuelName> | [g/h] | Fuel consumption considering engine stop/start not always activated. (FC-ESS = FC-AAUX if the engie is on, FC-ESS = FC(P_aux) * (1 - engine stop/start utility factor) if the combustion engine is off - see [Engine Stop/Start](#advanced-driver-assistant-systems-eco-roll-engine-stopstart) | | FC-Final_mod<\_FuelName> | [g/h] | Instantaneous final fuel consumption value after all applicable corrections. (FC-Final_mod = FC-ESS) | | EcoRollConditionsMet | | 0 if the conditions for switching to eco-roll are _not_ met, 1 if the conditions for eco-roll are met - eco roll is activated after the activation delay (2s in declaration mode) | | PCCSegment | | 1 if a PCC segment was identified in the pre-processing (gradient below threshold where vehicle accelerates on its own without engine power) , 0 otherwise | | PCCState | | 0: not inside PCC segment, 1: inside PCC segment, 2: PCC use-case 1 active, 3: PCC use-case 2 active | | ICE On | | 0 if the combustion engine is switched off (either during stand-still or eco-roll), 1 otherwise | -| i_\<POS}-em | [-] | Ratio between drivetrain and electric motor shaft -| n_\<POS>-em_avg | [rpm] | Angular speed of the electric motor at position *POS* | -| T_\<POS>-em | [Nm] | Torque at the shaft of electric motor at position *POS*. Positive values mean that the electric motor acts as generator, negative torque values mean that the electric motor propels the vehicle | -| T_\<POS>-em_map | [Nm] | Torque internal torque of the electric motor at posision *POS*. Takes into account the electric motor's intertia. Positive values mean that the electric motor acts as generator, negative torque values mean that the electric motor propels the vehicle | -| T_\<POS>-em_drive_max | [Nm] | Maximum torque the electric machine can apply to propel the vehicle. This already considers the maximum current the battery can provide | -| T_\<POS>-em_gen_max | [Nm] | Maximum torque the electric machine can apply to generate electric power. This already considers the maximum charge current the battery can handle. | -| P_\<POS>-em_drive_max | [kW] | Maximum power the electric motor can provide to drive the vehicle. This already considers the maximum electric power the battery can provide. | -| P_\<POS>-em_gen_max | [kW] | Maximum power the electric machine can generate. This already considers the maximum charge power the battery can handle. | -| P_\<POS>-em_mech | [kW] | Power at the shaft of the electric motor at position *POS* | -| P_\<POS>-em_mech_map | [kW] | Mechanical powerthe electric motor at position *POS* applies for driving or recuperation, including the electric motor's inertia | -| P_\<POS>-em_el | [kW] | Electric power generated or consumed by the elctric machine | -| P_\<POS>-em_loss | [kW] | Losses in the electric machine due to converting electric power to mechanical power | -| P_\<POS>-em_inertia_loss | [kW] | Inertia loses of the electric machine | -| P_\<POS>\_in | [kW] | Power at the electric machine's input shaft (drivetrain) | -| P_\<POS>\_out | [kW] | Power at the electric machine's output shaft (drivetrain) | -| P_\<POS>\_mech | [kW] | Mechanical power the electric machine applies to the drivetrain. Positive values mean that electric energy is generated while negative values mean that the electric machine drives the vehicle. | -| P_\<POS>\_loss | [kW] | The total sum of losses of the electric motor at position *POS*. Calcualted as the difference of mecanical power applied at the drivetrain and the electrical power drawn from the REESS. | -| P_\<POS>\_transm_loss | [kW] | Losses of the transmission stage inside the electric motor component | -| EM_OVL-\<POS>-em | [%] | Used capacity of the thermal overload buffer of the thermal derating model | -| EM_\<POS>_off | [-] | Indicates if the electric motor at position *POS* is energized or not. | -| P_bat_T | [kW] | Electric power provided at the battery's connector | -| P_bat_int | [kW] | Internal battery power | -| P_bat_loss | [kW] | Losses of the battery due to its internal resistance. | -| Battery SOC | [%] | The battery's current state of charge | -| E_bat | [kWh] | The amount of energy currently stored in the battery | -| P_bat charge max | [kW] | Maximum power the battery can be charged with | -| P_bat discharge max | [kW] | Maximum power the battery can provide | -| U_bat_T | [V] | Voltage at the battery's connector | -| U_0_bat | [V] | Battery's internal voltage | -| I_bat | [A] | Current charging/discharging the battery. | **Note:** The fuel name is only added to the fuel-consumption signals in case of dual-fuel engines. diff --git a/Documentation/User Manual/5-input-and-output-files/VSUM.md b/Documentation/User Manual/5-input-and-output-files/VSUM.md index 46ecb11d8827860eab5aaf6ce2bd80e7cfe8ce29..cf7499f1eb86d5361eeb82f74b1995b8bd6f3f9c 100644 --- a/Documentation/User Manual/5-input-and-output-files/VSUM.md +++ b/Documentation/User Manual/5-input-and-output-files/VSUM.md @@ -21,15 +21,27 @@ The .vsum file includes total / average results for each calculation run in one | FC-Map<\_FuelName> | [g/h], [g/km] | Average fuel consumption before all corrections, interpolated from [Fuel Map](#engine-fuel-consumption-calculation), based on torque and engine speed. | | FC-NCVc<\_FuelName> | [g/h], [g/km] | Average fuel consumption after correcting for the [net calorific value](#engine-correction-factors) (Based on FC-Map from .vmod) | | FC-WHTCc<\_FuelName> | [g/h], [g/km] | Average fuel consumption after [WHTC Correction](#engine-fuel-consumption-calculation) (Based on FC-NCVc from .vmod) | -| FC-ESS<\_FuelName> | [g/h], [g/km] | Average fuel consumption including fuel consumption during engine-off periods (Based on FC-ESS from .vmod) | -| FC-ESS_Corr<\_FuelName> | [g/h], [g/km] | Average fuel consumption including fuel consumption during engine-off periods corrected for energy demand during engine-off periods not accounted (FC-ESS_Corr = FC-WHR_Corr + (E_aux_ess_mech + E_ice_start) * k_vehline) | -| FC-BusAux_PS_Corr<\_FuelName> | [g/h], [g/km] | Average fuel consumption corrected for the excessive/missing energy for the smart pneumatic system | +| FC-ESS<\_FuelName> | [g/h], [g/km] | Average fuel consumption considering the ICE is not always off during ICE-off periods in the simulation. Considers all auxiliary demands during Off-phases taking into account the ESS utility factors | +| FC-ESS_Corr<\_FuelName> | [g/h], [g/km] | Average fuel consumption including fuel consumption during engine-off periods corrected for energy demand during engine-off periods not accounted (FC-ESS_Corr = FC_WHTCc + FC_ESS) | +| FC-BusAux_PS_Corr<\_FuelName> | [g/h], [g/km] | Average fuel consumption corrected for the excessive/missing energy for the smart pneumatic system, also corrected for the air demand according to the correct driving time. | | FC-BusAux_ES_Corr<\_FuelName> | [g/h], [g/km] | Average fuel consumption corrected for the excessive/missing energy for the smart electric system | | FC-WHR_Corr<\_FuelName> | [g/h], [g/km] | Average fuel consumption including fuel consumption deduction due to electric power generated by an electric WHR system (FC-WHR_Corr = FC-ESS - E_WHR_el / eta_alternator * k_vehline) | +| FC-SoC<\_FuelName> | [g/h], [g/km] | Average fuel consumption to correct the REESS SoC so that the SoC at the end of the cycle mathces the SoC at the beginning | +| FC-SoC_Corr<\_FuelName> | [g/h], [g/km] | Average fuel consumption including the correction for the REESS SoC | | FC-BusAux\_AuxHeater<\_FuelName> | [g/h], [g/km] | Average fuel consumption of the additionalheater. In case of dual-fuel vehicles the aux heater is fueled with the primary fuel | | FC-BusAux\_AuxHeater\_Corr<\_FuelName> | [g/h], [g/km] | Average fuel consumptioncorrected for the aux heater fuel demand | | FC-Final<\_FuelName> | [g/h], [g/km], [l/100km], [l/100tkm], [l/100m^3km] | Final average fuel consumption after ALL corrections (FC-Final = FC-ESS_Corr). Fuel consumption for calculation of CO~2~ value. If Loading = 0[kg] the column [l/100tkm] is left empty. | +| k_vehline | [g/kWh] | Slope of the regression line derived from all operating points P_wheel vs. FC_final_mod where P_wheel > 0 and FC_final_mod > 0 | +| k_engline | [g/kWh] | Slope of the regression line used for the [fuel consumption correction](#engine-fuel-consumption-correction) | | CO2 | [g/km], [g/tkm], [g/m^3km] | Average CO~2~ emissions (based on FC-Final value). Output for [l/100tkm] is empty when Loading = 0[kg]. | +| REESS Start SoC | [%] | State of charge of the REESS at the beginning of the simulation run | +| REESS End SoC | [%] | State of charge pf the REESS at the end of the simulation run | +| ΔE_REESS | [kWh] | Delta energy stored in the REESS between start and end of the simulation run. Calculated from P_REESS_int. | +| E_REESS_loss | [kWh] | Total losses in the REESS due to its internal resistance | +| E_REESS_T_chg | [kWh] | Total energy charged into the REESS at the terminal (includes losses at internal resistance) | +| E_REESS_T_dischg | [kWh] | Total energy discharged from the REESS at the terminal (includes losses at the internal resistance) | +| E_REESS_int_chg | [kWh] | Total energy charged into the REES (excluding losses) | +| E_REESS_int_dischg | [kWh] | Total energy discharged from the REESS (excluding losses) | | P_wheel_in_pos | [kW] | Average positive power at the wheels | | P_wheel_in | [kW] | Average power at the wheels | | P_fcmap_pos | [kW] | Average positive power at engine (all non-negative values averaged over the whole cycle duration) | @@ -39,6 +51,7 @@ The .vsum file includes total / average results for each calculation run in one | E_powertrain_inertia | [kWh] | Total work of engine, torqueconverter, and gearbox inertia | | E_aux_xxx | [kWh] | Energy demand of auxiliary with ID xxx applied as torque demand to the engine (i.e. mechanical energy demand). See also [Aux Dialog](#auxiliary-dialog) and [Driving Cycle](#driving-cycles-.vdri). In Declaration Mode the following auxiliaries always exists: E_aux_FAN (Fan), E_aux_PS (Pneumatic System), E_aux_STP (Steering Pump), E_aux_ES (Electrical System), E_aux_AC (Air Condition). In case of fully electrical auxiliaries for trucks the electrical power demand is converted to mechanical power using the alternator efficiency. For Buses with fully electrical auxiliaries the consumer is connected to the electrical system and thus the according column reports 0 power demand. | | E_aux_sum | [kWh] | Total energy demand of all auxiliaries. This is the sum for all E_aux_xxx columns and the bus auxiliaires. | +| E_aux_el(HV) | [kWh] | Total energy demand of the electric auxiliaries connected directly to the REESS. | | E_clutch_loss | [kWh] | Total energy loss in the clutch | | E_tc_loss | [kWh] | Total torque converter energy loss | | E_gbx_loss | [kWh] | Total transmission energy losses at gearbox (includes loss-map, inertia, and gear-shifts). E_shift_loss is already included here. | @@ -51,6 +64,20 @@ The .vsum file includes total / average results for each calculation run in one | E_air | [kWh] | Total work of air resistance | | E_roll | [kWh] | Total work of rolling resistance | | E_grad | [kWh] | Total work of gradient resistance | +| n_EM_\<POS>-em_avg | [rpm] | Average angular speed of the electric machine | +| E_EM_\<POS>-em_drive | [kWh] | Mechanical energy at the electric motor shaft applied by the electric machine at position *POS* to drive the vehicle | +| E_EM_\<POS>-em_gen | [kWh] | Mechanical energy at the electric motor shaft recuperated by the electric machine at position *POS* | +| η_EM_\<POS>-em_drive | [-] | Average efficiency of the electric machine when the electric machine drives the vehicle. Based on the mechanical energy at the electric motor shaft and the electric energy. | +| η_EM_\<POS>-em_gen | [-] | Average efficiency of the electric machine when the electric machine generates electric energy. Based on the mechanical energy at the electric motor shaft and the electric energy. | +| E_EM_\<POS>_drive | [kWh] | Mechanical energy applied at the drivetrain by the electric machine at position *POS* to drive the vehicle | +| E_EM_\<POS>_gen | [kWh] | Mechanical energy at the drivetrain recuperated by the electric machine at position *POS* | +| η_EM_\<POS>_drive | [-] | Average efficiency at the drivetrain of the electric machine when the electric machine drives the vehicle. Based on the mechanical energy at the drivetrain and the electric power. | +| η_EM_\<POS>_gen | [-] | Average efficiency at the drivetrain of the electric machine when the electric machine generates electric energy. Based on the mechanical energy at the drivetrain and the electric power | +| E_EM_\<POS>\_off_loss | [kWh] | Total losses added by the electric machine when the electric machine is not energized (i.e., the electric machine's drag losses) | +| E_EM_\<POS>\_transm_loss | [kWh] | Losses of the transmission stage in the electric motor component. | +| E_EM_\<POS>-em_loss | [kWh] | Total losses of the electric motor component. Calculated from P_<POS>-em_loss | +| E_EM_\<POS>\_loss | [kWh] | Losses of the electric machine. Calculated from P_<POS>_loss | +| EM \<POS> off time share | [%] | Time share the electric motor is not energized during the cycle. | BusAux PS air consumed | [Nl] | Total air consumed by the pneumatic system. | | BusAux PS air generated | [Nl] | Total air generated by the pneumatic compressor. Difference to "BusAux PS air consumed" is corrected in the [post-processing](#engine-fuel-consumption-correction) | | E_PS_compressorOff | [kWh] | Total energy demand for the pneumatic compressor if no air would be generated (compressor always in drag) | @@ -63,17 +90,17 @@ The .vsum file includes total / average results for each calculation run in one | E_BusAux_HVAC_mech | [kWh] | Mechancial energy demand of the HVAC system | | E_BusAux_HVAC_el | [kWh] | Electrical energy demand of the HVAC system | | E_BusAux_AuxhHeater | [kWh] | Energy demand of an additional aux heater. | +| E_WHR_el | [kWh] | Energy from the electric WHR system | +| E_WHR_mech | [kWh] | Energy from the mechanical WHR system | +| E_ice_start | [kWh] | Total work for starting the combustion engine, not considered in FC-Map and FC-AAUX. Considered in FC-ESS_Corr via [fuel consumption correction](#engine-fuel-consumption-correction) (Based on P_ice_start in .vmod) | +| ice_starts | [-] | Number of times the combustion engine is started | | E_PTO_CONSUM | [kWh] | Total energy demand of the pto consumer (if a pto consumer was used). | | E_PTO_TRANSM | [kWh] | Total energy demand of the pto transmission (if a pto transmission was used). | | E_WHR_el | [kWh] | Total electric energy generated by an electrical WHR system | | E_WHR_mech | [kWh] | Total electric energy generated by an electrical WHR system | -| E_aux_PTO_RoadSweeping| [kWh] | Total energy demand of the pto acitvation in mode 2 (engineering mode only). | -| E_aux_PTO_DuringDrive | [kWh] | Total energy demand of the pto activation in mode 3 (engineering mode only. | +| E_aux_PTO_RoadSweeping | [kWh] | Total energy demand of the pto acitvation in mode 2 (engineering mode only). | +| E_aux_PTO_DuringDrive | [kWh] | Total energy demand of the pto activation in mode 3 (engineering mode only. | | E_aux_ess_mech | [kWh] | Total work of auxiliaries during engine stop and thus not considered in FC-Map and FC-AAUX. Considered in FC-ESS_Corr via [fuel consumption correction](#engine-fuel-consumption-correction) (Based on P_aux_ESS_mech in .vmod) | -| E_ice_start | [kWh] | Total work for starting the combustion engine, not considered in FC-Map and FC-AAUX. Considered in FC-ESS_Corr via [fuel consumption correction](#engine-fuel-consumption-correction) (Based on P_ice_start in .vmod) | -| ice_starts | [-] | Number of times the combustion engine is started | -| k_vehline | [g/kWh] | Slope of the regression line derived from all operating points P_wheel vs. FC_final_mod where P_wheel > 0 and FC_final_mod > 0 | -| k_engline | [g/kWh] | Slope of the regression line used for the [fuel consumption correction](#engine-fuel-consumption-correction) | | a | [m/s^2^] | Average acceleration | | a_pos | [m/s^2^] | Average acceleration in acceleration phases (a~3s~ \> 0.125 \[m/s^2^\], a~3s~ = 3-seconds-averaged acceleration) | | a_neg | [m/s^2^] | Average deceleration in deceleration phases (a~3s~ \< 0.125 \[m/s^2^\], a~3s~ = 3-seconds-averaged acceleration) | @@ -81,28 +108,6 @@ The .vsum file includes total / average results for each calculation run in one | DecelerationTimeShare | [%] | Time share of deceleration phases (a~3s~ \< 0.125 \[m/s^2^\], a~3s~ = 3-seconds-averaged acceleration) | | CruiseTimeShare | [%] | Time share of cruise phases (-0.125 ≤ a~3s~ ≤ 0.125 \[m/s^2^\]) | | StopTimeShare | [%] | Time share of stop phases (v \< 0.1 \[m/s\]) | -| E_EM_\<POS>_drive | [kWh] | Mechanical energy applied at the drivetrain by the electric machine at position *POS* to drive the vehicle | -| E_EM_\<POS>_gen | [kWh] | Mechanical energy at the drivetrain recuperated by the electric machine at position *POS* | -| η_EM_\<POS>_drive | [-] | Average efficiency at the drivetrain of the electric machine when the electric machine drives the vehicle. Based on the mechanical energy at the drivetrain and the electric power. | -| η_EM_\<POS>_gen | [-] | Average efficiency at the drivetrain of the electric machine when the electric machine generates electric energy. Based on the mechanical energy at the drivetrain and the electric power | -| E_EM_\<POS>-em_drive | [kWh] | Mechanical energy at the electric motor shaft applied by the electric machine at position *POS* to drive the vehicle | -| E_EM_\<POS>-em_gen | [kWh] | Mechanical energy at the electric motor shaft recuperated by the electric machine at position *POS* | -| η_EM_\<POS>-em_drive | [-] | Average efficiency of the electric machine when the electric machine drives the vehicle. Based on the mechanical energy at the electric motor shaft and the electric energy. | -| η_EM_\<POS>-em_gen | [-] | Average efficiency of the electric machine when the electric machine generates electric energy. Based on the mechanical energy at the electric motor shaft and the electric energy. | -| n_EM_\<POS>_avg | [rpm] | Average angular speed of the electric machine | -| E_EM_\<POS>\_off_loss | [kWh] | Total losses added by the electric machine when the electric machine is not energized (i.e., the electric machine's drag losses) | -| E_EM_\<POS>\_transm_loss | [kWh] | Losses of the transmission stage in the electric motor component. | -| E_EM_\<POS>-em_loss | [kWh] | Total losses of the electric motor component. Calculated from P_<POS>-em_loss | -| E_EM_\<POS>\_loss | [kWh] | Losses of the electric machine. Calculated from P_<POS>_loss | -| EM \<POS> off time share | [%] | Time share the electric motor is not energized during the cycle. -| Battery Start SoC | [%] | Battery state of charge at the beginning of the simulation run | -| Battery End SoC | [%] | Battery state of charge at the end of the simulation run | -| Battery Delta SoC | [kWh] | Difference of the energy stored in the battery between the beginning and end of the simulation run | -| E_Batt_loss | [kWh] | Total losses in the battery due to its internal resistance | -| E_Batt_T_chg | [kWh] | | -| E_Batt_T_dischg | [kWh] | | -| E_Batt_int_chg | [kWh] | | -| E_Batt_int_dischg | [kWh] | | **Note:** The fuel name is only added to the fuel consumption signals for vehicles with dual-fuel engines. In case single-fuel and dual-fuel vehicles are simulated in one simulation run, the fuel consumption for single-fuel vehicles is reported without the fuel name suffix while the fuel consumption of dual fuel vehicles contains the fuel name suffix! diff --git a/Documentation/User Manual/convert.bat b/Documentation/User Manual/convert.bat index 48632dc34037ee0e72aa5e19e98649ca3ae64360..0572237864cdfc9d5a8217ba9f0df6203c850eab 100644 --- a/Documentation/User Manual/convert.bat +++ b/Documentation/User Manual/convert.bat @@ -20,6 +20,8 @@ REM pandoc %LIST% -s -S --toc --toc-depth=2 --self-contained --email-obfuscation echo Generated outputfile: help.html +pause + REM pandoc -s -S --toc --toc-depth=2 -N %LIST% -o help.docx REM pandoc -s -S --toc --toc-depth=2 -N %LIST% -o help.pdf REM pandoc -s -S --toc --toc-depth=2 -N %LIST% -o help.latex diff --git a/Documentation/User Manual/help.html b/Documentation/User Manual/help.html index 92bfe348b0279461dcd991adeff47fd50022b5cf..f1e50b9e7b68c7b745ee66b6f19b1fea9f059f0c 100644 --- a/Documentation/User Manual/help.html +++ b/Documentation/User Manual/help.html @@ -1866,21 +1866,16 @@ Example: “Gears\Gear1.vtlm†points to the “Gears†subdirectory of the Ge <p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQsAAAAWBAMAAAAlRKSQAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAid3vmau7RHYyVGYizRAHtTi9AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAD+ElEQVRIDb1WXWgcVRT+dmfnf5zsqkVpqQR8snkwhWApSpj4aEXWSomhKuNL2oqUoQhCFJlAH1pSya3VWorgFFpYDchECCZdxEWjFhWyPvvQa0AbLMF9UDRaUs+d2ZndZGd3+2LPw5xzvvPdc+/99s6dBe6Szd1/lybqOY3ly8WehP+96IgZ9LrpCt/d7h0p7RjpXu6o5B4eKz3ndMDdAKupQq6PGooLvNatSRY+CahOViETy9VieJVnllNwwAe0NLuD4G/i0Jg7NKXJm+jD/5ABRh9Oe1nfoCxoR3rGF+Kqxmo9aZiF2Zuwrao1EG6DeqVPx8XX+wk4ia97temoKa5V7gC7Ay7MmZsLH9y+3eeIPlb6sXuTpFI4JCzqJL28u0/HZJDwaohvz4WG245lxdYG3gesJ0PYuxav4Zeh6qGYxhN2GsTACtM9YHkI+Ll6xrcPVhfKCTP1xkitcCzKZI7gU/S7NACzAUYn7iRwheMn5Bzk4m6vJk3TIAa+gE5HWnNgvIR7QtAlnSHOJgwe0WV6jqH/FSrXSYsAr0AfBM5ACWw1Go/h2KEVxMCL5L4jHt6hF71GA7mXMFOvDibn/mPC9kESFPUJ8JQRB61cKgIF4BbyAUiXAf6QYFwN3yVlKqG28zMKiNE6G3spdTBQwx66o4HNHCdges4j9toDl7+/ZJ+sFklTE2sH5oEybbKBFaKI/WwTti1foYWWYA3j94h6brFOXi8uaT6OacVgf4WCdrP+Auhi/gp2Q8D642/T05Au+sQONzQ3b0p8grQyEI7KzKZlmHV8HlHL24Vt5bnrY6WDmzDLOEFUjgUENWr+J1OYPljwfnChMNEjtd1/lHY8KngkPGwaaFi04W/oNy14uit7qziPI6TVm9BdxTM9+uVCPBsp65OwWoVPz701PfWMQER+ySMlk+6yT/sTx+pwfFGfHZZgOnlu+pASzhb/vBAQn0AOIb4EixFb8/P8MsWjpKwP05e4Eg/aJ5RVGAk7rk5JF2cG2E6BiBx7SMmkdZ5B8cSbux+6b+E9lNdNo/jlb7KH9cxL9hHgCOjNlRguoEbdIjZbxXg4bhYlrjLI3jyWowmshtBKImGtfyqkHAk2IRChOG5R3jR71gcerDKs/Vu9jyv+zTdY4SM8dcWn3VDQaWv0fcvNLMGerc6P4ihcxOyzOMWGKtAPLAH5qz5OR0PNulD2PAlrOEI5nMKwQITiap3ybAuy4a7oli+jPdjkrZJ3o1jzhVbzwbqpl8HGgQn1hSlCSHFHEXmm2emRySx3gjfaIdVpZuJPTK0ZC62WAxJ215xYmmsfFojITzeXmhBbfsvmWnD3KGgv/Xo8zuxJ3g73jP8DE+AO4VahWtcAAAAASUVORK5CYII=" alt="E_{ICE,start} = E_{ICE,rampUp} / \eta_{alternator}^2" title="E_{ICE,start} = E_{ICE,rampUp} / \eta_{alternator}^2" /></p> <p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEkAAAATBAMAAAAuSD1+AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAid3vmau7RHYyVGYizRAHtTi9AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABS0lEQVQoFY2SPUjDQBiGn/7FpAkxUQRRkO4uHYrQrTo6FcHJpZOgOARxc7nBUeiJiqNZCu3WRax2EUVwEKyzg1kEUYouDqKIF2KVIhK/4e69e5/vhfsBhgruSIG40iqwFgcxKECPpfYlZGOpKmYsA4uc/4Oacq/jKeuVPbBmmtjjrQvuJtvzUVPQ6w2F+YzEZwNqATckSiQie6VHhSLTUUk+yxg52ETz7YHIzveoUKQcSMM7SR+VOhhMhO5xc0fl1pv62KEScOWBi5XnKXTZbnXUaDhHumBJd/xiXQkSt9Pu3AdmmVXlBhzgnyjqRWrSyKW9ywqaVEZUGcGZeoKABRBqayufwiwlA1OQ+kLUlJRoXnglRQxhsUu5a2ad04eMR/f7aeyqChhtS+7f2sOBJh7XZbrBbE1o6miNn7A+5fet/ljY6tjx9esffQLEmU7JXuGxPAAAAABJRU5ErkJggg==" alt="E_{ICE,start}" title="E_{ICE,start}" /> is the amount of energy the combustion engine needs to provide to compensate the start up is the ramp-up energy multiplied by the efficiency of the alternator. <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAASBAMAAAAd9BUsAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAELt2Mu9Eic1mIqtU3Zk3oSI+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABJklEQVQoFYWNPUjDUBRGz0uT/qTRFgRdHARFEBwCHWpF8IGIi2Ic3ToIri4OgoijY8CilIKEgqtUKm5CnKTgYMFFcHASBwfFzcmbUIdAId/yzr33fDxQZVJiuCkCJZ1mrKYJuycHacpcmsAvXL3ARHPRVXfNVicuqP+aQNaDzBvONXmfI9iLb0YwUARyUjJCNsQLmKdcj0/WQEAg709SCngFE75zZTkVeuaHz2GNam9HYES7XKK+opK5vRA9awVdwdBVx1p3K+AsBbTIPoGi0HFsMTZvmJFv3+02AnG62B7cU/TJyMLcx+OCPqcIxHmGWcw6lmaFwOwU1bH/YPfDWwQiY+wHcrUGarl5vsW0OmvwqUcfu0whEBnJOMlxyDQ+ZJdchcmRP2mSPG7vupKbAAAAAElFTkSuQmCC" alt="t_{ICE,start}" title="t_{ICE,start}" /> is assumed to be 1 second and <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEUAAAAMBAMAAADG9G2+AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAZnYQqzIiRO9Uu92Zic3Ws5qbAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA+0lEQVQYGX2OMUvDUBRGv/dskpdYaShuoqQFx0AcXUodaqfCG01xL1TBQKdsneyaBB2FLDp3dQt0chDi2K3+g0yCW+9dLHbI2c6533AhOhfHGvVMblw7r58gOYHgjfWIYG+68080Sj7O8ba32fkCKqKj0afVf/7crPCAo8yV3u03ZBb46cyPV1zYXyI/jSA2OMOrLB0tPQytWIWdll5zYce7Cj1IFyNj2YwUHG3+ZuYUGGPAxdHGEj/kzEIUh8EYCnYBtIEu5lwURGFtyAmzssu7y9OkJ+hvPQQG1nVMpSfswmEn6KOPJ+8+aT7jK0UO5AdXXNjP2Qn6rZ4tHwI/DdYv7F0AAAAASUVORK5CYII=" alt="\eta_{alternator}" title="\eta_{alternator}" /> is 0.7.</p> </div> -<div id="utility-factor" class="section level3"> -<h3>Utility Factor</h3> -<p>Engine Stop/Start is usually not activated at every vehicle stop. This is considered in VECTO via a utility factor (e.g. 0.8). This utility factor (f) is applied for every engine stop as follows:</p> -<ul> -<li>the auxiliary demand during engine stops is multiplied by the utility factor</li> -<li>the fuel consumption FC_final during engine stop is the fuel consumption with the engine idling and all auxiliaires on multiplied by 1-f</li> -<li>the energy demand for starting the engine is multiplied by the utility factor</li> -</ul> +<div id="auxiliaries-and-utility-factor" class="section level3"> +<h3>Auxiliaries and Utility Factor</h3> +<p>During ICE-off phases the ICE is fully shut of in the simulation (.vmod data). However, in reality the ICE is not always switched off due to certain boundary conditions (e.g. power demand from an auxiliary, temperature, etc.). This is considered in the <a href="#engine-fuel-consumption-correction">post-processing</a>. Therefore, the demand for different auxiliaries is balanced in separate columns in the <a href="#modal-results-.vmod">.vmod</a> file for the two cases a) ICE is really off, and b) ICE would be on. This is done for the mechanical auxiliaries, bus-aux electric demand (all different cases like ES connected to the REESS, smart ES, conventional ES, and combinations thereof), bus-aux pneumatic system. A detailed description which auxiliary power demand is balanced in which columns can be found in <a href="BusAuxCases%20with%20ESS_Formatted.xlsx">this spreadsheet</a> for all combinations of conventional vehicles, bus auxiliaries, and hybrid vehicles.</p> <div class="declaration"> <p><strong>Auxiliary energy demand</strong></p> <p>In Declaration Mode the energy demand of all auxiliaries except the engine cooling fan and the steering pump is considered during vehicle stops.</p> </div> <div class="engineering"> <p><strong>Auxiliary energy demand</strong></p> -<p>In Engineering Mode the energy demand of all auxiliaries is assumed to be drawn also during engine-off periods and the fuel consumption is corrected in a post-processing step.</p> +<p>In Engineering Mode the energy demand of the auxiliaries can be specified for the cases: - ICE on - ICE off, vehicle standstill - ICE off, vehicle driving</p> </div> </div> </div> @@ -1971,7 +1966,7 @@ Example: “Gears\Gear1.vtlm†points to the “Gears†subdirectory of the Ge <ol style="list-style-type: decimal"> <li>In a preprocessing step the road gradient where the vehicle would accelerate on its own is computed for certain velocities. If the vehicle is equipped with eco-roll the powertrain is declutched, otherwise the engine is in full drag. The slope is calculated for every simulated cycle as this values vary with the vehicle’s payload, rolling resistance and air drag.</li> <li>All positions in the driving cycle where the slope is lower than the road gradient required that the vehicle accelerates on its own are marked as potential candidates for PCC events. At this distance the vehicle’s velocity shall be a minimum. Denoted as <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAANBAMAAAA+k6ESAAAALVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAOrOgAAAADnRSTlMARFSZImYQMrvddqvNiR1MEkMAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACFSURBVAgdY2AQMhE1Y0AG7AoVARORBRi4GOoSAlBEGBhWo/EZGA6hiTCyPGNYwLohEyEcyTqN1SFgGg/TBpiYr4qsOgPLAVbGBTARMM21gIm3AEWEV0GMg4F94YJUgxApiASLqQAHQwbDNheDBla40toCWYYDrAIHSuAivgK8Ug4si4wEAObGF0JnApkOAAAAAElFTkSuQmCC" alt="x_{v_{low}}" title="x_{v_{low}}" />.</li> -<li>For every potential PCC event, the end position is marked in the driving cycle. This is the first position in the driving cycle after <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHkAAAAZCAYAAAAVDoETAAAACXBIWXMAAAsSAAALEgHS3X78AAAEsUlEQVRoge1ae2hTZxQ/jWlqjH1mD1yLyqrCBjqd1CJYdDLt3B+1RZ3639xErNiNrYpDuzGxHQ6V2VnmVqq04NyLYhXR+Vxkw2JLfaB/iNoprbVVzDtp0iTejHOye73xPvrFGB/J/cEluV/O4zvnfOec77u5ab0G81QAyAENSQs9AOwEgNlaiJMXulR3QCpAz9uYs2s1jF5Vm+r+SBoEL56Gu8UfkDlaJqcAtCCnAPSPY6Ktqgw4hwv04wogp3ZfqvvwuUfMQfYfaYLBxrP/310BY2krZJQsSi2vvWCIqVyHPXawVW6OGrNv2PhULB766xe4nfESeFvqmHnCHhvx2KsXJ3RuanB/v47mEOw69szmEFOQvft3ADfgixoLdVnB01jDxI/ORoND1zpVx5IRnMsW7cuWOrJbfOGCSASYg8zdvQmOqh/pu2FBIRQM3Yfcxs/o3lXXQlmuIXagD9GXeGV+sv3ZBtm2boVkjHNGAovZ7dxaFfdk+JLs3PKxsMIfXd3+Mxa4UzhOoOMhzox75cXA9XdL59vfDdaP5gl0fOkfTq9YNj+OPAMlb0pkIXg5OM/AxUsx+4Ev8cjPy0J9LP6RA1OQ8WDt//2KcB+6PCCh8Wz7E0I3zsdskBxCN3toZZvWzgHn+uaogD2wuWDMpQuQWbMQ3LUHwdf2AxmPwc+3XoPXbp2DwNFucDd9I5Fs37QaRpVVRLKmZiHYV30XJVtOL8pGOj7jMGjY660rvwDj/Jk0lr3tQ6LBloP0OC8cw3kGr/ep2op8fMBQLvKjbp7fd7xdwqPmHzkwBdm6ppKFDBybP2eiGw4jZ88hCsOUafQZvNohcJgqyiBtdB6MnPUu3Yd6/gVDUSnocrOhzzwJ7owvpnHO4ZRowQA7dzREMqD2YITO/bBXyukNXO6i7xkz59Onee8JCHQeA+62l2RQZq1vpt8e9N0Q6I3vLaV5mpa8r2qtuFwjPQu/mn/kMGyQB3/dTpsrFmC2D/3dqqwsJ1v5t8w8Jh0SvuxcGGzdDd4GC7x69mfKZiXYq7+F9In5QvbFC3GA8Mp4Z3ncMhMB1SDjZsqxoV4yjqtYvILFUDtS8dnn/S2ygcMy42vrpI2cbkwhk3neA4eorPn/OUn3+rGvC3uDtMw8yjJ5W2w0b8x4BGuvRPmIofbj9ImngRH5E0BXYKIWoUaPOr1/HGHS86T45aAaZPfuLyVHJoR+xiuK2aB2pMKVjqvf23wysrEYXwzG8iJ4ed9R5gkb55ZQWcZSibJQpmlJJS2UgckLwP7VFprfo8DSR7obLKQbezuTvvI1Qs9FPiyR+klFYG7aSv1WfATCoCA93+/735pGfRuhy5KvVOKejJso5Mdey/Nj5YkbvQazpddgDrt/2hQWI3i9K4zjclf/rDeI0lVfLft739iCMOe2hTXED97H/tP7Y5IVuHBKiIfiY01X/deK6yfUcY9WnhIw+32H98CoZYk53KcilCoBCxL2L5QuS3uj6EkAH5Bga0yfXvrY0hQzOW/XIcj69DyEPQ5hLH3q3KdupIb4ofovlH7C25qLkwBCkEM9t+jJlobkQPDqw6eP+EquRXtbM7mhvf6T7ACA/wBNZfePfHHJ0wAAAABJRU5ErkJggg==" alt="x_v_{low}}" title="x_v_{low}}" /> where the slope is greater than the road gradient required that the vehicle accelerates on its own. Latest at this position the vehicle shall reach the target velocity again. Denoted as <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAAOBAMAAACBYGLnAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMARFSZImYQMrvddqvNie8Nf0xcAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA7ElEQVQYGWNgEDIRNWPACdgVKgIm4pRl4GKoTwiAS2csgDNhjNUwBpDmFkDiQJiHkET4kNhgJiPLN4YFDIuWZV1UTmC4tIaBgW2tkEnQBYZLSxmEDFUZIlmnsTpwCwgGfOdV4ChYy8DAyl+wgmECkMkWsEuWwVdFVp3BX2kBewN3QSWDIdDECoaNbBOATDaGI1CrlBkYuBbwMQQzTAMKrGKYxmQAYrJNYIPIVzOwcxdIO+qyTFNwYNjONoFbFMjUUmpQgUjzBgVwMGQHMCvtYuhiaGC/wLUcyGQMvITpTSaofTioRBziUGEFFGkAZmcwi5umSJcAAAAASUVORK5CYII=" alt="x_{end, max}" title="x_{end, max}" /></li> +<li>For every potential PCC event, the end position is marked in the driving cycle. This is the first position in the driving cycle after <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAANBAMAAAA+k6ESAAAALVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAOrOgAAAADnRSTlMARFSZImYQMrvddqvNiR1MEkMAAAAJcEhZcwAADsQAAA7EAZUrDhsAAACFSURBVAgdY2AQMhE1Y0AG7AoVARORBRi4GOoSAlBEGBhWo/EZGA6hiTCyPGNYwLohEyEcyTqN1SFgGg/TBpiYr4qsOgPLAVbGBTARMM21gIm3AEWEV0GMg4F94YJUgxApiASLqQAHQwbDNheDBla40toCWYYDrAIHSuAivgK8Ug4si4wEAObGF0JnApkOAAAAAElFTkSuQmCC" alt="x_{v_{low}}" title="x_{v_{low}}" /> where the slope is greater than the road gradient required that the vehicle accelerates on its own. Latest at this position the vehicle shall reach the target velocity again. Denoted as <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAAOBAMAAACBYGLnAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMARFSZImYQMrvddqvNie8Nf0xcAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA7ElEQVQYGWNgEDIRNWPACdgVKgIm4pRl4GKoTwiAS2csgDNhjNUwBpDmFkDiQJiHkET4kNhgJiPLN4YFDIuWZV1UTmC4tIaBgW2tkEnQBYZLSxmEDFUZIlmnsTpwCwgGfOdV4ChYy8DAyl+wgmECkMkWsEuWwVdFVp3BX2kBewN3QSWDIdDECoaNbBOATDaGI1CrlBkYuBbwMQQzTAMKrGKYxmQAYrJNYIPIVzOwcxdIO+qyTFNwYNjONoFbFMjUUmpQgUjzBgVwMGQHMCvtYuhiaGC/wLUcyGQMvITpTSaofTioRBziUGEFFGkAZmcwi5umSJcAAAAASUVORK5CYII=" alt="x_{end, max}" title="x_{end, max}" /></li> <li>For every potential PCC event, the earliest start position is marked. This is calculated as <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAK8AAAATBAMAAAAUtEBIAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMARFSZImYQMrvddqvNie8Nf0xcAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB+ElEQVQ4Ea1TPWjUYBh+cpfPpKmJUWiRQuH84+AEOY7WxeWGWxxKY20RBSGIBxVuCOhwUEoj9MexDt78eYKLy7koWIQguIeC+0127VBcXHzvyw9fk0aQ+A55nvf5eQPhDig5/ZOSB4rqyrjIKakbo5IHiuq6U+SU1C+0iw5cWpi5XeRN9L/6xvBWUVer9Z3XefPOAc1X0gv8uLGDg3w3UgxsueIzuUkiJUJI/cSWkfn4Iu/ADWn9EPHtREpJLMR+YhNefkWzQ8RycCTpGfot2seJnJJYiP3ElnG5rR3Lu8wV9Rc4Vpzn32E2HOPwHhGa9BsLn42eyZ2Ub8HwZ9+thVTD8D2l2Ehg9WmAh2zA2lr4wODYM8LaUYOIPMJ3BucrZ/0RLPTCNcv9TLVp+yKlnIFACz6Wrs/Xof32dE/br9odH7on3418NWAKPyVHi9KqL7p9vOz4WL7KKaUGAvsQvwcKbY4tsOaUyzgsWrNj8Ip5+n1S4hF+Mo5rwCTlEDL+GLUosIFRj1XCu0+mbfRYpMlPszarQ3vLu83VOVkX/CMLqbYBjVJTXYE/Km4U68541TpaN7kOEMmNumjrWMenTtPPv/ZNA1QzVxxKVVcneHj/Su5EobDpzSNgdvAimzi3n1X+bV+yzbm2OmzZ2ZrSzCr/aV/fPfPQHyiVdoxIrrOxAAAAAElFTkSuQmCC" alt="x_{start} = x_{v_{low}} - d_{preview}" title="x_{start} = x_{v_{low}} - d_{preview}" />.</li> <li>For every potential PCC event, the vehicle’s energy is calculated: <img style="vertical-align:middle" src="data:image/png;base64,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" alt="E(x_{v_{low}}) = m \cdot g \cdot h(x_{v{low}}) + \frac{m \cdot (v_{target}(x_{v_{low}}) - v_{neg})^2}{2}" title="E(x_{v_{low}}) = m \cdot g \cdot h(x_{v{low}}) + \frac{m \cdot (v_{target}(x_{v_{low}}) - v_{neg})^2}{2}" /> <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAa0AAAApBAMAAAB0Lmt+AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAid3vmau7RHYyVGYizRAHtTi9AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAE5klEQVRoBd1YT2gjVRz+krTJJDOZpOoitAdz81ZyWARZkCjoSmGXKJRuUSEncVmFWVZY7F7S05Yt4qhQoYg7haxWw8K4VFjULmFBexBpPIiioEN7qRU0h72sLqm/mc6b5GWaeVPa2DTvkPf79773+/Jm8j4CDN6oPjJ4nIiRUh7OHjtiW4KOJSBZl0uCqv5LFwUtqQUqiBy785I0AS9UqWDDElX1Wz4tbMiumBZW9VuBfRrBI2JA0mvBNf2XfV3YUqKIyygLy/6/gtt3vprevqG7GyYr2Kz5N88DicraiuXPeJG8srPTR78byluncNNIldz+tmN6WlO9Zh2D3BywmLwQ9X491Nf4EvIavsiRBlJyDrcgFamJuzqgXYdUi9fIa414TakD5WRTbsWmWqZrPeWLHG1gKItziJepifc1+jgBGTG+oxhduRRxuLNMnhnePO5Z/WHENDyJv2usmcchJ8+YGJ3HbFWrrkBa/uOMqeYonTaI2/JfszNnEVkmoluPVr5bItNMVGZMwM+UQR7NvA6lgdUE27yJDzGHuD6bii1eLWxiKqHNOU1r65ZE3pWMPorzUhYw70ulqG3+OXyV3E5eWwyxyyx1iXcL7xdvFXIJz3uvThMmzuM9nFa+RVpfUP5ZJhe/Qc7dsr62vQVMJ3NDGunB0rC2YZtWukaqt8QaeujkyImTQJH5XWZHeXXJ8eGFpu3vF28edKVeNBjUEl3BeaxgHLeRwVyq4JzENSija6O67c0hLxeiFj2T5ahVccwNWJBNhhAvAW8inPJiawLnRJ7Sh4Cn1s0lZdyYot+Pn5JFfFQ38c3uxuTp04mXZ7J3txUM6xuY+pLMax+naohbrLdMmbpAOOXF1gTOEfuoQuN1XFLtyBP60GfnUII838BYFRO61zV5JfUlTNwox8txvIs5ncwrFz8BY04w13Ug5ejgdky/TY9JuJG2HwV6jATDxZM1QR2l1bpboxR8xQYfOeu579BNAYRSXt6aQCNT2w9eCF6fSmW24Qwz2KzyX4usswRedc4uH0J5eUtsg9dzUMfuWG7+0uIXzksuVHJOfQheY5+7yPRz51mukeIDbfknRn6gXK5DefHljtegz6FJe2RpA17P4Xtr03TXPKzHzbB4QAhee/QiDin38QG1We9QXnsoSk55deg5/AL78bOlHX5G1AiP1ytecgM6DL/y8itKXnnxei7RwCWi5Ei7B8hYYfGenXzlx8kXaGVm5zBHAximk1IMT3nRFrsjzwxv5iO8npPqpFR3B11fqwiP16vzimXprXHec0d5CRSl936B13NDBfzq8qLr60LKlmlh8Hr3fq1rwIinvAIUZUt5OQR4PZcqyg9cXmkTzTWm5MR4PTqvyO9Pj7xIgs5VXgGKsqW8HAIdem5smT2mpNlGjfB4PeLlfslMfwQoypbyYmu4mR6/9uEqOTFej3m5XQcoSrfT9ubb7ajR7jElJ8ZTLW5dsDP7nBFc4Msy5dVdUbaUl28x8DZu8tED4vFgzIvU1H+ZHXb2KS8Y3NI25cXFd51KNdsRPRheB5jrRnU8s3eme7RNWe0WdShKX747lJPx1R8QzwaNmXhMsK043aEoxQsEFYeD94Zgl2OaJjU7kIMu/YEcYwPJqu3fpsHiN+P8ZzFYnIhN8vTlysCRIkKxnZ174Xj9B2SE78DX2vz0AAAAAElFTkSuQmCC" alt="E(x_{end, max}) = m \cdot g \cdot h(x_{end, max}) + \frac{m \cdot v_{target}(x_{end, max})^2}{2}" title="E(x_{end, max}) = m \cdot g \cdot h(x_{end, max}) + \frac{m \cdot v_{target}(x_{end, max})^2}{2}" /></li> </ol> @@ -2317,36 +2312,165 @@ Example: “Gears\Gear1.vtlm†points to the “Gears†subdirectory of the Ge <p>The final fuel consumption is corrected in a post-processing to reflect systems not directly modeled in VECTO (e.g. electric waste heat recovery sysmtes) or to account for systems not active all the time for different reasons (e.g., engine stop-start).</p> <div id="engine-stopstart-correction" class="section level3"> <h3>Engine Stop/Start Correction</h3> -<p>As the energy demand of auxiliaries is modeled as an average power demand over the whole simulated cycle, the energy demand of certain auxiliaries during engine-off periods needs to be compensated during engine-on periods. This is done using the <a href="##engine-line-approach">Engine-Line approach</a>. The energy demand of the auxiliaries that shall be active also during engine-off periods as well as the energy demand for starting the engine is accumulated (see <a href="#advanced-driver-assistant-systems-engine-stopstart">Engine Stop/Start</a>, <a href="#advanced-driver-assistant-systems-eco-roll">Eco-Roll with Engine Stop/Start</a>, and <a href="#advanced-driver-assistant-systems-predictive-cruise-control">PCC with Eco-Roll and Engine Stop/Start</a>) during the simulation. The final fuel consumption is corrected for this “missing†energy</p> -</div> -<div id="bus-auxiliaries-correction" class="section level3"> -<h3>Bus Auxiliaries Correction</h3> -<p><strong>Electric System</strong></p> -<p>In case smart electrics are used the electric energy generated may be different from the electric energy consumed as the smart alternator may generate more electric power in drag situations. Moreover, the state of charge of a battery may be different at the end of the simulated cycle than at the beginning and thus the fuel consumption needs to be corrected.</p> -<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\Delta E_\textrm{ES} = E_\textrm{ES,consumed} - E_\textrm{ES,generated} + (\textrm{SOC}_\textrm{start} - \textrm{SOC}_\textrm{end}) * \textrm{Capacity}_{\textrm{RESS}}" title="\Delta E_\textrm{ES} = E_\textrm{ES,consumed} - E_\textrm{ES,generated} + (\textrm{SOC}_\textrm{start} - \textrm{SOC}_\textrm{end}) * \textrm{Capacity}_{\textrm{RESS}}" /></p> -<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAR0AAAAUCAMAAACHzBk1AAAAM1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxgEwMAAAAEHRSTlMAid3vmau7RHYyVGYizRBO9rH5EwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAA7lJREFUWAnVV4uSnCAQBAV5Svz/r003gx63Gr3jNqkKVQsqQ8+DnoFV6n9o5m1GDiDpaTZaazsPrB20u6zdwif9WXfCP3ocQlqWqtP9u+joLXVuPujXuZP90eMQ0uZFZxt+ZMCXFhe/zJ3gg37Zu05++HEEKWxB9MVhtd9c6FXoyPOgP7xt04aQ/AbneqZ/09dvixf425HnQb95W2INITHts/22j+MLSIaOPA/6azokn0pKtpF8UPUQ0rxovb7tXPhkubFH+1BA6vTkudfvyOrswowxjhSOw6AhpMyyExxAgplT8hYmOJ3ShzsH/vEQJsoPNl+48CDPg35L6ajShCG16Iypv0KiJWxEvERNLDukbFSOJiijCvNsrU7ww0Uz49ER6gC/HVsP+lvKG26W3XeM6uNdml1NXiLtvhHxyinbbmY5InqME0YCpb8UHaEO+NmOrXv9sR2kM7ejdvSHfix30bmYvEYiGtufojO3DcFdkNGpV8LZ0hg2N6Woo4sLYhVTQvIHjaQzHsknEvUdc9FDOGpfO5lSF3Vnp85Bnnv9bcMzCc7Ox+aHW2lANampTdHgSxXYJ3ebaM4LkpvgB64Wa1SabjfuVMA4Y6IWj7xJIDSChNLna2pnO+9XNFJ6y8onFTBlSwHUmg3STzgn72RbMMr6EqRr4TkPOobWfCXPvf6a4wBJVMYO2pGR9IUHmJgkGmEoTRKBOtnZpKRa9EgWrFyiMhgaIlAbIAJfSFq9bvVP1rSBHOQO2YHveBbmcjX2LHmlrXPW+Uquhgk5eccuUIwapcN43bauQd2D/tQ4jM0BMFlewlSO6IhJonE3qQowOr1NcOAViemR7Et0GmBeLy6AjA6PT8cLGLMIrSlFdEw9icmx4yue5H23hBEdv5Wc9bdDiiql7NhUPqKTxSTR2AwVAdiQe5tAE8GQngXsMjoNENkh3veL5MzSxTECuFkySHt0dGVdzgHsLbl9hYC8M7OcFTPHo/OqX+X+jzHLTsKHubTakwMTIec+OocAJjubzkiVcItDnVLuc2YBEHcHyZwuOtlsqLtmUw5DQpIsrFq2+C3mZc0K5RkRZd++UmD/6pMGpxHS2nWoX3886Ve+t5Flp9gYvfkFo1DmduWiVgwVgSyTh00oAK9IyprIfM3G4fSkQ/w1bxSr6WNjGbltjwK3qx8nP6WDr5n9uOZa4Ix0HMuXC86JdRZrlew8sX95FNgFx0am9nvaGekmOj7Hu8tes+iRGY8C73Htb6CEqf6zuIROcsD9BmjFIv9wFM5gAAAAAElFTkSuQmCC" alt="E_\textrm{ES,mech,corr} = \Delta E_\textrm{ES} / \eta_\textrm{alternator} / \eta_\textrm{pulley}" title="E_\textrm{ES,mech,corr} = \Delta E_\textrm{ES} / \eta_\textrm{alternator} / \eta_\textrm{pulley}" /></p> -<p><strong>Pneumatic System</strong></p> -<p>In case of smart pneumatics the total air generated may be different from the total air consumed by all pneumatic consumers as the smart compressor generates more compressed air in drag situations. The fuel energy difference is corrected according to the following equations:</p> -<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATQAAAATCAMAAAApgQGXAAAAM1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxgEwMAAAAEHRSTlMAEM2JZna77zJEVN2rIplOS3ctogAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAypJREFUWAm9V4u2oyAMDAIKCFz+/2t3CNiiW63UVs5pSzCPcUgCJeIhhvJbv71Yie+FboP3Lj/RuBeGTKoBKZIukpqb1YNpt8GBrwuP7oUh9Dg1YNVYybK+WT2Ydhsc+Lrw6F4Ymkybatql0IW926DL+2nlW2EIVGOTasHRJE8jhWK3QY/z87r3wsgdrEk1iJHr04zIODtMQQ2HmddtcJ6IHs1bYeREa1MNokmG4eYyDajcWESK/jGaXDww6Hnpq7q3wtB8wXikmskETfFBmqgE7r5Tt8GuJ4rrq89a0cx2vbCWvgbjDIiSaERDPUC1xKgtLmeaSG9ubd0G65dtpeW+6Gpm41kzjQtpdnyM51XpAowmBiKeAVESjcjWA5SL1SQGWEhrX+vFvNvghY+6tOAdn6Q10wdpLx1cgNHEgOsTIJZEW1LNFrwzX9G2pL3qabsGRio0PqecJjsrFxUF5aQ1gyM585J01o3IY6cUMsZKp0t52kFCLpY81S4TdkjaHgyNIQVHqChKODs7qYkdL+HOg5DO1KE51cayjTLl3zPluWcgcAIPwYB8EynKvIHSkLAUHXomKACj8K8VGbjwIoCw/MnDY+eqZZ4SXGWLpTxZZ/O1AwMoELhEqCiq4LUw1TGH6wGRmoH9H9KQW5ia06hMTN5Yn/yzcWyQIj12DTSfJdhNcFOJMtMIVwtp4A47ozRJb623GiQulZHfoloyaSTMLI5I24UBj+CtRKiRq+ARHxGzYw53HcR/5PQvSL6UrEgTwoG1hjSkD0iL3I42pIUnaYG8Esek7cPzCvldItTIVeDdKI4xDT8FsQ9v88Sg1ASXJ/7CFqKkIBHRR8jmYitVir6X6yWEXJoGdZjv0dEGk8szW2KqkLST4L62CfJeLOcDR6ghSzhOr4djhPsliPcwFw0nXW7nWklhBi90clo7HbCpFid1XQoj/m0smg46NOI1Td53tuSp8M7p+Acni+/zv+MwIJE4Qg1ZhTkGKo5DCVfh/gLEebifanKv+dR4a5f3Led87/gqiN7gH+gfnZHd7tDQ8Bex24y+CqI/fK/Fl/dYaqf6GTgE8Q82zSSVKQcOTAAAAABJRU5ErkJggg==" alt="\Delta \textrm{Air} = \textrm{Air}_\textrm{consumed,total} - \textrm{Air}_\textrm{generated,total}" title="\Delta \textrm{Air} = \textrm{Air}_\textrm{consumed,total} - \textrm{Air}_\textrm{generated,total}" /></p> -<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYQAAAAUCAMAAAC6croWAAAAM1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxgEwMAAAAEHRSTlMAMrsQRO+Jq81mdlTdmSJOW9yYjAAAAAlwSFlzAAAOxAAADsQBlSsOGwAABQdJREFUWAnNWNG2oyAMBEUUUJb//9qdJIB49Vq13Z7loQULySSThFilHo7ePzz4tWMbgAur/f9AZ5C6S/0Dx4xyxs7DYq0dB7HygaA7R25p6xtI0bKaDFqp8YnJd5Be3VtAmuHqiWafN3nRdTwxjcXNtk9Pb2kLrqq3kaYVdJ9yBLq5bvnuxHhn2YUZpK3xcQPHVPYWczbJX378+Pc9bRWkkkipa9dl55sntn/AKk1QJo4MATWtAXNZfA0ynbQcCpfPvrHxpjZbQGkOkQpa+ZDYAW9Aee9oR8g8Vw8BWdx4R2xXbPAJxx6weEfZuvemthrnC8OtoGNQg1wSq+jvztjncg8wSAM3anezmtRrhIp0/FpO39VWYEo1KisFYxeuR2hKojLTEJ2Uhm8xoTkRtXREBMt2SmtdAe5xLGMdNXzqfTZ01k718f7wZ5/c1UZpimEkVStokFAKG3kjJqeWXFXlwL/+NJkETlACOVltVM/V0wqS6SWgWK64SHmF87BkSc75Ba2fsc49pmUpko/8cE2bD35xOfalE5WGtILWZF/uqckb/ZOCTPhOweq5NJB7UyQThAo1AGTq6uZZ+syXHCi+3Em2Ixppf1CaAg3G91Scput9eNio6wsJpqujXjmXtKHz6wfGpNScSQAiwCyiPV5sbCe5LyRcRnsMtnnaTJfq150tHE0qSDkCSJM0ChIP406KkmzJn33J7DEbhquOSdBJaSLBXTZLdcckbPTlxSVto1aVSbEnSJNUQfP9pxP7SEg4Unb47Bhs87SZriTsRbHyIPDwSQwgccgTXg0EjPLIzMGWu/roTihslSYDKVQyQQ1jDQGPYfvgnINEFxbEdF6QeB+A00y2PEUhC76E6x44Skiucr9oCy54lueHHAQCs/QNGbQR1md+3JDwGGwxIWuHI8kwdUZCR9ntBRhg0VvCrFFOqNOU9zY6Pfp+E6E/fJLLTZRwUhbe0UNAMUYGxHHI71SIPQSlBs2oyottFiwe6QQAiNy8hYp2Ldw/FNLyhTZKQb2QvJIJkVOc6yOdz6Bz3lu+tddy9AZYNqFqhz/ZsDMSDIGQjoxAUtkMnjgIET0DgWUSJIVpeTT4gLJT4j+OZipubYOlQSsGnAHT7GgMkmOBxKEsRhbfa2gnC2SLB5XFfwdKX2nj1E0tCUhADFcSk0GbKTEZbk6d00satRnTiI1vgGUTqHCwdnyzYWckkMvlbwslIAkoDTQ1bibYTMJZHlC085H2o5BgqO/KkkeHhmuRuiYk5AXBVqPrhYQoT1+Q0CqrlDfa9iR0fDPlyD8E3cp8DhbWxFV7zIadkrAqFpB5zV0qt3YXSFCboyyhkkCFG6+oxIVcgfBCjDkTqDZhQSQ4lPahR/mMWp5SKeKbJSM6+zrQRuUIr58Qna9giZQoLR8J24NuVTwDS2ayCaKdptWwVvpv8004m4mC2ybcBZjpWd70fzuK14IfP9F7Aj8ySCiHatPBqG6a4JNg8a8NpPY+hbwg8f1Il0jUlAa8hXKUtlwYh9oC/plEIViUHRgKXVAIhDWnd6A3mp6BJTPFBNLOUzHsDwzeyD9eCMjj314+NS+dBYfDF7U7fynxvQ17OE68X6sR5J+Bfgp2r/iOIRnknSPtXsrD02EUv4G3Tjjd/96P5fZdpWSAG5ybxbqVZk/B7hVv5Z6vTgCdH7z2K0WI9aH2JtdOPd31Xjyy1mdgP6BY/QVWMCr2HydQygAAAABJRU5ErkJggg==" alt="k_\textrm{Air} = (E_\textrm{PS,generated} - E_\textrm{PS,off}) / (\textrm{Air}_\textrm{generated,total} - 0)" title="k_\textrm{Air} = (E_\textrm{PS,generated} - E_\textrm{PS,off}) / (\textrm{Air}_\textrm{generated,total} - 0)" /></p> -<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKYAAAATBAMAAADooWuCAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAid3vmau7RHYyVGYizRAHtTi9AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACZElEQVQ4EZ1RPWgTYRh+Lmny5XL56QkNgkMzVAQXIxRdoyAiCI2K2NbBgCCCSxQ3hV6gdOhQY6qJwSHXrdrl4iBoELM4FIe2lA6C2FuERpAGQW1pqL7fd/m52FzUvnB37/PzPvfdewAODKsDw/hr5XYdLF8t3mPadG8SuGvDDi2LOQiDhhA2NUCJNjxhAr5G3+MhJbqLoSnrZS+jAGt6ihnA391vZ4OGHbV7n7wjwHS9zeEBFBtybMP06o6SLbSB67wJ6Mdt6g28syHHdgJPtQ7RbSENRf4FPpwGcnW2+v4joRPqSoe3A5y5THWBUxG5ELNLr7wBnhXS4OW8D3yHdSwZ5+jQ28gjMFKeNNmhkn3oj34lH9Ih0dwHS8il36R4lgmx0ALccZ65SQ4oNWSgZ6EkPyNoEuFQP3iCKw5yW/VW488NulbpSquRmMg0CXiW+YKzkGuPoXCie7HtCAn3aK5RufQUT5+ha8IANMg/RSaX3f1AH/g53Vc4fljCwjw7evDOnEaotU8p6UploJ2EfIREUmifZKB1AsEYGOUfbmUupQAVs88nzcClLTJFg4sJOT5a9cyQrV1Bw5XRYQwAZzFa5bz479KzQqHwZAdeIgab3y6tn1Iv7mJWTGcz8MUhaaiNw6MLqnlzmf5p+CtFnjkuSMbv4V+8vrH1T1CO3Xr0PX/tanNCZN6HYkDqF5lj8HQc0zJK5RcGZY61xno2/Jy30VepyMuhxQRLdM/8Qlv/58zAiEE/tfwaNzG3gPlSdaiSPb/nEGwN0lZ1TR6q7JF6Ef5e4j41sfh9zjqN6U7Cf/C/AUq1prEylGgQAAAAAElFTkSuQmCC" alt="E_\textrm{PS,corr} = k_\textrm{Air} * \Delta \textrm{Air}" title="E_\textrm{PS,corr} = k_\textrm{Air} * \Delta \textrm{Air}" /></p> -<p><strong>Aux Heater</strong></p> -<p>The power demand for an additional fuel-fired heater is calculated in the post-processing. The HVAC steaty state model calculates the heating demand (weighted sum of different climatic conditions) and based on the engine’s average waste heat over the cycle the power demand for the aux heater is calculated.</p> +<p>As the energy demand of auxiliaries is modeled as an average power demand over the whole simulated cycle, the demand of certain auxiliaries during engine-off periods needs to be compensated during engine-on periods. This is done using the <a href="#engine-line-approach">Engine-Line approach</a>.</p> +<p>During the simulation the combustion engine is allways off. In this phases the “missing†auxiliary demand is balanced in separate colums for the cases a) the ICE is really off, and b) the ICE would be on. This allows for an accurate correction of the fuel consumption taking into account that ESS is in reality not active in all possible cases due to e.g. auxiliary power demand, environmental conditions, etc.</p> +<p>A general goal is that the actual auxiliary demand matches the target auxiliary demand over the cycle. So in case the ICE is off, some systems still consume electric energy but no electric energy is created during ICE-off phases. Or in case of bus auxiliaries the total air demand is pre-calculated and thus leading to an average air demand over the cycle. During ICE-off phases, however, no compressed air is generated. This ‘missing’ compressed air is corrected in the post-processing.</p> +<p>A utility factor (UF) considers that the ICE is not off in all cases. Therefore the fuel consumption for compensating the missing auxiliary demand consists of two parts. The first part considers the fuel consumption required for the ‘missing’ auxiliary demand if the ICE is really off. Here the according auxiliary energy demand is multiplied by the utility factor and the engine line. The second part considers the fuel consumption in case the ICE would not be switched off. Here the ‘missing’ auxiliary energy demand is multiplied by (1 - utility factor) and the engine line and the idle fuel consumption is added for time periods the ICE would be on.</p> +<p>For the post-processing two different utility factors are considered. One for ICE-off phases during vehicle standstill and one for ICE-off phases during driving.</p> +<div id="ice-start" class="section level4"> +<h4>ICE Start</h4> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQ0AAAAaBAMAAABfmBSsAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIondmbvvMs0QZnarVESUG+88AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAD7ElEQVRIDcVWXWgcVRg9s9nsOjPZyRDf4s8uW7FKI1Of1KeEYCuG1Cw++KAPjQ9aETGjYPHJpH3wwacVQaovO0LFnxAN4h/FwlqkYC3s+qJSW7NCEJEimxCjCep4vnvnzo6gCFlhv4V7v3vmO+eeuXPnzgJ7j0L8qIo4jv/cu0r/TCeuaZHx1i/9q/WhcHQ3Idtzfh8yfVNfjs30pal+xcYmp296QNbX2rcVwfvsQDiVQv+l7cUHTcmtsG/eqs6GMh6bnAGuTn+Up2T10COm5N/6ZzbUlQAoLkmW6wKzdazPI4UE9qXRYZnE9MGWydiTX9T7lfz85/AOK8lnTUmWnRGFN49XWEMSKlJLnXwNcJUPDQm8Ko0O1ySmvyZum1QRcV4NKXmIyYfKR85UZNkZUbhNPMSaADbeklr6WAzZH+xBAtek0TFsEtPbC3pN1Zg3gLm6pAGKv7IbEsm6oyAOs+yMKIYjSHUAF6qUpMMcY6oHcVTqCqZjzSRpv/ZbmspCpuuRZ468+Fi1TUWGnRXFqF+U6gCndCVJd+oshVYu1dY3b4OzXMGPD79541y1rQvSNh9X0pw+rD/UKMDQkkpyXVsnzpXXPWG//R6858dPiGgS7tmvvFtORvRRbWmIPpLjyEDFCpo21+MsPoC1mw8bqnD2IuNcIjPZO0nd3eVPQgUHGK2pJLc5QTrjaYyAbLft1lCO7hHRJB7ERQxHHARIdhJ9PMZxBiqdQCiUCSzC5jPUPnRN0pa362bspuIBCksKpWRFJd/4RWHnmsUuGiG0j2tDwKnhCz4ZFgUo8ccgSW33Tg9qPeErivUu7J1/9OHETeFKZH2MzBPwRLLNHzCy/am+i3H6qCc+jneAQoRj+IEVnJSuJCFJvS+rPci6vGN3LVy/v6yojexhIhRGS6ZRkfWh3hdXJIFIrt7QqpNtnXuKPkAxc5iUfa7QhFSIj+8kIUnOj6Ksh4YcH0fsHQePo1yUdWnUI1752/7ASSI6sj7U+fGc8lHq8PJryLfJLkRWV3aZiOpYhFvrvGDzZjipfbuAYp7n6XgPcqawHxsOt8baq/JcRv1Is3vtSDPN1c2rESV5nlqRknzJJ3YauZDsRljaifhcKJrQCjhVie7gETe2MF093x2N4w31fZk+0+5Bu2cutXH5DZx+57r7rv4eoXQhTGdNko9TwN631eaAf0bU92X9wAosfnImFgRaXlkRtjPz/fs/ty5ARHV4R76eqX/7Zaqyx6R01x6J/zPtuCz64MN6cvAexMFQZHxUTDKQ/n4zK9+sAYYcNyrsuU6SDaRLXtoXfzq6PZD5k0k9HgxJbA7Sh3t3Gvf26+Mv6gQ13AHWc2YAAAAASUVORK5CYII=" alt="\textrm{E\_ICE\_start} = \sum{\textrm{P\_ICE\_start} \cdot dt}" title="\textrm{E\_ICE\_start} = \sum{\textrm{P\_ICE\_start} \cdot dt}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAR0AAAATBAMAAABfOcSMAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIondmbt2ZlSrEEQy781kO9zxAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADzElEQVRIDc1WUWsUVxT+ZnayszszSYZIm0ofsmyrGLCMPvnWhIUQpYr7B0oX0ZqHSqdFzaKigwirKBpjQZpWMmBp37JbmpdQaKdK6YNtTB+K9KWuvvWhZQ1a26DYc+7ce3dUbN+MZ8m953znu998e3fmTjAwUnn9nRrcj9YnowCM1+6GacGNt6sE/U9o3sDIOLBQec8ijfLYL/+97PuVZ/V3AvYotsWYX2KK2YEsAsBrq1W+SshyNxWZ5lFizcDdITQWFStL76q44mKKk51JBSWrCuQFhfzIQjQUs6YS4nVTkWkeJWOE7BN+TMXK0msKhDml0ycSlguvJzRu4g75kUUAB4cY4iC/KnpUImfNC+A9ICzHGrEdy3aW3lXpC2X7qSlAAf4Ohkd5IC1ZBLQTMUMUhU4683ium4pM8wJYS4RYrFFzFCtDz6j0J6r/5ByAtvZNjZKWLALMpWi9UZ1f3gD7YAnf/Hz01Z3lSLM50bwAubbomB0nTeyTB1ymT+6C+8fgLVaR8S1+qKn88TkoXwDuaYz8yCIozwrUK2HKof2ZwB4Y962kKdBtH1NMc6p4ZKy/Knrm8nC6n1dQBNHzUb6KoXA7q8hY5/24pPLH5wAvAb9pjPzIQmwc4YVbSFhpGNfh0A2S+tELyIa8dwP0tgVMGiWRnPU9pptTXgfNBKmfNQn1bl9zIkHh4WqrL9FFABu4xGWLB9KSBd9YBYZmf/WFknEMDh0bT/uRvABF/s4ua0T0AYoPz6f0QfITSz8/8XXuiYtRwmG1vDThMeBBPFI1zkhLFtwgq3TgnFpxOgbWbhwSik34jOrQPPl85VmDnlkmvDIbE92Y/o78gFarw8h9sE6vZz+ZQvjhI8cTKGnJghun6c/2sdVZsXEDQx7vUzMOCc3cP5LH32yM8mvCT4HVPoAVEb03NDoJ+yGVNMxqrpU0Jt0tJ8L8u7s+a11tfVUfR2OSusIPH8mDgsrfLS2o4WwmzB7FRtyx6dY59wX/Xv0+++mG4rESnc9GKPxc9omxH2ZC9GZSWAnp9yIVuawvzCVnqsW44rQvO22rRZ/SnEcABkamiQi3sjdC/6NHd8T7i4uBm5XypQ5B9/c2Ipw6gv2HX35r4Z8QhYuJVBWT5i3z+2t+fR3GG3fLwzdZ7a96nen2+Je7v569CFZJIxcXJsxPFlpbsTTnbBJ+ol4GssrPObdqAPkpfphIPwysYnhVwyc/9H6TfhhYRT843vB+//zvnj8/XZxZnFqceT863lhNO/LaDeh/TV4AN6Bnt+eF8KFMmBOHVUrzvygUKX83MjyfAAAAAElFTkSuQmCC" alt="\textrm{FC\_ICE\_start} = \textrm{E\_ICE\_start} \cdot k_\textrm{engline}" title="\textrm{FC\_ICE\_start} = \textrm{E\_ICE\_start} \cdot k_\textrm{engline}" /></p> +</div> +<div id="mechanical-auxiliaries" class="section level4"> +<h4>Mechanical Auxiliaries</h4> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{E\_aux\_ESS\_mech\_ICEoff\_standstill} = \sum_{\forall \textrm{v\_act}_i = 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_off} \cdot dt}" title="\textrm{E\_aux\_ESS\_mech\_ICEoff\_standstill} = \sum_{\forall \textrm{v\_act}_i = 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_off} \cdot dt}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{E\_aux\_ESS\_mech\_ICEoff\_driving} = \sum_{\forall \textrm{v\_act}_i > 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_off} \cdot dt}" title="\textrm{E\_aux\_ESS\_mech\_ICEoff\_driving} = \sum_{\forall \textrm{v\_act}_i > 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_off} \cdot dt}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{E\_aux\_ESS\_mech\_ICEon\_standstill} = \sum_{\forall \textrm{v\_act}_i = 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_on} \cdot dt}" title="\textrm{E\_aux\_ESS\_mech\_ICEon\_standstill} = \sum_{\forall \textrm{v\_act}_i = 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_on} \cdot dt}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{E\_aux\_ESS\_mech\_ICEon\_driving} = \sum_{\forall \textrm{v\_act}_i > 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_on} \cdot dt}" title="\textrm{E\_aux\_ESS\_mech\_ICEon\_driving} = \sum_{\forall \textrm{v\_act}_i > 0}{\textrm{P\_aux\_ESS\_mech\_ICE\_on} \cdot dt}" /></p> +<p><br /><img style="vertical-align:middle" src="data:image/png;base64,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" alt=" +\begin{align*} +\textbf{\textrm{FC\_ESS}} =\, & \textrm{FC\_ICE\_start} + \\ + & \textrm{E\_aux\_ESS\_mech\_ICEoff\_standstill} \cdot k_\textrm{engline} \cdot \textrm{UF}_\textrm{standstill} + \\ + & (\textrm{E\_aux\_ESS\_mech\_ICEon\_standstill} \cdot k_\textrm{engline} + \textrm{FC}(n_\textrm{idle}, 0) \cdot \textrm{t\_ICEoff\_standstill}) \cdot (1 - \textrm{UF}_\textrm{standstill}) \\ + & \textrm{E\_aux\_ESS\_mech\_ICEoff\_driving} \cdot k_\textrm{engline} \cdot \textrm{UF}_\textrm{driving} + \\ + & (\textrm{E\_aux\_ESS\_mech\_ICEon\_driving} \cdot k_\textrm{engline} + \textrm{FC}(n_\textrm{idle}, 0) \cdot \textrm{t\_ICEoff\_driving}) \cdot (1 - \textrm{UF}_\textrm{driving}) +\end{align*} +" title=" +\begin{align*} +\textbf{\textrm{FC\_ESS}} =\, & \textrm{FC\_ICE\_start} + \\ + & \textrm{E\_aux\_ESS\_mech\_ICEoff\_standstill} \cdot k_\textrm{engline} \cdot \textrm{UF}_\textrm{standstill} + \\ + & (\textrm{E\_aux\_ESS\_mech\_ICEon\_standstill} \cdot k_\textrm{engline} + \textrm{FC}(n_\textrm{idle}, 0) \cdot \textrm{t\_ICEoff\_standstill}) \cdot (1 - \textrm{UF}_\textrm{standstill}) \\ + & \textrm{E\_aux\_ESS\_mech\_ICEoff\_driving} \cdot k_\textrm{engline} \cdot \textrm{UF}_\textrm{driving} + \\ + & (\textrm{E\_aux\_ESS\_mech\_ICEon\_driving} \cdot k_\textrm{engline} + \textrm{FC}(n_\textrm{idle}, 0) \cdot \textrm{t\_ICEoff\_driving}) \cdot (1 - \textrm{UF}_\textrm{driving}) +\end{align*} +" /><br /></p> +</div> +<div id="bus-auxiliaries-correction-electric-system" class="section level4"> +<h4>Bus Auxiliaries Correction – Electric System</h4> +<p>The bus auxiliaries electric system correction is used for conventional vehicles with ESS and buses with smart electric system in the same way.</p> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAdMAAAAaBAMAAAAeQKtWAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIondmbvvMs0QZnarVESUG+88AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEUklEQVRYCd1XbWhbVRh+btr09uY2H0zwh6C5hPqBDLL9EEHEhuqQTUqDoOAEFxUmAzHBrRNhkKi/9M8uZYzNP7ktK2I/aJnij2lZ/eNnWaMbKttag4jK/ixRuxLW7vq+5+Tkoy30jzeBvKU573PyvPc5zznn3nMDtDLStw5zpF3XLbZStw1as6tSVJt2k22Qb6Wk33WqcqfKrdRtg5aRrjm80nr5XQOD/c/zbjIe+De2r9A4gD67EVFe5f7YP9bE28RqhH+VGhFw8x+FfTZG04P9XzP2XHpEznAc0HMs6EtBu82JivycylQruEELRx3Vs0OrbbLqcxMNFXS5bJGx19KhFM6SDOnBon+YKWCYExUTe1SmWsHtsuFzVM8O7WarOLnRUPEZ0Jdi7LW0uYAXSSYOAx8rvbjNWTXmazeW6hHccASao3p2aLdYPe1G6iVktbvCkK16Ke13sEYycZgQBlnvEepQoRVeUalqBbf3BaBhvOq7bdstVoNurk5sWlUvpcMRPUWycZyR4mR1JIGRcuiQHVieoKnGk5BwYlV71WKS4Orud3Ltf5vK4NpUUT90z/UiZq4mRelIeWbow+kiApP7EXp4piSvXf8c/ruek9VogaG30ub8T6GH3nVo+LElKW5uLI87MMqI2m+ij61mMxLiWXwrOJJ7whXDDSaRMy0cQH5OT+kWFkSpcRvHHXoMxHAU0wiw1e5FDkuqdDW8J12c/Fw8geGZtNA8iEX4HUrj8NEnBW/gb4AywvYvER14Cz0JCXH6hlzHKlcfdojfU9SO5G1EES4aleA7yIhS3EGeMNnuensNWzYwNPcI1cq4qBLPpO/KAIEkvgc9YNhqkP4oWC/riPH23foSOB+7n3rYOUJvMKHK1WidcgSyZP9XkFG6TAVLr0cklwoiZH1j+fJKZRurmF2nWhlNVj2RPl6kJXHwGv5gRT5AApyw1XCCxktLde+SjTnod9gqQe05JlS5Jh3EewjcbLKqXa9ILs+NUeGdGyptZ7Wvftw0WfVMOhrRS9ithr/CSW1Vo/YYuguhDPA4W43aMHvnmCGmZaWXTCwQyNOdTN9lbV7VQARDkiutanSInC1Lq033KnotqpXRZFWs6v8tzTpZmMniB0ZBDN/Yy130yoL3gCcwmzkHX8ZPXbTiDJEw5A4mbOwNW/DTNMCXxJjPwjO8YcuBBB6UXNoGtIExiGDkC5ji2CRyPRbrKW8oEZ5K9+CM5TxKe3FXejD2VSnsuhV+B7aA3yezL03NzIROvo/AwEEBP1nTD++n35iS6xs9/zSooDQ+mcHUeEEfvnRs/caFqwXBPbb+5/ClE+uZwIWPEJhfXuVJaQwzV0OjA0Oc04U9lQ4N/XzAvvZDTbZlyWW7ZVJtFtJfbvMAWid/d7F1Wm1WekzpV99bFOy81m8pT+dU0qntPmXsFL2ddHRUTxrjvgk31dFG6V2SztBqWB1u9dOnatH64/U/IbZOnS+GAp0AAAAASUVORK5CYII=" alt="\textrm{E\_BusAux\_ES\_consumed} = \sum{\textrm{P\_BusAux\_ES\_consumed} \cdot dt}" title="\textrm{E\_BusAux\_ES\_consumed} = \sum{\textrm{P\_BusAux\_ES\_consumed} \cdot dt}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAXAAAAAaBAMAAABcLxqEAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIondmbvvMs0QZnarVESUG+88AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEZUlEQVRYCdVXXYgbVRT+ZrLpZDL5GSuICHXHWC20QnYfRBBrw2qRgpIqKLgP3ahY0Ac3tLv1RdioL/apo9Tii+y0bJBmXTasCtJ2YX0p/pQ2tiJ9MDbUouBLk9qu1O52PPfeuclk3WDHJrCekNxzznz3O989c3MnAXpgo4u7mY26rlvrAX3vKGevCW7lU3dn76r0gDnsOh7rwUYP6HtHqY829f7Qsyrrtw1tfIHdUP3Bq6ntFX+dmO2PyPewZzcebsOtQFF4+Q+ZU21O/HSeEt2qoI2YjD4NaAXmqDkoN5gjbbIsPTlybNzCXkdmVh9VN+O7oNah3WRxtyr8Ct3mwmExWiMHZJkjrTggPTmScFghG6ojMx3GA8u+C4z4JIu7VeEEwtTTNHQclbRpWknT5ps7VaY4NmlCcWSmw3jINVtXuF5GzJxuVBhGMs+EG+ByGe3DrXJQKi/7Iu5ybORFwJOlrwTIOO4WpCv0NjsesIKQ1uLiXgP7aEzjI5En4eMZjDcSI3a0WqR6eAIiLF5TXrEYiGM191u+UGyZm7eipR3ayD0/1dhVv2WvtCIiVvjWCVxBPb7lLEpT9nhj5nST73g1d/G9zSQmdUbkjOXqEQd6A/32HsSY8Im8CPEcvuEYgX3L5apUK1ZGCnsxWdZydLnvFDOLAxHyPTONv6ZP0K0lxoAViP07qJY2oN/gPebUYSe2gGFy01B5gu/Ar4EGkvZ5UwPexLqMCHHod9FjD6tlHZoSqhgFWmYon6zp1wVF61NxX2sGRt1zqeMIUgFb8SUmTTyCm5gkBXey5RdB/WLfvjTi9CJjtBMOFx5b/AqYSz1AGbYOJN5gAA+rUHMLFMTK6kJ8uXquQt/WfwjH7BJBhLUJD1KB+v0QLlSrW4UK7KsR4etYl0/kyGFHXJTeXHgyQxha3IYzNsr89OWh8jwDeFiDDv4BChKDd9tR1sxVhcdaB2Kb8CAV8Msd+zHLCvP2MQdKAxNQF8hjwn+md6vj/fZh9FUSdF8eY1P6bRiRMkMIbIQ0L1BgxGtQqNW2J7xtjyNiEURYm3De8VusgDIJo/K6T7hWxxeJiPMxF6MPsgr0XMO7wOOYzU9BzYcpRYtiITK62CsU64NJC2FaFEHoYwhxM2nSVl9pp1oJenIKC1oBm2hen4Xv2TYwPZKc/k40lC9j/ehQ6mQ96brX2W8VC7hUmtg1PTOTOLAf0W3DPPzsT233DvpxLbDqB3NPgSY03MVdiB77RMueHluqebRyMArSg37/1QoFNP9fKhDnFa5GVqj3u6/WMF3Kjy39lpXn4aXq2NH4vFxGs0oA50Pz/R87zj9nB2DqBNWf1Te81Onif88fo9vIWrmaaV2pZzjAM6vR315uHIh06vhdtdvjFrO1ncDb3SBq59A2l+5rz7SiR6XrPdxkGHDcUzrSqTUBmW4RHrYkcEo6/49xu5R5kP+BkNGaH72zUL+36ObWvFi/wMt0Zntm+fNr3v/8yabZvRL7NzKYtaPI6kgNAAAAAElFTkSuQmCC" alt="\textrm{E\_BusAux\_ES\_gen} = \sum{\textrm{P\_BusAux\_ES\_gen} \cdot dt}" title="\textrm{E\_BusAux\_ES\_gen} = \sum{\textrm{P\_BusAux\_ES\_gen} \cdot dt}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\Delta\textrm{E\_BusAux\_ES\_mech} = (\textrm{E\_BusAux\_ES\_consumed} - \textrm{E\_BusAux\_ES\_gen}) / \textrm{AlternatorEfficiency} / \textrm{AlternatorGearEfficiency}" title="\Delta\textrm{E\_BusAux\_ES\_mech} = (\textrm{E\_BusAux\_ES\_consumed} - \textrm{E\_BusAux\_ES\_gen}) / \textrm{AlternatorEfficiency} / \textrm{AlternatorGearEfficiency}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAU8AAAATBAMAAADi2JL5AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAMs3d74lURKsiu3ZmEJlws2FlAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAE10lEQVRIDc1W32scVRT+Jpvd2dlfGdOCIGK2G622gg0l/nhI3RAUiw/drU2gRNusYERkccfqQ1AhIz5UxJiBhD6I0BF/gArZBWNeFLJFjC8Vh1SfhGYRUkVCmWzSkMRuxnPuzGx34j+wZ9l7z3fOd+Z+ufee2aC7fyjz1NMAnjv+jVyjWep1Mr1PGOS12GMtvueKwiEoH3x9pdaaVc7sjfzzLEd+z62e/7I1hakAAjxuZGTtkp+5p+F7++eSDfkk8NLjiBzTORnZBHrWAzS5HoAuoEKljMsaxvRANmwD3SIyDFyutOSS/7YA4brccUgDfkYe9L39M62HC5A3LGBS5yQLje4GaDHHCGABuHDFeo/IeiDJi4dFZB5IEWha4rOm6zku9wTwgp8J6763f+b1Qui8TfGYILHQ1EaAtpytBbAAVKhG1X5A1gNJWtxKWBwioeHWk4yXjACT0oK7A3ziJzqqvrd/LtmKGcci/+UJnZMsNHSLvaYtLA42/aZDQtMRdfqwBbUZY4cWryRFhISGTOG5w6XOfAti1+UetaD4ia7gw/wwzSU7YQLlPg4JEglVpmuYyWF+GxOrf1I8vbJFN7/fjuf0b53K5JDF5JIdT9N1cTbOMbpjYTuZdtE8pDlIZeOtBpaKJlBJ9bkwUTZnH2WOy+3Z/sUtoHES91aaIOCU6lkT4K9nEefm30+SZAeR7aSNGTrbfJS7qctGSUe5uix0ggrTtP85Z5PISL3PlicvfOusTRPZ4stFunsrhtKQ8tBJqEQ9yhCxfFQ8xOVK0w4XChuV7hr03H1Tyb5uAsfo6xkffYyO3oG8Le1pMnWLJXE3kVBqt9DWEZdYsuU0efKo0+dVuhMdp7csHX00jS4DjcgROi1JxSl6CkEkn3H30Ofexy0yo9LwwN3JgvscGg9oHRxzrWRLJjAmFhNRFio5qhCKsnOINiGTcWq+0GSu4BcijTSVzFIztBgtXqAPGQmVbrvKpk8aiI+MfO4JxZuaqHC5BsAX7CDHdt2EyCKlSa7DI/UEESe5O+U8B1ho0qm6Qmm/LCwAvw76QlE+wSxRCEknEP6fUKDKDBKKPRKabEB5pYE4vZ81F+JjkwncTMSt0N4JSBLWRz2Pp5TWAkgoWXiPhqjK7p0djWzLFfQU0EebSt1ER093NLXkvf25MFUZAOL8hJY7SjCi8ZP8HVUaCQM38Dq9BHQSSncUlYeZIIRGtDQwISAFzJCmFq/KA69V499/d107oL2xtIbiVUrzemRjh6B8KDwWurxN/WVFd+UddFlyjS4tqQs1MG1iBGOEybhwsZCtYLYisD/wLl0zGA0DHX0IaYn1RA2nYQphDJHCbxozXC41xKeMyDqqIfVFM2qtJtPXkumURp/8skQBdGfrh5mhjB6fM9DlOA7/1g9V6Wdw7q/NB+c+uijdvwGl13kE0tGbk0NndjFWrxKtnq1nso7x1asZUc/PEKYM742czYEY/Fv/BZ3m2pXdd34oFi7ULfy4W2X4dlY9eGrFcXZc7rnnz6tedciKLIQvTmg3MLic7BNCC50c8PJtNaUqoIsyGP1J9YRyoB1NMhWDhFLveUI50I5CMV6UHvpjK5Z5t3uqW++eWiyMF9tSpyeq6P2z2M4ahbbTiLW9RiEwvPBzi9D/AIRItfl7RRDEAAAAAElFTkSuQmCC" alt="\textbf{\textrm{FC\_BusAux\_ES}} = \textrm{E\_BusAux\_ES} \cdot k_\textrm{engline}" title="\textbf{\textrm{FC\_BusAux\_ES}} = \textrm{E\_BusAux\_ES} \cdot k_\textrm{engline}" /></p> +</div> +<div id="bus-auxiliaries-correction-electric-system-supply-from-reess" class="section level4"> +<h4>Bus Auxiliaries Correction – Electric System Supply from REESS</h4> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUQAAAARBAMAAABX8MgFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIondmbvvMs0QZnarVESUG+88AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADHElEQVRIDa2VTUhUURTH//OhrzczzrxcCuIwSEEKY6siEIcBWykaRAsX+VoEFZGDqEFEfqxqN9hGgpjpw0BrYDZZaOEUoUSmQ6sQjUdJbVw4YcWgOZ1zr8+vgmTeO8Nwzrkfv/u/990PlDdEq8+0AlAPrYYaDQr8b2pikcGOaPVZSrAcfeZmv1/jjtPc2A6e0q4xKgwofRw4V6AOkG+KY0nn4qEg4H4L/0mu3bQHZuCpM6M9njr2GlxmB+8r1LiQiCAjvTpwOws3LSmFY7QO9UAjVVC4Zctm5M+Y0R5PrX06l9nBe4GSNEtUMWIiCdsbo6RO6BqD8osSF9fu20iiO8+tWaJVXhsCJCcML+Im0rEB8VkjQmKV4aZh8L+9KHozQdiuVbTKy6GHoGEMSTbPGms4LjMaCYG0q09m6M6lmu88MWj/ehaHkZpv7c4p7RULBpwTNR8220hHHauyHFrnTSzqn28eIYmhOckWyFX82BoJgUigVWZQ19CT9OsIaJ3wKUFkkEMiregI4R03aZohe83R5OiEONFSYrE8JpUkfRm0URCGk3M5a/U7LsiMVzERLO2TGbCBhKHmSeJHTSnrR4wkBrigHs/NJtJPmilPuVie4xhRhuFL0zAssYx+ZIx0/MYUx4bci1lxNv1cQoo0IdH38xXmLmuiAHlaw1qu3rZdEovlKVcIeAmlMfpwLBHw0F9I9FyUJzotJD6KixPt5VqSGBcSUTkXdyzkTYlfDt7i6m3bJdEKz5FDL5wZIrPETzwCr6IrKe5FRa7iCXkv3uDaLYn34J7X0GxKTIu+O/cit2azxKP+ygqe+g8k7wqJ6lFG0muA0+TpdakQxSUR8bo4klRIihLyQz+E81oEh4VENUfBHuMpC7PM09UBjyuWRnlHNDS1EigU8vRGz/Bt4Y+OZ0FPbe17HmmpJgWqXV3/1jJ7ff1qy/TjVMozPp/toni2a92oKpw3uJ1pgw3NHBYKBcu8pcWukbKXmkku1qun1MpzxXb+Rz+7eTSENwnal/aZ3TxSptDd3m+fQtt5LK1z9L7l3bJzin/z/gDLWH2/iS5fIgAAAABJRU5ErkJggg==" alt="\textrm{E\_DCDC\_missing} = \textrm{P\_DCDC\_missing} \cdot dt" title="\textrm{E\_DCDC\_missing} = \textrm{P\_DCDC\_missing} \cdot dt" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{E\_DCDC\_missing\_mech} = \textrm{E\_DCDC\_missing} / \textrm{DCDC\_ConverterEfficiency} / \eta_{\textrm{EM}_\textrm{chg}}" title="\textrm{E\_DCDC\_missing\_mech} = \textrm{E\_DCDC\_missing} / \textrm{DCDC\_ConverterEfficiency} / \eta_{\textrm{EM}_\textrm{chg}}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textbf{\textrm{FC\_DCDCMissing}} = \textrm{E\_DCDC\_missing\_mech} \cdot k_\textrm{engline}" title="\textbf{\textrm{FC\_DCDCMissing}} = \textrm{E\_DCDC\_missing\_mech} \cdot k_\textrm{engline}" /></p> +</div> +<div id="bus-auxiliaries-correction-pneumatic-system" class="section level4"> +<h4>Bus Auxiliaries Correction – Pneumatic System</h4> +<p>For the pneumatic system the goal of the post-processing correction is that the correct amount of compressed air is generated, even when the ICE is off. As the average air demand is calculated with an estimated cycle driving time, the first step is to correct the air demand using the actual cycle driving time. The missing (or excessive) amout of air is transferred into mechanical energy demand using <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAQBAMAAAAVPRmlAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAMrsQRO+Jq81mdlTdmSINXOHXAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAj0lEQVQIHWNg1DdgQAauyBwGhnRUbicq9yMKl+UD4ywkATYFQVEkLkeigzUDQyIDA4cASJRfBUSeZWBgBNEM/mIKDAwsU8FsIJHEcISRgYvVgUHGwWfbAoZOhoPcDJxsBQy8DuyLBRgOM+zawLCP8QOIuwGqJXPmSRAXbDYDA/MGhklIXI8ChvzFEgUy9xgAHxcaMf0UT3UAAAAASUVORK5CYII=" alt="k_\textrm{Air}" title="k_\textrm{Air}" />. This value depicts the delta energy demand for a certain delta compressed air. <img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAQBAMAAAAVPRmlAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAMrsQRO+Jq81mdlTdmSINXOHXAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAj0lEQVQIHWNg1DdgQAauyBwGhnRUbicq9yMKl+UD4ywkATYFQVEkLkeigzUDQyIDA4cASJRfBUSeZWBgBNEM/mIKDAwsU8FsIJHEcISRgYvVgUHGwWfbAoZOhoPcDJxsBQy8DuyLBRgOM+zawLCP8QOIuwGqJXPmSRAXbDYDA/MGhklIXI8ChvzFEgUy9xgAHxcaMf0UT3UAAAAASUVORK5CYII=" alt="k_\textrm{Air}" title="k_\textrm{Air}" /> is derived from two points. on the one hand the compressor runs in idle mode, applying only the drag load and producing no compressed air and the second point is that the compressor is always on, applying the always-on mechanical power demand and generating the maximum possible amount of compressed air. The mechanical energy is then corrected using the engineline.</p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{E\_busAux\_PS\_drag} = \sum_{\textrm{Nl\_busAux\_consumed}_i = \textrm{Nl\_busAux\_gen}_i}{\textrm{P\_busAux\_PS\_drag}\cdot dt}" title="\textrm{E\_busAux\_PS\_drag} = \sum_{\textrm{Nl\_busAux\_consumed}_i = \textrm{Nl\_busAux\_gen}_i}{\textrm{P\_busAux\_PS\_drag}\cdot dt}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{E\_busAux\_PS\_alwaysOn} = \sum_{\textrm{Nl\_busAux\_consumed}_i = \textrm{Nl\_busAux\_gen}_i}{\textrm{P\_busAux\_PS\_alwaysOn} \cdot dt}" title="\textrm{E\_busAux\_PS\_alwaysOn} = \sum_{\textrm{Nl\_busAux\_consumed}_i = \textrm{Nl\_busAux\_gen}_i}{\textrm{P\_busAux\_PS\_alwaysOn} \cdot dt}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{Nl\_alwaysOn} = \sum_{\textrm{Nl\_busAux\_consumed}_i = \textrm{Nl\_busAux\_gen}_i}{\textrm{Nl\_busAux\_gen\_max}}" title="\textrm{Nl\_alwaysOn} = \sum_{\textrm{Nl\_busAux\_consumed}_i = \textrm{Nl\_busAux\_gen}_i}{\textrm{Nl\_busAux\_gen\_max}}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="k_\textrm{Air} = \frac{\textrm{E\_busAux\_PS\_alwaysOn} - \textrm{E\_busAuxPS\_drag}}{\textrm{Nl\_alwaysOn} - 0}" title="k_\textrm{Air} = \frac{\textrm{E\_busAux\_PS\_alwaysOn} - \textrm{E\_busAuxPS\_drag}}{\textrm{Nl\_alwaysOn} - 0}" /></p> +<div class="figure"> +<img src="data:image/png;base64,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JX22hZT6hO8+6TUVUrDNNTQ4BxLnh+LqoN26dQvfCwoG3D/99NPDMjhX0A99Uhv858QQiMIgxzCIFkG2DrKFEAX3JfEtgShYP7AWEZHah+6hxO6iIpI6Hkn9Y9C/hnqAA/pNHUwcY/PlG5ZBcsNQCR988EH6VvVgoPT6gnESN3Wsv7333rvWA9WmwHsaN26cTZ06NVwsBhAOcQEatATWxWv2BwY4lwQFt/00Cs4PZI3zAlFWr14dyi677BIe782ePTu0FjI4+hZCBk8REak53F+z+H34gw8+aKNGjcrsf/kHOr8/Zi1SChQERURSeKCQr+CggheTQamoqAhlp512Sq9pgzlz5mRaDhEIEQLRSqggKCJSO5L22ZxWEBSpSl1DRUTSeDDgu3OymyhK0m0unw3XKSIi9QMhkLJNi5QiBUERkRQGNl+yhcGkkgTrEBGR+hGHvrKyssy0iCgIiohUwfDmA2FSIT8tIiINR7yvRhD0+3Dtv6XUKQiKiER4oFBIERGRhk37apFkCoIiIiIiUpR8CCwvL09PiQgoCIqIiIhIUUMgRBBkbw61EoooCIqIiIhIEVPoE0mmICgiIiIiRUtXCRVJpiAoIiIiIiJSYhQERURERKQosTXQ1ywipU5BUERERESKTr6wpzAopU5BUERERESKlg98Cn8iGygIioiIiEhRQwAsKyvLTIuIgqCIiIiIFDkMIcEgqOEkRCopCIqIiIhI0WHg88Ev27RIKVIQFBEREZGiV15enp4SEVAQFBEREZGi5FsFEQT9bZFSpyAoIiIiIkUrDn3+tgKhlDIFQREREREpWrpKqEgyBUERERERKQkIhSy8LVKqFARFREREpCgp8IlkpyAoIiIiIiJSYhQERURERKTo5GsNVCuhlDoFQREREREpemVlZekpEQEFQREREREpegqCIlUpCIqIiIhI0YkHj881nqBIKVIQFBEREZGihtA3e/bs9C2FQBFQEBQRERGRouQDX3l5ebitEChSSUFQRERERESkxCgIioiIiEjRUgugSDIFQREREREpWn68QEyziJQ6BUERERERKUoMfAp+IhtTEBQRERERESkxCoIiIiIiUnSSWgMxrVZCkUoKgiIiIiJS1BD6ysrK0rdEBBQERURERKSo4cqhDIK6iqhIJQVBERERESk6DHw++CkEimygICgiIiIiRa+8vDw9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" /> + +</div> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{CorrectedAirDemand} = \textrm{[Calculate Air demand with actual cycle time]}" title="\textrm{CorrectedAirDemand} = \textrm{[Calculate Air demand with actual cycle time]}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATIAAAAaBAMAAADGYM0ZAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAqxB2ZrvdVCLviZkyRM02CmKXAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEmUlEQVRIDc1WW2gcVRj+MjNmJ9mZZGuLaDRk3rRPM2K9UKFdzKYRG2weVGyx7FiUvihZQYzUS6YQiPiy+6K0iri2VuhqaRqKohV3XlpsU8gWioiWNBSE6oNN1oRsruN/zpmZvTR5ye5Dfpg53/+f//LNufy7QL3S4h3n4nneSr25GhuveP0i4XDXXGMz150tOeunkPJO3ckammC7FxCKjDY0MXBvOZ/+YM7NltU1kX6n2qx7dmA4AXw8UMDR1feTDtkmp4MJMTYZ1Tqk00u5cy4iufMjNTNclf6jYY+YOWXgPVvA2rcaGtIhEuDsUqXhcRuIod0hm1rDzLQqHRlunYa2giPQXqudYbryEr2u8ZnWKXK2ObzrJYeWWmZtXiqcA55aBOKCmVTDrMeu8ONQzgAP4BDwde0M0+UhJzCnC4BkB1r1eE+o1jKTviyFc4C121mP2ZOVfjyEMcsbZB6uyBDCkZZsgH9kIBZo1eNQqNYyw9BqOEfMmqfWYaamPqvw41Cs2V8GgrNiVHpYURta0pk89rzzL7MbUBJjWnL4rQID+t/Dt5HYCT2fSyGx18AfiTJHP03Uy/qIBkubDZkt957BxZKeNJTBHtocfA+h9sypn/IQYqbOY2LmGR7f+tjJI6zGxVJvJzNY2jLoXKizUddvlTlcgmlpGTCQjv8sp+R+mHQEs5qtxLCPRZ3bQtLBEMlARfe3aHuCczaPtpRUQtq4gibGbMIFV3HAbwjybPejLrQu8Wk5bOU16E5epqyai88ZM4n4vc7rUHCz216QihyYLlpj2jRjZjp4g9S7dhPpBYNHspeFlljArAg9gxLajQ8dDbiKllFwFduviwB5WsSN8259GLt4DazApHk5l9vPmRWB++imnl58eH7wnRRd+2KEAeaDYc5saHDw8E1jDWaKVz6cFiIrZWZqiVNpWrgf2Jk7lfGZ6V8IRoKZA/zC9K34CqyGYE9rjIkCWzOiz25pNKOwD2HMOKC1Ujt+Zcwcto03sQYzdKVoSogF7LdYOF3zIjgz+riRLoNWk3oXVSVVfVE4C2YUconpv310SxwVtszADaCZdUbGrKmfHlul1TMYMw6IWUtcnXZNI542IJmOYFZ1zvCPKMTeVMa0Q2YRtptp41lEU7oLvMqYURq5jdxIBLMpv59aH9BnUw1/zYgMdWJiRnywxcBRGz8h4pChxIFpwHQjxXi7E49m8a4cw26DPKukKVZWCSoZnxm7AXgT+9y9aHVZQzwLrmJUEttJlUkWgVfY+B09rAZbVweTqwb2zPXlH7o2Ewf0jh0pahY7+rR85/hMgYDetQ3K+d+fLkS2uehO0DM4xNOwVIHsCgDoNzNFLZHC2z2v2Pf2GeDPxMTB7t5e/c4tKAMvcPWJZe34GHP4Zom8ceLkty7o/13a+6TAaozP3Mh3llPWgSKH6gguh0ovSyPHymoj0GWnEVkgx4EfGpIpSKKKMxOoGx61fuD2hqPXCmyOB9ZsADY2Xkk852wscp2oA4FdGQ3Q5hijtAlcpHxhczAKWPgt45HryYXAtDlGnRqRL9QxN5PIF0IZaySv/wFJ03ua+JzU1gAAAABJRU5ErkJggg==" alt="\textrm{AirGenerated} = \sum{\textrm{Nl\_busAux\_PS\_gen}}" title="\textrm{AirGenerated} = \sum{\textrm{Nl\_busAux\_PS\_gen}}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAWgAAAANBAMAAAB2hem7AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEM2JZna77zJEVN2rIpl8k5VNAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAERklEQVRIDXVWTWzbZBh+TOLGTuvEwHbhksJlJ7RIgYGmiVqQQunGMGo1oEKQA+JHHBYEV8AcGK2ANuouO5QtRyiD9oAQmpDI1B0oTJBDOYAmtVMR/1ITVqoVGsHzvokTJ+0+yfb79zzvY/v1lwDALTy4Btzmtfc8t/5EqjfW7c/W6Hfgt76xft+L3RURzz4YccS82PHtb3NBtuPuabXwQ55mMz4QX9xVmLoI+5ddUQlUw6hToxWBD/FBZMPkrutqd8T4m/7RZuyQi092K9Cc00Yp3jhR1MCDLLcr7Vxo/Ezj8dDpuvqhp6IjcJYbF8LkrmuP6PhLrJjTqtggELuBaLPNo3jT2tTARKMdjxjWdTr9kUDHLISmio7A5R73vk9B9Ig2F6ohz2qJd3sD0X1hURO/H89LwCm/0o5HjFSRzp4znayFZSI6ChfBImDv1SP6x0Q2rNMprIRe93Wh7Srex4zHiIk/gFMN+8DKne08jf5B9ZLjT2L2tft/kGz+uIvTw8HZa4cRz1+FfdcoRUfhIjrtS92pxujv+46VEB/Oknt0GTid77RXZj+1COtkleTVOyTgCql1cuU8UfmrKic/BnsjV242Vrzho6/IYhMzAdDAqvcrvT8vcy3RSBd4AsaQ8pzNVMBsLGstJgsYNCg1h3dwDHEV3YGr6DWp41f2tmcXMYETEBvxCh5VwvbJlwFMV4V8qxkU0oxvFZWdDc2yWUCG407CFt50oUM9icSaiM4EiK7EoHhGHU7NIDuzmSo+T5SclynaaKD/zetMAVG4iM5kpQ7byJQIPoIZiO0S3z0eVoDXRbSQfyatlDRIEyXsAQGxilUT0ULYwu9n3QEeY7lDfOAU7QqyvQYYhC3zu83mkl2Yn78wwyKKTv4z/9GHcj/dcJ3pstSRj3qIc/h8abvnXBVtPyfLI7WZy/GTahZ9wz33nmu3kbScrqIu7GWVs6KihbCFf4zIc4T7sLZVNP3I0t3DbIqmNt6wvF5iKdqRubBrKjoKF9EPuToGIpSir9zL56uie3cPbmUzJRFNKtlHUkUhZQB1NdjQWXpPRFe1seINnyU3FWEHwBcd0e2ZhuzTU04dVl14ybHqwuBbMox6nGHc3BDRXXAR/anWqVCKfhWrltp8xZQfWWf4rVdaogcK/GFdFFJXRKvBhgnPqQUZ19PGio99MDk5+dYmZB8cUtFuhJImfxEdj99Eym+NRyqLj2MFPIJGHOtIVp+CWe+Gk6dvDVJHoRmOBwd2YZ/aZgXPdDUo8AOriWhKxWUXVxaVlIGGGhmX31Gy7qWrnhA28en/ZP1rH7wd8S+fnd6Z+u4S0dF19u5Rztr4YczteLZkh/MBHuBxfoRhHhPzW1NROP97HPmaDKyb3jmzsfzuTnD84e9/UxvD8wsvRNhn/3JxdGtk4yuSc9SWxsvc6cZHrI3l6Z0SDWkY/+n9p0vJS4E2Fvz/A5qjWEmt3/cAAAAASUVORK5CYII=" alt="\Delta\textrm{Air} = \textrm{CorrectedAirDemand} - \textrm{AirGenerated}" title="\Delta\textrm{Air} = \textrm{CorrectedAirDemand} - \textrm{AirGenerated}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAAQBAMAAADNHX/qAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIondmbvvMs0QZnarVESUG+88AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADWUlEQVQ4EcVUXUgUURT+9sfGmWnHwcgHoVw2LdJiK3opKqUeCulnITDoxS16DBvoZ6HIzSAjMppe+pPYIQn7IViCiCRDejD6w0WoQKL2JRMTXCuxVWs7546rO2u92ln23vOd75z7zbn3zqC4enN5XQiAdpGGXHuRC8iXl/4IbDfgC9QuymP+Aq/asflmPnc07YgEAekUR8ocYcgTTgy4U5B+oxfS+nxmNg5aIhaLA8qqXFoL5yKQOvwcifEwY8ruGd/21DDQjXVAZT4zC8sPKZfsFilrXcKdGtwOROoy7jCVp65+0qcKshOr7zJHgNJs5J+zKo0LrpOynVZoOXAQKkyO5Kkvmud35AF272dMuPKI2bAVdRx0Jfbnc0WGIxLE1A2JHe9NSvX65zTu94WAuHcVBFTqQyVruITUXb8QnRQ7Ba3yEXwdTzGw7/bi5tImx5qII2pxBbYAR0e0HH4Yx+M5ucFAj41iCVxATHelJT+6SF0ao/0giAK/fXXV8XtPDEg9GT8XvEUhHsBruca9Rpm1lSLbX5M9Y06OoyBMs4ootToCm2cGFVIkLBx7CMJtOzET/SjSkfY1gUQMHICAkBvsbtWUnXhEnGkDSq6l4UrJ/JCkkWuqCXHwEcyrYXWbX8BZpxvlBNzknRUFQfjoR0bqZTqro+egDjUQoKMTEP1JkWmr68A2ghK9t74U8Fsmh0od1kqomf4PAhVhoS74Y0kKjfLgqQE1yMZvnMLOlDqt5vqQpk1DNEnqvPjCEPOw1ePAYQLatHqKSgU/Mzwmd9ii0+MPBPc+TWljFeQPhrMBVv/IgNTfkZwrrejYgS/0hF0C0iLnRbKtfgoYIsgbfilNWyBPq0+fu0xPiMIwNAPY4FR3hzxJA/EGSJu0jVWid3k1ry5unSepjCk1WIaQ+LYxhBeXk5xA3zqyb8Aeniug6AF443/Zeff7SCRyYhwFlEbNUe8mV7AVWh4jAWsFsBOvrqD40OZAd6ook0ldP3kzCa22fXSwoy8x8NNE26jF8Gu1ceyAmclklvxIUP3yqnIDhJTKdigdKzE0aWk9L8XS2YFWI/uuXTwHpXrvkcnGGd5j+jrh06Os/iabP7ez+26bRerP51Y1q3YDSui/qWstcE9caZHW6n8A7qkRivg+a2wAAAAASUVORK5CYII=" alt="\textrm{E\_busAux\_PS\_corr} = \Delta\textrm{Air} \cdot k_\textrm{Air}" title="\textrm{E\_busAux\_PS\_corr} = \Delta\textrm{Air} \cdot k_\textrm{Air}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{FC\_BusAux\_PS\_AirDemand} = \textrm{E\_busAux\_PS\_corr} \cdot k_\textrm{engline}" title="\textrm{FC\_BusAux\_PS\_AirDemand} = \textrm{E\_busAux\_PS\_corr} \cdot k_\textrm{engline}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAo0AAAAqBAMAAAAkBXwBAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIondmbt2ZlSrEEQy781kO9zxAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAKC0lEQVRoBe1afWwcRxX/3Xl9H7tr35EW0kgoPo7Eiaugc/9ALQ0ih1HqtEnxtVIVqQFyMhC7NK2vIfGZFpolgjiiH74GRCBJyZKU8lfjTRMElqr22hBVKK3tgkolKsgV/kpU6NlKSuKkmPdmdvduz07iuwBS8b0oM++9eV/z29nZ3RsD/3/0bOWUApWK/7a8YFXHko1paD9qzScpl/qps/HVRnnSsFkuEX/wVMeS/cCOJQ8ZtrShwgLwffJsRsbk+F9OSYP+7NatgtPem+Exi8JOVJmRLF8sVpjnKmSoSaE5MVU5UCEvWNUJjHRsVqji+Oo35WiwJ9uZFOzcChWmXUAwidtNHBtn2T8O3/tiwG6G0+US8wlgzArFcDxjS4djzHjITzOVMclaL4gxJR28dJ20ahHdN6Vgd1Iob0UiVngz0mWi6OUUsMolwQ+KVhufMeAofJKh0MpeaHeCKx6Vutuw/eV2yc6tULalQIgpKSAgcnLbJWPIdpsdsaR7AAiPN5jwZ1hHknpLadDmqCo7pogvtBFTLdrDsrwRKdmdPVTWiUQsezPOxLG5zMlmpcqfmzlia+w7n8pbTZoHBI5+OTaFYcdtboWyNc8zM5anVgDGOCZMkhzqnXA4p6dZKVORKHwZ1pAk/jujsicc7ZgJqHhYKIdL60iW53WZKYlErPZmnImjXHyeAH6DxWZRomfAERolk4B+ibgGxtEMmqykq+3W5zI8cEVKIITonWyS5IZx/DQzNvmM3zus09OswuPN9wJR1pCEFssZo15lnqqyYyYQgMkqusju/XiZ8oSrsBWNSMScN2MljibuKvk4nJZjLpJ35Bn9kNQkoNCMoXDFaZl/DjhWFMqhEqDV/DkZlFrC8UQSJya0jWZw1zaS8QVIcds53x9ibEezajH06T0mCwLHSPrFNx6NBvtjQGt3L7VclR0zgcMk7+y3tK74kkkew/PZIZDDxzdGnzyLxP6N0RMTA/tcV7aQJBIx682oLRsoan9f+A6y3ZRoU+sOEBI7H87Sw6+MGB28hFfTZboylqoxWEygocA9VawSE+q5H8cm411xoZtroWyciP8QOCfcuAmc37UlA3UCLeYrCDOOdH8KEXdjrzDry26ikn83PSkkmiMiSd8/lXwvvg5/LJxmNeFox0zED1CUGDrd9RjMYTvYIRL1TdBVjETV9/G663r7T4l2cxCZyGWcjN9CkO68zLqAEUghjh/zjuR74S18n31cKjK3VH9N4OlqS4y9BSYQSQmlf7KNXLqhZNz1eJVCS7GYS+CjwF9cHd/XPwMmEDGfjOrAa2hKShHP/doUZn3SWO/KMMM4DsdU2mTaMIYGI1BgLeFoxxTrfdikLce5r4fzJLAD7bF34wh3FzFsOq7sLslORIBKWWYkT9ofKIg/pxdxCx6Er4BQsB33oTkPfFFfKaz/hOvy+OtJ1ZC+1B63eFyQ77POoySBpoJQUcUxqFMU28XxSoVScC8lEASeZp3FDeM4lhE4hj94ii5QfClpGFZob7OBPSt6bVAKLDGOLQYVQNvWdoTT/hxrqSo7Ju+/oSECzXJwfIlBZQcC8AmkueP4jiu7S/Li6GTUeK6EO9ksLNJqbBPvVUqMWLrutIusFd634nUL58SchEz1WjwuSH+7hGOY5geNKzawqwhcdHG8UqEU3EsJFuneBc2IiHGMJGliVOgNB0xS6hcZRxJ997CBjSO9NujtLDGO3zEpNxataIF202KTtVSVHZPjB704EvD8UGQAm35gODg6ruwuyYujk1ErChzpsu1+uYijHzkDlQppsqhIJgfHceK1S0uFTjaKVSYQjlEW7ed1gCsGBqgpw3GuhcpA1CopgsVi0V2PLeZDUAwtD3yGcWwxEWhOk4GNI72faTmWGMebBSxvoUUPhEQUrsqOyTg+Rt5jprMeh6MlHP3rBZy8Hh3Xsv2R4zMJQJ2MtFnzeiToMr5iPv0YjY/zhEMF67ilLX+Q1uNgVujgTzVY+cGsdvP3MoFN3c/Q+NGBTjFKe5GZ4dBU3mrqTgocQ0emoE/RJZbvE1cplN1LxPMU3x4LBUPfM/gbsBLb81vhzzeSkixYRFKVN7bwiMTQmGcPkhqTfJvSvjX0S7/QifXI3zMUk8bVm/wx3EZTp/kTBXLoM+37mp4wcj0ORx1XNpEkEjHrzXgfAvSmbNIWGZrKrODxM8CjUGIZxVqMxVirp8KmL0X65kxD/nESOtTCIbWgWPQvdphHaSwSdXCk7xl6Feb1eCgah5J2cZxzoRRuwardHFXr6KEbbHp6ir+vY8Cx7NiG/oEB7b0zCK5aL8SvXtL/fMf09PTBVWvIwX+wex07TJ7qaPsJfaJeyGDrIx9b65v+YAPISHxfc8wFpzriTxfRv8XQDqwbOZshl2L/rqEvkYPeRY/9p0Ddby+80LVPuFJkl2QizuHJWAz27jp38sAeBDuPfM1qmX7TQi/QA325qVjdfF/7941YQUapwQz1srAG44fVdoGj0cQKGgvtyYvQnTTZ1gH4aOJtpxDsWY6RsycPdPIkMMdC3Yr/c8wvoj9/IlpbuJpc1bvUG97AIjujjaOSpnvEhCQWCMfwlryNIyuuiWoqtMqMPbTXGlX62OY1uQZo2a1Boylj8H19nO9rX9SBFiwQjvSUsnFkhTSvsa2p0CpznaBNqcYqa3LVU8A78CVlmaO5UG/f46fNHYO4wy18x6B++tnzjf/YP7p3NDe6t8+g0WuimgqtMqO+LPuJKl0c89pcX8luoev2GyeI0wfzDmf3g86PYhX6GsTaCq0h0f/ehd7RvTRDsQL86lGna0XA3/vItYao+9cRqCMwDxBQ01VPsnqPqlN8+BzCM0peQF9ei859l88ePYeFruEzLldnXATup+/pd11JMPxLQA5KEZAnzN5R+hrNVGrqMgrwbaafo8uJcUyL3zzotGY2KsymnN86sbYui2NwdnCWz66ez9pG+pDC5XA0ZnwJSKhG5jNis8+9idWXwzE2uw+E02XG5qm6gec9O46Tbe00phSoEQ8i94ANEVLVyYPAYpZmx7Eofo5XC2SQp//iAI57OgwxRVdvSgiMMitw/NU9ROtZ7KP/MX5e8/uNwJG1ZdRglgl1lhE4xE3FehwybRxp6PmdhaM7Nq8M/VFfKQ/YNm26sb4/Mmhemu0585zhnJnRXyf4CuFv5NdimWqIAza1/TDd194YdYl++DcJBTrcLyftVhyUp6UIxNRC2KBT4MVBPtIwmujQEvzHK3XyIhAwoLb9Sxz8lgaub03TXyNfuJGOlxnHPOHY/KrEEXvINlsyrXMSAV/uikj4Cnq7wDH4ro1jmuzvvaLP/By8CiY7d54//nn9NJCCPGD7yun8VbCfnzheX920Qxm9oJjV+cwLa82oapr0hzepb1flMV+Mo9VNtHXQqtKjuvgfTut/A5PrRyO8XdN0AAAAAElFTkSuQmCC" alt="\textrm{FC\_BusAux\_PS\_Drag\_ICEoff\_driving} = \textrm{P\_PS\_drag}(n_\textrm{idle}) \cdot k_\textrm{engline} \cdot \textrm{t\_ICEoff\_driving} \cdot (1 - \textrm{UF}_\textrm{driving})" title="\textrm{FC\_BusAux\_PS\_Drag\_ICEoff\_driving} = \textrm{P\_PS\_drag}(n_\textrm{idle}) \cdot k_\textrm{engline} \cdot \textrm{t\_ICEoff\_driving} \cdot (1 - \textrm{UF}_\textrm{driving})" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{FC\_BusAux\_PS\_Drag\_ICEoff\_standstill} = \textrm{P\_PS\_drag}(n_\textrm{idle}) \cdot k_\textrm{engline} \cdot \textrm{t\_ICEoff\_standstill} \cdot (1 - \textrm{UF}_\textrm{standstill})" title="\textrm{FC\_BusAux\_PS\_Drag\_ICEoff\_standstill} = \textrm{P\_PS\_drag}(n_\textrm{idle}) \cdot k_\textrm{engline} \cdot \textrm{t\_ICEoff\_standstill} \cdot (1 - \textrm{UF}_\textrm{standstill})" /></p> +<p><br /><img style="vertical-align:middle" src="data:image/png;base64,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" alt=" +\begin{align*} +\textbf{\textrm{FC\_BusAux\_PS}} =\, & \textrm{FC\_BusAux\_PS\_AirDemand} + \\ + & \textrm{FC\_BusAux\_PS\_Drag\_ICEoff\_driving} + \\ + & \textrm{FC\_busAux\_PS\_Drag\_ICEoff\_standstill} \\ +\end{align*} +" title=" +\begin{align*} +\textbf{\textrm{FC\_BusAux\_PS}} =\, & \textrm{FC\_BusAux\_PS\_AirDemand} + \\ + & \textrm{FC\_BusAux\_PS\_Drag\_ICEoff\_driving} + \\ + & \textrm{FC\_busAux\_PS\_Drag\_ICEoff\_standstill} \\ +\end{align*} +" /><br /></p> +</div> +<div id="bus-auxiliaries-correction-aux-heater" class="section level4"> +<h4>Bus Auxiliaries Correction – Aux Heater</h4> +<p>The power demand for an additional fuel-fired heater is calculated in the post-processing. The HVAC steaty state model calculates the heating demand (weighted sum of different climatic conditions) and based on the engine’s average waste heat over the cycle the power demand for the aux heater is calculated. The fuel consumption for the aux heater is only added for the main fuel:</p> <p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAWEAAAAnCAMAAADpVwkgAAAAOVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACXHtMAAAAEnRSTlMAid3vmau7RHYyVGYizRCxi04T3PaeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGd0lEQVRoBe1Z2ZbsJgwEb6wmCf//sSlJ4N1ud5+Z3Jkc89CNhUBFISRslPojpc25XZQsxfwRLP9PoyHnYTWzGPqtaNX+PLzLwJBz2PRJXY4b0fP4OQMJcWLHp+8+H/CyZ7KXzbXxnlbVfudfN22nte7b75rhARiTc7MT61REgqgbqqMn22trVfyQg36yZIOf6suKbjD3dD5/3bBDYJ8NJVvMkGyTe0eD2dxsN2a1MUhQNOcWqubX/eucL8wVRFr4CA1PS8vf2xjslEKD9ft15fFGsuTPCAJ7xf3qYi0h6bZAqo17hLn4xocush/wjmTM+difqHNBZNg3dCO+bfKdcfc64yRqXJzYnoRcyWxi1ly3KhWExlTWYAUpFFyhbsFtZ+UyTwRruGv6RsFhKC72KiJDmMMUsc8JuMI5e2Y8XSIjrl32zH405yL7g5HksYZkBGA8p8+S4fMNsrf3NRKf8xlljAjeRvNJdYcppT8yPEwp1Z/ZU1oillns8+J1YhLsjBRKZZdvIMUsQewcHQW9uBj7XPNrW7qcTzjriYrSpmUDf266Rsmkm1ETF44PLXJy8cETa2NxsKoL0aLKzHrCIQxvIXFC9tNC7qG2g9bjyVz32m9Lun4qGyNNltXfDdmOQFSyQrN+N9npvhTMuW1gHpNXLRy0p/Hpx4D1GohqGAlODSrO+5p0aS+JZAuJsuDViTBSGHbs6ONqa7zEXhTchzleRbw8H2UH3na6YFn7ubWekc7YXlmPc2ggYsEoEg/+6CEQ+zoqUx22wnGD1WGcLHF+7FpVwvAaklIUBGgNku5WsbhC41RItr0qk0L9sviNXjdBmbptVaaGVQVvz0fRiRFVB6pnYk7ENii37XFgfWnETQyn6qEaQ3DWawYf6CxHAi7l1IJ6mMN/cV2XTcG0ggTdrhEP1SGtHaZA46AHvYtcyNbnn+E1w1uVufOq1h+e2CoiVm1qaAkIdHK0Xw2hXjCcpihRDgxK0Z4L8LtUg0MNw1PwJR+28xzIQdGNAwtVlpDwjMTMGjskRdAW/U6xVzsdIPAhyIL5NrjGqqG3HvoxeG3MqNE2aWANrZklrCcqBAutUxjuKzJpwO9x+K+IWM0WHyQHoGH1qEwTfAcIbKoyzNAc3hx0wwraGz+QS9UIoGz1VMpZYMtPTp1jFKepuhKHhVgMIRVbfXcJiTD6zG+jbuh8AVDYEYbLWUNpTB8SWvIxOqxwLx7fG9V7hHjIW4XgmPAMOAsN1XUqjVXCeofORmDWpa9zXokroiKUVZAdCsuwpDrNf2KqOIpAo0AImqBA2QtBBbOpO7e6oEK0SK1BcG2IV+/AtLhTXGTVSjY0SnRI9b2hOEYNGojr0p2QCIDCDkPTY+aPEg0tLCSWT4a6NwbUUsGpBouPIZJrkmspHxPDC40yapWQ3j2Gqy+wnelHD3nt7LbDRwk5C1WGhUeGVH1YoFWGoQAeAzmfRZ2LJDpUQwf/pl0Xtff0JqaDzLXsW9YWCVW7tpEh5tf8BSQo0KJTmRkuXDDD0lZ+ISFXhu60QeASPg1Y7z6kJqXkQTHmGZcaMq0iYT1WWQ198ODnvHLQeihaMyymyjQE2oJhOCEzXI/6U0w4HJmFHFXOm1+1zAwXLg4ZptSbOErEyO9UClvZDlh3cJ3+SvQFqjPR0T6ABpd5Z8QoeojZJbKdo3LtxRn9pBsxjNggBidTQAI/ZGhwWDp6FaIpo+AwRWHCJH8YkpaG6losZe/UyaoAKOzsGHYjQHhNL/LyO5ArI9yA1dR7b7u/rcd+dbREokEA0C1ZHApYInqRVS7RxXbeh5eKi0aHj4y6NcWgmPoH1hWA4qQMaLEzJoeiEIeRFjHS7s6mk2S2GG5b7WrE3jbce4bVCkC4IBivutYQ9krvg/aDb6nscR8MhS6XQA1a69noYngcIP778r6b3cU47OmkXf9puQZ6Lxzd0/oU4XG/S8847nJT2i3ORdIF9wfXNF2N/H1Ar6z+5Lb1OS1FE3A3ujiB/mTsvwIbbukOyj5u/IrJ/EiQtjsqL/Puj5zLA+ph4GHgYeBh4GFgz8DZdcte85F8xsDZdctnoz299gzsvjntBPs+j+QNBg6vW/gW6I1BHtUrBshl54/K+MQHgdwCXfV62u4zMDM8X7fILdD9MR7NKwZmhufrFrkFuur1tN1n4Oi6RW6B7o/xaF4wcHjdIrdAF71+Z9O/Z6QyTJOE1LEAAAAASUVORK5CYII=" alt="E_\textrm{ice,waste heat} = \sum_\textrm{fuels} FC_\textrm{final,sum}(fuel) * NCV_\textrm{fuel}" title="E_\textrm{ice,waste heat} = \sum_\textrm{fuels} FC_\textrm{final,sum}(fuel) * NCV_\textrm{fuel}" /></p> <p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQMAAAAVCAMAAAB193vLAAAANlBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHL6OuAAAAEXRSTlMAid2ZuzKrVCJmEO9Eds2xiyjcV7oAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAMGSURBVFgJ7VfbtqMgDA1yB3HG///ZyQUteFpLXXYeZg0PreBOdhKSgLD2A/6Pfy0CetghNa1aaWPssMQdQDVlrZRyedzQT2mDGpcwjrB+DeMiNyCNYSXz92Kg2KGURoxdI6GS/I0I3IJZi6ipf7fo7JVIkM0IgV25CuzqexXfnVVWzL9v8VhxXrx7QxJXBug8lDRvlA2/LsTKCTgs8iFQcynYPCLmOGfm/Hd7IrWDwI1oxMYrGHJrVsuiBiKdTYylqK9lgXb7aBp1NkotzfyKl6cys7huBiIAYZ13XculXLDTQ8Ou6s1DoDK1LHeNlPSfEjvZ1BenXS9a2wHbPBgCf8DpnzE4Qo4hYVZS4+Gg7Ihs50etZ8RSZ/OrdtCJuqVlGXo+Xqc6faLhCDnq3VjDR8fCUesJsRfF6lXL6USnR1FyglgVccXHKIXkc7RTAeOKR7EQvZpnbjM7AkCXmRqPrDBOIOL4036QK6uWhD6QouDOC9eIq+9LhISpRj75XJhMuCgGmwuhvRbgizQBLMFiU60F5WZwHk8xXM+gLCScY/o2CNAa0rKtMI4hx71v5lsTUhiKZ6QI3XivEacag8lCqT4B7hPGQxwk1s0FZVb0cBv4ovDdVbl5RiNoeA3F0Ume7JQsHiJoHsagQYBGDRifKkO4NzFQC36i4MfCtGLjekba8l4ijrVF+eJD9QnCQm6Ig8S6Gcxu7j/0gpNUNxfM7JMJuPkxTSklj0HAGIQWITGoK4xjyK72/OEpKYpU3mvEfOfZeMUnym+MQZ0ga+vCBuUtsdgiE9dCCMA3LeegGIiYHzn9SpA0xjBYSiRE8JAYyIrgsHeE0X6P1vwkRb3Ce404dF9ioh6vpdRT64RYGxf2GNgFq8grj9GSX/7ewMsG+p2c90X/Lr4EsBRBQZAsiqWCbYVXBBcYsis+e3hOihLCe4249BtQbaVWUA0nmxsXzgx8tIoz1M3vbiDtSuFhHm7u5+Pn5edzHR9L3EBai7SjLsFf+R64YUc6M4Ym3yKN21nRW/EHxmEcIdmxv1gAAAAASUVORK5CYII=" alt="\overline{P}_\textrm{ice,waste heat} = E_\textrm{ice, waste heat} / t_\textrm{cycle}" title="\overline{P}_\textrm{ice,waste heat} = E_\textrm{ice, waste heat} / t_\textrm{cycle}" /></p> -<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="E_{auxHeater} = P_\textrm{HVACSSM,auxHtr}(\overline{P}_\textrm{ice,waste heat}) * t_\textrm{cycle}" title="E_{auxHeater} = P_\textrm{HVACSSM,auxHtr}(\overline{P}_\textrm{ice,waste heat}) * t_\textrm{cycle}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textrm{E\_auxHeater} = \textrm{HVACSSM}_\textrm{AuxHtr}(\overline{P}_\textrm{ice,waste heat}) * t_\textrm{cycle}" title="\textrm{E\_auxHeater} = \textrm{HVACSSM}_\textrm{AuxHtr}(\overline{P}_\textrm{ice,waste heat}) * t_\textrm{cycle}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textbf{\textrm{FC\_BusAux\_AuxHeater}} = \textrm{E\_auxHeater} \cdot \textrm{NCV}_\textrm{main fuel}" title="\textbf{\textrm{FC\_BusAux\_AuxHeater}} = \textrm{E\_auxHeater} \cdot \textrm{NCV}_\textrm{main fuel}" /></p> +</div> +<div id="waste-heat-recovery-systems" class="section level4"> +<h4>Waste Heat Recovery Systems</h4> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAS4AAAAaBAMAAAD78qx/AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIondmbvvMs0QZnarVESUG+88AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADSklEQVRIDc2XP0wTcRTHv23B9g6ubTo4uIAFB1mKLsappCEmJDYlDg440MlBE1ojMJlASCDExepg1ER7iyEQDV1EIppWB10MNDHGMKCNMZo4tQTRQuF879e79qA4tDSmr7n7/d57v9/3Pr9/dylweDuiXRamadru4dXqpyBr/UWxYyu/6qdaB6XBLV1ECrnrIFc3ibuagaP01EvU4w90XuR1kG/dREch45x63bGR9viDdyKBzpMHPWUkvz/q1LqNEPXgju/Yr1HRPihG6QPs4ywTT0DJAR5Ys8A5gBILogUnTSZVcMG3Ycpzx7EMB2pU/A4pJh6PdlZpHodlG1g1uBYAVz8n9lsll0NLmxpRx9Yw+zUqvkRzgrkkzLKKnIcyDagmLls3J/ZbJZcUoYkuGXE1iTY1Kg7AFWWuFsRYU9qCPO/ew0ULcYBVcuHLH1O70nzVqJjDKKn5cE/XnIQSTzjd5fl6dElkRnJPgw+eZCDP9cHZ9Ry5uWUThag2ae3lEHG1pYVbi+LSWvjrdBdxeVd0ySRWHeMyYF33eqeA5NqiKjLSNkZVZxheXMdHOEAux8+/J3sjWgB+05s+ObckziNJVKfIWs1qawoDVPHByj5ZW1qV88yVFeeRhn26mNhFPCPlpRxs0SEcjZErFr6YLN7bNsuhZClRnaLlDHV8jNYEeLf6oNCPzZZSpa1rZi79CTm43FJe2Vn78In3FrllCNGTDo2W0ms8S4ZVp2gfon5XcCRKa8NcpEoX8ey4Manu4XJzXIBIeTkLOP/FhZW0aMq3Mlf1ipYcxmBNkQpzfaaLXq8F0kyYueYzIsETJOUtxHT/NxDT52vP/sKEaCluZa4qFam3PYtnTof6UHBJp4qiV2mPRUtcIfIShMnzFad1RACK+wRkN7vFDuU7bdaS8Uh1q14xLE3ItmgCnkjA+zbr0rQscJyOA2Dh72Mk6OkNQhlIU2aj8CO0fKMQlV/MQO6aGWbXeLBRLhoV+j76g+TUqvhtbXhWeVUx7rJ8VTXlbFXN/1vj0XoNsL7EFj7hDWg21YBqNyoNUV4wKOQeo9YIZVO/TiGFMo3AYzDoL4nbPwc3jVAjlE7646jbeiPwGAwtvSXrM2KHLf8CDcaLgaDtrbwAAAAASUVORK5CYII=" alt="\textrm{E\_WHR\_mech} = \sum{\textrm{P\_WHR\_mech} \cdot dt}" title="\textrm{E\_WHR\_mech} = \sum{\textrm{P\_WHR\_mech} \cdot dt}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPgAAAAaBAMAAABoc4yxAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIondmbvvMs0QZnarVESUG+88AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADIElEQVRIDb2WP2gTURzHv7k0Xu/SS0IGRxvTIugSdSkIUglVECzp5FAH4yKoYCJWV4PQUlwapIiL9oYWaSskgxbRSurSqWikLh2iQcS1Sa1Ca+v5e3f3cpfUiyQp+YXc+/N73+/n3rt7LwGaisSvqywSmqYVmzJoRZT5aahdz7WhVnya0no01dRNlpsyaEUkJSrMTy34BPujvRfZ0skTD9CzU/SNvevZzAf7Bx8mor1HK8Z3KjCja/0HTwlpSEc2wxeS//UQLwe4CGY9Aogp1jmVhUKIIIQScA6gxII1ugYuaGeYxgxSiH9Yvb6H37LDd0hpnYEQE3pScP0G1jh8AfAPsYQeNXBM7PIMld44sMza9T3s8EV4sgwuYZYJ5S0o44Bqg7uPs4QetfBHWoCnDHgsTe36Hnb4MPxJBveC6SBtQ84EquC0ijxq4YqW4inbzOt72OFl3CV9BI9Nl1EoU1lfwJr500tGZm46jVo4YhtVcJfxGBw95LnzsOBvCvGv48cIHv5guuSw1pmSAWEjHB4DcoVXqp4RQuJxHd6xwiJkDHfbzjbv9vwiLSKFkwfCuG3BPWrXEoZpeASCLgO686q8xeAl/W2nF+6knpkKoG/vzF3aNVNHy04KI5w8pDLcSTZzVx8NnEFXVneMQKEPC/eSKm3fssNzev+XQuH0XjgyO3qWXSy4k4eyW1jNM7h4k8Zfx4GkL04V2s6g6VIIuwGMqlVwGg1k2GXPM0eXtdksuJOHzNaGP3NXGfcgLFEPg3+mL90UTSWXtcMzRdbfTWeYDq965ugMsaQeFtzJw7UFpDlcLOGlr1N9osOlE4bHDQIlK/AYtbJ0L+gI4eM/Zr5iiNiVvSVmOHggCiXA4YhL92V3MotgIhpeLvk1jfSH6YiiV4Kd7YnB4MAglOE8y8zPJUd2itzeLL2pSodECmrQj7uzh/z6mRh7b0q+FUZmlbeBikHDldV0w5J9E4hX9s2qcaODxcY1+6Y4xZ34EcXbbSg9IQ6Z5pX2lWc5alL/E8FbbSnNfSYdmtHibQHaIeu0p80I2fvbUn8xUIkWtvtfRF41xgceYsIAAAAASUVORK5CYII=" alt="\textrm{E\_WHR\_el} = \sum{\textrm{P\_WHR\_el} \cdot dt}" title="\textrm{E\_WHR\_el} = \sum{\textrm{P\_WHR\_el} \cdot dt}" /></p> +<p><br /><img style="vertical-align:middle" src="data:image/png;base64,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" alt=" +\textrm{E\_WHR\_el\_mech} = \begin{cases} +\textrm{E\_WHR\_el} / \textrm{AlternatorEfficiency} & if conventional truck \\ +\textrm{E\_WHR\_el} / \eta_{\textrm{EM}_\textrm{chg}} & if bus with ES connected to REES and smart alternator \\ +\textrm{E\_WHR\_el} / \textrm{BusAlternatorEfficiency} & otherwise +\end{cases} +" title=" +\textrm{E\_WHR\_el\_mech} = \begin{cases} +\textrm{E\_WHR\_el} / \textrm{AlternatorEfficiency} & if conventional truck \\ +\textrm{E\_WHR\_el} / \eta_{\textrm{EM}_\textrm{chg}} & if bus with ES connected to REES and smart alternator \\ +\textrm{E\_WHR\_el} / \textrm{BusAlternatorEfficiency} & otherwise +\end{cases} +" /><br /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\textbf{\textrm{FC\_WHR}} = - (\textrm{E\_WHR\_mech} + \textrm{E\_WHR\_el\_mech}) \cdot k_\textrm{engline}" title="\textbf{\textrm{FC\_WHR}} = - (\textrm{E\_WHR\_mech} + \textrm{E\_WHR\_el\_mech}) \cdot k_\textrm{engline}" /></p> +</div> +<div id="hybrid-vehicles-reess-soc-correction" class="section level4"> +<h4>Hybrid Vehicles: REESS SoC Correction</h4> +<p>If the REESS Soc at the end of the simulation is higher than the initial SoC the correction is done according to:</p> +<p><br /><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQkAAAAtCAMAAACK/G7CAAAANlBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHL6OuAAAAEXRSTlMAMs3d74lURKsiu3ZmEJlwQDoFlAYAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAYZSURBVGgF7VqLcusoDAXbvLHv8v8/u0fiacfOnW67iTsTZloECCEdC/GKEO9I61RGdWpOm1KbX3zVY1ULV6kVNWP7SAuh0Ss6DZ5OVRGcS59Iws2TSrFqqBJTsmKDUq4Ki6OWsX2gtUKbnCGmU8Q+JLMMhZuSa/BNy2KdIMtKCrkxsZuM7QM98/dWQKJTtX/JlT1U3LAYhGxOwdbBrNhduSAxz6T62D7QiR3GAYlOHSydmt8dGu5TXIMQzSnYOlR0IERGYk2oLUiU9oF38twBeHTqYGGSh4r7FcnC5hRkXQugWVdCYjWegWCfqO0Dr0zJZjfq1N5SA8EyZiH7ltuUyCW6U6iklM1Rs2oYktah+vbYPtLSppQ4uHSqCuBceSGlbPFo13aTQmC/rk7BHj+ESyiZZ8ecK8f2kQaf3Gq06ZSb65yYlDRipWX2mORsMKkq37H1deXsElAlfy62jrcFTYWMRMiOMrYPNAdMsWHt7RQJkAus5JR8pUpFzza0vB8IkV1CCJM/KFtHSvZIX5FgG8f2gc7zX2J56VQ3FZRJEvPjPBES70/VJapTVOt01y4jERPXjO0DnTdiBluGTu2MIxgwC6TQMUZh5qg3YB2Q1AokaIbUSubYdX5JQWnEMU6BnaJYt87Zy0mHjeeFwyqK7z22D3QOlh4+3qmd/hRxETO0BCJ2FZuiFWqdeZ0in+A/riwcQk7zskzTtCxLiVtqmicsYWbrkp313kc51OS2E9be6ZxCxG9pxrmCDxnKLmR9blDbtnHg8FGP7SMt1KqC2miyd2o3IG09ddBCWWOsESRxKWBkFAgNriwc6K0TfwOz8O5ULxRZhZ5S36w6dlQ11PCgZ6w7be5Q2HIcyUYLGxXQaz7BSBQOMjojIQzNOJPyPh5ER8LyvlfYXkM2nrJSw60S+b5z5fOX8LpHonBA64qEIHuXukQL3+2e84JH8WlIp6xD+01IrXREDLArNmzCT5OVVMBfq2QO0paRcIAOfhSKf6A6drttmjRth3Zr8DkrCbxvAiaw/1I/RiICCSSf8kQgutttKJTNfHUijLfW09p/zkod75soSIhs6ZmSQGKa82WAqPmBTy+ExQI5gYLnSsH1jHWzLe030Ad5byuqoCMtCOeJfGLdMlJTQeSB0ygPtxBr9hmLKXfJ+tD311Tw7KAAiqROZ0eeJ25JTieeZTgUXrA+WG2wEymJ5hT51j0TlGMkykEGEYFPiqg23b/LwqoGJDYsomesD0j8poqMRNFYpbqRtD1i0sUpEk6HLvGCSrMDTvHAevs4Uay8yHZIwD4+uTubrec+M1+kuYWPAcDA1cvWR9aLMX5DNc4dWDsm2FeSUx7njo0PRGVGe6exJck8miZ93sHi1NBZa/dP/kHgg8AHgQ8CHwT+VwRiiGuMw87lC6N9p+8XhnkNqzNywbZFX58Or/X4Tt9rqe9q0SLSJUD0cltiDNYLt+UHX5PqY8BRt/q00/qiSwyKjgZNSiNwZIgRTSU7yrpTGVfOuHpWuHAnrbB7lygg6fzsQ+Qh9aed2pcePcRGO/8mpRIr3TZNa8kOku5V5Bcr/CNrcCWPjTwbscpLJLr+Y18R6IzcpFRCEhJxLVnvej/KkcH0j1Tn85yTuJIHJH9HYtfX0MtHl9LELSQNt7M5I/KmKdKXpH+InIHjppN0b9yQcDxrTrUf+uro+dzUpDTC4SEFh6SSQc4TgaejvKoy0IGXIgN9RNBSOImfC8m1+cT1srLrKxa+ca5SmjiIl/n1vGRPbjFfZfT1ODTfSXUKEoSEivjAdXZcI8ECW9+ZnKJJqYShE3WMJeMefxHIPG/6x/M9B3vcnuM3D44e4YCE0riK9pp+Wxf0xs8MRxW5L5s94bdbZe2AlCqO7902VzKW+FzgcYCXlmm+054gRrwM4wFWCivwShP+8CWId3gMXy2vg49q1b5YQH10XUoVZyAVHlYy/qnRc4GPQ7ywJpRrn+OQtCNaaVoDqdhvEndsV313TK3AEp8LbLy3IhAvnJs1TZbJ0lPmtxMk/vOjAr+t0VcFwCUwQb7a6wn/jwt8MtaPNrlo9MUc+m/jnAn8FwdOQQT6bjmOAAAAAElFTkSuQmCC" alt=" +\textbf{\textrm{FC\_SoC}} = -\frac{\Delta\textrm{E\_REESS} \cdot k_\textrm{engline}}{\eta_{\textrm{EM}_\textrm{chg}} \cdot \eta_{\textrm{REESS}_\textrm{chg}}} +" title=" +\textbf{\textrm{FC\_SoC}} = -\frac{\Delta\textrm{E\_REESS} \cdot k_\textrm{engline}}{\eta_{\textrm{EM}_\textrm{chg}} \cdot \eta_{\textrm{REESS}_\textrm{chg}}} +" /><br /></p> +<p>If the REESS Soc at the end of the simulation is lower than the initial SoC the correction is done according to:</p> +<p><br /><img style="vertical-align:middle" src="data:image/png;base64,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" alt=" +\textbf{\textrm{FC\_SoC}} = - \Delta\textrm{E\_REESS} \cdot k_\textrm{engline} \cdot \eta_{\textrm{EM}_\textrm{dischg}} \cdot \eta_{\textrm{REESS}_\textrm{dischg}} +" title=" +\textbf{\textrm{FC\_SoC}} = - \Delta\textrm{E\_REESS} \cdot k_\textrm{engline} \cdot \eta_{\textrm{EM}_\textrm{dischg}} \cdot \eta_{\textrm{REESS}_\textrm{dischg}} +" /><br /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\eta_{\textrm{REESS}_\textrm{chg}} = \frac{\textrm{E\_REESS\_INT\_CHG}}{\textrm{E\_REEES\_T\_CHG}}" title="\eta_{\textrm{REESS}_\textrm{chg}} = \frac{\textrm{E\_REESS\_INT\_CHG}}{\textrm{E\_REEES\_T\_CHG}}" /></p> +<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\eta_{\textrm{REESS}_\textrm{dischg}} = \frac{\textrm{E\_REESS\_INT\_DISCHG}}{\textrm{E\_REEES\_T\_DISCHG}}" title="\eta_{\textrm{REESS}_\textrm{dischg}} = \frac{\textrm{E\_REESS\_INT\_DISCHG}}{\textrm{E\_REEES\_T\_DISCHG}}" /></p> +</div> +</div> +<div id="corrected-total-fuel-consumption" class="section level3"> +<h3>Corrected Total Fuel Consumption</h3> +<p>The final fuel consumption after all corrections are applied is calcualted as follows:</p> +<p><br /><img style="vertical-align:middle" src="data:image/png;base64,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" alt=" +\begin{align*} +\textrm{FC\_FINAL} =\;& \textrm{FC\_ModSum} \;+ \\ + & \textrm{FC\_ESS} \;+ \\ + & \textrm{FC\_DCDCMissing} \;+ \\ + & \textrm{FC\_BusAux\_PS} \;+ \\ + & \textrm{FC\_BusAux\_ES} \;+ \\ + & \textrm{FC\_WHR} \;+ \\ + & \textrm{FC\_BusAux\_AuxHeater} \;+ \\ + & \textrm{FC\_SoC} \\ +\end{align*} +" title=" +\begin{align*} +\textrm{FC\_FINAL} =\;& \textrm{FC\_ModSum} \;+ \\ + & \textrm{FC\_ESS} \;+ \\ + & \textrm{FC\_DCDCMissing} \;+ \\ + & \textrm{FC\_BusAux\_PS} \;+ \\ + & \textrm{FC\_BusAux\_ES} \;+ \\ + & \textrm{FC\_WHR} \;+ \\ + & \textrm{FC\_BusAux\_AuxHeater} \;+ \\ + & \textrm{FC\_SoC} \\ +\end{align*} +" /><br /></p> </div> <div id="engine-line-approach" class="section level3"> <h3>Engine-Line Approach</h3> -<p>The total fuel consumption is corrected in a post-processing step according to the <em>engine-line</em> approach. Therefore, for every engine operating point where the engine is switched on and has a positive fuel consumption the fuel consumption is plotted over the engine power. The slope (k) of the linear regression of the fuel consumption is used to compute the additional fuel that is needed for the energy demand during engine-off periods and engine starts.</p> +<p>The total fuel consumption is corrected in a post-processing step according to the <em>engine-line</em> approach. Therefore, for every engine operating point where the engine is on and has a positive fuel consumption the fuel consumption is plotted over the engine power. The slope (k) of the linear regression of the fuel consumption is used to compute the additional fuel that is needed for the energy demand during engine-off periods and engine starts.</p> <div class="figure"> -<img src="data:image/png;base64,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" /> +<img src="data:image/png;base64,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" /> </div> -<p><img style="vertical-align:middle" src="data:image/png;base64,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" alt="\Delta FC = k * (E_\textrm{aux,ICE,off} + E_\textrm{ICE,start} - E_\textrm{WHR,corr}/\eta_\textrm{alternator}) + k * (E_\textrm{ES,mech,corr} + E_\textrm{PS,corr})" title="\Delta FC = k * (E_\textrm{aux,ICE,off} + E_\textrm{ICE,start} - E_\textrm{WHR,corr}/\eta_\textrm{alternator}) + k * (E_\textrm{ES,mech,corr} + E_\textrm{PS,corr})" /></p> -<p>The fuel consumption for the aux heater is only added for the main fuel:</p> -<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATUAAAAQCAMAAABA1xgHAAAAM1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxgEwMAAAAEHRSTlMAEM2JZna77zJEVN2ZIqtO/CVJ+QAAAAlwSFlzAAAOxAAADsQBlSsOGwAAA7hJREFUWAm1WNnCsyoMZFX2n/d/2pMNRVs93T4vxMaQYcIQsErRpQ23dLd5LdaWpTt+55v1XlU/ufzwkdFsW8sPg2Iom3uFRpe+RA6tNyY+9xbQ6Htmluzx3t1KhrjXslBrEzYuE6blhh1+ehe0+OusKS8T0WS4MxO7inG8/ICS9suIgr07yyribNisKWDs1PzBTdDUz7XsODVaxHRg4oSOY3Yf0fIqTGILncSrIkR0pHIMOq/hj0AuOg00Rcq+cPrEHELtGDPiOj0zicyrfgGqYZonsXmcB1iWgKaHEEB0hP37G6F9XlsOA+LZFhPENFhqWMMnJrVz3Tl0f+8Hxp3E1lBWnCTbv1Dwa4PAsla/qC4zylxmMFsJh89ZOzOhtZVYhnOIl59RarPYVmOtYazM+8LLoW4dS9uuSbjrAmjT79sQdy9dUIuqu2qRAS4VtpyZ4E7BxO9i3rzzpKdNbCRey2Lv/0OnltWpWqaieIPz9FXFIhrkaPDg8U78sHjrzBap4lNZR1k7M0GJszJOoOawzCG1thyKX+DDxMi4EX3T9iJTtqfj0HMHitgpHFYGGNIJefd/eCI0dH8O8FZ8t1dhkVjo8YJJyRdzdR66dfpYpQpNDEsN6r+kiMqasMtDa+6iAoQMng9ZW87QD8naDAPtYjd7Iz5qze/IUmKaCOrMBDahp1LbBjYeOEnjF7RkGFKDHYcls45MgYeX8wZx8gk6BJPgDKeSKWppVe2sknMwreQTjYVHMsSc7Bjd07o20KDMfBmf69oAk5z4sVoOTIBZ6hYlFLNLNsW04LZB/GABorGIRsNSknBmRpw1m4JcjCB7MkTEi+s0yxxkBXnFVQ5NNTSusEKy8DQZoE40rdgHv1bE0Ly+E95AszBV38fnaaeBy8rUcvY8MgGPUcYLAMPZzUOSBB8WIBi3b0yUFnMWRqS1Pl3Qzy69TWJTvsBHqCxPHeBDQbKmHMlw05ptMTYAIB/Mmhja83pFzMDJdPjktS3TCefr+FRxKHRZMwPv32kzExinrCKkA+dThxpl/C1LPMY9a8KIsibjf6FpTk9Zi7RdbVkrvDTYB7JWh+FOaUfQv45/RJNfIgLMmuBfZk0YvZc1B9O26uSTwo2tUgrpkXYDlG+t4lNiDWxQ/NfC0wGfjH8d/wR3yppV29jHimQPTCtzFkbvZU23lHyptUTYbfH/g8VEOqrxeQ2KqlPiE3BayBByudh9H0j8dfwHQDQE07TvqS6mMv4/04aROoBDhYWDnIUR9PgPgKslRcYEdVgAAAAASUVORK5CYII=" alt="\Delta FC_\textrm{auxHeater} = E_\textrm{auxHeater} * NCV_\textrm{main fuel}" title="\Delta FC_\textrm{auxHeater} = E_\textrm{auxHeater} * NCV_\textrm{main fuel}" /></p> -<p><img style="vertical-align:middle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAVgAAAATCAMAAADiWuVpAAAAM1BMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxgEwMAAAAEHRSTlMAid3vmbtmVHZEMhAiq81OASNrqQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAA3BJREFUWAndWItyrSAMDIq8BOr/f+1NAiLqUanamfY608ojbpJ1CXgA8BJdL4WQw6SoB6MJwhjwhnvf/Pcm1qnrMVbTd7w+Bqj8HzWHgWeEppvqLN1EulHzW9ebWGeORZZBsrnh9THAWXR5bkritA77oht51E4ND34weRNrgU8xLX1cVkNfdS+9PgaonDU33USMAlj0riafn6uXWh5quL2JVblTvIqqAQOukuy118cAle/mpiFxYuRI6ZhfPQ6I5udrwzexKtwtLyOusUqy114fA1TBNDcDiTPxKKbdmmmGYcM3sSrPW16odlWSvfb6GKAKprnZRyFiKrNd2sZaHpWhXJW472Fd+tvwQoKtJXvt9THAZYh7Az9hGRCpzE4VRwDG6E1tcxdnhfew5KrGb3gxvK6KZI+9lmwfAxQkL3sFXlYVvkxtGopKbDrCwmKORy+jwIWNsdwwvZl+D6scM3llxEjLY37rSbAAMR8MDr1ydI8BNjla8urqMwkZ6KTM2pYLVB7o5tgV7mRhbwsXxL6HVYjlyNaCS4LFDTfr4NDrkuZjgAXKddjeETvsyepnMtHe5AXoUbA2CiUi2E5piYI2mkhdiP1YY+9gkQOhrR5wfWulqXxaoedIUkIrXmbBFskeeU3P8v+bAJy0ixqP96CjhCF4WIjVSs3EEFkUPg7YTgtKggtUCSEyy5YrAyqWdCMF3/A9ofwXYssjVeMeFjoAPD7nyuMkePRKf8u14kVoly/Dkj32+hggJ40yw9wxJCLM9UifwL7DnT6MkGxoeeeBYEbsiGEqtYviMBJ/KEgfCTOxCRZGhx9lp8TexJLoAOu8MsBvegKDTJ+Ugqm6MKsTrwfEVs9PFwAp6cyA4pddFCuCtQFXMdsQsXkgoPnptSY2qPGK2BO0MywiFgXQTOyJm8OpleQPrXYTOelMrI20dRdiJR/6INlggn4e2JfbNTCRgS805a0kZj9ynV1btfWOsGhtzMQKPoTYwGWAwy/Y48PvFrgHkJM2Gugo4Fla3OTNi1a+94UY79LAx02/ZIIN10kQvXUxjGbSY9DayC/s1Dat7UOsAT/6kwM/RA/aKEF7mNHoshX85+xS0t5LiwcQ+tlviJaPsOkci3uugmzjSK48gLmmUvpzcbUg/wL6WsL8ezbnHxx/L5/fEvH/Kth/erIog+hmXIUAAAAASUVORK5CYII=" alt="FC_\textrm{final} = FC_\textrm{final,mod} + \Delta FC + \Delta FC_\textrm{auxHeater}" title="FC_\textrm{final} = FC_\textrm{final,mod} + \Delta FC + \Delta FC_\textrm{auxHeater}" /></p> </div> </div> <div id="engine-waste-heat-recovery-systems" class="section level2"> @@ -5488,7 +5612,7 @@ CycleTime,UnknownCycleName,3600</code></pre> <td>[kW]</td> <td>Auxiliary Supply Power. Can be defined multiple times with different Identifiers. The supply power input for each auxiliary defined in the <a href="#job-file">.vecto file</a> with the corresponding ID. ID’s are not case sensitive and must only contain letters and numbers [a-z,A-Z,0-9]. Must be >= 0 kW.</td> </tr> -<tr class="even"> +<tr class="odd"> <td><em>P_PTO</em></td> <td>[kW]</td> <td>Auxiliary power applied for PTO activation mode 2 (PTO active during drive, PTO demand defined in cycle)</td> @@ -5947,7 +6071,7 @@ CycleTime,UnknownCycleName,3600</code></pre> <h2>Modal Results (.vmod)</h2> <p>Modal results are only created if enabled in the <a href="#main-form">Options</a> tab. One file is created for each calculation and stored in the same directory as the .vecto file.</p> <p>In Vecto 3 the structure of the modal data output has been revised and re-structured. Basically for every powertrain component the .vmod file contains the power at the input shaft and the individual power losses for every component. For the engine the power, torque and engine speed at the output shaft is given along with the internal power and torque used for computing the fuel consumption. See <a href="#powertrain-and-components-structure">Powertrain and Components Structure</a> for schematics how the powertrain looks like and which positions in the powertrain the values represent.</p> -<p>Every line in the .vmod file represents the simulation interval from time - dt/2 to time + dt/2. All values represent the average power/torque/angular velocity during this simulation interval. If a certain power value can be described as function of the vehicle’s acceleration the average power is calculated by <img style="vertical-align:middle" src="data:image/png;base64,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" alt="P_{avg} = \frac{1}{simulation interval} \int{P(t) dt}" title="P_{avg} = \frac{1}{simulation interval} \int{P(t) dt}" />. <strong>Note:</strong> Columns for the torque converter operating point represent the torque/angular speed at the end of the simulation interval!</p> +<p>Every line in the .vmod file represents the simulation interval from time - dt/2 to time + dt/2. All values represent the average power/torque/angular velocity during this simulation interval. If a certain power value can be described as function of the vehicle’s acceleration the average power is calculated by <img style="vertical-align:middle" src="data:image/png;base64,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" alt="P_{avg} = \frac{1}{simulation interval} \int{P(t) dt}" title="P_{avg} = \frac{1}{simulation interval} \int{P(t) dt}" />.</p> <p><strong>Note:</strong> Columns for the torque converter operating point represent the torque/angular speed at the end of the simulation interval!</p> <div id="quantities" class="section level3"> <h3>Quantities:</h3> @@ -6043,20 +6167,170 @@ CycleTime,UnknownCycleName,3600</code></pre> <td>Engine’s transient maximum power (see <a href="#engine-transient-full-load">transient full load</a>)</td> </tr> <tr class="even"> +<td>P_ice_full_stat</td> +<td>[kW]</td> +<td>Engine’s stationary maximum power</td> +</tr> +<tr class="odd"> <td>P_ice_drag</td> <td>[kW]</td> <td>Engine’s drag power</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_ice_inertia</td> <td>[kW]</td> <td>Power loss/gain due to the engine’s inertia</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_ice_out</td> <td>[kW]</td> <td>Power provided at the engine’s output shaft</td> </tr> +<tr class="even"> +<td>P_REESS_T</td> +<td>[kW]</td> +<td>Electric power provided at the battery’s connector</td> +</tr> +<tr class="odd"> +<td>P_REESS_int</td> +<td>[kW]</td> +<td>Internal battery power</td> +</tr> +<tr class="even"> +<td>P_REESS_loss</td> +<td>[kW]</td> +<td>Losses of the battery due to its internal resistance.</td> +</tr> +<tr class="odd"> +<td>P_REESS_charge_max</td> +<td>[kW]</td> +<td>Maximum power the battery can be charged with</td> +</tr> +<tr class="even"> +<td>P_REESS_discharge_max</td> +<td>[kW]</td> +<td>Maximum power the battery can provide</td> +</tr> +<tr class="odd"> +<td>REESS SOC</td> +<td>[%]</td> +<td>The battery’s current state of charge</td> +</tr> +<tr class="even"> +<td>U_REESS_T</td> +<td>[V]</td> +<td>Voltage at the battery’s connector</td> +</tr> +<tr class="odd"> +<td>U_0_REESS</td> +<td>[V]</td> +<td>Battery’s internal voltage</td> +</tr> +<tr class="even"> +<td>I_REESS</td> +<td>[A]</td> +<td>Current charging/discharging the battery.</td> +</tr> +<tr class="odd"> +<td>i_<POS}-em</td> +<td>[-]</td> +<td>Ratio between drivetrain and electric motor shaft</td> +</tr> +<tr class="even"> +<td>P_<POS>_out</td> +<td>[kW]</td> +<td>Power at the electric machine’s output shaft (drivetrain)</td> +</tr> +<tr class="odd"> +<td>P_<POS>_mech</td> +<td>[kW]</td> +<td>Mechanical power the electric machine applies to the drivetrain. Positive values mean that electric energy is generated while negative values mean that the electric machine drives the vehicle.</td> +</tr> +<tr class="even"> +<td>P_<POS>_in</td> +<td>[kW]</td> +<td>Power at the electric machine’s input shaft (drivetrain)</td> +</tr> +<tr class="odd"> +<td>P_<POS>_transm_loss</td> +<td>[kW]</td> +<td>Losses of the transmission stage inside the electric motor component</td> +</tr> +<tr class="even"> +<td>P_<POS>-em_mech</td> +<td>[kW]</td> +<td>Power at the shaft of the electric motor at position <em>POS</em></td> +</tr> +<tr class="odd"> +<td>P_<POS>-em_inertia_loss</td> +<td>[kW]</td> +<td>Inertia loses of the electric machine</td> +</tr> +<tr class="even"> +<td>P_<POS>-em_mech_map</td> +<td>[kW]</td> +<td>Mechanical powerthe electric motor at position <em>POS</em> applies for driving or recuperation, including the electric motor’s inertia</td> +</tr> +<tr class="odd"> +<td>P_<POS>-em_loss</td> +<td>[kW]</td> +<td>Losses in the electric machine due to converting electric power to mechanical power</td> +</tr> +<tr class="even"> +<td>P_<POS>-em_el</td> +<td>[kW]</td> +<td>Electric power generated or consumed by the elctric machine</td> +</tr> +<tr class="odd"> +<td>P_<POS>_loss</td> +<td>[kW]</td> +<td>The total sum of losses of the electric motor at position <em>POS</em>. Calcualted as the difference of mecanical power applied at the drivetrain and the electrical power drawn from the REESS.</td> +</tr> +<tr class="even"> +<td>n_<POS>-em_avg</td> +<td>[rpm]</td> +<td>Angular speed of the electric motor at position <em>POS</em></td> +</tr> +<tr class="odd"> +<td>T_<POS>-em</td> +<td>[Nm]</td> +<td>Torque at the shaft of electric motor at position <em>POS</em>. Positive values mean that the electric motor acts as generator, negative torque values mean that the electric motor propels the vehicle</td> +</tr> +<tr class="even"> +<td>T_<POS>-em_map</td> +<td>[Nm]</td> +<td>Torque internal torque of the electric motor at posision <em>POS</em>. Takes into account the electric motor’s intertia. Positive values mean that the electric motor acts as generator, negative torque values mean that the electric motor propels the vehicle</td> +</tr> +<tr class="odd"> +<td>T_<POS>-em_drive_max</td> +<td>[Nm]</td> +<td>Maximum torque the electric machine can apply to propel the vehicle. This already considers the maximum current the battery can provide</td> +</tr> +<tr class="even"> +<td>T_<POS>-em_gen_max</td> +<td>[Nm]</td> +<td>Maximum torque the electric machine can apply to generate electric power. This already considers the maximum charge current the battery can handle.</td> +</tr> +<tr class="odd"> +<td>P_<POS>-em_drive_max</td> +<td>[kW]</td> +<td>Maximum power the electric motor can provide to drive the vehicle. This already considers the maximum electric power the battery can provide.</td> +</tr> +<tr class="even"> +<td>P_<POS>-em_gen_max</td> +<td>[kW]</td> +<td>Maximum power the electric machine can generate. This already considers the maximum charge power the battery can handle.</td> +</tr> +<tr class="odd"> +<td>EM_OVL-<POS>-em</td> +<td>[%]</td> +<td>Used capacity of the thermal overload buffer of the thermal derating model</td> +</tr> +<tr class="even"> +<td>EM_<POS>_off</td> +<td>[-]</td> +<td>Indicates if the electric motor at position <em>POS</em> is energized or not.</td> +</tr> <tr class="odd"> <td>P_clutch_loss</td> <td>[kW]</td> @@ -6078,121 +6352,132 @@ CycleTime,UnknownCycleName,3600</code></pre> <td>Power loss in the torque converter</td> </tr> <tr class="odd"> -<td>P_aux</td> +<td>P_aux_mech</td> <td>[kW]</td> -<td>Total power demand from the auxiliaries</td> +<td>Total power demand from the mechanical auxiliaries</td> </tr> <tr class="even"> +<td>P_aux_el</td> +<td>[kW]</td> +<td>Total power demand from the electric auxiliaries connected to the REESS</td> +</tr> +<tr class="odd"> <td>P_gbx_in</td> <td>[kW]</td> <td>Power at the gearbox’ input shaft</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_gbx_loss</td> <td>[kW]</td> <td>Power loss at the gearbox, interpolated from the loss-map + shift losses + inertia losses</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_gbx_shift</td> <td>[kW]</td> <td>Power loss due to gearshifts (AT gearbox)</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_gbx_inertia</td> <td>[kW]</td> <td>Power loss due to the gearbox’ inertia</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_ret_in</td> <td>[kW]</td> <td>Power at the retarder’s input shaft. P_ret_in = P_gbx_in - P_gbx_loss - P_gbx_inertia</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_ret_loss</td> <td>[kW]</td> <td>Power loss at the retarder, interpolated from the loss-map.</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_angle_in</td> <td>[kW]</td> <td>Power at the anglegear’s input shaft. Empty if no Anglegear is used.</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_angle_loss</td> <td>[kW]</td> <td>Power loss at the anglegear, interpolated from the loss-map. Empty if no Anglegear is used.</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_axle_in</td> <td>[kW]</td> <td>Power at the axle-gear input shaft. P_axle_in = P_ret_in - P_ret_loss ( - P_angle_loss if an Angulargear is used).</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_axle_loss</td> <td>[kW]</td> <td>Power loss at the axle gear, interpolated from the loss-map.</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_brake_in</td> <td>[kW]</td> <td>Power at the brake input shaft (definition: serially mounted into the drive train between wheels and axle). P_brake_in = P_axle_in - P_axle_loss</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_brake_loss</td> <td>[kW]</td> <td>Power loss due to braking.</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_wheel_in</td> <td>[kW]</td> <td>Power at the driven wheels. P_wheel_in = P_brake_in - P_brake_loss</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_wheel_inertia</td> <td>[kW]</td> <td>Power loss due to the wheels’ inertia</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_trac</td> <td>[kW]</td> <td>Vehicle’s traction power. P_trac = P_wheel_in - P_wheel_inertia</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_slope</td> <td>[kW]</td> <td>Power loss/gain due to the road’s slope</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_air</td> <td>[kW]</td> <td>Power loss due to air drag.</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_roll</td> <td>[kW]</td> <td>Rolling resistance power loss.</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_veh_inertia</td> <td>[kW]</td> <td>Power loss due to the vehicle’s inertia</td> </tr> +<tr class="even"> +<td>n_gbx_out_avg</td> +<td>[rpm]</td> +<td>Average angular speed at gearbox out shaft</td> +</tr> <tr class="odd"> -<td>P_busAux_ES_HVAC</td> -<td>[kW]</td> -<td>(Average) electric power demand for the HVAC system (mainly ventilation power) <em>(only in .vmod file if bus auxiliaries are used)</em></td> +<td>T_gbx_out</td> +<td>[Nm]</td> +<td>Torque at gearbox out shaft</td> </tr> <tr class="even"> -<td>P_PTO_RoadSweeping</td> -<td>[kW]</td> -<td>Power demand from the PTO in PTO mode 2. Only in engineering mode if PTO mode 2 is activated.</td> +<td>T_gbx_in</td> +<td>[Nm]</td> +<td>Torque at gearbox in shaft</td> </tr> <tr class="odd"> -<td>P_PTO_DuringDrive</td> +<td>P_busAux_ES_HVAC</td> <td>[kW]</td> -<td>Power demand from the PTO cycle in PTO mode 3. Only in engineering mode if PTO mode 3 is activated.</td> +<td>(Average) electric power demand for the HVAC system (mainly ventilation power) <em>(only in .vmod file if bus auxiliaries are used)</em></td> </tr> <tr class="even"> +<td>P_busAux_ES_other</td> <td>[kW]</td> <td>(Average) electric power demand for all other electric consumers (lights, radio, kitchen, …) <em>(only in .vmod file if bus auxiliaries are used)</em></td> </tr> @@ -6257,10 +6542,30 @@ CycleTime,UnknownCycleName,3600</code></pre> <td>Mechanical power demand for the air compressor if no air is produced (compressor is in drag only, used for correcting the total fuel consumption in case of smart pneumatic system) <em>(only in .vmod file if bus auxiliaries are used)</em></td> </tr> <tr class="odd"> +<td>P_DC/DC_In</td> +<td>[kW]</td> +<td>Electrical power at the input (REESS side) of the DC/DC converter. <em>(only applicable in case the electric auxiliaries are connected to the high-voltage REESS, output is delayed by one simulation step)</em></td> +</tr> +<tr class="even"> +<td>P_DC/DC_Out</td> +<td>[kW]</td> +<td>Electrical power at the output (REESS side) of the DC/DC converter. <em>(only applicable in case the electric auxiliaries are connected to the high-voltage REESS, output is delayed by one simulation step)</em></td> +</tr> +<tr class="odd"> +<td>P_DC/DC_missing</td> +<td>[kW]</td> +<td>Electrical power the DC/DC converter could not provide to the low-voltage auxiliaries becuase the REESS was already at its minimum SoC. This column is used in post-processing.</td> +</tr> +<tr class="even"> <td>P_aux_<XXX></td> <td>[kW]</td> <td>Mechanical power demand for every individual auxiliary. Only if the run has auxiliaries. In case of fully electrical auxiliaries for trucks the electrical power demand is converted to mechanical power using the alternator efficiency. For Buses with fully electrical auxiliaries the consumer is connected to the electrical system and thus the according column reports 0 power demand.</td> </tr> +<tr class="odd"> +<td>T_max_propulsion</td> +<td>[Nm]</td> +<td>Maximum allowed propulsion torque at gearbox input shaft</td> +</tr> <tr class="even"> <td>P_WHR_el</td> <td>[kW]</td> @@ -6272,255 +6577,120 @@ CycleTime,UnknownCycleName,3600</code></pre> <td>Power generated by an electric WHR system after applying</td> </tr> <tr class="even"> -<td>P_aux_ESS_mech</td> +<td>P_WHR_mech</td> +<td>[kW]</td> +<td>Power generated by an mechanical WHR system, interpolated from WHR map.</td> +</tr> +<tr class="odd"> +<td>P_WHR_mech_corr</td> +<td>[kW]</td> +<td>Power generated by an mechanical WHR system after applying</td> +</tr> +<tr class="even"> +<td>P_aux_ESS_mech_ICE_off</td> <td>[kW]</td> -<td>Power demand of the auxiliaries considered during engine off periods, multiplied by the engine start/stop utility factor. The final fuel consumption (.vsum) is correctedd for this power demand in a <a href="#engine-fuel-consumption-correction">post-processing step</a>. This power demand has no influence on FC-Map.</td> +<td>Power demand of the auxiliaries ‘missing’ if the ICE is off.T he final fuel consumption (.vsum) is correctedd for this power demand in a <a href="#engine-fuel-consumption-correction">post-processing step</a>. This power demand has no influence on FC-Map.</td> </tr> <tr class="odd"> +<td>P_aux_ESS_mech_ICE_on</td> +<td>[kW]</td> +<td>Power demand of the auxiliaries ‘missing’ in case the ICE would be on during actual ICE off periods. The final fuel consumption (.vsum) is correctedd for this power demand in a <a href="#engine-fuel-consumption-correction">post-processing step</a>. This power demand has no influence on FC-Map.</td> +</tr> +<tr class="even"> <td>P_ice_start</td> <td>[kW]</td> <td>Power demand for starting the engine after an engine-off period multiplied by the engine start/stop utility factor. P_ice_start = <a href="#advanced-driver-assistant-systems-eco-roll-engine-stopstart">E_ice_start</a> / dt. The final fuel consumption (.vmod) is corrected for this power demand in a <a href="#engine-fuel-consumption-correction">post-processing step</a>. This power demand has no influence on FC-Map.</td> </tr> -<tr class="even"> +<tr class="odd"> <td>P_PTO_consum</td> <td>[kW]</td> <td>Power demand from the PTO consumer. Only if the vehicle has a PTO consumer.</td> </tr> -<tr class="odd"> +<tr class="even"> <td>P_PTO_transmission</td> <td>[kW]</td> <td>Power demand from the PTO transmission. Only if the vehicle has a PTO consumer.</td> </tr> +<tr class="odd"> +<td>P_PTO_RoadSweeping</td> +<td>[kW]</td> +<td>Power demand from the PTO in PTO mode 2. Only in engineering mode if PTO mode 2 is activated.</td> +</tr> <tr class="even"> +<td>P_PTO_DuringDrive</td> +<td>[kW]</td> +<td>Power demand from the PTO cycle in PTO mode 3. Only in engineering mode if PTO mode 3 is activated.</td> +</tr> +<tr class="odd"> <td>TCnu</td> <td>[-]</td> <td>Torque converter operating point: speed ratio</td> </tr> -<tr class="odd"> +<tr class="even"> <td>TCmu</td> <td>[-]</td> <td>Torque converter operating point: torque ratio</td> </tr> -<tr class="even"> +<tr class="odd"> <td>T_TC_out</td> <td>[Nm]</td> <td>Torque converter operating point: output torque</td> </tr> -<tr class="odd"> +<tr class="even"> <td>n_TC_out</td> <td>[rpm]</td> <td>Torque converter operating point: output speed</td> </tr> -<tr class="even"> +<tr class="odd"> <td>T_TC_in</td> <td>[Nm]</td> <td>Torque converter operating point: input torque</td> </tr> -<tr class="odd"> +<tr class="even"> <td>n_TC_in</td> <td>[rpm]</td> <td>Torque converter operating point: input speed</td> </tr> -<tr class="even"> +<tr class="odd"> <td>FC-Map<_FuelName></td> <td>[g/h]</td> <td>Fuel consumption interpolated from FC map.</td> </tr> -<tr class="odd"> +<tr class="even"> <td>FC-NCVc<_FuelName></td> <td>[g/h]</td> <td>Fuel consumption corrected for different NCV values in VECTO and VECTO Engine (FC-NCVc = FC-Map * LowerHeatingValueVectoEngine(fuel) / LowerHeatingValueVecto(fuel) )</td> </tr> -<tr class="even"> +<tr class="odd"> <td>FC-WHTCc<_FuelName></td> <td>[g/h]</td> <td>Fuel consumption after <a href="#engine-fuel-consumption-calculation">WHTC Correction</a> (FC-WHTCc = FC-NCVc * WHTCCorrectionFactor(cycle, fuel) )</td> </tr> -<tr class="odd"> -<td>FC-AAUX<_FuelName></td> -<td>[g/h]</td> -<td>Fuel consumption computed by the AAUX module considering smart auxiliaries. (FC-AAUX = FC-WHTCc if the AAUX model is not used, otherwise the fuel consumption as calculated by the AAUX model)</td> -</tr> <tr class="even"> -<td>FC-ESS<_FuelName></td> -<td>[g/h]</td> -<td>Fuel consumption considering engine stop/start not always activated. (FC-ESS = FC-AAUX if the engie is on, FC-ESS = FC(P_aux) * (1 - engine stop/start utility factor) if the combustion engine is off - see <a href="#advanced-driver-assistant-systems-eco-roll-engine-stopstart">Engine Stop/Start</a></td> -</tr> -<tr class="odd"> <td>FC-Final_mod<_FuelName></td> <td>[g/h]</td> <td>Instantaneous final fuel consumption value after all applicable corrections. (FC-Final_mod = FC-ESS)</td> </tr> -<tr class="even"> +<tr class="odd"> <td>EcoRollConditionsMet</td> <td></td> <td>0 if the conditions for switching to eco-roll are <em>not</em> met, 1 if the conditions for eco-roll are met - eco roll is activated after the activation delay (2s in declaration mode)</td> </tr> -<tr class="odd"> +<tr class="even"> <td>PCCSegment</td> <td></td> <td>1 if a PCC segment was identified in the pre-processing (gradient below threshold where vehicle accelerates on its own without engine power) , 0 otherwise</td> </tr> -<tr class="even"> +<tr class="odd"> <td>PCCState</td> <td></td> <td>0: not inside PCC segment, 1: inside PCC segment, 2: PCC use-case 1 active, 3: PCC use-case 2 active</td> </tr> -<tr class="odd"> +<tr class="even"> <td>ICE On</td> <td></td> <td>0 if the combustion engine is switched off (either during stand-still or eco-roll), 1 otherwise</td> </tr> -<tr class="even"> -<td>i_<POS}-em</td> -<td>[-]</td> -<td>Ratio between drivetrain and electric motor shaft</td> -</tr> -<tr class="odd"> -<td>n_<POS>-em_avg</td> -<td>[rpm]</td> -<td>Angular speed of the electric motor at position <em>POS</em></td> -</tr> -<tr class="even"> -<td>T_<POS>-em</td> -<td>[Nm]</td> -<td>Torque at the shaft of electric motor at position <em>POS</em>. Positive values mean that the electric motor acts as generator, negative torque values mean that the electric motor propels the vehicle</td> -</tr> -<tr class="odd"> -<td>T_<POS>-em_map</td> -<td>[Nm]</td> -<td>Torque internal torque of the electric motor at posision <em>POS</em>. Takes into account the electric motor’s intertia. Positive values mean that the electric motor acts as generator, negative torque values mean that the electric motor propels the vehicle</td> -</tr> -<tr class="even"> -<td>T_<POS>-em_drive_max</td> -<td>[Nm]</td> -<td>Maximum torque the electric machine can apply to propel the vehicle. This already considers the maximum current the battery can provide</td> -</tr> -<tr class="odd"> -<td>T_<POS>-em_gen_max</td> -<td>[Nm]</td> -<td>Maximum torque the electric machine can apply to generate electric power. This already considers the maximum charge current the battery can handle.</td> -</tr> -<tr class="even"> -<td>P_<POS>-em_drive_max</td> -<td>[kW]</td> -<td>Maximum power the electric motor can provide to drive the vehicle. This already considers the maximum electric power the battery can provide.</td> -</tr> -<tr class="odd"> -<td>P_<POS>-em_gen_max</td> -<td>[kW]</td> -<td>Maximum power the electric machine can generate. This already considers the maximum charge power the battery can handle.</td> -</tr> -<tr class="even"> -<td>P_<POS>-em_mech</td> -<td>[kW]</td> -<td>Power at the shaft of the electric motor at position <em>POS</em></td> -</tr> -<tr class="odd"> -<td>P_<POS>-em_mech_map</td> -<td>[kW]</td> -<td>Mechanical powerthe electric motor at position <em>POS</em> applies for driving or recuperation, including the electric motor’s inertia</td> -</tr> -<tr class="even"> -<td>P_<POS>-em_el</td> -<td>[kW]</td> -<td>Electric power generated or consumed by the elctric machine</td> -</tr> -<tr class="odd"> -<td>P_<POS>-em_loss</td> -<td>[kW]</td> -<td>Losses in the electric machine due to converting electric power to mechanical power</td> -</tr> -<tr class="even"> -<td>P_<POS>-em_inertia_loss</td> -<td>[kW]</td> -<td>Inertia loses of the electric machine</td> -</tr> -<tr class="odd"> -<td>P_<POS>_in</td> -<td>[kW]</td> -<td>Power at the electric machine’s input shaft (drivetrain)</td> -</tr> -<tr class="even"> -<td>P_<POS>_out</td> -<td>[kW]</td> -<td>Power at the electric machine’s output shaft (drivetrain)</td> -</tr> -<tr class="odd"> -<td>P_<POS>_mech</td> -<td>[kW]</td> -<td>Mechanical power the electric machine applies to the drivetrain. Positive values mean that electric energy is generated while negative values mean that the electric machine drives the vehicle.</td> -</tr> -<tr class="even"> -<td>P_<POS>_loss</td> -<td>[kW]</td> -<td>The total sum of losses of the electric motor at position <em>POS</em>. Calcualted as the difference of mecanical power applied at the drivetrain and the electrical power drawn from the REESS.</td> -</tr> -<tr class="odd"> -<td>P_<POS>_transm_loss</td> -<td>[kW]</td> -<td>Losses of the transmission stage inside the electric motor component</td> -</tr> -<tr class="even"> -<td>EM_OVL-<POS>-em</td> -<td>[%]</td> -<td>Used capacity of the thermal overload buffer of the thermal derating model</td> -</tr> -<tr class="odd"> -<td>EM_<POS>_off</td> -<td>[-]</td> -<td>Indicates if the electric motor at position <em>POS</em> is energized or not.</td> -</tr> -<tr class="even"> -<td>P_bat_T</td> -<td>[kW]</td> -<td>Electric power provided at the battery’s connector</td> -</tr> -<tr class="odd"> -<td>P_bat_int</td> -<td>[kW]</td> -<td>Internal battery power</td> -</tr> -<tr class="even"> -<td>P_bat_loss</td> -<td>[kW]</td> -<td>Losses of the battery due to its internal resistance.</td> -</tr> -<tr class="odd"> -<td>Battery SOC</td> -<td>[%]</td> -<td>The battery’s current state of charge</td> -</tr> -<tr class="even"> -<td>E_bat</td> -<td>[kWh]</td> -<td>The amount of energy currently stored in the battery</td> -</tr> -<tr class="odd"> -<td>P_bat charge max</td> -<td>[kW]</td> -<td>Maximum power the battery can be charged with</td> -</tr> -<tr class="even"> -<td>P_bat discharge max</td> -<td>[kW]</td> -<td>Maximum power the battery can provide</td> -</tr> -<tr class="odd"> -<td>U_bat_T</td> -<td>[V]</td> -<td>Voltage at the battery’s connector</td> -</tr> -<tr class="even"> -<td>U_0_bat</td> -<td>[V]</td> -<td>Battery’s internal voltage</td> -</tr> -<tr class="odd"> -<td>I_bat</td> -<td>[A]</td> -<td>Current charging/discharging the battery.</td> -</tr> </tbody> </table> <p><strong>Note:</strong> The fuel name is only added to the fuel-consumption signals in case of dual-fuel engines.</p> @@ -6623,17 +6793,17 @@ CycleTime,UnknownCycleName,3600</code></pre> <tr class="odd"> <td>FC-ESS<_FuelName></td> <td>[g/h], [g/km]</td> -<td>Average fuel consumption including fuel consumption during engine-off periods (Based on FC-ESS from .vmod)</td> +<td>Average fuel consumption considering the ICE is not always off during ICE-off periods in the simulation. Considers all auxiliary demands during Off-phases taking into account the ESS utility factors</td> </tr> <tr class="even"> <td>FC-ESS_Corr<_FuelName></td> <td>[g/h], [g/km]</td> -<td>Average fuel consumption including fuel consumption during engine-off periods corrected for energy demand during engine-off periods not accounted (FC-ESS_Corr = FC-WHR_Corr + (E_aux_ess_mech + E_ice_start) * k_vehline)</td> +<td>Average fuel consumption including fuel consumption during engine-off periods corrected for energy demand during engine-off periods not accounted (FC-ESS_Corr = FC_WHTCc + FC_ESS)</td> </tr> <tr class="odd"> <td>FC-BusAux_PS_Corr<_FuelName></td> <td>[g/h], [g/km]</td> -<td>Average fuel consumption corrected for the excessive/missing energy for the smart pneumatic system</td> +<td>Average fuel consumption corrected for the excessive/missing energy for the smart pneumatic system, also corrected for the air demand according to the correct driving time.</td> </tr> <tr class="even"> <td>FC-BusAux_ES_Corr<_FuelName></td> @@ -6646,6 +6816,16 @@ CycleTime,UnknownCycleName,3600</code></pre> <td>Average fuel consumption including fuel consumption deduction due to electric power generated by an electric WHR system (FC-WHR_Corr = FC-ESS - E_WHR_el / eta_alternator * k_vehline)</td> </tr> <tr class="even"> +<td>FC-SoC<_FuelName></td> +<td>[g/h], [g/km]</td> +<td>Average fuel consumption to correct the REESS SoC so that the SoC at the end of the cycle mathces the SoC at the beginning</td> +</tr> +<tr class="odd"> +<td>FC-SoC_Corr<_FuelName></td> +<td>[g/h], [g/km]</td> +<td>Average fuel consumption including the correction for the REESS SoC</td> +</tr> +<tr class="even"> <td>FC-BusAux_AuxHeater<_FuelName></td> <td>[g/h], [g/km]</td> <td>Average fuel consumption of the additionalheater. In case of dual-fuel vehicles the aux heater is fueled with the primary fuel</td> @@ -6661,11 +6841,61 @@ CycleTime,UnknownCycleName,3600</code></pre> <td>Final average fuel consumption after ALL corrections (FC-Final = FC-ESS_Corr). Fuel consumption for calculation of CO<sub>2</sub> value. If Loading = 0[kg] the column [l/100tkm] is left empty.</td> </tr> <tr class="odd"> +<td>k_vehline</td> +<td>[g/kWh]</td> +<td>Slope of the regression line derived from all operating points P_wheel vs. FC_final_mod where P_wheel > 0 and FC_final_mod > 0</td> +</tr> +<tr class="even"> +<td>k_engline</td> +<td>[g/kWh]</td> +<td>Slope of the regression line used for the <a href="#engine-fuel-consumption-correction">fuel consumption correction</a></td> +</tr> +<tr class="odd"> <td>CO2</td> <td>[g/km], [g/tkm], [g/m^3km]</td> <td>Average CO<sub>2</sub> emissions (based on FC-Final value). Output for [l/100tkm] is empty when Loading = 0[kg].</td> </tr> <tr class="even"> +<td>REESS Start SoC</td> +<td>[%]</td> +<td>State of charge of the REESS at the beginning of the simulation run</td> +</tr> +<tr class="odd"> +<td>REESS End SoC</td> +<td>[%]</td> +<td>State of charge pf the REESS at the end of the simulation run</td> +</tr> +<tr class="even"> +<td>ΔE_REESS</td> +<td>[kWh]</td> +<td>Delta energy stored in the REESS between start and end of the simulation run. Calculated from P_REESS_int.</td> +</tr> +<tr class="odd"> +<td>E_REESS_loss</td> +<td>[kWh]</td> +<td>Total losses in the REESS due to its internal resistance</td> +</tr> +<tr class="even"> +<td>E_REESS_T_chg</td> +<td>[kWh]</td> +<td>Total energy charged into the REESS at the terminal (includes losses at internal resistance)</td> +</tr> +<tr class="odd"> +<td>E_REESS_T_dischg</td> +<td>[kWh]</td> +<td>Total energy discharged from the REESS at the terminal (includes losses at the internal resistance)</td> +</tr> +<tr class="even"> +<td>E_REESS_int_chg</td> +<td>[kWh]</td> +<td>Total energy charged into the REES (excluding losses)</td> +</tr> +<tr class="odd"> +<td>E_REESS_int_dischg</td> +<td>[kWh]</td> +<td>Total energy discharged from the REESS (excluding losses)</td> +</tr> +<tr class="even"> <td>P_wheel_in_pos</td> <td>[kW]</td> <td>Average positive power at the wheels</td> @@ -6711,149 +6941,209 @@ CycleTime,UnknownCycleName,3600</code></pre> <td>Total energy demand of all auxiliaries. This is the sum for all E_aux_xxx columns and the bus auxiliaires.</td> </tr> <tr class="odd"> +<td>E_aux_el(HV)</td> +<td>[kWh]</td> +<td>Total energy demand of the electric auxiliaries connected directly to the REESS.</td> +</tr> +<tr class="even"> <td>E_clutch_loss</td> <td>[kWh]</td> <td>Total energy loss in the clutch</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_tc_loss</td> <td>[kWh]</td> <td>Total torque converter energy loss</td> </tr> -<tr class="odd"> +<tr class="even"> <td>E_gbx_loss</td> <td>[kWh]</td> <td>Total transmission energy losses at gearbox (includes loss-map, inertia, and gear-shifts). E_shift_loss is already included here.</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_shift_loss</td> <td>[kWh]</td> <td>Total energy losses due to gearshifts</td> </tr> -<tr class="odd"> +<tr class="even"> <td>E_ret_loss</td> <td>[kWh]</td> <td>Total retarder energy loss</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_angle_loss</td> <td>[kWh]</td> <td>Total torque converter energy loss</td> </tr> -<tr class="odd"> +<tr class="even"> <td>E_axl_loss</td> <td>[kWh]</td> <td>Total transmission energy losses at the axlegear</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_brake</td> <td>[kWh]</td> <td>Total work dissipated in mechanical braking (sum of service brakes, retader and additional engine exhaust brakes)</td> </tr> -<tr class="odd"> +<tr class="even"> <td>E_vehicle_inertia</td> <td>[kWh]</td> <td>Total work of wheels inertia and vehicle mass</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_air</td> <td>[kWh]</td> <td>Total work of air resistance</td> </tr> -<tr class="odd"> +<tr class="even"> <td>E_roll</td> <td>[kWh]</td> <td>Total work of rolling resistance</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_grad</td> <td>[kWh]</td> <td>Total work of gradient resistance</td> </tr> +<tr class="even"> +<td>n_EM_<POS>-em_avg</td> +<td>[rpm]</td> +<td>Average angular speed of the electric machine</td> +</tr> +<tr class="odd"> +<td>E_EM_<POS>-em_drive</td> +<td>[kWh]</td> +<td>Mechanical energy at the electric motor shaft applied by the electric machine at position <em>POS</em> to drive the vehicle</td> +</tr> +<tr class="even"> +<td>E_EM_<POS>-em_gen</td> +<td>[kWh]</td> +<td>Mechanical energy at the electric motor shaft recuperated by the electric machine at position <em>POS</em></td> +</tr> <tr class="odd"> +<td>η_EM_<POS>-em_drive</td> +<td>[-]</td> +<td>Average efficiency of the electric machine when the electric machine drives the vehicle. Based on the mechanical energy at the electric motor shaft and the electric energy.</td> +</tr> +<tr class="even"> +<td>η_EM_<POS>-em_gen</td> +<td>[-]</td> +<td>Average efficiency of the electric machine when the electric machine generates electric energy. Based on the mechanical energy at the electric motor shaft and the electric energy.</td> +</tr> +<tr class="odd"> +<td>E_EM_<POS>_drive</td> +<td>[kWh]</td> +<td>Mechanical energy applied at the drivetrain by the electric machine at position <em>POS</em> to drive the vehicle</td> +</tr> +<tr class="even"> +<td>E_EM_<POS>_gen</td> +<td>[kWh]</td> +<td>Mechanical energy at the drivetrain recuperated by the electric machine at position <em>POS</em></td> +</tr> +<tr class="odd"> +<td>η_EM_<POS>_drive</td> +<td>[-]</td> +<td>Average efficiency at the drivetrain of the electric machine when the electric machine drives the vehicle. Based on the mechanical energy at the drivetrain and the electric power.</td> +</tr> +<tr class="even"> +<td>η_EM_<POS>_gen</td> +<td>[-]</td> +<td>Average efficiency at the drivetrain of the electric machine when the electric machine generates electric energy. Based on the mechanical energy at the drivetrain and the electric power</td> +</tr> +<tr class="odd"> +<td>E_EM_<POS>_off_loss</td> +<td>[kWh]</td> +<td>Total losses added by the electric machine when the electric machine is not energized (i.e., the electric machine’s drag losses)</td> +</tr> +<tr class="even"> +<td>E_EM_<POS>_transm_loss</td> +<td>[kWh]</td> +<td>Losses of the transmission stage in the electric motor component.</td> +</tr> +<tr class="odd"> +<td>E_EM_<POS>-em_loss</td> +<td>[kWh]</td> +<td>Total losses of the electric motor component. Calculated from P_<POS>-em_loss</td> +</tr> +<tr class="even"> +<td>E_EM_<POS>_loss</td> +<td>[kWh]</td> +<td>Losses of the electric machine. Calculated from P_<POS>_loss</td> +</tr> +<tr class="odd"> +<td>EM <POS> off time share</td> +<td>[%]</td> +<td>Time share the electric motor is not energized during the cycle.</td> +</tr> +<tr class="even"> <td>BusAux PS air consumed</td> <td>[Nl]</td> <td>Total air consumed by the pneumatic system.</td> </tr> -<tr class="even"> +<tr class="odd"> <td>BusAux PS air generated</td> <td>[Nl]</td> <td>Total air generated by the pneumatic compressor. Difference to “BusAux PS air consumed†is corrected in the <a href="#engine-fuel-consumption-correction">post-processing</a></td> </tr> -<tr class="odd"> +<tr class="even"> <td>E_PS_compressorOff</td> <td>[kWh]</td> <td>Total energy demand for the pneumatic compressor if no air would be generated (compressor always in drag)</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_PS_compressorOn</td> <td>[kWh]</td> <td>Total mechanical work for the pneumatic compressor to generate “BusAux PS air generatedâ€</td> </tr> -<tr class="odd"> +<tr class="even"> <td>E_BusAux_ES_consumed</td> <td>[kWh]</td> <td>Total electric energy for all electric consumers</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_BusAux_ES_generated</td> <td>[kWh]</td> <td>Total electric energy generated</td> </tr> -<tr class="odd"> +<tr class="even"> <td>ΔE_BusAux_Bat</td> <td>[kWh]</td> <td>In case of smart electrics, the difference of energy stored in the RESS between the beginning and end of the driving cycle. This energy difference is corrected in the post-processing</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_BusAux_PS_corr</td> <td>[kWh]</td> <td>Mechanical energy of the pneumatic system that needs to be considered in the post-processing to <a href="#engine-fuel-consumption-correction">correct the total fuel consumption</a></td> </tr> -<tr class="odd"> +<tr class="even"> <td>E_BusAux_ES_mech_corr</td> <td>[kWh]</td> <td>Mechanical energy of the electric system that needs to be considered in the post-processing to <a href="#engine-fuel-consumption-correction">correct the total fuel consumption</a></td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_BusAux_HVAC_mech</td> <td>[kWh]</td> <td>Mechancial energy demand of the HVAC system</td> </tr> -<tr class="odd"> +<tr class="even"> <td>E_BusAux_HVAC_el</td> <td>[kWh]</td> <td>Electrical energy demand of the HVAC system</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_BusAux_AuxhHeater</td> <td>[kWh]</td> <td>Energy demand of an additional aux heater.</td> </tr> -<tr class="odd"> -<td>E_PTO_CONSUM</td> -<td>[kWh]</td> -<td>Total energy demand of the pto consumer (if a pto consumer was used).</td> -</tr> <tr class="even"> -<td>E_PTO_TRANSM</td> -<td>[kWh]</td> -<td>Total energy demand of the pto transmission (if a pto transmission was used).</td> -</tr> -<tr class="odd"> <td>E_WHR_el</td> <td>[kWh]</td> -<td>Total electric energy generated by an electrical WHR system</td> +<td>Energy from the electric WHR system</td> </tr> -<tr class="even"> +<tr class="odd"> <td>E_WHR_mech</td> <td>[kWh]</td> -<td>Total electric energy generated by an electrical WHR system</td> -</tr> -<tr class="odd"> -<td>E_aux_ess_mech</td> -<td>[kWh]</td> -<td>Total work of auxiliaries during engine stop and thus not considered in FC-Map and FC-AAUX. Considered in FC-ESS_Corr via <a href="#engine-fuel-consumption-correction">fuel consumption correction</a> (Based on P_aux_ESS_mech in .vmod)</td> +<td>Energy from the mechanical WHR system</td> </tr> <tr class="even"> <td>E_ice_start</td> @@ -6866,14 +7156,24 @@ CycleTime,UnknownCycleName,3600</code></pre> <td>Number of times the combustion engine is started</td> </tr> <tr class="even"> -<td>k_vehline</td> -<td>[g/kWh]</td> -<td>Slope of the regression line derived from all operating points P_wheel vs. FC_final_mod where P_wheel > 0 and FC_final_mod > 0</td> +<td>E_PTO_CONSUM</td> +<td>[kWh]</td> +<td>Total energy demand of the pto consumer (if a pto consumer was used).</td> </tr> <tr class="odd"> -<td>k_engline</td> -<td>[g/kWh]</td> -<td>Slope of the regression line used for the <a href="#engine-fuel-consumption-correction">fuel consumption correction</a></td> +<td>E_PTO_TRANSM</td> +<td>[kWh]</td> +<td>Total energy demand of the pto transmission (if a pto transmission was used).</td> +</tr> +<tr class="even"> +<td>E_WHR_el</td> +<td>[kWh]</td> +<td>Total electric energy generated by an electrical WHR system</td> +</tr> +<tr class="odd"> +<td>E_WHR_mech</td> +<td>[kWh]</td> +<td>Total electric energy generated by an electrical WHR system</td> </tr> <tr class="even"> <td>E_aux_PTO_RoadSweeping</td> @@ -6886,150 +7186,45 @@ CycleTime,UnknownCycleName,3600</code></pre> <td>Total energy demand of the pto activation in mode 3 (engineering mode only.</td> </tr> <tr class="even"> +<td>E_aux_ess_mech</td> +<td>[kWh]</td> +<td>Total work of auxiliaries during engine stop and thus not considered in FC-Map and FC-AAUX. Considered in FC-ESS_Corr via <a href="#engine-fuel-consumption-correction">fuel consumption correction</a> (Based on P_aux_ESS_mech in .vmod)</td> +</tr> +<tr class="odd"> <td>a</td> <td>[m/s<sup>2</sup>]</td> <td>Average acceleration</td> </tr> -<tr class="odd"> +<tr class="even"> <td>a_pos</td> <td>[m/s<sup>2</sup>]</td> <td>Average acceleration in acceleration phases (a<sub>3s</sub> > 0.125 [m/s<sup>2</sup>], a<sub>3s</sub> = 3-seconds-averaged acceleration)</td> </tr> -<tr class="even"> +<tr class="odd"> <td>a_neg</td> <td>[m/s<sup>2</sup>]</td> <td>Average deceleration in deceleration phases (a<sub>3s</sub> < 0.125 [m/s<sup>2</sup>], a<sub>3s</sub> = 3-seconds-averaged acceleration)</td> </tr> -<tr class="odd"> +<tr class="even"> <td>AccelerationTimeShare</td> <td>[%]</td> <td>Time share of acceleration phases (a<sub>3s</sub> > 0.125 [m/s<sup>2</sup>], a<sub>3s</sub> = 3-seconds-averaged acceleration)</td> </tr> -<tr class="even"> +<tr class="odd"> <td>DecelerationTimeShare</td> <td>[%]</td> <td>Time share of deceleration phases (a<sub>3s</sub> < 0.125 [m/s<sup>2</sup>], a<sub>3s</sub> = 3-seconds-averaged acceleration)</td> </tr> -<tr class="odd"> +<tr class="even"> <td>CruiseTimeShare</td> <td>[%]</td> <td>Time share of cruise phases (-0.125 ≤ a<sub>3s</sub> ≤ 0.125 [m/s<sup>2</sup>])</td> </tr> -<tr class="even"> +<tr class="odd"> <td>StopTimeShare</td> <td>[%]</td> <td>Time share of stop phases (v < 0.1 [m/s])</td> </tr> -<tr class="odd"> -<td>E_EM_<POS>_drive</td> -<td>[kWh]</td> -<td>Mechanical energy applied at the drivetrain by the electric machine at position <em>POS</em> to drive the vehicle</td> -</tr> -<tr class="even"> -<td>E_EM_<POS>_gen</td> -<td>[kWh]</td> -<td>Mechanical energy at the drivetrain recuperated by the electric machine at position <em>POS</em></td> -</tr> -<tr class="odd"> -<td>η_EM_<POS>_drive</td> -<td>[-]</td> -<td>Average efficiency at the drivetrain of the electric machine when the electric machine drives the vehicle. Based on the mechanical energy at the drivetrain and the electric power.</td> -</tr> -<tr class="even"> -<td>η_EM_<POS>_gen</td> -<td>[-]</td> -<td>Average efficiency at the drivetrain of the electric machine when the electric machine generates electric energy. Based on the mechanical energy at the drivetrain and the electric power</td> -</tr> -<tr class="odd"> -<td>E_EM_<POS>-em_drive</td> -<td>[kWh]</td> -<td>Mechanical energy at the electric motor shaft applied by the electric machine at position <em>POS</em> to drive the vehicle</td> -</tr> -<tr class="even"> -<td>E_EM_<POS>-em_gen</td> -<td>[kWh]</td> -<td>Mechanical energy at the electric motor shaft recuperated by the electric machine at position <em>POS</em></td> -</tr> -<tr class="odd"> -<td>η_EM_<POS>-em_drive</td> -<td>[-]</td> -<td>Average efficiency of the electric machine when the electric machine drives the vehicle. Based on the mechanical energy at the electric motor shaft and the electric energy.</td> -</tr> -<tr class="even"> -<td>η_EM_<POS>-em_gen</td> -<td>[-]</td> -<td>Average efficiency of the electric machine when the electric machine generates electric energy. Based on the mechanical energy at the electric motor shaft and the electric energy.</td> -</tr> -<tr class="odd"> -<td>n_EM_<POS>_avg</td> -<td>[rpm]</td> -<td>Average angular speed of the electric machine</td> -</tr> -<tr class="even"> -<td>E_EM_<POS>_off_loss</td> -<td>[kWh]</td> -<td>Total losses added by the electric machine when the electric machine is not energized (i.e., the electric machine’s drag losses)</td> -</tr> -<tr class="odd"> -<td>E_EM_<POS>_transm_loss</td> -<td>[kWh]</td> -<td>Losses of the transmission stage in the electric motor component.</td> -</tr> -<tr class="even"> -<td>E_EM_<POS>-em_loss</td> -<td>[kWh]</td> -<td>Total losses of the electric motor component. Calculated from P_<POS>-em_loss</td> -</tr> -<tr class="odd"> -<td>E_EM_<POS>_loss</td> -<td>[kWh]</td> -<td>Losses of the electric machine. Calculated from P_<POS>_loss</td> -</tr> -<tr class="even"> -<td>EM <POS> off time share</td> -<td>[%]</td> -<td>Time share the electric motor is not energized during the cycle.</td> -</tr> -<tr class="odd"> -<td>Battery Start SoC</td> -<td>[%]</td> -<td>Battery state of charge at the beginning of the simulation run</td> -</tr> -<tr class="even"> -<td>Battery End SoC</td> -<td>[%]</td> -<td>Battery state of charge at the end of the simulation run</td> -</tr> -<tr class="odd"> -<td>Battery Delta SoC</td> -<td>[kWh]</td> -<td>Difference of the energy stored in the battery between the beginning and end of the simulation run</td> -</tr> -<tr class="even"> -<td>E_Batt_loss</td> -<td>[kWh]</td> -<td>Total losses in the battery due to its internal resistance</td> -</tr> -<tr class="odd"> -<td>E_Batt_T_chg</td> -<td>[kWh]</td> -<td></td> -</tr> -<tr class="even"> -<td>E_Batt_T_dischg</td> -<td>[kWh]</td> -<td></td> -</tr> -<tr class="odd"> -<td>E_Batt_int_chg</td> -<td>[kWh]</td> -<td></td> -</tr> -<tr class="even"> -<td>E_Batt_int_dischg</td> -<td>[kWh]</td> -<td></td> -</tr> </tbody> </table> <p><strong>Note:</strong> The fuel name is only added to the fuel consumption signals for vehicles with dual-fuel engines. In case single-fuel and dual-fuel vehicles are simulated in one simulation run, the fuel consumption for single-fuel vehicles is reported without the fuel name suffix while the fuel consumption of dual fuel vehicles contains the fuel name suffix!</p> diff --git a/Documentation/User Manual/pics/BusAux_PS_kAir.png b/Documentation/User Manual/pics/BusAux_PS_kAir.png new file mode 100644 index 0000000000000000000000000000000000000000..811346c3567789f9ec4523041812ddd294937f8a Binary files /dev/null and b/Documentation/User Manual/pics/BusAux_PS_kAir.png differ diff --git a/Documentation/User Manual/pics/FC_Correction.PNG b/Documentation/User Manual/pics/FC_Correction.PNG index 8110df0885adb1143f6b8fb7168f0d161d6b637c..6cf35ea375f08572c1c0799e7a045a84e1d032b0 100644 Binary files a/Documentation/User Manual/pics/FC_Correction.PNG and b/Documentation/User Manual/pics/FC_Correction.PNG differ diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Bus.vacc b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Bus.vacc new file mode 100644 index 0000000000000000000000000000000000000000..8ae1ce269631975dc3cda4923cdbe8b7a5377490 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Bus.vacc @@ -0,0 +1,15 @@ +v [km/h] , acc [m/s²] , dec [m/s²] +0 , 0.88 , -0.94 +10 , 1.00 , -0.94 +13 , 1.00 , -0.94 +20 , 1.00 , -0.88 +30 , 0.97 , -0.81 +40 , 0.80 , -0.73 +50 , 0.63 , -0.66 +58 , 0.50 , -0.52 +60 , 0.46 , -0.50 +70 , 0.39 , -0.50 +80 , 0.39 , -0.50 +90 , 0.39 , -0.50 +100 , 0.39 , -0.50 +120 , 0.39 , -0.50 \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/CityBus_AT-P.vecto b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/CityBus_AT-P.vecto new file mode 100644 index 0000000000000000000000000000000000000000..68e4ddc91bee029a32f5c5706a560c955ec7dc68 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/CityBus_AT-P.vecto @@ -0,0 +1,63 @@ +{ + "Header": { + "CreatedBy": "", + "Date": "2021-01-18T16:23:23.1599991Z", + "AppVersion": "3", + "FileVersion": 8 + }, + "Body": { + "SavedInDeclMode": false, + "EngineOnlyMode": false, + "VehicleFile": "CityBus_AT-P.vveh", + "EngineFile": "GenericICE_220kW_7.7l.veng", + "GearboxFile": "GearboxAT-P.vgbx", + "TCU": "ShiftPArameters.vtcu", + "ShiftStrategy": "TUGraz.VectoCore.Models.SimulationComponent.Impl.ATShiftStrategyOptimized", + "HybridStrategyParams": "HybridStrategyParams.vhctl", + "AuxiliaryAssembly": "Classic", + "AuxiliaryVersion": "CLASSIC", + "AdvancedAuxiliaryFilePath": "", + "Aux": [], + "Padd": 5000.0, + "Padd_electric": 0.0, + "VACC": "Bus.vacc", + "EngineStopStartAtVehicleStopThreshold": 2.0, + "EngineStopStartMaxOffTimespan": 30.0, + "EngineStopStartUtilityFactor": 1.0, + "EcoRollMinSpeed": 0.0, + "EcoRollActivationDelay": 0.0, + "EcoRollUnderspeedThreshold": 0.0, + "EcoRollMaxAcceleration": 0.0, + "PCCEnableSpeed": 0.0, + "PCCMinSpeed": 0.0, + "PCCUnderspeed": 0.0, + "PCCOverSpeed": 5.0, + "PCCPreviewDistanceUC1": 0.0, + "PCCPreviewDistanceUC2": 0.0, + "LAC": { + "Enabled": true, + "PreviewDistanceFactor": 10.0, + "DF_offset": 2.5, + "DF_scaling": 1.5, + "DF_targetSpeedLookup": "", + "Df_velocityDropLookup": "", + "MinSpeed": 50.0 + }, + "OverSpeedEcoRoll": { + "Mode": "Off", + "MinSpeed": 50.0, + "OverSpeed": 2.5 + }, + "Cycles": [ + "LongHaul", + "Coach", + "Construction", + "HeavyUrban", + "Interurban", + "RegionalDelivery", + "Suburban", + "Urban", + "UrbanDelivery" + ] + } +} \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/CityBus_AT-P.vveh b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/CityBus_AT-P.vveh new file mode 100644 index 0000000000000000000000000000000000000000..434bc9f53ac4e7bab87504a75f9550bd42c2bbb3 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/CityBus_AT-P.vveh @@ -0,0 +1,82 @@ +{ + "Header": { + "CreatedBy": "", + "Date": "2021-02-01T12:49:19.2221328Z", + "AppVersion": "3", + "FileVersion": 10 + }, + "Body": { + "SavedInDeclMode": false, + "VehCat": "CityBus", + "LegislativeClass": "Unknown", + "CurbWeight": 12000.0, + "CurbWeightExtra": 0.0, + "MassMax": 18.0, + "Loading": 1000.0, + "rdyn": 421.0, + "CdCorrMode": "CdofVdecl", + "CdCorrFile": "", + "AxleConfig": { + "Type": "4x2", + "Axles": [ + { + "Inertia": 6.5, + "Wheels": "265/70 R19.5", + "AxleWeightShare": 0.4, + "TwinTyres": false, + "RRCISO": 0.0065, + "FzISO": 20850.0, + "Type": "VehicleNonDriven" + }, + { + "Inertia": 6.5, + "Wheels": "265/70 R19.5", + "AxleWeightShare": 0.6, + "TwinTyres": true, + "RRCISO": 0.0075, + "FzISO": 20850.0, + "Type": "VehicleDriven" + } + ] + }, + "EngineStopStart": true, + "EcoRoll": "None", + "PredictiveCruiseControl": "None", + "ATEcoRollReleaseLockupClutch": false, + "CdA": 4.25, + "VehicleHeight": 3.3, + "IdlingSpeed": 600.0, + "Retarder": { + "Type": "None", + "Ratio": 0.0, + "File": "" + }, + "Angledrive": { + "Type": "None", + "Ratio": 0.0, + "LossMap": "" + }, + "PTO": { + "Type": "None", + "LossMap": "", + "Cycle": "" + }, + "TorqueLimits": {}, + "MaxDrivetrainPower": 10000.0, + "InitialSoC": 90.0, + "PowertrainConfiguration": "ParallelHybrid", + "ElectricMotors": [ + { + "Count": 1, + "Ratio": 2.0, + "MechanicalEfficiency": 0.98, + "Position": "P1", + "MotorFile": "GenericEM_15KW_220Nm.vem" + } + ], + "Battery": { + "NumPacks": 1, + "BatteryFile": "Generic Supercap 48V.vreess" + } + } +} \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Engine map_7.7l.vmap b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Engine map_7.7l.vmap new file mode 100644 index 0000000000000000000000000000000000000000..0dcbccd5228fc1a5a663a157d584ed14c43533a8 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Engine map_7.7l.vmap @@ -0,0 +1,183 @@ +engine speed [rpm],torque [Nm],fuel consumption [g/h] +600,-156.5714286,0 +600,-56.57142857,0 +600,0,638 +600,216.9,3553.94 +600,433.8,6644.06 +600,650.7,11050.13 +600,867.6,15456.14 +600,1084.5,19862.14 +600,1301.4,24268.15 +600,1518.3,28674.15 +600,1735.2,33080.15 +600,1952.1,37486.16 +600,2169,41892.16 +748.9,-166.0198746,0 +748.9,-66.01987455,0 +748.9,0,843.67 +748.9,216.9,4100.1 +748.9,433.8,7706.21 +748.9,650.7,12298.69 +748.9,867.6,16731.15 +748.9,1084.5,21128.17 +748.9,1301.4,25525.18 +748.9,1518.3,29922.2 +748.9,1735.2,34319.22 +748.9,1952.1,38716.24 +748.9,2169,43113.26 +897.8,-174.5509889,0 +897.8,-74.55098889,0 +897.8,0,1049.35 +897.8,216.9,4646.25 +897.8,433.8,8768.36 +897.8,650.7,13541.46 +897.8,867.6,18156.42 +897.8,1084.5,22760.37 +897.8,1301.4,27362.81 +897.8,1518.3,31965.25 +897.8,1735.2,36567.69 +897.8,1952.1,41170.14 +897.8,2169,45772.58 +1046.7,-183.6305194,0 +1046.7,-83.63051942,0 +1046.7,0,1255.02 +1046.7,216.9,5192.4 +1046.7,433.8,9830.52 +1046.7,650.7,14781.21 +1046.7,867.6,19659.22 +1046.7,1084.5,24580.08 +1046.7,1301.4,29611.62 +1046.7,1518.3,34620.74 +1046.7,1735.2,39629.86 +1046.7,1952.1,44638.98 +1046.7,2169,49648.11 +1195.57,-193.9794114,0 +1195.57,-93.97941143,0 +1195.57,0,1460.65 +1195.57,216.9,5738.45 +1195.57,433.8,10892.45 +1195.57,650.7,16020.7 +1195.57,867.6,21159.59 +1195.57,1084.5,26391.05 +1195.57,1301.4,32095.87 +1195.57,1518.3,37706.84 +1195.57,1735.2,43317.81 +1195.57,1952.1,48928.77 +1195.57,2169,54539.74 +1359.19,-205.6210761,0 +1359.19,-105.6210761,0 +1359.19,0,1846.01 +1359.19,216.9,6560.14 +1359.19,433.8,12332.07 +1359.19,650.7,18097.95 +1359.19,867.6,23937.72 +1359.19,1084.5,29597.59 +1359.19,1301.4,35520.27 +1359.19,1518.3,41402.13 +1359.19,1735.2,47284 +1359.19,1952.1,53165.86 +1359.19,2169,59047.73 +1484,-215.5394502,0 +1484,-115.5394502,0 +1484,0,2131.16 +1484,216.9,7194.66 +1484,433.8,13496.22 +1484,650.7,19795.45 +1484,867.6,26122.03 +1484,1084.5,32222.77 +1484,1301.4,38588.45 +1484,1518.3,44936.74 +1484,1735.2,51285.03 +1484,1952.1,57633.32 +1484,2169,63981.62 +1608.9,-223.6490478,0 +1608.9,-123.6490478,0 +1608.9,0,2412.92 +1608.9,216.9,7832.39 +1608.9,433.8,14689.88 +1608.9,650.7,21533.67 +1608.9,867.6,28332.13 +1608.9,1084.5,34956.02 +1608.9,1301.4,41921.53 +1608.9,1518.3,48882.7 +1608.9,1735.2,55843.86 +1608.9,1952.1,62805.03 +1608.9,2169,69766.19 +1733.8,-228.2687944,0 +1733.8,-128.2687944,0 +1733.8,0,2725.03 +1733.8,216.9,8486.62 +1733.8,433.8,15875.76 +1733.8,650.7,23166.99 +1733.8,867.6,30597.07 +1733.8,1084.5,38101 +1733.8,1301.4,45882.06 +1733.8,1518.3,53661.69 +1733.8,1735.2,61441.31 +1733.8,1952.1,69220.94 +1733.8,2169,77000.57 +1858.61,-233.2770119,0 +1858.61,-133.2770119,0 +1858.61,0,3067.94 +1858.61,216.9,9180.54 +1858.61,433.8,17097.03 +1858.61,650.7,24909.82 +1858.61,867.6,32982.42 +1858.61,1084.5,41176.53 +1858.61,1301.4,49526.09 +1858.61,1518.3,57875.73 +1858.61,1735.2,66225.36 +1858.61,1952.1,74575 +1858.61,2169,82924.64 +1983.51,-239.7011553,0 +1983.51,-139.7011553,0 +1983.51,0,3446.165969 +1983.51,216.9,9920.378324 +1983.51,433.8,18360.13899 +1983.51,650.7,26779.01758 +1983.51,867.6,35507.453 +1983.51,1084.5,44178.34965 +1983.51,1301.4,52818.23622 +1983.51,1518.3,61458.13164 +1983.51,1735.2,70098.02705 +1983.51,1952.1,78737.92246 +1983.51,2169,87377.81788 +2108.41,-250.3624289,0 +2108.41,-150.3624289,0 +2108.41,0,3903.220883 +2108.41,216.9,10693.19834 +2108.41,433.8,19641.08191 +2108.41,650.7,28745.17923 +2108.41,867.6,38180.93551 +2108.41,1084.5,47433.46318 +2108.41,1301.4,56664.44413 +2108.41,1518.3,65895.42508 +2108.41,1735.2,75126.40604 +2108.41,1952.1,84357.38699 +2108.41,2169,93588.36794 +2233.31,-260.6179336,0 +2233.31,-160.6179336,0 +2233.31,0,4363.413897 +2233.31,216.9,11487.86565 +2233.31,433.8,20985.72948 +2233.31,650.7,30841.62288 +2233.31,867.6,41079.19748 +2233.31,1084.5,51089.00489 +2233.31,1301.4,61104.85222 +2233.31,1518.3,71120.69954 +2233.31,1735.2,81136.54686 +2233.31,1952.1,91152.39418 +2233.31,2169,101168.2415 +2358.21,-268.3446286,0 +2358.21,-168.3446286,0 +2358.21,0,4799.266043 +2358.21,216.9,12328.80853 +2358.21,433.8,22498.08244 +2358.21,650.7,33255.73916 +2358.21,867.6,44533.43058 +2358.21,1084.5,55739.63684 +2358.21,1301.4,66947.35734 +2358.21,1518.3,78155.07784 +2358.21,1735.2,89362.79834 +2358.21,1952.1,100570.5188 +2358.21,2169,111778.2393 diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Full-load curve 220kW.vfld b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Full-load curve 220kW.vfld new file mode 100644 index 0000000000000000000000000000000000000000..c886b973fd4999cf55bbd97d57565d78e161fa07 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Full-load curve 220kW.vfld @@ -0,0 +1,14 @@ +engine speed [1/min],full load torque [Nm],motoring torque [Nm] +500,628.5714286,-50.28571429 +600,779.4285714,-56.57142857 +800,942.8571429,-69.14285714 +1000,1131.428571,-80.45714286 +1100,1294.857143,-87.37142857 +1200,1294.857143,-94.28571429 +1300,1294.857143,-101.2 +1600,1294.857143,-123.2 +1800,1150.285714,-130.7428571 +2000,1043.428571,-140.8 +2200,955.4285714,-158.4 +2300,867.4285714,-164.6857143 +2400,779.4285714,-170.9714286 diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GearboxAT-P.vgbx b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GearboxAT-P.vgbx new file mode 100644 index 0000000000000000000000000000000000000000..7f3a3f92be54c5d11b0e7f14921ab7959c884f2e --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GearboxAT-P.vgbx @@ -0,0 +1,61 @@ +{ + "Header": { + "CreatedBy": "", + "Date": "2021-01-18T16:15:44.9706996Z", + "AppVersion": "3", + "FileVersion": 6 + }, + "Body": { + "SavedInDeclMode": false, + "ModelName": "AT PowerSplit", + "Inertia": 0.0, + "TracInt": 0.0, + "Gears": [ + { + "Ratio": 5.8, + "Efficiency": 0.97 + }, + { + "Ratio": 1.43, + "Efficiency": 0.93, + "ShiftPolygon": "", + "MaxTorque": "", + "MaxSpeed": "" + }, + { + "Ratio": 1.0, + "Efficiency": 0.93, + "ShiftPolygon": "", + "MaxTorque": "", + "MaxSpeed": "" + }, + { + "Ratio": 0.7, + "Efficiency": 0.93, + "ShiftPolygon": "", + "MaxTorque": "", + "MaxSpeed": "" + } + ], + "TqReserve": 0.0, + "ShiftTime": 0.5, + "StartTqReserve": 0.0, + "StartSpeed": 2.0, + "StartAcc": 0.6, + "GearboxType": "ATPowerSplit", + "TorqueConverter": { + "Enabled": true, + "File": "TC Parallel.vtcc", + "RefRPM": 999.99999999999989, + "Inertia": 0.0, + "MaxTCSpeed": 5000.0, + "ShiftPolygon": "", + "CLUpshiftMinAcceleration": 0.0, + "CCUpshiftMinAcceleration": 0.0 + }, + "DownshiftAfterUpshiftDelay": 6.0, + "UpshiftAfterDownshiftDelay": 0.0, + "UpshiftMinAcceleration": 0.0, + "PowershiftShiftTime": 0.8 + } +} \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Generic Supercap 48V.vreess b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Generic Supercap 48V.vreess new file mode 100644 index 0000000000000000000000000000000000000000..5cf5a9b538063f4c171bd6dbbb9007a00c01cacf --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/Generic Supercap 48V.vreess @@ -0,0 +1,19 @@ +{ + "Header": { + "CreatedBy": "", + "Date": "2021-01-18T15:17:57.4852109Z", + "AppVersion": "3", + "FileVersion": 1 + }, + "Body": { + "SavedInDeclMode": false, + "REESSType": "SuperCap", + "Model": "Generic Supercap 48V", + "Capacity": 166.0, + "InternalResistance": 0.005, + "U_min": 5.0, + "U_max": 48.6, + "I_maxCharge": 2200.0, + "I_maxDischarge": 2200.0 + } +} \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM.vemd b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM.vemd new file mode 100644 index 0000000000000000000000000000000000000000..41157c01c87a2201fb1af0f5aacd5983d7e8e786 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM.vemd @@ -0,0 +1,3 @@ +n [rpm] , T_drag [Nm] +0 , -5.6 +5000 , -28.1 \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM_15KW_220Nm.vem b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM_15KW_220Nm.vem new file mode 100644 index 0000000000000000000000000000000000000000..a960e797c1258cc5ef401dad878f891c26a526c6 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM_15KW_220Nm.vem @@ -0,0 +1,20 @@ +{ + "Header": { + "CreatedBy": "", + "Date": "2021-01-18T16:23:20.3712200Z", + "AppVersion": "3", + "FileVersion": 1 + }, + "Body": { + "SavedInDeclMode": false, + "Model": "Generic 15kW_220Nm", + "FullLoadCurve": "GenericEM_15kW_220Nm.vemp", + "DragCurve": "GenericEM.vemd", + "EfficiencyMap": "GenericEM_32kW_450Nm.vemo", + "Inertia": 0.198, + "ContinuousPower": 15000.0, + "ContinuousPowerSpeed": 651.0, + "OverloadTime": 15.0, + "ThermalOverloadRecoveryFactor": 0.9 + } +} \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM_15kW_220Nm.vemp b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM_15kW_220Nm.vemp new file mode 100644 index 0000000000000000000000000000000000000000..249f3bb3b67d87cdb259a4d730d3d116946d8a03 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM_15kW_220Nm.vemp @@ -0,0 +1,75 @@ +n [rpm], T_drive [Nm], T_recuperation [Nm] +0,220,-440 +651.0884036,220,-440 +648.7012987,220,-440 +652.5974026,219.494,-438.988 +656.4935065,218.1905,-436.381 +660.3896104,216.9035,-433.807 +662.3376623,216.2655,-432.531 +681.8181818,210.0835,-420.167 +701.2987013,204.248,-408.496 +720.7792208,198.726,-397.452 +740.2597403,193.501,-387.002 +759.7402597,188.54,-377.08 +779.2207792,183.8265,-367.653 +798.7012987,179.3385,-358.677 +818.1818182,175.0705,-350.141 +837.6623377,171.0005,-342.001 +857.1428571,167.112,-334.224 +876.6233766,163.3995,-326.799 +896.1038961,159.8465,-319.693 +915.5844156,156.4475,-312.895 +935.0649351,153.186,-306.372 +954.5454545,150.062,-300.124 +974.025974,147.059,-294.118 +993.5064935,144.177,-288.354 +1012.987013,141.405,-282.81 +1032.467532,138.7375,-277.475 +1051.948052,136.1635,-272.327 +1071.428571,133.6885,-267.377 +1090.909091,131.3015,-262.603 +1110.38961,128.997,-257.994 +1129.87013,126.775,-253.55 +1149.350649,124.6245,-249.249 +1168.831169,122.551,-245.102 +1188.311688,120.538,-241.076 +1207.792208,118.5965,-237.193 +1227.272727,116.7155,-233.431 +1246.753247,114.8895,-229.779 +1266.233766,113.124,-226.248 +1285.714286,111.408,-222.816 +1305.194805,109.747,-219.494 +1324.675325,108.13,-216.26 +1344.155844,106.5625,-213.125 +1363.636364,105.0445,-210.089 +1383.116883,103.565,-207.13 +1402.597403,102.124,-204.248 +1422.077922,100.727,-201.454 +1441.558442,99.363,-198.726 +1461.038961,98.0375,-196.075 +1480.519481,96.7505,-193.501 +1500,95.491,-190.982 +1519.480519,94.27,-188.54 +1538.961039,93.0765,-186.153 +1558.441558,91.9105,-183.821 +1577.922078,90.7775,-181.555 +1597.402597,89.672,-179.344 +1616.883117,88.5885,-177.177 +1636.363636,87.5325,-175.065 +1655.844156,86.504,-173.008 +1675.324675,85.4975,-170.995 +1694.805195,84.5185,-169.037 +1714.285714,83.556,-167.112 +1733.766234,82.6155,-165.231 +1753.246753,81.697,-163.394 +1772.727273,80.8005,-161.601 +1792.207792,79.926,-159.852 +1811.688312,79.0625,-158.125 +1831.168831,78.221,-156.442 +1850.649351,77.4015,-154.803 +1870.12987,76.593,-153.186 +1889.61039,75.801,-151.602 +1909.090909,75.031,-150.062 +1928.571429,74.272,-148.544 +1948.051948,73.5295,-147.059 +4864.577923,29.44539927,-58.89079854 diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM_32kW_450Nm.vemo b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM_32kW_450Nm.vemo new file mode 100644 index 0000000000000000000000000000000000000000..d83549939cce849ba212493c65671b81017e72f8 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericEM_32kW_450Nm.vemo @@ -0,0 +1,2016 @@ +n [rpm] , T [Nm] , P_el [kW] +0,-450,5.625657143 +0,-435.9375,5.298228573 +0,-421.875,4.980628573 +0,-407.8125,4.672742858 +0,-393.75,4.374742858 +0,-379.6875,4.086514285 +0,-365.625,3.808057143 +0,-351.5625,3.539428573 +0,-337.5,3.280571428 +0,-323.4375,3.031542858 +0,-309.375,2.792342858 +0,-295.3125,2.562914285 +0,-281.25,2.343257143 +0,-267.1875,2.133428573 +0,-253.125,1.933371428 +0,-239.0625,1.743142858 +0,-225,1.562742858 +0,-210.9375,1.392114285 +0,-196.875,1.231257143 +0,-182.8125,1.080228573 +0,-168.75,0.939028573 +0,-154.6875,0.8076 +0,-140.625,0.685942858 +0,-126.5625,0.574114285 +0,-112.5,0.472097143 +0,-98.4375,0.379874285 +0,-84.375,0.297445715 +0,-70.3125,0.224822858 +0,-56.25,0.161994285 +0,-42.1875,0.108971428 +0,-28.125,0.065748573 +0,-14.0625,0.032323428 +0,0,0.020628573 +0,14.0625,0.049702285 +0,28.125,0.088577143 +0,42.1875,0.137251428 +0,56.25,0.195725715 +0,70.3125,0.264 +0,84.375,0.34208 +0,98.4375,0.429954285 +0,112.5,0.527628573 +0,126.5625,0.635085715 +0,140.625,0.7524 +0,154.6875,0.879485715 +0,168.75,1.016342858 +0,182.8125,1.163028573 +0,196.875,1.319485715 +0,210.9375,1.485771428 +0,225,1.661885715 +0,239.0625,1.847771428 +0,253.125,2.043428573 +0,267.1875,2.248914285 +0,281.25,2.464171428 +0,295.3125,2.689257143 +0,309.375,2.924171428 +0,323.4375,3.168857143 +0,337.5,3.423314285 +0,351.5625,3.6876 +0,365.625,3.961714285 +0,379.6875,4.2456 +0,393.75,4.539257143 +0,407.8125,4.842742858 +0,421.875,5.156057143 +0,435.9375,5.479142858 +0,450,5.812 +46.50584415,-450,3.335257143 +46.50584415,-435.9375,3.080057143 +46.50584415,-421.875,2.834628573 +46.50584415,-407.8125,2.598971428 +46.50584415,-393.75,2.373142858 +46.50584415,-379.6875,2.157142858 +46.50584415,-365.625,1.950914285 +46.50584415,-351.5625,1.754514285 +46.50584415,-337.5,1.567885715 +46.50584415,-323.4375,1.391085715 +46.50584415,-309.375,1.224057143 +46.50584415,-295.3125,1.0668 +46.50584415,-281.25,0.919428573 +46.50584415,-267.1875,0.781771428 +46.50584415,-253.125,0.654 +46.50584415,-239.0625,0.53596 +46.50584415,-225,0.427742858 +46.50584415,-210.9375,0.32988 +46.50584415,-196.875,0.242057143 +46.50584415,-182.8125,0.164377143 +46.50584415,-168.75,0.096302858 +46.50584415,-154.6875,0.037838285 +46.50584415,-140.625,-0.011020573 +46.50584415,-126.5625,-0.050273715 +46.50584415,-112.5,-0.07992 +46.50584415,-98.4375,-0.09996 +46.50584415,-84.375,-0.110394285 +46.50584415,-70.3125,-0.111222858 +46.50584415,-56.25,-0.10244 +46.50584415,-42.1875,-0.084057143 +46.50584415,-28.125,-0.056062858 +46.50584415,-14.0625,-0.018464573 +46.50584415,0,0.0414 +46.50584415,14.0625,0.142691428 +46.50584415,28.125,0.253777143 +46.50584415,42.1875,0.374668573 +46.50584415,56.25,0.505354285 +46.50584415,70.3125,0.645828573 +46.50584415,84.375,0.796114285 +46.50584415,98.4375,0.956228573 +46.50584415,112.5,1.126114285 +46.50584415,126.5625,1.305828573 +46.50584415,140.625,1.495314285 +46.50584415,154.6875,1.694571428 +46.50584415,168.75,1.903714285 +46.50584415,182.8125,2.122571428 +46.50584415,196.875,2.351257143 +46.50584415,210.9375,2.589771428 +46.50584415,225,2.838057143 +46.50584415,239.0625,3.096171428 +46.50584415,253.125,3.364057143 +46.50584415,267.1875,3.641771428 +46.50584415,281.25,3.929257143 +46.50584415,295.3125,4.226571428 +46.50584415,309.375,4.533657143 +46.50584415,323.4375,4.850571428 +46.50584415,337.5,5.177257143 +46.50584415,351.5625,5.513771428 +46.50584415,365.625,5.86 +46.50584415,379.6875,6.216 +46.50584415,393.75,6.582285715 +46.50584415,407.8125,6.957714285 +46.50584415,421.875,7.343428573 +46.50584415,435.9375,7.738285715 +46.50584415,450,8.143428573 +93.01266235,-450,1.045885715 +93.01266235,-435.9375,0.862914285 +93.01266235,-421.875,0.69 +93.01266235,-407.8125,0.528325715 +93.01266235,-393.75,0.377337143 +93.01266235,-379.6875,0.235954285 +93.01266235,-365.625,0.104177143 +93.01266235,-351.5625,-0.017996 +93.01266235,-337.5,-0.13056 +93.01266235,-323.4375,-0.23352 +93.01266235,-309.375,-0.326868573 +93.01266235,-295.3125,-0.410617143 +93.01266235,-281.25,-0.484754285 +93.01266235,-267.1875,-0.549285715 +93.01266235,-253.125,-0.604228573 +93.01266235,-239.0625,-0.649542858 +93.01266235,-225,-0.685257143 +93.01266235,-210.9375,-0.711371428 +93.01266235,-196.875,-0.727828573 +93.01266235,-182.8125,-0.734742858 +93.01266235,-168.75,-0.732057143 +93.01266235,-154.6875,-0.719714285 +93.01266235,-140.625,-0.697771428 +93.01266235,-126.5625,-0.666228573 +93.01266235,-112.5,-0.625085715 +93.01266235,-98.4375,-0.574342858 +93.01266235,-84.375,-0.514017143 +93.01266235,-70.3125,-0.444057143 +93.01266235,-56.25,-0.364497143 +93.01266235,-42.1875,-0.275325715 +93.01266235,-28.125,-0.176548573 +93.01266235,-14.0625,-0.068165715 +93.01266235,0,0.063228573 +93.01266235,14.0625,0.236731428 +93.01266235,28.125,0.42004 +93.01266235,42.1875,0.613142858 +93.01266235,56.25,0.816057143 +93.01266235,70.3125,1.028742858 +93.01266235,84.375,1.251257143 +93.01266235,98.4375,1.483542858 +93.01266235,112.5,1.725657143 +93.01266235,126.5625,1.9776 +93.01266235,140.625,2.239314285 +93.01266235,154.6875,2.5108 +93.01266235,168.75,2.792114285 +93.01266235,182.8125,3.0832 +93.01266235,196.875,3.384114285 +93.01266235,210.9375,3.694857143 +93.01266235,225,4.015371428 +93.01266235,239.0625,4.345657143 +93.01266235,253.125,4.685771428 +93.01266235,267.1875,5.035657143 +93.01266235,281.25,5.395371428 +93.01266235,295.3125,5.765142858 +93.01266235,309.375,6.144 +93.01266235,323.4375,6.533142858 +93.01266235,337.5,6.932 +93.01266235,351.5625,7.341142858 +93.01266235,365.625,7.759428573 +93.01266235,379.6875,8.188 +93.01266235,393.75,8.625714285 +93.01266235,407.8125,9.073714285 +93.01266235,421.875,9.531428573 +93.01266235,435.9375,9.998857143 +93.01266235,450,10.47657143 +139.5194805,-450,-1.204057143 +139.5194805,-435.9375,-1.313085715 +139.5194805,-421.875,-1.412514285 +139.5194805,-407.8125,-1.502285715 +139.5194805,-393.75,-1.582514285 +139.5194805,-379.6875,-1.653085715 +139.5194805,-365.625,-1.714114285 +139.5194805,-351.5625,-1.765485715 +139.5194805,-337.5,-1.807257143 +139.5194805,-323.4375,-1.839428573 +139.5194805,-309.375,-1.862 +139.5194805,-295.3125,-1.874971428 +139.5194805,-281.25,-1.878342858 +139.5194805,-267.1875,-1.872057143 +139.5194805,-253.125,-1.856228573 +139.5194805,-239.0625,-1.830742858 +139.5194805,-225,-1.795657143 +139.5194805,-210.9375,-1.750971428 +139.5194805,-196.875,-1.696685715 +139.5194805,-182.8125,-1.6328 +139.5194805,-168.75,-1.559314285 +139.5194805,-154.6875,-1.476228573 +139.5194805,-140.625,-1.383485715 +139.5194805,-126.5625,-1.2812 +139.5194805,-112.5,-1.169257143 +139.5194805,-98.4375,-1.047714285 +139.5194805,-84.375,-0.916571428 +139.5194805,-70.3125,-0.775828573 +139.5194805,-56.25,-0.625485715 +139.5194805,-42.1875,-0.465548573 +139.5194805,-28.125,-0.295988573 +139.5194805,-14.0625,-0.116822858 +139.5194805,0,0.086125715 +139.5194805,14.0625,0.33184 +139.5194805,28.125,0.587371428 +139.5194805,42.1875,0.852685715 +139.5194805,56.25,1.127828573 +139.5194805,70.3125,1.412742858 +139.5194805,84.375,1.707428573 +139.5194805,98.4375,2.011942858 +139.5194805,112.5,2.326285715 +139.5194805,126.5625,2.6504 +139.5194805,140.625,2.984342858 +139.5194805,154.6875,3.328057143 +139.5194805,168.75,3.6816 +139.5194805,182.8125,4.044914285 +139.5194805,196.875,4.418 +139.5194805,210.9375,4.800971428 +139.5194805,225,5.193657143 +139.5194805,239.0625,5.596228573 +139.5194805,253.125,6.008571428 +139.5194805,267.1875,6.430857143 +139.5194805,281.25,6.862857143 +139.5194805,295.3125,7.304571428 +139.5194805,309.375,7.756 +139.5194805,323.4375,8.217142858 +139.5194805,337.5,8.688571428 +139.5194805,351.5625,9.169142858 +139.5194805,365.625,9.66 +139.5194805,379.6875,10.16057143 +139.5194805,393.75,10.67085714 +139.5194805,407.8125,11.19085714 +139.5194805,421.875,11.72114286 +139.5194805,435.9375,12.26057143 +139.5194805,450,12.81028572 +186.0292208,-450,-3.446 +186.0292208,-435.9375,-3.484228573 +186.0292208,-421.875,-3.512857143 +186.0292208,-407.8125,-3.531885715 +186.0292208,-393.75,-3.541314285 +186.0292208,-379.6875,-3.541142858 +186.0292208,-365.625,-3.531371428 +186.0292208,-351.5625,-3.511942858 +186.0292208,-337.5,-3.482914285 +186.0292208,-323.4375,-3.444342858 +186.0292208,-309.375,-3.396114285 +186.0292208,-295.3125,-3.338285715 +186.0292208,-281.25,-3.270857143 +186.0292208,-267.1875,-3.193828573 +186.0292208,-253.125,-3.1072 +186.0292208,-239.0625,-3.010914285 +186.0292208,-225,-2.905085715 +186.0292208,-210.9375,-2.7896 +186.0292208,-196.875,-2.664514285 +186.0292208,-182.8125,-2.529828573 +186.0292208,-168.75,-2.3856 +186.0292208,-154.6875,-2.231657143 +186.0292208,-140.625,-2.068171428 +186.0292208,-126.5625,-1.895085715 +186.0292208,-112.5,-1.7124 +186.0292208,-98.4375,-1.520057143 +186.0292208,-84.375,-1.318114285 +186.0292208,-70.3125,-1.106628573 +186.0292208,-56.25,-0.885485715 +186.0292208,-42.1875,-0.654742858 +186.0292208,-28.125,-0.414394285 +186.0292208,-14.0625,-0.16444 +186.0292208,0,0.11008 +186.0292208,14.0625,0.428011428 +186.0292208,28.125,0.755771428 +186.0292208,42.1875,1.093257143 +186.0292208,56.25,1.440628573 +186.0292208,70.3125,1.797771428 +186.0292208,84.375,2.164685715 +186.0292208,98.4375,2.541428573 +186.0292208,112.5,2.927942858 +186.0292208,126.5625,3.324285715 +186.0292208,140.625,3.730457143 +186.0292208,154.6875,4.146342858 +186.0292208,168.75,4.572114285 +186.0292208,182.8125,5.007657143 +186.0292208,196.875,5.452971428 +186.0292208,210.9375,5.908 +186.0292208,225,6.373142858 +186.0292208,239.0625,6.848 +186.0292208,253.125,7.332571428 +186.0292208,267.1875,7.826857143 +186.0292208,281.25,8.330857143 +186.0292208,295.3125,8.844571428 +186.0292208,309.375,9.368571428 +186.0292208,323.4375,9.902285715 +186.0292208,337.5,10.44514286 +186.0292208,351.5625,10.99828572 +186.0292208,365.625,11.56171429 +186.0292208,379.6875,12.13428572 +186.0292208,393.75,12.71657143 +186.0292208,407.8125,13.30914286 +186.0292208,421.875,13.91142857 +186.0292208,435.9375,14.52342857 +186.0292208,450,15.14514286 +232.5292208,-450,-5.686914285 +232.5292208,-435.9375,-5.654342858 +232.5292208,-421.875,-5.612228573 +232.5292208,-407.8125,-5.560457143 +232.5292208,-393.75,-5.499085715 +232.5292208,-379.6875,-5.428114285 +232.5292208,-365.625,-5.347542858 +232.5292208,-351.5625,-5.257371428 +232.5292208,-337.5,-5.1576 +232.5292208,-323.4375,-5.048171428 +232.5292208,-309.375,-4.929142858 +232.5292208,-295.3125,-4.800571428 +232.5292208,-281.25,-4.662342858 +232.5292208,-267.1875,-4.514514285 +232.5292208,-253.125,-4.357085715 +232.5292208,-239.0625,-4.190057143 +232.5292208,-225,-4.013428573 +232.5292208,-210.9375,-3.827142858 +232.5292208,-196.875,-3.631314285 +232.5292208,-182.8125,-3.425828573 +232.5292208,-168.75,-3.2108 +232.5292208,-154.6875,-2.986114285 +232.5292208,-140.625,-2.751828573 +232.5292208,-126.5625,-2.507942858 +232.5292208,-112.5,-2.254457143 +232.5292208,-98.4375,-1.991371428 +232.5292208,-84.375,-1.718628573 +232.5292208,-70.3125,-1.436342858 +232.5292208,-56.25,-1.1444 +232.5292208,-42.1875,-0.842857143 +232.5292208,-28.125,-0.531754285 +232.5292208,-14.0625,-0.211017143 +232.5292208,0,0.135091428 +232.5292208,14.0625,0.52524 +232.5292208,28.125,0.9252 +232.5292208,42.1875,1.334914285 +232.5292208,56.25,1.754514285 +232.5292208,70.3125,2.183828573 +232.5292208,84.375,2.622971428 +232.5292208,98.4375,3.071942858 +232.5292208,112.5,3.530685715 +232.5292208,126.5625,3.999257143 +232.5292208,140.625,4.4776 +232.5292208,154.6875,4.965771428 +232.5292208,168.75,5.463714285 +232.5292208,182.8125,5.971428573 +232.5292208,196.875,6.489142858 +232.5292208,210.9375,7.016571428 +232.5292208,225,7.553714285 +232.5292208,239.0625,8.100571428 +232.5292208,253.125,8.657142858 +232.5292208,267.1875,9.224 +232.5292208,281.25,9.8 +232.5292208,295.3125,10.38628572 +232.5292208,309.375,10.98228572 +232.5292208,323.4375,11.588 +232.5292208,337.5,12.20342857 +232.5292208,351.5625,12.82914286 +232.5292208,365.625,13.464 +232.5292208,379.6875,14.10914286 +232.5292208,393.75,14.764 +232.5292208,407.8125,15.42857143 +232.5292208,421.875,16.10285714 +232.5292208,435.9375,16.78685714 +232.5292208,450,17.48114286 +279.038961,-450,-7.926857143 +279.038961,-435.9375,-7.823428573 +279.038961,-421.875,-7.710285715 +279.038961,-407.8125,-7.588 +279.038961,-393.75,-7.456 +279.038961,-379.6875,-7.314285715 +279.038961,-365.625,-7.162857143 +279.038961,-351.5625,-7.001714285 +279.038961,-337.5,-6.831428573 +279.038961,-323.4375,-6.650857143 +279.038961,-309.375,-6.461142858 +279.038961,-295.3125,-6.261714285 +279.038961,-281.25,-6.052571428 +279.038961,-267.1875,-5.834285715 +279.038961,-253.125,-5.606 +279.038961,-239.0625,-5.368171428 +279.038961,-225,-5.120742858 +279.038961,-210.9375,-4.863714285 +279.038961,-196.875,-4.597028573 +279.038961,-182.8125,-4.3208 +279.038961,-168.75,-4.034971428 +279.038961,-154.6875,-3.739485715 +279.038961,-140.625,-3.434457143 +279.038961,-126.5625,-3.119771428 +279.038961,-112.5,-2.795485715 +279.038961,-98.4375,-2.4616 +279.038961,-84.375,-2.118114285 +279.038961,-70.3125,-1.765028573 +279.038961,-56.25,-1.402285715 +279.038961,-42.1875,-1.03 +279.038961,-28.125,-0.648057143 +279.038961,-14.0625,-0.256548573 +279.038961,0,0.161171428 +279.038961,14.0625,0.623542858 +279.038961,28.125,1.095714285 +279.038961,42.1875,1.577657143 +279.038961,56.25,2.069428573 +279.038961,70.3125,2.570971428 +279.038961,84.375,3.082342858 +279.038961,98.4375,3.603542858 +279.038961,112.5,4.134514285 +279.038961,126.5625,4.675257143 +279.038961,140.625,5.225828573 +279.038961,154.6875,5.786285715 +279.038961,168.75,6.356571428 +279.038961,182.8125,6.936571428 +279.038961,196.875,7.526285715 +279.038961,210.9375,8.125714285 +279.038961,225,8.734857143 +279.038961,239.0625,9.354285715 +279.038961,253.125,9.983428573 +279.038961,267.1875,10.62171429 +279.038961,281.25,11.27028572 +279.038961,295.3125,11.92914286 +279.038961,309.375,12.59714286 +279.038961,323.4375,13.27485714 +279.038961,337.5,13.96285714 +279.038961,351.5625,14.66057143 +279.038961,365.625,15.368 +279.038961,379.6875,16.08514286 +279.038961,393.75,16.812 +279.038961,407.8125,17.54857143 +279.038961,421.875,18.29542857 +279.038961,435.9375,19.05142857 +279.038961,450,19.81771429 +325.5487013,-450,-10.16571429 +325.5487013,-435.9375,-9.991428573 +325.5487013,-421.875,-9.808 +325.5487013,-407.8125,-9.614285715 +325.5487013,-393.75,-9.411428573 +325.5487013,-379.6875,-9.198857143 +325.5487013,-365.625,-8.976571428 +325.5487013,-351.5625,-8.745142858 +325.5487013,-337.5,-8.503428573 +325.5487013,-323.4375,-8.252571428 +325.5487013,-309.375,-7.992 +325.5487013,-295.3125,-7.721714285 +325.5487013,-281.25,-7.442285715 +325.5487013,-267.1875,-7.152571428 +325.5487013,-253.125,-6.853714285 +325.5487013,-239.0625,-6.545142858 +325.5487013,-225,-6.226857143 +325.5487013,-210.9375,-5.899428573 +325.5487013,-196.875,-5.561771428 +325.5487013,-182.8125,-5.214742858 +325.5487013,-168.75,-4.858057143 +325.5487013,-154.6875,-4.491828573 +325.5487013,-140.625,-4.116 +325.5487013,-126.5625,-3.730514285 +325.5487013,-112.5,-3.335485715 +325.5487013,-98.4375,-2.9308 +325.5487013,-84.375,-2.516514285 +325.5487013,-70.3125,-2.092628573 +325.5487013,-56.25,-1.659142858 +325.5487013,-42.1875,-1.216057143 +325.5487013,-28.125,-0.763371428 +325.5487013,-14.0625,-0.301045715 +325.5487013,0,0.188308573 +325.5487013,14.0625,0.722914285 +325.5487013,28.125,1.267257143 +325.5487013,42.1875,1.821428573 +325.5487013,56.25,2.385428573 +325.5487013,70.3125,2.9592 +325.5487013,84.375,3.5428 +325.5487013,98.4375,4.136171428 +325.5487013,112.5,4.739371428 +325.5487013,126.5625,5.352342858 +325.5487013,140.625,5.974857143 +325.5487013,154.6875,6.607428573 +325.5487013,168.75,7.250285715 +325.5487013,182.8125,7.902285715 +325.5487013,196.875,8.564 +325.5487013,210.9375,9.236 +325.5487013,225,9.917714285 +325.5487013,239.0625,10.60914286 +325.5487013,253.125,11.31028572 +325.5487013,267.1875,12.02114286 +325.5487013,281.25,12.74171429 +325.5487013,295.3125,13.47257143 +325.5487013,309.375,14.21314286 +325.5487013,323.4375,14.96285714 +325.5487013,337.5,15.72285714 +325.5487013,351.5625,16.49314286 +325.5487013,365.625,17.27257143 +325.5487013,379.6875,18.06171429 +325.5487013,393.75,18.86114286 +325.5487013,407.8125,19.67028572 +325.5487013,421.875,20.48914286 +325.5487013,435.9375,21.31771429 +325.5487013,450,22.156 +372.0487013,-450,-12.40342857 +372.0487013,-435.9375,-12.15828572 +372.0487013,-421.875,-11.904 +372.0487013,-407.8125,-11.64 +372.0487013,-393.75,-11.36628572 +372.0487013,-379.6875,-11.08285714 +372.0487013,-365.625,-10.78971429 +372.0487013,-351.5625,-10.48742857 +372.0487013,-337.5,-10.17542857 +372.0487013,-323.4375,-9.853714285 +372.0487013,-309.375,-9.522285715 +372.0487013,-295.3125,-9.181142858 +372.0487013,-281.25,-8.830857143 +372.0487013,-267.1875,-8.470285715 +372.0487013,-253.125,-8.100571428 +372.0487013,-239.0625,-7.721142858 +372.0487013,-225,-7.332 +372.0487013,-210.9375,-6.933714285 +372.0487013,-196.875,-6.525142858 +372.0487013,-182.8125,-6.107428573 +372.0487013,-168.75,-5.680171428 +372.0487013,-154.6875,-5.243142858 +372.0487013,-140.625,-4.796514285 +372.0487013,-126.5625,-4.340285715 +372.0487013,-112.5,-3.8744 +372.0487013,-98.4375,-3.398971428 +372.0487013,-84.375,-2.913885715 +372.0487013,-70.3125,-2.419257143 +372.0487013,-56.25,-1.914971428 +372.0487013,-42.1875,-1.401085715 +372.0487013,-28.125,-0.8776 +372.0487013,-14.0625,-0.344502858 +372.0487013,0,0.216508573 +372.0487013,14.0625,0.823314285 +372.0487013,28.125,1.439885715 +372.0487013,42.1875,2.066285715 +372.0487013,56.25,2.702457143 +372.0487013,70.3125,3.348457143 +372.0487013,84.375,4.004285715 +372.0487013,98.4375,4.669885715 +372.0487013,112.5,5.345257143 +372.0487013,126.5625,6.030285715 +372.0487013,140.625,6.725714285 +372.0487013,154.6875,7.430285715 +372.0487013,168.75,8.145142858 +372.0487013,182.8125,8.869142858 +372.0487013,196.875,9.603428573 +372.0487013,210.9375,10.34742857 +372.0487013,225,11.10114286 +372.0487013,239.0625,11.86514286 +372.0487013,253.125,12.63828572 +372.0487013,267.1875,13.42171429 +372.0487013,281.25,14.21428572 +372.0487013,295.3125,15.01714286 +372.0487013,309.375,15.82971429 +372.0487013,323.4375,16.652 +372.0487013,337.5,17.48457143 +372.0487013,351.5625,18.32628572 +372.0487013,365.625,19.17828572 +372.0487013,379.6875,20.04 +372.0487013,393.75,20.91142857 +372.0487013,407.8125,21.79257143 +372.0487013,421.875,22.68342857 +372.0487013,435.9375,23.58457143 +372.0487013,450,24.49485714 +418.5584415,-450,-14.64 +418.5584415,-435.9375,-14.32457143 +418.5584415,-421.875,-13.99942857 +418.5584415,-407.8125,-13.664 +418.5584415,-393.75,-13.32 +418.5584415,-379.6875,-12.96571429 +418.5584415,-365.625,-12.60171429 +418.5584415,-351.5625,-12.22857143 +418.5584415,-337.5,-11.84571429 +418.5584415,-323.4375,-11.45314286 +418.5584415,-309.375,-11.05085714 +418.5584415,-295.3125,-10.63942857 +418.5584415,-281.25,-10.21771429 +418.5584415,-267.1875,-9.786857143 +418.5584415,-253.125,-9.346285715 +418.5584415,-239.0625,-8.896 +418.5584415,-225,-8.436571428 +418.5584415,-210.9375,-7.966857143 +418.5584415,-196.875,-7.488 +418.5584415,-182.8125,-6.999428573 +418.5584415,-168.75,-6.501142858 +418.5584415,-154.6875,-5.993142858 +418.5584415,-140.625,-5.476 +418.5584415,-126.5625,-4.948971428 +418.5584415,-112.5,-4.412342858 +418.5584415,-98.4375,-3.866114285 +418.5584415,-84.375,-3.310228573 +418.5584415,-70.3125,-2.7448 +418.5584415,-56.25,-2.169714285 +418.5584415,-42.1875,-1.585085715 +418.5584415,-28.125,-0.9908 +418.5584415,-14.0625,-0.38692 +418.5584415,0,0.245771428 +418.5584415,14.0625,0.9248 +418.5584415,28.125,1.6136 +418.5584415,42.1875,2.312171428 +418.5584415,56.25,3.020628573 +418.5584415,70.3125,3.7388 +418.5584415,84.375,4.4668 +418.5584415,98.4375,5.204628573 +418.5584415,112.5,5.952 +418.5584415,126.5625,6.709714285 +418.5584415,140.625,7.477142858 +418.5584415,154.6875,8.253714285 +418.5584415,168.75,9.040571428 +418.5584415,182.8125,9.837142858 +418.5584415,196.875,10.644 +418.5584415,210.9375,11.46 +418.5584415,225,12.28571429 +418.5584415,239.0625,13.12171429 +418.5584415,253.125,13.96742857 +418.5584415,267.1875,14.82285714 +418.5584415,281.25,15.688 +418.5584415,295.3125,16.56285714 +418.5584415,309.375,17.448 +418.5584415,323.4375,18.34228572 +418.5584415,337.5,19.24685714 +418.5584415,351.5625,20.16114286 +418.5584415,365.625,21.08514286 +418.5584415,379.6875,22.01885714 +418.5584415,393.75,22.96285714 +418.5584415,407.8125,23.916 +418.5584415,421.875,24.87942857 +418.5584415,435.9375,25.852 +418.5584415,450,26.83485715 +465.0584415,-450,-16.876 +465.0584415,-435.9375,-16.48914286 +465.0584415,-421.875,-16.09314286 +465.0584415,-407.8125,-15.68742857 +465.0584415,-393.75,-15.27257143 +465.0584415,-379.6875,-14.84742857 +465.0584415,-365.625,-14.41314286 +465.0584415,-351.5625,-13.96857143 +465.0584415,-337.5,-13.51485714 +465.0584415,-323.4375,-13.052 +465.0584415,-309.375,-12.57885714 +465.0584415,-295.3125,-12.09657143 +465.0584415,-281.25,-11.604 +465.0584415,-267.1875,-11.10228572 +465.0584415,-253.125,-10.59085714 +465.0584415,-239.0625,-10.07028572 +465.0584415,-225,-9.539428573 +465.0584415,-210.9375,-8.999428573 +465.0584415,-196.875,-8.449714285 +465.0584415,-182.8125,-7.890285715 +465.0584415,-168.75,-7.321142858 +465.0584415,-154.6875,-6.742857143 +465.0584415,-140.625,-6.154285715 +465.0584415,-126.5625,-5.556628573 +465.0584415,-112.5,-4.9492 +465.0584415,-98.4375,-4.332171428 +465.0584415,-84.375,-3.705542858 +465.0584415,-70.3125,-3.069314285 +465.0584415,-56.25,-2.423485715 +465.0584415,-42.1875,-1.768 +465.0584415,-28.125,-1.102971428 +465.0584415,-14.0625,-0.428291428 +465.0584415,0,0.276097143 +465.0584415,14.0625,1.027314285 +465.0584415,28.125,1.788342858 +465.0584415,42.1875,2.559142858 +465.0584415,56.25,3.339771428 +465.0584415,70.3125,4.130228573 +465.0584415,84.375,4.930457143 +465.0584415,98.4375,5.740571428 +465.0584415,112.5,6.560571428 +465.0584415,126.5625,7.389714285 +465.0584415,140.625,8.229142858 +465.0584415,154.6875,9.078857143 +465.0584415,168.75,9.937714285 +465.0584415,182.8125,10.80628572 +465.0584415,196.875,11.68514286 +465.0584415,210.9375,12.57371429 +465.0584415,225,13.472 +465.0584415,239.0625,14.38 +465.0584415,253.125,15.29771429 +465.0584415,267.1875,16.22514286 +465.0584415,281.25,17.16285714 +465.0584415,295.3125,18.10971429 +465.0584415,309.375,19.06685714 +465.0584415,323.4375,20.03371429 +465.0584415,337.5,21.01028572 +465.0584415,351.5625,21.99657143 +465.0584415,365.625,22.99314286 +465.0584415,379.6875,23.99885714 +465.0584415,393.75,25.01485715 +465.0584415,407.8125,26.04057143 +465.0584415,421.875,27.076 +465.0584415,435.9375,28.12114285 +465.0584415,450,29.176 +511.5681818,-450,-19.11028572 +511.5681818,-435.9375,-18.65314286 +511.5681818,-421.875,-18.18628572 +511.5681818,-407.8125,-17.70971429 +511.5681818,-393.75,-17.224 +511.5681818,-379.6875,-16.728 +511.5681818,-365.625,-16.22285714 +511.5681818,-351.5625,-15.708 +511.5681818,-337.5,-15.18342857 +511.5681818,-323.4375,-14.64914286 +511.5681818,-309.375,-14.10571429 +511.5681818,-295.3125,-13.55257143 +511.5681818,-281.25,-12.98971429 +511.5681818,-267.1875,-12.41714286 +511.5681818,-253.125,-11.83485714 +511.5681818,-239.0625,-11.24285714 +511.5681818,-225,-10.64171429 +511.5681818,-210.9375,-10.03085714 +511.5681818,-196.875,-9.410285715 +511.5681818,-182.8125,-8.78 +511.5681818,-168.75,-8.14 +511.5681818,-154.6875,-7.490857143 +511.5681818,-140.625,-6.832 +511.5681818,-126.5625,-6.163428573 +511.5681818,-112.5,-5.485028573 +511.5681818,-98.4375,-4.7972 +511.5681818,-84.375,-4.099828573 +511.5681818,-70.3125,-3.3928 +511.5681818,-56.25,-2.676171428 +511.5681818,-42.1875,-1.949942858 +511.5681818,-28.125,-1.214057143 +511.5681818,-14.0625,-0.468622858 +511.5681818,0,0.30748 +511.5681818,14.0625,1.130914285 +511.5681818,28.125,1.964171428 +511.5681818,42.1875,2.8072 +511.5681818,56.25,3.660057143 +511.5681818,70.3125,4.522685715 +511.5681818,84.375,5.395085715 +511.5681818,98.4375,6.277142858 +511.5681818,112.5,7.169142858 +511.5681818,126.5625,8.071428573 +511.5681818,140.625,8.982857143 +511.5681818,154.6875,9.904571428 +511.5681818,168.75,10.83542857 +511.5681818,182.8125,11.77657143 +511.5681818,196.875,12.72742857 +511.5681818,210.9375,13.688 +511.5681818,225,14.65828572 +511.5681818,239.0625,15.63885714 +511.5681818,253.125,16.62857143 +511.5681818,267.1875,17.62857143 +511.5681818,281.25,18.63828572 +511.5681818,295.3125,19.65771429 +511.5681818,309.375,20.68685714 +511.5681818,323.4375,21.72628572 +511.5681818,337.5,22.77485714 +511.5681818,351.5625,23.83371429 +511.5681818,365.625,24.90228572 +511.5681818,379.6875,25.98 +511.5681818,393.75,27.06857143 +511.5681818,407.8125,28.16628573 +511.5681818,421.875,29.27371428 +511.5681818,435.9375,30.39142858 +511.5681818,450,31.51828573 +558.077922,-450,-21.344 +558.077922,-435.9375,-20.816 +558.077922,-421.875,-20.27828572 +558.077922,-407.8125,-19.73142857 +558.077922,-393.75,-19.17428572 +558.077922,-379.6875,-18.608 +558.077922,-365.625,-18.032 +558.077922,-351.5625,-17.44628572 +558.077922,-337.5,-16.85085714 +558.077922,-323.4375,-16.24571429 +558.077922,-309.375,-15.63142857 +558.077922,-295.3125,-15.00742857 +558.077922,-281.25,-14.37371429 +558.077922,-267.1875,-13.73028572 +558.077922,-253.125,-13.07714286 +558.077922,-239.0625,-12.41485714 +558.077922,-225,-11.74285714 +558.077922,-210.9375,-11.06114286 +558.077922,-196.875,-10.36971429 +558.077922,-182.8125,-9.668571428 +558.077922,-168.75,-8.958285715 +558.077922,-154.6875,-8.237714285 +558.077922,-140.625,-7.508 +558.077922,-126.5625,-6.768571428 +558.077922,-112.5,-6.02 +558.077922,-98.4375,-5.2612 +558.077922,-84.375,-4.493028573 +558.077922,-70.3125,-3.7152 +558.077922,-56.25,-2.927771428 +558.077922,-42.1875,-2.1308 +558.077922,-28.125,-1.324171428 +558.077922,-14.0625,-0.50792 +558.077922,0,0.339925715 +558.077922,14.0625,1.2356 +558.077922,28.125,2.141028573 +558.077922,42.1875,3.056285715 +558.077922,56.25,3.981314285 +558.077922,70.3125,4.916171428 +558.077922,84.375,5.860571428 +558.077922,98.4375,6.815428573 +558.077922,112.5,7.779428573 +558.077922,126.5625,8.753714285 +558.077922,140.625,9.737714285 +558.077922,154.6875,10.73085714 +558.077922,168.75,11.73485714 +558.077922,182.8125,12.748 +558.077922,196.875,13.77085714 +558.077922,210.9375,14.804 +558.077922,225,15.84628572 +558.077922,239.0625,16.89885714 +558.077922,253.125,17.96114286 +558.077922,267.1875,19.03314286 +558.077922,281.25,20.11485714 +558.077922,295.3125,21.20685714 +558.077922,309.375,22.308 +558.077922,323.4375,23.41942857 +558.077922,337.5,24.54057143 +558.077922,351.5625,25.67142858 +558.077922,365.625,26.812 +558.077922,379.6875,27.96228573 +558.077922,393.75,29.12285715 +558.077922,407.8125,30.29257143 +558.077922,421.875,31.47257143 +558.077922,435.9375,32.66228573 +558.077922,450,33.86171428 +930.1266235,-450,-39.17542858 +930.1266235,-435.9375,-38.08114285 +930.1266235,-421.875,-36.97771428 +930.1266235,-407.8125,-35.864 +930.1266235,-393.75,-34.74057143 +930.1266235,-379.6875,-33.608 +930.1266235,-365.625,-32.46571428 +930.1266235,-351.5625,-31.31371428 +930.1266235,-337.5,-30.152 +930.1266235,-323.4375,-28.98114285 +930.1266235,-309.375,-27.8 +930.1266235,-295.3125,-26.60971428 +930.1266235,-281.25,-25.40971428 +930.1266235,-267.1875,-24.2 +930.1266235,-253.125,-22.98114286 +930.1266235,-239.0625,-21.752 +930.1266235,-225,-20.51371429 +930.1266235,-210.9375,-19.26571429 +930.1266235,-196.875,-18.008 +930.1266235,-182.8125,-16.74114286 +930.1266235,-168.75,-15.464 +930.1266235,-154.6875,-14.17771429 +930.1266235,-140.625,-12.88171429 +930.1266235,-126.5625,-11.576 +930.1266235,-112.5,-10.26057143 +930.1266235,-98.4375,-8.936 +930.1266235,-84.375,-7.601142858 +930.1266235,-70.3125,-6.257142858 +930.1266235,-56.25,-4.903542858 +930.1266235,-42.1875,-3.540228573 +930.1266235,-28.125,-2.167314285 +930.1266235,-14.0625,-0.7848 +930.1266235,0,0.637714285 +930.1266235,14.0625,2.111085715 +930.1266235,28.125,3.594285715 +930.1266235,42.1875,5.087257143 +930.1266235,56.25,6.590285715 +930.1266235,70.3125,8.102857143 +930.1266235,84.375,9.625142858 +930.1266235,98.4375,11.15714286 +930.1266235,112.5,12.69885714 +930.1266235,126.5625,14.25085714 +930.1266235,140.625,15.81257143 +930.1266235,154.6875,17.384 +930.1266235,168.75,18.96514286 +930.1266235,182.8125,20.556 +930.1266235,196.875,22.15657143 +930.1266235,210.9375,23.76742857 +930.1266235,225,25.388 +930.1266235,239.0625,27.01771428 +930.1266235,253.125,28.65771428 +930.1266235,267.1875,30.30742858 +930.1266235,281.25,31.96742858 +930.1266235,295.3125,33.63657143 +930.1266235,309.375,35.316 +930.1266235,323.4375,37.00457143 +930.1266235,337.5,38.70342858 +930.1266235,351.5625,40.412 +930.1266235,365.625,42.13028573 +930.1266235,379.6875,43.85885715 +930.1266235,393.75,45.59657143 +930.1266235,407.8125,47.34457143 +930.1266235,421.875,49.10228573 +930.1266235,435.9375,50.86971428 +930.1266235,450,52.64685715 +1162.694805,-450,-50.28685715 +1162.694805,-435.9375,-48.83828573 +1162.694805,-421.875,-47.38057143 +1162.694805,-407.8125,-45.91314285 +1162.694805,-393.75,-44.436 +1162.694805,-379.6875,-42.94914285 +1162.694805,-365.625,-41.45314285 +1162.694805,-351.5625,-39.94742858 +1162.694805,-337.5,-38.43142858 +1162.694805,-323.4375,-36.90628573 +1162.694805,-309.375,-35.372 +1162.694805,-295.3125,-33.82742858 +1162.694805,-281.25,-32.27371428 +1162.694805,-267.1875,-30.71028573 +1162.694805,-253.125,-29.13714285 +1162.694805,-239.0625,-27.55428573 +1162.694805,-225,-25.96171428 +1162.694805,-210.9375,-24.36 +1162.694805,-196.875,-22.74857143 +1162.694805,-182.8125,-21.12742857 +1162.694805,-168.75,-19.49657143 +1162.694805,-154.6875,-17.856 +1162.694805,-140.625,-16.20628572 +1162.694805,-126.5625,-14.54628572 +1162.694805,-112.5,-12.87714286 +1162.694805,-98.4375,-11.19828572 +1162.694805,-84.375,-9.510285715 +1162.694805,-70.3125,-7.812 +1162.694805,-56.25,-6.104571428 +1162.694805,-42.1875,-4.387314285 +1162.694805,-28.125,-2.660457143 +1162.694805,-14.0625,-0.924057143 +1162.694805,0,0.858342858 +1162.694805,14.0625,2.6928 +1162.694805,28.125,4.537028573 +1162.694805,42.1875,6.390857143 +1162.694805,56.25,8.254857143 +1162.694805,70.3125,10.12857143 +1162.694805,84.375,12.012 +1162.694805,98.4375,13.90514286 +1162.694805,112.5,15.80857143 +1162.694805,126.5625,17.72114286 +1162.694805,140.625,19.644 +1162.694805,154.6875,21.576 +1162.694805,168.75,23.51828572 +1162.694805,182.8125,25.47085715 +1162.694805,196.875,27.43257143 +1162.694805,210.9375,29.404 +1162.694805,225,31.38571428 +1162.694805,239.0625,33.37657143 +1162.694805,253.125,35.37771428 +1162.694805,267.1875,37.38857143 +1162.694805,281.25,39.40914285 +1162.694805,295.3125,41.44 +1162.694805,309.375,43.48 +1162.694805,323.4375,45.53028573 +1162.694805,337.5,47.58971428 +1162.694805,351.5625,49.65942858 +1162.694805,365.625,51.73885715 +1162.694805,379.6875,53.82857143 +1162.694805,393.75,55.92742858 +1162.694805,407.8125,58.03428573 +1162.694805,421.875,60.15428573 +1162.694805,435.9375,62.28571428 +1162.694805,450,64.42285715 +1395.194805,-450,-61.37142858 +1395.194805,-435.9375,-59.57142858 +1395.194805,-421.875,-57.76 +1395.194805,-407.8125,-55.936 +1395.194805,-393.75,-54.10514285 +1395.194805,-379.6875,-52.26457143 +1395.194805,-365.625,-50.41428573 +1395.194805,-351.5625,-48.55428573 +1395.194805,-337.5,-46.68514285 +1395.194805,-323.4375,-44.80628573 +1395.194805,-309.375,-42.91771428 +1395.194805,-295.3125,-41.01942858 +1395.194805,-281.25,-39.11142858 +1395.194805,-267.1875,-37.19371428 +1395.194805,-253.125,-35.26685715 +1395.194805,-239.0625,-33.33028573 +1395.194805,-225,-31.384 +1395.194805,-210.9375,-29.428 +1395.194805,-196.875,-27.46285715 +1395.194805,-182.8125,-25.48742858 +1395.194805,-168.75,-23.50285714 +1395.194805,-154.6875,-21.50857143 +1395.194805,-140.625,-19.50457143 +1395.194805,-126.5625,-17.49142857 +1395.194805,-112.5,-15.468 +1395.194805,-98.4375,-13.43542857 +1395.194805,-84.375,-11.39314286 +1395.194805,-70.3125,-9.341142858 +1395.194805,-56.25,-7.279428573 +1395.194805,-42.1875,-5.2084 +1395.194805,-28.125,-3.127657143 +1395.194805,-14.0625,-1.037257143 +1395.194805,0,1.105485715 +1395.194805,14.0625,3.301028573 +1395.194805,28.125,5.506342858 +1395.194805,42.1875,7.721714285 +1395.194805,56.25,9.946285715 +1395.194805,70.3125,12.18114286 +1395.194805,84.375,14.42571429 +1395.194805,98.4375,16.68 +1395.194805,112.5,18.944 +1395.194805,126.5625,21.21771429 +1395.194805,140.625,23.50171429 +1395.194805,154.6875,25.79542858 +1395.194805,168.75,28.09885715 +1395.194805,182.8125,30.41142858 +1395.194805,196.875,32.73485715 +1395.194805,210.9375,35.06742858 +1395.194805,225,37.40971428 +1395.194805,239.0625,39.76228573 +1395.194805,253.125,42.12457143 +1395.194805,267.1875,44.496 +1395.194805,281.25,46.87828573 +1395.194805,295.3125,49.26971428 +1395.194805,309.375,51.67085715 +1395.194805,323.4375,54.08228573 +1395.194805,337.5,56.50285715 +1395.194805,351.5625,58.93142858 +1395.194805,365.625,61.37142858 +1395.194805,379.6875,63.82285715 +1395.194805,393.75,66.28571428 +1395.194805,407.8125,68.75428573 +1395.194805,421.875,71.23428573 +1395.194805,435.9375,73.72571428 +1395.194805,450,76.22285715 +1627.694805,-450,-72.42857143 +1627.694805,-435.9375,-70.27428573 +1627.694805,-421.875,-68.10857143 +1627.694805,-407.8125,-65.93142858 +1627.694805,-393.75,-63.74857143 +1627.694805,-379.6875,-61.55428573 +1627.694805,-365.625,-59.34857143 +1627.694805,-351.5625,-57.136 +1627.694805,-337.5,-54.91257143 +1627.694805,-323.4375,-52.67942858 +1627.694805,-309.375,-50.43714285 +1627.694805,-295.3125,-48.18514285 +1627.694805,-281.25,-45.92342858 +1627.694805,-267.1875,-43.652 +1627.694805,-253.125,-41.37085715 +1627.694805,-239.0625,-39.08057143 +1627.694805,-225,-36.78 +1627.694805,-210.9375,-34.47028573 +1627.694805,-196.875,-32.15085715 +1627.694805,-182.8125,-29.82171428 +1627.694805,-168.75,-27.48342858 +1627.694805,-154.6875,-25.13485715 +1627.694805,-140.625,-22.77714286 +1627.694805,-126.5625,-20.40971429 +1627.694805,-112.5,-18.03257143 +1627.694805,-98.4375,-15.64628572 +1627.694805,-84.375,-13.24971429 +1627.694805,-70.3125,-10.844 +1627.694805,-56.25,-8.428571428 +1627.694805,-42.1875,-6.003428573 +1627.694805,-28.125,-3.568742858 +1627.694805,-14.0625,-1.124457143 +1627.694805,0,1.3792 +1627.694805,14.0625,3.935771428 +1627.694805,28.125,6.502285715 +1627.694805,42.1875,9.078285715 +1627.694805,56.25,11.66457143 +1627.694805,70.3125,14.26 +1627.694805,84.375,16.86571429 +1627.694805,98.4375,19.48114286 +1627.694805,112.5,22.10628572 +1627.694805,126.5625,24.74114286 +1627.694805,140.625,27.38628573 +1627.694805,154.6875,30.04057143 +1627.694805,168.75,32.70514285 +1627.694805,182.8125,35.37942858 +1627.694805,196.875,38.06342858 +1627.694805,210.9375,40.75714285 +1627.694805,225,43.46057143 +1627.694805,239.0625,46.17428573 +1627.694805,253.125,48.89714285 +1627.694805,267.1875,51.63028573 +1627.694805,281.25,54.37314285 +1627.694805,295.3125,57.12571428 +1627.694805,309.375,59.88571428 +1627.694805,323.4375,62.66285715 +1627.694805,337.5,65.44 +1627.694805,351.5625,68.23428573 +1627.694805,365.625,71.03428573 +1627.694805,379.6875,73.84571428 +1627.694805,393.75,76.66857143 +1627.694805,407.8125,79.49714285 +1627.694805,421.875,82.34285715 +1627.694805,435.9375,85.18857143 +1627.694805,450,88.05142858 +1860.292208,-450,-83.46285715 +1860.292208,-435.9375,-80.95428573 +1860.292208,-421.875,-78.43428573 +1860.292208,-407.8125,-75.90285715 +1860.292208,-393.75,-73.36571428 +1860.292208,-379.6875,-70.81714285 +1860.292208,-365.625,-68.25714285 +1860.292208,-351.5625,-65.69142858 +1860.292208,-337.5,-63.11428573 +1860.292208,-323.4375,-60.52571428 +1860.292208,-309.375,-57.93142858 +1860.292208,-295.3125,-55.32457143 +1860.292208,-281.25,-52.70914285 +1860.292208,-267.1875,-50.08342858 +1860.292208,-253.125,-47.44857143 +1860.292208,-239.0625,-44.804 +1860.292208,-225,-42.15028573 +1860.292208,-210.9375,-39.48628573 +1860.292208,-196.875,-36.81314285 +1860.292208,-182.8125,-34.13028573 +1860.292208,-168.75,-31.43771428 +1860.292208,-154.6875,-28.73542858 +1860.292208,-140.625,-26.024 +1860.292208,-126.5625,-23.30228572 +1860.292208,-112.5,-20.57142857 +1860.292208,-98.4375,-17.83085714 +1860.292208,-84.375,-15.08057143 +1860.292208,-70.3125,-12.32114286 +1860.292208,-56.25,-9.551428573 +1860.292208,-42.1875,-6.772571428 +1860.292208,-28.125,-3.983885715 +1860.292208,-14.0625,-1.185657143 +1860.292208,0,1.679428573 +1860.292208,14.0625,4.597085715 +1860.292208,28.125,7.524571428 +1860.292208,42.1875,10.46171429 +1860.292208,56.25,13.40914286 +1860.292208,70.3125,16.36571429 +1860.292208,84.375,19.33257143 +1860.292208,98.4375,22.30914286 +1860.292208,112.5,25.29542858 +1860.292208,126.5625,28.29142858 +1860.292208,140.625,31.29714285 +1860.292208,154.6875,34.31257143 +1860.292208,168.75,37.33828573 +1860.292208,182.8125,40.37371428 +1860.292208,196.875,43.41885715 +1860.292208,210.9375,46.47371428 +1860.292208,225,49.53828573 +1860.292208,239.0625,52.61257143 +1860.292208,253.125,55.69714285 +1860.292208,267.1875,58.78857143 +1860.292208,281.25,61.89714285 +1860.292208,295.3125,65.01142858 +1860.292208,309.375,68.13142858 +1860.292208,323.4375,71.26285715 +1860.292208,337.5,74.40571428 +1860.292208,351.5625,77.56 +1860.292208,365.625,80.72571428 +1860.292208,379.6875,83.89714285 +1860.292208,393.75,87.08 +1860.292208,407.8125,90.26857143 +1860.292208,421.875,93.47428573 +1860.292208,435.9375,96.68571428 +1860.292208,450,99.90857143 +2092.792208,-450,-94.46857143 +2092.792208,-435.9375,-91.60571428 +2092.792208,-421.875,-88.73142858 +2092.792208,-407.8125,-85.85142858 +2092.792208,-393.75,-82.95428573 +2092.792208,-379.6875,-80.05714285 +2092.792208,-365.625,-77.14285715 +2092.792208,-351.5625,-74.22285715 +2092.792208,-337.5,-71.29142858 +2092.792208,-323.4375,-68.34857143 +2092.792208,-309.375,-65.4 +2092.792208,-295.3125,-62.44 +2092.792208,-281.25,-59.46857143 +2092.792208,-267.1875,-56.48971428 +2092.792208,-253.125,-53.50057143 +2092.792208,-239.0625,-50.50228573 +2092.792208,-225,-47.49428573 +2092.792208,-210.9375,-44.47657143 +2092.792208,-196.875,-41.44914285 +2092.792208,-182.8125,-38.41257143 +2092.792208,-168.75,-35.36628573 +2092.792208,-154.6875,-32.30971428 +2092.792208,-140.625,-29.244 +2092.792208,-126.5625,-26.16914285 +2092.792208,-112.5,-23.084 +2092.792208,-98.4375,-19.98971429 +2092.792208,-84.375,-16.88571429 +2092.792208,-70.3125,-13.772 +2092.792208,-56.25,-10.64857143 +2092.792208,-42.1875,-7.515428573 +2092.792208,-28.125,-4.373028573 +2092.792208,-14.0625,-1.220857143 +2092.792208,0,2.006171428 +2092.792208,14.0625,5.284914285 +2092.792208,28.125,8.573714285 +2092.792208,42.1875,11.872 +2092.792208,56.25,15.18 +2092.792208,70.3125,18.49771429 +2092.792208,84.375,21.82571429 +2092.792208,98.4375,25.16342858 +2092.792208,112.5,28.51028573 +2092.792208,126.5625,31.86742858 +2092.792208,140.625,35.23485715 +2092.792208,154.6875,38.61142858 +2092.792208,168.75,41.99771428 +2092.792208,182.8125,45.39428573 +2092.792208,196.875,48.80057143 +2092.792208,210.9375,52.21657143 +2092.792208,225,55.64228573 +2092.792208,239.0625,59.08 +2092.792208,253.125,62.52571428 +2092.792208,267.1875,65.97714285 +2092.792208,281.25,69.44571428 +2092.792208,295.3125,72.92 +2092.792208,309.375,76.4 +2092.792208,323.4375,79.89714285 +2092.792208,337.5,83.4 +2092.792208,351.5625,86.91428573 +2092.792208,365.625,90.44 +2092.792208,379.6875,93.97142858 +2092.792208,393.75,97.51428573 +2092.792208,407.8125,101.0685714 +2092.792208,421.875,104.6342857 +2092.792208,435.9375,108.2057143 +2092.792208,450,111.7885714 +2325.292208,-450,-105.4514286 +2325.292208,-435.9375,-102.2342857 +2325.292208,-421.875,-99.00571428 +2325.292208,-407.8125,-95.76571428 +2325.292208,-393.75,-92.52 +2325.292208,-379.6875,-89.26285715 +2325.292208,-365.625,-86 +2325.292208,-351.5625,-82.72571428 +2325.292208,-337.5,-79.44 +2325.292208,-323.4375,-76.14285715 +2325.292208,-309.375,-72.84 +2325.292208,-295.3125,-69.52571428 +2325.292208,-281.25,-66.2 +2325.292208,-267.1875,-62.86857143 +2325.292208,-253.125,-59.52571428 +2325.292208,-239.0625,-56.17428573 +2325.292208,-225,-52.812 +2325.292208,-210.9375,-49.44057143 +2325.292208,-196.875,-46.05942858 +2325.292208,-182.8125,-42.66857143 +2325.292208,-168.75,-39.26857143 +2325.292208,-154.6875,-35.85828573 +2325.292208,-140.625,-32.43885715 +2325.292208,-126.5625,-29.00971428 +2325.292208,-112.5,-25.57085715 +2325.292208,-98.4375,-22.12228572 +2325.292208,-84.375,-18.664 +2325.292208,-70.3125,-15.19657143 +2325.292208,-56.25,-11.71942857 +2325.292208,-42.1875,-8.232571428 +2325.292208,-28.125,-4.736114285 +2325.292208,-14.0625,-1.230057143 +2325.292208,0,2.359485715 +2325.292208,14.0625,5.999428573 +2325.292208,28.125,9.649142858 +2325.292208,42.1875,13.30857143 +2325.292208,56.25,16.97771429 +2325.292208,70.3125,20.65657143 +2325.292208,84.375,24.34514286 +2325.292208,98.4375,28.044 +2325.292208,112.5,31.75257143 +2325.292208,126.5625,35.47085715 +2325.292208,140.625,39.19885715 +2325.292208,154.6875,42.93657143 +2325.292208,168.75,46.684 +2325.292208,182.8125,50.44171428 +2325.292208,196.875,54.20857143 +2325.292208,210.9375,57.98857143 +2325.292208,225,61.77142858 +2325.292208,239.0625,65.57142858 +2325.292208,253.125,69.37714285 +2325.292208,267.1875,73.19428573 +2325.292208,281.25,77.01714285 +2325.292208,295.3125,80.85142858 +2325.292208,309.375,84.69714285 +2325.292208,323.4375,88.55428573 +2325.292208,337.5,92.42285715 +2325.292208,351.5625,96.29714285 +2325.292208,365.625,100.1771429 +2325.292208,379.6875,104.0742857 +2325.292208,393.75,107.9771429 +2325.292208,407.8125,111.8914286 +2325.292208,421.875,115.8171429 +2325.292208,435.9375,119.7485714 +2325.292208,450,123.6971429 +2557.88961,-450,-116.4057143 +2557.88961,-435.9375,-112.8342857 +2557.88961,-421.875,-109.2514286 +2557.88961,-407.8125,-105.6628572 +2557.88961,-393.75,-102.0628572 +2557.88961,-379.6875,-98.45142858 +2557.88961,-365.625,-94.82857143 +2557.88961,-351.5625,-91.2 +2557.88961,-337.5,-87.56 +2557.88961,-323.4375,-83.91428573 +2557.88961,-309.375,-80.25714285 +2557.88961,-295.3125,-76.58857143 +2557.88961,-281.25,-72.90857143 +2557.88961,-267.1875,-69.22285715 +2557.88961,-253.125,-65.52571428 +2557.88961,-239.0625,-61.82285715 +2557.88961,-225,-58.10285715 +2557.88961,-210.9375,-54.37885715 +2557.88961,-196.875,-50.64342858 +2557.88961,-182.8125,-46.89885715 +2557.88961,-168.75,-43.14457143 +2557.88961,-154.6875,-39.38057143 +2557.88961,-140.625,-35.60742858 +2557.88961,-126.5625,-31.824 +2557.88961,-112.5,-28.03142858 +2557.88961,-98.4375,-24.22914286 +2557.88961,-84.375,-20.41714286 +2557.88961,-70.3125,-16.59542857 +2557.88961,-56.25,-12.76457143 +2557.88961,-42.1875,-8.923428573 +2557.88961,-28.125,-5.0732 +2557.88961,-14.0625,-1.2132 +2557.88961,0,2.739314285 +2557.88961,14.0625,6.74 +2557.88961,28.125,10.75085714 +2557.88961,42.1875,14.77142857 +2557.88961,56.25,18.80171429 +2557.88961,70.3125,22.84171429 +2557.88961,84.375,26.89142858 +2557.88961,98.4375,30.95142858 +2557.88961,112.5,35.02114285 +2557.88961,126.5625,39.1 +2557.88961,140.625,43.18914285 +2557.88961,154.6875,47.288 +2557.88961,168.75,51.39714285 +2557.88961,182.8125,55.51542858 +2557.88961,196.875,59.64571428 +2557.88961,210.9375,63.78285715 +2557.88961,225,67.93142858 +2557.88961,239.0625,72.08571428 +2557.88961,253.125,76.25714285 +2557.88961,267.1875,80.43428573 +2557.88961,281.25,84.61714285 +2557.88961,295.3125,88.81714285 +2557.88961,309.375,93.02285715 +2557.88961,323.4375,97.24 +2557.88961,337.5,101.4685714 +2557.88961,351.5625,105.7028572 +2557.88961,365.625,109.9485714 +2557.88961,379.6875,114.2057143 +2557.88961,393.75,118.4685714 +2557.88961,407.8125,122.7428572 +2557.88961,421.875,127.0285714 +2557.88961,435.9375,131.3257143 +2557.88961,450,135.6285714 +2790.38961,-450,-127.3371429 +2790.38961,-435.9375,-123.4114286 +2790.38961,-421.875,-119.4742857 +2790.38961,-407.8125,-115.5314286 +2790.38961,-393.75,-111.5714286 +2790.38961,-379.6875,-107.6114286 +2790.38961,-365.625,-103.6342857 +2790.38961,-351.5625,-99.65142858 +2790.38961,-337.5,-95.65714285 +2790.38961,-323.4375,-91.65714285 +2790.38961,-309.375,-87.64571428 +2790.38961,-295.3125,-83.62285715 +2790.38961,-281.25,-79.59428573 +2790.38961,-267.1875,-75.54857143 +2790.38961,-253.125,-71.50285715 +2790.38961,-239.0625,-67.44 +2790.38961,-225,-63.37142858 +2790.38961,-210.9375,-59.29142858 +2790.38961,-196.875,-55.20171428 +2790.38961,-182.8125,-51.10342858 +2790.38961,-168.75,-46.99485715 +2790.38961,-154.6875,-42.87714285 +2790.38961,-140.625,-38.74971428 +2790.38961,-126.5625,-34.61257143 +2790.38961,-112.5,-30.46571428 +2790.38961,-98.4375,-26.30971428 +2790.38961,-84.375,-22.144 +2790.38961,-70.3125,-17.96857143 +2790.38961,-56.25,-13.78342857 +2790.38961,-42.1875,-9.588571428 +2790.38961,-28.125,-5.384285715 +2790.38961,-14.0625,-1.170342858 +2790.38961,0,3.145714285 +2790.38961,14.0625,7.507428573 +2790.38961,28.125,11.87942857 +2790.38961,42.1875,16.26114286 +2790.38961,56.25,20.65257143 +2790.38961,70.3125,25.05371428 +2790.38961,84.375,29.46457143 +2790.38961,98.4375,33.88514285 +2790.38961,112.5,38.316 +2790.38961,126.5625,42.756 +2790.38961,140.625,47.20628573 +2790.38961,154.6875,51.66628573 +2790.38961,168.75,56.136 +2790.38961,182.8125,60.61714285 +2790.38961,196.875,65.10285715 +2790.38961,210.9375,69.60571428 +2790.38961,225,74.11428573 +2790.38961,239.0625,78.63428573 +2790.38961,253.125,83.16 +2790.38961,267.1875,87.69714285 +2790.38961,281.25,92.24571428 +2790.38961,295.3125,96.80571428 +2790.38961,309.375,101.3714286 +2790.38961,323.4375,105.9485714 +2790.38961,337.5,110.5371429 +2790.38961,351.5625,115.1371429 +2790.38961,365.625,119.7428572 +2790.38961,379.6875,124.36 +2790.38961,393.75,128.9828572 +2790.38961,407.8125,133.6228572 +2790.38961,421.875,138.2685714 +2790.38961,435.9375,142.9257143 +2790.38961,450,147.5885714 +3022.88961,-450,-138.24 +3022.88961,-435.9375,-133.96 +3022.88961,-421.875,-129.6685714 +3022.88961,-407.8125,-125.3714286 +3022.88961,-393.75,-121.0628572 +3022.88961,-379.6875,-116.7428572 +3022.88961,-365.625,-112.4171429 +3022.88961,-351.5625,-108.08 +3022.88961,-337.5,-103.7314286 +3022.88961,-323.4375,-99.37714285 +3022.88961,-309.375,-95.01142858 +3022.88961,-295.3125,-90.63428573 +3022.88961,-281.25,-86.24571428 +3022.88961,-267.1875,-81.85142858 +3022.88961,-253.125,-77.44571428 +3022.88961,-239.0625,-73.03428573 +3022.88961,-225,-68.61142858 +3022.88961,-210.9375,-64.17714285 +3022.88961,-196.875,-59.73142858 +3022.88961,-182.8125,-55.28171428 +3022.88961,-168.75,-50.81942858 +3022.88961,-154.6875,-46.34742858 +3022.88961,-140.625,-41.86628573 +3022.88961,-126.5625,-37.37542858 +3022.88961,-112.5,-32.87485715 +3022.88961,-98.4375,-28.36457143 +3022.88961,-84.375,-23.84457143 +3022.88961,-70.3125,-19.31542857 +3022.88961,-56.25,-14.776 +3022.88961,-42.1875,-10.22742857 +3022.88961,-28.125,-5.669314285 +3022.88961,-14.0625,-1.101485715 +3022.88961,0,3.578628573 +3022.88961,14.0625,8.301714285 +3022.88961,28.125,13.03428572 +3022.88961,42.1875,17.77714286 +3022.88961,56.25,22.52971429 +3022.88961,70.3125,27.292 +3022.88961,84.375,32.064 +3022.88961,98.4375,36.84571428 +3022.88961,112.5,41.63714285 +3022.88961,126.5625,46.43885715 +3022.88961,140.625,51.25028573 +3022.88961,154.6875,56.07142858 +3022.88961,168.75,60.90285715 +3022.88961,182.8125,65.74285715 +3022.88961,196.875,70.59428573 +3022.88961,210.9375,75.45142858 +3022.88961,225,80.32571428 +3022.88961,239.0625,85.20571428 +3022.88961,253.125,90.09142858 +3022.88961,267.1875,94.99428573 +3022.88961,281.25,99.90285715 +3022.88961,295.3125,104.8228572 +3022.88961,309.375,109.7485714 +3022.88961,323.4375,114.6857143 +3022.88961,337.5,119.6342857 +3022.88961,351.5625,124.5942857 +3022.88961,365.625,129.5657143 +3022.88961,379.6875,134.5428572 +3022.88961,393.75,139.5257143 +3022.88961,407.8125,144.5257143 +3022.88961,421.875,149.5314286 +3022.88961,435.9375,154.5485714 +3022.88961,450,159.5771429 +3255.487013,-450,-149.1142857 +3255.487013,-435.9375,-144.48 +3255.487013,-421.875,-139.84 +3255.487013,-407.8125,-135.1828572 +3255.487013,-393.75,-130.52 +3255.487013,-379.6875,-125.8514286 +3255.487013,-365.625,-121.1714286 +3255.487013,-351.5625,-116.48 +3255.487013,-337.5,-111.7771429 +3255.487013,-323.4375,-107.0685714 +3255.487013,-309.375,-102.3485714 +3255.487013,-295.3125,-97.61714285 +3255.487013,-281.25,-92.88 +3255.487013,-267.1875,-88.12571428 +3255.487013,-253.125,-83.37142858 +3255.487013,-239.0625,-78.6 +3255.487013,-225,-73.82285715 +3255.487013,-210.9375,-69.03428573 +3255.487013,-196.875,-64.24 +3255.487013,-182.8125,-59.43428573 +3255.487013,-168.75,-54.61771428 +3255.487013,-154.6875,-49.792 +3255.487013,-140.625,-44.95657143 +3255.487013,-126.5625,-40.11142858 +3255.487013,-112.5,-35.25714285 +3255.487013,-98.4375,-30.39314285 +3255.487013,-84.375,-25.51942858 +3255.487013,-70.3125,-20.636 +3255.487013,-56.25,-15.74285714 +3255.487013,-42.1875,-10.84057143 +3255.487013,-28.125,-5.928571428 +3255.487013,-14.0625,-1.006628573 +3255.487013,0,4.038114285 +3255.487013,14.0625,9.122285715 +3255.487013,28.125,14.216 +3255.487013,42.1875,19.32 +3255.487013,56.25,24.43314286 +3255.487013,70.3125,29.55657143 +3255.487013,84.375,34.68971428 +3255.487013,98.4375,39.83257143 +3255.487013,112.5,44.98571428 +3255.487013,126.5625,50.148 +3255.487013,140.625,55.32057143 +3255.487013,154.6875,60.50285715 +3255.487013,168.75,65.69714285 +3255.487013,182.8125,70.89714285 +3255.487013,196.875,76.10857143 +3255.487013,210.9375,81.33142858 +3255.487013,225,86.56 +3255.487013,239.0625,91.8 +3255.487013,253.125,97.05142858 +3255.487013,267.1875,102.3142857 +3255.487013,281.25,107.5828572 +3255.487013,295.3125,112.8628572 +3255.487013,309.375,118.1542857 +3255.487013,323.4375,123.4514286 +3255.487013,337.5,128.76 +3255.487013,351.5625,134.08 +3255.487013,365.625,139.4114286 +3255.487013,379.6875,144.7485714 +3255.487013,393.75,150.0971429 +3255.487013,407.8125,155.4571429 +3255.487013,421.875,160.8228572 +3255.487013,435.9375,166.2057143 +3255.487013,450,171.5885714 +3487.987013,-450,-159.9657143 +3487.987013,-435.9375,-154.9771429 +3487.987013,-421.875,-149.9828572 +3487.987013,-407.8125,-144.9714286 +3487.987013,-393.75,-139.96 +3487.987013,-379.6875,-134.9314286 +3487.987013,-365.625,-129.8971429 +3487.987013,-351.5625,-124.8514286 +3487.987013,-337.5,-119.7942857 +3487.987013,-323.4375,-114.7314286 +3487.987013,-309.375,-109.6571429 +3487.987013,-295.3125,-104.5714286 +3487.987013,-281.25,-99.48 +3487.987013,-267.1875,-94.37714285 +3487.987013,-253.125,-89.26857143 +3487.987013,-239.0625,-84.14285715 +3487.987013,-225,-79.01142858 +3487.987013,-210.9375,-73.86857143 +3487.987013,-196.875,-68.72 +3487.987013,-182.8125,-63.56 +3487.987013,-168.75,-58.38857143 +3487.987013,-154.6875,-53.21028573 +3487.987013,-140.625,-48.02114285 +3487.987013,-126.5625,-42.82228573 +3487.987013,-112.5,-37.61371428 +3487.987013,-98.4375,-32.396 +3487.987013,-84.375,-27.168 +3487.987013,-70.3125,-21.93085714 +3487.987013,-56.25,-16.684 +3487.987013,-42.1875,-11.42742857 +3487.987013,-28.125,-6.161142858 +3487.987013,-14.0625,-0.885714285 +3487.987013,0,4.524114285 +3487.987013,14.0625,9.969142858 +3487.987013,28.125,15.42457143 +3487.987013,42.1875,20.88914286 +3487.987013,56.25,26.36342858 +3487.987013,70.3125,31.848 +3487.987013,84.375,37.34228573 +3487.987013,98.4375,42.84628573 +3487.987013,112.5,48.36 +3487.987013,126.5625,53.88342858 +3487.987013,140.625,59.41714285 +3487.987013,154.6875,64.96 +3487.987013,168.75,70.51428573 +3487.987013,182.8125,76.07428573 +3487.987013,196.875,81.65142858 +3487.987013,210.9375,87.22857143 +3487.987013,225,92.82285715 +3487.987013,239.0625,98.42285715 +3487.987013,253.125,104.0342857 +3487.987013,267.1875,109.6571429 +3487.987013,281.25,115.2914286 +3487.987013,295.3125,120.9314286 +3487.987013,309.375,126.5828572 +3487.987013,323.4375,132.2457143 +3487.987013,337.5,137.9142857 +3487.987013,351.5625,143.5942857 +3487.987013,365.625,149.2857143 +3487.987013,379.6875,154.9828572 +3487.987013,393.75,160.6914286 +3487.987013,407.8125,166.4114286 +3487.987013,421.875,172.1428572 +3487.987013,435.9375,177.88 +3487.987013,450,183.6285714 +3720.487013,-450,-170.7885714 +3720.487013,-435.9375,-165.4457143 +3720.487013,-421.875,-160.0971429 +3720.487013,-407.8125,-154.7371429 +3720.487013,-393.75,-149.3657143 +3720.487013,-379.6875,-143.9885714 +3720.487013,-365.625,-138.5942857 +3720.487013,-351.5625,-133.2 +3720.487013,-337.5,-127.7885714 +3720.487013,-323.4375,-122.3714286 +3720.487013,-309.375,-116.9428572 +3720.487013,-295.3125,-111.5085714 +3720.487013,-281.25,-106.0571429 +3720.487013,-267.1875,-100.6 +3720.487013,-253.125,-95.13714285 +3720.487013,-239.0625,-89.65714285 +3720.487013,-225,-84.17142858 +3720.487013,-210.9375,-78.68 +3720.487013,-196.875,-73.17714285 +3720.487013,-182.8125,-67.66285715 +3720.487013,-168.75,-62.13714285 +3720.487013,-154.6875,-56.60285715 +3720.487013,-140.625,-51.05942858 +3720.487013,-126.5625,-45.50685715 +3720.487013,-112.5,-39.94457143 +3720.487013,-98.4375,-34.37257143 +3720.487013,-84.375,-28.79085715 +3720.487013,-70.3125,-23.19942857 +3720.487013,-56.25,-17.59885714 +3720.487013,-42.1875,-11.98857143 +3720.487013,-28.125,-6.368571428 +3720.487013,-14.0625,-0.7388 +3720.487013,0,5.036628573 +3720.487013,14.0625,10.84285714 +3720.487013,28.125,16.65885714 +3720.487013,42.1875,22.48457143 +3720.487013,56.25,28.32057143 +3720.487013,70.3125,34.16571428 +3720.487013,84.375,40.02114285 +3720.487013,98.4375,45.88628573 +3720.487013,112.5,51.76114285 +3720.487013,126.5625,57.64571428 +3720.487013,140.625,63.54285715 +3720.487013,154.6875,69.44571428 +3720.487013,168.75,75.36 +3720.487013,182.8125,81.28 +3720.487013,196.875,87.21714285 +3720.487013,210.9375,93.16 +3720.487013,225,99.11428573 +3720.487013,239.0625,105.0742857 +3720.487013,253.125,111.0514286 +3720.487013,267.1875,117.0342857 +3720.487013,281.25,123.0228572 +3720.487013,295.3125,129.0285714 +3720.487013,309.375,135.04 +3720.487013,323.4375,141.0628572 +3720.487013,337.5,147.0914286 +3720.487013,351.5625,153.1314286 +3720.487013,365.625,159.1828572 +3720.487013,379.6875,165.2457143 +3720.487013,393.75,171.3142857 +3720.487013,407.8125,177.4 +3720.487013,421.875,183.4857143 +3720.487013,435.9375,189.5885714 +3720.487013,450,195.6971429 +3953.084415,-450,-181.5885714 +3953.084415,-435.9375,-175.8914286 +3953.084415,-421.875,-170.1885714 +3953.084415,-407.8125,-164.4742857 +3953.084415,-393.75,-158.7485714 +3953.084415,-379.6875,-153.0171429 +3953.084415,-365.625,-147.2742857 +3953.084415,-351.5625,-141.52 +3953.084415,-337.5,-135.7542857 +3953.084415,-323.4375,-129.9828572 +3953.084415,-309.375,-124.2 +3953.084415,-295.3125,-118.4114286 +3953.084415,-281.25,-112.6114286 +3953.084415,-267.1875,-106.8 +3953.084415,-253.125,-100.9771429 +3953.084415,-239.0625,-95.14857143 +3953.084415,-225,-89.30857143 +3953.084415,-210.9375,-83.46285715 +3953.084415,-196.875,-77.6 +3953.084415,-182.8125,-71.73142858 +3953.084415,-168.75,-65.85714285 +3953.084415,-154.6875,-59.97142858 +3953.084415,-140.625,-54.072 +3953.084415,-126.5625,-48.16514285 +3953.084415,-112.5,-42.24914285 +3953.084415,-98.4375,-36.32285715 +3953.084415,-84.375,-30.38742858 +3953.084415,-70.3125,-24.44228572 +3953.084415,-56.25,-18.48742857 +3953.084415,-42.1875,-12.52342857 +3953.084415,-28.125,-6.549714285 +3953.084415,-14.0625,-0.565897143 +3953.084415,0,5.575714285 +3953.084415,14.0625,11.74285714 +3953.084415,28.125,17.92 +3953.084415,42.1875,24.10742857 +3953.084415,56.25,30.304 +3953.084415,70.3125,36.51028573 +3953.084415,84.375,42.72685715 +3953.084415,98.4375,48.95314285 +3953.084415,112.5,55.18914285 +3953.084415,126.5625,61.43428573 +3953.084415,140.625,67.69142858 +3953.084415,154.6875,73.95428573 +3953.084415,168.75,80.22857143 +3953.084415,182.8125,86.51428573 +3953.084415,196.875,92.81142858 +3953.084415,210.9375,99.11428573 +3953.084415,225,105.4285714 +3953.084415,239.0625,111.7542857 +3953.084415,253.125,118.0857143 +3953.084415,267.1875,124.4285714 +3953.084415,281.25,130.7828572 +3953.084415,295.3125,137.1485714 +3953.084415,309.375,143.52 +3953.084415,323.4375,149.9028572 +3953.084415,337.5,156.2971429 +3953.084415,351.5625,162.6971429 +3953.084415,365.625,169.1142857 +3953.084415,379.6875,175.5314286 +3953.084415,393.75,181.9657143 +3953.084415,407.8125,188.4057143 +3953.084415,421.875,194.8571429 +3953.084415,435.9375,201.32 +3953.084415,450,207.7942857 +4185.584415,-450,-192.36 +4185.584415,-435.9375,-186.3142857 +4185.584415,-421.875,-180.2514286 +4185.584415,-407.8125,-174.1828572 +4185.584415,-393.75,-168.1085714 +4185.584415,-379.6875,-162.0171429 +4185.584415,-365.625,-155.92 +4185.584415,-351.5625,-149.8171429 +4185.584415,-337.5,-143.6971429 +4185.584415,-323.4375,-137.5714286 +4185.584415,-309.375,-131.4342857 +4185.584415,-295.3125,-125.2914286 +4185.584415,-281.25,-119.1371429 +4185.584415,-267.1875,-112.9714286 +4185.584415,-253.125,-106.8 +4185.584415,-239.0625,-100.6114286 +4185.584415,-225,-94.42285715 +4185.584415,-210.9375,-88.21714285 +4185.584415,-196.875,-82.00571428 +4185.584415,-182.8125,-75.78285715 +4185.584415,-168.75,-69.54857143 +4185.584415,-154.6875,-63.30857143 +4185.584415,-140.625,-57.05828573 +4185.584415,-126.5625,-50.79771428 +4185.584415,-112.5,-44.52742858 +4185.584415,-98.4375,-38.24742858 +4185.584415,-84.375,-31.95828573 +4185.584415,-70.3125,-25.65942858 +4185.584415,-56.25,-19.35028572 +4185.584415,-42.1875,-13.032 +4185.584415,-28.125,-6.704571428 +4185.584415,-14.0625,-0.366965715 +4185.584415,0,6.141142858 +4185.584415,14.0625,12.66971429 +4185.584415,28.125,19.208 +4185.584415,42.1875,25.756 +4185.584415,56.25,32.31371428 +4185.584415,70.3125,38.88171428 +4185.584415,84.375,45.45885715 +4185.584415,98.4375,52.04628573 +4185.584415,112.5,58.64571428 +4185.584415,126.5625,65.25142858 +4185.584415,140.625,71.86857143 +4185.584415,154.6875,78.49142858 +4185.584415,168.75,85.13142858 +4185.584415,182.8125,91.77714285 +4185.584415,196.875,98.42857143 +4185.584415,210.9375,105.0971429 +4185.584415,225,111.7714286 +4185.584415,239.0625,118.4571429 +4185.584415,253.125,125.1542857 +4185.584415,267.1875,131.8571429 +4185.584415,281.25,138.5714286 +4185.584415,295.3125,145.2971429 +4185.584415,309.375,152.0285714 +4185.584415,323.4375,158.7771429 +4185.584415,337.5,165.5257143 +4185.584415,351.5625,172.2914286 +4185.584415,365.625,179.0628572 +4185.584415,379.6875,185.8457143 +4185.584415,393.75,192.64 +4185.584415,407.8125,199.4457143 +4185.584415,421.875,206.2571429 +4185.584415,435.9375,213.08 +4185.584415,450,219.9142857 +4418.084415,-450,-203.1085714 +4418.084415,-435.9375,-196.7028572 +4418.084415,-421.875,-190.2914286 +4418.084415,-407.8125,-183.8685714 +4418.084415,-393.75,-177.44 +4418.084415,-379.6875,-170.9942857 +4418.084415,-365.625,-164.5428572 +4418.084415,-351.5625,-158.0857143 +4418.084415,-337.5,-151.6114286 +4418.084415,-323.4375,-145.1314286 +4418.084415,-309.375,-138.6457143 +4418.084415,-295.3125,-132.1428572 +4418.084415,-281.25,-125.6342857 +4418.084415,-267.1875,-119.1142857 +4418.084415,-253.125,-112.5885714 +4418.084415,-239.0625,-106.0514286 +4418.084415,-225,-99.50285715 +4418.084415,-210.9375,-92.94857143 +4418.084415,-196.875,-86.38285715 +4418.084415,-182.8125,-79.80571428 +4418.084415,-168.75,-73.21714285 +4418.084415,-154.6875,-66.62285715 +4418.084415,-140.625,-60.01714285 +4418.084415,-126.5625,-53.404 +4418.084415,-112.5,-46.78 +4418.084415,-98.4375,-40.14628573 +4418.084415,-84.375,-33.50285715 +4418.084415,-70.3125,-26.84971428 +4418.084415,-56.25,-20.18742857 +4418.084415,-42.1875,-13.51542857 +4418.084415,-28.125,-6.833142858 +4418.084415,-14.0625,-0.142028573 +4418.084415,0,6.733714285 +4418.084415,14.0625,13.62285714 +4418.084415,28.125,20.52228572 +4418.084415,42.1875,27.43142858 +4418.084415,56.25,34.35028573 +4418.084415,70.3125,41.27885715 +4418.084415,84.375,48.21771428 +4418.084415,98.4375,55.16571428 +4418.084415,112.5,62.12571428 +4418.084415,126.5625,69.09142858 +4418.084415,140.625,76.06857143 +4418.084415,154.6875,83.05714285 +4418.084415,168.75,90.05142858 +4418.084415,182.8125,97.06285715 +4418.084415,196.875,104.08 +4418.084415,210.9375,111.1028572 +4418.084415,225,118.1428572 +4418.084415,239.0625,125.1885714 +4418.084415,253.125,132.2457143 +4418.084415,267.1875,139.3085714 +4418.084415,281.25,146.3828572 +4418.084415,295.3125,153.4685714 +4418.084415,309.375,160.5657143 +4418.084415,323.4375,167.6685714 +4418.084415,337.5,174.7885714 +4418.084415,351.5625,181.9085714 +4418.084415,365.625,189.0457143 +4418.084415,379.6875,196.1885714 +4418.084415,393.75,203.3428572 +4418.084415,407.8125,210.5085714 +4418.084415,421.875,217.68 +4418.084415,435.9375,224.8628572 +4418.084415,450,232.0571429 +4650.584415,-450,-213.8285714 +4650.584415,-435.9375,-207.0742857 +4650.584415,-421.875,-200.3028572 +4650.584415,-407.8125,-193.5257143 +4650.584415,-393.75,-186.7428572 +4650.584415,-379.6875,-179.9485714 +4650.584415,-365.625,-173.1428572 +4650.584415,-351.5625,-166.3257143 +4650.584415,-337.5,-159.5028572 +4650.584415,-323.4375,-152.6685714 +4650.584415,-309.375,-145.8228572 +4650.584415,-295.3125,-138.9714286 +4650.584415,-281.25,-132.1085714 +4650.584415,-267.1875,-125.2342857 +4650.584415,-253.125,-118.3542857 +4650.584415,-239.0625,-111.4628572 +4650.584415,-225,-104.56 +4650.584415,-210.9375,-97.65142858 +4650.584415,-196.875,-90.73142858 +4650.584415,-182.8125,-83.8 +4650.584415,-168.75,-76.86285715 +4650.584415,-154.6875,-69.91428573 +4650.584415,-140.625,-62.95428573 +4650.584415,-126.5625,-55.98457143 +4650.584415,-112.5,-49.00628573 +4650.584415,-98.4375,-42.01885715 +4650.584415,-84.375,-35.02171428 +4650.584415,-70.3125,-28.01485715 +4650.584415,-56.25,-20.99828572 +4650.584415,-42.1875,-13.972 +4650.584415,-28.125,-6.936571428 +4650.584415,-14.0625,0.111422858 +4650.584415,0,7.352 +4650.584415,14.0625,14.60285714 +4650.584415,28.125,21.86285714 +4650.584415,42.1875,29.13314285 +4650.584415,56.25,36.41314285 +4650.584415,70.3125,43.70285715 +4650.584415,84.375,51.00285715 +4650.584415,98.4375,58.31428573 +4650.584415,112.5,65.62857143 +4650.584415,126.5625,72.96 +4650.584415,140.625,80.29714285 +4650.584415,154.6875,87.64571428 +4650.584415,168.75,95.00571428 +4650.584415,182.8125,102.3714286 +4650.584415,196.875,109.7542857 +4650.584415,210.9375,117.1371429 +4650.584415,225,124.5371429 +4650.584415,239.0625,131.9428572 +4650.584415,253.125,139.36 +4650.584415,267.1875,146.7885714 +4650.584415,281.25,154.2228572 +4650.584415,295.3125,161.6742857 +4650.584415,309.375,169.1257143 +4650.584415,323.4375,176.5942857 +4650.584415,337.5,184.0685714 +4650.584415,351.5625,191.5542857 +4650.584415,365.625,199.0514286 +4650.584415,379.6875,206.56 +4650.584415,393.75,214.0742857 +4650.584415,407.8125,221.6 +4650.584415,421.875,229.1314286 +4650.584415,435.9375,236.6742857 +4650.584415,450,244.2285714 +4864.577923,-450,-223.6685714 +4864.577923,-435.9375,-216.5885714 +4864.577923,-421.875,-209.4914286 +4864.577923,-407.8125,-202.3942857 +4864.577923,-393.75,-195.28 +4864.577923,-379.6875,-188.16 +4864.577923,-365.625,-181.0285714 +4864.577923,-351.5625,-173.8857143 +4864.577923,-337.5,-166.7371429 +4864.577923,-323.4375,-159.5771429 +4864.577923,-309.375,-152.4114286 +4864.577923,-295.3125,-145.2285714 +4864.577923,-281.25,-138.04 +4864.577923,-267.1875,-130.8457143 +4864.577923,-253.125,-123.6342857 +4864.577923,-239.0625,-116.4171429 +4864.577923,-225,-109.1942857 +4864.577923,-210.9375,-101.9542857 +4864.577923,-196.875,-94.70857143 +4864.577923,-182.8125,-87.45142858 +4864.577923,-168.75,-80.18857143 +4864.577923,-154.6875,-72.91428573 +4864.577923,-140.625,-65.62857143 +4864.577923,-126.5625,-58.33714285 +4864.577923,-112.5,-51.032 +4864.577923,-98.4375,-43.71885715 +4864.577923,-84.375,-36.396 +4864.577923,-70.3125,-29.06342858 +4864.577923,-56.25,-21.72114286 +4864.577923,-42.1875,-14.36971429 +4864.577923,-28.125,-7.008 +4864.577923,-14.0625,0.371868573 +4864.577923,0,7.944571428 +4864.577923,14.0625,15.52742857 +4864.577923,28.125,23.12 +4864.577923,42.1875,30.72228573 +4864.577923,56.25,38.33485715 +4864.577923,70.3125,45.95657143 +4864.577923,84.375,53.58857143 +4864.577923,98.4375,61.22857143 +4864.577923,112.5,68.88 +4864.577923,126.5625,76.54285715 +4864.577923,140.625,84.21142858 +4864.577923,154.6875,91.89142858 +4864.577923,168.75,99.58285715 +4864.577923,182.8125,107.2857143 +4864.577923,196.875,114.9942857 +4864.577923,210.9375,122.7142857 +4864.577923,225,130.4457143 +4864.577923,239.0625,138.1828572 +4864.577923,253.125,145.9314286 +4864.577923,267.1875,153.6914286 +4864.577923,281.25,161.4628572 +4864.577923,295.3125,169.24 +4864.577923,309.375,177.0285714 +4864.577923,323.4375,184.8285714 +4864.577923,337.5,192.6342857 +4864.577923,351.5625,200.4514286 +4864.577923,365.625,208.28 +4864.577923,379.6875,216.12 +4864.577923,393.75,223.9657143 +4864.577923,407.8125,231.8228572 +4864.577923,421.875,239.6914286 +4864.577923,435.9375,247.5657143 +4864.577923,450,255.4514285 diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericICE_220kW_7.7l.veng b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericICE_220kW_7.7l.veng new file mode 100644 index 0000000000000000000000000000000000000000..cca85ad4876bc8468233a5ea42647d710327f230 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/GenericICE_220kW_7.7l.veng @@ -0,0 +1,35 @@ +{ + "Header": { + "CreatedBy": "", + "Date": "2021-01-18T16:15:30.8161241Z", + "AppVersion": "3", + "FileVersion": 5 + }, + "Body": { + "SavedInDeclMode": false, + "ModelName": "Generic 220kW 7.7l", + "Displacement": "7700", + "IdlingSpeed": 600.0, + "Inertia": 3.789, + "Fuels": [ + { + "WHTC-Urban": 0.0, + "WHTC-Rural": 0.0, + "WHTC-Motorway": 0.0, + "WHTC-Engineering": 1.02, + "ColdHotBalancingFactor": 0.0, + "CFRegPer": 0.0, + "FuelMap": "Engine map_7.7l.vmap", + "FuelType": "DieselCI" + } + ], + "RatedPower": 220000.0, + "RatedSpeed": 2200.0, + "MaxTorque": 1295.0, + "FullLoadCurve": "Full-load curve 220kW.vfld", + "WHRType": [ + "None" + ], + "WHRCorrectionFactors": {} + } +} \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/HybridStrategyParams.vhctl b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/HybridStrategyParams.vhctl new file mode 100644 index 0000000000000000000000000000000000000000..7a28da155f1ad000e68fff3b98cc3c652d01a6c6 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/HybridStrategyParams.vhctl @@ -0,0 +1,18 @@ +{ + "Header": { + "CreatedBy": "", + "Date": "2020-08-04T07:11:24.0318977Z", + "AppVersion": "3", + "FileVersion": 1 + }, + "Body": { + "EquivalenceFactorDischarge": 2.5, + "EquivalenceFactorCharge": 1.5, + "MinSoC": 10.0, + "MaxSoC": 90.0, + "TargetSoC": 50.0, + "MinICEOnTime": 3, + "AuxBufferTime": 5, + "AuxBufferChgTime": 3 + } +} \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/MaxCurrent.vimax b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/MaxCurrent.vimax new file mode 100644 index 0000000000000000000000000000000000000000..d802d5d760daf410bca1fa2b9aa42c231188f3ad --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/MaxCurrent.vimax @@ -0,0 +1,4 @@ +SOC, I_charge, I_discharge +0, 375, 375 +50, 375, 375 +100, 375, 375 \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/ShiftParameters.vtcu b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/ShiftParameters.vtcu new file mode 100644 index 0000000000000000000000000000000000000000..623d9125b82cd7ca4c1760b3938de57a76ae8ea1 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/ShiftParameters.vtcu @@ -0,0 +1,13 @@ +{ + "Header": { + "CreatedBy": " ()", + "Date": "2016-10-13T15:52:04.0766564Z", + "AppVersion": "3", + "FileVersion": 1 + }, + "Body": { + + "GearRangeUp": 1, + "GearRangeDown": 1 + } +} \ No newline at end of file diff --git a/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/TC Parallel.vtcc b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/TC Parallel.vtcc new file mode 100644 index 0000000000000000000000000000000000000000..4860d3fa3c67c70269e124cd0116d1bdb6973d49 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/Citybus_P1-APT-P-220kW-7.7l/TC Parallel.vtcc @@ -0,0 +1,13 @@ +Speed Ratio, Torque Ratio,MP1000 +0,5.434,436.7877021 +0.06993007,3.984933333,400.388727 +0.13986014,3.384710267,363.9897518 +0.20979021,2.92414291,327.5907766 +0.27972028,2.535866667,291.1918014 +0.34965035,2.193788429,254.7928262 +0.41958042,1.884526063,218.3938511 +0.48951049,1.600129967,167.4352858 +0.559440559,1.335420534,116.4767206 +0.629370629,1.0868,65.51815532 +0.699300699,0.9295,0 +3.496503497,1.287,-1747.150809 diff --git a/Generic Vehicles/Engineering Mode/GenericVehicle_Group2_P2_EM/SuperCap.vreess b/Generic Vehicles/Engineering Mode/GenericVehicle_Group2_P2_EM/SuperCap.vreess new file mode 100644 index 0000000000000000000000000000000000000000..fc743eb9cec56a3225dc8741fd63725646cffd52 --- /dev/null +++ b/Generic Vehicles/Engineering Mode/GenericVehicle_Group2_P2_EM/SuperCap.vreess @@ -0,0 +1,19 @@ +{ + "Header": { + "CreatedBy": "", + "Date": "2020-12-02T13:46:10.3043598Z", + "AppVersion": "3", + "FileVersion": 1 + }, + "Body": { + "SavedInDeclMode": false, + "REESSType": "SuperCap", + "Model": "SuperCap", + "Capacity": 161.9, + "InternalResistance": 0.00754, + "U_min": 39.87, + "U_max": 57.0, + "I_maxCharge": 100.0, + "I_maxDischarge": 100.0 + } +} \ No newline at end of file diff --git a/VECTO.sln.DotSettings b/VECTO.sln.DotSettings index 360277a6863d27e2a7137b3eda5936fa2a5d9f28..2443e9b1d0456a0103167234864b09daabfcdb3e 100644 --- a/VECTO.sln.DotSettings +++ b/VECTO.sln.DotSettings @@ -2,6 +2,7 @@ <s:Boolean x:Key="/Default/CodeEditing/GenerateMemberBody/WrapIntoRegions/@EntryValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=HashingTool_002EAnnotations/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=VECTO3GUI2020_002EAnnotations/@EntryIndexedValue">True</s:Boolean> + <s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Evdri/@EntryIndexedValue">True</s:Boolean> <s:String x:Key="/Default/CodeStyle/CodeCleanup/SilentCleanupProfile/@EntryValue">Default: Reformat Code</s:String> <s:String x:Key="/Default/CodeStyle/CodeFormatting/CommonFormatter/ALIGNMENT_TAB_FILL_STYLE/@EntryValue">USE_TABS_ONLY</s:String> <s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGNMENT_TAB_FILL_STYLE/@EntryValue">USE_TABS_ONLY</s:String> @@ -124,6 +125,11 @@ <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsWrapperSettingsUpgrader/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EVB_002ECodeStyle_002ESettingsUpgrade_002EVBSpaceAfterUnaryMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EXml_002ECodeStyle_002EFormatSettingsUpgrade_002EXmlMoveToCommonFormatterSettingsUpgrade/@EntryIndexedValue">True</s:Boolean> +<<<<<<< HEAD + <s:Boolean x:Key="/Default/Housekeeping/ExcludedProjects/ProjectMasksToIgnore/=_002A_002A_002Evdri/@EntryIndexedValue">False</s:Boolean> + <s:Boolean x:Key="/Default/Housekeeping/ExcludedProjects/ProjectMasksToIgnore/=_002A_002Evdri/@EntryIndexedValue">False</s:Boolean> + <s:Boolean x:Key="/Default/UserDictionary/Words/=RESS/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> +======= <s:Boolean x:Key="/Default/UserDictionary/Words/=Graz/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Overspeed/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Padd/@EntryIndexedValue">True</s:Boolean> @@ -135,3 +141,4 @@ <s:Boolean x:Key="/Default/UserDictionary/Words/=vair/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=vdri/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Vecto/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> +>>>>>>> develop diff --git a/VECTO/Input Files/Engine.vb b/VECTO/Input Files/Engine.vb index c3cb756085aae22d74f6710eceeb62f3f472ab0b..3b45ac7055d93b53ac3a3ffb3e44c06fee1d82f5 100644 --- a/VECTO/Input Files/Engine.vb +++ b/VECTO/Input Files/Engine.vb @@ -619,7 +619,6 @@ Public Class DummyVehicle Public Property Identifier As String Implements IVehicleDeclarationInputData.Identifier Public Property ExemptedVehicle As Boolean Implements IVehicleDeclarationInputData.ExemptedVehicle Public Property VIN As String Implements IVehicleDeclarationInputData.VIN - Public ReadOnly Property LegislativeCategory As String Implements IVehicleDeclarationInputData.LegislativeCategory Public Property LegislativeClass As LegislativeClass? Implements IVehicleDeclarationInputData.LegislativeClass Public Property VehicleCategory As VehicleCategory Implements IVehicleDeclarationInputData.VehicleCategory Public Property AxleConfiguration As AxleConfiguration Implements IVehicleDeclarationInputData.AxleConfiguration @@ -652,7 +651,8 @@ Public Class DummyVehicle Public Property DualFuelVehicle As Boolean Implements IVehicleDeclarationInputData.DualFuelVehicle Public Property MaxNetPower1 As Watt Implements IVehicleDeclarationInputData.MaxNetPower1 Public Property MaxNetPower2 As Watt Implements IVehicleDeclarationInputData.MaxNetPower2 - Public ReadOnly Property RegisteredClass As RegistrationClass? Implements IVehicleDeclarationInputData.RegisteredClass + Public ReadOnly Property ExemptedTechnology As String Implements IVehicleDeclarationInputData.ExemptedTechnology + Public ReadOnly Property RegisteredClass As RegistrationClass? Implements IVehicleDeclarationInputData.RegisteredClass Public ReadOnly Property NumberPassengerSeatsUpperDeck As Integer? Implements IVehicleDeclarationInputData.NumberPassengerSeatsUpperDeck Public ReadOnly Property NumberPassengerSeatsLowerDeck As Integer? Implements IVehicleDeclarationInputData.NumberPassengerSeatsLowerDeck Public ReadOnly Property NumberPassengersStandingLowerDeck As Integer? Implements IVehicleDeclarationInputData.NumberPassengersStandingLowerDeck diff --git a/VECTO/Input Files/Gearbox.vb b/VECTO/Input Files/Gearbox.vb index 69701bdf91a841f78e471d65b78c1d82e3d33b07..55b9a11a1040645ff2d484f931365e93972b4292 100644 --- a/VECTO/Input Files/Gearbox.vb +++ b/VECTO/Input Files/Gearbox.vb @@ -703,6 +703,23 @@ Public Class Gearbox End Get End Property + Public ReadOnly Property PEV_TargetSpeedBrakeNorm As Double? Implements IGearshiftEngineeringInputData.PEV_TargetSpeedBrakeNorm + get + Return Nothing + End Get + End Property + Public ReadOnly Property PEV_DeRatingDownshiftSpeedFactor As Double? Implements IGearshiftEngineeringInputData.PEV_DeRatingDownshiftSpeedFactor + get + return Nothing + End Get + End Property + + Public ReadOnly Property PEV_DownshiftMinSpeedFactor As Double? Implements IGearshiftEngineeringInputData.PEV_DownshiftMinSpeedFactor + get + Return Nothing + End Get + End Property + Public Overridable ReadOnly Property LoadStageShiftLines As TableData _ Implements IGearshiftEngineeringInputData.LoadStageShiftLines Get @@ -802,7 +819,6 @@ Public Class MockEngineeringVehicle Public Property Identifier As String Implements IVehicleDeclarationInputData.Identifier Public Property ExemptedVehicle As Boolean Implements IVehicleDeclarationInputData.ExemptedVehicle Public Property VIN As String Implements IVehicleDeclarationInputData.VIN - Public ReadOnly Property LegislativeCategory As String Implements IVehicleDeclarationInputData.LegislativeCategory Public Property LegislativeClass As LegislativeClass? Implements IVehicleDeclarationInputData.LegislativeClass Public Property VehicleCategory As VehicleCategory Implements IVehicleDeclarationInputData.VehicleCategory Public Property AxleConfiguration As AxleConfiguration Implements IVehicleDeclarationInputData.AxleConfiguration @@ -839,6 +855,7 @@ Public Class MockEngineeringVehicle Public Property DualFuelVehicle As Boolean Implements IVehicleDeclarationInputData.DualFuelVehicle Public Property MaxNetPower1 As Watt Implements IVehicleDeclarationInputData.MaxNetPower1 Public Property MaxNetPower2 As Watt Implements IVehicleDeclarationInputData.MaxNetPower2 + Public ReadOnly Property ExemptedTechnology As String Implements IVehicleDeclarationInputData.ExemptedTechnology Public ReadOnly Property RegisteredClass As RegistrationClass? Implements IVehicleDeclarationInputData.RegisteredClass Public ReadOnly Property NumberPassengerSeatsUpperDeck As Integer? Implements IVehicleDeclarationInputData.NumberPassengerSeatsUpperDeck Public ReadOnly Property NumberPassengerSeatsLowerDeck As Integer? Implements IVehicleDeclarationInputData.NumberPassengerSeatsLowerDeck diff --git a/VECTO/Input Files/MockVehicleInputData.vb b/VECTO/Input Files/MockVehicleInputData.vb index 0ff5fff18194700bcd5118c54631dc26b275fbf9..3b484d4c0486e8f5305b31385f504c001eba1d8c 100644 --- a/VECTO/Input Files/MockVehicleInputData.vb +++ b/VECTO/Input Files/MockVehicleInputData.vb @@ -19,7 +19,6 @@ Public Class MockVehicleInputData Public Property Identifier As String Implements IVehicleDeclarationInputData.Identifier Public Property ExemptedVehicle As Boolean Implements IVehicleDeclarationInputData.ExemptedVehicle Public Property VIN As String Implements IVehicleDeclarationInputData.VIN - Public ReadOnly Property LegislativeCategory As String Implements IVehicleDeclarationInputData.LegislativeCategory Public Property LegislativeClass As LegislativeClass? Implements IVehicleDeclarationInputData.LegislativeClass Public Property VehicleCategory As VehicleCategory Implements IVehicleDeclarationInputData.VehicleCategory Public Property AxleConfiguration As AxleConfiguration Implements IVehicleDeclarationInputData.AxleConfiguration @@ -41,6 +40,7 @@ Public Class MockVehicleInputData Public Property DualFuelVehicle As Boolean Implements IVehicleDeclarationInputData.DualFuelVehicle Public Property MaxNetPower1 As Watt Implements IVehicleDeclarationInputData.MaxNetPower1 Public Property MaxNetPower2 As Watt Implements IVehicleDeclarationInputData.MaxNetPower2 + Public ReadOnly Property ExemptedTechnology As String Implements IVehicleDeclarationInputData.ExemptedTechnology Public ReadOnly Property RegisteredClass As RegistrationClass? Implements IVehicleDeclarationInputData.RegisteredClass Public ReadOnly Property NumberPassengerSeatsUpperDeck As Integer? Implements IVehicleDeclarationInputData.NumberPassengerSeatsUpperDeck Public ReadOnly Property NumberPassengerSeatsLowerDeck As Integer? Implements IVehicleDeclarationInputData.NumberPassengerSeatsLowerDeck diff --git a/VECTO/Input Files/Vehicle.vb b/VECTO/Input Files/Vehicle.vb index 4bbc2859e6f8104e27f21ada8ab2bb6fe404addd..c261e84768e1a1f185c41fbc19fe5d02cc46822e 100644 --- a/VECTO/Input Files/Vehicle.vb +++ b/VECTO/Input Files/Vehicle.vb @@ -380,8 +380,6 @@ Public Class Vehicle End Get End Property - Public ReadOnly Property LegislativeCategory As String Implements IVehicleDeclarationInputData.LegislativeCategory - Public ReadOnly Property LegislativeClass As LegislativeClass? Implements IVehicleEngineeringInputData.LegislativeClass Get Return legClass @@ -856,7 +854,9 @@ end Property End Get End Property - Public ReadOnly Property RegisteredClass As RegistrationClass? Implements IVehicleDeclarationInputData.RegisteredClass + Public ReadOnly Property ExemptedTechnology As String Implements IVehicleDeclarationInputData.ExemptedTechnology + + Public ReadOnly Property RegisteredClass As RegistrationClass? Implements IVehicleDeclarationInputData.RegisteredClass Public ReadOnly Property NumberPassengerSeatsUpperDeck As Integer? Implements IVehicleDeclarationInputData.NumberPassengerSeatsUpperDeck Public ReadOnly Property NumberPassengerSeatsLowerDeck As Integer? Implements IVehicleDeclarationInputData.NumberPassengerSeatsLowerDeck Public ReadOnly Property NumberPassengersStandingLowerDeck As Integer? Implements IVehicleDeclarationInputData.NumberPassengersStandingLowerDeck diff --git a/VECTO3GUI/Helper/ViewModelBase.cs b/VECTO3GUI/Helper/ViewModelBase.cs index 2ed110649bd797cc4eeef4837324b36113faceb7..295f42fdd1937b47252f44b4728a6bbadd21d988 100644 --- a/VECTO3GUI/Helper/ViewModelBase.cs +++ b/VECTO3GUI/Helper/ViewModelBase.cs @@ -59,5 +59,7 @@ namespace VECTO3GUI.Helper { ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName)); } + + } } diff --git a/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs b/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs index 72a6c617ffcffb21622c35e24a5f65be9f591558..c585f453b3cedc8375a678434285db1865248911 100644 --- a/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs +++ b/VECTO3GUI/ViewModel/Impl/JoblistViewModel.cs @@ -268,8 +268,6 @@ namespace VECTO3GUI.ViewModel.Impl #region Commands - - public ICommand RunSimulation { get { return _runSimulationCommand ?? (_runSimulationCommand = new RelayCommand(DoRunSimulation, CanRunSimulationCmd)); } diff --git a/VECTO3GUI2020/App.xaml b/VECTO3GUI2020/App.xaml index 817f5f0b1b06102dfd0be81a55b244696f9a79d1..2655e63c000b91d4ef3b7958157faf8437f2ea41 100644 --- a/VECTO3GUI2020/App.xaml +++ b/VECTO3GUI2020/App.xaml @@ -2,7 +2,8 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:VECTO3GUI2020" - ShutdownMode="OnMainWindowClose"> + ShutdownMode="OnMainWindowClose" + > <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> @@ -14,12 +15,13 @@ <ResourceDictionary Source="Resources/Styles/GlobalStyles.xaml"/> <ResourceDictionary Source="Resources/Styles/Colors.xaml"/> <ResourceDictionary Source="Resources/Styles/ButtonStyles.xaml"/> - <ResourceDictionary Source="DataGridStyles.xaml"/> + <ResourceDictionary Source="Resources/Styles/DataGridStyles.xaml"/> <ResourceDictionary Source="Resources/Templates/ErrorTemplates.xaml"/> <ResourceDictionary Source="Resources/ObjectProvider.xaml"/> - <ResourceDictionary Source="Resources/Icons/drawables.xaml"></ResourceDictionary> + <ResourceDictionary Source="Resources/Icons/drawables.xaml"/> + <ResourceDictionary Source="Resources/DataTemplateSelectors.xaml"/> + <ResourceDictionary Source="Resources/Sizes.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> - </Application> diff --git a/VECTO3GUI2020/App.xaml.cs b/VECTO3GUI2020/App.xaml.cs index 93284aafd7b2b9bd4f35035ddabcbd647880dcc9..36c054f95d713baa242579b3a285baab243b7cfc 100644 --- a/VECTO3GUI2020/App.xaml.cs +++ b/VECTO3GUI2020/App.xaml.cs @@ -44,20 +44,12 @@ namespace VECTO3GUI2020 new DocumentModule(), new XMLWriterFactoryModule(), new FactoryModule(), - new MultistageModule() + new MultistageModule(), + new Vecto3GUI2020Module() ); - container.Bind<IJobListViewModel>().To<JobListViewModel>(); - container.Bind<IMainWindowViewModel>().To<MainWindowViewModel>(); - container.Bind<IMainViewModel>().To<JobListViewModel>(); - container.Bind<ISettingsViewModel>().To<SettingsViewModel>(); - container.Bind<IOutputViewModel>().To<OutputViewModel>().InSingletonScope(); - container.Bind<ISettingsModel>().To<SettingsModel>(); - - container.Bind<IDialogHelper>().To<DialogHelper>().InSingletonScope(); - container.Bind<IWindowHelper>().To<WindowHelper>(); diff --git a/VECTO3GUI2020/Behaviours/AutoScrollDataGridBehaviour.cs b/VECTO3GUI2020/Behaviours/AutoScrollDataGridBehaviour.cs new file mode 100644 index 0000000000000000000000000000000000000000..8f7f7d0d14467fc7df94f4a9da4260efdea6fce4 --- /dev/null +++ b/VECTO3GUI2020/Behaviours/AutoScrollDataGridBehaviour.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Controls; +using System.Windows.Threading; +using Microsoft.Xaml.Behaviors; + +namespace VECTO3GUI2020.Behaviours +{ + public class AutoScrollDataGridBehaviour : Behavior<DataGrid> + { + #region Overrides of Behavior + + private INotifyCollectionChanged sourceCollection; + private DependencyPropertyDescriptor _dpd; + + protected override void OnAttached() + { + base.OnAttached(); + + //subsrice to Itemssource + _dpd = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof(DataGrid)); + if (_dpd != null) + { + _dpd.AddValueChanged(this.AssociatedObject, OnItemsSourceChanged); + } + + + } + + private void OnItemsSourceChanged(object sender, EventArgs e) + { + UnSubscribeFromSourceCollectionChanged(); + + sourceCollection = AssociatedObject.ItemsSource as INotifyCollectionChanged; + if (sourceCollection != null) { + sourceCollection.CollectionChanged += SourceCollectionChanged; + } + } + + private void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + var newIndex = e.NewStartingIndex; + if (newIndex < 0) { + return; + } + Dispatcher.CurrentDispatcher.BeginInvoke( + DispatcherPriority.ApplicationIdle, + new Action(() => this.AssociatedObject.ScrollIntoView(this.AssociatedObject.Items[newIndex])) + ); + + } + + + protected override void OnDetaching() + { + base.OnDetaching(); + UnSubscribeFromSourceCollectionChanged(); + if (_dpd != null) + { + _dpd.RemoveValueChanged(this.AssociatedObject, OnItemsSourceChanged); + } + } + + private void UnSubscribeFromSourceCollectionChanged() + { + if (sourceCollection != null) { + sourceCollection.CollectionChanged -= SourceCollectionChanged; + } + + } + + #endregion + } +} diff --git a/VECTO3GUI2020/Behaviours/PopUpHorizontalAlignmentBehavior.cs b/VECTO3GUI2020/Behaviours/PopUpHorizontalAlignmentBehavior.cs new file mode 100644 index 0000000000000000000000000000000000000000..16d62fcbc82100bcb8ca463a8ae9b9fd10fcadd0 --- /dev/null +++ b/VECTO3GUI2020/Behaviours/PopUpHorizontalAlignmentBehavior.cs @@ -0,0 +1,57 @@ +using System.Windows; +using System.Windows.Controls.Primitives; +using Microsoft.Xaml.Behaviors; + +namespace VECTO3GUI2020.Behaviours +{ + public class PopUpHorizontalAlignmentBehavior : Behavior<Popup> + { + + private FrameworkElement _placementTarget; + private double _initialHorizontalOffset; + private double _popUpWidth; + + + + private void SetHorizontalAlignment(double placeMentTargetActualWidth, double popUpActualWidth) + { + if (popUpActualWidth > placeMentTargetActualWidth) { + this.AssociatedObject.HorizontalOffset = placeMentTargetActualWidth - popUpActualWidth; + } + } + private void AssociatedObject_Opened(object sender, System.EventArgs e) + { + + var popUpWidth = this.AssociatedObject.ActualWidth; + if (this.AssociatedObject.ActualWidth == 0 && this.AssociatedObject.IsMeasureValid) { + popUpWidth = this.AssociatedObject.DesiredSize.Width; + } + + //SetHorizontalAlignment(_placementTarget.ActualWidth, this.AssociatedObject.ActualWidth != 0 ? : this.AssociatedObject.ActualWidth); + } + + + #region Overrides of Behavior + + + protected override void OnAttached() + { + _placementTarget = this.AssociatedObject.PlacementTarget as FrameworkElement; + _popUpWidth = this.AssociatedObject.MinWidth; + this.AssociatedObject.Opened += AssociatedObject_Opened; + base.OnAttached(); + } + + + + protected override void OnDetaching() + { + this.AssociatedObject.HorizontalOffset = _initialHorizontalOffset; + base.OnDetaching(); + } + + + + #endregion + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Helper/Converter/BoolToVisibilityConverter.cs b/VECTO3GUI2020/Helper/Converter/BoolToVisibilityConverter.cs index 0eb30e7c549784ad287c57a8645066fcf89ebae7..f91f4022fba7c4c270658653384bc106e0a138ed 100644 --- a/VECTO3GUI2020/Helper/Converter/BoolToVisibilityConverter.cs +++ b/VECTO3GUI2020/Helper/Converter/BoolToVisibilityConverter.cs @@ -17,7 +17,16 @@ namespace VECTO3GUI2020.Helper.Converter /// <returns></returns> public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { + + + if (value is bool b) { + if (parameter != null) { + if (string.Equals((string)parameter, "invert", StringComparison.InvariantCultureIgnoreCase)) { + b = !b; + } + } + var visibility = b ? Visibility.Collapsed : Visibility.Visible; return visibility; } diff --git a/VECTO3GUI2020/Helper/Converter/MultipleBoolConverter.cs b/VECTO3GUI2020/Helper/Converter/MultipleBoolConverter.cs new file mode 100644 index 0000000000000000000000000000000000000000..2217f002db725c114b5b54c7c3cc4e235f79bbe1 --- /dev/null +++ b/VECTO3GUI2020/Helper/Converter/MultipleBoolConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Windows.Data; + +namespace VECTO3GUI2020.Helper.Converter +{ + public class MultipleBoolConverter : IMultiValueConverter + { + #region Implementation of IMultiValueConverter + + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + var boolVals = values.Cast<bool>(); + bool returnValue = (bool)values[0]; + foreach (var val in boolVals) { + returnValue = returnValue && val; + if (!returnValue) { + break; + } + } + + return returnValue; + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + + #endregion + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Helper/Converter/PropertyNameToLabelTextConverter.cs b/VECTO3GUI2020/Helper/Converter/PropertyNameToLabelTextConverter.cs new file mode 100644 index 0000000000000000000000000000000000000000..e164d620aef8169cc0ccdb3338e81a89efaac07d --- /dev/null +++ b/VECTO3GUI2020/Helper/Converter/PropertyNameToLabelTextConverter.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Resources; +using System.Windows.Data; +using VECTO3GUI2020.Properties; + +namespace VECTO3GUI2020.Helper.Converter +{ + public class PropertyNameToLabelTextConverter : IValueConverter + { + #region Implementation of IValueConverter + /// <summary> + /// Maps the value to a string found in the given ResourceFiles (first match). + /// + /// </summary> + /// <param name="value"></param> + /// <param name="targetType"></param> + /// <param name="parameter"></param> + /// <param name="culture"></param> + /// <example> + /// + /// <Binding Path="." Converter="{StaticResource PropertyNameToLabelConverter}"> + /// <Binding.ConverterParameter> + /// <x:Array Type="resources:ResourceManager"> + /// <x:Static MemberType="properties:Strings" Member="ResourceManager"/> + /// </x:Array> + /// </Binding.ConverterParameter> + /// </Binding> + /// + /// </example> + /// <returns></returns> + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (parameter is IEnumerable<ResourceManager> resourceManagers) { + return NameResolver.ResolveName(value as string, resourceManagers.ToArray()); + } else { + return NameResolver.ResolveName(value as string, BusStrings.ResourceManager, Strings.ResourceManager) ?? Binding.DoNothing; + } + + + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + + #endregion + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Helper/DialogHelper.cs b/VECTO3GUI2020/Helper/DialogHelper.cs index 9609208a1d3ef0c2dfbe981952a0478ece06a7d2..848827af70a567dc18b3054ca4a025fcd09f4cab 100644 --- a/VECTO3GUI2020/Helper/DialogHelper.cs +++ b/VECTO3GUI2020/Helper/DialogHelper.cs @@ -19,14 +19,16 @@ namespace VECTO3GUI2020.Helper #region File and Folder Dialogs private string _xmlFilter = "XML Files (*.xml)|*.xml"; + private string _jsonFilter = "JSON Files (*.json)|*.json"; - private Dictionary<string, string> lastUsedDirectories = new Dictionary<string, string>(); + private Dictionary<string, string> lastUsedLoadDirectories = new Dictionary<string, string>(); + private Dictionary<string, string> lastUsedSaveDirectories = new Dictionary<string, string>(); private string lastUsedDirectoryFolderPicker = null; private string[] OpenFilesDialog(string filter, string initialDirectory, bool multiselect) { if (initialDirectory == null) { - initialDirectory = LookUpLastDir(filter); + initialDirectory = LookUpLastDir(lastUsedLoadDirectories, filter); } @@ -39,7 +41,7 @@ namespace VECTO3GUI2020.Helper }) { var result = fd.ShowDialog(); if (result == DialogResult.OK) { - lastUsedDirectories[filter] = Path.GetDirectoryName(fd.FileName); + lastUsedLoadDirectories[filter] = Path.GetDirectoryName(fd.FileName); return fd.FileNames; } } @@ -47,11 +49,33 @@ namespace VECTO3GUI2020.Helper return null; } + public string SaveToDialog(string initialDirectory, string filter) + { + if (initialDirectory == null) { + initialDirectory = LookUpLastDir(lastUsedSaveDirectories, filter); + } + using (var saveFileDialog = new SaveFileDialog + { + Filter = filter, + InitialDirectory = initialDirectory ?? _defaultInitialDirectory, + AddExtension = true + }) { + var result = saveFileDialog.ShowDialog(); + { + if (result == DialogResult.OK) { + lastUsedSaveDirectories[filter] = Path.GetDirectoryName(saveFileDialog.FileName); + return saveFileDialog.FileName; + } + } - private string LookUpLastDir(string filter) + return null; + } + } + + private static string LookUpLastDir(Dictionary<string, string> dict, string filter) { string lastUsedDirectory = null; - if (lastUsedDirectories.TryGetValue(filter, out lastUsedDirectory)) { + if (dict.TryGetValue(filter, out lastUsedDirectory)) { return lastUsedDirectory; } else { return Settings.Default.DefaultFilePath; @@ -85,6 +109,11 @@ namespace VECTO3GUI2020.Helper return OpenFilesDialog(_xmlFilter, initialDirectory, false)?[0]; } + public string OpenJsonFileDialog(string initialDirectory) + { + return OpenFilesDialog(_jsonFilter, initialDirectory, false)?[0]; + } + public string OpenFolderDialog(string initialDirectory = null) { @@ -125,16 +154,7 @@ namespace VECTO3GUI2020.Helper return MessageBox.Show(messageBoxText, caption); } - public string SaveToDialog(string initialDirectory, string filter) - { - using (var saveFileDialog = new SaveFileDialog { - Filter = filter - }) { - saveFileDialog.InitialDirectory = initialDirectory ?? _defaultInitialDirectory; - return saveFileDialog.ShowDialog() == DialogResult.OK ? saveFileDialog.FileName : null; - } - } public string SaveToXMLDialog(string initialDirectory) @@ -142,6 +162,20 @@ namespace VECTO3GUI2020.Helper return SaveToDialog(initialDirectory, _xmlFilter); } + public string SaveToJsonDialog(string initialDirectory) + { + return SaveToDialog(initialDirectory, _jsonFilter); + } + + public MessageBoxResult ShowErrorMessage(string errorMessage, string caption) + { + return ShowMessageBox(errorMessage, caption, MessageBoxButton.OK, MessageBoxImage.Error); + } + + public MessageBoxResult ShowErrorMessage(string errorMessage) + { + return ShowErrorMessage(errorMessage, "Error"); + } #endregion @@ -188,6 +222,11 @@ namespace VECTO3GUI2020.Helper /// <param name="initialDirectory"></param> /// <returns></returns> string OpenFolderDialog(string initialDirectory = null); + string OpenJsonFileDialog(string initialDirectory = null); + string SaveToDialog(string initialDirectory = null, string filter = "All files (*.*|*.*"); + string SaveToXMLDialog(string initialDirectory = null); + string SaveToJsonDialog(string initialDirectory = null); + /// <summary> /// Displays a messagebox @@ -210,9 +249,7 @@ namespace VECTO3GUI2020.Helper /// <returns></returns> MessageBoxResult ShowMessageBox(string messageBoxText, string caption); - - string SaveToDialog(string initialDirectory = null, string filter = "All files (*.*|*.*"); - - string SaveToXMLDialog(string initialDirectory = null); + MessageBoxResult ShowErrorMessage(string errorMessage, string caption); + MessageBoxResult ShowErrorMessage(string errorMessage); } } diff --git a/VECTO3GUI2020/Helper/ExceptionExtension.cs b/VECTO3GUI2020/Helper/ExceptionExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..cf656d36044e294754d7dc7bfbb5ec6a2e5f30e9 --- /dev/null +++ b/VECTO3GUI2020/Helper/ExceptionExtension.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Documents; + +namespace VECTO3GUI2020.Helper +{ + public static class ExceptionExtension + { + public static string GetInnerExceptionMessages(this Exception ex, string separator = "\n") + { + IList<string> errorStrings = new List<string>(); + + + do { + errorStrings.Add(ex.Message); + ex = ex.InnerException; + } while (ex != null); + + var errorString = String.Join(separator, errorStrings); + + + return errorString; + } + + + + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Helper/FileHelper.cs b/VECTO3GUI2020/Helper/FileHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..3cad81f50936a6ddab2eb8bfbb269f8016628293 --- /dev/null +++ b/VECTO3GUI2020/Helper/FileHelper.cs @@ -0,0 +1,16 @@ +using System.IO; +using Castle.Core.Internal; + +namespace VECTO3GUI2020.Helper +{ + public static class FileHelper + { + public static void CreateDirectory(string fileName) + { + var dirName = Path.GetDirectoryName(fileName); + if (!dirName.IsNullOrEmpty()) { + Directory.CreateDirectory(dirName); + } + } + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Helper/IndexedStorage.cs b/VECTO3GUI2020/Helper/IndexedStorage.cs deleted file mode 100644 index fee593ec2cf4c5b5f33aabc8463d2ae868f18540..0000000000000000000000000000000000000000 --- a/VECTO3GUI2020/Helper/IndexedStorage.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace VECTO3GUI2020.Helper -{ - //Helper class that can be used to store values of the same type that are identified by a string - public class IndexedStorage<T> where T : IEquatable<T> - { - private Dictionary<string, T> indexedStorageDictionary = new Dictionary<string, T>(); - private readonly Action<string> _valueChangedCallback; - - - - public IndexedStorage(Action<string> valueChangedCallback = null) - { - _valueChangedCallback = valueChangedCallback; - } - - - public T this[string identifier] - { - get - { - if (!indexedStorageDictionary.ContainsKey(identifier)) - { - indexedStorageDictionary.Add(identifier, default(T)); - } - return indexedStorageDictionary[identifier]; - } - set - { - var oldValue = default(T); - if (indexedStorageDictionary.ContainsKey(identifier)) - { - oldValue = indexedStorageDictionary[identifier]; - } - else - { - indexedStorageDictionary.Add(identifier, default(T)); - } - indexedStorageDictionary[identifier] = value; - if (!value.Equals(oldValue)) - { - _valueChangedCallback?.Invoke(identifier); - } - } - } - } - -} diff --git a/VECTO3GUI2020/Helper/NameOfMarkUpExtension.cs b/VECTO3GUI2020/Helper/NameOfMarkUpExtension.cs deleted file mode 100644 index 0e5218d4007204b9647b23db8c84464a098d8743..0000000000000000000000000000000000000000 --- a/VECTO3GUI2020/Helper/NameOfMarkUpExtension.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Windows.Markup; - -namespace VECTO3GUI2020.Helper -{ - public class NameOfMarkUpExtension : MarkupExtension - { - #region Overrides of MarkupExtension - - public override object ProvideValue(IServiceProvider serviceProvider) - { - throw new NotImplementedException(); - return null; - } - - #endregion - } -} \ No newline at end of file diff --git a/VECTO3GUI2020/Helper/NameResolver.cs b/VECTO3GUI2020/Helper/NameResolver.cs index 022c954acad0c2257c9241babb061c9c2d3a4247..6d9fe13a50352ba1e68978b397888c721c82c0e4 100644 --- a/VECTO3GUI2020/Helper/NameResolver.cs +++ b/VECTO3GUI2020/Helper/NameResolver.cs @@ -3,7 +3,7 @@ using Castle.Core.Internal; namespace VECTO3GUI2020.Helper { - public class NameResolver + public static class NameResolver { public static string ResolveName(string propertyName, params ResourceManager[] resourceManagers) { diff --git a/VECTO3GUI2020/Helper/ObservableDictionary.cs b/VECTO3GUI2020/Helper/ObservableDictionary.cs new file mode 100644 index 0000000000000000000000000000000000000000..a61739b9783cb1859e644bbddb24fbc8857597a0 --- /dev/null +++ b/VECTO3GUI2020/Helper/ObservableDictionary.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Diagnostics; +using System.Windows; + +namespace VECTO3GUI2020.Helper +{ + interface IObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, INotifyCollectionChanged + { + + } + public class ObservableDictionary<TKey,TValue> : IObservableDictionary<TemplateKey, TValue> + { + #region Implementation of INotifyCollectionChanged + + public event NotifyCollectionChangedEventHandler CollectionChanged; + + #endregion + + private IDictionary<TemplateKey, TValue> _dict = new Dictionary<TemplateKey, TValue>(); + + public ObservableDictionary() + { + throw new NotImplementedException(); + } + + #region Implementation of IEnumerable + + IEnumerator<KeyValuePair<TemplateKey, TValue>> IEnumerable<KeyValuePair<TemplateKey, TValue>>.GetEnumerator() + { + return _dict.GetEnumerator(); + } + + public IEnumerator GetEnumerator() + { + return ((IEnumerable)_dict).GetEnumerator(); + } + + #endregion + + #region Implementation of ICollection<KeyValuePair<TemplateKey,TValue>> + + public void Add(KeyValuePair<TemplateKey, TValue> item) + { + _dict.Add(item); + } + + public void Clear() + { + CollectionChanged.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + _dict.Clear(); + } + + public bool Contains(KeyValuePair<TemplateKey, TValue> item) + { + return _dict.Contains(item); + } + + public void CopyTo(KeyValuePair<TemplateKey, TValue>[] array, int arrayIndex) + { + _dict.CopyTo(array, arrayIndex); + } + + public bool Remove(KeyValuePair<TemplateKey, TValue> item) + { + return _dict.Remove(item); + } + + public int Count => _dict.Count; + + public bool IsReadOnly => _dict.IsReadOnly; + + #endregion + + #region Implementation of IDictionary<TemplateKey,TValue> + + public bool ContainsKey(TemplateKey key) + { + return _dict.ContainsKey(key); + } + + public void Add(TemplateKey key, TValue value) + { + + _dict.Add(key, value); + } + + public bool Remove(TemplateKey key) + { + TValue value; + var itemFound = _dict.TryGetValue(key, out value); + var result = itemFound && _dict.Remove(key); + if (result) { + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, + new List<TValue>(){ + value + })); + } + return result; + } + + public bool TryGetValue(TemplateKey key, out TValue value) + { + return _dict.TryGetValue(key, out value); + } + + public TValue this[TemplateKey key] + { + get => _dict[key]; + set => _dict[key] = value; + } + + public ICollection<TemplateKey> Keys => _dict.Keys; + + public ICollection<TValue> Values => _dict.Values; + + #endregion + + + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Helper/ProcessHelper.cs b/VECTO3GUI2020/Helper/ProcessHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..a5383aa430a705134b34b18323ca71ed3cb8c141 --- /dev/null +++ b/VECTO3GUI2020/Helper/ProcessHelper.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VECTO3GUI2020.Helper +{ + public static class ProcessHelper + { + + public static void OpenFolder(string path) + { + if (path == null) + { + return; + } + + path = Path.GetFullPath(path); + + var explorerCommandStrBuilder = new StringBuilder(); + explorerCommandStrBuilder.Append("explorer.exe"); + explorerCommandStrBuilder.Append(" /select "); + explorerCommandStrBuilder.Append(path); + + StartProcess("explorer.exe", ("/select," + path)); + } + + + + public static void OpenFile(string path) + { + if (path == null) + { + return; + } + + StartProcess(path); + + + } + + private static void StartProcess(string command, params string[] arguments) + { + string argumentsString = ""; + if (arguments != null) + { + var argumentsStrBuilder = new StringBuilder(); + foreach (var argument in arguments) + { + argumentsStrBuilder.Append(argument); + if (argument != arguments.Last()) + { + argumentsStrBuilder.Append(" "); + } + } + + argumentsString = argumentsStrBuilder.ToString(); + Debug.WriteLine(argumentsString); + } + + try + { + Process.Start(command, argumentsString); + } + catch (Exception e) + { + Debug.WriteLine(e.Message); + } + } + + } +} diff --git a/VECTO3GUI2020/Helper/MultistageParameterDataTemplateSelector.cs b/VECTO3GUI2020/Helper/TemplateSelector/MultistageParameterDataTemplateSelector.cs similarity index 92% rename from VECTO3GUI2020/Helper/MultistageParameterDataTemplateSelector.cs rename to VECTO3GUI2020/Helper/TemplateSelector/MultistageParameterDataTemplateSelector.cs index 74a73b23bee97dada9d9e9a539a7fd19e34e380b..57da972b0d0744b0e7bf761165b3e810f3f50b75 100644 --- a/VECTO3GUI2020/Helper/MultistageParameterDataTemplateSelector.cs +++ b/VECTO3GUI2020/Helper/TemplateSelector/MultistageParameterDataTemplateSelector.cs @@ -2,9 +2,10 @@ using System.Windows; using System.Windows.Controls; using TUGraz.VectoCommon.Exceptions; +using VECTO3GUI2020.ViewModel.MultiStage.Implementation; using VECTO3GUI2020.Views.Multistage.CustomControls; -namespace VECTO3GUI2020.Helper +namespace VECTO3GUI2020.Helper.TemplateSelector { public class MultistageParameterDataTemplateSelector : DataTemplateSelector { diff --git a/VECTO3GUI2020/Helper/TemplateSelector/MultistageVehicleDataTemplateSelector.cs b/VECTO3GUI2020/Helper/TemplateSelector/MultistageVehicleDataTemplateSelector.cs new file mode 100644 index 0000000000000000000000000000000000000000..5c230dfe950700dc01724da4c9dbe16c46be2a22 --- /dev/null +++ b/VECTO3GUI2020/Helper/TemplateSelector/MultistageVehicleDataTemplateSelector.cs @@ -0,0 +1,53 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using TUGraz.VectoCommon.Exceptions; +using VECTO3GUI2020.ViewModel.Interfaces.JobEdit.Vehicle; +using VECTO3GUI2020.ViewModel.MultiStage.Implementation; +using VECTO3GUI2020.Views.Multistage; +using VECTO3GUI2020.Views.Multistage.CustomControls; + +namespace VECTO3GUI2020.Helper.TemplateSelector +{ + public class MultistageVehicleDataTemplateSelector : DataTemplateSelector + { + + /// <summary> + /// Selects a vehicle viewmodel based on the ExemptedVehicleProperty + /// </summary> + /// <param name="item"></param> + /// <param name="container"></param> + /// <returns></returns> + public override DataTemplate SelectTemplate(object item, DependencyObject container) + { + FrameworkElement element = container as FrameworkElement; + IVehicleViewModel vm = item as IVehicleViewModel; + + if (element != null && item != null && vm != null) + { + FrameworkElementFactory factory = null; + Type type = null; + + switch (vm) { + case InterimStageBusVehicleViewModel_v2_8 declvm: + if (declvm.ExemptedVehicle) { + type = typeof(VehicleView_v2_8_exempted); + } else { + type = typeof(VehicleView_v2_8); + } + + break; + default: + throw new NotImplementedException($"no template defined for {vm.GetType()}"); + } + + factory = new FrameworkElementFactory(type); + DataTemplate dt = new DataTemplate(); + dt.VisualTree = factory; + return dt; + } + + return base.SelectTemplate(item, container); + } + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Helper/VisualTreeHelperExtensions.cs b/VECTO3GUI2020/Helper/VisualTreeHelperExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..d9d8b66e8c34d9e243eaf1045eebf39c2aab0e4d --- /dev/null +++ b/VECTO3GUI2020/Helper/VisualTreeHelperExtensions.cs @@ -0,0 +1,28 @@ +using System; +using System.Windows; +using System.Windows.Media; +using TUGraz.VectoCommon.Models; + +namespace VECTO3GUI2020.Helper +{ + public static class VisualTreeHelperExtensions + { + + public static T GetChild<T>(FrameworkElement rootElement) where T : FrameworkElement + { + T child = null; + for(var i = 0; i < VisualTreeHelper.GetChildrenCount(rootElement); i++) { + var childElement = VisualTreeHelper.GetChild(rootElement, i); + if (childElement.GetType() == typeof(T)) { + child = childElement as T; + return child; + } else { + return GetChild<T>(childElement as FrameworkElement); + } + } + + + return child; + } + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Helper/WindowHelper.cs b/VECTO3GUI2020/Helper/WindowHelper.cs index 1e56f7c2a28c96993ea963584e8b4a016b3eaf9b..5e74748502d2a28ff66d15ee3c4cc8a22fb7d464 100644 --- a/VECTO3GUI2020/Helper/WindowHelper.cs +++ b/VECTO3GUI2020/Helper/WindowHelper.cs @@ -1,6 +1,10 @@ -using System.Windows; -using VECTO3GUI2020.ViewModel.Implementation.Common; +using System; +using System.Windows; +using System.Windows.Data; +using System.Windows.Forms; +using VECTO3GUI2020.Properties; using VECTO3GUI2020.ViewModel.Interfaces.Common; +using Binding = System.Windows.Data.Binding; namespace VECTO3GUI2020.Helper { @@ -10,20 +14,55 @@ namespace VECTO3GUI2020.Helper public void ShowWindow(object viewModel) { + IViewModelBase viewModelBase = (IViewModelBase)viewModel; + var height = viewModelBase?.Height ?? Double.NaN; + var width = viewModelBase?.Height ?? Double.NaN; + var sizeToContent = viewModelBase?.SizeToContent ?? SizeToContent.Manual; + var title = viewModelBase?.Title ?? GUILabels.DefaultTitle; + var minHeight = viewModelBase?.MinHeight ?? 0; + var minWidth = viewModelBase?.MinWidth ?? 0; + + var window = new Window { Content = viewModel, - Width = 800, - Height = 600, - WindowStartupLocation = WindowStartupLocation.CenterScreen + Height = height, + Width = width, + MinHeight = minHeight, + MinWidth = minWidth, + SizeToContent = sizeToContent, + WindowStartupLocation = WindowStartupLocation.CenterScreen, + Title = title }; + if (viewModelBase != null) { + SetBinding(viewModelBase, window, new PropertyPath(nameof(viewModelBase.Height)), FrameworkElement.HeightProperty ); + SetBinding(viewModelBase, window, new PropertyPath(nameof(viewModelBase.Width)), FrameworkElement.WidthProperty); + SetBinding(viewModelBase, window, new PropertyPath(nameof(viewModelBase.SizeToContent)), Window.SizeToContentProperty); + SetBinding(viewModelBase, window, new PropertyPath(nameof(viewModelBase.Title)), Window.TitleProperty); + SetBinding(viewModelBase, window, new PropertyPath(nameof(viewModelBase.SizeToContent)), Window.SizeToContentProperty); + SetBinding(viewModelBase, window, new PropertyPath(nameof(viewModelBase.Title)), Window.TitleProperty); + - if (viewModel is IViewModelBase vmBase) { - window.Title = vmBase.Title; } + window.Show(); } - + private static void SetBinding(IViewModelBase viewModelBase, + Window window, + PropertyPath path, + DependencyProperty dependencyProperty, + UpdateSourceTrigger updateSourceTrigger = UpdateSourceTrigger.PropertyChanged, + BindingMode mode = BindingMode.TwoWay + ) + { + Binding binding = new Binding() { + Source = viewModelBase, + Path = path, + UpdateSourceTrigger = updateSourceTrigger, + Mode = mode + }; + BindingOperations.SetBinding(window, dependencyProperty, binding); + } } } diff --git a/VECTO3GUI2020/MainWindow.xaml b/VECTO3GUI2020/MainWindow.xaml index 73a0a4efb0ecca551477ec3772aa586d54540eff..1b900af38931c5ac09b42d6a6cce2e2f13883376 100644 --- a/VECTO3GUI2020/MainWindow.xaml +++ b/VECTO3GUI2020/MainWindow.xaml @@ -4,9 +4,15 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:VECTO3GUI2020" - xmlns:Implementation="clr-namespace:VECTO3GUI2020.ViewModel.Implementation" d:DataContext="{d:DesignInstance Type=Implementation:MainWindowViewModel}" x:Class="VECTO3GUI2020.MainWindow" + xmlns:resx="clr-namespace:VECTO3GUI2020.Properties" + xmlns:Implementation="clr-namespace:VECTO3GUI2020.ViewModel.Implementation" + xmlns:system="clr-namespace:System;assembly=mscorlib" + d:DataContext="{d:DesignInstance Type=Implementation:MainWindowViewModel}" x:Class="VECTO3GUI2020.MainWindow" mc:Ignorable="d" Title="Vecto" Height="450" Width="820" + MinWidth="800" + MinHeight="420" + WindowStartupLocation="CenterScreen" AutomationProperties.Name="=" x:Name="MainView"> @@ -14,30 +20,107 @@ <Grid x:Name="Grid" > - <Grid.ColumnDefinitions> - <ColumnDefinition Width="1*"/> - </Grid.ColumnDefinitions> - <Grid.RowDefinitions> - <RowDefinition Height="40"/> - <RowDefinition Height="1.5*"/> - <RowDefinition Height="5"></RowDefinition> - <RowDefinition Height="1*"/> - </Grid.RowDefinitions> + <DockPanel Margin="0 0 0 0"> + <StackPanel DockPanel.Dock="Top" Grid.Row="0" Orientation="Vertical"> + <Menu IsMainMenu="True"> + <MenuItem Header="File" VerticalAlignment="Stretch"> + <MenuItem Header="New File"> + <MenuItem Header="{x:Static resx:GUILabels.NewInterimOrCompletedJob}" Command="{Binding JobListVm.NewManufacturingStageFileCommand}"/> + <MenuItem Header="{x:Static resx:GUILabels.NewPrimaryAndInterimJob}" + Command="{Binding JobListVm.NewVifCommand}" > + <MenuItem.CommandParameter> + <system:Boolean>False</system:Boolean> + </MenuItem.CommandParameter> + </MenuItem> - <StackPanel Grid.Row="0" Orientation="Vertical"> - <Menu x:Name="menu" AutomationProperties.Name="-" AutomationProperties.AutomationId="Test" IsMainMenu="True"> - <MenuItem Header="File" x:Name="MenuItemFile" AutomationProperties.Name="=" VerticalAlignment="Stretch"> + <MenuItem Header="{x:Static resx:GUILabels.NewCompleteJob}" + Command="{Binding JobListVm.NewVifCommand}"> + <MenuItem.CommandParameter> + <system:Boolean>True</system:Boolean> + </MenuItem.CommandParameter> + </MenuItem> + <Separator></Separator> + <MenuItem Header="Create interim/completeted input" Command="{Binding JobListVm.NewCompletedInputCommand}"/> + <MenuItem Header="Create extemted interim/completed input" Command="{Binding JobListVm.NewExemptedCompletedInputCommand}"/> + </MenuItem> + <MenuItem Header="Load File" Command="{Binding JobListVm.AddJobAsyncCommand}"/> <MenuItem Header="Settings" Command="{Binding OpenSettings}"/> - <MenuItem Header="New File" Command="{Binding NewInterimFile}"/> - <MenuItem Header="Open File" Command="{Binding AddJob}"/> + </MenuItem> + <MenuItem Header="Edit" VerticalAlignment="Stretch"> + <MenuItem Header="Edit Job" ToolTip="Edit selected Job" Command="{Binding JobListVm.EditDocument}"/> + <MenuItem Header="Source File"> + <MenuItem Header="Show in Explorer" Command="{Binding JobListVm.ShowSourceFileCommand}"/> + <MenuItem Header="Open in Editor" Command="{Binding JobListVm.OpenSourceFileCommand}"/> + </MenuItem> + <!--<MenuItem Header="Simulate Job" ToolTip="Simulates the selected Job"/>--> </MenuItem> </Menu> </StackPanel> + <UniformGrid Margin="0 10 0 0 " Rows="1" DockPanel.Dock="Top" Width="400" HorizontalAlignment="Left"> + <Border x:Name="JobsButtonBorder" BorderThickness ="0 0 0 3"> + <Border.Style> + <Style TargetType="Border"> + <Style.Triggers> + <DataTrigger Binding="{Binding JobsSelected}" Value="true"> + <Setter Property="BorderBrush" Value="{StaticResource AccentColorButton}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Border.Style> + + + <Button x:Name="Jobs" Margin="0 0 0 0" + VerticalAlignment="Stretch" + DockPanel.Dock="Top" + Content="Jobs" + Command="{Binding SwitchTopView}" + CommandParameter="Jobs" + Style="{DynamicResource MultiStageButtonStyle1}"> + </Button> + </Border> - - <ContentControl Grid.Row="1" Margin="0, 4, 0 0" Content="{Binding CurrentViewModelTop}"/> - <GridSplitter Grid.Row="2" HorizontalAlignment="Stretch" Height="5"/> - <ContentControl Grid.Row="3" Margin="0,0,0,0" Name="ContentControlBottom" Content="{Binding CurrentViewModelBottom}"/> - + <Border BorderThickness="{Binding ElementName=JobsButtonBorder, Path=BorderThickness}"> + <Border.Style> + <Style TargetType="Border"> + <Style.Triggers> + <DataTrigger Binding="{Binding SettingsSelected}" Value="true"> + <Setter Property="BorderBrush" Value="{StaticResource AccentColorButton}"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Border.Style> + <Button Margin="0 0 0 0" + VerticalAlignment="Stretch" + DockPanel.Dock="Top" + Content="Settings" + Command="{Binding SwitchTopView}" + CommandParameter="Settings" + Style="{DynamicResource MultiStageButtonStyle1}"> + </Button> + </Border> + <Border BorderThickness="{Binding ElementName=JobsButtonBorder, Path=BorderThickness}"> + <Border.Style> + <Style TargetType="Border"> + <Style.Triggers> + <DataTrigger Binding="{Binding AboutSelected}" Value="true"> + <Setter Property="BorderBrush" Value="{StaticResource AccentColorButton}"/> + </DataTrigger> + </Style.Triggers> + </Style> + </Border.Style> + <Button Margin="0 0 0 0" + VerticalAlignment="Stretch" + DockPanel.Dock="Top" + Content="About" + Command="{Binding SwitchTopView}" + CommandParameter="About" + Style="{DynamicResource MultiStageButtonStyle1}"> + </Button> + </Border> + </UniformGrid> + <Border DockPanel.Dock="Top" BorderBrush="{DynamicResource AccentColorButton}" BorderThickness="3" VerticalAlignment="Stretch"> + <ContentControl Content="{Binding CurrentViewModel}"></ContentControl> + </Border> + </DockPanel> </Grid> </Window> diff --git a/VECTO3GUI2020/Model/Multistage/JSONJob.cs b/VECTO3GUI2020/Model/Multistage/JSONJob.cs new file mode 100644 index 0000000000000000000000000000000000000000..733d512b0379bedb18f71bf5028bfc84144ba989 --- /dev/null +++ b/VECTO3GUI2020/Model/Multistage/JSONJob.cs @@ -0,0 +1,95 @@ +using System; +using System.Diagnostics; +using Newtonsoft.Json; +using TUGraz.VectoCore; +using VECTO3GUI2020.ViewModel.Implementation.Common; + +namespace VECTO3GUI2020.Model.Multistage +{ + public class JSONJob : ObservableObject + { + private JSONJobHeader _header; + + public JSONJobHeader Header + { + get => _header; + set => SetProperty(ref _header, value); + } + + private JSONJobBody _jobBody; + + public JSONJobBody Body + { + get => _jobBody; + set => SetProperty(ref _jobBody, value); + } + } + + + + public class JSONJobHeader : ObservableObject + { + public static int PrimaryAndInterimVersion = 10; + //public const int CompletedBusFileVersion = 7; + + private string _createdBy; + private DateTime _dateTime; + private string _appVersion; + private int _fileVersion; + + + public string CreatedBy + { + get { return _createdBy; } + set { SetProperty(ref _createdBy, value); } + } + + public DateTime Date + { + get { return _dateTime; } + set { SetProperty(ref _dateTime, value); } + } + + public string AppVersion + { + get { return _appVersion; } + set { SetProperty(ref _appVersion, value); } + } + + public int FileVersion + { + get { return _fileVersion; } + set + { + SetProperty(ref _fileVersion, value); + //JobType = JobTypeHelper.GetJobTypeByFileVersion(_fileVersion); + } + } + } + + + public class JSONJobBody : ObservableObject + { + private string _interimStage; + private string _primaryVehicle; + private bool _completed; + + public string PrimaryVehicle + { + get { return _primaryVehicle; } + set { SetProperty(ref _primaryVehicle, value); } + } + + public string InterimStage + { + get { return _interimStage; } + set { SetProperty(ref _interimStage, value); } + } + + public bool Completed + { + get => _completed; + set => SetProperty(ref _completed, value); + } + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Ninject/DocumentModule.cs b/VECTO3GUI2020/Ninject/DocumentModule.cs index 8e2f284c2f865e218d820bbef3cef9a0cfdbedcd..03fb21c1d5944b2d0ea46d61355f2305d27ec938 100644 --- a/VECTO3GUI2020/Ninject/DocumentModule.cs +++ b/VECTO3GUI2020/Ninject/DocumentModule.cs @@ -1,5 +1,6 @@ using Ninject.Extensions.Factory; using Ninject.Modules; +using TUGraz.VectoCore.InputData.FileIO.JSON; using TUGraz.VectoCore.Utils; using VECTO3GUI2020.Model.Interfaces; using VECTO3GUI2020.Ninject.Util; @@ -18,6 +19,10 @@ namespace VECTO3GUI2020.Ninject Bind<IDocumentViewModel>().To<DeclarationJobViewModel>().Named(XmlDocumentType.DeclarationJobData.ToString()); Bind<IDocumentViewModel>().To<MultiStageJobViewModel_v0_1>() .Named(XmlDocumentType.MultistageOutputData.ToString()); + + Bind<IDocumentViewModel>().To<CreateVifViewModel>() + .Named(typeof(JSONInputDataV10_PrimaryAndStageInputBus).ToString()); + //Bind<IDocumentViewModel>().To<MultistageJobViewModel>().Named(XmlDocumentType.MultistageOutputData.ToString()); //Bind<IDocumentViewModel>().To<DeclarationTrailerJobDocumentViewModel>().Named(XmlDocumentType.DeclarationTrailerJobData.ToString()); diff --git a/VECTO3GUI2020/Ninject/FactoryModule.cs b/VECTO3GUI2020/Ninject/FactoryModule.cs index 8dffd4b7be9e5c7ca138b2a6952be477c2b709b8..fa07b41e5527c1f8a45b85fbcd9d79c311ce3a7d 100644 --- a/VECTO3GUI2020/Ninject/FactoryModule.cs +++ b/VECTO3GUI2020/Ninject/FactoryModule.cs @@ -20,11 +20,22 @@ namespace VECTO3GUI2020.Ninject { Bind<IXMLWriterFactory>().ToFactory(() => new UseFirstArgumentTypeAsNameInstanceProvider(fallback:true)); //Bind<IMultiStageViewModelFactory>().ToFactory(() => new UseFirstArgumentAsNameInstanceProvider(skipFirstArgument: true, fallback: true)); - Bind<IMultiStageViewModelFactory>().ToFactory(); + Bind<IJobEditViewModelFactory>().ToFactory(() => new UseFirstArgumentTypeAsNameInstanceProvider()); Bind<IDocumentViewModelFactory>().ToFactory(() => new UseFirstArgumentAsNameInstanceProvider(false)); Bind<IComponentViewModelFactory>().ToFactory( () => new UseFirstArgumentTypeAsNameInstanceProvider(true)); + + + Bind<IMultiStageViewModelFactory>().To<MultiStageViewModelFactory>(). + InSingletonScope(); + Bind<IMultiStageViewModelFactoryDefaultInstanceProvider>(). + ToFactory(); + Bind<IMultiStageViewModelFactoryTypeAsNameInstanceProvider>(). + ToFactory(() => new UseFirstArgumentTypeAsNameInstanceProvider()); + Bind<IMultistageViewModelFactoryFirstParameterAsNameInstanceProvider>().ToFactory(() => + new UseFirstArgumentAsNameInstanceProvider(skipFirstArgument: false)); + } } } diff --git a/VECTO3GUI2020/Ninject/MultiStageViewModelFactory.cs b/VECTO3GUI2020/Ninject/MultiStageViewModelFactory.cs new file mode 100644 index 0000000000000000000000000000000000000000..e62c06a5ebf839b3b8b31c2cbd98f09f9e2c1887 --- /dev/null +++ b/VECTO3GUI2020/Ninject/MultiStageViewModelFactory.cs @@ -0,0 +1,123 @@ +using TUGraz.VectoCommon.InputData; +using VECTO3GUI2020.ViewModel.Implementation; +using VECTO3GUI2020.ViewModel.Interfaces.Common; +using VECTO3GUI2020.ViewModel.Interfaces.Document; +using VECTO3GUI2020.ViewModel.Interfaces.JobEdit.Vehicle; +using VECTO3GUI2020.ViewModel.MultiStage.Implementation; +using VECTO3GUI2020.ViewModel.MultiStage.Interfaces; + +namespace VECTO3GUI2020.Ninject +{ + public class MultiStageViewModelFactory : IMultiStageViewModelFactory + { + private IMultiStageViewModelFactoryDefaultInstanceProvider _multiStageVmFactoryDefaultInstanceProvider; + private IMultiStageViewModelFactoryTypeAsNameInstanceProvider _multiStageViewModelFactoryTypeAsNameInstanceProvider; + + private IMultistageViewModelFactoryFirstParameterAsNameInstanceProvider + _multistageViewModelFactoryFirstParameterAsNameInstanceProvider; + + + public MultiStageViewModelFactory(IMultiStageViewModelFactoryDefaultInstanceProvider multiStageVmFactoryDefaultInstanceProvider, + IMultiStageViewModelFactoryTypeAsNameInstanceProvider multiStageViewModelFactoryTypeAsNameInstanceProvider, IMultistageViewModelFactoryFirstParameterAsNameInstanceProvider multistageViewModelFactoryFirstParameterAsNameInstanceProvider) + { + _multiStageVmFactoryDefaultInstanceProvider = multiStageVmFactoryDefaultInstanceProvider; + _multiStageViewModelFactoryTypeAsNameInstanceProvider = multiStageViewModelFactoryTypeAsNameInstanceProvider; + _multistageViewModelFactoryFirstParameterAsNameInstanceProvider = multistageViewModelFactoryFirstParameterAsNameInstanceProvider; + } + + #region Implementation of IMultiStageViewModelFactoryDefaultInstanceProvider + + public IDocumentViewModel GetStageInputViewModel(bool exemptedVehicle) + { + return _multiStageVmFactoryDefaultInstanceProvider.GetStageInputViewModel(exemptedVehicle); + } + + public IViewModelBase GetNewMultistageJobViewModel() + { + return _multiStageVmFactoryDefaultInstanceProvider.GetNewMultistageJobViewModel(); + } + + public IMultiStageJobViewModel GetMultiStageJobViewModel(IMultistageBusInputDataProvider inputData) + { + return _multiStageVmFactoryDefaultInstanceProvider.GetMultiStageJobViewModel(inputData); + } + + public IVehicleViewModel GetInterimStageVehicleViewModel() + { + return _multiStageVmFactoryDefaultInstanceProvider.GetInterimStageVehicleViewModel(); + } + + public IVehicleViewModel GetInterimStageVehicleViewModel(IVehicleDeclarationInputData consolidatedVehicleData, bool exempted) + { + return _multiStageVmFactoryDefaultInstanceProvider.GetInterimStageVehicleViewModel(consolidatedVehicleData, exempted); + } + + public IManufacturingStageViewModel GetManufacturingStageViewModel( + IManufacturingStageInputData consolidatedManufacturingStageInputData, bool exempted) + { + return _multiStageVmFactoryDefaultInstanceProvider.GetManufacturingStageViewModel(consolidatedManufacturingStageInputData, exempted); + } + + public IMultistageAirdragViewModel GetMultistageAirdragViewModel() + { + return _multiStageVmFactoryDefaultInstanceProvider.GetMultistageAirdragViewModel(); + } + + public IMultistageAirdragViewModel GetMultistageAirdragViewModel(IAirdragDeclarationInputData consolidatedAirdragInputData) + { + return _multiStageVmFactoryDefaultInstanceProvider.GetMultistageAirdragViewModel(consolidatedAirdragInputData); + } + + public IMultistageAuxiliariesViewModel GetAuxiliariesViewModel() + { + return _multiStageVmFactoryDefaultInstanceProvider.GetAuxiliariesViewModel(); + } + + public IMultistageAuxiliariesViewModel + GetAuxiliariesViewModel(IBusAuxiliariesDeclarationData consolidatedAuxiliariesInputData) + { + return _multiStageVmFactoryDefaultInstanceProvider.GetAuxiliariesViewModel(consolidatedAuxiliariesInputData); + } + + public ICreateVifViewModel GetCreateNewVifViewModel(bool completed) + { + return _multiStageVmFactoryDefaultInstanceProvider.GetCreateNewVifViewModel(completed); + } + + public ICreateVifViewModel GetCreateNewVifViewModel() + { + return _multiStageVmFactoryDefaultInstanceProvider.GetCreateNewVifViewModel(); + } + + #endregion + + #region Implementation of IMultiStageViewModelFactoryTypeAsNameInstanceProvider + + public IDocumentViewModel CreateDocumentViewModel(IDeclarationInputDataProvider inputData) + { + return _multiStageViewModelFactoryTypeAsNameInstanceProvider.CreateDocumentViewModel(inputData); + } + + public IDocumentViewModel CreateDocumentViewModel(IInputDataProvider inputData) + { + return _multiStageViewModelFactoryTypeAsNameInstanceProvider.CreateDocumentViewModel(inputData); + } + + public IVehicleViewModel CreateStageInputVehicleViewModel(IVehicleDeclarationInputData inputData) + { + return _multiStageViewModelFactoryTypeAsNameInstanceProvider.CreateStageInputVehicleViewModel(inputData); + } + + #endregion + + + #region Implementation of IMultistageViewModelFactoryFirstParameterAsNameInstanceProvider + + public IVehicleViewModel CreateStageInputVehicleViewModel(string inputProviderType) + { + return _multistageViewModelFactoryFirstParameterAsNameInstanceProvider.CreateStageInputVehicleViewModel(inputProviderType); + } + + #endregion + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Ninject/MultistageLazyDependencies.cs b/VECTO3GUI2020/Ninject/MultistageLazyDependencies.cs index b268e93677b245278571010fde2f3383fdf23595..4272646006b9a3ed0b98932bef69d93d44e908ff 100644 --- a/VECTO3GUI2020/Ninject/MultistageLazyDependencies.cs +++ b/VECTO3GUI2020/Ninject/MultistageLazyDependencies.cs @@ -11,26 +11,18 @@ namespace VECTO3GUI2020.Ninject { public class MultistageLazyDependencies : IMultistageDependencies { - + private readonly Lazy<IXMLWriterFactory> _xmlWriterFactory; + private readonly Lazy<IDeclarationInjectFactory> _injectFactory; + private readonly Lazy<IComponentViewModelFactory> _componentViewModelFactory; + private readonly Lazy<IMultiStageViewModelFactory> _multistageViewModelFactory; private readonly Lazy<IDialogHelper> _dialogHelper; + public Lazy<IMultiStageViewModelFactory> MultistageViewModelFactory => _multistageViewModelFactory; public Lazy<IDialogHelper> DialogHelperLazy => _dialogHelper; public IDialogHelper DialogHelper => _dialogHelper.Value; - - - //private readonly Lazy<XMLValidator> _xmlValidator = new Lazy<XMLValidator>(() => {return }); - //public Lazy<XMLValidator> XMLValidatorLazy => _xmlValidator; - //public XMLValidator XMLValidator => _xmlValidator.Value; - - public IDeclarationInjectFactory InjectFactory => _injectFactory.Value; public IComponentViewModelFactory ComponentViewModelFactory => _componentViewModelFactory.Value; public IXMLWriterFactory XMLWriterFactory => _xmlWriterFactory.Value; - private Lazy<IXMLWriterFactory> _xmlWriterFactory; - - - private readonly Lazy<IDeclarationInjectFactory> _injectFactory; - private readonly Lazy<IComponentViewModelFactory> _componentViewModelFactory; public MultistageLazyDependencies( Lazy<IDialogHelper> dialogHelper, Lazy<IDeclarationInjectFactory> injectFactory, @@ -42,7 +34,7 @@ namespace VECTO3GUI2020.Ninject _componentViewModelFactory = componentViewModelFactory; _injectFactory = injectFactory; _xmlWriterFactory = xmlWriterFactory; - + _multistageViewModelFactory = viewModelFactory; } } } \ No newline at end of file diff --git a/VECTO3GUI2020/Ninject/MultistageModule.cs b/VECTO3GUI2020/Ninject/MultistageModule.cs index c36e13772ffe0bc172f7b9eb92b7bbd1cc8c750b..3e9c110f8a36a1abee882d736707c01f8cc92c72 100644 --- a/VECTO3GUI2020/Ninject/MultistageModule.cs +++ b/VECTO3GUI2020/Ninject/MultistageModule.cs @@ -6,9 +6,15 @@ using System.Threading.Tasks; using System.Windows.Automation.Peers; using Ninject.Extensions.Factory; using Ninject.Modules; +using TUGraz.VectoCore.InputData.FileIO.XML.Declaration; +using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider; using TUGraz.VectoCore.Models.SimulationComponent; +using VECTO3GUI2020.Model.Multistage; using VECTO3GUI2020.Ninject.Util; +using VECTO3GUI2020.ViewModel.Implementation; +using VECTO3GUI2020.ViewModel.Implementation.Common; using VECTO3GUI2020.ViewModel.Interfaces.Common; +using VECTO3GUI2020.ViewModel.Interfaces.Document; using VECTO3GUI2020.ViewModel.Interfaces.JobEdit.Vehicle; using VECTO3GUI2020.ViewModel.MultiStage.Implementation; using VECTO3GUI2020.ViewModel.MultiStage.Interfaces; @@ -26,11 +32,11 @@ namespace VECTO3GUI2020.Ninject Bind<IMultiStageJobViewModel>().To<MultiStageJobViewModel_v0_1>(). NamedLikeFactoryMethod((IMultiStageViewModelFactory f) => f.GetMultiStageJobViewModel(null)); - Bind<IVehicleViewModel>().To<DeclarationInterimStageBusVehicleViewModel_v2_8>(). + Bind<IVehicleViewModel>().To<InterimStageBusVehicleViewModel_v2_8>(). NamedLikeFactoryMethod((IMultiStageViewModelFactory f)=>f.GetInterimStageVehicleViewModel()); Bind<IManufacturingStageViewModel>().To<ManufacturingStageViewModel_v0_1>(). - NamedLikeFactoryMethod((IMultiStageViewModelFactory f) => f.GetManufacturingStageViewModel(null)); + NamedLikeFactoryMethod((IMultiStageViewModelFactory f) => f.GetManufacturingStageViewModel(null, false)); Bind<IMultistageAirdragViewModel>().To<MultistageAirdragViewModel>(). NamedLikeFactoryMethod((IMultiStageViewModelFactory f) => f.GetMultistageAirdragViewModel()); @@ -39,6 +45,26 @@ namespace VECTO3GUI2020.Ninject NamedLikeFactoryMethod((IMultiStageViewModelFactory f) => f.GetAuxiliariesViewModel(null)); Bind<IMultistageDependencies>().To<MultistageLazyDependencies>(); + + Bind<ICreateVifViewModel>().To<CreateVifViewModel>(). + NamedLikeFactoryMethod((IMultiStageViewModelFactory f) => f.GetCreateNewVifViewModel()); + + Bind<IDocumentViewModel>().To<StageInputViewModel>() + .Named(typeof(XMLDeclarationInputDataProviderV20).ToString()); + + Bind<IDocumentViewModel>().To<StageInputViewModel>() + .NamedLikeFactoryMethod((IMultiStageViewModelFactory f) => f.GetStageInputViewModel(default(bool))); + + Bind<IAdditionalJobInfoViewModel>().To<AdditionalJobInfoViewModelMultiStage>() + .WhenInjectedInto(typeof(IMultiStageJobViewModel)); + + Bind<IAdditionalJobInfoViewModel>().To<AdditionalJobInfoViewModelNewVif>() + .WhenInjectedInto(typeof(ICreateVifViewModel)); + + Bind<IAdditionalJobInfoViewModel>().To<AdditionalJobInfoViewModelStageInput>() + .WhenInjectedInto(typeof(IStageViewModelBase)); + + Bind<JSONJob>().ToSelf(); } } } diff --git a/VECTO3GUI2020/Ninject/Vecto3GUI2020Module.cs b/VECTO3GUI2020/Ninject/Vecto3GUI2020Module.cs new file mode 100644 index 0000000000000000000000000000000000000000..cfbe3a2fc2872d464985a0648cca0122af454cfc --- /dev/null +++ b/VECTO3GUI2020/Ninject/Vecto3GUI2020Module.cs @@ -0,0 +1,33 @@ +using System.Windows; +using Ninject.Modules; +using VECTO3GUI2020.Helper; +using VECTO3GUI2020.Model.Implementation; +using VECTO3GUI2020.Model.Interfaces; +using VECTO3GUI2020.ViewModel; +using VECTO3GUI2020.ViewModel.Implementation; +using VECTO3GUI2020.ViewModel.Interfaces; + +namespace VECTO3GUI2020.Ninject +{ + public class Vecto3GUI2020Module : NinjectModule + { + #region Overrides of NinjectModule + + public override void Load() + { + + Bind<IJobListViewModel>().To<JobListViewModel>().InSingletonScope(); + Bind<IMainWindowViewModel>().To<MainWindowViewModel>(); + Bind<IMainViewModel>().To<JobListViewModel>(); + Bind<ISettingsViewModel>().To<SettingsViewModel>(); + Bind<IOutputViewModel>().To<OutputViewModel>().InSingletonScope(); + Bind<ISettingsModel>().To<SettingsModel>().InSingletonScope(); + Bind<IDialogHelper>().To<DialogHelper>().InSingletonScope(); + Bind<IWindowHelper>().To<WindowHelper>(); + Bind<AboutViewModel>().ToSelf().InSingletonScope(); + + } + + #endregion + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/Ninject/Vehicle/ComponentModule.cs b/VECTO3GUI2020/Ninject/Vehicle/ComponentModule.cs index edbbce58125ff6731a7d06984f093e08a7a5814c..7754d1da5fbd91b6b48568ab739c58f7d23c2788 100644 --- a/VECTO3GUI2020/Ninject/Vehicle/ComponentModule.cs +++ b/VECTO3GUI2020/Ninject/Vehicle/ComponentModule.cs @@ -26,8 +26,10 @@ namespace VECTO3GUI2020.Ninject.Vehicle Bind<IVehicleViewModel>().To<VehicleViewModel_v1_0>().Named(VehicleViewModel_v1_0.VERSION); Bind<IVehicleViewModel>().To<VehicleViewModel_v2_0>().Named(VehicleViewModel_v2_0.VERSION); - //Bind<IVehicleViewModel>().To<DeclarationInterimStageBusVehicleViewModel_v2_8>() - // .Named(DeclarationInterimStageBusVehicleViewModel_v2_8.INPUTPROVIDERTYPE).BindingConfiguration.; + + + Bind<IVehicleViewModel>().To<InterimStageBusVehicleViewModel_v2_8>().Named(InterimStageBusVehicleViewModel_v2_8.VERSION); + Bind<IVehicleViewModel>().To<InterimStageBusVehicleViewModel_v2_8>().Named(InterimStageBusVehicleViewModel_v2_8.VERSION_EXEMPTED); Bind<IComponentViewModel>().To<EngineViewModel_v1_0>().Named(EngineViewModel_v1_0.VERSION); diff --git a/VECTO3GUI2020/Properties/GUILabels.Designer.cs b/VECTO3GUI2020/Properties/GUILabels.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..a0bbf92d1f74e34b3175c24345bb34a7e3e897d2 --- /dev/null +++ b/VECTO3GUI2020/Properties/GUILabels.Designer.cs @@ -0,0 +1,108 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace VECTO3GUI2020.Properties { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class GUILabels { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal GUILabels() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VECTO3GUI2020.Properties.GUILabels", typeof(GUILabels).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// Looks up a localized string similar to VECTO. + /// </summary> + public static string DefaultTitle { + get { + return ResourceManager.GetString("DefaultTitle", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to New Complete Job. + /// </summary> + public static string NewCompleteJob { + get { + return ResourceManager.GetString("NewCompleteJob", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to New Interim/Completed Job. + /// </summary> + public static string NewInterimOrCompletedJob { + get { + return ResourceManager.GetString("NewInterimOrCompletedJob", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to New Primary Job with Interim Input. + /// </summary> + public static string NewPrimaryAndInterimJob { + get { + return ResourceManager.GetString("NewPrimaryAndInterimJob", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to No Manufacturing Steps. + /// </summary> + public static string no_manufacturing_stages { + get { + return ResourceManager.GetString("no manufacturing stages", resourceCulture); + } + } + } +} diff --git a/VECTO3GUI2020/Properties/GUILabels.resx b/VECTO3GUI2020/Properties/GUILabels.resx new file mode 100644 index 0000000000000000000000000000000000000000..c045f7d379c534175080ba21803c4b8e922fd152 --- /dev/null +++ b/VECTO3GUI2020/Properties/GUILabels.resx @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="DefaultTitle" xml:space="preserve"> + <value>VECTO</value> + </data> + <data name="NewPrimaryAndInterimJob" xml:space="preserve"> + <value>New Primary Job with Interim Input</value> + </data> + <data name="NewInterimOrCompletedJob" xml:space="preserve"> + <value>New Interim/Completed Job</value> + </data> + <data name="NewCompleteJob" xml:space="preserve"> + <value>New Complete Job</value> + </data> + <data name="no manufacturing stages" xml:space="preserve"> + <value>No Manufacturing Steps</value> + </data> +</root> \ No newline at end of file diff --git a/VECTO3GUI2020/Resources/Converter.xaml b/VECTO3GUI2020/Resources/Converter.xaml index ee924cdf0baa31fbe9a8b27f15c5c77b939709f5..d8d3ef9da09a635a6121bd97b438347162a13a2f 100644 --- a/VECTO3GUI2020/Resources/Converter.xaml +++ b/VECTO3GUI2020/Resources/Converter.xaml @@ -1,7 +1,7 @@ <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:converter="clr-namespace:VECTO3GUI2020.Helper.Converter" - xmlns:helper="clr-namespace:VECTO3GUI2020.Helper"> + xmlns:converter="clr-namespace:VECTO3GUI2020.Helper.Converter"> + <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> <converter:SIToUnitString x:Shared="False" x:Key="SIToUnitStringConverter"/> @@ -17,7 +17,9 @@ <converter:EnumConverter x:Key="EnumConverter"></converter:EnumConverter> <converter:NullToUnsetValueConverter x:Key="NullToUnsetValue"></converter:NullToUnsetValueConverter> <converter:BoolToIntConverter x:Key="BoolToIntConverter"></converter:BoolToIntConverter> + <converter:PropertyNameToLabelTextConverter x:Key="PropertyNameToLabelConverter"/> + </ResourceDictionary> diff --git a/VECTO3GUI2020/Resources/DataTemplateSelectors.xaml b/VECTO3GUI2020/Resources/DataTemplateSelectors.xaml new file mode 100644 index 0000000000000000000000000000000000000000..acb9d8062dca35fd8f288c268e975d575814889e --- /dev/null +++ b/VECTO3GUI2020/Resources/DataTemplateSelectors.xaml @@ -0,0 +1,7 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:templateSelector="clr-namespace:VECTO3GUI2020.Helper.TemplateSelector"> + <templateSelector:MultistageParameterDataTemplateSelector x:Key="MultistageParameterTemplateSelector"/> + <templateSelector:MultistageVehicleDataTemplateSelector x:Key="MultistageVehicleDataTemplateSelector"/> + +</ResourceDictionary> \ No newline at end of file diff --git a/VECTO3GUI2020/Resources/Icons/FolderClosed_16x.xaml b/VECTO3GUI2020/Resources/Icons/FolderClosed_16x.xaml new file mode 100644 index 0000000000000000000000000000000000000000..3d162d6e29001f1317a402e6c40d19258bb411f6 --- /dev/null +++ b/VECTO3GUI2020/Resources/Icons/FolderClosed_16x.xaml @@ -0,0 +1,20 @@ +<!-- This file was generated by the AiToXaml tool.--> +<!-- Tool Version: 14.0.22307.0 --> +<Viewbox Width="16" Height="16" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> + <Rectangle Width="16" Height="16"> + <Rectangle.Fill> + <DrawingBrush> + <DrawingBrush.Drawing> + <DrawingGroup> + <DrawingGroup.Children> + <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M0,0L16,0 16,16 0,16z" /> + <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M1.5,1L9.61,1 10.61,3 13.496,3C14.323,3,14.996,3.673,14.996,4.5L14.996,12.5C14.996,13.327,14.323,14,13.496,14L1.5,14C0.673,14,0,13.327,0,12.5L0,2.5C0,1.673,0.673,1,1.5,1" /> + <GeometryDrawing Brush="#FFEFEFF0" Geometry="F1M1.9998,3.0004L1.9998,4.0004 8.8738,4.0004 8.3738,3.0004z" /> + <GeometryDrawing Brush="#FFDBB679" Geometry="F1M2,3L8.374,3 8.874,4 2,4z M13.496,4L10,4 9.992,4 8.992,2 1.5,2C1.225,2,1,2.224,1,2.5L1,12.5C1,12.776,1.225,13,1.5,13L13.496,13C13.773,13,13.996,12.776,13.996,12.5L13.996,4.5C13.996,4.224,13.773,4,13.496,4" /> + </DrawingGroup.Children> + </DrawingGroup> + </DrawingBrush.Drawing> + </DrawingBrush> + </Rectangle.Fill> + </Rectangle> +</Viewbox> \ No newline at end of file diff --git a/VECTO3GUI2020/Resources/Icons/StatusInformationOutline_nohalo_16x.xaml b/VECTO3GUI2020/Resources/Icons/StatusInformationOutline_nohalo_16x.xaml new file mode 100644 index 0000000000000000000000000000000000000000..9a31d5f1e2aeade975c276b7675c3aea461f161a --- /dev/null +++ b/VECTO3GUI2020/Resources/Icons/StatusInformationOutline_nohalo_16x.xaml @@ -0,0 +1,18 @@ +<!-- This file was generated by the AiToXaml tool.--> +<!-- Tool Version: 14.0.22307.0 --> +<Viewbox Width="16" Height="16" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> + <Rectangle Width="16" Height="16"> + <Rectangle.Fill> + <DrawingBrush> + <DrawingBrush.Drawing> + <DrawingGroup> + <DrawingGroup.Children> + <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" /> + <GeometryDrawing Brush="#FF1AA1E2" Geometry="F1M7,5L8,5 8,4 7,4z M14,7.5C14,6.906 13.922,6.332 13.766,5.777 13.609,5.223 13.391,4.705 13.109,4.223 12.828,3.741 12.489,3.302 12.094,2.906 11.698,2.51 11.259,2.172 10.777,1.891 10.296,1.609 9.777,1.391 9.223,1.234 8.668,1.078 8.094,1 7.5,1 6.901,1 6.326,1.078 5.773,1.234 5.221,1.391 4.705,1.609 4.223,1.891 3.741,2.172 3.302,2.51 2.906,2.906 2.51,3.302 2.172,3.741 1.891,4.223 1.609,4.705 1.391,5.223 1.234,5.777 1.078,6.332 1,6.906 1,7.5 1,8.094 1.078,8.668 1.234,9.223 1.391,9.777 1.609,10.296 1.891,10.777 2.172,11.259 2.51,11.698 2.906,12.094 3.302,12.489 3.741,12.828 4.223,13.109 4.705,13.391 5.221,13.609 5.773,13.766 6.326,13.922 6.901,14 7.5,14 8.094,14 8.668,13.922 9.223,13.766 9.777,13.609 10.296,13.391 10.777,13.109 11.259,12.828 11.698,12.489 12.094,12.094 12.489,11.698 12.828,11.259 13.109,10.777 13.391,10.296 13.609,9.779 13.766,9.227 13.922,8.674 14,8.099 14,7.5 M15,7.5C15,8.193 14.911,8.858 14.734,9.496 14.558,10.134 14.306,10.731 13.98,11.289 13.655,11.847 13.265,12.353 12.809,12.809 12.353,13.265 11.847,13.655 11.289,13.98 10.731,14.306 10.134,14.558 9.496,14.734 8.858,14.911 8.193,15 7.5,15 6.807,15 6.142,14.911 5.504,14.734 4.866,14.558 4.268,14.306 3.711,13.98 3.154,13.655 2.647,13.265 2.191,12.809 1.736,12.353 1.345,11.847 1.02,11.289 0.694,10.731 0.443,10.134 0.266,9.496 0.088,8.858 0,8.193 0,7.5 0,6.807 0.088,6.142 0.266,5.504 0.443,4.866 0.694,4.268 1.02,3.711 1.345,3.154 1.736,2.647 2.191,2.191 2.647,1.736 3.154,1.345 3.711,1.02 4.268,0.694000000000001 4.866,0.443 5.504,0.266 6.142,0.0879999999999992 6.807,0 7.5,0 8.193,0 8.858,0.0879999999999992 9.496,0.266 10.134,0.443 10.731,0.694000000000001 11.289,1.02 11.847,1.345 12.353,1.736 12.809,2.191 13.265,2.647 13.655,3.154 13.98,3.711 14.306,4.268 14.558,4.866 14.734,5.504 14.911,6.142 15,6.807 15,7.5 M7,6L8,6 8,11 7,11z" /> + </DrawingGroup.Children> + </DrawingGroup> + </DrawingBrush.Drawing> + </DrawingBrush> + </Rectangle.Fill> + </Rectangle> +</Viewbox> \ No newline at end of file diff --git a/VECTO3GUI2020/Resources/Icons/drawables.xaml b/VECTO3GUI2020/Resources/Icons/drawables.xaml index 2d2c760217db5d9d2b2519a774f34d0e9c52e469..cae566a8905183a54e27cc4438048d3594a6a396 100644 --- a/VECTO3GUI2020/Resources/Icons/drawables.xaml +++ b/VECTO3GUI2020/Resources/Icons/drawables.xaml @@ -66,4 +66,45 @@ </Rectangle> </Viewbox> </DataTemplate> + <DataTemplate x:Key="FolderIcon"> + <Viewbox Width="16" Height="16" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> + <Rectangle Width="16" Height="16"> + <Rectangle.Fill> + <DrawingBrush> + <DrawingBrush.Drawing> + <DrawingGroup> + <DrawingGroup.Children> + <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M0,0L16,0 16,16 0,16z" /> + <GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M1.5,1L9.61,1 10.61,3 13.496,3C14.323,3,14.996,3.673,14.996,4.5L14.996,12.5C14.996,13.327,14.323,14,13.496,14L1.5,14C0.673,14,0,13.327,0,12.5L0,2.5C0,1.673,0.673,1,1.5,1" /> + <GeometryDrawing Brush="#FFEFEFF0" Geometry="F1M1.9998,3.0004L1.9998,4.0004 8.8738,4.0004 8.3738,3.0004z" /> + <GeometryDrawing Brush="#FFDBB679" Geometry="F1M2,3L8.374,3 8.874,4 2,4z M13.496,4L10,4 9.992,4 8.992,2 1.5,2C1.225,2,1,2.224,1,2.5L1,12.5C1,12.776,1.225,13,1.5,13L13.496,13C13.773,13,13.996,12.776,13.996,12.5L13.996,4.5C13.996,4.224,13.773,4,13.496,4" /> + </DrawingGroup.Children> + </DrawingGroup> + </DrawingBrush.Drawing> + </DrawingBrush> + </Rectangle.Fill> + </Rectangle> + </Viewbox> + </DataTemplate> + + <DataTemplate x:Key="InformationIcon"> + <Viewbox Width="16" Height="16" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> + <Rectangle Width="16" Height="16"> + <Rectangle.Fill> + <DrawingBrush> + <DrawingBrush.Drawing> + <DrawingGroup> + <DrawingGroup.Children> + <GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" /> + <GeometryDrawing Brush="{StaticResource AccentColorButton}" Geometry="F1M7,5L8,5 8,4 7,4z M14,7.5C14,6.906 13.922,6.332 13.766,5.777 13.609,5.223 13.391,4.705 13.109,4.223 12.828,3.741 12.489,3.302 12.094,2.906 11.698,2.51 11.259,2.172 10.777,1.891 10.296,1.609 9.777,1.391 9.223,1.234 8.668,1.078 8.094,1 7.5,1 6.901,1 6.326,1.078 5.773,1.234 5.221,1.391 4.705,1.609 4.223,1.891 3.741,2.172 3.302,2.51 2.906,2.906 2.51,3.302 2.172,3.741 1.891,4.223 1.609,4.705 1.391,5.223 1.234,5.777 1.078,6.332 1,6.906 1,7.5 1,8.094 1.078,8.668 1.234,9.223 1.391,9.777 1.609,10.296 1.891,10.777 2.172,11.259 2.51,11.698 2.906,12.094 3.302,12.489 3.741,12.828 4.223,13.109 4.705,13.391 5.221,13.609 5.773,13.766 6.326,13.922 6.901,14 7.5,14 8.094,14 8.668,13.922 9.223,13.766 9.777,13.609 10.296,13.391 10.777,13.109 11.259,12.828 11.698,12.489 12.094,12.094 12.489,11.698 12.828,11.259 13.109,10.777 13.391,10.296 13.609,9.779 13.766,9.227 13.922,8.674 14,8.099 14,7.5 M15,7.5C15,8.193 14.911,8.858 14.734,9.496 14.558,10.134 14.306,10.731 13.98,11.289 13.655,11.847 13.265,12.353 12.809,12.809 12.353,13.265 11.847,13.655 11.289,13.98 10.731,14.306 10.134,14.558 9.496,14.734 8.858,14.911 8.193,15 7.5,15 6.807,15 6.142,14.911 5.504,14.734 4.866,14.558 4.268,14.306 3.711,13.98 3.154,13.655 2.647,13.265 2.191,12.809 1.736,12.353 1.345,11.847 1.02,11.289 0.694,10.731 0.443,10.134 0.266,9.496 0.088,8.858 0,8.193 0,7.5 0,6.807 0.088,6.142 0.266,5.504 0.443,4.866 0.694,4.268 1.02,3.711 1.345,3.154 1.736,2.647 2.191,2.191 2.647,1.736 3.154,1.345 3.711,1.02 4.268,0.694000000000001 4.866,0.443 5.504,0.266 6.142,0.0879999999999992 6.807,0 7.5,0 8.193,0 8.858,0.0879999999999992 9.496,0.266 10.134,0.443 10.731,0.694000000000001 11.289,1.02 11.847,1.345 12.353,1.736 12.809,2.191 13.265,2.647 13.655,3.154 13.98,3.711 14.306,4.268 14.558,4.866 14.734,5.504 14.911,6.142 15,6.807 15,7.5 M7,6L8,6 8,11 7,11z" /> + + <!--<GeometryDrawing Brush="#FF1AA1E2" Geometry="F1M7,5L8,5 8,4 7,4z M14,7.5C14,6.906 13.922,6.332 13.766,5.777 13.609,5.223 13.391,4.705 13.109,4.223 12.828,3.741 12.489,3.302 12.094,2.906 11.698,2.51 11.259,2.172 10.777,1.891 10.296,1.609 9.777,1.391 9.223,1.234 8.668,1.078 8.094,1 7.5,1 6.901,1 6.326,1.078 5.773,1.234 5.221,1.391 4.705,1.609 4.223,1.891 3.741,2.172 3.302,2.51 2.906,2.906 2.51,3.302 2.172,3.741 1.891,4.223 1.609,4.705 1.391,5.223 1.234,5.777 1.078,6.332 1,6.906 1,7.5 1,8.094 1.078,8.668 1.234,9.223 1.391,9.777 1.609,10.296 1.891,10.777 2.172,11.259 2.51,11.698 2.906,12.094 3.302,12.489 3.741,12.828 4.223,13.109 4.705,13.391 5.221,13.609 5.773,13.766 6.326,13.922 6.901,14 7.5,14 8.094,14 8.668,13.922 9.223,13.766 9.777,13.609 10.296,13.391 10.777,13.109 11.259,12.828 11.698,12.489 12.094,12.094 12.489,11.698 12.828,11.259 13.109,10.777 13.391,10.296 13.609,9.779 13.766,9.227 13.922,8.674 14,8.099 14,7.5 M15,7.5C15,8.193 14.911,8.858 14.734,9.496 14.558,10.134 14.306,10.731 13.98,11.289 13.655,11.847 13.265,12.353 12.809,12.809 12.353,13.265 11.847,13.655 11.289,13.98 10.731,14.306 10.134,14.558 9.496,14.734 8.858,14.911 8.193,15 7.5,15 6.807,15 6.142,14.911 5.504,14.734 4.866,14.558 4.268,14.306 3.711,13.98 3.154,13.655 2.647,13.265 2.191,12.809 1.736,12.353 1.345,11.847 1.02,11.289 0.694,10.731 0.443,10.134 0.266,9.496 0.088,8.858 0,8.193 0,7.5 0,6.807 0.088,6.142 0.266,5.504 0.443,4.866 0.694,4.268 1.02,3.711 1.345,3.154 1.736,2.647 2.191,2.191 2.647,1.736 3.154,1.345 3.711,1.02 4.268,0.694000000000001 4.866,0.443 5.504,0.266 6.142,0.0879999999999992 6.807,0 7.5,0 8.193,0 8.858,0.0879999999999992 9.496,0.266 10.134,0.443 10.731,0.694000000000001 11.289,1.02 11.847,1.345 12.353,1.736 12.809,2.191 13.265,2.647 13.655,3.154 13.98,3.711 14.306,4.268 14.558,4.866 14.734,5.504 14.911,6.142 15,6.807 15,7.5 M7,6L8,6 8,11 7,11z" />--> + </DrawingGroup.Children> + </DrawingGroup> + </DrawingBrush.Drawing> + </DrawingBrush> + </Rectangle.Fill> + </Rectangle> + </Viewbox> + </DataTemplate> </ResourceDictionary> \ No newline at end of file diff --git a/VECTO3GUI2020/Resources/Images/JRC-About.png b/VECTO3GUI2020/Resources/Images/JRC-About.png new file mode 100644 index 0000000000000000000000000000000000000000..7ccda103840925863e14e959ef1371dedc797ba6 Binary files /dev/null and b/VECTO3GUI2020/Resources/Images/JRC-About.png differ diff --git a/VECTO3GUI2020/Resources/Images/VECTO-About.png b/VECTO3GUI2020/Resources/Images/VECTO-About.png new file mode 100644 index 0000000000000000000000000000000000000000..4755b511626afcd157f27b0cf70e1c21b6ee067e Binary files /dev/null and b/VECTO3GUI2020/Resources/Images/VECTO-About.png differ diff --git a/VECTO3GUI2020/Resources/MultistageParameterDataTemplates.xaml b/VECTO3GUI2020/Resources/MultistageParameterDataTemplates.xaml index f3499fc795fdb1f56bf70c50d1759cc676333396..8cfc734c7145572251067ec2c1cc7edb1054dff6 100644 --- a/VECTO3GUI2020/Resources/MultistageParameterDataTemplates.xaml +++ b/VECTO3GUI2020/Resources/MultistageParameterDataTemplates.xaml @@ -1,9 +1,9 @@ <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:customControls="clr-namespace:VECTO3GUI2020.Views.Multistage.CustomControls" - xmlns:helper="clr-namespace:VECTO3GUI2020.Helper"> + xmlns:helper="clr-namespace:VECTO3GUI2020.Helper" + xmlns:templateSelector="clr-namespace:VECTO3GUI2020.Helper.TemplateSelector"> - <helper:MultistageParameterDataTemplateSelector x:Key="MultistageParameterTemplateSelector"/> <customControls:MultistageParameterTextView x:Key="MultistageTextBoxView"/> <customControls:MultistageParameterComboBoxView x:Key="MultistageComboBoxView"/> diff --git a/VECTO3GUI2020/Resources/ObjectProvider.xaml b/VECTO3GUI2020/Resources/ObjectProvider.xaml index 1c858f64f60896d10c1172ad92ddc26a8d65996b..91185b8f684c5c35100f50cd3d82a698c1439418 100644 --- a/VECTO3GUI2020/Resources/ObjectProvider.xaml +++ b/VECTO3GUI2020/Resources/ObjectProvider.xaml @@ -7,5 +7,4 @@ ObjectType="{x:Type helper:ConvertedSIDummyCreator}" MethodName="CreateMillimeterDummy"/> - <ObjectDataProvider x:Key="BusStringResourceManager" ObjectType="{x:Type resources:ResourceManager}" ObjectInstance="{x:Static properties:BusStrings.ResourceManager}"/> </ResourceDictionary> \ No newline at end of file diff --git a/VECTO3GUI2020/Resources/Sizes.xaml b/VECTO3GUI2020/Resources/Sizes.xaml new file mode 100644 index 0000000000000000000000000000000000000000..2b00aceb9559ab6d404d9d5c361691f6305424c0 --- /dev/null +++ b/VECTO3GUI2020/Resources/Sizes.xaml @@ -0,0 +1,8 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:system="clr-namespace:System;assembly=mscorlib"> + <!--<system:Double x:Key="EditJobUserControlWidth"> + 800.0 + </system:Double> + <system:Double x:Key="EditJobUserControlHeight">600</system:Double>--> +</ResourceDictionary> \ No newline at end of file diff --git a/VECTO3GUI2020/Resources/Styles/Colors.xaml b/VECTO3GUI2020/Resources/Styles/Colors.xaml index 24f9fd5328a3a725b7cb3a642ff474827b645142..2cf976355e8909033f32cfa95b0b02fe82506a7f 100644 --- a/VECTO3GUI2020/Resources/Styles/Colors.xaml +++ b/VECTO3GUI2020/Resources/Styles/Colors.xaml @@ -15,4 +15,6 @@ Color="{Binding Color, Source={StaticResource AccentColorButton}, Mode=OneWay}" /> + <SolidColorBrush x:Key="SemiTransparentWhite" Opacity="0.5" Color="White"></SolidColorBrush> + <SolidColorBrush x:Key="SemiTransparentYellow" Opacity="0.5" Color="Gold"></SolidColorBrush> </ResourceDictionary> \ No newline at end of file diff --git a/VECTO3GUI2020/DataGridStyles.xaml b/VECTO3GUI2020/Resources/Styles/DataGridStyles.xaml similarity index 88% rename from VECTO3GUI2020/DataGridStyles.xaml rename to VECTO3GUI2020/Resources/Styles/DataGridStyles.xaml index 71273451d233039b3dca9760cbe966e2d8dbd21e..3d2178c42d7c415640fca69ad5c9ad947041d2c4 100644 --- a/VECTO3GUI2020/DataGridStyles.xaml +++ b/VECTO3GUI2020/Resources/Styles/DataGridStyles.xaml @@ -37,12 +37,15 @@ <Style x:Key="DataGridCellStyle1" TargetType="{x:Type DataGridCell}"> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="Transparent"/> - <Setter Property="BorderThickness" Value="1"/> + <Setter Property="BorderThickness" Value="0"/> + <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type DataGridCell}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> - <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> + <ContentPresenter VerticalAlignment="Center" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"> + + </ContentPresenter> </Border> </ControlTemplate> </Setter.Value> @@ -53,7 +56,7 @@ <!-- <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> --> <Setter Property="Foreground" Value="Black"/> - <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> + <!--<Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>--> </Trigger> <Trigger Property="IsKeyboardFocusWithin" Value="True"> <Setter Property="BorderBrush" Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}"/> @@ -64,7 +67,7 @@ <Condition Property="Selector.IsSelectionActive" Value="false"/> </MultiTrigger.Conditions> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> - <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> + <!--<Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>--> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/> </MultiTrigger> <Trigger Property="IsEnabled" Value="false"> diff --git a/VECTO3GUI2020/Resources/Templates/ButtonTemplates.xaml b/VECTO3GUI2020/Resources/Templates/ButtonTemplates.xaml new file mode 100644 index 0000000000000000000000000000000000000000..72b220dc8dc1e8b36c766f283b5e269aa7d320b6 --- /dev/null +++ b/VECTO3GUI2020/Resources/Templates/ButtonTemplates.xaml @@ -0,0 +1,11 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + + <ControlTemplate x:Key="multistageParameterControlErrorTemplate"> + <Grid> + <AdornedElementPlaceholder x:Name="placeHolder"></AdornedElementPlaceholder> + <TextBlock Text="!" Height="Auto" FontWeight="ExtraBold" Foreground="OrangeRed" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0 0 -10 0"></TextBlock> + </Grid> + + </ControlTemplate> +</ResourceDictionary> \ No newline at end of file diff --git a/VECTO3GUI2020/Resources/ViewModelBindings.xaml b/VECTO3GUI2020/Resources/ViewModelBindings.xaml index 8ab51b42b3298ef42586280491f1b96d77eb0b38..8c644cee027e7fa3d676bed2e31c27b9a82d5e73 100644 --- a/VECTO3GUI2020/Resources/ViewModelBindings.xaml +++ b/VECTO3GUI2020/Resources/ViewModelBindings.xaml @@ -9,10 +9,12 @@ xmlns:vehicleimpl="clr-namespace:VECTO3GUI2020.ViewModel.Implementation.JobEdit.Vehicle" xmlns:vehicleviews="clr-namespace:VECTO3GUI2020.Views.JobEditViews.Vehicle" xmlns:multistageviews="clr-namespace:VECTO3GUI2020.Views.Multistage" + xmlns:additionaljobInfoViews="clr-namespace:VECTO3GUI2020.Views.Multistage.AdditionalJobInfoViews" xmlns:componentimpl="clr-namespace:VECTO3GUI2020.ViewModel.Implementation.JobEdit.Vehicle.Components" xmlns:componentviews="clr-namespace:VECTO3GUI2020.Views.JobEditViews.Vehicle.Components" xmlns:multistageimpl="clr-namespace:VECTO3GUI2020.ViewModel.MultiStage.Implementation" - xmlns:viewModel="clr-namespace:VECTO3GUI2020.ViewModel"> + xmlns:viewModel="clr-namespace:VECTO3GUI2020.ViewModel" + xmlns:common="clr-namespace:VECTO3GUI2020.ViewModel.Implementation.Common"> <DataTemplate x:Shared="False" DataType="{x:Type impl:JobListViewModel}"> <views:JobListView /> </DataTemplate> @@ -28,7 +30,9 @@ <views:SettingsView/> </DataTemplate> - + <DataTemplate x:Shared="False" DataType="{x:Type impl:AboutViewModel}"> + <views:AboutView></views:AboutView> + </DataTemplate> @@ -210,7 +214,7 @@ <multistageviews:ManufacturingStageView></multistageviews:ManufacturingStageView> </DataTemplate> - <DataTemplate x:Shared="False" DataType="{x:Type multistageimpl:DeclarationInterimStageBusVehicleViewModel_v2_8}"> + <DataTemplate x:Shared="False" DataType="{x:Type multistageimpl:InterimStageBusVehicleViewModel_v2_8}"> <multistageviews:VehicleView_v2_8/> </DataTemplate> @@ -225,10 +229,31 @@ <DataTemplate x:Shared="False" DataType="{x:Type multistageimpl:MultistageAuxiliariesViewModel}"> <multistageviews:ManufacturingStageAuxiliariesView/> </DataTemplate> + + <DataTemplate DataType="{x:Type multistageimpl:StageInputViewModel}"> + <multistageviews:ManufacturingStageView></multistageviews:ManufacturingStageView> + </DataTemplate> + + <DataTemplate DataType="{x:Type multistageimpl:CreateVifViewModel}"> + <multistageviews:CreateVifView/> + </DataTemplate> <!--#endregion--> <DataTemplate DataType="{x:Type local:TestViewModel}"> <local:Test></local:Test> </DataTemplate> + <DataTemplate DataType="{x:Type common:AdditionalJobInfoViewModelMultiStage}"> + <additionaljobInfoViews:AdditionalJobInfoViewMultiStage/> + </DataTemplate> + + <DataTemplate DataType="{x:Type common:AdditionalJobInfoViewModelNewVif}"> + <additionaljobInfoViews:AdditionalJobInfoViewNewVIF/> + </DataTemplate> + + <DataTemplate DataType="{x:Type common:AdditionalJobInfoViewModelStageInput}"> + <additionaljobInfoViews:AdditionalJobInfoStageInput/> + </DataTemplate> + + </ResourceDictionary> \ No newline at end of file diff --git a/VECTO3GUI2020/Util/XML/Implementation/ComponentWriter/XMLVehicleWriter.cs b/VECTO3GUI2020/Util/XML/Implementation/ComponentWriter/XMLVehicleWriter.cs index 9be3eb5d59e8b0f9ef47495a083cd02b083c5300..2b18d352282c7a928c9ee52f1d50a64d1dad6534 100644 --- a/VECTO3GUI2020/Util/XML/Implementation/ComponentWriter/XMLVehicleWriter.cs +++ b/VECTO3GUI2020/Util/XML/Implementation/ComponentWriter/XMLVehicleWriter.cs @@ -1,24 +1,21 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Xml.Linq; using Castle.Core.Internal; -using TUGraz.IVT.VectoXML.Writer; using TUGraz.VectoCommon.BusAuxiliaries; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Resources; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider; -using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Interfaces; using VECTO3GUI2020.Helper; using VECTO3GUI2020.Util.XML.Interfaces; using VECTO3GUI2020.ViewModel.Implementation.JobEdit.Vehicle; using VECTO3GUI2020.ViewModel.Interfaces.JobEdit.Vehicle; using VECTO3GUI2020.ViewModel.MultiStage.Implementation; -namespace VECTO3GUI2020.Util.XML.Implementation +namespace VECTO3GUI2020.Util.XML.Implementation.ComponentWriter { public abstract class XMLVehicleWriter : IXMLVehicleWriter { @@ -51,7 +48,6 @@ namespace VECTO3GUI2020.Util.XML.Implementation { if (_Xelement == null) { Initialize(); - CreateElements(); } return _Xelement; @@ -190,14 +186,16 @@ namespace VECTO3GUI2020.Util.XML.Implementation public class XMLVehicleWriter_ExcemptedVehicle_v2_2 { } + public class XMLVehicleWriter_v2_8 : XMLVehicleWriter { + private readonly bool _exempted; public static readonly string[] SUPPORTEDVERSIONS = { - typeof(DeclarationInterimStageBusVehicleViewModel_v2_8).ToString() + typeof(InterimStageBusVehicleViewModel_v2_8).ToString() }; public XMLVehicleWriter_v2_8(IVehicleDeclarationInputData inputData, IXMLWriterFactory xmlWriterFactory) : base(inputData, xmlWriterFactory) { - + _exempted = inputData.ExemptedVehicle; } @@ -209,14 +207,21 @@ namespace VECTO3GUI2020.Util.XML.Implementation _Xelement = new XElement(XMLNamespaces.V20 + XMLNames.Component_Vehicle); - _Xelement.Add(new XAttribute(XMLNames.Component_ID_Attr, "TODO_ADDIDENTIFIER")); - _Xelement.Add(new XAttribute(XMLNamespaces.Xsi + XMLNames.Attr_Type, "InterimStageInputType")); + _Xelement.Add(new XAttribute(XMLNames.Component_ID_Attr, _inputData.Identifier ?? ("VEH-" + Guid.NewGuid().ToString("n").Substring(0, 20)))); + if (_exempted) { + _Xelement.Add(new XAttribute(XMLNamespaces.Xsi + XMLNames.Attr_Type, "ExemptedInterimStageInputType")); + } else { + _Xelement.Add(new XAttribute(XMLNamespaces.Xsi + XMLNames.Attr_Type, "InterimStageInputType")); + } + } protected override void CreateElements() { - - + if (_exempted) { + CreateExemptedElements(); + return; + } _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Component_Manufacturer, _inputData.Manufacturer)); _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Component_ManufacturerAddress, _inputData.ManufacturerAddress)); @@ -226,14 +231,10 @@ namespace VECTO3GUI2020.Util.XML.Implementation _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Component_Model, _inputData.Model)); _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_LegislativeCategory, _inputData.LegislativeClass.ToXMLFormat())); - - - _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_CorrectedActualMass, _inputData.CurbMassChassis?.ToXMLFormat(0))); _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Vehicle_TPMLM, _inputData.GrossVehicleMassRating?.ToXMLFormat(0))); - _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_AirdragModifiedMultistage, _inputData.AirdragModifiedMultistage)); _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Vehicle_NgTankSystem, _inputData.TankSystem)); _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Vehicle_RegisteredClass, _inputData.RegisteredClass.ToXMLFormat())); @@ -246,7 +247,6 @@ namespace VECTO3GUI2020.Util.XML.Implementation _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_LowEntry, _inputData.LowEntry)); - _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_HeighIntegratedBody, _inputData.Height?.ConvertToMilliMeter())); _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_VehicleLength, _inputData.Length?.ConvertToMilliMeter())); @@ -309,6 +309,38 @@ namespace VECTO3GUI2020.Util.XML.Implementation } + private void CreateExemptedElements() + { + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Component_Manufacturer, _inputData.Manufacturer)); + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Component_ManufacturerAddress, + _inputData.ManufacturerAddress)); + + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Vehicle_VIN, _inputData.VIN)); + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Component_Date, DateTime.Today.ToXmlFormat())); + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Component_Model, _inputData.Model)); + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_LegislativeCategory, _inputData.LegislativeClass.ToXMLFormat())); + + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_CorrectedActualMass, _inputData.CurbMassChassis?.ToXMLFormat(0))); + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Vehicle_TPMLM, + _inputData.GrossVehicleMassRating?.ToXMLFormat(0))); + + + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Vehicle_RegisteredClass, _inputData.RegisteredClass.ToXMLFormat())); + + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_NumberPassengerSeatsLowerDeck, _inputData.NumberPassengerSeatsLowerDeck)); + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_NumberPassengersStandingLowerDeck, _inputData.NumberPassengersStandingUpperDeck)); + + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_NumberPassengerSeatsUpperDeck, _inputData.NumberPassengerSeatsUpperDeck)); + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_NumberPassengersStandingUpperDeck, _inputData.NumberPassengersStandingUpperDeck)); + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Vehicle_BodyworkCode, _inputData.VehicleCode.ToXMLFormat())); + + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_LowEntry, _inputData.LowEntry)); + + _Xelement.Add(new XElement(_defaultNamespace + XMLNames.Bus_HeighIntegratedBody, _inputData.Height?.ConvertToMilliMeter())); + + _Xelement.DescendantsAndSelf().Where(e => e.Value.IsNullOrEmpty()).Remove(); + } + #endregion } diff --git a/VECTO3GUI2020/VECTO3GUI2020.csproj b/VECTO3GUI2020/VECTO3GUI2020.csproj index 979084874e8c8c1db94549333023f156c8af2f4b..10a1a9cc7a7e9fe089c01438b481f9208079e8b6 100644 --- a/VECTO3GUI2020/VECTO3GUI2020.csproj +++ b/VECTO3GUI2020/VECTO3GUI2020.csproj @@ -31,7 +31,7 @@ <BootstrapperEnabled>true</BootstrapperEnabled> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <PlatformTarget>AnyCPU</PlatformTarget> + <PlatformTarget>x64</PlatformTarget> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> @@ -41,7 +41,7 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <PlatformTarget>AnyCPU</PlatformTarget> + <PlatformTarget>x64</PlatformTarget> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <OutputPath>bin\Release\</OutputPath> @@ -77,6 +77,12 @@ <Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\packages\WindowsAPICodePack-Shell.1.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath> </Reference> + <Reference Include="Microsoft.Xaml.Behaviors, Version=1.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\Microsoft.Xaml.Behaviors.Wpf.1.1.31\lib\net45\Microsoft.Xaml.Behaviors.dll</HintPath> + </Reference> + <Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> + </Reference> <Reference Include="Ninject, Version=3.3.4.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL"> <HintPath>..\packages\Ninject.3.3.4\lib\net45\Ninject.dll</HintPath> </Reference> @@ -86,6 +92,9 @@ <Reference Include="Ninject.Extensions.Factory, Version=3.3.3.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL"> <HintPath>..\packages\Ninject.Extensions.Factory.3.3.3\lib\net45\Ninject.Extensions.Factory.dll</HintPath> </Reference> + <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> + <HintPath>..\packages\NLog.4.5.11\lib\net45\NLog.dll</HintPath> + </Reference> <Reference Include="PresentationFramework.Aero2" /> <Reference Include="System" /> <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> @@ -95,8 +104,10 @@ <HintPath>..\packages\System.ComponentModel.Annotations.5.0.0\lib\net461\System.ComponentModel.Annotations.dll</HintPath> </Reference> <Reference Include="System.ComponentModel.DataAnnotations" /> + <Reference Include="System.Configuration" /> <Reference Include="System.Data" /> <Reference Include="System.Drawing" /> + <Reference Include="System.IO.Compression" /> <Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath> </Reference> @@ -116,9 +127,12 @@ <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll</HintPath> </Reference> + <Reference Include="System.Runtime.Serialization" /> + <Reference Include="System.ServiceModel" /> <Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath> </Reference> + <Reference Include="System.Transactions" /> <Reference Include="System.Windows" /> <Reference Include="System.Windows.Controls.DataVisualization.Toolkit, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\packages\System.Windows.Controls.DataVisualization.Toolkit.4.0.0.0\lib\net40-Client\System.Windows.Controls.DataVisualization.Toolkit.dll</HintPath> @@ -140,6 +154,8 @@ <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> </ApplicationDefinition> + <Compile Include="Behaviours\AutoScrollDataGridBehaviour.cs" /> + <Compile Include="Behaviours\PopUpHorizontalAlignmentBehavior.cs" /> <Compile Include="Helper\ConvertedSIDummyCreator.cs" /> <Compile Include="Helper\Converter\AlwaysVisibleConverter.cs" /> <Compile Include="Helper\Converter\BoolToVisibilityConverter.cs" /> @@ -147,32 +163,49 @@ <Compile Include="Helper\Converter\InvertBoolConverter.cs" /> <Compile Include="Helper\Converter\JobTypeStringConverter.cs" /> <Compile Include="Helper\Converter\LabledTextBoxLabelConverter.cs" /> + <Compile Include="Helper\Converter\MultipleBoolConverter.cs" /> <Compile Include="Helper\Converter\MultistageParameterModeToVisibilityConverter.cs" /> <Compile Include="Helper\Converter\BoolToIntConverter.cs" /> <Compile Include="Helper\Converter\NullToUnsetValueConverter.cs" /> <Compile Include="Helper\Converter\NullToVisibilityConverter.cs" /> <Compile Include="Helper\Converter\LabledTextBoxConverter.cs" /> + <Compile Include="Helper\Converter\PropertyNameToLabelTextConverter.cs" /> <Compile Include="Helper\Converter\SIToUnitString.cs" /> <Compile Include="Helper\Converter\SIValueToStringConverter.cs" /> <Compile Include="Helper\Converter\VehicleCategoryToStringConverter.cs" /> <Compile Include="Helper\Converter\XToBoolConverter.cs" /> <Compile Include="Helper\DoubleValidation.cs" /> + <Compile Include="Helper\ExceptionExtension.cs" /> <Compile Include="Helper\Exceptions.cs" /> <Compile Include="Helper\EnumHelper.cs" /> - <Compile Include="Helper\IndexedStorage.cs" /> + <Compile Include="Helper\FileHelper.cs" /> <Compile Include="Helper\IWindowHelper.cs" /> <Compile Include="Helper\DialogHelper.cs" /> - <Compile Include="Helper\MultistageParameterDataTemplateSelector.cs" /> - <Compile Include="Helper\MultistageParameterViewModel.cs" /> - <Compile Include="Helper\NameOfMarkUpExtension.cs" /> + <Compile Include="Helper\ObservableDictionary.cs" /> + <Compile Include="Helper\ProcessHelper.cs" /> + <Compile Include="Helper\VisualTreeHelperExtensions.cs" /> + <Compile Include="Helper\TemplateSelector\MultistageParameterDataTemplateSelector.cs" /> + <Compile Include="Model\Multistage\JSONJob.cs" /> + <Compile Include="Properties\GUILabels.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>GUILabels.resx</DependentUpon> + </Compile> + <Compile Include="ViewModel\Implementation\Common\AdditionalJobInfoViewModel.cs" /> + <Compile Include="ViewModel\Implementation\Common\BackingStorage.cs" /> + <Compile Include="ViewModel\Implementation\Common\ObservableObject.cs" /> + <Compile Include="ViewModel\MultiStage\Implementation\MultistageParameterViewModel.cs" /> <Compile Include="Helper\NameResolver.cs" /> + <Compile Include="Helper\TemplateSelector\MultistageVehicleDataTemplateSelector.cs" /> <Compile Include="Helper\WindowHelper.cs" /> <Compile Include="Helper\XMLExtension.cs" /> <Compile Include="Helper\XmlHelper.cs" /> <Compile Include="Ninject\FactoryModule.cs" /> <Compile Include="Ninject\IMultistageDependencies.cs" /> + <Compile Include="Ninject\MultiStageViewModelFactory.cs" /> <Compile Include="Ninject\MultistageLazyDependencies.cs" /> <Compile Include="Ninject\MultistageModule.cs" /> + <Compile Include="Ninject\Vecto3GUI2020Module.cs" /> <Compile Include="Properties\Annotations.cs" /> <Compile Include="Properties\BusStrings.Designer.cs"> <AutoGen>True</AutoGen> @@ -190,6 +223,8 @@ <Compile Include="TestViewModel.cs" /> <Compile Include="Util\XML\Implementation\ComponentWriter\XMLBusAuxiliariesWriter.cs" /> <Compile Include="Util\XML\Implementation\ComponentWriter\XMLPTOWriter.cs" /> + <Compile Include="ViewModel\Implementation\AboutViewModel.cs" /> + <Compile Include="ViewModel\MultiStage\Implementation\CreateVifViewModel.cs" /> <Compile Include="ViewModel\Implementation\Document\DeclarationJobViewModel.cs" /> <Compile Include="ViewModel\Implementation\Document\DeclarationTrailerJobDocumentViewModel.cs" /> <Compile Include="Model\Interfaces\IAuxiliaryModelFactory.cs" /> @@ -302,9 +337,14 @@ <Compile Include="ViewModel\MultiStage\Implementation\MultistageAuxiliariesViewModel.cs" /> <Compile Include="ViewModel\MultiStage\Implementation\NewMultiStageJobViewModel.cs" /> <Compile Include="ViewModel\MultiStage\Implementation\MultistageJobViewModel_v0_1.cs" /> + <Compile Include="ViewModel\MultiStage\Implementation\StageInputViewModel.cs" /> + <Compile Include="ViewModel\MultiStage\Implementation\StageViewModelBase.cs" /> <Compile Include="ViewModel\MultiStage\Interfaces\IMultistageAirdragViewModel.cs" /> <Compile Include="ViewModel\MultiStage\Interfaces\IMultiStageViewModelFactory.cs" /> <Compile Include="ViewModel\Implementation\OutputViewModel.cs" /> + <Compile Include="Views\AboutView.xaml.cs"> + <DependentUpon>AboutView.xaml</DependentUpon> + </Compile> <Compile Include="Views\CustomControls\ComboParameter.xaml.cs"> <DependentUpon>ComboParameter.xaml</DependentUpon> </Compile> @@ -396,12 +436,27 @@ <Compile Include="Views\MessageView.xaml.cs"> <DependentUpon>MessageView.xaml</DependentUpon> </Compile> + <Compile Include="Views\Multistage\AdditionalJobInfoViews\AdditionalJobInfoStageInput.xaml.cs"> + <DependentUpon>AdditionalJobInfoStageInput.xaml</DependentUpon> + </Compile> + <Compile Include="Views\Multistage\AdditionalJobInfoViews\AdditionalJobInfoViewMultiStage.xaml.cs"> + <DependentUpon>AdditionalJobInfoViewMultiStage.xaml</DependentUpon> + </Compile> + <Compile Include="Views\Multistage\AdditionalJobInfoViews\AdditionalJobInfoViewNewVIF.xaml.cs"> + <DependentUpon>AdditionalJobInfoViewNewVIF.xaml</DependentUpon> + </Compile> <Compile Include="Views\Multistage\AirDragView_v2_8.xaml.cs"> <DependentUpon>AirDragView_v2_8.xaml</DependentUpon> </Compile> + <Compile Include="Views\Multistage\CreateVifView.xaml.cs"> + <DependentUpon>CreateVifView.xaml</DependentUpon> + </Compile> <Compile Include="Views\Multistage\CustomControls\FilePicker.xaml.cs"> <DependentUpon>FilePicker.xaml</DependentUpon> </Compile> + <Compile Include="Views\Multistage\CustomControls\InputStageView.xaml.cs"> + <DependentUpon>InputStageView.xaml</DependentUpon> + </Compile> <Compile Include="Views\Multistage\CustomControls\LabledTextBoxMultistage.xaml.cs"> <DependentUpon>LabledTextBoxMultistage.xaml</DependentUpon> </Compile> @@ -435,6 +490,9 @@ <Compile Include="Views\Multistage\VehicleView_v2_8.xaml.cs"> <DependentUpon>VehicleView_v2_8.xaml</DependentUpon> </Compile> + <Compile Include="Views\Multistage\VehicleView_v2_8_exempted.xaml.cs"> + <DependentUpon>VehicleView_v2_8_exempted.xaml</DependentUpon> + </Compile> <Compile Include="Views\OutputView.xaml.cs"> <DependentUpon>OutputView.xaml</DependentUpon> </Compile> @@ -444,7 +502,19 @@ <Compile Include="Views\XMLViewer.xaml.cs"> <DependentUpon>XMLViewer.xaml</DependentUpon> </Compile> - <Page Include="DataGridStyles.xaml"> + <Page Include="Resources\Icons\StatusInformationOutline_nohalo_16x.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + <Page Include="Resources\Sizes.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Resources\Styles\DataGridStyles.xaml"> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Resources\DataTemplateSelectors.xaml"> + <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> <Page Include="Resources\Icons\AddDocument_16x.xaml"> @@ -459,6 +529,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Resources\Icons\FolderClosed_16x.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> <Page Include="Resources\Icons\Trash_16x.xaml"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> @@ -498,6 +572,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Resources\Templates\ButtonTemplates.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Resources\Templates\ErrorTemplates.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -510,6 +588,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Views\AboutView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\CustomControls\ComboParameter.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -630,14 +712,34 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Views\Multistage\AdditionalJobInfoViews\AdditionalJobInfoStageInput.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Views\Multistage\AdditionalJobInfoViews\AdditionalJobInfoViewMultiStage.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Views\Multistage\AdditionalJobInfoViews\AdditionalJobInfoViewNewVIF.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\Multistage\AirDragView_v2_8.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Views\Multistage\CreateVifView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\Multistage\CustomControls\FilePicker.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Views\Multistage\CustomControls\InputStageView.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\Multistage\CustomControls\LabledTextBoxMultistage.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -682,6 +784,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Views\Multistage\VehicleView_v2_8_exempted.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\OutputView.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -713,6 +819,11 @@ <Generator>PublicResXFileCodeGenerator</Generator> <LastGenOutput>BusStrings.Designer.cs</LastGenOutput> </EmbeddedResource> + <EmbeddedResource Include="Properties\GUILabels.resx"> + <Generator>PublicResXFileCodeGenerator</Generator> + <LastGenOutput>GUILabels.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </EmbeddedResource> <EmbeddedResource Include="Properties\Strings.resx"> <Generator>PublicResXFileCodeGenerator</Generator> <LastGenOutput>Strings.Designer.cs</LastGenOutput> @@ -777,9 +888,7 @@ <ItemGroup> <Resource Include="Resources\Icons\folderpicker.ico" /> </ItemGroup> - <ItemGroup> - <Folder Include="Model\Multistage\" /> - </ItemGroup> + <ItemGroup /> <ItemGroup> <Resource Include="Resources\Icons\Trash_16x.ico" /> </ItemGroup> @@ -789,6 +898,12 @@ <LastGenOutput>Version.cs</LastGenOutput> </None> </ItemGroup> + <ItemGroup> + <Resource Include="Resources\Images\JRC-About.png" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\Images\VECTO-About.png" /> + </ItemGroup> <!-- ItemGroup> <Analyzer Include="..\packages\Microsoft.DependencyValidation.Analyzers.0.11.0\analyzers\dotnet\cs\Microsoft.DependencyValidation.Analyzers.resources.dll" /> </-ItemGroup --> diff --git a/VECTO3GUI2020/ViewModel/Implementation/AboutViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/AboutViewModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..de8eef21be44febe9c57829fd86e26d56a107d10 --- /dev/null +++ b/VECTO3GUI2020/ViewModel/Implementation/AboutViewModel.cs @@ -0,0 +1,72 @@ +using System.Diagnostics; +using System.Windows.Input; +using Microsoft.Toolkit.Mvvm.Input; +using VECTO3GUI2020.ViewModel.Implementation.Common; +using VECTO3GUI2020.ViewModel.Interfaces; + +namespace VECTO3GUI2020.ViewModel.Implementation +{ + public class AboutViewModel : ViewModelBase, IMainViewModel + { + #region Members + + private ICommand _euplLinkClickedCommand; + private ICommand _mailClickedCommand; + private ICommand _jrcPicClickedCommand; + + #endregion + + #region Properties + + public string EUPLLink { get; set; } + public string JRCMail { get; set; } + public string JRCPic { get; set; } + + #endregion + + public AboutViewModel() + { + EUPLLink = "https://joinup.ec.europa.eu/community/eupl/og_page/eupl"; + JRCMail = "mailto:jrc-vecto@ec.europa.eu"; + JRCPic = "http://ec.europa.eu/dgs/jrc/index.cfm"; + } + + #region Commands + + public ICommand EUPLLinkClickedCommand + { + get + { + return _euplLinkClickedCommand ?? (_euplLinkClickedCommand = new RelayCommand(DoLinkClickedCommand)); + } + } + + private void DoLinkClickedCommand() + { + Process.Start(EUPLLink); + } + + public ICommand MailClickedCommand + { + get { return _mailClickedCommand ?? (_mailClickedCommand = new RelayCommand(DoMailClickedCommand)); } + } + + private void DoMailClickedCommand() + { + Process.Start(JRCMail); + } + + public ICommand JrcPicClickedCommand + { + get { return _jrcPicClickedCommand ?? (_jrcPicClickedCommand = new RelayCommand(DoJrcPicClickedCommand)); } + } + + private void DoJrcPicClickedCommand() + { + Process.Start(JRCPic); + } + #endregion + + + } +} diff --git a/VECTO3GUI2020/ViewModel/Implementation/Common/AdditionalJobInfoViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/Common/AdditionalJobInfoViewModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..cea5bd15ba5e33849543f5a64d88d87ebca105e2 --- /dev/null +++ b/VECTO3GUI2020/ViewModel/Implementation/Common/AdditionalJobInfoViewModel.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Windows; +using System.Windows.Media.TextFormatting; +using TUGraz.VectoCommon.InputData; +using VECTO3GUI2020.ViewModel.Interfaces.Common; +using VECTO3GUI2020.ViewModel.MultiStage.Implementation; + +namespace VECTO3GUI2020.ViewModel.Implementation.Common +{ + public interface IAdditionalJobInfoViewModel + { + void SetParent(IViewModelBase parent); + } + public abstract class AdditionalJobInfoViewModelBase : ViewModelBase, IAdditionalJobInfoViewModel + { + + #region Implementation of IAdditionalJobInfoViewModel + + public string Information { get; } = "Nothing to show here"; + + public abstract void SetParent(IViewModelBase parent); + + + public AdditionalJobInfoViewModelBase() + { + SizeToContent = SizeToContent.WidthAndHeight; + MinHeight = 200; + MinWidth = 300; + } + #endregion + } + + public class AdditionalJobInfoViewModelMultiStage : AdditionalJobInfoViewModelBase + { + + private IMultiStageJobViewModel _parent; + private string _errorInfo; + + public AdditionalJobInfoViewModelMultiStage() + { + Title = "Multistage Job Info"; + } + + #region Overrides of AdditionalJobInfoViewModelBase + + public override void SetParent(IViewModelBase parent) + { + _parent = parent as IMultiStageJobViewModel; + if (parent == null) { + throw new ArgumentException( + "this class should only be used to extend the functionality of a class that implements the IMultistageJobViewModel interface"); + } + + //Title += $"- {_parent.DataSource.}" + if (_parent.CanBeSimulated) { + return; + } + + if(_parent.JobInputData?.ConsolidateManufacturingStage?.Vehicle?.VehicleDeclarationType != + VehicleDeclarationType.final && !_parent.Exempted) + { + ErrorInfo = "Job is not declared as \"final\""; + } + + + if (_parent.InvalidEntries != null && _parent.InvalidEntries.Count != 0) { + ErrorInfo = "This Job cannot be Simulated! The following inputs are missing or invalid"; + foreach (var parentInvalidEntry in _parent.InvalidEntries) + { + InvalidEntries.Add(parentInvalidEntry); + } + } + } + + public ObservableCollection<string> InvalidEntries { get; set; } = new ObservableCollection<string>(); + + public string ErrorInfo + { + get => _errorInfo; + set => SetProperty(ref _errorInfo, value); + } + + #endregion + } + + public class AdditionalJobInfoViewModelNewVif : AdditionalJobInfoViewModelBase + { + private CreateVifViewModel _parent; + public ObservableCollection<string> InvalidEntries { get; set; } = new ObservableCollection<string>(); + + #region Overrides of AdditionalJobInfoViewModelBase + + public override void SetParent(IViewModelBase parent) + { + _parent = parent as CreateVifViewModel; + (_parent as INotifyPropertyChanged).PropertyChanged += AdditionalJobInfoViewModelNewVif_PropertyChanged; + Debug.Assert(_parent != null); + } + + private void AdditionalJobInfoViewModelNewVif_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(_parent.CanBeSimulated)) { + + + + } + } + + + + #endregion + } + + public class AdditionalJobInfoViewModelStageInput : AdditionalJobInfoViewModelBase + { + private IStageViewModelBase stageViewModel; + #region Overrides of AdditionalJobInfoViewModelBase + + public override void SetParent(IViewModelBase parent) + { + stageViewModel = parent as IStageViewModelBase; + Debug.Assert(stageViewModel != null); + } + #endregion + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/ViewModel/Implementation/Common/BackingStorage.cs b/VECTO3GUI2020/ViewModel/Implementation/Common/BackingStorage.cs new file mode 100644 index 0000000000000000000000000000000000000000..45de76bb68f1528775f17a5666611bbe9382ee4b --- /dev/null +++ b/VECTO3GUI2020/ViewModel/Implementation/Common/BackingStorage.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using TUGraz.VectoCommon.Utils; + +namespace VECTO3GUI2020.ViewModel.Implementation.Common +{ + public class BackingStorage<T> : ObservableObject + where T : INotifyPropertyChanged + { + + delegate object GetterDelegate(); + private IReadOnlyCollection<string> _observedProperties; + private T _observedObject; + + private Dictionary<string, GetterDelegate> _getterDelegatesMap = new Dictionary<string, GetterDelegate>(); + private Dictionary<string, Type> _propertyTypesMap = new Dictionary<string, Type>(); + private IDictionary<string, IEqualityComparer> _equalityComparers = new Dictionary<string, IEqualityComparer>(); + + private IDictionary<string, object> _savedValues = null; + private IDictionary<string, object> _unsavedChanges = new Dictionary<string, object>(); + private IDictionary<string, object> _currentValues = new Dictionary<string, object>(); + + + public BackingStorage(T observedObject, params string[] observedProperties) + { + _observedProperties = new HashSet<string>(observedProperties); + _observedObject = observedObject; + observedObject.PropertyChanged += OnObservedPropertyChanged; + } + + public bool UnsavedChanges + { + get => (_savedValues == null) || (_unsavedChanges.Count != 0); + } + + private void ResetUnsavedChanges() + { + _unsavedChanges.Clear(); + OnPropertyChanged(nameof(UnsavedChanges)); + } + + public void SaveChanges() + { + _savedValues = new ReadOnlyDictionary<string, object>(new Dictionary<string, object>(_currentValues)); + ResetUnsavedChanges(); + } + + private void OnObservedPropertyChanged(object sender, PropertyChangedEventArgs e) + { + var propertyName = e.PropertyName; + if (!_observedProperties.Contains(propertyName)) { + return; + } + + if (!_getterDelegatesMap.ContainsKey(propertyName)) { + StorePropertyInfo(propertyName); + } + + UpdateValue(propertyName); + } + + private void UpdateValue(string propertyName) + { + + var newValue = _getterDelegatesMap[propertyName](); + _currentValues[propertyName] = newValue; + if (ValueHasChanged(newValue, propertyName)) { + _unsavedChanges[propertyName] = newValue; + } else { + _unsavedChanges.Remove(propertyName); + } + OnPropertyChanged(nameof(UnsavedChanges)); + } + + private bool ValueHasChanged(object newValue, string propertyName) + { + if (_savedValues == null + || !_savedValues.ContainsKey(propertyName)) { + return true; + } + + var savedValue = _savedValues[propertyName]; + + if (_equalityComparers.ContainsKey(propertyName)) { + var equalityComparer = _equalityComparers[propertyName]; + return !equalityComparer.Equals(newValue, savedValue); + } else { + return newValue == savedValue; + } + } + + private void StorePropertyInfo(string propertyName) + { + var propInfo = _observedObject.GetType().GetProperty(propertyName); + + + var propertyType = propInfo.PropertyType; + _propertyTypesMap[propertyName] = propInfo.PropertyType; + + try { + _equalityComparers[propertyName] = CreateEqualityComparer(propertyType); + } catch (Exception ex) { + // TODO; + } + + + + var getMethod = propInfo.GetGetMethod(); + var getterDelegate = (GetterDelegate)getMethod.CreateDelegate(typeof(GetterDelegate), _observedObject); + _getterDelegatesMap[propertyName] = getterDelegate; + + + } + + private static IEqualityComparer CreateEqualityComparer(Type type) + { + + Type myGeneric = typeof(EqualityComparer<>); + Type constructedClass = myGeneric.MakeGenericType(type); + return (IEqualityComparer)constructedClass + .GetProperty(nameof(EqualityComparer<T>.Default), BindingFlags.Static | BindingFlags.Public) + .GetValue(null); + + } + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/ViewModel/Implementation/Common/ObservableObject.cs b/VECTO3GUI2020/ViewModel/Implementation/Common/ObservableObject.cs new file mode 100644 index 0000000000000000000000000000000000000000..94747b95114529c6de79de306c78f585f8de0fea --- /dev/null +++ b/VECTO3GUI2020/ViewModel/Implementation/Common/ObservableObject.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace VECTO3GUI2020.ViewModel.Implementation.Common +{ + public class ObservableObject : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + /// <summary> + /// Needs to be called when a Property is changed + /// </summary> + /// + /// <param name="name">Is automatically set to CallerMemberName</param> + protected void OnPropertyChanged([CallerMemberName] string name = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); + } + + protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null) + { + bool propertyChanged = false; + + if (!EqualityComparer<T>.Default.Equals(field, value)) + { + field = value; + OnPropertyChanged(propertyName); + propertyChanged = true; + } + return propertyChanged; + } + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/ViewModel/Implementation/Common/ViewModelBase.cs b/VECTO3GUI2020/ViewModel/Implementation/Common/ViewModelBase.cs index 876ef38084047d02775fd175a3c4f5df826c610d..3f65bb37e9544f510e25011f601b895a4b292ca5 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/Common/ViewModelBase.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/Common/ViewModelBase.cs @@ -1,47 +1,86 @@ -using System.Collections.Generic; -using System.ComponentModel; -using System.Runtime.CompilerServices; -using System.Windows; +using System.Windows; +using System.Windows.Input; +using Microsoft.Toolkit.Mvvm.Input; +using Ninject; using VECTO3GUI2020.Helper; +using VECTO3GUI2020.Properties; using VECTO3GUI2020.ViewModel.Interfaces.Common; namespace VECTO3GUI2020.ViewModel.Implementation.Common { - /// <summary> + /// <summary> /// Base Implementation of INotifyPropertyChanged /// https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-property-change-notification /// </summary> /// - public class ViewModelBase : INotifyPropertyChanged, IViewModelBase + public class ViewModelBase : ObservableObject, IViewModelBase { private string _error; - public event PropertyChangedEventHandler PropertyChanged; - /// <summary> - /// Needs to be called when a Property is changed - /// </summary> - /// - /// <param name="name">Is automatically set to CallerMemberName</param> - protected void OnPropertyChanged([CallerMemberName] string name = "") - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); - } - - - //borrowed from Franz Kober - protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null) - { - bool propertyChanged = false; - - if (!EqualityComparer<T>.Default.Equals(field, value)) - { - field = value; - OnPropertyChanged(propertyName); - propertyChanged = true; - } - return propertyChanged; - } - - public virtual string Title { get; set; } = "No Title Set"; + + #region Size And Window position + private double? _width = 800; + private double? _height = 600; + public double? Width + { + get => _width; + set => SetProperty(ref _width, value); + } + public double? Height + { + get => _height; + set => SetProperty(ref _height, value); + } + + private double? _minHeight = null; + + public double? MinHeight + { + get => _minHeight; + set => SetProperty(ref _minHeight, value); + } + + private double? _minWidth = null; + + public double? MinWidth + { + get => _minWidth; + set => SetProperty(ref _minWidth, value); + } + + public SizeToContent _sizeToContent = SizeToContent.Manual; + public SizeToContent SizeToContent + { + get => _sizeToContent; + set => _sizeToContent = value; + } + #endregion + + + //borrowed from Franz Kober + + private string _title = GUILabels.DefaultTitle; + public virtual string Title + { + get => _title; + set => SetProperty(ref _title, value); + } + + [Inject] + public IDialogHelper DialogHelper { get; set; } + + +#region Commands + protected bool AskForConfirmationOnClose { get; set; } = false; + private ICommand _closeWindowCommand; + public ICommand CloseWindowCommand + { + get + { + return _closeWindowCommand ?? new RelayCommand<Window>(window => CloseWindow(window, DialogHelper, AskForConfirmationOnClose), window => true); + } + } + + protected void CloseWindow(Window window, IDialogHelper dialogHelper, bool showDialog = true) { @@ -58,5 +97,6 @@ namespace VECTO3GUI2020.ViewModel.Implementation.Common window?.Close(); } } + #endregion } } diff --git a/VECTO3GUI2020/ViewModel/Implementation/Document/DeclarationJobViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/Document/DeclarationJobViewModel.cs index 7f3cc8db43acad0a5b3e2b4ecbe8edd1a12cfbbb..cd26f24a0a66345c6aa9842e12e3991dd8783a5c 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/Document/DeclarationJobViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/Document/DeclarationJobViewModel.cs @@ -28,16 +28,22 @@ namespace VECTO3GUI2020.ViewModel.Implementation.Document public bool Selected { - get => _selected; + get => _selected && CanBeSimulated; set => SetProperty(ref _selected, value); } - public bool CanBeEdited + public bool CanBeSimulated { get => false; set => throw new System.NotImplementedException(); } + public IAdditionalJobInfoViewModel AdditionalJobInfoVm + { + get => throw new System.NotImplementedException(); + set => throw new System.NotImplementedException(); + } + #endregion #region Members diff --git a/VECTO3GUI2020/ViewModel/Implementation/Document/DeclarationTrailerJobDocumentViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/Document/DeclarationTrailerJobDocumentViewModel.cs index 9362ab868a256c06784589a8304023be9c092de4..d684390880cf1599306637018dde7daa779fdf75 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/Document/DeclarationTrailerJobDocumentViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/Document/DeclarationTrailerJobDocumentViewModel.cs @@ -1,6 +1,7 @@ using TUGraz.VectoCommon.InputData; using TUGraz.VectoCore.InputData.FileIO.XML; using TUGraz.VectoCore.Utils; +using VECTO3GUI2020.ViewModel.Implementation.Common; using VECTO3GUI2020.ViewModel.Interfaces; using VECTO3GUI2020.ViewModel.Interfaces.Document; using VECTO3GUI2020.ViewModel.Interfaces.JobEdit; @@ -26,9 +27,15 @@ namespace VECTO3GUI2020.ViewModel.Implementation.Document set => throw new System.NotImplementedException(); } - public bool CanBeEdited + public bool CanBeSimulated { - get => false; + get => throw new System.NotImplementedException(); + set => throw new System.NotImplementedException(); + } + + public IAdditionalJobInfoViewModel AdditionalJobInfoVm + { + get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); } diff --git a/VECTO3GUI2020/ViewModel/Implementation/Document/SimulationOnlyDeclarationJob.cs b/VECTO3GUI2020/ViewModel/Implementation/Document/SimulationOnlyDeclarationJob.cs index 9c6a69dc8fb23d839e59699d46d28fac7a7b74a5..650a6755df28bc928c63e2fd9f03969da500dce9 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/Document/SimulationOnlyDeclarationJob.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/Document/SimulationOnlyDeclarationJob.cs @@ -1,4 +1,5 @@ -using System.Configuration; +using System; +using System.Configuration; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCore.Utils; using VECTO3GUI2020.ViewModel.Implementation.Common; @@ -38,14 +39,20 @@ namespace VECTO3GUI2020.ViewModel.Implementation.Document public bool Selected { - get => _selected; + get => _selected && CanBeSimulated; set => SetProperty(ref _selected, value); } - public bool CanBeEdited + public bool CanBeSimulated { - get => false; - set => throw new System.NotImplementedException(); + get => true; + set => throw new NotImplementedException(); + } + + public IAdditionalJobInfoViewModel AdditionalJobInfoVm + { + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } #endregion diff --git a/VECTO3GUI2020/ViewModel/Implementation/JobEdit/Vehicle/VehicleViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/JobEdit/Vehicle/VehicleViewModel.cs index 86dbd231f7e3dd335f799c6bd9ede924e857af08..9ffa326e265b11f4f4582c5fde25b96b7ff33559 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/JobEdit/Vehicle/VehicleViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/JobEdit/Vehicle/VehicleViewModel.cs @@ -179,8 +179,6 @@ namespace VECTO3GUI2020.ViewModel.Implementation.JobEdit.Vehicle set => throw new NotImplementedException(); } - public virtual string LegislativeCategory => throw new NotImplementedException(); - LegislativeClass? IVehicleDeclarationInputData.LegislativeClass { get; } public virtual LegislativeClass LegislativeClass @@ -282,6 +280,8 @@ namespace VECTO3GUI2020.ViewModel.Implementation.JobEdit.Vehicle set => throw new NotImplementedException(); } + public string ExemptedTechnology { get; } + RegistrationClass? IVehicleDeclarationInputData.RegisteredClass { get; } int? IVehicleDeclarationInputData.NumberPassengerSeatsUpperDeck { get; } int? IVehicleDeclarationInputData.NumberPassengerSeatsLowerDeck { get; } diff --git a/VECTO3GUI2020/ViewModel/Implementation/JobListViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/JobListViewModel.cs index f910a87d065547a9324f4620388b2695ddc2b74a..db0f9f8f17a3b7ab74cf1f70a2091f9bf7e41306 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/JobListViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/JobListViewModel.cs @@ -1,6 +1,4 @@ -using Microsoft.Win32; -using Ninject; -using System; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; @@ -11,32 +9,28 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Data; -using System.Windows.Forms; using System.Windows.Input; using System.Xml; using System.Xml.Linq; using Microsoft.Toolkit.Mvvm.Input; -using Microsoft.WindowsAPICodePack.Shell.Interop; -using Microsoft.WindowsAPICodePack.Shell.PropertySystem; +using Newtonsoft.Json; +using NLog; +using NLog.Targets; using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Resources; -using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore; using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.InputData.FileIO.JSON; using TUGraz.VectoCore.InputData.FileIO.XML; using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider; using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Interfaces; -using TUGraz.VectoCore.InputData.Impl; using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.OutputData; using TUGraz.VectoCore.OutputData.FileIO; using TUGraz.VectoCore.Utils; using VECTO3GUI2020.Annotations; using VECTO3GUI2020.Helper; -using VECTO3GUI2020.Model.Interfaces; using VECTO3GUI2020.Properties; using VECTO3GUI2020.ViewModel.Implementation.Common; using VECTO3GUI2020.ViewModel.Implementation.Document; @@ -44,9 +38,7 @@ using VECTO3GUI2020.ViewModel.Interfaces; using VECTO3GUI2020.ViewModel.Interfaces.Document; using VECTO3GUI2020.ViewModel.MultiStage.Implementation; using VECTO3GUI2020.ViewModel.MultiStage.Interfaces; -using VECTO3GUI2020.Views; using IDocumentViewModel = VECTO3GUI2020.ViewModel.Interfaces.Document.IDocumentViewModel; -using RelayCommand = VECTO3GUI2020.Util.RelayCommand; using XmlDocumentType = TUGraz.VectoCore.Utils.XmlDocumentType; namespace VECTO3GUI2020.ViewModel.Implementation @@ -55,61 +47,63 @@ namespace VECTO3GUI2020.ViewModel.Implementation { #region Members and Properties private readonly Settings _settings = Settings.Default; + private bool _simulationLoggingEnabled = true; //Enabled and Disable NLOG Messages - private ICommand _addJobCommand; - private ICommand _editJobCommand; - private ICommand _removeJobCommand; - private ICommand _moveJobUpCommand; - private ICommand _moveJobDownCommand; - private ICommand _viewXMLCommand; - private bool _isLoading = false; - public bool IsLoading - { - get => _isLoading; - set => SetProperty(ref _isLoading, value); - } - - private BackgroundWorker fileReadingBackgroundWorker; + private BackgroundWorker fileReadingBackgroundWorker; private object _jobsLock = new Object(); private ObservableCollection<IDocumentViewModel> _jobs = new ObservableCollection<IDocumentViewModel>(); public ObservableCollection<IDocumentViewModel> Jobs{ get => _jobs; set => SetProperty(ref _jobs, value);} - private IDialogHelper _dialogHelper; + public IDocumentViewModel SelectedJob + { + get => _selectedJob; + set + { + if(SetProperty(ref _selectedJob, value)) { + RemoveJob.NotifyCanExecuteChanged(); + _openSourceFileCommand?.NotifyCanExecuteChanged(); + _showSourceFileInExplorerCommand?.NotifyCanExecuteChanged(); + }; + } + } + + + + private IDialogHelper _dialogHelper; private IWindowHelper _windowHelper; private IDocumentViewModelFactory _documentViewModelFactory; - private ICommand _newMultiStageFileCommand; + private IMultiStageViewModelFactory _multiStageViewModelFactory; - private IAsyncRelayCommand _addJobAsync; private readonly IXMLInputDataReader _inputDataReader; - private IAsyncRelayCommand _simulationCommand; - private readonly IOutputViewModel _outputViewModel; + private IOutputViewModel _outputViewModel; + - + private readonly string StoredJobsFileName = "storedJobs.json"; + #endregion + - public JobListViewModel() + private JobListViewModel() { BindingOperations.EnableCollectionSynchronization(Jobs, _jobsLock); - InitFileBackGroundWorker(); - - - } + } public JobListViewModel(IDocumentViewModelFactory documentViewModelFactory, IXMLInputDataReader inputDataReader, IDialogHelper dialogHelper, IWindowHelper windowHelper, - IMultiStageViewModelFactory multiStageViewModelFactory, IOutputViewModel outputViewModel) : this() + IMultiStageViewModelFactory multiStageViewModelFactory, + IOutputViewModel outputViewModel) : this() { _documentViewModelFactory = documentViewModelFactory; _dialogHelper = dialogHelper; @@ -117,27 +111,221 @@ namespace VECTO3GUI2020.ViewModel.Implementation _inputDataReader = inputDataReader; _multiStageViewModelFactory = multiStageViewModelFactory; _outputViewModel = outputViewModel; + + _outputMessage = new Progress<MessageEntry>((message) => { + _outputViewModel.AddMessage(message); + }); + _progress = new Progress<int>((i) => { + _outputViewModel.Progress = i; + }); + _status = new Progress<string>((msg) => { + _outputViewModel.StatusMessage = msg; + }); + + + //configure Nlog + var target = new MethodCallTarget("VectoGuiTarget", (evtInfo, obj) => LogMethod(evtInfo, obj)); + NLog.Config.SimpleConfigurator.ConfigureForTargetLogging(target); + + + if(System.Windows.Application.Current != null){ + System.Windows.Application.Current.Exit += new ExitEventHandler(this.OnApplicationExit); + LoadFiles(); + } } + private void LogMethod(LogEventInfo evtInfo, object[] objects) + { + if (!SimulationRunning || !_simulationLoggingEnabled) + { + return; + } + if (evtInfo.Level == LogLevel.Error || evtInfo.Level == LogLevel.Warn || evtInfo.Level == LogLevel.Fatal) + _outputMessage.Report(new MessageEntry() + { + Type = evtInfo.Level == LogLevel.Warn ? MessageType.WarningMessage : MessageType.ErrorMessage, + Message = evtInfo.FormattedMessage, + Source = evtInfo.CallerMemberName, + }); + } + - private void InitFileBackGroundWorker() - { - fileReadingBackgroundWorker = new BackgroundWorker - { - WorkerReportsProgress = true - }; - fileReadingBackgroundWorker.DoWork += fileworker_DoWork; - fileReadingBackgroundWorker.ProgressChanged += fileworker_ProgressChanged; - fileReadingBackgroundWorker.RunWorkerCompleted += fileworker_RunWorkerCompleted; - } - private void fileworker_ProgressChanged(object sender, ProgressChangedEventArgs e) + #region JobList + #region Store and Restore JobList + private void LoadFiles() { - Debug.WriteLine(e.ProgressPercentage); + var filesToRead = ReadFileNamesFromFile(); + if (filesToRead != null) + { + foreach (var fileName in filesToRead) + { + Task.Run(() => AddJobAsync(fileName)); + } + } } - private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + + private void OnApplicationExit(object sender, EventArgs e) + { + SaveFileNamesToFile(); + } + + + private string[] ReadFileNamesFromFile() + { + try { + var filesJson = File.ReadAllText(StoredJobsFileName); + IList<string> filesToRead = JsonConvert.DeserializeObject<List<string>>(filesJson); + return filesToRead.ToArray(); + } catch (Exception e) { + Debug.WriteLine(e.Message); + } + + return null; + } + + private void SaveFileNamesToFile() + { + var filesToStore = Jobs.Where(job => job.DataSource?.SourceFile != null).Select(job => job.DataSource.SourceFile).ToList(); + string jsonString = JsonConvert.SerializeObject(filesToStore); + Debug.WriteLine(jsonString); + File.WriteAllText(StoredJobsFileName, jsonString); + } + #endregion + + public void AddJob(IDocumentViewModel jobToAdd) + { + lock (_jobsLock) { + _jobs.Add(jobToAdd); + } + } + + + public async Task<IDocumentViewModel> AddJobExecuteAsync() + { + var fileName = _dialogHelper.OpenXMLFileDialog(); + if (fileName != null) + { + return await AddJobAsync(fileName); + } + + return null; + + } + + public async Task<IDocumentViewModel> AddJobAsync(string fileName, bool runSimulationAfterAdding = false) + { + if (fileName != null) + { + try + { + var result = await LoadFileAsync(fileName); + lock (_jobsLock) + { + Jobs.Add(result); + } + if (runSimulationAfterAdding) { + if (result.CanBeSimulated) { + await RunSimulationExecute(result); + } + } + + return result; + } + catch (Exception e) + { + var errorString = ""; + errorString = $"{fileName}\n"; + errorString += e.Message; + _dialogHelper.ShowMessageBox(errorString, "Error", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + + + return null; + } + + private Task<IDocumentViewModel> LoadFileAsync([NotNull] string fileName) + { + var extension = Path.GetExtension(fileName); + switch (extension) { + case ".xml": + return LoadXMLFile(fileName); + case ".json": + return LoadJsonFile(fileName); + default: + throw new VectoException($"{extension} not supported!"); + } + + } + + private Task<IDocumentViewModel> LoadJsonFile([NotNull] string fileName) + { + IDocumentViewModel result = null; + try { + var inputData = JSONInputDataFactory.ReadJsonJob(fileName, true); + return Task.FromResult(_multiStageViewModelFactory.CreateDocumentViewModel(inputData)); + } catch (Exception ex) { + return Task.FromException<IDocumentViewModel>(ex); + //_dialogHelper.ShowErrorMessage(ex.Message)); + } + } + + private Task<IDocumentViewModel> LoadXMLFile([NotNull] string fileName) + { + var xElement = new System.Xml.XmlDocument(); + xElement.Load(fileName); + + var documentType = XMLHelper.GetDocumentType(xElement?.DocumentElement?.LocalName); + if (documentType == XmlDocumentType.MultistageOutputData) + { + var inputDataProvider = _inputDataReader.Create(fileName) as IMultistageBusInputDataProvider; + return Task.FromResult(_multiStageViewModelFactory.GetMultiStageJobViewModel(inputDataProvider) as IDocumentViewModel); + } + else if (documentType == XmlDocumentType.DeclarationJobData) + { + //Remove + var inputDataProvider = _inputDataReader.CreateDeclaration(fileName); + IDocumentViewModel result; + try + { + result = _multiStageViewModelFactory.CreateDocumentViewModel(inputDataProvider); + } + catch (Exception ex) + { + Debug.WriteLine(ex.GetInnerExceptionMessages()); + result = new SimulationOnlyDeclarationJob(inputDataProvider.DataSource, inputDataProvider.JobInputData.JobName, XmlDocumentType.DeclarationJobData) as IDocumentViewModel; + } + return Task.FromResult(result); + } + else { + return Task.FromException<IDocumentViewModel>( + new VectoXMLException($"{documentType.ToString()} not supported")); + //throw new VectoXMLException($"{documentType.ToString()} not supported"); + } + + return null; + + + + } + + #endregion + + private bool _newFilePopUpIsOpen = false; + public bool NewFilePopUpIsOpen + { + get => _newFilePopUpIsOpen; + set => SetProperty(ref _newFilePopUpIsOpen, value); + } + + + + + #region Simulation + private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); private bool _simulationRunning = false; public bool SimulationRunning @@ -146,47 +334,77 @@ namespace VECTO3GUI2020.ViewModel.Implementation set { SetProperty(ref _simulationRunning, value); - OnPropertyChanged(nameof(SimulationCommand)); - OnPropertyChanged(nameof(CancelSimulation)); + SimulationCommand?.NotifyCanExecuteChanged(); + + (_cancelSimulationCommand as RelayCommand)?.NotifyCanExecuteChanged(); } } private ICommand _cancelSimulationCommand; + private IProgress<MessageEntry> _outputMessage; + private IProgress<int> _progress; + private IProgress<string> _status; + - private async Task RunSimulationExecute() + public async Task RunSimulationExecute(IDocumentViewModel jobToSimulate = null) { - cancellationTokenSource = new CancellationTokenSource(); + if (SimulationRunning) { + return; + } SimulationRunning = true; - await Task.Run(() => RunSimulationAsync(cancellationTokenSource.Token, - new Progress<MessageEntry>((message) => { _outputViewModel.AddMessage(message); }), - new Progress<int>((i) => _outputViewModel.Progress = i), - new Progress<string>((msg) => _outputViewModel.StatusMessage = msg))); - SimulationRunning = false; - _outputViewModel.Progress = 0; - cancellationTokenSource.Dispose(); - } + try { + await Task.Run(() => RunSimulationAsync(_cancellationTokenSource.Token, + outputMessages: _outputMessage, + progress: _progress, + status: _status, + jobToSimulate: jobToSimulate)); + } catch (Exception ex) { + _outputViewModel.AddMessage(new MessageEntry() { + Type = MessageType.ErrorMessage, + Message = ex.Message + }); + } finally { + _cancellationTokenSource = new CancellationTokenSource(); + _simulationLoggingEnabled = true; + SimulationRunning = false; + _outputViewModel.Progress = 0; + } + } - private async Task RunSimulationAsync(CancellationToken ct, IProgress<MessageEntry> outputMessages, - IProgress<int> progress, IProgress<string> status) + private async Task RunSimulationAsync(CancellationToken ct, + IProgress<MessageEntry> outputMessages, + IProgress<int> progress, + IProgress<string> status, + IDocumentViewModel jobToSimulate = null) { progress.Report(0); status.Report("starting..."); IDocumentViewModel[] jobs; - lock (_jobsLock) { - jobs = Jobs.Where(x => x.Selected).ToArray(); - if (jobs.Length == 0) { - outputMessages.Report(new MessageEntry() { - Message = "No Jobs Selected", - Time = DateTime.Now, - Type = MessageType.InfoMessage, - }); - status.Report("No jobs selected"); - return; + if (jobToSimulate == null) { + lock (_jobsLock) + { + jobs = Jobs.Where(x => x.Selected).ToArray(); + if (jobs.Length == 0) + { + outputMessages.Report(new MessageEntry() + { + Message = "No Jobs Selected", + Time = DateTime.Now, + Type = MessageType.InfoMessage, + }); + status.Report("No jobs selected"); + return; + } } + } else { + jobs = new IDocumentViewModel[] { + jobToSimulate + }; } + var sumFileWriter = new FileOutputWriter(GetOutputDirectory(Jobs.First(x => x.Selected).DataSource.SourceFile)); var sumContainer = new SummaryDataContainer(sumFileWriter); var jobContainer = new JobContainer(sumContainer); @@ -292,7 +510,7 @@ namespace VECTO3GUI2020.ViewModel.Implementation outputMessages.Report(new MessageEntry() { Message = "Simulation canceled", - Type = MessageType.StatusMessage, + Type = MessageType.InfoMessage, }); return; } @@ -356,11 +574,18 @@ namespace VECTO3GUI2020.ViewModel.Implementation { if (ct.IsCancellationRequested) { - jobContainer.Cancel(); - outputMessages.Report(new MessageEntry() { + try { + await Task.Run(() => jobContainer.Cancel()); + } catch (Exception e) { + Debug.WriteLine(e.Message); + } + + outputMessages.Report(new MessageEntry() + { Message = "Simulation canceled", - Type = MessageType.StatusMessage, + Type = MessageType.InfoMessage, }); + return; } @@ -377,15 +602,15 @@ namespace VECTO3GUI2020.ViewModel.Implementation string.Join(", ", jobProgress.Select(x => string.Format("{0,4:P}", x.Value.Progress))))); var justFinished = jobProgress.Where(x => x.Value.Done & !finishedRuns.Contains(x.Key)) .ToDictionary(x => x.Key, x => x.Value); - //PrintRuns(justFinished, fileWriters); + PrintRuns(justFinished, fileWriters, outputMessages); finishedRuns.AddRange(justFinished.Select(x => x.Key)); - await Task.Delay(100, ct); + await Task.Delay(100); } start.Stop(); var remainingRuns = jobContainer.GetProgress().Where(x => x.Value.Done && !finishedRuns.Contains(x.Key)) .ToDictionary(x => x.Key, x => x.Value); - //PrintRuns(remainingRuns, fileWriters); + PrintRuns(remainingRuns, fileWriters, outputMessages); finishedRuns.Clear(); fileWriters.Clear(); @@ -425,7 +650,7 @@ namespace VECTO3GUI2020.ViewModel.Implementation Type = MessageType.StatusMessage, Message = string.Format( "{2} for '{0}' written to {1}", Path.GetFileName(jobEntry.DataSource.SourceFile), entry.Key, entry.Value), - //Link = "<XML>" + entry.Key + Link = entry.Key }); } } @@ -437,7 +662,7 @@ namespace VECTO3GUI2020.ViewModel.Implementation { Type = MessageType.StatusMessage, Message = string.Format("Sum file written to {0}", sumFileWriter.SumFileName), - //Link = "<CSV>" + sumFileWriter.SumFileName + Link = sumFileWriter.SumFileName, }); } @@ -457,34 +682,36 @@ namespace VECTO3GUI2020.ViewModel.Implementation .GetModDataFileName(p.Value.RunName, p.Value.CycleName, p.Value.RunSuffix); var runName = string.Format("{0} {1} {2}", p.Value.RunName, p.Value.CycleName, p.Value.RunSuffix); - // if (p.Value.Error != null) - // { - // SimulationWorker.ReportProgress(0, new VectoSimulationProgress() - // { - // Type = VectoSimulationProgress.MsgType.StatusMessage, - // Message = string.Format("Finished Run {0} with ERROR: {1}", runName, - // p.Value.Error.Message), - // Link = "<CSV>" + modFilename - // }); - // } - // else - // { - // SimulationWorker.ReportProgress(0, new VectoSimulationProgress() - // { - // Type = VectoSimulationProgress.MsgType.StatusMessage, - // Message = string.Format("Finished run {0} successfully.", runName) - // }); - // } - // if (File.Exists(modFilename)) - // { - // SimulationWorker.ReportProgress(0, new VectoSimulationProgress() - // { - // Type = VectoSimulationProgress.MsgType.StatusMessage, - // Message = string.Format("Run {0}: Modal results written to {1}", runName, modFilename), - // Link = "<CSV>" + modFilename - // }); - // } - } + if (p.Value.Error != null) + { + outputMessages.Report(new MessageEntry() + { + Type = MessageType.StatusMessage, + Message = string.Format("Finished Run {0} with ERROR: {1}", runName, + p.Value.Error.Message), + Link = modFilename + //Link = "<CSV>" + modFilename + }); + } + else + { + outputMessages.Report(new MessageEntry() + { + Type = MessageType.StatusMessage, + Message = string.Format("Finished run {0} successfully.", runName) + }); + } + if (File.Exists(modFilename)) + { + outputMessages.Report(new MessageEntry() + { + Type = MessageType.StatusMessage, + Message = string.Format("Run {0}: Modal results written to {1}", runName, modFilename), + Link = modFilename, + //Link = "<CSV>" + modFilename + }); + } + } } @@ -507,157 +734,164 @@ namespace VECTO3GUI2020.ViewModel.Implementation return outFile; } - + #endregion #region Commands + private ICommand _editJobCommand; + private IAsyncRelayCommand _removeJobCommand; + private ICommand _moveJobUpCommand; + private ICommand _moveJobDownCommand; + private ICommand _viewXMLCommand; + private IDocumentViewModel _selectedJob; + private IAsyncRelayCommand _addJobAsync; + private IAsyncRelayCommand<IDocumentViewModel> _simulationCommand; + private IRelayCommand<bool> _newVifCommand; + private ICommand _newMultiStageFileCommand; + private ICommand _openNewFilePopUpCommand; + private ICommand _newCompletedInputCommand; + private ICommand _newExemptedCompletedInputCommand; + private ICommand _openAdditionalJobInformationCommand; + private IRelayCommand _openSourceFileCommand; + private IRelayCommand _showSourceFileInExplorerCommand; + + + public ICommand OpenSourceFileCommand + { + get + { + return _openSourceFileCommand ?? (_openSourceFileCommand = + new RelayCommand(() => { ProcessHelper.OpenFile(_selectedJob?.DataSource?.SourceFile); }, + () => _selectedJob != null)); + } + } + + public ICommand ShowSourceFileCommand + { + get + { + return _showSourceFileInExplorerCommand ?? (_showSourceFileInExplorerCommand = + new RelayCommand(() => { ProcessHelper.OpenFolder(_selectedJob?.DataSource?.SourceFile); }, + () => _selectedJob != null)); + } + } + + + public ICommand OpenPopUpCommand + { + get => _openNewFilePopUpCommand ?? + (_openNewFilePopUpCommand = new RelayCommand(() => { + if (NewFilePopUpIsOpen == false) { + NewFilePopUpIsOpen = true; + } + + })); + } + + public ICommand CancelSimulation { get { - return _cancelSimulationCommand ?? new RelayCommand(() => { + return _cancelSimulationCommand ?? (_cancelSimulationCommand = new RelayCommand(() => { _outputViewModel.AddMessage(new MessageEntry() { Message="Canceling Simulation", - Type=MessageType.StatusMessage, + Type=MessageType.InfoMessage, }); - cancellationTokenSource.Cancel(); + _simulationLoggingEnabled = false; + _cancellationTokenSource.Cancel(); + + }, - () => SimulationRunning); + () => SimulationRunning)); } } - - public IAsyncRelayCommand SimulationCommand + public ICommand NewCompletedInputCommand { get { - return _simulationCommand ?? new AsyncRelayCommand(RunSimulationExecute, () => !SimulationRunning); + return _newCompletedInputCommand ?? (_newCompletedInputCommand = new RelayCommand(() => { + NewCompletedInputCommandExecute(false); + })); } } + private void NewCompletedInputCommandExecute(bool exempted) + { + var stageInputVm = _multiStageViewModelFactory.GetStageInputViewModel(exempted); + + AddJob(stageInputVm); + _windowHelper.ShowWindow(stageInputVm); + } - public ICommand NewManufacturingStageFile + public ICommand NewExemptedCompletedInputCommand { get { - return _newMultiStageFileCommand ?? new RelayCommand(NewManufacturingStageFileExecute, () => { return true; }); + return _newExemptedCompletedInputCommand ?? (_newExemptedCompletedInputCommand = new RelayCommand(() => { + NewCompletedInputCommandExecute(true); + })); } } - private void NewManufacturingStageFileExecute() + public IRelayCommand<bool> NewVifCommand { - _windowHelper.ShowWindow(_multiStageViewModelFactory.GetNewMultistageJobViewModel()); + get + { + return _newVifCommand ?? (_newVifCommand = new Microsoft.Toolkit.Mvvm.Input.RelayCommand<bool>((b) => { + var newVifViewModel = _multiStageViewModelFactory.GetCreateNewVifViewModel(b); + lock (_jobsLock) { + _jobs.Add(newVifViewModel); + } + _windowHelper.ShowWindow(newVifViewModel); + }, b => true)); + } } - public IAsyncRelayCommand AddJobAsyncCommand + public IAsyncRelayCommand<IDocumentViewModel> SimulationCommand { get { - return _addJobAsync ?? new AsyncRelayCommand(AddJobExecuteAsync - , () => true); + return _simulationCommand ?? (_simulationCommand = + new AsyncRelayCommand<IDocumentViewModel>(RunSimulationExecute, (d) => !SimulationRunning)); } } - private async Task<IDocumentViewModel> AddJobExecuteAsync() + public ICommand NewManufacturingStageFileCommand { - var fileName = _dialogHelper.OpenXMLFileDialog(); - if (fileName != null) { - return await AddJobAsync(fileName); - } - - return null; - + get + { + return _newMultiStageFileCommand ?? new RelayCommand(NewManufacturingStageFileExecute, () => { return true; }); + } } - public async Task<IDocumentViewModel> AddJobAsync(string fileName) + private void NewManufacturingStageFileExecute() { - if (fileName != null) { - try { - var result = await LoadFileAsync(fileName); - Jobs.Add(result); - return result; - } catch (Exception e) { - var errorString = ""; - errorString = $"{fileName}\n"; - errorString += e.Message; - _dialogHelper.ShowMessageBox(errorString, "Error", MessageBoxButton.OK, MessageBoxImage.Error); - } - } - - - return null; + _windowHelper.ShowWindow(_multiStageViewModelFactory.GetNewMultistageJobViewModel()); } - private Task<IDocumentViewModel> LoadFileAsync([NotNull] string fileName) + public IAsyncRelayCommand AddJobAsyncCommand { - var xElement = new System.Xml.XmlDocument(); - xElement.Load(fileName); - - var documentType = XMLHelper.GetDocumentType(xElement?.DocumentElement?.LocalName); - if (documentType == XmlDocumentType.MultistageOutputData) { - var inputDataProvider = _inputDataReader.Create(fileName) as IMultistageBusInputDataProvider; - return Task.FromResult(_multiStageViewModelFactory.GetMultiStageJobViewModel(inputDataProvider) as IDocumentViewModel); - } else if (documentType == XmlDocumentType.DeclarationJobData) { - //Remove - var inputDataProvider = _inputDataReader.CreateDeclaration(fileName); - var result = new SimulationOnlyDeclarationJob(inputDataProvider.DataSource, - inputDataProvider.JobInputData.JobName, XmlDocumentType.DeclarationJobData) as IDocumentViewModel; - return Task.FromResult(result); - - - }else { - throw new VectoXMLException($"{documentType.ToString()} not supported"); + get + { + return _addJobAsync ?? new AsyncRelayCommand(AddJobExecuteAsync + , () => true); } - - return null; } + - - public ICommand AddJob + public ICommand EditDocument { get - { - return _addJobCommand ?? new RelayCommand(AddJobExecute, () => { return true; }); - } - private set - { - _addJobCommand = value; - OnPropertyChanged(); - } - } - - - private void AddJobExecute() - { - IsLoading = true; - var filename = _dialogHelper.OpenXMLFileDialog(); - if (filename != null) - { - LoadJob(filename); + { + return _editJobCommand ?? (_editJobCommand = new Util.RelayCommand<IDocumentViewModel>(EditDocumentExecute, + (IDocumentViewModel jobentry) => { + var canExecute = jobentry != null && jobentry.EditViewModel != null; + return canExecute; + })); } - else - { - IsLoading = false; - } - } - - public void LoadJob([NotNull] string fileName) - { - fileReadingBackgroundWorker.RunWorkerAsync(fileName); - } - - - public ICommand EditJob - { - get - { - return _editJobCommand ?? new Util.RelayCommand<IJobViewModel>(EditJobExecute, - (IJobViewModel jobentry) => { - var canExecute = jobentry != null && jobentry.CanBeEdited; - return canExecute; - }); - } set { _editJobCommand = value; @@ -665,7 +899,7 @@ namespace VECTO3GUI2020.ViewModel.Implementation } } - private void EditJobExecute(IDocumentViewModel selectedJob) + private void EditDocumentExecute(IDocumentViewModel selectedJob) { if (selectedJob == null) { return; @@ -702,14 +936,14 @@ namespace VECTO3GUI2020.ViewModel.Implementation } - public ICommand RemoveJob + public IAsyncRelayCommand RemoveJob { get { - return _removeJobCommand ?? new Util.RelayCommand<IDocumentViewModel>(RemoveJobExecute, (IDocumentViewModel jobentry) => - { - return (jobentry != null); - }); + return _removeJobCommand ?? (_removeJobCommand = new AsyncRelayCommand<IDocumentViewModel>(RemoveJobExecute, + (IDocumentViewModel jobEntry) => { + return (SelectedJob != null); + })); } set { @@ -718,14 +952,28 @@ namespace VECTO3GUI2020.ViewModel.Implementation } } - private void RemoveJobExecute(IDocumentViewModel selectedDocument) - { - if (selectedDocument == null) return; + public void OnJobSelectionChanged() + { + RemoveJob.NotifyCanExecuteChanged(); + } + + private async Task RemoveJobExecute(IDocumentViewModel selectedDocument) + { + if (selectedDocument == null) { + return; + } - Jobs.Remove(selectedDocument); + await Task.Run(() => { + lock (_jobsLock) { + Jobs.Remove(selectedDocument); + } + }); + + OnPropertyChanged(); - } + + } public ICommand moveJobUp { @@ -770,7 +1018,24 @@ namespace VECTO3GUI2020.ViewModel.Implementation } - private void MoveJobDownExecute(IDocumentViewModel selectedJob) + public IOutputViewModel OutputViewModel + { + get => _outputViewModel; + set => SetProperty(ref _outputViewModel, value); + } + + public ICommand OpenAdditionalJobInformationCommand + { + get + { + return _openAdditionalJobInformationCommand ?? (_openAdditionalJobInformationCommand = new RelayCommand<IDocumentViewModel>( + (docVm) => { + _windowHelper.ShowWindow(docVm.AdditionalJobInfoVm); + })); + } + } + + private void MoveJobDownExecute(IDocumentViewModel selectedJob) { Debug.WriteLine("move down command"); @@ -782,69 +1047,5 @@ namespace VECTO3GUI2020.ViewModel.Implementation } #endregion Commands - - #region BackgroundworkerXMLreading - - void fileworker_DoWork(object sender, DoWorkEventArgs e) - { - string filename = e.Argument as string; - Debug.Assert(filename != null); - - try - { - var xElement = new System.Xml.XmlDocument(); - xElement.Load(filename); - - var documentType = XMLHelper.GetDocumentType(xElement?.DocumentElement?.LocalName); - if (documentType == null) - { - Debug.WriteLine("Unknown Document Type"); - e.Cancel = true; - return; - } - - - - - var result = _documentViewModelFactory.CreateDocumentViewModel((XmlDocumentType)documentType, filename); - e.Result = result; - } - catch (Exception) - { - e.Cancel = true; - throw; - } - } - - - void fileworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) - { - Debug.Assert(e.Result is IDocumentViewModel); - Jobs.Add(e.Result as IDocumentViewModel); - IsLoading = false; - } - - #endregion - } - - - public class VectoSimulationProgress - { - public enum MsgType - { - StatusMessage, - InfoMessage, - Progress, - LogError, - LogWarning, - - } - - public string Message { get; set; } - - public MsgType Type { get; set; } - - public string Link { get; set; } } - } diff --git a/VECTO3GUI2020/ViewModel/Implementation/MainWindowViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/MainWindowViewModel.cs index ddb2e680e424c12a871fd59f19b6ea9167b75478..4d7a411dbd0b014efe4dea171c22882c9fb09281 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/MainWindowViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/MainWindowViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using VECTO3GUI2020.ViewModel.Interfaces; using Ninject; using System.Diagnostics; @@ -13,35 +14,75 @@ namespace VECTO3GUI2020.ViewModel.Implementation { public class MainWindowViewModel : ViewModelBase, IMainWindowViewModel { - #region Member + #region Members private IJobListViewModel _jobListVm; private IMainViewModel _bottomView; - #endregion - - #region Commands - private ICommand _openSettings; + + private Dictionary<string, IMainViewModel> _viewModels = new Dictionary<string, IMainViewModel>(StringComparer.InvariantCultureIgnoreCase); + private readonly AboutViewModel _aboutViewModel; private IWindowHelper _windowHelper; private ISettingsViewModel _settingsViewModel; - - + private IMainViewModel _currentViewModelTop; #endregion - - public MainWindowViewModel(IWindowHelper windowHelper, ISettingsViewModel settingsViewModel, IJobListViewModel jobListViewModel, IOutputViewModel outputViewModel) + public MainWindowViewModel(IWindowHelper windowHelper, ISettingsViewModel settingsViewModel, IJobListViewModel jobListViewModel, IOutputViewModel outputViewModel, AboutViewModel aboutVm) { _windowHelper = windowHelper; _settingsViewModel = settingsViewModel; _jobListVm = jobListViewModel; + _aboutViewModel = aboutVm; + _currentViewModelTop = _jobListVm; _bottomView = outputViewModel; + //_bottomView = new TestViewModel(); + _viewModels.Add("Jobs", _jobListVm); + _viewModels.Add("Settings", _settingsViewModel); + _viewModels.Add("About", _aboutViewModel); } - public IMainViewModel CurrentViewModelTop - { - get { return _jobListVm; - } - set { throw new NotImplementedException(); } + #region Properties + public void SwitchTopViewModel(string key) + { + CurrentViewModel = _viewModels[key]; + } + + public bool JobsSelected + { + get + { + return CurrentViewModel == _jobListVm; + } + } + + public bool SettingsSelected + { + get + { + return CurrentViewModel == _settingsViewModel; + } + } + + public bool AboutSelected + { + get + { + return CurrentViewModel == _aboutViewModel; + } + } + + public IMainViewModel CurrentViewModel + { + get { + return _currentViewModelTop; + } + set { + if (SetProperty(ref _currentViewModelTop, value)) { + OnPropertyChanged(nameof(JobsSelected)); + OnPropertyChanged(nameof(SettingsSelected)); + OnPropertyChanged(nameof(AboutSelected)); + } + } } public IMainViewModel CurrentViewModelBottom @@ -50,10 +91,18 @@ namespace VECTO3GUI2020.ViewModel.Implementation set { _bottomView = value; } } + public IJobListViewModel JobListVm + { + get => _jobListVm; + set => SetProperty(ref _jobListVm, value); + } + #endregion + + #region Commands - #region CommandImplementations - #region CommandOpenSettings - public ICommand OpenSettings + private ICommand _openSettings; + private ICommand _switchTopView; + public ICommand OpenSettings { get{ return _openSettings ?? (ICommand)new RelayCommand(OpenSettingsExecute); @@ -69,35 +118,17 @@ namespace VECTO3GUI2020.ViewModel.Implementation _windowHelper.ShowWindow(_settingsViewModel); } - - #region newMultiStage - - public ICommand NewInterimFile => _jobListVm.NewManufacturingStageFile; - - + public ICommand SwitchTopView + { + get + { + return _switchTopView ?? (_switchTopView = new RelayCommand<string>(SwitchTopViewModel, (s) => true)); + } + } #endregion - #endregion - - - - - - - - - - - - - - - - - #endregion - - } + } } diff --git a/VECTO3GUI2020/ViewModel/Implementation/MessageEntry.cs b/VECTO3GUI2020/ViewModel/Implementation/MessageEntry.cs index d1bff4229030242c6a959b12fad118562ffb7422..f5602802670104739d6436c62ae955ee880fbaa3 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/MessageEntry.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/MessageEntry.cs @@ -31,7 +31,7 @@ namespace VECTO3GUI2020.ViewModel.Implementation public string Link { get { return _link; } - set {} + set { SetProperty(ref _link, value); } } public MessageType Type diff --git a/VECTO3GUI2020/ViewModel/Implementation/OutputViewModel.cs b/VECTO3GUI2020/ViewModel/Implementation/OutputViewModel.cs index 3e41e51fdd89f701162b0f9b997869f22b7ad463..3c0b356ea3fc699a732a35d41f195e3fd470b6da 100644 --- a/VECTO3GUI2020/ViewModel/Implementation/OutputViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Implementation/OutputViewModel.cs @@ -1,8 +1,15 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; using System.Windows.Data; +using System.Windows.Input; +using Microsoft.Toolkit.Mvvm.Input; using Microsoft.WindowsAPICodePack.Shell.Interop; +using VECTO3GUI2020.Helper; using VECTO3GUI2020.ViewModel.Implementation; using VECTO3GUI2020.ViewModel.Implementation.Common; using VECTO3GUI2020.ViewModel.Interfaces; @@ -13,22 +20,20 @@ namespace VECTO3GUI2020.ViewModel public class OutputViewModel : ViewModelBase, IOutputViewModel { + #region MembersAndProperties private object _messageLock = new Object(); private ObservableCollection<MessageEntry> _messages = new ObservableCollection<MessageEntry>(); private int _progress; private string _statusMessage; + private ICommand _openFolderCommand; + private ICommand _openFileCommand; public ObservableCollection<MessageEntry> Messages { get { return _messages; } } - public void AddMessage(MessageEntry messageEntry) - { - lock (_messageLock) { - Messages.Add(messageEntry); - } - } + public int Progress { @@ -43,12 +48,54 @@ namespace VECTO3GUI2020.ViewModel } + + #endregion + + public void AddMessage(MessageEntry messageEntry) + { + lock (_messageLock) + { + Messages.Add(messageEntry); + } + } + + public OutputViewModel() { BindingOperations.EnableCollectionSynchronization(Messages, _messageLock); } + + + #region Commands + + // ReSharper disable once UnusedMember.Global + public ICommand OpenFolderCommand => + _openFolderCommand ?? (_openFolderCommand = new RelayCommand<string>( + OpenFolderExecute)); + + // ReSharper disable once UnusedMember.Global + public ICommand OpenFileCommand => + _openFileCommand ?? (_openFileCommand = new RelayCommand<string>( + OpenFileExecute)); + + private void OpenFolderExecute(string path) + { + ProcessHelper.OpenFolder(path); + } + + private void OpenFileExecute(string path){ + if (path == null) { + return; + } + + ProcessHelper.OpenFile(path); + } + #endregion } + + + public interface IOutputViewModel : IMainViewModel { //ObservableCollection<MessageEntry> Messages { get; } diff --git a/VECTO3GUI2020/ViewModel/Interfaces/Common/IViewModelBase.cs b/VECTO3GUI2020/ViewModel/Interfaces/Common/IViewModelBase.cs index 39808350ec312e252e4fee1d1df3624f39f19ff1..407034e20c9334ae4d18c12e581382ccdf1cd28e 100644 --- a/VECTO3GUI2020/ViewModel/Interfaces/Common/IViewModelBase.cs +++ b/VECTO3GUI2020/ViewModel/Interfaces/Common/IViewModelBase.cs @@ -1,9 +1,16 @@ using System.ComponentModel; +using System.Windows; namespace VECTO3GUI2020.ViewModel.Interfaces.Common { public interface IViewModelBase : INotifyPropertyChanged { string Title { get; set; } + double? Width { get; set; } + double? Height { get; set; } + + double? MinHeight { get; set; } + double? MinWidth { get; set; } + SizeToContent SizeToContent { get; set; } } } \ No newline at end of file diff --git a/VECTO3GUI2020/ViewModel/Interfaces/Document/IDocumentViewModel.cs b/VECTO3GUI2020/ViewModel/Interfaces/Document/IDocumentViewModel.cs index 60b6f9edecc3c4896fe5312feb8b61675b6a5afb..cd12c7d033a295b2026e419f2a3283765df7905d 100644 --- a/VECTO3GUI2020/ViewModel/Interfaces/Document/IDocumentViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Interfaces/Document/IDocumentViewModel.cs @@ -1,5 +1,6 @@ using TUGraz.VectoCommon.InputData; using TUGraz.VectoCore.Utils; +using VECTO3GUI2020.ViewModel.Implementation.Common; using VECTO3GUI2020.ViewModel.Interfaces.JobEdit; namespace VECTO3GUI2020.ViewModel.Interfaces.Document @@ -9,10 +10,10 @@ namespace VECTO3GUI2020.ViewModel.Interfaces.Document string DocumentName { get; } XmlDocumentType DocumentType { get; } DataSource DataSource { get; } - - IEditViewModel EditViewModel { get; } + IEditViewModel EditViewModel { get; } bool Selected { get; set; } - bool CanBeEdited { get; set; } + bool CanBeSimulated { get; set; } + IAdditionalJobInfoViewModel AdditionalJobInfoVm { get; set; } } } diff --git a/VECTO3GUI2020/ViewModel/Interfaces/IJobListViewModel.cs b/VECTO3GUI2020/ViewModel/Interfaces/IJobListViewModel.cs index 6b09b8717c8fab496c4bae1091a04c2640d9cbce..9f429c60afebbdceff089cf1e22bb37e666f4c67 100644 --- a/VECTO3GUI2020/ViewModel/Interfaces/IJobListViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Interfaces/IJobListViewModel.cs @@ -1,6 +1,8 @@ using System.Collections.ObjectModel; using System.Threading.Tasks; using System.Windows.Input; +using Microsoft.Toolkit.Mvvm.Input; +using NLog; using VECTO3GUI2020.Model.Interfaces; using VECTO3GUI2020.ViewModel.Interfaces.Document; @@ -8,10 +10,18 @@ namespace VECTO3GUI2020.ViewModel.Interfaces { public interface IJobListViewModel : IMainViewModel { - ICommand AddJob { get; } - ICommand EditJob { get; } - ObservableCollection<IDocumentViewModel> Jobs { get; } - ICommand NewManufacturingStageFile { get; } - Task<IDocumentViewModel> AddJobAsync(string fileName); + ObservableCollection<IDocumentViewModel> Jobs { get; } + ICommand NewManufacturingStageFileCommand { get; } + ICommand NewCompletedInputCommand { get; } + ICommand NewExemptedCompletedInputCommand { get; } + IRelayCommand<bool> NewVifCommand { get; } + ICommand EditDocument { get; set; } + ICommand ViewXMLFile { get; set; } + IAsyncRelayCommand RemoveJob { get; set; } + ICommand OpenSourceFileCommand { get; } + ICommand ShowSourceFileCommand { get; } + IAsyncRelayCommand AddJobAsyncCommand { get; } + Task<IDocumentViewModel> AddJobAsync(string fileName, bool runSimulationAfterAdding = false); + void AddJob(IDocumentViewModel jobToAdd); } } diff --git a/VECTO3GUI2020/ViewModel/Interfaces/IMainWindowViewModel.cs b/VECTO3GUI2020/ViewModel/Interfaces/IMainWindowViewModel.cs index 688159a82fbef1ba6c38118537057a0f637aaa85..28ce249b57f78279f67b8abb0eb9889714e59281 100644 --- a/VECTO3GUI2020/ViewModel/Interfaces/IMainWindowViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Interfaces/IMainWindowViewModel.cs @@ -4,10 +4,9 @@ namespace VECTO3GUI2020.ViewModel.Interfaces { public interface IMainWindowViewModel { - IMainViewModel CurrentViewModelTop { get; set; } - IMainViewModel CurrentViewModelBottom { get; set; } + IMainViewModel CurrentViewModel { get; set; } - #region Commands + #region Commands ICommand OpenSettings { get;} #endregion } diff --git a/VECTO3GUI2020/ViewModel/Interfaces/ISettingsViewModel.cs b/VECTO3GUI2020/ViewModel/Interfaces/ISettingsViewModel.cs index 889bdc9b65870abd36d314e3f62200bc9b8801bd..326fdcef515188cebfc385168672ed1a520692c6 100644 --- a/VECTO3GUI2020/ViewModel/Interfaces/ISettingsViewModel.cs +++ b/VECTO3GUI2020/ViewModel/Interfaces/ISettingsViewModel.cs @@ -1,9 +1,13 @@ namespace VECTO3GUI2020.ViewModel.Interfaces { - public interface ISettingsViewModel + public interface ISettingsViewModel : IMainViewModel { - - - - } + string DefaultFilePath { get; set; } + string DefaultOutputPath { get; set; } + bool SerializeVectoRunData { get; set; } + bool ActualModalData { get; set; } + bool Validate { get; set; } + bool ModalResults1Hz { get; set; } + bool WriteModalResults { get; set; } + } } diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/CreateVifViewModel.cs b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/CreateVifViewModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..35f6902108c8ea1bf70cc2668e799098cf94fd18 --- /dev/null +++ b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/CreateVifViewModel.cs @@ -0,0 +1,500 @@ +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.ServiceModel.Channels; +using System.Text; +using System.Windows; +using System.Windows.Input; +using Castle.Core.Internal; +using InteractiveDataDisplay.WPF; +using Microsoft.Toolkit.Mvvm.Input; +using Microsoft.WindowsAPICodePack.Shell.Interop; +using Newtonsoft.Json; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCore.InputData.FileIO.JSON; +using TUGraz.VectoCore.InputData.FileIO.XML; +using TUGraz.VectoCore.InputData.FileIO.XML.Declaration; +using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider; +using TUGraz.VectoCore.Utils; +using VECTO3GUI2020.Helper; +using VECTO3GUI2020.Model.Multistage; +using VECTO3GUI2020.ViewModel.Implementation.Common; +using VECTO3GUI2020.ViewModel.Interfaces; +using VECTO3GUI2020.ViewModel.Interfaces.Document; +using Delegate = System.Delegate; + +namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation +{ + public interface ICreateVifViewModel: IDocumentViewModel, IEditViewModel + { + bool LoadStageInput(string fileName); + bool LoadPrimaryInput(string fileName); + bool? IsPrimaryExempted { get; set; } + bool? IsStageInputExempted { get; set; } + string PrimaryInputPath { get; set; } + string StageInputPath { get; set; } + IRelayCommand RemoveStageInputCommand { get; } + IRelayCommand RemovePrimaryCommand { get; } + string SaveJob(string path); + } + public class CreateVifViewModel : ViewModelBase, ICreateVifViewModel + { + private string _primaryInputPath; + private string _stageInputPath; + private readonly IDialogHelper _dialogHelper; + private readonly IXMLInputDataReader _inputDataReader; + private static uint _newVifCounter = 0; + private readonly uint _newVifCount; + + private bool? _isPrimaryExempted; + + public bool? IsPrimaryExempted + { + get => _isPrimaryExempted; + set => SetProperty(ref _isPrimaryExempted, value); + } + + private bool? _isStageInputExempted; + + public bool? IsStageInputExempted + { + get => _isStageInputExempted; + set => SetProperty(ref _isStageInputExempted, value); + } + + private bool _completed; + public bool Completed + { + get => _completed; + set => SetProperty(ref _completed, value); + } + + #region Labeling + + private string _vifType; + + private string VifType + { + get + { + return Completed ? "Completed Job" : "Primary Job with Interim Input"; + } + set => SetProperty(ref _vifType, value); + } + + #endregion + + public bool UnsavedChanges => _backingStorage.UnsavedChanges; + + + public CreateVifViewModel(IDialogHelper dialogHelper, + IXMLInputDataReader inputDataReader, + IAdditionalJobInfoViewModel additionalJobInfo) + { + SizeToContent = SizeToContent.WidthAndHeight; + + _newVifCount = ++_newVifCounter; + _dialogHelper = dialogHelper; + _inputDataReader = inputDataReader; + _additionalJobInfo = additionalJobInfo; + additionalJobInfo.SetParent(this); + + + SetupBackingStorage(); + + + + UpdateTitleAndDocumentName(); + (this as INotifyPropertyChanged).PropertyChanged += CreateVifViewModel_PropertyChanged; + } + + private void SetupBackingStorage() + { + _backingStorage = new BackingStorage<CreateVifViewModel>(this, + nameof(this.PrimaryInputPath), + nameof(this.StageInputPath)); + _backingStorage.PropertyChanged += (object s, PropertyChangedEventArgs e) => { + OnPropertyChanged(nameof(UnsavedChanges)); + }; + } + + private void CreateVifViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName != nameof(CanBeSimulated)) { + OnPropertyChanged(nameof(CanBeSimulated)); + } + switch (e.PropertyName) { + case nameof(DataSource): + case nameof(Completed): + case nameof(UnsavedChanges): + UpdateTitleAndDocumentName(); + break; + default: + break; + } + } + + public CreateVifViewModel(IInputDataProvider inputData, + IDialogHelper dialogHelper, + IXMLInputDataReader inputDataReader, + IAdditionalJobInfoViewModel additionalJobInfo) : this(dialogHelper, inputDataReader, additionalJobInfo) + { + SetInputData(inputData); + _backingStorage.SaveChanges(); + } + + public CreateVifViewModel(bool completed, IDialogHelper dialogHelper, IXMLInputDataReader inputDataReader, + IAdditionalJobInfoViewModel additionalJobInfo) : this(dialogHelper, inputDataReader, additionalJobInfo) + { + _completed = completed; + } + + + private void SetInputData(IInputDataProvider inputData) + { + var inputDataProvider = inputData as JSONInputDataV10_PrimaryAndStageInputBus; + Debug.Assert(inputDataProvider != null); + + + if (inputDataProvider.StageInputData != null && (inputDataProvider.StageInputData.ExemptedVehicle != + inputDataProvider.PrimaryVehicle.ExemptedVehicle)) { + throw new VectoException("Can't combine exempted and non-exempted input data"); + } + + Completed = inputDataProvider.Completed ?? false; + StageInputPath = inputDataProvider.StageInputData?.DataSource?.SourceFile; + PrimaryInputPath = inputDataProvider.PrimaryVehicle?.DataSource?.SourceFile; + DataSource = inputData.DataSource; + UpdateTitleAndDocumentName(); + } + + private void UpdateTitleAndDocumentName() + { + var titleStringBuilder = new StringBuilder(); + titleStringBuilder.Append("Create ").Append(VifType); + if (DataSource != null) { + titleStringBuilder.Append(" - ").Append(Path.GetFileName(DataSource.SourceFile)); + } + + titleStringBuilder.Append(UnsavedChanges ? "*" : ""); + Title = titleStringBuilder.ToString(); + DocumentName = Path.GetFileNameWithoutExtension(_dataSource?.SourceFile) ?? $"New {VifType} {_newVifCount}"; + } + + + public string PrimaryInputPath + { + get => _primaryInputPath; + set + { + if (SetProperty(ref _primaryInputPath, value)) { + OnPropertyChanged(nameof(CanBeSimulated)); + _removePrimaryCommand?.NotifyCanExecuteChanged(); + } + } + } + + public string StageInputPath + { + get => _stageInputPath; + set + { + if (SetProperty(ref _stageInputPath, value)) + { + OnPropertyChanged(nameof(CanBeSimulated)); + _removeStageInputCommand?.NotifyCanExecuteChanged(); + } + } + } + + #region Commands + + private ICommand _selectPrimaryInputFileCommand; + private ICommand _selectCompletedInputFileCommand; + public ICommand SelectCompletedInputFileCommand + { + get => _selectCompletedInputFileCommand ?? (_selectCompletedInputFileCommand = new RelayCommand(() => { + var selectedFile = _dialogHelper.OpenXMLFileDialog(); + LoadStageInput(selectedFile); + + + })); + } + + public ICommand SelectPrimaryInputFileCommand + { + get => _selectPrimaryInputFileCommand ?? (_selectPrimaryInputFileCommand = new RelayCommand(() => { + var selectedFilePath = _dialogHelper.OpenXMLFileDialog(); + LoadPrimaryInput(selectedFilePath); + + })); + } + + private IRelayCommand _saveJobCommand; + + public ICommand SaveJobCommand + { + get => _saveJobCommand ?? (_saveJobCommand = new RelayCommand(() => { + if (_dataSource.SourceFile != null) { + if (CanBeSaved()) { + SaveJob(_dataSource.SourceFile); + } + } + }, () => DataSource != null)); + } + public IRelayCommand _removeStageInputCommand; + + public IRelayCommand RemoveStageInputCommand => + _removeStageInputCommand ?? (_removeStageInputCommand = new RelayCommand(() => { + StageInputPath = null; + IsStageInputExempted = null; + + }, () => StageInputPath != null)); + + + + + public IRelayCommand _removePrimaryCommand; + + public IRelayCommand RemovePrimaryCommand => + _removePrimaryCommand ?? (_removePrimaryCommand = new RelayCommand(() => { + PrimaryInputPath = null; + IsPrimaryExempted = null; + + }, () => PrimaryInputPath != null)); + + + private bool CanBeSaved() + { + if (_primaryInputPath == null) { + _dialogHelper.ShowMessageBox("At least Primary Vehicle has to be provided", "Info", MessageBoxButton.OK, + MessageBoxImage.Information); + return false; + } + + return true; + } + + public string SaveJob(string path) + { + if (path == null) { + return null; + } + + var jsonJob = new JSONJob() { + Header = new JSONJobHeader() { + AppVersion = "Vecto3GUI2020", + CreatedBy = Environment.UserName, + Date = DateTime.Today, + FileVersion = JSONJobHeader.PrimaryAndInterimVersion + }, + Body = new JSONJobBody() { + PrimaryVehicle = PrimaryInputPath, + InterimStage = StageInputPath + } + }; + + string jsonString = JsonConvert.SerializeObject(jsonJob, Formatting.Indented); + + + Debug.WriteLine(jsonString); + File.WriteAllText(path, jsonString); + SetInputData(JSONInputDataFactory.ReadJsonJob(path)); + _backingStorage.SaveChanges(); + return path; + } + + private IRelayCommand _saveJobAsCommand; + + public IRelayCommand SaveJobAsCommand + { + get => _saveJobAsCommand ?? (_saveJobAsCommand = new RelayCommand(() => { + if (CanBeSaved()) { + var path = _dialogHelper.SaveToJsonDialog(); + SaveJob(path); + } + })); + } + + public bool LoadStageInput(string fileName) + { + if (fileName == null) + { + return false; + } + + var valid = true; + IVehicleDeclarationInputData vehicleInputData = null; + try + { + var inputData = _inputDataReader.Create(fileName) as IDeclarationInputDataProvider; + vehicleInputData = inputData.JobInputData.Vehicle; + var type = vehicleInputData.GetType(); + valid = (inputData != null) && (vehicleInputData is XMLDeclarationInterimStageBusDataProviderV28) || (vehicleInputData is XMLDeclarationExemptedInterimStageBusDataProviderV28); + } + catch (Exception e) + { + valid = false; + } + + valid = valid && SetStageInputExempted(vehicleInputData.ExemptedVehicle); + + if (valid) + { + StageInputPath = fileName; + } + else + { + _dialogHelper.ShowMessageBox("Invalid File", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + } + + + + + return valid; + } + + + public bool LoadPrimaryInput(string fileName) + { + if (fileName == null) + { + return false; + } + + var valid = true; + IDeclarationInputDataProvider inputData = null; + try + { + inputData = _inputDataReader.Create(fileName) as IDeclarationInputDataProvider; + valid = inputData != null && inputData.JobInputData.Vehicle.VehicleCategory.IsBus(); + } + catch (Exception ex) + { + valid = false; + } + + valid = valid && SetPrimaryInputExempted(inputData.JobInputData.Vehicle.ExemptedVehicle); + + + + if (valid) + { + PrimaryInputPath = fileName; + } + else + { + _dialogHelper.ShowMessageBox("Invalid File", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + } + + + return valid; + } + + private bool SetPrimaryInputExempted(bool primaryExempted) + { + var valid = IsStageInputExempted == null || IsStageInputExempted == primaryExempted; + + if (valid) + { + IsPrimaryExempted = primaryExempted; + } + else + { + _dialogHelper.ShowMessageBox( + caption: "Error", + button: MessageBoxButton.OK, + icon: MessageBoxImage.Error, + messageBoxText: (primaryExempted + ? "Exempted primary vehicle not allowed for non-exempted interim/completed input" + : "Only exempted input allowed for exempted interim/completed input")); + } + return valid; + } + + private bool SetStageInputExempted(bool stageInputExempted) + { + var valid = IsPrimaryExempted == null || IsPrimaryExempted == stageInputExempted; + + if (valid) + { + IsStageInputExempted = stageInputExempted; + } + else + { + _dialogHelper.ShowMessageBox( + caption: "Error", + button: MessageBoxButton.OK, + icon: MessageBoxImage.Error, + messageBoxText: (stageInputExempted + ? "Exempted interim/complete input is invalid for non-exempted primary vehicle" + : "Only exempted input allowed for selected primary vehicle")); + } + return valid; + } + + + #endregion + + #region Implementation of IDocumentViewModel + private bool _selected; + private string _documentName; + private DataSource _dataSource; + private IAdditionalJobInfoViewModel _additionalJobInfo; + private BackingStorage<CreateVifViewModel> _backingStorage; + + + public string DocumentName + { + get => _documentName; + set => SetProperty(ref _documentName, value); + } + + + public XmlDocumentType DocumentType => throw new NotImplementedException(); + + public DataSource DataSource + { + get => _dataSource; + set + { + if (SetProperty(ref _dataSource, value)) { + _saveJobCommand?.NotifyCanExecuteChanged(); + } + } + } + + public IEditViewModel EditViewModel => this; + + public bool Selected + { + get => _selected && CanBeSimulated; + set => SetProperty(ref _selected, value); + } + + public bool CanBeSimulated + { + get => PrimaryInputPath != null && StageInputPath != null && !UnsavedChanges; + set => throw new NotImplementedException(); + } + + public IAdditionalJobInfoViewModel AdditionalJobInfoVm + { + get => _additionalJobInfo; + set => SetProperty(ref _additionalJobInfo, value); + } + + #endregion + + #region Implementation of IEditViewModel + + public string Name => DocumentName; + + + + #endregion + } +} diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/InterimStageBusVehicleViewModel_v2_8.cs b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/InterimStageBusVehicleViewModel_v2_8.cs index 7cf379e0a0e613e99dfe177628aa15defb0c31ba..6dab867e83d75e3ba0888201f8a46a2b2c447444 100644 --- a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/InterimStageBusVehicleViewModel_v2_8.cs +++ b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/InterimStageBusVehicleViewModel_v2_8.cs @@ -14,6 +14,7 @@ using System.Xml; using Castle.Core.Internal; using Microsoft.Build.Framework; using TUGraz.VectoCommon.BusAuxiliaries; +using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; @@ -69,7 +70,7 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation } } - public interface IMultistageVehicleViewModel : IVehicleViewModel + public interface IMultistageVehicleViewModel : IVehicleViewModel, INotifyPropertyChanged { bool HasErrors { get; } Dictionary<string, string> Errors { get; } @@ -80,9 +81,14 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation } - public class DeclarationInterimStageBusVehicleViewModel_v2_8 : ViewModelBase, IMultistageVehicleViewModel, + public class InterimStageBusVehicleViewModel_v2_8 : ViewModelBase, IMultistageVehicleViewModel, IVehicleComponentsDeclaration, IAdvancedDriverAssistantSystemDeclarationInputData, IDataErrorInfo { + public static readonly Type INPUTPROVIDERTYPE = typeof(XMLDeclarationInterimStageBusDataProviderV28); + public static readonly Type INPUTPROVIDERTYPEEXEMPTED = typeof(XMLDeclarationExemptedInterimStageBusDataProviderV28); + public static string VERSION = INPUTPROVIDERTYPE.ToString(); + public static string VERSION_EXEMPTED = INPUTPROVIDERTYPEEXEMPTED.ToString(); + private readonly IMultiStageViewModelFactory _multiStageViewModelFactory; @@ -121,8 +127,7 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation #endregion - public static readonly string INPUTPROVIDERTYPE = - typeof(XMLDeclarationInterimStageBusDataProviderV28).ToString(); + public string Name => "Vehicle"; @@ -138,29 +143,79 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation set { throw new NotImplementedException(); } } + private bool _showConsolidatedData; + + public bool ShowConsolidatedData + { + get => _showConsolidatedData; + set + { + SetProperty(ref _showConsolidatedData, value); + if (MultistageAuxiliariesViewModel != null) { + MultistageAuxiliariesViewModel.ShowConsolidatedData = value; + } + + if (MultistageAirdragViewModel != null) { + MultistageAirdragViewModel.ShowConsolidatedData = value; + } + foreach (var multistageParameterViewModel in _parameterViewModels) { + multistageParameterViewModel.Value.ShowConsolidatedData = value; + } + } + } + + public InterimStageBusVehicleViewModel_v2_8(string inputProviderType, IMultiStageViewModelFactory multiStageViewModelFactory) + { + if (inputProviderType == VERSION_EXEMPTED) + { + _exemptedVehicle = true; + } + + _multiStageViewModelFactory = multiStageViewModelFactory; + + if (!_exemptedVehicle) + { + MultistageAirdragViewModel = _multiStageViewModelFactory.GetMultistageAirdragViewModel(); + MultistageAuxiliariesViewModel = _multiStageViewModelFactory.GetAuxiliariesViewModel(); + } - public DeclarationInterimStageBusVehicleViewModel_v2_8(IVehicleDeclarationInputData consolidatedVehicleData, - IMultiStageViewModelFactory multistageViewModelFactory) + CreateParameterViewModels(); + ShowConsolidatedData = false; + } + public InterimStageBusVehicleViewModel_v2_8(IVehicleDeclarationInputData inputData, IMultiStageViewModelFactory multiStageViewModelFactory) : + this(inputData.GetType().ToString(), multiStageViewModelFactory) + { + SetVehicleInputData(inputData); + } + + public InterimStageBusVehicleViewModel_v2_8(IVehicleDeclarationInputData consolidatedVehicleData, + IMultiStageViewModelFactory multistageViewModelFactory, bool exempted) { ConsolidatedVehicleData = consolidatedVehicleData; - + _exemptedVehicle = exempted; _multiStageViewModelFactory = multistageViewModelFactory; - MultistageAirdragViewModel = _multiStageViewModelFactory.GetMultistageAirdragViewModel(consolidatedVehicleData?.Components?.AirdragInputData); - - MultistageAirdragViewModel.AirdragViewModelChanged += ((sender, args) => { - if (sender is IMultistageAirdragViewModel vm) { - if (AirdragModifiedMultistageMandatory) { - if (vm.AirDragViewModel != null) { - AirdragModifiedMultistage = true; + + if (!exempted) { + MultistageAirdragViewModel = _multiStageViewModelFactory.GetMultistageAirdragViewModel(consolidatedVehicleData?.Components?.AirdragInputData); + + MultistageAirdragViewModel.AirdragViewModelChanged += ((sender, args) => { + if (sender is IMultistageAirdragViewModel vm) + { + if (AirdragModifiedMultistageMandatory) + { + if (vm.AirDragViewModel != null) + { + AirdragModifiedMultistage = true; + } } } - } - }); + }); - MultistageAuxiliariesViewModel = - _multiStageViewModelFactory.GetAuxiliariesViewModel(consolidatedVehicleData?.Components? - .BusAuxiliaries); + MultistageAuxiliariesViewModel = + _multiStageViewModelFactory.GetAuxiliariesViewModel(consolidatedVehicleData?.Components? + .BusAuxiliaries); + } CreateParameterViewModels(); @@ -287,8 +342,8 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation .NOT_APPLICABLE)); _parameterViewModels[nameof(LegislativeClass)].AllowedItems = - EnumHelper.GetValuesAsObservableCollectionExcluding<Enum, LegislativeClass>((TUGraz.VectoCommon.Models - .LegislativeClass.Unknown)); + EnumHelper.GetValuesAsObservableCollectionIncluding<Enum, LegislativeClass>((TUGraz.VectoCommon.Models + .LegislativeClass.M3)); _parameterViewModels[nameof(RegisteredClass)].AllowedItems = EnumHelper.GetValuesAsObservableCollectionExcluding<Enum, RegistrationClass>(RegistrationClass.unknown); @@ -334,6 +389,16 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation public void SetVehicleInputData(IVehicleDeclarationInputData vehicleInputData) { + if (vehicleInputData.ExemptedVehicle != ExemptedVehicle) { + throw new VectoException(ExemptedVehicle ? "Only exempted stage inputs are allowed" : "Exempted Vehicle not allowed"); + } + + if (ExemptedVehicle) { + SetExemptedVehicleInputData(vehicleInputData); + return; + } + + Manufacturer = vehicleInputData.Manufacturer; Identifier = vehicleInputData.Identifier; ManufacturerAddress = vehicleInputData.ManufacturerAddress; @@ -372,9 +437,28 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation { multistageParameterViewModel.UpdateEditingEnabled(); } + MultistageAirdragViewModel.SetAirdragInputData(vehicleInputData?.Components?.AirdragInputData); + MultistageAuxiliariesViewModel.SetAuxiliariesInputData(vehicleInputData?.Components?.BusAuxiliaries); OnPropertyChanged(string.Empty); } + private void SetExemptedVehicleInputData(IVehicleDeclarationInputData vehicleInputData) + { + Debug.Assert(vehicleInputData.ExemptedVehicle); + Manufacturer = vehicleInputData.Manufacturer; + Identifier = vehicleInputData.Identifier; + ManufacturerAddress = vehicleInputData.ManufacturerAddress; + VIN = vehicleInputData.VIN; + Model = vehicleInputData.Model; + LegislativeClass = vehicleInputData.LegislativeClass; + CurbMassChassis = vehicleInputData.CurbMassChassis; + GrossVehicleMassRating = vehicleInputData.GrossVehicleMassRating; + RegisteredClass = vehicleInputData.RegisteredClass; + NumberPassengerSeatsUpperDeck = vehicleInputData.NumberPassengerSeatsUpperDeck; + NumberPassengerSeatsLowerDeck = vehicleInputData.NumberPassengerSeatsLowerDeck; + VehicleCode = vehicleInputData.VehicleCode; + Height = vehicleInputData.Height; + } @@ -687,6 +771,8 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation #endregion; + public string ExemptedTechnology { get; } + public RegistrationClass? RegisteredClass { get => _registeredClass; @@ -729,20 +815,16 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation public IAirdragDeclarationInputData AirdragInputData { - get => MultistageAirdragViewModel.AirDragViewModel; + get => MultistageAirdragViewModel?.AirDragViewModel; } public IBusAuxiliariesDeclarationData BusAuxiliaries { - get => MultistageAuxiliariesViewModel.HasValues ? MultistageAuxiliariesViewModel : null; + get => MultistageAuxiliariesViewModel != null && MultistageAuxiliariesViewModel.HasValues ? MultistageAuxiliariesViewModel : null; } #region not implemented - public string LegislativeCategory - { - get => throw new NotImplementedException(); - } public IGearboxDeclarationInputData GearboxInputData => throw new NotImplementedException(); public ITorqueConverterDeclarationInputData TorqueConverterInputData => throw new NotImplementedException(); @@ -924,11 +1006,11 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation public bool ExemptedVehicle { - get { throw new NotImplementedException(); } + get => _exemptedVehicle; + //set => SetProperty(ref _exemptedVehicle, value); } - public VehicleCategory VehicleCategory { get { throw new NotImplementedException(); } @@ -1132,7 +1214,8 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation { get { - return !Error.IsNullOrEmpty() || MultistageAuxiliariesViewModel.HasErrors; + return !Error.IsNullOrEmpty() || + (MultistageAuxiliariesViewModel != null && MultistageAuxiliariesViewModel.HasErrors); } } #endregion @@ -1140,7 +1223,7 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation private bool _airdragModifiedMultistageMandatory; private int? _numberPassengersStandingLowerDeck; private int? _numberPassengersStandingUpperDeck; - + private bool _exemptedVehicle; } } \ No newline at end of file diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/ManufacturingStageViewModel_v0_1.cs b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/ManufacturingStageViewModel_v0_1.cs index a0f8a942108ebf574af9b5dcc2d7640a11bf3dc9..573b344afab3f9dc5da11024a6c8745a7d75a416 100644 --- a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/ManufacturingStageViewModel_v0_1.cs +++ b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/ManufacturingStageViewModel_v0_1.cs @@ -1,18 +1,14 @@ using System; using System.Collections; -using System.Collections.Generic; using System.Linq; using System.Net.Mime; using System.Security.RightsManagement; using System.Text; using System.Threading.Tasks; -using System.Windows.Input; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider; using TUGraz.VectoCore.InputData.Impl; using TUGraz.VectoCore.Models.GenericModelData; -using VECTO3GUI2020.Util; -using VECTO3GUI2020.ViewModel.Implementation.Common; using VECTO3GUI2020.ViewModel.Implementation.JobEdit.Vehicle; using VECTO3GUI2020.ViewModel.Implementation.JobEdit.Vehicle.Components; using VECTO3GUI2020.ViewModel.Interfaces.Common; @@ -22,12 +18,8 @@ using VECTO3GUI2020.ViewModel.MultiStage.Interfaces; namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation { - public class ManufacturingStageViewModel_v0_1 : ViewModelBase, IManufacturingStageViewModel + public class ManufacturingStageViewModel_v0_1 : StageViewModelBase, IManufacturingStageViewModel { - public static readonly string INPUTPROVIDERTYPE = typeof(XMLDeclarationMultistageTypeInputDataV01).ToString(); - public static readonly string QualifiedXSD = XMLDeclarationMultistageTypeInputDataV01.QUALIFIED_XSD_TYPE; - private Dictionary<string, IViewModelBase> Components = new Dictionary<string, IViewModelBase>(StringComparer.CurrentCultureIgnoreCase); - public DigestData HashPreviousStage { get => _hashPreviousStage; @@ -42,24 +34,9 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation public IVehicleDeclarationInputData Vehicle => _vehicleViewModel; - public IViewModelBase CurrentView - { - get => _currentview; - set => SetProperty(ref _currentview, value); - } - private IApplicationInformation _applicationInformation = new ApplicationInformation { Date = DateTime.Today, }; - private IMultistageVehicleViewModel _vehicleViewModel; - private IMultiStageViewModelFactory _viewModelFactory; - private IViewModelBase _currentview; - - public IMultistageVehicleViewModel VehicleViewModel - { - get => _vehicleViewModel; - set => SetProperty(ref _vehicleViewModel, value); - } public IApplicationInformation ApplicationInformation { @@ -71,33 +48,29 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation public void SetInputData(IVehicleDeclarationInputData vehicleInputData) { VehicleViewModel.SetVehicleInputData(vehicleInputData); - VehicleViewModel.MultistageAirdragViewModel.SetAirdragInputData(vehicleInputData?.Components?.AirdragInputData); - VehicleViewModel.MultistageAuxiliariesViewModel.SetAuxiliariesInputData(vehicleInputData?.Components?.BusAuxiliaries); + OnPropertyChanged(nameof(CurrentView)); } - public ManufacturingStageViewModel_v0_1(IManufacturingStageInputData consolidatedManufacturingStageInputData, IMultiStageViewModelFactory viewModelFactory) + public ManufacturingStageViewModel_v0_1(IManufacturingStageInputData consolidatedManufacturingStageInputData, bool exempted, + IMultiStageViewModelFactory viewModelFactory) : base(viewModelFactory) { Title = "Edit Manufacturing Stage"; - _viewModelFactory = viewModelFactory; + _stageCount = consolidatedManufacturingStageInputData?.StageCount + 1 ?? 2; _consolidatedManufacturingStageInputData = consolidatedManufacturingStageInputData; - VehicleViewModel = (IMultistageVehicleViewModel)_viewModelFactory.GetInterimStageVehicleViewModel(consolidatedManufacturingStageInputData?.Vehicle); + VehicleViewModel = (IMultistageVehicleViewModel)_viewModelFactory.GetInterimStageVehicleViewModel(consolidatedManufacturingStageInputData?.Vehicle, exempted); CurrentView = VehicleViewModel as IViewModelBase; Components.Add(VehicleViewModel.Name, VehicleViewModel as IViewModelBase); - - - Components.Add("Airdrag", VehicleViewModel.MultistageAirdragViewModel as IViewModelBase); - Components.Add("Auxiliaries", VehicleViewModel.MultistageAuxiliariesViewModel as IViewModelBase); } @@ -107,28 +80,6 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation private DigestData _hashPreviousStage; private IManufacturingStageInputData _consolidatedManufacturingStageInputData; - #region Commands - - private ICommand _switchComponentViewCommand; - - - public ICommand SwitchComponentViewCommand - { - get { - return _switchComponentViewCommand ?? new RelayCommand<string>(SwitchViewExecute, (string s) => true); - } - } - - private void SwitchViewExecute(string viewToShow) - { - IViewModelBase newView; - var success= Components.TryGetValue(viewToShow, out newView); - if (success) { - CurrentView = newView; - } - } - - #endregion private class ApplicationInformationMultistage : IApplicationInformation { @@ -138,9 +89,8 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation } } - public interface IManufacturingStageViewModel : IManufacturingStageInputData - { + + public interface IManufacturingStageViewModel : IManufacturingStageInputData, IStageViewModelBase{ void SetInputData(IVehicleDeclarationInputData vehicleInputData); - IMultistageVehicleViewModel VehicleViewModel { get; } } } diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageAirdragViewModel.cs b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageAirdragViewModel.cs index 03e0394b8961589b7d5c4c7af9ae954b3d84636b..4811f904c9caae3c645ddd41de77239b8ac7e455 100644 --- a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageAirdragViewModel.cs +++ b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageAirdragViewModel.cs @@ -62,6 +62,12 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation } } + public bool ShowConsolidatedData + { + get => _showConsolidatedData; + set => SetProperty(ref _showConsolidatedData, value); + } + private void StoreAirdragViewModel() { if (AirDragViewModel != null && StoredAirdragViewModel != AirDragViewModel) { @@ -115,6 +121,7 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation private IAirdragDeclarationInputData _consolidatedAirdragInputData; private string _airdragFilePath; private readonly IMultistageDependencies _dependencies; + private bool _showConsolidatedData = true; public ICommand LoadAirdragFileCommand { diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageAuxiliariesViewModel.cs b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageAuxiliariesViewModel.cs index 3b762b2fa2417a2ba5c7924235905c64392b2b0d..a1a749c1215e0d97958825f8dfd3728b1653647c 100644 --- a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageAuxiliariesViewModel.cs +++ b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageAuxiliariesViewModel.cs @@ -38,12 +38,18 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation object PrimaryVehicleHybridElectric { get; set; } bool HasErrors { get; } Dictionary<string, string> Errors { get; } + bool ShowConsolidatedData { get; set; } } public class MultistageAuxiliariesViewModel : ViewModelBase, IMultistageAuxiliariesViewModel, IDataErrorInfo { + public MultistageAuxiliariesViewModel() + { + CreateParameterViewModels(); + } + public MultistageAuxiliariesViewModel(IBusAuxiliariesDeclarationData consolidatedAuxiliariesInputData) { ConsolidatedInputData = consolidatedAuxiliariesInputData; @@ -224,11 +230,23 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation OnPropertyChanged(String.Empty); } + private bool _showConsolidatedData; + public bool ShowConsolidatedData + { + get => _showConsolidatedData; + set + { + SetProperty(ref _showConsolidatedData, value); + foreach (var multistageParameterViewModel in ParameterViewModels) { + multistageParameterViewModel.Value.ShowConsolidatedData = value; + } + } + } - private IBusAuxiliariesDeclarationData _consolidatedInputData; + private IBusAuxiliariesDeclarationData _consolidatedInputData; public IBusAuxiliariesDeclarationData ConsolidatedInputData { get => _consolidatedInputData; @@ -274,15 +292,6 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation set => SetProperty(ref _primaryVehicleHybridElectric, value); } - private IndexedStorage<bool> _editingEnabledDictionary; - public IndexedStorage<bool> EditingEnabledDictionary - { - get - { - return _editingEnabledDictionary; - } - } - #region HVAC @@ -364,23 +373,37 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation public ICommand AddPassengerHeatpumpCommand { - get => _addPassengerHeatpumpCommand ?? + get + { + return _addPassengerHeatpumpCommand ?? (_addPassengerHeatpumpCommand = new RelayCommand(() => { HeatPumpGroupEditingEnabled = true; if (HeatPumpConfigurationsPassenger == null) { HeatPumpConfigurationsPassenger = new ObservableCollection<HeatPumpConfiguration>(); } + HeatPumpConfigurationsPassenger.Add(new HeatPumpConfiguration()); + RemovePassengerHeatpumpCommand.NotifyCanExecuteChanged(); + }, - () => true); + () => true)); + } } - public ICommand _removePasssengerHeatpumpCommand; + private IRelayCommand _removePassengerHeatpumpCommand; - public ICommand RemovePassengerHeatpumpCommand + public IRelayCommand RemovePassengerHeatpumpCommand { - get => _removePasssengerHeatpumpCommand ?? - new RelayCommand<HeatPumpConfiguration>(hp => HeatPumpConfigurationsPassenger?.Remove(hp), (hp) => true); + get + { + return _removePassengerHeatpumpCommand ?? (_removePassengerHeatpumpCommand = + new RelayCommand<HeatPumpConfiguration>(hp => { + if (HeatPumpGroupEditingEnabled && HeatPumpConfigurationsPassenger.Count > 1) { + HeatPumpConfigurationsPassenger?.Remove(hp); + RemovePassengerHeatpumpCommand.NotifyCanExecuteChanged(); + } + }, hp => HeatPumpConfigurationsPassenger.Count > 1)); + } } public IList<Tuple<HeatPumpType, HeatPumpMode>> HeatPumpPassengerCompartments{ @@ -559,6 +582,10 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation _parameterViewModels[nameof(SystemConfiguration)].EditingEnabled = value; if (value == false) { HeatPumpConfigurationsPassenger = null; + } else { + if (HeatPumpConfigurationsPassenger == null || HeatPumpConfigurationsPassenger.Count == 0) { + AddPassengerHeatpumpCommand.Execute(null); + } } } } @@ -648,9 +675,6 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation set { SetProperty(ref _interiorLightsLed, value); - if (value != null) { - OnPropertyChanged(nameof(EditingEnabledDictionary)); - } } } diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageJobViewModel_v0_1.cs b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageJobViewModel_v0_1.cs index b9d1a2a335bd9f5b8b88a4a3674c5583d1cccd21..9afa71ae8a6e55f181f1dd5f606c360fad09a14e 100644 --- a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageJobViewModel_v0_1.cs +++ b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageJobViewModel_v0_1.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Windows; +using System.Windows.Forms; using System.Windows.Input; using System.Windows.Navigation; using System.Xml; @@ -33,6 +34,7 @@ using VECTO3GUI2020.ViewModel.Interfaces.Common; using VECTO3GUI2020.ViewModel.Interfaces.Document; using VECTO3GUI2020.ViewModel.Interfaces.JobEdit.Vehicle; using VECTO3GUI2020.ViewModel.MultiStage.Interfaces; +using INotifyPropertyChanged = System.ComponentModel.INotifyPropertyChanged; using XmlDocumentType = TUGraz.VectoCore.Utils.XmlDocumentType; namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation @@ -41,6 +43,14 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation public interface IMultiStageJobViewModel : IDeclarationMultistageJobInputData, IMultistageVIFInputData, IMultistageBusInputDataProvider, IJobViewModel, IEditViewModel { IManufacturingStageViewModel ManufacturingStageViewModel { get; } + bool Exempted { get; } + + /// <summary> + /// Creates a new VIF file + /// </summary> + /// <param name="outputFile"></param> + /// <returns>Name of the created File</returns> + string SaveVif(string outputFile); } @@ -55,6 +65,9 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation private VectoSimulationJobType _jobType; private bool _inputComplete; private readonly IMultiStageViewModelFactory _vmFactory; + private IAdditionalJobInfoViewModel _additionalJobInfoVm; + + public IManufacturingStageViewModel ManufacturingStageViewModel { @@ -62,11 +75,18 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation set => SetProperty(ref _manufacturingStageViewModel, value); } - public MultiStageJobViewModel_v0_1(IMultistageBusInputDataProvider inputData, IMultiStageViewModelFactory vmFactory, IMultistageDependencies multistageDependencies, IXMLInputDataReader inputDataReader) + public MultiStageJobViewModel_v0_1(IMultistageBusInputDataProvider inputData, + IMultiStageViewModelFactory vmFactory, + IMultistageDependencies multistageDependencies, + IXMLInputDataReader inputDataReader, + IJobListViewModel jobListViewModel, + IAdditionalJobInfoViewModel additionalJobInfo) { - Title = "Edit Multistage Job"; + _dataSource = inputData.DataSource; + Title = $"Edit Multistage Job - {Path.GetFileName(_dataSource.SourceFile)}"; _jobInputData = inputData.JobInputData; + _jobListViewModel = jobListViewModel; _inputData = inputData; _vmFactory = vmFactory; _consolidateManufacturingStage = _jobInputData.ConsolidateManufacturingStage; @@ -74,28 +94,50 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation _primaryVehicle = _jobInputData.PrimaryVehicle; _dialogHelper = multistageDependencies.DialogHelperLazy; _inputDataReader = inputDataReader; + _inputComplete = inputData.JobInputData.InputComplete; + _invalidEntries = inputData.JobInputData?.InvalidEntries?.Distinct().ToList(); + _additionalJobInfoVm = additionalJobInfo; + _additionalJobInfoVm.SetParent(this); + + + _exempted = PrimaryVehicle.Vehicle.ExemptedVehicle; + _manufacturingStageViewModel = - vmFactory.GetManufacturingStageViewModel(_consolidateManufacturingStage); + vmFactory.GetManufacturingStageViewModel(_consolidateManufacturingStage, _exempted); // QUESTION: HEV/PEV ? //var hybridElectric = inputData.PrimaryVehicleData.Vehicle.HybridElectricHDV; //_manufacturingStageViewModel.VehicleViewModel.PrimaryVehicleHybridElectric = hybridElectric; _multistageDependencies = multistageDependencies; - } - #region Commands + (_manufacturingStageViewModel as INotifyPropertyChanged).PropertyChanged += MultiStageJobViewModel_v0_1_PropertyChanged; + } + public IAdditionalJobInfoViewModel AdditionalJobInfoVm + { + get => _additionalJobInfoVm; + set => SetProperty(ref _additionalJobInfoVm, value); + } - private ICommand _closeWindowCommand; - public ICommand CloseWindowCommand - { - get - { - return _closeWindowCommand ?? new RelayCommand<Window>(window => CloseWindow(window, _dialogHelper.Value), window => true); + private void MultiStageJobViewModel_v0_1_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + + if (e.PropertyName == nameof(VehicleInputDataFilePath)) { + OnPropertyChanged(nameof(VehicleInputDataFilePath)); } - } + } + + + + + + #region Commands + + + + private ICommand _saveVifCommand; @@ -114,16 +156,11 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation var auxiliariesErrorInfo = vehicleViewModel.MultistageAuxiliariesViewModel as IDataErrorInfo; - if (!auxiliariesErrorInfo.Error.IsNullOrEmpty()) { + if (auxiliariesErrorInfo != null && !auxiliariesErrorInfo.Error.IsNullOrEmpty()) { errorMessage += "Auxiliaries\n"; errorMessage += auxiliariesErrorInfo.Error.Replace(",", "\n"); } - - //_dialogHelper.Value.ShowMessageBox("Vehicle\n" + string.Join("\n", vehicleViewModel.Errors.Values) - // + (vehicleViewModel.MultistageAuxiliariesViewModel.HasErrors ? ("\nAuxiliaries\n" + string.Join("\n", vehicleViewModel.MultistageAuxiliariesViewModel.Errors.Values)) : ""), - //"Error"); - _dialogHelper.Value.ShowMessageBox(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; @@ -141,23 +178,35 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation }, () => true); } } - - public void SaveVif(string outputFile) + /// <summary> + /// Creates a new VIF file + /// </summary> + /// <param name="outputFile"></param> + /// <returns>Name of the created File</returns> + public string SaveVif(string outputFile) { - SaveVif(vifData:this, outputFile:outputFile, dialogHelper:_dialogHelper.Value); + return SaveVif(vifData:this, outputFile:outputFile, dialogHelper:_dialogHelper.Value); } - public static void SaveVif(IMultistageVIFInputData vifData, FileOutputVIFWriter writer, IDialogHelper dialogHelper = null) + public void SaveVif(IMultistageVIFInputData vifData, FileOutputVIFWriter writer, IDialogHelper dialogHelper = null) { SaveVif(vifData, null, writer, dialogHelper); } - public static void SaveVif(IMultistageVIFInputData vifData, string outputFile, + + /// <summary> + /// Creates a new VIF file + /// </summary> + /// <param name="vifData"></param> + /// <param name="outputFile"></param> + /// <param name="writer"></param> + /// <param name="dialogHelper"></param> + /// <returns>Name of the created file</returns> + private string SaveVif(IMultistageVIFInputData vifData, string outputFile, FileOutputVIFWriter writer = null, IDialogHelper dialogHelper = null) { try { - - + FileHelper.CreateDirectory(outputFile); if (writer == null) { var numberOfManufacturingStages = vifData.MultistageJobInputData.JobInputData.ManufacturingStages?.Count ?? 0; @@ -169,7 +218,7 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation var factory = new SimulatorFactory(ExecutionMode.Declaration, inputData, writer); - var jobContainer = new JobContainer(new NullSumWriter()); //TODO: Replace with real sumwriter + var jobContainer = new JobContainer(new NullSumWriter()); var runs = factory.SimulationRuns().ToList(); foreach (var run in runs) { @@ -183,114 +232,36 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation var validator = new XMLValidator(reader); var valid = validator.ValidateXML(XmlDocumentType.MultistageOutputData); if (!valid) { - dialogHelper?.ShowMessageBox($"Error writing file {validator.ValidationError}", "Error", + dialogHelper?.ShowMessageBox($"Error writing VIF {validator.ValidationError}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); Debug.WriteLine("Invalid Outputfile"); - return; + return null; } else { dialogHelper?.ShowMessageBox($"Written to {writer.XMLMultistageReportFileName}", "Info", MessageBoxButton.OK, MessageBoxImage.Information); + + var runSimulation = vifData.VehicleInputData.VehicleDeclarationType == VehicleDeclarationType.final && + (_dialogHelper.Value.ShowMessageBox("Do you want to start the simulation?", + "Run Simulation", + MessageBoxButton.YesNo, + MessageBoxImage.Question) == MessageBoxResult.Yes); + _jobListViewModel.AddJobAsync(writer.XMLMultistageReportFileName, runSimulation); + Debug.WriteLine($"Written to {writer.XMLMultistageReportFileName}"); + return writer.XMLMultistageReportFileName; } } }catch (Exception e) { - dialogHelper?.ShowMessageBox($"{e.Message}", "Error writing VIF", MessageBoxButton.OK, + dialogHelper?.ShowMessageBox($"{e.GetInnerExceptionMessages()}", "Error writing VIF", MessageBoxButton.OK, MessageBoxImage.Error); - + return null; } - } - private ICommand _saveInputDataCommand; - private ICommand _saveInputDataAsCommand; - - public ICommand SaveInputDataCommand => - _saveInputDataCommand ?? new RelayCommand(() => { - SaveInputDataExecute(filename:_vehicleInputDataFilePath); - }, () => _vehicleInputDataFilePath != null); - - public ICommand SaveInputDataAsCommand => - _saveInputDataAsCommand ?? new RelayCommand(() => { - SaveInputDataExecute(filename:null); - }, () => true); - - private void SaveInputDataExecute(string filename) - { - if(_manufacturingStageViewModel.Vehicle is IMultistageVehicleViewModel vehicleViewModel) - { - if (vehicleViewModel.HasErrors) { - var errorMessage = "Vehicle\n"; - var vehicleErrorInfo = vehicleViewModel as IDataErrorInfo; - errorMessage += vehicleErrorInfo.Error.Replace(",", "\n"); - - var auxiliariesErrorInfo = - vehicleViewModel.MultistageAuxiliariesViewModel as IDataErrorInfo; - if (!auxiliariesErrorInfo.Error.IsNullOrEmpty()) - { - errorMessage += "\n Auxiliaries \n"; - errorMessage += auxiliariesErrorInfo.Error.Replace(",", "\n"); - } - - _dialogHelper.Value.ShowMessageBox(errorMessage, "Error", MessageBoxButton.OK, - MessageBoxImage.Error); - return; - - //_dialogHelper.Value.ShowMessageBox("Vehicle\n" + string.Join("\n", vehicleViewModel.Errors.Values) - // + (vehicleViewModel.MultistageAuxiliariesViewModel.HasErrors ? ("\nAuxiliaries\n" + string.Join("\n", vehicleViewModel.MultistageAuxiliariesViewModel.Errors.Values)) : ""), - // "Error"); - return; - } - } - - - if (filename == null) { - filename = _dialogHelper.Value.SaveToXMLDialog(Settings.Default.DefaultFilePath); - if (filename == null) { - return; - } - } - - var vehicleWriter = - _multistageDependencies.XMLWriterFactory.CreateVehicleWriter(_manufacturingStageViewModel.Vehicle); - - - - var xElement = vehicleWriter.GetElement(); - var xDoc = xElement.CreateWrapperDocument(XMLNamespaces.V28); - Debug.WriteLine(xElement.CreateWrapperDocument(XMLNamespaces.V28).ToString()); - - - var valid = false; - var validationError = ""; - try { - var validator = new XMLValidator(xDoc.ToXmlDocument()); - valid = validator.ValidateXML(XmlDocumentType.DeclarationJobData); - validationError = validator.ValidationError; - } catch (Exception e) { - _dialogHelper.Value.ShowMessageBox(messageBoxText:(e.Message + "\n" + e.InnerException), caption:"Error saving File"); - } - if (!valid) { - _dialogHelper.Value.ShowMessageBox($"Invalid Document: {validationError}", "Error"); - var tempFile = Path.GetTempFileName(); - try { - xDoc.Save(tempFile, SaveOptions.OmitDuplicateNamespaces); - LoadVehicleData(tempFile); - File.Delete(tempFile); - } catch (Exception e) { - _dialogHelper.Value.ShowMessageBox(e.Message, "Error"); - throw; - } - - - } else { - xDoc.Save(filename, SaveOptions.OmitDuplicateNamespaces); - LoadVehicleData(filename); - } - } - private ICommand _loadVehicleDataCommand; + private readonly Lazy<IDialogHelper> _dialogHelper; private readonly IXMLInputDataReader _inputDataReader; private string _vehicleInputDataFilePath = null; @@ -298,53 +269,23 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation private readonly DataSource _dataSource; private readonly IMultistageBusInputDataProvider _inputData; private bool _selected; + private readonly bool _exempted; + private readonly IJobListViewModel _jobListViewModel; + private readonly IList<string> _invalidEntries; - public ICommand LoadVehicleDataCommand - { - get - { - return _loadVehicleDataCommand ?? new RelayCommand(LoadVehicleDataExecute, () => true); - } - } - - private void LoadVehicleDataExecute() - { - var fileName = _dialogHelper.Value.OpenXMLFileDialog(); - if (fileName == null) { - return; - } - - LoadVehicleData(fileName); - return; - } - private bool LoadVehicleData(string fileName) + public string VehicleInputDataFilePath { - try { - var inputData = (IDeclarationInputDataProvider)_inputDataReader.Create(fileName); - var vehicleInputData = inputData.JobInputData.Vehicle; - _manufacturingStageViewModel.SetInputData(vehicleInputData); - - VehicleInputDataFilePath = fileName; - } catch (Exception e) { - _dialogHelper.Value.ShowMessageBox(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); - return false; + get => ManufacturingStageViewModel.InputDataFilePath; + set + { + ManufacturingStageViewModel.InputDataFilePath = value; + OnPropertyChanged(); } - - return true; } - public string VehicleInputDataFilePath - { - get => _vehicleInputDataFilePath; - set => SetProperty(ref _vehicleInputDataFilePath, value); - } #endregion - - - - #region Implementation of IInputDataProvider public string DocumentName => Path.GetFileNameWithoutExtension(_inputData.DataSource.SourceFile); @@ -357,13 +298,17 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation public bool Selected { - get => _selected; + get => _selected && CanBeSimulated; set => SetProperty(ref _selected, value); } - public bool CanBeEdited + public bool CanBeSimulated { - get => true; + get + { + return (InputComplete && _inputData.JobInputData.ConsolidateManufacturingStage.Vehicle.VehicleDeclarationType == + VehicleDeclarationType.final) || (InputComplete && Exempted); + } set => throw new NotImplementedException(); } @@ -423,6 +368,7 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation set => _inputComplete = value; } + public IList<string> InvalidEntries => _invalidEntries; #endregion @@ -430,6 +376,10 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation public string Name => "Multistage"; + public bool Exempted => _exempted; + + + #endregion } diff --git a/VECTO3GUI2020/Helper/MultistageParameterViewModel.cs b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageParameterViewModel.cs similarity index 94% rename from VECTO3GUI2020/Helper/MultistageParameterViewModel.cs rename to VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageParameterViewModel.cs index 7c3413d7539e46b06491da6c9b66f20a25ece57c..17248322fe92fd3e603b09c24df0331e3cecb515 100644 --- a/VECTO3GUI2020/Helper/MultistageParameterViewModel.cs +++ b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/MultistageParameterViewModel.cs @@ -1,26 +1,16 @@ using System; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Linq; -using System.Net.Mime; using System.Reflection; using System.Resources; -using System.Runtime.InteropServices; -using System.Windows; -using System.Windows.Controls; -using Castle.Core.Internal; -using Castle.Core.Resource; -using Castle.DynamicProxy.Internal; -using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.Utils; -using VECTO3GUI2020.Annotations; +using VECTO3GUI2020.Helper; using VECTO3GUI2020.ViewModel.Implementation.Common; using VECTO3GUI2020.ViewModel.Interfaces.Common; -using VECTO3GUI2020.Views.Multistage.CustomControls; -namespace VECTO3GUI2020.Helper +namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation { public enum ViewMode { @@ -66,6 +56,7 @@ namespace VECTO3GUI2020.Helper private readonly string _propertyName; private bool _isReadOnly; private bool _valueFieldIsEditable; + private bool _showConsolidatedData = true; public MultistageParameterViewModel ( string propertyName, @@ -82,7 +73,6 @@ namespace VECTO3GUI2020.Helper PreviousContent = previousContent; _propertyChangedCallback = propertyChangedCallback; _parentViewModel = parentViewModel; - //_parentViewModel.PropertyChanged += ParentViewModelPropertyChanged; _propertyInfo = parentViewModel.GetType().GetProperty(propertyName); _viewMode = viewMode; @@ -196,10 +186,6 @@ namespace VECTO3GUI2020.Helper if (type == typeof(string)) { return ""; } - - - - } catch (Exception ex) { @@ -378,6 +364,12 @@ namespace VECTO3GUI2020.Helper get => !_mandatory; } + public bool ShowConsolidatedData + { + get => _showConsolidatedData && !Mandatory; + set => SetProperty(ref _showConsolidatedData, value); + } + #region Implementation of IDataErrorInfo public string this[string columnName] @@ -418,4 +410,6 @@ namespace VECTO3GUI2020.Helper #endregion } + + } \ No newline at end of file diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/NewMultiStageJobViewModel.cs b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/NewMultiStageJobViewModel.cs index 0468834e7dd0d4b08022fa0fe555d6139a270432..5d4332410de37846f6c7465fa81b1ab649a705dc 100644 --- a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/NewMultiStageJobViewModel.cs +++ b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/NewMultiStageJobViewModel.cs @@ -14,6 +14,7 @@ using VECTO3GUI2020.Helper; using VECTO3GUI2020.Properties; using VECTO3GUI2020.Util; using VECTO3GUI2020.ViewModel.Implementation.Common; +using VECTO3GUI2020.ViewModel.Interfaces; using VECTO3GUI2020.ViewModel.Interfaces.JobEdit.Vehicle; using VECTO3GUI2020.ViewModel.Interfaces.JobEdit.Vehicle.Components; using VECTO3GUI2020.ViewModel.MultiStage.Interfaces; @@ -46,11 +47,13 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation public NewMultiStageJobViewModel(IDialogHelper dialogHelper, IXMLInputDataReader inputDataReader, - IMultiStageViewModelFactory vmFactory) + IMultiStageViewModelFactory vmFactory, + IJobListViewModel jobListViewModel) { _inputDataReader = inputDataReader; _dialogHelper = dialogHelper; _vmFactory = vmFactory; + _jobListViewModel = jobListViewModel; Title = "New Multistage File"; VifPath = "Select VIF File"; } @@ -59,7 +62,7 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation #region AddVifCommand - public ICommand AddVifFile + public ICommand AddVifFileCommand { get => _addVifCommand ?? new RelayCommand(AddVifFileExecute, () => true); } @@ -68,19 +71,27 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation { var fileName = _dialogHelper.OpenXMLFileDialog(); - if (fileName == null) { + AddVifFile(fileName); + } + + internal void AddVifFile(string fileName) + { + if (fileName == null) + { return; } IMultistageBusInputDataProvider inputDataProvider = null; - try { + try + { inputDataProvider = _inputDataReader.Create(fileName) as IMultistageBusInputDataProvider; } - catch(Exception e) { + catch (Exception e) + { _dialogHelper.ShowMessageBox(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } - if (inputDataProvider == null) { - + if (inputDataProvider == null) + { _dialogHelper.ShowMessageBox("invalid input file", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } @@ -88,11 +99,13 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation MultiStageJobViewModel = null; MultiStageJobViewModel = _vmFactory.GetMultiStageJobViewModel(inputDataProvider); + _jobListViewModel.AddJob(MultiStageJobViewModel); VifPath = fileName; } private ICommand _closeWindow; + private readonly IJobListViewModel _jobListViewModel; public ICommand CloseWindow { diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/StageInputViewModel.cs b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/StageInputViewModel.cs new file mode 100644 index 0000000000000000000000000000000000000000..2b08c6e6e471c1e5e57d190a55f23cfcf758ff79 --- /dev/null +++ b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/StageInputViewModel.cs @@ -0,0 +1,144 @@ +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using Castle.Core.Smtp; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Utils; +using VECTO3GUI2020.ViewModel.Implementation.Common; +using VECTO3GUI2020.ViewModel.Implementation.JobEdit.Vehicle; +using VECTO3GUI2020.ViewModel.Interfaces; +using VECTO3GUI2020.ViewModel.Interfaces.Common; +using VECTO3GUI2020.ViewModel.Interfaces.Document; +using VECTO3GUI2020.ViewModel.Interfaces.JobEdit; +using VECTO3GUI2020.ViewModel.Interfaces.JobEdit.Vehicle; +using VECTO3GUI2020.ViewModel.MultiStage.Interfaces; + +namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation +{ + public class StageInputViewModel : StageViewModelBase, IDocumentViewModel, IJobEditViewModel + { + private bool _canBeEdited; + private DataSource _dataSource; + private readonly XmlDocumentType _documentType; + private string _documentName; + private bool _selected; + private static uint _newDocumentCounter = 0; + + private StageInputViewModel(IMultiStageViewModelFactory multistageViewModelFactory, + IAdditionalJobInfoViewModel additionalJobInfoViewModel) : base(multistageViewModelFactory) + { + _documentType = XmlDocumentType.DeclarationJobData; + _additionalJobInfoViewModel = additionalJobInfoViewModel; + _additionalJobInfoViewModel.SetParent(this); + } + + + public StageInputViewModel(bool exemptedVehicle, IMultiStageViewModelFactory multiStageViewModelFactory, IAdditionalJobInfoViewModel additionalJobInfoViewModel) : this(multiStageViewModelFactory, additionalJobInfoViewModel) + { + _vehicleViewModel = _viewModelFactory.CreateStageInputVehicleViewModel( + exemptedVehicle + ? InterimStageBusVehicleViewModel_v2_8.VERSION_EXEMPTED + : InterimStageBusVehicleViewModel_v2_8.VERSION) as IMultistageVehicleViewModel; + + Title = "Edit Stage Input - New File"; + + _documentName = $"New {(exemptedVehicle ? "Exempted " : "")}Stage Input {++_newDocumentCounter}"; + Init(); + } + + public StageInputViewModel(IDeclarationInputDataProvider inputData, IMultiStageViewModelFactory multiStageViewModelFactory, IAdditionalJobInfoViewModel additionalJobInfoViewModel) : this(multiStageViewModelFactory,additionalJobInfoViewModel) + { + _documentName = inputData.JobInputData.JobName; + _vehicleViewModel = + _viewModelFactory.CreateStageInputVehicleViewModel(inputData.JobInputData.Vehicle) as IMultistageVehicleViewModel; + (_vehicleViewModel as InterimStageBusVehicleViewModel_v2_8).ShowConsolidatedData = false; + + _dataSource = inputData.DataSource; + + Title = $"Edit Stage Input - {Path.GetFileName(_dataSource.SourceFile)}"; + Init(); + } + + #region Overrides of StageViewModelBase + /// <summary> + /// Called in base class after input data is loaded. + /// </summary> + /// <param name="loadedInputData"></param> + protected override void LoadStageInputDataFollowUp(IDeclarationInputDataProvider loadedInputData) + { + DataSource = loadedInputData.DataSource; + UpdateTitle(); + DocumentName = loadedInputData.JobInputData.JobName; + } + + #endregion + + private void UpdateTitle() + { + Title = "Edit Stage Input - " + ((_dataSource?.SourceFile != null) + ? Path.GetFileName(_dataSource.SourceFile) + : "New File"); + } + + private void Init() + { + UpdateTitle(); + Components.Add("vehicle", VehicleViewModel as IViewModelBase); + Components.Add("auxiliaries", VehicleViewModel.MultistageAuxiliariesViewModel as IViewModelBase); + Components.Add("airdrag", VehicleViewModel.MultistageAirdragViewModel as IViewModelBase); + CurrentView = VehicleViewModel as IViewModelBase; + + ShowSaveAndCloseButtons = true; + } + + #region Implementation of IDocumentViewModel + + public string DocumentName + { + get => _documentName; + set => SetProperty(ref _documentName, value); + } + + public XmlDocumentType DocumentType => _documentType; + + public DataSource DataSource + { + get => _dataSource; + set + { + SetProperty(ref _dataSource, value); + UpdateTitle(); + } + } + + public IEditViewModel EditViewModel => this; + + public bool Selected + { + get => _selected && CanBeSimulated; + set => SetProperty(ref _selected, value); + } + + public bool CanBeSimulated + { + get => false; + set => throw new System.NotImplementedException(); + } + private IAdditionalJobInfoViewModel _additionalJobInfoViewModel; + public IAdditionalJobInfoViewModel AdditionalJobInfoVm + { + get => _additionalJobInfoViewModel; + set => SetProperty(ref _additionalJobInfoViewModel, value); + } + + #endregion + + #region Implementation of IEditViewModel + + public string Name => "Edit Stage Input"; + + #endregion + } +} \ No newline at end of file diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Implementation/StageViewModelBase.cs b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/StageViewModelBase.cs new file mode 100644 index 0000000000000000000000000000000000000000..b89f5f0265c4ff4f4a637fd03f979bf9c8b1fdf5 --- /dev/null +++ b/VECTO3GUI2020/ViewModel/MultiStage/Implementation/StageViewModelBase.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Windows; +using System.Windows.Input; +using System.Xml.Linq; +using Castle.Core.Internal; +using Ninject; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCore.InputData.FileIO.XML; +using TUGraz.VectoCore.Utils; +using VECTO3GUI2020.Helper; +using VECTO3GUI2020.Ninject; +using VECTO3GUI2020.Properties; +using VECTO3GUI2020.Util; +using VECTO3GUI2020.Util.XML; +using VECTO3GUI2020.ViewModel.Implementation.Common; +using VECTO3GUI2020.ViewModel.Interfaces.Common; +using VECTO3GUI2020.ViewModel.MultiStage.Interfaces; + +namespace VECTO3GUI2020.ViewModel.MultiStage.Implementation +{ + public interface IStageViewModelBase + { + string InputDataFilePath { get; set; } + IMultistageVehicleViewModel VehicleViewModel { get; set; } + ICommand SwitchComponentViewCommand { get; } + ICommand SaveInputDataCommand { get; } + ICommand SaveInputDataAsCommand { get; } + ICommand LoadVehicleDataCommand { get; } + bool ShowSaveAndCloseButtons { get; set; } + void SaveInputDataExecute(string filename); + bool LoadStageInputData(string fileName); + } + + public class StageViewModelBase : ViewModelBase, IStageViewModelBase + { + protected Dictionary<string, IViewModelBase> Components = + new Dictionary<string, IViewModelBase>(StringComparer.CurrentCultureIgnoreCase); + + protected IMultistageVehicleViewModel _vehicleViewModel; + protected IMultiStageViewModelFactory _viewModelFactory; + private IViewModelBase _currentview; + private ICommand _switchComponentViewCommand; + + [Inject] + public IMultistageDependencies MultistageDependencies + { + get => _multistageDependencies; + set => _multistageDependencies = value; + } + + [Inject] + public IXMLInputDataReader InputDataReader + { + get => _inputDataReader; + set => _inputDataReader = value; + } + + public StageViewModelBase(IMultiStageViewModelFactory viewModelFactory) + { + _viewModelFactory = viewModelFactory; + } + + public IViewModelBase CurrentView + { + get => _currentview; + set => SetProperty(ref _currentview, value); + } + + public IMultistageVehicleViewModel VehicleViewModel + { + get => _vehicleViewModel; + set => SetProperty(ref _vehicleViewModel, value); + } + + private bool _showSaveAndCloseButtons = false; + + public bool ShowSaveAndCloseButtons + { + get => _showSaveAndCloseButtons; + set => SetProperty(ref _showSaveAndCloseButtons, value); + } + + #region Commands + + public ICommand SwitchComponentViewCommand + { + get + { + return _switchComponentViewCommand ?? + new RelayCommand<string>(SwitchViewExecute, (string s) => SwitchViewCanExecute(s)); + } + } + + private void SwitchViewExecute(string viewToShow) + { + IViewModelBase newView; + var success = Components.TryGetValue(viewToShow, out newView); + if (success) { + CurrentView = newView; + } + } + + private bool SwitchViewCanExecute(string viewToShow) + { + return Components[viewToShow] != null; + } + + private ICommand _saveInputDataCommand; + private ICommand _saveInputDataAsCommand; + private IMultistageDependencies _multistageDependencies; + private IXMLInputDataReader _inputDataReader; + + public ICommand SaveInputDataCommand => + _saveInputDataCommand ?? + new RelayCommand(() => { SaveInputDataExecute(filename: _vehicleInputDataFilePath); }, + () => _vehicleInputDataFilePath != null); + + public ICommand SaveInputDataAsCommand => + _saveInputDataAsCommand ?? new RelayCommand(() => { SaveInputDataExecute(filename: null); }, () => true); + + + private ICommand _loadVehicleDataCommand; + private string _vehicleInputDataFilePath; + + + public ICommand LoadVehicleDataCommand + { + get { return _loadVehicleDataCommand ?? new RelayCommand(LoadVehicleDataExecute, () => true); } + } + + #endregion Commands + + #region File I/O + + private void LoadVehicleDataExecute() + { + var fileName = _multistageDependencies.DialogHelper.OpenXMLFileDialog(); + if (fileName == null) { + return; + } + + LoadStageInputData(fileName); + return; + } + + + + public void SaveInputDataExecute(string filename) + { + var dialogHelper = _multistageDependencies.DialogHelper; + if (VehicleViewModel.HasErrors) { + var errorMessage = "Vehicle\n"; + var vehicleErrorInfo = VehicleViewModel as IDataErrorInfo; + errorMessage += vehicleErrorInfo.Error.Replace(",", "\n"); + + + var auxiliariesErrorInfo = + VehicleViewModel.MultistageAuxiliariesViewModel as IDataErrorInfo; + if (auxiliariesErrorInfo != null && + !auxiliariesErrorInfo.Error.IsNullOrEmpty()) { + errorMessage += "\n Auxiliaries \n"; + errorMessage += auxiliariesErrorInfo.Error.Replace(",", "\n"); + } + + dialogHelper.ShowMessageBox(errorMessage, "Error", MessageBoxButton.OK, + MessageBoxImage.Error); + return; + } + + + if (filename == null) { + filename = dialogHelper.SaveToXMLDialog(Settings.Default.DefaultFilePath); + if (filename == null) { + return; + } + } + + var vehicleWriter = + _multistageDependencies.XMLWriterFactory.CreateVehicleWriter(VehicleViewModel); + + + + var xElement = vehicleWriter.GetElement(); + var xDoc = xElement.CreateWrapperDocument(XMLNamespaces.V28); + Debug.WriteLine(xElement.CreateWrapperDocument(XMLNamespaces.V28).ToString()); + + + var valid = false; + var validationError = ""; + try { + var validator = new XMLValidator(xDoc.ToXmlDocument()); + valid = validator.ValidateXML(XmlDocumentType.DeclarationJobData); + validationError = validator.ValidationError; + } catch (Exception e) { + dialogHelper.ShowMessageBox(messageBoxText: (e.Message + "\n" + e.InnerException), + caption: "Error saving File"); + } + + if (!valid) { + dialogHelper.ShowMessageBox($"Invalid Document: {validationError}", "Error"); + var tempFile = Path.GetTempFileName(); + try { + xDoc.Save(tempFile, SaveOptions.OmitDuplicateNamespaces); + LoadStageInputData(tempFile); + + } catch (Exception e) { + dialogHelper.ShowMessageBox(e.Message, "Error"); + throw; + } finally { + if (File.Exists(tempFile)) { + File.Delete(tempFile); + } + + ; + } + + + } else { + xDoc.Save(filename, SaveOptions.OmitDuplicateNamespaces); + LoadStageInputData(filename); + } + } + + public bool LoadStageInputData(string fileName) + { + try + { + var inputData = (IDeclarationInputDataProvider)_inputDataReader.Create(fileName); + var vehicleInputData = inputData.JobInputData.Vehicle; + VehicleViewModel.SetVehicleInputData(vehicleInputData); + InputDataFilePath = inputData.DataSource.SourceFile; + LoadStageInputDataFollowUp(inputData); + + + return true; + } + catch (Exception e) + { + _multistageDependencies.DialogHelper.ShowMessageBox(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); + return false; + } + return true; + } + + protected virtual void LoadStageInputDataFollowUp(IDeclarationInputDataProvider loadedInputData) + { + + } + + public string InputDataFilePath + { + get => _vehicleInputDataFilePath; + set => SetProperty(ref _vehicleInputDataFilePath, value); + } + + #endregion + + } + + +} \ No newline at end of file diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Interfaces/IMultiStageViewModelFactory.cs b/VECTO3GUI2020/ViewModel/MultiStage/Interfaces/IMultiStageViewModelFactory.cs index 90e54e472247409ce253f842c908ea3e585edc53..33cad2ad89c2b53d96dc056a0e7dad2cd348717b 100644 --- a/VECTO3GUI2020/ViewModel/MultiStage/Interfaces/IMultiStageViewModelFactory.cs +++ b/VECTO3GUI2020/ViewModel/MultiStage/Interfaces/IMultiStageViewModelFactory.cs @@ -5,31 +5,63 @@ using System.Text; using System.Threading.Tasks; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCore.Utils; +using VECTO3GUI2020.ViewModel.Implementation; using VECTO3GUI2020.ViewModel.Interfaces.Common; +using VECTO3GUI2020.ViewModel.Interfaces.Document; using VECTO3GUI2020.ViewModel.Interfaces.JobEdit.Vehicle; using VECTO3GUI2020.ViewModel.Interfaces.JobEdit.Vehicle.Components; using VECTO3GUI2020.ViewModel.MultiStage.Implementation; namespace VECTO3GUI2020.ViewModel.MultiStage.Interfaces { - public interface IMultiStageViewModelFactory + + public interface IMultiStageViewModelFactory : + IMultiStageViewModelFactoryDefaultInstanceProvider, + IMultiStageViewModelFactoryTypeAsNameInstanceProvider, + IMultistageViewModelFactoryFirstParameterAsNameInstanceProvider + { + + } + + + public interface IMultiStageViewModelFactoryTypeAsNameInstanceProvider + { + IDocumentViewModel CreateDocumentViewModel(IDeclarationInputDataProvider inputData); + IDocumentViewModel CreateDocumentViewModel(IInputDataProvider inputData); + IVehicleViewModel CreateStageInputVehicleViewModel(IVehicleDeclarationInputData inputData); + } + + public interface IMultistageViewModelFactoryFirstParameterAsNameInstanceProvider { + IVehicleViewModel CreateStageInputVehicleViewModel(string inputProviderType); + } + + + + public interface IMultiStageViewModelFactoryDefaultInstanceProvider + { + IDocumentViewModel GetStageInputViewModel(bool exemptedVehicle); IViewModelBase GetNewMultistageJobViewModel(); IMultiStageJobViewModel GetMultiStageJobViewModel(IMultistageBusInputDataProvider inputData); IVehicleViewModel GetInterimStageVehicleViewModel(); - IVehicleViewModel GetInterimStageVehicleViewModel(IVehicleDeclarationInputData consolidatedVehicleData); + IVehicleViewModel GetInterimStageVehicleViewModel(IVehicleDeclarationInputData consolidatedVehicleData, bool exempted); - IManufacturingStageViewModel GetManufacturingStageViewModel(IManufacturingStageInputData consolidatedManufacturingStageInputData); + IManufacturingStageViewModel GetManufacturingStageViewModel(IManufacturingStageInputData consolidatedManufacturingStageInputData, bool exempted); IMultistageAirdragViewModel GetMultistageAirdragViewModel(); IMultistageAirdragViewModel GetMultistageAirdragViewModel( IAirdragDeclarationInputData consolidatedAirdragInputData); + IMultistageAuxiliariesViewModel GetAuxiliariesViewModel(); IMultistageAuxiliariesViewModel GetAuxiliariesViewModel( IBusAuxiliariesDeclarationData consolidatedAuxiliariesInputData); + + ICreateVifViewModel GetCreateNewVifViewModel(bool completed); + ICreateVifViewModel GetCreateNewVifViewModel(); + //IViewModelBase CreateNewMultiStageJobViewModel(); //IMultiStageJobViewModel CreateMultiStageJobViewModel(string inputProviderType, IMultistageBusInputDataProvider inputData); diff --git a/VECTO3GUI2020/ViewModel/MultiStage/Interfaces/IMultistageAirdragViewModel.cs b/VECTO3GUI2020/ViewModel/MultiStage/Interfaces/IMultistageAirdragViewModel.cs index 865e3d14f189454ac9ff688b01ac2a99a07d5909..212b1af55307351c1bbe81092264be5e225196cc 100644 --- a/VECTO3GUI2020/ViewModel/MultiStage/Interfaces/IMultistageAirdragViewModel.cs +++ b/VECTO3GUI2020/ViewModel/MultiStage/Interfaces/IMultistageAirdragViewModel.cs @@ -9,10 +9,13 @@ namespace VECTO3GUI2020.ViewModel.MultiStage.Interfaces EventHandler AirdragViewModelChanged { get; set; } IAirDragViewModel AirDragViewModel { get; set; } + bool ShowConsolidatedData { get; set; } + void SetAirdragInputData(IAirdragDeclarationInputData airdragInputData); bool LoadAirdragFile(string fileName); void RestoreAirdragViewModel(); + void RemoveAirdragComponent(); } } \ No newline at end of file diff --git a/VECTO3GUI2020/Views/AboutView.xaml b/VECTO3GUI2020/Views/AboutView.xaml new file mode 100644 index 0000000000000000000000000000000000000000..fcd4e879bfb1a3419f7a2b9b508bd7fc6f2d175b --- /dev/null +++ b/VECTO3GUI2020/Views/AboutView.xaml @@ -0,0 +1,90 @@ +<UserControl x:Class="VECTO3GUI2020.Views.AboutView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:VECTO3GUI2020.Views" + mc:Ignorable="d" + d:DesignHeight="450" d:DesignWidth="800" MaxHeight="400"> + + + <Grid> + + <Grid.ColumnDefinitions> + <ColumnDefinition Width="5"/> + <ColumnDefinition/> + <ColumnDefinition Width="5"/> + </Grid.ColumnDefinitions> + + <Grid Grid.Column ="1"> + <Grid.RowDefinitions> + <RowDefinition Height="10"/> + <RowDefinition/> + <RowDefinition Height="38"/> + <RowDefinition Height="115"/> + <RowDefinition Height="30"/> + </Grid.RowDefinitions> + + <Grid Grid.Row="1"> + <Image HorizontalAlignment="Center" VerticalAlignment="Center"> + <Image.Source> + <BitmapImage UriSource="../Resources/Images/VECTO-About.png"/> + </Image.Source> + </Image> + </Grid> + + <Grid Grid.Row="2" Margin="0,5,0,0"> + <StackPanel Orientation="Vertical" HorizontalAlignment="Left" Margin="5,0,0,0"> + <TextBlock> + <Hyperlink NavigateUri="{Binding EUPLLink}" Command="{Binding EUPLLinkClickedCommand}"> + <TextBlock Text="VECTO is licensed under EUPL 1.1+"/> + </Hyperlink> + </TextBlock> + <TextBlock Text="Copyright © 2012-2019 European Union"/> + </StackPanel> + </Grid> + + <Grid Grid.Row="3"> + + <Grid.ColumnDefinitions> + <ColumnDefinition/> + <ColumnDefinition/> + </Grid.ColumnDefinitions> + + <Grid Grid.Column="0" Margin="10,30,0,0" > + <StackPanel Orientation="Vertical" HorizontalAlignment="Left"> + <TextBlock Text="Developed on behalf of the"/> + <TextBlock Text="European Commission DG CLIMA" Margin="20,0,0,0"/> + </StackPanel> + </Grid> + + <Grid Grid.Column="1"> + <Button Command="{Binding JrcPicClickedCommand}"> + <Button.Template> + <ControlTemplate> + <Image HorizontalAlignment="Center" VerticalAlignment="Center"> + <Image.Source> + <BitmapImage UriSource="../Resources/Images/JRC-About.png"/> + </Image.Source> + </Image> + </ControlTemplate> + </Button.Template> + </Button> + </Grid> + </Grid> + + <Grid Grid.Row="4"> + <StackPanel Orientation="Horizontal" Margin="10,0,0,0"> + <TextBlock Text="Support Contact:"/> + <TextBlock Margin="5,0,0,0"> + <Hyperlink NavigateUri="{Binding JRCMail}" Command="{Binding MailClickedCommand}" > + <TextBlock Text="jrc-vecto@ec.europa.eu"/> + </Hyperlink> + </TextBlock> + </StackPanel> + </Grid> + + </Grid> + + </Grid> +</UserControl> diff --git a/VECTO3GUI2020/Views/AboutView.xaml.cs b/VECTO3GUI2020/Views/AboutView.xaml.cs new file mode 100644 index 0000000000000000000000000000000000000000..6522582166d4bff97b380456d97dca9a5c5033eb --- /dev/null +++ b/VECTO3GUI2020/Views/AboutView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace VECTO3GUI2020.Views +{ + /// <summary> + /// Interaction logic for AboutView.xaml + /// </summary> + public partial class AboutView : UserControl + { + public AboutView() + { + InitializeComponent(); + } + } +} diff --git a/VECTO3GUI2020/Views/JoblistView.xaml b/VECTO3GUI2020/Views/JoblistView.xaml index d0f691c0a4e7068dd7a99da7317d765d81417634..d9c73bb7f46246d5fe7349a0abdae73987c541e2 100644 --- a/VECTO3GUI2020/Views/JoblistView.xaml +++ b/VECTO3GUI2020/Views/JoblistView.xaml @@ -4,45 +4,60 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:VECTO3GUI2020.Views" - xmlns:converter="clr-namespace:VECTO3GUI2020.Helper.Converter" xmlns:implementation="clr-namespace:VECTO3GUI2020.ViewModel.Implementation" d:DataContext="{d:DesignInstance Type=implementation:JobListViewModel}" + xmlns:converter="clr-namespace:VECTO3GUI2020.Helper.Converter" xmlns:implementation="clr-namespace:VECTO3GUI2020.ViewModel.Implementation" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" + xmlns:behavior="clr-namespace:VECTO3GUI2020.Behaviours" + xmlns:document="clr-namespace:VECTO3GUI2020.ViewModel.Interfaces.Document" + d:DataContext="{d:DesignInstance Type=implementation:JobListViewModel}" mc:Ignorable="d" AutomationProperties.Name="JobListView" d:DesignHeight="450" d:DesignWidth="1000"> + <Grid> <Grid.ColumnDefinitions> - <ColumnDefinition MinWidth="140" Width="1*"/> - <ColumnDefinition Name="MiddleColumn" Width="6*"/> - <ColumnDefinition MinWidth="140" Width="1*"/> + <ColumnDefinition Width="1*"/> </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="1*"/> + <RowDefinition Height="5"></RowDefinition> + <RowDefinition Height="1*" MinHeight="65"/> + </Grid.RowDefinitions> + + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition MinWidth="140" Width="1*"/> + <ColumnDefinition Width="6*"/> + <ColumnDefinition MinWidth="140" Width="1*"/> + </Grid.ColumnDefinitions> - <Border BorderBrush="Transparent" BorderThickness="1"> - <Grid> - <StackPanel HorizontalAlignment="Stretch"> - <Button x:Name="button" Margin="4" HorizontalAlignment="Stretch" + <Border BorderBrush="Transparent" BorderThickness="1"> + <Grid> + <StackPanel HorizontalAlignment="Stretch"> + <Button x:Name="button" Margin="4" HorizontalAlignment="Stretch" Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding SimulationCommand}">Simulation</Button> - <Button Margin="4" HorizontalAlignment="Stretch" + <Button Margin="4" HorizontalAlignment="Stretch" Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding CancelSimulation}">Stop</Button> - <Button x:Name="button1" Margin="4" HorizontalAlignment="Stretch" + <Button x:Name="button1" Margin="4" HorizontalAlignment="Stretch" Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding moveJobUp}" CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}">Up</Button> - <Button x:Name="button2" Margin="4" HorizontalAlignment="Stretch" + <Button x:Name="button2" Margin="4" HorizontalAlignment="Stretch" Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding moveJobDown}" CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}">Down</Button> - </StackPanel> - </Grid> - </Border> - <Grid Grid.Column="1"> - <Border BorderBrush="{StaticResource AccentColorButton}" BorderThickness="0" > - <DataGrid ItemsSource="{Binding Jobs}" - BorderBrush ="{StaticResource AccentColorButton}" BorderThickness="1" + </StackPanel> + </Grid> + </Border> + <Grid Grid.Column="1"> + <Border BorderBrush="{StaticResource AccentColorButton}" BorderThickness="0" > + <DataGrid ItemsSource="{Binding Jobs}" + BorderBrush ="{StaticResource AccentColorButton}" + BorderThickness="1 0 1 1" Name="JobDataGrid" HorizontalAlignment="Stretch" - CanUserReorderColumns="False" AutoGenerateColumns="False" SelectionMode="Single" @@ -55,54 +70,133 @@ AllowDrop="True" Drop="JobDataGrid_OnDrop" PreviewDrop = "JobDataGrid_OnPreviewDrop" ColumnHeaderStyle="{StaticResource JobListDataGridHeaderStyle}" - RowHeight="30" AlternatingRowBackground="LightGray" CellStyle="{DynamicResource DataGridCellStyle1}" + SelectedItem = "{Binding SelectedJob}" > - <DataGrid.Columns> - <DataGridCheckBoxColumn IsReadOnly="False" Header="Simulate" Binding="{Binding Selected}" Width="1*"></DataGridCheckBoxColumn> - <DataGridTextColumn IsReadOnly="True" Header="Name" Binding="{Binding DocumentName}" Width="4*"></DataGridTextColumn> - <DataGridTextColumn IsReadOnly ="True" Header="Type" Binding="{Binding DocumentType}" Width="4*"></DataGridTextColumn> - + <i:Interaction.Behaviors> + <behavior:AutoScrollDataGridBehaviour> + </behavior:AutoScrollDataGridBehaviour> + </i:Interaction.Behaviors> + + <!--CONTEXT MENU--> + + <!--<DataGrid.Resources> + <ContextMenu x:Key="RowMenu"> + <MenuItem Header="Edit WIP" Command="{Binding RowCopyCommand}" /> + <MenuItem Header="Show Source File"> + <MenuItem Header="Show in Explorer"></MenuItem> + </MenuItem> + </ContextMenu> + </DataGrid.Resources> + <DataGrid.RowStyle> + <Style TargetType="DataGridRow" > + <Setter Property="ContextMenu" Value="{StaticResource RowMenu}" /> + </Style> + </DataGrid.RowStyle>--> + <DataGrid.Columns> + <DataGridTemplateColumn Header="Simulate" Width="1*" MinWidth="50" IsReadOnly="False"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate DataType="document:IDocumentViewModel"> + <Grid> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="1*"/> + </Grid.ColumnDefinitions> + <CheckBox + HorizontalAlignment="Center" + IsEnabled="{Binding CanBeSimulated}" + Visibility="{Binding CanBeSimulated, + Converter={StaticResource BooleanToVisibilityConverter}}" + IsChecked="{Binding Selected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> + <Button Margin="0" + Padding="5" + Background="Transparent" + HorizontalAlignment="Center" + BorderThickness="0" + Grid.Column="0" + Command="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}, + Path=DataContext.OpenAdditionalJobInformationCommand}" + CommandParameter="{Binding }" + ContentTemplate="{DynamicResource InformationIcon}" + Visibility="{Binding CanBeSimulated, Converter={StaticResource InvertedBoolToVisibilityConverter}}"> + </Button> + </Grid> + + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTextColumn IsReadOnly="True" + Header="Name" + Binding="{Binding DocumentName}" + MinWidth="250" + Width="4*"></DataGridTextColumn> + <DataGridTextColumn IsReadOnly ="True" + Header="Type" + MinWidth="100" + Binding="{Binding DocumentType}" + Width="4*"></DataGridTextColumn> </DataGrid.Columns> - <DataGrid.RowDetailsTemplate> + + <DataGrid.RowDetailsTemplate> <DataTemplate> - <StackPanel Orientation="Vertical"> - <Label x:Name="label" Content="Filename"/> + <StackPanel Orientation="Vertical" Visibility="{Binding DataSource, Converter={StaticResource NullToVisibilityConverter}}"> + <!--<Label x:Name="label" Content="Filename"/>--> <TextBlock x:Name="textBlock" Text="{Binding DataSource.SourceFile}" TextWrapping="Wrap" Margin="10" /> </StackPanel> </DataTemplate> </DataGrid.RowDetailsTemplate> - <DataGrid.InputBindings> + <DataGrid.InputBindings> <MouseBinding MouseAction="LeftDoubleClick" - Command="{Binding EditJob}" + Command="{Binding EditDocument}" CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}"></MouseBinding> </DataGrid.InputBindings> </DataGrid> <!--<Label x:Name="label" Content="Loading . . ." Visibility="{Binding IsLoading, Converter={StaticResource BooleanToVisibilityConverter}}"/>--> - </Border> - </Grid> - <Grid Grid.Column="2"> - <Border BorderBrush="Transparent" BorderThickness="1"> - <StackPanel > - <Button x:Name="button3" Margin="4" HorizontalAlignment="Stretch" - Style="{StaticResource MultiStageButtonStyle1}" - Command="{Binding AddJobAsyncCommand}" Background="#FFDDDDDD"> - Add Job</Button> - <Button x:Name="button4" Margin ="4" HorizontalAlignment="Stretch" - Style="{StaticResource MultiStageButtonStyle1}" - Command="{Binding EditJob}" - CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}">Edit Job</Button> - <Button x:Name="button5" Margin="4" HorizontalAlignment="Stretch" - Style="{StaticResource MultiStageButtonStyle1}" - Command="{Binding NewManufacturingStageFile}" AutomationProperties.AutomationId="JobListViewNewManufacturingStageFileButton">New Multistage Job</Button> - <Button x:Name="button6" Margin="4" HorizontalAlignment="Stretch" - Style="{StaticResource MultiStageButtonStyle1}" - Command="{Binding RemoveJob}" - CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}">Remove Job</Button> - </StackPanel> - </Border> + </Border> + </Grid> + <Grid Grid.Column="2"> + <Border BorderBrush="Transparent" BorderThickness="1"> + <StackPanel > + <Button x:Name="button3" Margin="4" HorizontalAlignment="Stretch" + Style="{StaticResource MultiStageButtonStyle1}" + Command="{Binding AddJobAsyncCommand, IsAsync=True}" Background="#FFDDDDDD"> + Load File</Button> + <Button x:Name="button4" Margin ="4" HorizontalAlignment="Stretch" + Style="{StaticResource MultiStageButtonStyle1}" + Command="{Binding EditDocument}" + CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}">Edit Job</Button> + <!--<Button x:Name="newFileButton" Margin="4" HorizontalAlignment="Stretch" + Style="{StaticResource MultiStageButtonStyle1}" + Command="{Binding OpenPopUpCommand}">New File</Button> + <Popup HorizontalAlignment="Center" + x:Name="newFilePopup" + PlacementTarget="{Binding ElementName=newFileButton, Path=.}" + Margin="{Binding ElementName=newFileButton, Path=Margin}" + MinWidth="{Binding ElementName=newFileButton, Path=ActualWidth}" + IsOpen="{Binding NewFilePopUpIsOpen, Mode=TwoWay}" + StaysOpen="False" PreviewMouseLeftButtonUp="NewFilePopup_OnPreviewMouseLeftButtonDown"> + <Border BorderThickness="1px" BorderBrush="{StaticResource AccentColorButton}"> + <StackPanel Background="White"> + <Button Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding NewManufacturingStageFileCommand}">New Manufacturing Stage</Button> + <Button Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding NewVifCommand}">New VIF</Button> + <Button Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding NewCompletedInputCommand}">New Completed Input</Button> + <Button Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding NewExemptedCompletedInputCommand}">New Exempted Completed Input</Button> + </StackPanel> + </Border> + </Popup>--> + <Button x:Name="button6" Margin="4" HorizontalAlignment="Stretch" + Style="{StaticResource MultiStageButtonStyle1}" + Command="{Binding RemoveJob, IsAsync=True}" + CommandParameter="{Binding ElementName=JobDataGrid, Path=SelectedItem}">Remove Job</Button> + + + </StackPanel> + </Border> + </Grid> </Grid> + <GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" Height="5"/> + <ContentControl Grid.Row="2" Margin="0,0,0,0" Name="ContentControlBottom" Content="{Binding OutputViewModel }"/> </Grid> + </UserControl> diff --git a/VECTO3GUI2020/Views/JoblistView.xaml.cs b/VECTO3GUI2020/Views/JoblistView.xaml.cs index b64cacf114f17b87aeb375903b41251c696ad156..41d88075f3984bdac0119c4f1eb6061a775d71aa 100644 --- a/VECTO3GUI2020/Views/JoblistView.xaml.cs +++ b/VECTO3GUI2020/Views/JoblistView.xaml.cs @@ -1,7 +1,9 @@ -using System.Windows; +using System.Threading.Tasks; +using System.Windows; using System.Windows.Controls; +using System.Windows.Input; using VECTO3GUI2020.ViewModel.Implementation; -using VECTO3GUI2020.ViewModel.Interfaces; + namespace VECTO3GUI2020.Views { @@ -18,7 +20,7 @@ namespace VECTO3GUI2020.Views } - private void JobDataGrid_OnDrop(object sender, DragEventArgs e) + private async void JobDataGrid_OnDrop(object sender, DragEventArgs e) { var success = true; if (e.Data.GetDataPresent(DataFormats.FileDrop)) { @@ -27,7 +29,7 @@ namespace VECTO3GUI2020.Views var fileNames = e.Data.GetData(DataFormats.FileDrop, true) as string[]; if (fileNames != null) { foreach (var fileName in fileNames) { - ((JobListViewModel)this.DataContext).AddJobAsync(fileName); + await ((JobListViewModel)this.DataContext).AddJobAsync(fileName); } } diff --git a/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoStageInput.xaml b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoStageInput.xaml new file mode 100644 index 0000000000000000000000000000000000000000..5f16f70b3d55465a6ff25f717dfad5527db98ac6 --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoStageInput.xaml @@ -0,0 +1,12 @@ +<UserControl x:Class="VECTO3GUI2020.Views.Multistage.AdditionalJobInfoViews.AdditionalJobInfoStageInput" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:VECTO3GUI2020.Views.Multistage.AdditionalJobInfoViews" + mc:Ignorable="d" + d:DesignHeight="450" d:DesignWidth="800"> + <Grid> + <Label>This File cannot be simulated on its own.</Label> + </Grid> +</UserControl> diff --git a/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoStageInput.xaml.cs b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoStageInput.xaml.cs new file mode 100644 index 0000000000000000000000000000000000000000..61e43a35eacffeb6ceb270b1c7045e947146acac --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoStageInput.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace VECTO3GUI2020.Views.Multistage.AdditionalJobInfoViews +{ + /// <summary> + /// Interaction logic for AdditionalJobInfoStageInput.xaml + /// </summary> + public partial class AdditionalJobInfoStageInput : UserControl + { + public AdditionalJobInfoStageInput() + { + InitializeComponent(); + } + } +} diff --git a/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewMultiStage.xaml b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewMultiStage.xaml new file mode 100644 index 0000000000000000000000000000000000000000..8c2b7dab7ae5c40b2acc36b96d589112e4ca8b4c --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewMultiStage.xaml @@ -0,0 +1,41 @@ +<UserControl x:Class="VECTO3GUI2020.Views.Multistage.AdditionalJobInfoViews.AdditionalJobInfoViewMultiStage" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:VECTO3GUI2020.Views.Multistage.AdditionalJobInfoViews" + xmlns:common="clr-namespace:VECTO3GUI2020.ViewModel.Implementation.Common" + xmlns:resources="clr-namespace:System.Resources;assembly=mscorlib" + xmlns:properties="clr-namespace:VECTO3GUI2020.Properties" + mc:Ignorable="d" + d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance common:AdditionalJobInfoViewModelMultiStage }"> + <Grid> + <StackPanel Margin="10"> + <Label>This Job cannot be Simulated because the following Parameters are invalid:</Label> + <ItemsControl ItemsSource="{Binding InvalidEntries }"> + <ItemsControl.ItemTemplate> + <DataTemplate> + <BulletDecorator> + <BulletDecorator.Bullet> + <Ellipse HorizontalAlignment="Center" VerticalAlignment="Center" Height="5" Width="5" Fill="{DynamicResource AccentColorButton}"/> + </BulletDecorator.Bullet> + <TextBlock Margin="5 0"> + <TextBlock.Text> + <Binding Path="." Converter="{StaticResource PropertyNameToLabelConverter}"> + <Binding.ConverterParameter> + <x:Array Type="resources:ResourceManager"> + <x:Static MemberType="properties:GUILabels" Member="ResourceManager"/> + <x:Static MemberType="properties:BusStrings" Member="ResourceManager"/> + <x:Static MemberType="properties:Strings" Member="ResourceManager"/> + </x:Array> + </Binding.ConverterParameter> + </Binding> + </TextBlock.Text> + </TextBlock> + </BulletDecorator> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </StackPanel> + </Grid> +</UserControl> diff --git a/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewMultiStage.xaml.cs b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewMultiStage.xaml.cs new file mode 100644 index 0000000000000000000000000000000000000000..e284ba17aae6ecab1e2791d504a838f0c81af2c4 --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewMultiStage.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace VECTO3GUI2020.Views.Multistage.AdditionalJobInfoViews +{ + /// <summary> + /// Interaction logic for AdditionalJobInfoViewMultiStage.xaml + /// </summary> + public partial class AdditionalJobInfoViewMultiStage : UserControl + { + public AdditionalJobInfoViewMultiStage() + { + InitializeComponent(); + } + } +} diff --git a/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewNewVIF.xaml b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewNewVIF.xaml new file mode 100644 index 0000000000000000000000000000000000000000..c29c356e5347b11a23e59e5a6f67c0c75d97fca8 --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewNewVIF.xaml @@ -0,0 +1,41 @@ +<UserControl x:Class="VECTO3GUI2020.Views.Multistage.AdditionalJobInfoViews.AdditionalJobInfoViewNewVIF" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:VECTO3GUI2020.Views.Multistage.AdditionalJobInfoViews" + xmlns:properties="clr-namespace:VECTO3GUI2020.Properties" + xmlns:resources="clr-namespace:System.Resources;assembly=mscorlib" + mc:Ignorable="d" + d:DesignHeight="450" d:DesignWidth="800"> + <Grid> + <StackPanel Margin="10"> + <Label>This Job cannot be Simulated</Label> + <ItemsControl ItemsSource="{Binding InvalidEntries }"> + <ItemsControl.ItemTemplate> + <DataTemplate> + <BulletDecorator> + <BulletDecorator.Bullet> + <Ellipse HorizontalAlignment="Center" VerticalAlignment="Center" Height="5" Width="5" Fill="{DynamicResource AccentColorButton}"></Ellipse> + </BulletDecorator.Bullet> + <TextBlock Margin="5 0"> + <TextBlock.Text> + <Binding Path="." Converter="{StaticResource PropertyNameToLabelConverter}"> + <Binding.ConverterParameter> + <x:Array Type="resources:ResourceManager"> + <x:Static MemberType="properties:GUILabels" Member="ResourceManager"/> + <x:Static MemberType="properties:BusStrings" Member="ResourceManager"/> + <x:Static MemberType="properties:Strings" Member="ResourceManager"/> + </x:Array> + </Binding.ConverterParameter> + </Binding> + </TextBlock.Text> + </TextBlock> + + </BulletDecorator> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </StackPanel> + </Grid> +</UserControl> diff --git a/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewNewVIF.xaml.cs b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewNewVIF.xaml.cs new file mode 100644 index 0000000000000000000000000000000000000000..d1935b00b3ebabc94dd92c1fe37d4ef0a129bb8f --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/AdditionalJobInfoViews/AdditionalJobInfoViewNewVIF.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace VECTO3GUI2020.Views.Multistage.AdditionalJobInfoViews +{ + /// <summary> + /// Interaction logic for AdditionalJobInfoViewNewVIF.xaml + /// </summary> + public partial class AdditionalJobInfoViewNewVIF : UserControl + { + public AdditionalJobInfoViewNewVIF() + { + InitializeComponent(); + } + } +} diff --git a/VECTO3GUI2020/Views/Multistage/CreateVifView.xaml b/VECTO3GUI2020/Views/Multistage/CreateVifView.xaml new file mode 100644 index 0000000000000000000000000000000000000000..017e59827400afc8400c6f4232d93c000fe89738 --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/CreateVifView.xaml @@ -0,0 +1,83 @@ +<UserControl x:Class="VECTO3GUI2020.Views.Multistage.CreateVifView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:VECTO3GUI2020.Views.Multistage" + xmlns:customControls="clr-namespace:VECTO3GUI2020.Views.Multistage.CustomControls" + xmlns:implementation="clr-namespace:VECTO3GUI2020.ViewModel.Implementation" + xmlns:implementation1="clr-namespace:VECTO3GUI2020.ViewModel.MultiStage.Implementation" + mc:Ignorable="d" + MinWidth="500" + MinHeight="200" + d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance implementation1:CreateVifViewModel}"> + <Grid> + <DockPanel LastChildFill="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> + <!--<Label HorizontalAlignment="Center" DockPanel.Dock="Top" + Visibility="{Binding UnsavedChanges, + Converter={StaticResource BooleanToVisibilityConverter}}"> + There are unsaved changes + </Label>--> + <Grid DockPanel.Dock="Top" VerticalAlignment="Top"> + <Grid.RowDefinitions> + <RowDefinition></RowDefinition> + <RowDefinition></RowDefinition> + <RowDefinition></RowDefinition> + <RowDefinition></RowDefinition> + </Grid.RowDefinitions> + <Label Style="{DynamicResource LabelStyle1}">Select Primary Input</Label> + + <DockPanel Grid.Row="1" HorizontalAlignment="Stretch" DockPanel.Dock="Top"> + <Button DockPanel.Dock="Right" + Command="{Binding RemovePrimaryCommand}" + ContentTemplate="{StaticResource TrashIcon}" + Width="30" + Padding="4" + Margin="2 4"> + + </Button> + <customControls:FilePicker DockPanel.Dock="Left" HorizontalAlignment="Stretch" + Text="{Binding PrimaryInputPath}" + Command="{Binding SelectPrimaryInputFileCommand}"/> + + </DockPanel> + <Label Grid.Row="2" Style="{DynamicResource LabelStyle1}" + Visibility="{Binding Completed, + Converter={StaticResource InvertedBoolToVisibilityConverter}}">Select Interim Input</Label> + <Label Grid.Row="2" Style="{DynamicResource LabelStyle1}" + Visibility="{Binding Completed, + Converter={StaticResource BooleanToVisibilityConverter}}">Select Completed Input</Label> + <DockPanel Grid.Row="3" HorizontalAlignment="Stretch"> + <Button Command="{Binding RemoveStageInputCommand}" + DockPanel.Dock="Right" + ContentTemplate="{StaticResource TrashIcon}" + Width="30" + Padding="4" + Margin="2 4"> + + </Button> + <customControls:FilePicker DockPanel.Dock="Left" + Text="{Binding StageInputPath}" + Command="{Binding SelectCompletedInputFileCommand}"></customControls:FilePicker> + </DockPanel> + </Grid> + <DockPanel DockPanel.Dock="Bottom" LastChildFill="False"> + <UniformGrid DockPanel.Dock="Right" Rows="1" Width="500" HorizontalAlignment="Right"> + <Button Style="{StaticResource MultiStageButtonStyle1}">Create</Button> + <Button Style="{StaticResource MultiStageButtonStyle1}" + Command="{Binding SaveJobAsCommand}" + > + Save Job as ... + </Button> + <Button Style="{StaticResource MultiStageButtonStyle1}" + Command="{Binding SaveJobCommand}"> + Save Job + </Button> + <Button Style="{StaticResource MultiStageButtonStyle1}" + Command="{Binding CloseWindowCommand}" + CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">Close</Button> + </UniformGrid> + </DockPanel> + </DockPanel> + </Grid> +</UserControl> diff --git a/VECTO3GUI2020/Views/Multistage/CreateVifView.xaml.cs b/VECTO3GUI2020/Views/Multistage/CreateVifView.xaml.cs new file mode 100644 index 0000000000000000000000000000000000000000..70b55ddc961fa68e8de09e251524b3b7c550090e --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/CreateVifView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace VECTO3GUI2020.Views.Multistage +{ + /// <summary> + /// Interaction logic for CreateVifView.xaml + /// </summary> + public partial class CreateVifView : UserControl + { + public CreateVifView() + { + InitializeComponent(); + } + } +} diff --git a/VECTO3GUI2020/Views/Multistage/CustomControls/FilePicker.xaml b/VECTO3GUI2020/Views/Multistage/CustomControls/FilePicker.xaml index 614ebbf578717fae433d5e08887404b7c31095a6..31afd998057d63816e703fe626eff8fee935105a 100644 --- a/VECTO3GUI2020/Views/Multistage/CustomControls/FilePicker.xaml +++ b/VECTO3GUI2020/Views/Multistage/CustomControls/FilePicker.xaml @@ -17,9 +17,15 @@ <TextBox x:Name="textBox" VerticalContentAlignment="Center" Padding="4" Margin = "0 0 0 0" IsReadOnly="True" Text="{Binding Text, ElementName=filepickercustomcontrol}" HorizontalAlignment="Stretch" TextWrapping="Wrap" Style="{DynamicResource TextBoxStyle1}"/> - <Button x:Name="button" Padding="4" Margin="4 0 0 0" Grid.Column="1" ContentTemplate="{DynamicResource AddDocumentIcon}" + <Button x:Name="button" Padding="4" Margin="4 0 0 0" Grid.Column="1" Command="{Binding Command, ElementName=filepickercustomcontrol}" Style="{DynamicResource FilePickerButtonStyle}"> - + <Button.ContentTemplate> + <Binding Path="ButtonContentTemplate" ElementName="filepickercustomcontrol" Converter="{StaticResource NullToUnsetValue}"> + <Binding.FallbackValue> + <StaticResource ResourceKey="AddDocumentIcon"></StaticResource> + </Binding.FallbackValue> + </Binding> + </Button.ContentTemplate> </Button> </Grid> </UserControl> diff --git a/VECTO3GUI2020/Views/Multistage/CustomControls/FilePicker.xaml.cs b/VECTO3GUI2020/Views/Multistage/CustomControls/FilePicker.xaml.cs index 8fe20e035718c3aed625d9204a7007086d28dae3..6c7de5effe5ecc2f774e384ac89ddf77d2e272dc 100644 --- a/VECTO3GUI2020/Views/Multistage/CustomControls/FilePicker.xaml.cs +++ b/VECTO3GUI2020/Views/Multistage/CustomControls/FilePicker.xaml.cs @@ -20,6 +20,15 @@ namespace VECTO3GUI2020.Views.Multistage.CustomControls /// </summary> public partial class FilePicker : UserControl { + public static readonly DependencyProperty ButtonContentTemplateProperty = DependencyProperty.Register( + "ButtonContentTemplate", typeof(DataTemplate), typeof(FilePicker), new PropertyMetadata(default(DataTemplate))); + + public DataTemplate ButtonContentTemplate + { + get { return (DataTemplate)GetValue(ButtonContentTemplateProperty); } + set { SetValue(ButtonContentTemplateProperty, value); } + } + public static readonly DependencyProperty CommandProperty = DependencyProperty.Register( "Command", typeof(ICommand), typeof(FilePicker), new PropertyMetadata(default(ICommand))); diff --git a/VECTO3GUI2020/Views/Multistage/CustomControls/InputStageView.xaml b/VECTO3GUI2020/Views/Multistage/CustomControls/InputStageView.xaml new file mode 100644 index 0000000000000000000000000000000000000000..ac1d32d1a0a497cb65e7c030417dbbeec6ff2a7f --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/CustomControls/InputStageView.xaml @@ -0,0 +1,12 @@ +<UserControl x:Class="VECTO3GUI2020.Views.Multistage.CustomControls.InputStageView" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:VECTO3GUI2020.Views.Multistage.CustomControls" + mc:Ignorable="d" + d:DesignHeight="450" d:DesignWidth="800"> + <Grid> + + </Grid> +</UserControl> diff --git a/VECTO3GUI2020/Views/Multistage/CustomControls/InputStageView.xaml.cs b/VECTO3GUI2020/Views/Multistage/CustomControls/InputStageView.xaml.cs new file mode 100644 index 0000000000000000000000000000000000000000..faa68ed735d38ebcb05a7edf73beda7ec987a2f0 --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/CustomControls/InputStageView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace VECTO3GUI2020.Views.Multistage.CustomControls +{ + /// <summary> + /// Interaction logic for InputStageView.xaml + /// </summary> + public partial class InputStageView : UserControl + { + public InputStageView() + { + InitializeComponent(); + } + } +} diff --git a/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterCheckBoxView.xaml b/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterCheckBoxView.xaml index 08282aadb40ed4c467e1203e425d931f7078a23d..60b14141332c3418a4f0831e2f85d4b887bf0ac0 100644 --- a/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterCheckBoxView.xaml +++ b/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterCheckBoxView.xaml @@ -33,7 +33,8 @@ <CheckBox x:Name="checkBox" Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center" IsTabStop="False" IsChecked="{Binding Path=PreviousContent, - Converter={StaticResource XToBoolConverter}}" IsEnabled="False"> + Converter={StaticResource XToBoolConverter}}" IsEnabled="False" + Visibility="{Binding ShowConsolidatedData, Converter={StaticResource BooleanToVisibilityConverter}}"> </CheckBox> <CheckBox x:Name="checkBox1" Grid.Column="3" VerticalAlignment="Center" HorizontalAlignment="Center" diff --git a/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterComboBoxView.xaml b/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterComboBoxView.xaml index 04884c5f67220fc0b9dafa6482d300983964c6d6..0347fbf21fb57b612be479ddd21ca9f4b83c38a7 100644 --- a/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterComboBoxView.xaml +++ b/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterComboBoxView.xaml @@ -5,23 +5,10 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:VECTO3GUI2020.Views.Multistage.CustomControls" xmlns:helper="clr-namespace:VECTO3GUI2020.Helper" + xmlns:implementation="clr-namespace:VECTO3GUI2020.ViewModel.MultiStage.Implementation" mc:Ignorable="d" - d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance helper:MultistageParameterViewModel }" x:Name="ComboboxView"> + d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance implementation:MultistageParameterViewModel }" x:Name="ComboboxView"> <Grid> - <!--<Grid> - <Grid.ColumnDefinitions> - --><!--<ColumnDefinition Width="4*" SharedSizeGroup="W"/> - <ColumnDefinition Width="1*" SharedSizeGroup="N"/> - <ColumnDefinition Width="4*" SharedSizeGroup="W"/> - <ColumnDefinition Width="4*" SharedSizeGroup="W"/> - <ColumnDefinition Width="1*" SharedSizeGroup="N"/>--><!-- - <ColumnDefinition SharedSizeGroup=""></ColumnDefinition> - <ColumnDefinition SharedSizeGroup=""></ColumnDefinition> - <ColumnDefinition SharedSizeGroup=""></ColumnDefinition> - <ColumnDefinition SharedSizeGroup=""></ColumnDefinition> - <ColumnDefinition SharedSizeGroup=""></ColumnDefinition> - </Grid.ColumnDefinitions>--> - <UniformGrid Rows="1" Margin="0 0 10 2"> <DockPanel Margin="5 0"> <Label x:Name="label1" DockPanel.Dock="Left"> @@ -37,7 +24,7 @@ Mode=TwoWay}" Checked="CheckBoxCombo_OnChecked"/> </DockPanel> <ComboBox x:Name="comboBox" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="2 0 2 0" IsTabStop="False" - Visibility="{Binding Optional, + Visibility="{Binding ShowConsolidatedData, Converter={StaticResource BooleanToVisibilityConverter}}" IsHitTestVisible="False" Focusable="False" IsEditable="False" SelectedValue="{Binding PreviousContent, Mode=TwoWay}" ItemsSource="{Binding GeneratedListItems}"> @@ -72,8 +59,6 @@ </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> - - </DockPanel> </UniformGrid> </Grid> diff --git a/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterTextView.xaml b/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterTextView.xaml index 67bba1d5e8f6ad9eeb7a5dd18cce77b480c96bc1..64b8183e6e57f186c43882a9a90a5acdfbc2a6cb 100644 --- a/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterTextView.xaml +++ b/VECTO3GUI2020/Views/Multistage/CustomControls/MultistageParameterTextView.xaml @@ -36,7 +36,7 @@ Converter={StaticResource SIValueToStringConverter}}" Style="{DynamicResource TextBoxStyle1}" - Visibility="{Binding Optional, + Visibility="{Binding ShowConsolidatedData, Converter={StaticResource BooleanToVisibilityConverter}, UpdateSourceTrigger=PropertyChanged}"/> <DockPanel> diff --git a/VECTO3GUI2020/Views/Multistage/ManufacturingStageAuxiliariesView.xaml b/VECTO3GUI2020/Views/Multistage/ManufacturingStageAuxiliariesView.xaml index ec56c6569599d4ddea8043b81f2840a355aaa1ef..65740ac709baf4f651bc795bcd379721b38d20e1 100644 --- a/VECTO3GUI2020/Views/Multistage/ManufacturingStageAuxiliariesView.xaml +++ b/VECTO3GUI2020/Views/Multistage/ManufacturingStageAuxiliariesView.xaml @@ -41,37 +41,39 @@ <Border Margin="5 0" BorderBrush="{DynamicResource ButtonHighlightColor}" BorderThickness="2" > <StackPanel Margin="0"> <Label Margin="0" Style="{DynamicResource LabelStyle1}">Heat Pumps Passenger Compartment</Label> - <Label Padding="10 4 0 4" Style="{DynamicResource LabelStyle1}">Consolidated Data</Label> - <ItemsControl AlternationCount="2" - Visibility="{Binding ConsolidatedHeatPumpConfigurationsPassenger, Converter={StaticResource NullToVisibilityConverter}}" - ItemsSource="{Binding ConsolidatedHeatPumpConfigurationsPassenger}" - HorizontalContentAlignment="Stretch" - Padding="5 5 29 5 " > - <ItemsControl.ItemTemplate> - <DataTemplate> - <Border BorderThickness="1"> - <DockPanel LastChildFill="true" x:Name="ItemsDockPanel"> - <UniformGrid DockPanel.Dock="Left" Columns="2"> - <ContentControl Grid.Column="0" DockPanel.Dock="Top" Content="{Binding Path=HeatPumpTypeVM}"/> - <ContentControl Grid.Column="1" DockPanel.Dock="Top" Content="{Binding Path=HeatPumpModeVM}"/> - </UniformGrid> - </DockPanel> - </Border> - <DataTemplate.Triggers> - <Trigger Property="ItemsControl.AlternationIndex" Value="0"> - <Setter Property="Background" Value="White" TargetName="ItemsDockPanel"/> - </Trigger> - <Trigger Property="ItemsControl.AlternationIndex" Value="1"> - <Setter Property="Background" Value="LightGray" TargetName="ItemsDockPanel"/> - </Trigger> - </DataTemplate.Triggers> - </DataTemplate> - </ItemsControl.ItemTemplate> - </ItemsControl> - <Label Visibility="{Binding ConsolidatedHeatPumpConfigurationsPassenger, - Converter={StaticResource NullToVisibilityConverter}, - ConverterParameter=invert}" - HorizontalAlignment="Center">No consolidated data available</Label> + <StackPanel Visibility="{Binding ShowConsolidatedData, Converter={StaticResource BooleanToVisibilityConverter}}"> + <Label Padding="10 4 0 4" Style="{DynamicResource LabelStyle1}">Consolidated Data</Label> + <ItemsControl AlternationCount="2" + Visibility="{Binding ConsolidatedHeatPumpConfigurationsPassenger, Converter={StaticResource NullToVisibilityConverter}}" + ItemsSource="{Binding ConsolidatedHeatPumpConfigurationsPassenger}" + HorizontalContentAlignment="Stretch" + Padding="5 5 29 5 " > + <ItemsControl.ItemTemplate> + <DataTemplate> + <Border BorderThickness="1"> + <DockPanel LastChildFill="true" x:Name="ItemsDockPanel"> + <UniformGrid DockPanel.Dock="Left" Columns="2"> + <ContentControl Grid.Column="0" DockPanel.Dock="Top" Content="{Binding Path=HeatPumpTypeVM}"/> + <ContentControl Grid.Column="1" DockPanel.Dock="Top" Content="{Binding Path=HeatPumpModeVM}"/> + </UniformGrid> + </DockPanel> + </Border> + <DataTemplate.Triggers> + <Trigger Property="ItemsControl.AlternationIndex" Value="0"> + <Setter Property="Background" Value="White" TargetName="ItemsDockPanel"/> + </Trigger> + <Trigger Property="ItemsControl.AlternationIndex" Value="1"> + <Setter Property="Background" Value="LightGray" TargetName="ItemsDockPanel"/> + </Trigger> + </DataTemplate.Triggers> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + <Label Visibility="{Binding ConsolidatedHeatPumpConfigurationsPassenger, + Converter={StaticResource NullToVisibilityConverter}, + ConverterParameter=invert}" + HorizontalAlignment="Center">No consolidated data available</Label> + </StackPanel> <DockPanel LastChildFill="true"> <Button DockPanel.Dock="right" ContentTemplate="{DynamicResource AddIcon}" Command="{Binding AddPassengerHeatpumpCommand}"> diff --git a/VECTO3GUI2020/Views/Multistage/ManufacturingStageView.xaml b/VECTO3GUI2020/Views/Multistage/ManufacturingStageView.xaml index 9d8137454ca38e97b76c0d0a162239683443eb07..5d2b36a12ff695c078b2556ef598269eec531d19 100644 --- a/VECTO3GUI2020/Views/Multistage/ManufacturingStageView.xaml +++ b/VECTO3GUI2020/Views/Multistage/ManufacturingStageView.xaml @@ -4,32 +4,56 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:VECTO3GUI2020.Views.Multistage" - xmlns:implementation="clr-namespace:VECTO3GUI2020.ViewModel.MultiStage.Implementation" + xmlns:implementation="clr-namespace:VECTO3GUI2020.ViewModel.MultiStage.Implementation" + xmlns:system="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance implementation:ManufacturingStageViewModel_v0_1 }"> <Grid> <DockPanel> - <Grid Margin="4" DockPanel.Dock="Top"> - <Grid.ColumnDefinitions> - <ColumnDefinition></ColumnDefinition> - <ColumnDefinition Width="30px"></ColumnDefinition> - </Grid.ColumnDefinitions> - </Grid> - <DockPanel Grid.Row="1" LastChildFill="False" DockPanel.Dock="Top" > - <Button Width="100" DockPanel.Dock="Left" Style="{DynamicResource MultiStageButtonStyle1}" - Margin="4" Command="{Binding SwitchComponentViewCommand}" CommandParameter="Vehicle">Vehicle</Button> - <Button Width="100" DockPanel.Dock="Left" Style="{DynamicResource MultiStageButtonStyle1}" - Margin="4" Command="{Binding SwitchComponentViewCommand}" CommandParameter="Airdrag">Airdrag</Button> - <Button Width="100" DockPanel.Dock="Left" Style="{DynamicResource MultiStageButtonStyle1}" - Margin="4" Command="{Binding SwitchComponentViewCommand}" CommandParameter="Auxiliaries">Auxiliaries</Button> - <StackPanel Orientation="Horizontal" DockPanel.Dock="Right"> - <Label>Manufacturing Stage</Label> - <Label Content="{Binding StageCount}"/> + + <DockPanel DockPanel.Dock="Top" LastChildFill="False"> + <UniformGrid DockPanel.Dock="Left" Width="350" Rows="1" HorizontalAlignment="Left"> + <Button Style="{DynamicResource MultiStageButtonStyle1}" + Margin="4" Command="{Binding SwitchComponentViewCommand}" CommandParameter="Vehicle">Vehicle</Button> + <Button Style="{DynamicResource MultiStageButtonStyle1}" + Margin="4" Command="{Binding SwitchComponentViewCommand}" CommandParameter="Airdrag">Airdrag</Button> + <Button Style="{DynamicResource MultiStageButtonStyle1}" + Margin="4" Command="{Binding SwitchComponentViewCommand}" CommandParameter="Auxiliaries">Auxiliaries</Button> + </UniformGrid> + <StackPanel Orientation="Horizontal" DockPanel.Dock="Right" Margin="0 10 20 10" > + <StackPanel.Visibility> + <PriorityBinding> + <Binding Path="StageCount" Converter="{StaticResource AlwaysVisibleConverter}"/> + <Binding> + <Binding.Source> + <Visibility>Collapsed</Visibility> + </Binding.Source> + </Binding> + </PriorityBinding> + </StackPanel.Visibility> + <Label>Manufacturing Stage</Label> + <Label> + <PriorityBinding> + <Binding Path="StageCount"></Binding> + <Binding > + </Binding> + </PriorityBinding> + </Label> </StackPanel> - + + </DockPanel> - <ContentControl DockPanel.Dock="Top" Content="{Binding CurrentView}"/> + <UniformGrid Rows="1" Width="350" DockPanel.Dock="Bottom" HorizontalAlignment="Right" + Visibility="{Binding ShowSaveAndCloseButtons, + Converter={StaticResource BooleanToVisibilityConverter}}"> + <Button Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding SaveInputDataCommand}">Save</Button> + <Button Style="{StaticResource MultiStageButtonStyle1}" Command="{Binding SaveInputDataAsCommand}">Save As ...</Button> + <Button Style="{StaticResource MultiStageButtonStyle1}" + Command="{Binding CloseWindowCommand}" + CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">Close</Button> + </UniformGrid> + <ContentControl DockPanel.Dock="Top" ContentTemplateSelector="{StaticResource MultistageVehicleDataTemplateSelector}" Content="{Binding CurrentView}"/> </DockPanel> </Grid> </UserControl> diff --git a/VECTO3GUI2020/Views/Multistage/MultiStageView.xaml b/VECTO3GUI2020/Views/Multistage/MultiStageView.xaml index 449554b41c18f989dc1709a95bfe4b9e3eedfd0e..46ff212b1a4d0f52cd7afbfe3968bc0a42751cb8 100644 --- a/VECTO3GUI2020/Views/Multistage/MultiStageView.xaml +++ b/VECTO3GUI2020/Views/Multistage/MultiStageView.xaml @@ -13,9 +13,10 @@ <customControls:FilePicker DockPanel.Dock="Top" Command="{Binding LoadVehicleDataCommand}" - Text="{Binding VehicleInputDataFilePath, TargetNullValue=Select Vehicle Input Data . . .}"></customControls:FilePicker> + Text="{Binding VehicleInputDataFilePath, TargetNullValue=Select Vehicle Input Data . . .}"/> + <Label DockPanel.Dock="Top" HorizontalAlignment="Center" Visibility="{Binding Exempted, Converter={StaticResource BooleanToVisibilityConverter}}">Exempted Vehicle</Label> <Border BorderThickness="1" BorderBrush="{DynamicResource ButtonHighlightColor}" Height="40" DockPanel.Dock="Bottom"> - <DockPanel LastChildFill="False"> + <DockPanel LastChildFill="False" DockPanel.Dock="Bottom"> <Button DockPanel.Dock="Right" Width="100" Command="{Binding CloseWindowCommand}" @@ -35,18 +36,18 @@ Style="{DynamicResource MultiStageButtonStyle1}" Margin="4" Padding="4" - Command="{Binding SaveInputDataCommand}">Save Input</Button> + Command="{Binding ManufacturingStageViewModel.SaveInputDataCommand}">Save Input</Button> <Button DockPanel.Dock="Right" Width="100" Style="{DynamicResource MultiStageButtonStyle1}" Margin="4" Padding="4" - Command="{Binding SaveInputDataAsCommand}">Save Input As ... </Button> + Command="{Binding ManufacturingStageViewModel.SaveInputDataAsCommand}">Save Input As ... </Button> </DockPanel> </Border> <ContentControl DockPanel.Dock="Top" Content="{Binding ManufacturingStageViewModel}"/> - + </DockPanel> </Grid> </UserControl> diff --git a/VECTO3GUI2020/Views/Multistage/MultistageAirDragView.xaml b/VECTO3GUI2020/Views/Multistage/MultistageAirDragView.xaml index 2b7cf405dff4475dcd99a4fea093e590e40558b9..a6da16c578fe90ad63b3f2c3cf0786a1fa932b80 100644 --- a/VECTO3GUI2020/Views/Multistage/MultistageAirDragView.xaml +++ b/VECTO3GUI2020/Views/Multistage/MultistageAirDragView.xaml @@ -30,6 +30,8 @@ </DockPanel> <StackPanel HorizontalAlignment="Stretch" Margin="4" > + <StackPanel Visibility="{Binding ShowConsolidatedData, + Converter={StaticResource BooleanToVisibilityConverter}}"> <Label Style="{DynamicResource LabelStyle1}">Consolidated Airdrag Data</Label> <StackPanel Visibility="{Binding ConsolidatedAirdragData, Converter={StaticResource NullToVisibilityConverter}}"> <customControlsMultistage:LabledTextBoxMultistage Content="{Binding ConsolidatedAirdragData.Manufacturer, Mode=OneWay}" ReadOnly="True"/> @@ -37,6 +39,7 @@ <customControlsMultistage:LabledTextBoxMultistage Content="{Binding ConsolidatedAirdragData.AirDragArea, Mode=OneWay}" ReadOnly="True"/> </StackPanel> <Label Visibility="{Binding ConsolidatedAirdragData, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=invert}">No data set</Label> + </StackPanel> <Label Style="{DynamicResource LabelStyle1}">Data from File</Label> <ContentControl Content="{Binding AirDragViewModel}" Visibility="{Binding AirDragViewModel, Converter={StaticResource NullToVisibilityConverter}}"> diff --git a/VECTO3GUI2020/Views/Multistage/NewMultistageFileView.xaml b/VECTO3GUI2020/Views/Multistage/NewMultistageFileView.xaml index 6a1b5a60b56e2d1d75ddb51485e77be92c81ed8f..b8e27af00a50661acf11845f1c8a689339c3b751 100644 --- a/VECTO3GUI2020/Views/Multistage/NewMultistageFileView.xaml +++ b/VECTO3GUI2020/Views/Multistage/NewMultistageFileView.xaml @@ -12,7 +12,7 @@ <Grid MaxWidth="900"> <DockPanel> <Grid DockPanel.Dock="Top"> - <customControls:FilePicker x:Name="NewMultistageFilePicker" Grid.Row="0" Text="{Binding VifPath}" HorizontalAlignment="Stretch" Command="{Binding AddVifFile}"/> + <customControls:FilePicker x:Name="NewMultistageFilePicker" Grid.Row="0" Text="{Binding VifPath}" HorizontalAlignment="Stretch" Command="{Binding AddVifFileCommand}"/> </Grid> <Button Style="{DynamicResource MultiStageButtonStyle1}" Margin="4" DockPanel.Dock="Bottom" diff --git a/VECTO3GUI2020/Views/Multistage/VehicleView_v2_8.xaml b/VECTO3GUI2020/Views/Multistage/VehicleView_v2_8.xaml index 99ef7e8b6b34a4334df68cbb32b3faacb0f29968..eef272c305d14f887a9d213780fe1a8121784336 100644 --- a/VECTO3GUI2020/Views/Multistage/VehicleView_v2_8.xaml +++ b/VECTO3GUI2020/Views/Multistage/VehicleView_v2_8.xaml @@ -7,15 +7,10 @@ xmlns:custom="clr-namespace:VECTO3GUI2020.Views.Multistage.CustomControls" xmlns:implementation="clr-namespace:VECTO3GUI2020.ViewModel.MultiStage.Implementation" xmlns:properties="clr-namespace:VECTO3GUI2020.Properties" xmlns:resources="clr-namespace:System.Resources;assembly=mscorlib" - d:DataContext="{d:DesignInstance Type=implementation:DeclarationInterimStageBusVehicleViewModel_v2_8}" + d:DataContext="{d:DesignInstance Type=implementation:InterimStageBusVehicleViewModel_v2_8}" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" BorderBrush="{DynamicResource ButtonHighlightColor}" BorderThickness="2px" Margin="4px"> <UserControl.Resources> - <Style TargetType="custom:MultiStageParameter"> - <Setter Property="NameLookUpResourceManager" Value="{x:Static properties:BusStrings.ResourceManager}"/> - <Setter Property="Validation.ErrorTemplate" Value="{StaticResource multistageParameterControlErrorTemplate}"/> - </Style> - <Style TargetType="ContentControl"> <Setter Property="ContentTemplateSelector" Value="{DynamicResource MultistageParameterTemplateSelector}"/> <Setter Property="IsTabStop" Value="False"></Setter> @@ -32,12 +27,8 @@ Style="{DynamicResource LabelStyle1}"/> - <ContentControl Content="{Binding ParameterViewModels[Manufacturer]}" > - </ContentControl> - - + <ContentControl Content="{Binding ParameterViewModels[Manufacturer]}"/> <ContentControl Content="{Binding ParameterViewModels[ManufacturerAddress]}"/> - <ContentControl Content="{Binding ParameterViewModels[VIN]}"/> diff --git a/VECTO3GUI2020/Views/Multistage/VehicleView_v2_8_exempted.xaml b/VECTO3GUI2020/Views/Multistage/VehicleView_v2_8_exempted.xaml new file mode 100644 index 0000000000000000000000000000000000000000..e3f52ba7dbc010f5226c8134035eb564a88b0d24 --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/VehicleView_v2_8_exempted.xaml @@ -0,0 +1,55 @@ +<UserControl x:Class="VECTO3GUI2020.Views.Multistage.VehicleView_v2_8_exempted" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:VECTO3GUI2020.Views.Multistage" + mc:Ignorable="d" + d:DesignHeight="450" d:DesignWidth="800"> + <UserControl.Resources> + <Style TargetType="ContentControl"> + <Setter Property="ContentTemplateSelector" Value="{DynamicResource MultistageParameterTemplateSelector}"/> + <Setter Property="IsTabStop" Value="False"></Setter> + </Style> + </UserControl.Resources> + <Grid> + <ScrollViewer> + <DockPanel> + <StackPanel> + <Label Content="VEHICLE DATA" HorizontalAlignment="Stretch" FontSize="15" VerticalAlignment="Stretch" + Style="{DynamicResource LabelStyle1}"/> + + + <ContentControl Content="{Binding ParameterViewModels[Manufacturer]}"/> + <ContentControl Content="{Binding ParameterViewModels[ManufacturerAddress]}"/> + <ContentControl Content="{Binding ParameterViewModels[VIN]}"/> + <ContentControl Content="{Binding ParameterViewModels[Model]}"/> + <ContentControl Content="{Binding ParameterViewModels[LegislativeClass]}"/> + <ContentControl Content="{Binding ParameterViewModels[CurbMassChassis]}"/> + <ContentControl Content="{Binding ParameterViewModels[GrossVehicleMassRating]}"/> + <ContentControl Content="{Binding ParameterViewModels[RegisteredClass]}"/> + <ContentControl + Content="{Binding ParameterViewModels[VehicleCode]}"/> + <ContentControl + Content="{Binding ParameterViewModels[LowEntry]}"/> + <ContentControl + Content="{Binding ParameterViewModels[HeightInMm]}"/> + + <Label Style="{DynamicResource LabelStyle1}">Number of Passengers</Label> + + <ContentControl + Content="{Binding ParameterViewModels[NumberPassengerSeatsLowerDeck]}"/> + <ContentControl + Content="{Binding ParameterViewModels[NumberPassengersStandingLowerDeck]}"/> + <ContentControl + Content="{Binding ParameterViewModels[NumberPassengerSeatsUpperDeck]}"/> + <ContentControl + Content="{Binding ParameterViewModels[NumberPassengersStandingUpperDeck]}"/> + + + + </StackPanel> + </DockPanel> + </ScrollViewer> + </Grid> +</UserControl> diff --git a/VECTO3GUI2020/Views/Multistage/VehicleView_v2_8_exempted.xaml.cs b/VECTO3GUI2020/Views/Multistage/VehicleView_v2_8_exempted.xaml.cs new file mode 100644 index 0000000000000000000000000000000000000000..56db7aca7d57d6cf53f94e4baea20e5833ba72f7 --- /dev/null +++ b/VECTO3GUI2020/Views/Multistage/VehicleView_v2_8_exempted.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace VECTO3GUI2020.Views.Multistage +{ + /// <summary> + /// Interaction logic for VehicleView_v2_8_exempted.xaml + /// </summary> + public partial class VehicleView_v2_8_exempted : UserControl + { + public VehicleView_v2_8_exempted() + { + InitializeComponent(); + } + } +} diff --git a/VECTO3GUI2020/Views/OutputView.xaml b/VECTO3GUI2020/Views/OutputView.xaml index 7f8015871ae09214136d3b87940a49dff23249c6..0f988ee09b50fd530bb0a15e578781f276cec587 100644 --- a/VECTO3GUI2020/Views/OutputView.xaml +++ b/VECTO3GUI2020/Views/OutputView.xaml @@ -3,11 +3,13 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:local="clr-namespace:VECTO3GUI2020.Views" xmlns:impl="clr-namespace:VECTO3GUI2020.ViewModel.Implementation" - xmlns:viewModel="clr-namespace:VECTO3GUI2020.ViewModel" - mc:Ignorable="d" - d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignData Type=viewModel:IOutputViewModel}"> + xmlns:helper="clr-namespace:VECTO3GUI2020.Helper" + mc:Ignorable="d" + d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignData Type=viewModel:IOutputViewModel}" + xmlns:behavior="clr-namespace:VECTO3GUI2020.Behaviours" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors"> + <Grid> <DockPanel LastChildFill="False"> <ProgressBar DockPanel.Dock="Top" @@ -28,57 +30,87 @@ SelectionUnit="FullRow" IsReadOnly="True" HeadersVisibility="All" - RowHeaderWidth="5" - Name="MessageList"> + RowHeaderWidth="0.1" + Name="MessageList" + ColumnHeaderStyle="{StaticResource JobListDataGridHeaderStyle}" + ColumnHeaderHeight="30" + d:DataContext="{d:DesignInstance helper:DesignData}" + AlternationCount="2" + Background="White"> + + <i:Interaction.Behaviors> + <behavior:AutoScrollDataGridBehaviour> + </behavior:AutoScrollDataGridBehaviour> + </i:Interaction.Behaviors> <DataGrid.Columns> <DataGridTemplateColumn Header="Message" Width="*"> <DataGridTemplateColumn.CellTemplate> - <DataTemplate> - <StackPanel> + <DataTemplate DataType="impl:MessageEntry"> + <StackPanel Margin="10"> <TextBlock Text="{Binding Message}" Visibility="{Binding Message, Converter={StaticResource NullToVisibilityConverter}}" TextWrapping="Wrap"/> - <TextBlock Text="{Binding Link}" Visibility="{Binding Message, Converter={StaticResource NullToVisibilityConverter}}" - TextWrapping="Wrap"/> + + <TextBlock Visibility="{Binding Link, Converter={StaticResource NullToVisibilityConverter}}"> + <Hyperlink Command="{Binding Path=DataContext.OpenFolderCommand, + RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" + CommandParameter="{Binding Link}"> + Open Folder + </Hyperlink> + + <Hyperlink Command="{Binding Path=DataContext.OpenFileCommand, + RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" + CommandParameter="{Binding Link}"> + Open File + </Hyperlink> + </TextBlock> </StackPanel> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> - <DataGridTextColumn Header="Time" Binding="{Binding Time}" Width="130" /> + <DataGridTextColumn Header="Time" Binding="{Binding Time, StringFormat=hh:mm:ss dd.MM.yyyy}" Width="150" /> </DataGrid.Columns> <DataGrid.RowStyle> <Style TargetType="DataGridRow"> <Style.Triggers> + + + + <DataTrigger Binding="{Binding Type}" Value="{x:Static impl:MessageType.StatusMessage}"> - <Setter Property="Background" Value="AliceBlue"/> + <Setter Property="Background" Value="{StaticResource SemiTransparentWhite}"/> </DataTrigger> <DataTrigger Binding="{Binding Type}" Value="{x:Static impl:MessageType.InfoMessage}"> <Setter Property="Background" Value="LemonChiffon"/> </DataTrigger> <DataTrigger Binding="{Binding Type}" Value="{x:Static impl:MessageType.ErrorMessage}"> - <Setter Property="Background" Value="Red"/> + <Setter Property="Background" Value="OrangeRed"/> </DataTrigger> <DataTrigger Binding="{Binding Type}" Value="{x:Static impl:MessageType.WarningMessage}"> - <Setter Property="Background" Value="Gold"/> + <Setter Property="Background" Value="{StaticResource SemiTransparentYellow}"/> </DataTrigger> </Style.Triggers> </Style> </DataGrid.RowStyle> <DataGrid.CellStyle> - <Style TargetType="DataGridCell"> + <Style TargetType="DataGridCell" BasedOn="{StaticResource DataGridCellStyle1}"> <Setter Property="FontFamily" Value="Courier New"/> <Style.Triggers> <DataTrigger Binding="{Binding Type}" Value="{x:Static impl:MessageType.StatusMessage}"> <Setter Property="Foreground" Value="Black"/> + </DataTrigger> <DataTrigger Binding="{Binding Type}" Value="{x:Static impl:MessageType.InfoMessage}"> - <Setter Property="Foreground" Value="DimGray"/> + <Setter Property="Foreground" Value="Black"/> + </DataTrigger> <DataTrigger Binding="{Binding Type}" Value="{x:Static impl:MessageType.ErrorMessage}"> - <Setter Property="Foreground" Value="White"/> + <Setter Property="Foreground" Value="LightGray"/> + <Setter Property="FontWeight" Value="Bold"/> </DataTrigger> <DataTrigger Binding="{Binding Type}" Value="{x:Static impl:MessageType.WarningMessage}"> <Setter Property="Foreground" Value="Black"/> + <Setter Property="FontWeight" Value="Bold"/> </DataTrigger> </Style.Triggers> diff --git a/VECTO3GUI2020/Views/OutputView.xaml.cs b/VECTO3GUI2020/Views/OutputView.xaml.cs index c9eab7dc568a76159f596d5818f783f5ba58ec51..f07ca73a6f19f525376cf3977a8e30eca1fba086 100644 --- a/VECTO3GUI2020/Views/OutputView.xaml.cs +++ b/VECTO3GUI2020/Views/OutputView.xaml.cs @@ -24,5 +24,6 @@ namespace VECTO3GUI2020.Views { InitializeComponent(); } - } + + } } diff --git a/VECTO3GUI2020/Views/SettingsView.xaml b/VECTO3GUI2020/Views/SettingsView.xaml index 225d9506482e2c5aa0e773fb63623bc488f283da..6ef78b6a93d8de01b64309520d4547ebcd419a1f 100644 --- a/VECTO3GUI2020/Views/SettingsView.xaml +++ b/VECTO3GUI2020/Views/SettingsView.xaml @@ -6,7 +6,10 @@ xmlns:local="clr-namespace:VECTO3GUI2020.Views" xmlns:customControls="clr-namespace:VECTO3GUI2020.Views.Multistage.CustomControls" xmlns:implementation="clr-namespace:VECTO3GUI2020.ViewModel.Implementation" - mc:Ignorable="d" Height="450" Width="800" d:DataContext="{d:DesignInstance implementation:SettingsViewModel }"> + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" + xmlns:behaviour="clr-namespace:VECTO3GUI2020.Behaviours" + mc:Ignorable="d" d:DataContext="{d:DesignInstance implementation:SettingsViewModel }" + MinHeight="200" MinWidth="400"> <UserControl.Resources> <Style TargetType="Label"> <Setter Property="Margin" Value="4 4 4 4"></Setter> @@ -20,66 +23,82 @@ </UserControl.Resources> <Grid> - <DockPanel LastChildFill="False"> - <Grid DockPanel.Dock="Top"> + <DockPanel VerticalAlignment="Stretch" LastChildFill="False"> + <Label DockPanel.Dock="Top" Style="{StaticResource LabelStyle1}">File I/O</Label> + <Border DockPanel.Dock="Top" BorderBrush="{StaticResource ButtonHighlightColor}" BorderThickness="1"> + <Grid DockPanel.Dock="Top" IsSharedSizeScope="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <Grid.ColumnDefinitions> - <ColumnDefinition Width="1*"/> - <ColumnDefinition Width="1*"></ColumnDefinition> - <ColumnDefinition Width="1*"></ColumnDefinition> - <ColumnDefinition Width="1*"></ColumnDefinition> + <ColumnDefinition Width="Auto"/> + <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> - <RowDefinition Height="30"></RowDefinition> - <RowDefinition Height="30"></RowDefinition> - <RowDefinition Height="30"></RowDefinition> </Grid.RowDefinitions> - - - <Label Grid.Row="0" Grid.Column="0" DockPanel.Dock="Left">Default Path</Label> - <customControls:FilePicker Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3" DockPanel.Dock="Right" - Text="{Binding DefaultFilePath}" - HorizontalAlignment="Stretch" Command="{Binding ChangeFilePath}"/> - - <Label Grid.Row="1" Grid.Column="0" DockPanel.Dock="Left">Default Path</Label> - <Grid Grid.Row="1" Grid.Column="1" Margin="4" VerticalAlignment="Stretch" Grid.ColumnSpan="3" DockPanel.Dock="Right"> - <Grid.RowDefinitions> - <RowDefinition></RowDefinition> - </Grid.RowDefinitions> + + <Label Grid.Row="0" Grid.Column="0" DockPanel.Dock="Left">Default Input Path</Label> + <customControls:FilePicker Grid.Row="0" + Grid.Column="1" + DockPanel.Dock="Right" + Text="{Binding DefaultFilePath}" + HorizontalAlignment="Stretch" Command="{Binding ChangeFilePath}" + ButtonContentTemplate="{DynamicResource FolderIcon}"/> + + + <Label Grid.Column="0" Grid.Row="1">Default Output Path</Label> + <customControls:FilePicker Grid.Row="1" + Grid.Column="1" + Text="{Binding DefaultOutputPath}" + Command="{Binding ChangeOutputPath}" + ButtonContentTemplate="{DynamicResource FolderIcon}"/> + </Grid> + </Border> + <Border BorderBrush="{DynamicResource ButtonHighlightColor}" BorderThickness="1" DockPanel.Dock="Top"> + <StackPanel> + + <Label Style="{DynamicResource LabelStyle1}" HorizontalAlignment="Stretch">Simulation Settings</Label> + + <Grid HorizontalAlignment="Left" MaxWidth="500" > <Grid.ColumnDefinitions> - <ColumnDefinition></ColumnDefinition> - <ColumnDefinition Width="30px"></ColumnDefinition> + <ColumnDefinition Width="2*"/> + <ColumnDefinition Width="1*"/> + <ColumnDefinition Width="2*"/> + <ColumnDefinition Width="1*"/> </Grid.ColumnDefinitions> - <TextBox x:Name="textBox" VerticalContentAlignment="Center" Padding="4" Margin = "0 0 0 0" IsReadOnly="false" - Text="{Binding DefaultOutputPath}" HorizontalAlignment="Stretch" TextWrapping="Wrap" - Style="{DynamicResource TextBoxStyle1}"/> - <Button x:Name="button" Padding="4" Margin="4 0 0 0" Grid.Column="1" ContentTemplate="{DynamicResource AddDocumentIcon}" - Command="{Binding ChangeOutputPath}" Style="{DynamicResource FilePickerButtonStyle}"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="Auto"/> + <RowDefinition Height="Auto"/> + </Grid.RowDefinitions> + <Label Grid.Row="0" Grid.Column="0">Serialize Vecto Run Data</Label> + <CheckBox Grid.Row="0" Grid.Column="1" IsChecked="{Binding SerializeVectoRunData}"></CheckBox> + + <Label Grid.Row="1" Grid.Column="2">Write Modal Results</Label> + <CheckBox Grid.Row="1" Grid.Column="3" IsChecked="{Binding WriteModalResults}"></CheckBox> + + <Label Grid.Row="2" Grid.Column="0">Validate</Label> + <CheckBox Grid.Row="2" Grid.Column="1" IsChecked="{Binding Validate}"></CheckBox> + + <Label Grid.Row="0" Grid.Column="2">Actual Modal Data</Label> + <CheckBox Grid.Row="0" Grid.Column="3" IsChecked="{Binding ActualModalData}"></CheckBox> + + <Label Grid.Row="1" Grid.Column="0">ModalResults1Hz</Label> + <CheckBox Grid.Row="1" Grid.Column="1" IsChecked="{Binding ModalResults1Hz}"></CheckBox> + + - </Button> - </Grid> - <!--<customControls:FilePicker Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" DockPanel.Dock="Right" - Text="{Binding DefaultOutputPath}" - HorizontalAlignment="Stretch" Command="{Binding ChangeOutputPath}"/>--> + </Grid> - <Label Grid.Row="2" Grid.Column="0">Serialize Vecto Run Data</Label> - <CheckBox Grid.Row="2" Grid.Column="1" IsChecked="{Binding SerializeVectoRunData}"></CheckBox> + </StackPanel> + </Border> - <Label Grid.Row="3" Grid.Column="2">Write Modal Results</Label> - <CheckBox Grid.Row="3" Grid.Column="3" IsChecked="{Binding WriteModalResults}"></CheckBox> - <Label Grid.Row="3" Grid.Column="0">Validate</Label> - <CheckBox Grid.Row="3" Grid.Column="1" IsChecked="{Binding Validate}"></CheckBox> - <Label Grid.Row="4" Grid.Column="2">Actual Modal Data</Label> - <CheckBox Grid.Row="4" Grid.Column="3" IsChecked="{Binding ActualModalData}"></CheckBox> - <Label Grid.Row="4" Grid.Column="0">ModalResults1Hz</Label> - <CheckBox Grid.Row="4" Grid.Column="1" IsChecked="{Binding ModalResults1Hz}"></CheckBox> - </Grid> - <!--<DockPanel DockPanel.Dock="Bottom" LastChildFill="False"> + + <!--</Grid>--> + <DockPanel DockPanel.Dock="Bottom" LastChildFill="False"> <Button DockPanel.Dock="Right" Width="100" Command="{Binding CloseWindowCommand}" @@ -87,7 +106,7 @@ Style="{DynamicResource MultiStageButtonStyle1}" Margin="4" Padding="4">Close</Button> - </DockPanel>--> + </DockPanel> </DockPanel> </Grid> </UserControl> diff --git a/VECTO3GUI2020/packages.config b/VECTO3GUI2020/packages.config index 858916a3f79f42e0406d5119d5d69b34c14416a4..9cb9073c2bdc9af52f5c0bcaa4269bafa9b3f6f7 100644 --- a/VECTO3GUI2020/packages.config +++ b/VECTO3GUI2020/packages.config @@ -5,9 +5,12 @@ <package id="Microsoft.Bcl.AsyncInterfaces" version="5.0.0" targetFramework="net48" /> <package id="Microsoft.Maps.MapControl.WPF" version="1.0.0.3" targetFramework="net48" /> <package id="Microsoft.Toolkit.Mvvm" version="7.0.2" targetFramework="net48" /> + <package id="Microsoft.Xaml.Behaviors.Wpf" version="1.1.31" targetFramework="net48" /> + <package id="Newtonsoft.Json" version="8.0.3" targetFramework="net48" /> <package id="Ninject" version="3.3.4" targetFramework="net48" /> <package id="Ninject.Extensions.ChildKernel" version="3.3.0" targetFramework="net48" /> <package id="Ninject.Extensions.Factory" version="3.3.3" targetFramework="net48" /> + <package id="NLog" version="4.5.11" targetFramework="net48" /> <package id="System.Buffers" version="4.5.1" targetFramework="net48" /> <package id="System.ComponentModel.Annotations" version="5.0.0" targetFramework="net48" /> <package id="System.Memory" version="4.5.4" targetFramework="net48" /> diff --git a/VECTOAux/VectoAuxiliariesTests/IntegrationTests/AuxDemandTest.vb b/VECTOAux/VectoAuxiliariesTests/IntegrationTests/AuxDemandTest.vb index 05de179604b4cb0e122f3ff5c4b555e4e400e5e5..ed079df9a565dc1a50cbf9fe6156e95d242ef7f0 100644 --- a/VECTOAux/VectoAuxiliariesTests/IntegrationTests/AuxDemandTest.vb +++ b/VECTOAux/VectoAuxiliariesTests/IntegrationTests/AuxDemandTest.vb @@ -113,7 +113,7 @@ Namespace IntegrationTests For i As Integer = 0 To 9 aux.ResetCalculations() Assert.AreEqual(6087.0317, aux.AuxiliaryPowerAtCrankWatts().Value(), 0.001) - aux.CycleStep(1.SI(Of Second), 1.0) + aux.CycleStep(1.SI(Of Second)) 'Console.WriteLine("{0}", aux.AA_TotalCycleFC_Grams) Next @@ -128,7 +128,7 @@ Namespace IntegrationTests For i As Integer = 0 To 9 aux.ResetCalculations() Assert.AreEqual(8954.1435, aux.AuxiliaryPowerAtCrankWatts().Value(), 0.001) - aux.CycleStep(1.SI(Of Second), 1.0) + aux.CycleStep(1.SI(Of Second)) 'Console.WriteLine("{0}", aux.AA_TotalCycleFC_Grams) Next @@ -143,7 +143,7 @@ Namespace IntegrationTests For i As Integer = 0 To 9 aux.ResetCalculations() Assert.AreEqual(6087.0317, aux.AuxiliaryPowerAtCrankWatts().Value(), 0.001) - aux.CycleStep(1.SI(Of Second), 1.0) + aux.CycleStep(1.SI(Of Second)) 'Console.WriteLine("{0}", aux.AA_TotalCycleFC_Grams) Next diff --git a/Vecto3GUI2020Test/AllTestWithoutUI.testsession b/Vecto3GUI2020Test/AllTestWithoutUI.testsession deleted file mode 100644 index 09c416848ccbebfc94be4fd3f62e8923f6fd29a7..0000000000000000000000000000000000000000 --- a/Vecto3GUI2020Test/AllTestWithoutUI.testsession +++ /dev/null @@ -1,14 +0,0 @@ -<SessionState ContinuousTestingMode="0" IsActive="True" Name="AllTestWithoutUI" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> - <TestAncestor> - <TestId>NUnit3x::7F4FF473-96B3-461E-9CE6-76D3B75F87CB::.NETFramework,Version=v4.8::Vecto3GUI2020Test.ViewModelTests.VIFTests.LoadPrimaryVehicleAndStageInputThenCreateVif</TestId> - <TestId>NUnit3x::7F4FF473-96B3-461E-9CE6-76D3B75F87CB::.NETFramework,Version=v4.8::Vecto3GUI2020Test.ViewModelTests.VehicleViewModelTests.airdragNotModifiedInPreviousStages</TestId> - <TestId>NUnit3x::7F4FF473-96B3-461E-9CE6-76D3B75F87CB::.NETFramework,Version=v4.8::Vecto3GUI2020Test.ViewModelTests.VIFTests.loadPrimaryVehicleOnlyAndCreateNewVIF</TestId> - <TestId>NUnit3x::7F4FF473-96B3-461E-9CE6-76D3B75F87CB::.NETFramework,Version=v4.8::Vecto3GUI2020Test.ViewModelTests.VIFTests.TestAirdragLoad</TestId> - <TestId>NUnit3x::7F4FF473-96B3-461E-9CE6-76D3B75F87CB::.NETFramework,Version=v4.8::Vecto3GUI2020Test.LoadAndSaveVehicleData.SaveVehicleDataWithMissingFields</TestId> - <TestId>NUnit3x::7F4FF473-96B3-461E-9CE6-76D3B75F87CB::.NETFramework,Version=v4.8::Vecto3GUI2020Test.LoadAndSaveVehicleData.loadPrimaryAndSaveVehicleData</TestId> - <TestId>NUnit3x::7F4FF473-96B3-461E-9CE6-76D3B75F87CB::.NETFramework,Version=v4.8::Vecto3GUI2020Test.LoadAndSaveVehicleData.loadInputFileMultipleStage</TestId> - <TestId>NUnit3x::7F4FF473-96B3-461E-9CE6-76D3B75F87CB::.NETFramework,Version=v4.8::Vecto3GUI2020Test.LoadAndSaveVehicleData</TestId> - <TestId>NUnit3x::7F4FF473-96B3-461E-9CE6-76D3B75F87CB::.NETFramework,Version=v4.8::Vecto3GUI2020Test.ViewModelTests.VIFTests</TestId> - <TestId>NUnit3x::7F4FF473-96B3-461E-9CE6-76D3B75F87CB::.NETFramework,Version=v4.8::Vecto3GUI2020Test.ViewModelTests.VehicleViewModelTests</TestId> - </TestAncestor> -</SessionState> \ No newline at end of file diff --git a/Vecto3GUI2020Test/BugReports/VIFTests.cs b/Vecto3GUI2020Test/BugReports/VIFTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..7e4693efc1968ddf03807c86f255974c4a672d9a --- /dev/null +++ b/Vecto3GUI2020Test/BugReports/VIFTests.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Ninject; +using NUnit.Framework; +using NUnit.Framework.Internal; +using VECTO3GUI2020.ViewModel.Implementation; +using VECTO3GUI2020.ViewModel.Interfaces; + +namespace Vecto3GUI2020Test.BugReports +{ + [TestFixture] + public class VifTests : ViewModelTestBase + { + public const string primaryDecimalTestFile = "PrimaryDecimal/primary_heavyBus group41_nonSmart_rounded_decimals.xml"; + + + [TestCase(VifTests.primaryDecimalTestFile, TestName="PneumaticsCompressorDrive")] + public async Task CreateAndLoadVifWithWrongDecimalCount(string fileName) + { + //Load JobFile + var jobListViewModel = _kernel.Get<IJobListViewModel>() as JobListViewModel; + await jobListViewModel.AddJobAsync(GetTestDataPath(fileName: fileName)); + Assert.AreEqual(1, jobListViewModel.Jobs.Count); + jobListViewModel.Jobs[0].Selected = true; + + //Start Simulation + TestContext.Write("Starting simulation ... "); + Stopwatch stop = Stopwatch.StartNew(); + await jobListViewModel.RunSimulationExecute(); + stop.Stop(); + TestContext.WriteLine($"Done! ({stop.Elapsed.TotalSeconds}s)"); + + + var vifName = fileName.Replace(".xml", ".RSLT_VIF.xml"); + TestContext.WriteLine($"Trying to add {vifName} to JobList"); + await jobListViewModel.AddJobAsync(GetTestDataPath(fileName: vifName)); + Assert.AreEqual(2, jobListViewModel.Jobs.Count); + + foreach (var documentViewModel in jobListViewModel.Jobs) { + TestContext.WriteLine($"{documentViewModel.DataSource.SourcePath}"); + } + + return; + } + + + + + + } +} diff --git a/Vecto3GUI2020Test/HelperTests/BackingStorageTest.cs b/Vecto3GUI2020Test/HelperTests/BackingStorageTest.cs new file mode 100644 index 0000000000000000000000000000000000000000..278bbcba1f1610393009858163ebce167266b19e --- /dev/null +++ b/Vecto3GUI2020Test/HelperTests/BackingStorageTest.cs @@ -0,0 +1,219 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; +using Castle.Components.DictionaryAdapter; +using NUnit.Framework; +using VECTO3GUI2020; +using VECTO3GUI2020.ViewModel.Implementation.Common; +using VECTO3GUI2020.ViewModel.MultiStage.Implementation; + +namespace Vecto3GUI2020Test.HelperTests +{ + [TestFixture] + public class BackingStorageTest + { + private TestVm _testVm; + private Dictionary<string, object> _currentValues; + private IReadOnlyDictionary<string, object> _savedValues; + private IReadOnlyDictionary<string, object> _unsavedChanges; + private bool _unsavedChangesNotified = false; + + public class TestVm : ObservableObject + { + private string _stringTestProperty; + + public string StringTestProperty + { + get => _stringTestProperty; + set => SetProperty(ref _stringTestProperty, value); + } + + private string _notMonitoredProperty; + + public string NotMonitoredProperty + { + get => _notMonitoredProperty; + set => SetProperty(ref _notMonitoredProperty, value); + } + + + public BackingStorage<TestVm> BackingStorage { get; set; } + public TestVm() + { + BackingStorage = new BackingStorage<TestVm>(this, nameof(StringTestProperty)); + } + } + + #region Setup and Property implementation + private IReadOnlyDictionary<string, object> SavedValues + { + get + { + return _savedValues ?? (_savedValues = (IReadOnlyDictionary<string, object>)_testVm.BackingStorage.GetType() + .GetField("_savedValues", BindingFlags.NonPublic | BindingFlags.Instance) + .GetValue(_testVm.BackingStorage)); + } + } + + + [SetUp] + public void SetUp() + { + _unsavedChangesNotified = false; + _testVm = new TestVm(); + _currentValues = (Dictionary<string, object>)_testVm.BackingStorage. + GetType().GetField("_currentValues", BindingFlags.NonPublic | BindingFlags.Instance). + GetValue(_testVm.BackingStorage); + _unsavedChanges = (Dictionary<string, object>)_testVm.BackingStorage. + GetType().GetField("_unsavedChanges", BindingFlags.NonPublic | BindingFlags.Instance). + GetValue(_testVm.BackingStorage); + + _testVm.BackingStorage.PropertyChanged += BackingStorage_PropertyChanged; + } + + [TearDown] + public void TearDown() + { + _unsavedChangesNotified = false; + + _currentValues = null; + _unsavedChanges = null; + _savedValues = null; + _testVm.BackingStorage.PropertyChanged -= BackingStorage_PropertyChanged; + _testVm = null; + } + + private void BackingStorage_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + switch (e.PropertyName) { + case nameof(TestVm.BackingStorage.UnsavedChanges): + _unsavedChangesNotified = true; + break; + default: + break; + } + } + +#endregion + [Test] + public void ValueUpdatedOnChange() + { + + var stopWatch = Stopwatch.StartNew(); + _testVm.StringTestProperty = "Hi i am the new value"; + stopWatch.Stop(); + TestContext.WriteLine($"Ticks ellapsed first update: {stopWatch.ElapsedTicks} ({stopWatch.Elapsed.TotalMilliseconds} ms)"); + + + + + Assert.AreEqual(1, _currentValues.Count); + Assert.AreEqual(_testVm.StringTestProperty, _currentValues[nameof(_testVm.StringTestProperty)]); + + + + stopWatch = Stopwatch.StartNew(); + _testVm.StringTestProperty = "Hi i am ANOTHER value"; + stopWatch.Stop(); + TestContext.WriteLine($"Ticks ellapsed second update: {stopWatch.ElapsedTicks} ({stopWatch.Elapsed.TotalMilliseconds} ms)"); + + Assert.AreEqual(1, _currentValues.Count); + Assert.AreEqual(_testVm.StringTestProperty, _currentValues[nameof(_testVm.StringTestProperty)]); + } + + [Test] + public void NotMonitoredProperty() + { + _testVm.NotMonitoredProperty = "Hi i should not get stored in the backing storage"; + Assert.IsFalse(_currentValues.ContainsKey(nameof(TestVm.NotMonitoredProperty))); + } + + [Test] + public void SaveChanges() + { + _testVm.StringTestProperty = "hi"; + Assert.IsTrue(checkNotified(ref _unsavedChangesNotified)); + Assert.IsTrue(_testVm.BackingStorage.UnsavedChanges); + + _testVm.BackingStorage.SaveChanges(); + Assert.IsTrue(checkNotified(ref _unsavedChangesNotified)); + Assert.IsFalse(_testVm.BackingStorage.UnsavedChanges); + } + + + [Test] + public void ChangeAndUndo() + { + var originalString = "original"; + var newValue = "new Value"; + //Set to initial value + _testVm.StringTestProperty = originalString; + Assert.IsTrue(checkNotified(ref _unsavedChangesNotified)); + Assert.IsTrue(_testVm.BackingStorage.UnsavedChanges); + + //Save + _testVm.BackingStorage.SaveChanges(); + Assert.GreaterOrEqual(SavedValues.Count, 1); + Assert.IsTrue(checkNotified(ref _unsavedChangesNotified)); + Assert.IsFalse(_testVm.BackingStorage.UnsavedChanges); + + //Set to new value + _testVm.StringTestProperty = newValue; + Assert.IsTrue(checkNotified(ref _unsavedChangesNotified)); + Assert.IsTrue(_testVm.BackingStorage.UnsavedChanges); + + //Set to initial value + _testVm.StringTestProperty = originalString; + Assert.IsTrue(checkNotified(ref _unsavedChangesNotified)); + Assert.IsFalse(_testVm.BackingStorage.UnsavedChanges); + } + + [Test] + public void UnsavedTrueBeforeFirstSave() + { + Assert.IsTrue(_testVm.BackingStorage.UnsavedChanges); + _testVm.BackingStorage.SaveChanges(); + Assert.IsFalse(_testVm.BackingStorage.UnsavedChanges); + } + + [Test] + public void SavedChangesNotModified() + { + string initialValue = "hello world"; + + _testVm.StringTestProperty = initialValue; + + _testVm.BackingStorage.SaveChanges(); + + Assert.AreEqual(SavedValues.Count, _currentValues.Count); + Assert.AreEqual( initialValue, SavedValues[nameof(_testVm.StringTestProperty)]); + + _testVm.StringTestProperty = "New value"; + Assert.AreEqual(initialValue, SavedValues[nameof(_testVm.StringTestProperty)]); + } + + [Test] + public void createEqualityComparer() + { + var stringEqualityComparer = EqualityComparer<string>.Default; + var CreateEqualityComparererMethodInfo = _testVm.BackingStorage.GetType() + .GetMethod("CreateEqualityComparer", BindingFlags.NonPublic | BindingFlags.Static); + + var generatedEqualityComparer = CreateEqualityComparererMethodInfo.Invoke(null, new []{ typeof(String) }); + Assert.AreEqual(stringEqualityComparer.GetType(), generatedEqualityComparer.GetType()); + + + } + + public bool checkNotified(ref bool value) + { + var result = value; + value = false; + return result; + } + + + } +} \ No newline at end of file diff --git a/Vecto3GUI2020Test/TestData/asdf.xml b/Vecto3GUI2020Test/TestData/asdf.xml new file mode 100644 index 0000000000000000000000000000000000000000..70415bde697691075112a4a1c38990fceeee656d --- /dev/null +++ b/Vecto3GUI2020Test/TestData/asdf.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<tns:VectoInputDeclaration xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" schemaVersion="2.8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob V:\VectoCore\VectoCore\Resources\XSD\VectoDeclarationJob.xsd"> + <v2.0:Vehicle id="TODO_ADDIDENTIFIER" xsi:type="InterimStageInputType"> + <Manufacturer>adf</Manufacturer> + <ManufacturerAddress>asdf</ManufacturerAddress> + <VIN>asdf</VIN> + <Date>2021-07-01T22:00:00Z</Date> + <VehicleDeclarationType>interim</VehicleDeclarationType> + </v2.0:Vehicle> +</tns:VectoInputDeclaration> \ No newline at end of file diff --git a/Vecto3GUI2020Test/TestData/bugreports/PrimaryDecimal/primary_heavyBus group41_nonSmart_rounded_decimals.xml b/Vecto3GUI2020Test/TestData/bugreports/PrimaryDecimal/primary_heavyBus group41_nonSmart_rounded_decimals.xml new file mode 100644 index 0000000000000000000000000000000000000000..5a3f639288f4678d8217f1584a89cc80ec93d47e --- /dev/null +++ b/Vecto3GUI2020Test/TestData/bugreports/PrimaryDecimal/primary_heavyBus group41_nonSmart_rounded_decimals.xml @@ -0,0 +1,2213 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:VectoInputDeclaration schemaVersion="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xmlns:di="http://www.w3.org/2000/09/xmldsig#" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob V:\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> + <v2.0:Vehicle id="VEH-PrimaryBus_nonSmart" xsi:type="PrimaryVehicleDeclarationType" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6"> + <Manufacturer>Generic Truck Manufacturer</Manufacturer> + <ManufacturerAddress>Street, ZIP City</ManufacturerAddress> + <Model>Generic Model</Model> + <VIN>VEH-1234567890_nonSmart</VIN> + <Date>2017-02-15T11:00:00Z</Date> + <ChassisConfiguration>Bus</ChassisConfiguration> + <AxleConfiguration>4x2</AxleConfiguration> + <Articulated>false</Articulated> + <TechnicalPermissibleMaximumLadenMass>28000</TechnicalPermissibleMaximumLadenMass> + <IdlingSpeed>700</IdlingSpeed> + <RetarderType>Transmission Output Retarder</RetarderType> + <RetarderRatio>1.000</RetarderRatio> + <AngledriveType>None</AngledriveType> + <ZeroEmissionVehicle>false</ZeroEmissionVehicle> + <v2.6:ADAS xsi:type="v2.1:AdvancedDriverAssistantSystemsType" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1"> + <EngineStopStart>false</EngineStopStart> + <EcoRollWithoutEngineStop>false</EcoRollWithoutEngineStop> + <EcoRollWithEngineStop>false</EcoRollWithEngineStop> + <PredictiveCruiseControl>none</PredictiveCruiseControl> + </v2.6:ADAS> + <v2.6:TorqueLimits xsi:type="TorqueLimitsType" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0"> + <Entry gear="6" maxTorque="1800"/> + <Entry gear="1" maxTorque="2500"/> + </v2.6:TorqueLimits> + <Components xsi:type="PrimaryVehicleComponentsDeclarationType"> + <v2.6:Engine xsi:type="v2.0:EngineComponentDeclarationType" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0"> + <v2.0:Data id="ENG-gooZah3D" xsi:type="v2.1:EngineDataDeclarationType" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1"> + <Manufacturer>Generic Engine Manufacturer</Manufacturer> + <Model>Generic primary bus 41 Engine</Model> + <CertificationNumber>e12*0815/8051*2017/05E0000*00</CertificationNumber> + <Date>2017-02-15T11:00:00Z</Date> + <AppVersion>VectoEngine x.y</AppVersion> + <Displacement>7700</Displacement> + <IdlingSpeed>700</IdlingSpeed> + <RatedSpeed>2200</RatedSpeed> + <RatedPower>220000</RatedPower> + <MaxEngineTorque>1100</MaxEngineTorque> + <WHTCUrban>1.0600</WHTCUrban> + <WHTCRural>1.0300</WHTCRural> + <WHTCMotorway>1.0000</WHTCMotorway> + <BFColdHot>1.0000</BFColdHot> + <CFRegPer>1.0000</CFRegPer> + <CFNCV>1.0000</CFNCV> + <FuelType>Diesel CI</FuelType> + <FuelConsumptionMap> + <Entry engineSpeed='600.00' torque='-39.66' fuelConsumption='0.00'/> + <Entry engineSpeed='600.00' torque='0.00' fuelConsumption='580.60'/> + <Entry engineSpeed='600.00' torque='63.70' fuelConsumption='1457.17'/> + <Entry engineSpeed='600.00' torque='91.00' fuelConsumption='1838.29'/> + <Entry engineSpeed='600.00' torque='182.01' fuelConsumption='3031.03'/> + <Entry engineSpeed='600.00' torque='273.01' fuelConsumption='4233.11'/> + <Entry engineSpeed='600.00' torque='364.01' fuelConsumption='5425.95'/> + <Entry engineSpeed='600.00' torque='455.01' fuelConsumption='7261.20'/> + <Entry engineSpeed='600.00' torque='546.02' fuelConsumption='9123.12'/> + <Entry engineSpeed='800.00' torque='-48.83' fuelConsumption='0.00'/> + <Entry engineSpeed='800.00' torque='0.00' fuelConsumption='832.00'/> + <Entry engineSpeed='800.00' torque='63.70' fuelConsumption='1694.68'/> + <Entry engineSpeed='800.00' torque='91.00' fuelConsumption='2154.71'/> + <Entry engineSpeed='800.00' torque='182.01' fuelConsumption='3646.28'/> + <Entry engineSpeed='800.00' torque='273.01' fuelConsumption='5158.01'/> + <Entry engineSpeed='800.00' torque='364.01' fuelConsumption='6675.35'/> + <Entry engineSpeed='800.00' torque='455.01' fuelConsumption='8655.27'/> + <Entry engineSpeed='800.00' torque='546.02' fuelConsumption='10602.39'/> + <Entry engineSpeed='800.00' torque='637.02' fuelConsumption='12534.67'/> + <Entry engineSpeed='800.00' torque='728.02' fuelConsumption='14376.07'/> + <Entry engineSpeed='800.00' torque='760.78' fuelConsumption='15042.65'/> + <Entry engineSpeed='1000.00' torque='-56.44' fuelConsumption='0.00'/> + <Entry engineSpeed='1000.00' torque='0.00' fuelConsumption='1083.40'/> + <Entry engineSpeed='1000.00' torque='63.70' fuelConsumption='1932.20'/> + <Entry engineSpeed='1000.00' torque='91.00' fuelConsumption='2471.14'/> + <Entry engineSpeed='1000.00' torque='182.01' fuelConsumption='4261.53'/> + <Entry engineSpeed='1000.00' torque='273.01' fuelConsumption='6082.91'/> + <Entry engineSpeed='1000.00' torque='364.01' fuelConsumption='7924.76'/> + <Entry engineSpeed='1000.00' torque='455.01' fuelConsumption='10049.34'/> + <Entry engineSpeed='1000.00' torque='546.02' fuelConsumption='12081.67'/> + <Entry engineSpeed='1000.00' torque='637.02' fuelConsumption='14085.16'/> + <Entry engineSpeed='1000.00' torque='728.02' fuelConsumption='16091.69'/> + <Entry engineSpeed='1000.00' torque='819.02' fuelConsumption='18118.90'/> + <Entry engineSpeed='1000.00' torque='910.03' fuelConsumption='20145.67'/> + <Entry engineSpeed='1000.00' torque='973.73' fuelConsumption='21556.46'/> + <Entry engineSpeed='1200.00' torque='-67.29' fuelConsumption='0.00'/> + <Entry engineSpeed='1200.00' torque='0.00' fuelConsumption='1334.80'/> + <Entry engineSpeed='1200.00' torque='63.70' fuelConsumption='2169.71'/> + <Entry engineSpeed='1200.00' torque='91.00' fuelConsumption='2787.56'/> + <Entry engineSpeed='1200.00' torque='182.01' fuelConsumption='4876.78'/> + <Entry engineSpeed='1200.00' torque='273.01' fuelConsumption='7007.81'/> + <Entry engineSpeed='1200.00' torque='364.01' fuelConsumption='9174.17'/> + <Entry engineSpeed='1200.00' torque='455.01' fuelConsumption='11443.41'/> + <Entry engineSpeed='1200.00' torque='546.02' fuelConsumption='13560.95'/> + <Entry engineSpeed='1200.00' torque='637.02' fuelConsumption='15635.64'/> + <Entry engineSpeed='1200.00' torque='728.02' fuelConsumption='17807.32'/> + <Entry engineSpeed='1200.00' torque='819.02' fuelConsumption='20010.10'/> + <Entry engineSpeed='1200.00' torque='910.03' fuelConsumption='22214.23'/> + <Entry engineSpeed='1200.00' torque='1001.03' fuelConsumption='24405.18'/> + <Entry engineSpeed='1200.00' torque='1092.03' fuelConsumption='26937.53'/> + <Entry engineSpeed='1400.00' torque='-77.58' fuelConsumption='0.00'/> + <Entry engineSpeed='1400.00' torque='0.00' fuelConsumption='1768.39'/> + <Entry engineSpeed='1400.00' torque='63.70' fuelConsumption='2609.47'/> + <Entry engineSpeed='1400.00' torque='91.00' fuelConsumption='3331.51'/> + <Entry engineSpeed='1400.00' torque='182.01' fuelConsumption='5738.32'/> + <Entry engineSpeed='1400.00' torque='273.01' fuelConsumption='8220.47'/> + <Entry engineSpeed='1400.00' torque='364.01' fuelConsumption='10725.58'/> + <Entry engineSpeed='1400.00' torque='455.01' fuelConsumption='13167.60'/> + <Entry engineSpeed='1400.00' torque='546.02' fuelConsumption='15637.27'/> + <Entry engineSpeed='1400.00' torque='637.02' fuelConsumption='18217.82'/> + <Entry engineSpeed='1400.00' torque='728.02' fuelConsumption='20778.63'/> + <Entry engineSpeed='1400.00' torque='819.02' fuelConsumption='23209.12'/> + <Entry engineSpeed='1400.00' torque='910.03' fuelConsumption='25601.87'/> + <Entry engineSpeed='1400.00' torque='1001.03' fuelConsumption='28049.44'/> + <Entry engineSpeed='1400.00' torque='1092.03' fuelConsumption='30591.88'/> + <Entry engineSpeed='1600.00' torque='-87.88' fuelConsumption='0.00'/> + <Entry engineSpeed='1600.00' torque='0.00' fuelConsumption='2175.58'/> + <Entry engineSpeed='1600.00' torque='63.70' fuelConsumption='3071.70'/> + <Entry engineSpeed='1600.00' torque='91.00' fuelConsumption='3886.46'/> + <Entry engineSpeed='1600.00' torque='182.01' fuelConsumption='6602.31'/> + <Entry engineSpeed='1600.00' torque='273.01' fuelConsumption='9459.95'/> + <Entry engineSpeed='1600.00' torque='364.01' fuelConsumption='12314.99'/> + <Entry engineSpeed='1600.00' torque='455.01' fuelConsumption='15203.38'/> + <Entry engineSpeed='1600.00' torque='546.02' fuelConsumption='18046.03'/> + <Entry engineSpeed='1600.00' torque='637.02' fuelConsumption='20894.65'/> + <Entry engineSpeed='1600.00' torque='728.02' fuelConsumption='23760.26'/> + <Entry engineSpeed='1600.00' torque='819.02' fuelConsumption='26535.17'/> + <Entry engineSpeed='1600.00' torque='910.03' fuelConsumption='29166.53'/> + <Entry engineSpeed='1600.00' torque='1001.03' fuelConsumption='32054.59'/> + <Entry engineSpeed='1600.00' torque='1092.03' fuelConsumption='34958.85'/> + <Entry engineSpeed='1800.00' torque='-94.11' fuelConsumption='0.00'/> + <Entry engineSpeed='1800.00' torque='0.00' fuelConsumption='2630.39'/> + <Entry engineSpeed='1800.00' torque='63.70' fuelConsumption='3626.48'/> + <Entry engineSpeed='1800.00' torque='91.00' fuelConsumption='4518.67'/> + <Entry engineSpeed='1800.00' torque='182.01' fuelConsumption='7492.63'/> + <Entry engineSpeed='1800.00' torque='273.01' fuelConsumption='10723.22'/> + <Entry engineSpeed='1800.00' torque='364.01' fuelConsumption='13929.84'/> + <Entry engineSpeed='1800.00' torque='455.01' fuelConsumption='17153.22'/> + <Entry engineSpeed='1800.00' torque='546.02' fuelConsumption='20263.97'/> + <Entry engineSpeed='1800.00' torque='637.02' fuelConsumption='23432.40'/> + <Entry engineSpeed='1800.00' torque='728.02' fuelConsumption='26745.26'/> + <Entry engineSpeed='1800.00' torque='819.02' fuelConsumption='29986.85'/> + <Entry engineSpeed='1800.00' torque='910.03' fuelConsumption='33277.81'/> + <Entry engineSpeed='1800.00' torque='1001.03' fuelConsumption='36723.98'/> + <Entry engineSpeed='1800.00' torque='1022.87' fuelConsumption='37550.81'/> + <Entry engineSpeed='2000.00' torque='-100.76' fuelConsumption='0.00'/> + <Entry engineSpeed='2000.00' torque='0.00' fuelConsumption='3181.54'/> + <Entry engineSpeed='2000.00' torque='63.70' fuelConsumption='4374.30'/> + <Entry engineSpeed='2000.00' torque='91.00' fuelConsumption='5327.75'/> + <Entry engineSpeed='2000.00' torque='182.01' fuelConsumption='8505.93'/> + <Entry engineSpeed='2000.00' torque='273.01' fuelConsumption='12119.90'/> + <Entry engineSpeed='2000.00' torque='364.01' fuelConsumption='15645.31'/> + <Entry engineSpeed='2000.00' torque='455.01' fuelConsumption='19238.95'/> + <Entry engineSpeed='2000.00' torque='546.02' fuelConsumption='22808.60'/> + <Entry engineSpeed='2000.00' torque='637.02' fuelConsumption='26330.44'/> + <Entry engineSpeed='2000.00' torque='728.02' fuelConsumption='30061.06'/> + <Entry engineSpeed='2000.00' torque='819.02' fuelConsumption='33840.66'/> + <Entry engineSpeed='2000.00' torque='910.03' fuelConsumption='37508.22'/> + <Entry engineSpeed='2000.00' torque='944.61' fuelConsumption='38855.94'/> + <Entry engineSpeed='2200.00' torque='-113.36' fuelConsumption='0.00'/> + <Entry engineSpeed='2200.00' torque='0.00' fuelConsumption='3865.04'/> + <Entry engineSpeed='2200.00' torque='63.70' fuelConsumption='5036.10'/> + <Entry engineSpeed='2200.00' torque='91.00' fuelConsumption='6086.05'/> + <Entry engineSpeed='2200.00' torque='182.01' fuelConsumption='9585.86'/> + <Entry engineSpeed='2200.00' torque='273.01' fuelConsumption='13516.63'/> + <Entry engineSpeed='2200.00' torque='364.01' fuelConsumption='17425.54'/> + <Entry engineSpeed='2200.00' torque='455.01' fuelConsumption='21286.40'/> + <Entry engineSpeed='2200.00' torque='546.02' fuelConsumption='25325.51'/> + <Entry engineSpeed='2200.00' torque='637.02' fuelConsumption='29576.52'/> + <Entry engineSpeed='2200.00' torque='728.02' fuelConsumption='33783.46'/> + <Entry engineSpeed='2200.00' torque='819.02' fuelConsumption='37868.27'/> + <Entry engineSpeed='2200.00' torque='869.07' fuelConsumption='40086.82'/> + <Entry engineSpeed='2400.00' torque='-122.60' fuelConsumption='0.00'/> + <Entry engineSpeed='2400.00' torque='0.00' fuelConsumption='4500.17'/> + <Entry engineSpeed='2400.00' torque='63.70' fuelConsumption='5673.27'/> + <Entry engineSpeed='2400.00' torque='91.00' fuelConsumption='6848.54'/> + <Entry engineSpeed='2400.00' torque='182.01' fuelConsumption='10766.15'/> + <Entry engineSpeed='2400.00' torque='273.01' fuelConsumption='14963.98'/> + <Entry engineSpeed='2400.00' torque='364.01' fuelConsumption='19391.00'/> + <Entry engineSpeed='2400.00' torque='455.01' fuelConsumption='23957.03'/> + <Entry engineSpeed='2400.00' torque='546.02' fuelConsumption='28516.04'/> + <Entry engineSpeed='2400.00' torque='637.02' fuelConsumption='33412.68'/> + <Entry engineSpeed='2400.00' torque='728.02' fuelConsumption='38318.27'/> + <Entry engineSpeed='2400.00' torque='741.99' fuelConsumption='38989.24'/> + <Entry engineSpeed='2500.00' torque='-126.66' fuelConsumption='0.00'/> + <Entry engineSpeed='2500.00' torque='0.00' fuelConsumption='4857.60'/> + <Entry engineSpeed='2500.00' torque='63.70' fuelConsumption='5721.11'/> + <Entry engineSpeed='2500.00' torque='91.00' fuelConsumption='7036.25'/> + <Entry engineSpeed='2500.00' torque='182.01' fuelConsumption='11272.41'/> + <Entry engineSpeed='2500.00' torque='273.01' fuelConsumption='15682.12'/> + <Entry engineSpeed='2500.00' torque='364.01' fuelConsumption='20326.33'/> + <Entry engineSpeed='2500.00' torque='455.01' fuelConsumption='25430.26'/> + <Entry engineSpeed='2500.00' torque='546.02' fuelConsumption='30212.78'/> + <Entry engineSpeed='2500.00' torque='646.12' fuelConsumption='35844.80'/> + <Entry engineSpeed='2600.00' torque='-132.07' fuelConsumption='0.00'/> + <Entry engineSpeed='2600.00' torque='0.00' fuelConsumption='5036.31'/> + </FuelConsumptionMap> + + <FullLoadAndDragCurve> + <Entry engineSpeed='600.00' maxTorque='546.02' dragTorque='-39.66'/> + <Entry engineSpeed='800.00' maxTorque='760.78' dragTorque='-48.83'/> + <Entry engineSpeed='1000.00' maxTorque='973.29' dragTorque='-56.44'/> + <Entry engineSpeed='1200.00' maxTorque='1092.03' dragTorque='-67.29'/> + <Entry engineSpeed='1400.00' maxTorque='1092.03' dragTorque='-77.58'/> + <Entry engineSpeed='1600.00' maxTorque='1092.03' dragTorque='-87.88'/> + <Entry engineSpeed='1800.00' maxTorque='1022.52' dragTorque='-94.11'/> + <Entry engineSpeed='2000.00' maxTorque='944.17' dragTorque='-100.76'/> + <Entry engineSpeed='2200.00' maxTorque='868.12' dragTorque='-113.36'/> + <Entry engineSpeed='2400.00' maxTorque='741.99' dragTorque='-122.60'/> + <Entry engineSpeed='2500.00' maxTorque='647.29' dragTorque='-126.66'/> + <Entry engineSpeed='2600.00' maxTorque='0.00' dragTorque='-132.07'/> + </FullLoadAndDragCurve> + </v2.0:Data> + <Signature> + <di:Reference URI="#ENG-gooZah3D"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization"/> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <di:DigestValue>sNtMe9udO39TyKXzgwYEpVKImWizFalaBVqq3jLktuo=</di:DigestValue> + </di:Reference> + </Signature> + </v2.6:Engine> + <v2.6:Gearbox xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:type="GearboxComponentDeclarationType"> + <Data id="gbx-vi2Oak2N" xsi:type="GearboxDataDeclarationType"> + <Manufacturer>Generic Gearbox Manufacturer</Manufacturer> + <Model>AT 6 Gear</Model> + <CertificationNumber>e12*0815/8051*2017/05E0000*00</CertificationNumber> + <Date>2017-01-11T11:00:00Z</Date> + <AppVersion>3.0.1</AppVersion> + <TransmissionType>APT-S</TransmissionType> + <MainCertificationMethod>Standard values</MainCertificationMethod> + <Gears xsi:type="GearsDeclarationType"> + <Gear number="1"> + <Ratio>3.364</Ratio> + <MaxTorque>1900</MaxTorque> + <MaxSpeed>2500</MaxSpeed> + <TorqueLossMap> + <Entry inputSpeed='0.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='0.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='0.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='600.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='600.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='600.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='600.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='600.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='600.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='200.00' torqueLoss='65.00'/> + <Entry inputSpeed='900.00' inputTorque='400.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='600.00' torqueLoss='81.00'/> + <Entry inputSpeed='900.00' inputTorque='900.00' torqueLoss='93.00'/> + <Entry inputSpeed='900.00' inputTorque='1200.00' torqueLoss='105.00'/> + <Entry inputSpeed='900.00' inputTorque='1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='900.00' inputTorque='2000.00' torqueLoss='137.00'/> + <Entry inputSpeed='900.00' inputTorque='2500.00' torqueLoss='157.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='200.00' torqueLoss='74.00'/> + <Entry inputSpeed='1200.00' inputTorque='400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='600.00' torqueLoss='90.00'/> + <Entry inputSpeed='1200.00' inputTorque='900.00' torqueLoss='102.00'/> + <Entry inputSpeed='1200.00' inputTorque='1200.00' torqueLoss='114.00'/> + <Entry inputSpeed='1200.00' inputTorque='1600.00' torqueLoss='130.00'/> + <Entry inputSpeed='1200.00' inputTorque='2000.00' torqueLoss='146.00'/> + <Entry inputSpeed='1200.00' inputTorque='2500.00' torqueLoss='166.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='200.00' torqueLoss='86.00'/> + <Entry inputSpeed='1600.00' inputTorque='400.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='600.00' torqueLoss='102.00'/> + <Entry inputSpeed='1600.00' inputTorque='900.00' torqueLoss='114.00'/> + <Entry inputSpeed='1600.00' inputTorque='1200.00' torqueLoss='126.00'/> + <Entry inputSpeed='1600.00' inputTorque='1600.00' torqueLoss='142.00'/> + <Entry inputSpeed='1600.00' inputTorque='2000.00' torqueLoss='158.00'/> + <Entry inputSpeed='1600.00' inputTorque='2500.00' torqueLoss='178.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='200.00' torqueLoss='98.00'/> + <Entry inputSpeed='2000.00' inputTorque='400.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='600.00' torqueLoss='114.00'/> + <Entry inputSpeed='2000.00' inputTorque='900.00' torqueLoss='126.00'/> + <Entry inputSpeed='2000.00' inputTorque='1200.00' torqueLoss='138.00'/> + <Entry inputSpeed='2000.00' inputTorque='1600.00' torqueLoss='154.00'/> + <Entry inputSpeed='2000.00' inputTorque='2000.00' torqueLoss='170.00'/> + <Entry inputSpeed='2000.00' inputTorque='2500.00' torqueLoss='190.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='200.00' torqueLoss='113.00'/> + <Entry inputSpeed='2500.00' inputTorque='400.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='600.00' torqueLoss='129.00'/> + <Entry inputSpeed='2500.00' inputTorque='900.00' torqueLoss='141.00'/> + <Entry inputSpeed='2500.00' inputTorque='1200.00' torqueLoss='153.00'/> + <Entry inputSpeed='2500.00' inputTorque='1600.00' torqueLoss='169.00'/> + <Entry inputSpeed='2500.00' inputTorque='2000.00' torqueLoss='185.00'/> + <Entry inputSpeed='2500.00' inputTorque='2500.00' torqueLoss='205.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='200.00' torqueLoss='128.00'/> + <Entry inputSpeed='3000.00' inputTorque='400.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='600.00' torqueLoss='144.00'/> + <Entry inputSpeed='3000.00' inputTorque='900.00' torqueLoss='156.00'/> + <Entry inputSpeed='3000.00' inputTorque='1200.00' torqueLoss='168.00'/> + <Entry inputSpeed='3000.00' inputTorque='1600.00' torqueLoss='184.00'/> + <Entry inputSpeed='3000.00' inputTorque='2000.00' torqueLoss='200.00'/> + <Entry inputSpeed='3000.00' inputTorque='2500.00' torqueLoss='220.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='600.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='600.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='600.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='600.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='600.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='600.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='-200.00' torqueLoss='65.00'/> + <Entry inputSpeed='900.00' inputTorque='-400.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='-600.00' torqueLoss='81.00'/> + <Entry inputSpeed='900.00' inputTorque='-900.00' torqueLoss='93.00'/> + <Entry inputSpeed='900.00' inputTorque='-1200.00' torqueLoss='105.00'/> + <Entry inputSpeed='900.00' inputTorque='-1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='900.00' inputTorque='-2000.00' torqueLoss='137.00'/> + <Entry inputSpeed='900.00' inputTorque='-2500.00' torqueLoss='157.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='-200.00' torqueLoss='74.00'/> + <Entry inputSpeed='1200.00' inputTorque='-400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='-600.00' torqueLoss='90.00'/> + <Entry inputSpeed='1200.00' inputTorque='-900.00' torqueLoss='102.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1200.00' torqueLoss='114.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1600.00' torqueLoss='130.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2000.00' torqueLoss='146.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2500.00' torqueLoss='166.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='-200.00' torqueLoss='86.00'/> + <Entry inputSpeed='1600.00' inputTorque='-400.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='-600.00' torqueLoss='102.00'/> + <Entry inputSpeed='1600.00' inputTorque='-900.00' torqueLoss='114.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1200.00' torqueLoss='126.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1600.00' torqueLoss='142.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2000.00' torqueLoss='158.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2500.00' torqueLoss='178.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='-200.00' torqueLoss='98.00'/> + <Entry inputSpeed='2000.00' inputTorque='-400.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='-600.00' torqueLoss='114.00'/> + <Entry inputSpeed='2000.00' inputTorque='-900.00' torqueLoss='126.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1200.00' torqueLoss='138.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1600.00' torqueLoss='154.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2000.00' torqueLoss='170.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2500.00' torqueLoss='190.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='-200.00' torqueLoss='113.00'/> + <Entry inputSpeed='2500.00' inputTorque='-400.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='-600.00' torqueLoss='129.00'/> + <Entry inputSpeed='2500.00' inputTorque='-900.00' torqueLoss='141.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1200.00' torqueLoss='153.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1600.00' torqueLoss='169.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2000.00' torqueLoss='185.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2500.00' torqueLoss='205.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='-200.00' torqueLoss='128.00'/> + <Entry inputSpeed='3000.00' inputTorque='-400.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='-600.00' torqueLoss='144.00'/> + <Entry inputSpeed='3000.00' inputTorque='-900.00' torqueLoss='156.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1200.00' torqueLoss='168.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1600.00' torqueLoss='184.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2000.00' torqueLoss='200.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2500.00' torqueLoss='220.00'/> + <Entry inputSpeed='1300.00' inputTorque='2610.00' torqueLoss='66.00'/> + <Entry inputSpeed='1300.00' inputTorque='2842.00' torqueLoss='71.00'/> + <Entry inputSpeed='1500.00' inputTorque='-812.00' torqueLoss='46.00'/> + <Entry inputSpeed='1500.00' inputTorque='-348.00' torqueLoss='37.00'/> + <Entry inputSpeed='1500.00' inputTorque='0.00' torqueLoss='13.00'/> + <Entry inputSpeed='1500.00' inputTorque='58.00' torqueLoss='16.00'/> + <Entry inputSpeed='1500.00' inputTorque='290.00' torqueLoss='21.00'/> + <Entry inputSpeed='1500.00' inputTorque='522.00' torqueLoss='26.00'/> + <Entry inputSpeed='1500.00' inputTorque='754.00' torqueLoss='30.00'/> + <Entry inputSpeed='1500.00' inputTorque='986.00' torqueLoss='35.00'/> + <Entry inputSpeed='1500.00' inputTorque='1218.00' torqueLoss='39.00'/> + <Entry inputSpeed='1500.00' inputTorque='1450.00' torqueLoss='44.00'/> + <Entry inputSpeed='1500.00' inputTorque='1682.00' torqueLoss='49.00'/> + <Entry inputSpeed='1500.00' inputTorque='1914.00' torqueLoss='53.00'/> + <Entry inputSpeed='1500.00' inputTorque='2146.00' torqueLoss='58.00'/> + <Entry inputSpeed='1500.00' inputTorque='2378.00' torqueLoss='63.00'/> + <Entry inputSpeed='1500.00' inputTorque='2610.00' torqueLoss='67.00'/> + <Entry inputSpeed='1500.00' inputTorque='2842.00' torqueLoss='72.00'/> + <Entry inputSpeed='1700.00' inputTorque='-812.00' torqueLoss='49.00'/> + <Entry inputSpeed='1700.00' inputTorque='-348.00' torqueLoss='39.00'/> + <Entry inputSpeed='1700.00' inputTorque='0.00' torqueLoss='14.00'/> + <Entry inputSpeed='1700.00' inputTorque='58.00' torqueLoss='17.00'/> + <Entry inputSpeed='1700.00' inputTorque='290.00' torqueLoss='22.00'/> + <Entry inputSpeed='1700.00' inputTorque='522.00' torqueLoss='27.00'/> + <Entry inputSpeed='1700.00' inputTorque='754.00' torqueLoss='31.00'/> + <Entry inputSpeed='1700.00' inputTorque='986.00' torqueLoss='36.00'/> + <Entry inputSpeed='1700.00' inputTorque='1218.00' torqueLoss='41.00'/> + <Entry inputSpeed='1700.00' inputTorque='1450.00' torqueLoss='45.00'/> + <Entry inputSpeed='1700.00' inputTorque='1682.00' torqueLoss='50.00'/> + <Entry inputSpeed='1700.00' inputTorque='1914.00' torqueLoss='55.00'/> + <Entry inputSpeed='1700.00' inputTorque='2146.00' torqueLoss='59.00'/> + <Entry inputSpeed='1700.00' inputTorque='2378.00' torqueLoss='64.00'/> + <Entry inputSpeed='1700.00' inputTorque='2610.00' torqueLoss='68.00'/> + <Entry inputSpeed='1700.00' inputTorque='2842.00' torqueLoss='73.00'/> + <Entry inputSpeed='1900.00' inputTorque='-812.00' torqueLoss='51.00'/> + <Entry inputSpeed='1900.00' inputTorque='-348.00' torqueLoss='42.00'/> + <Entry inputSpeed='1900.00' inputTorque='0.00' torqueLoss='15.00'/> + <Entry inputSpeed='1900.00' inputTorque='58.00' torqueLoss='19.00'/> + <Entry inputSpeed='1900.00' inputTorque='290.00' torqueLoss='23.00'/> + <Entry inputSpeed='1900.00' inputTorque='522.00' torqueLoss='28.00'/> + <Entry inputSpeed='1900.00' inputTorque='754.00' torqueLoss='32.00'/> + <Entry inputSpeed='1900.00' inputTorque='986.00' torqueLoss='37.00'/> + <Entry inputSpeed='1900.00' inputTorque='1218.00' torqueLoss='42.00'/> + <Entry inputSpeed='1900.00' inputTorque='1450.00' torqueLoss='46.00'/> + <Entry inputSpeed='1900.00' inputTorque='1682.00' torqueLoss='51.00'/> + <Entry inputSpeed='1900.00' inputTorque='1914.00' torqueLoss='56.00'/> + <Entry inputSpeed='1900.00' inputTorque='2146.00' torqueLoss='60.00'/> + <Entry inputSpeed='1900.00' inputTorque='2378.00' torqueLoss='65.00'/> + <Entry inputSpeed='1900.00' inputTorque='2610.00' torqueLoss='70.00'/> + <Entry inputSpeed='1900.00' inputTorque='2842.00' torqueLoss='74.00'/> + <Entry inputSpeed='2100.00' inputTorque='-812.00' torqueLoss='53.00'/> + <Entry inputSpeed='2100.00' inputTorque='-348.00' torqueLoss='44.00'/> + <Entry inputSpeed='2100.00' inputTorque='0.00' torqueLoss='16.00'/> + <Entry inputSpeed='2100.00' inputTorque='58.00' torqueLoss='20.00'/> + <Entry inputSpeed='2100.00' inputTorque='290.00' torqueLoss='24.00'/> + <Entry inputSpeed='2100.00' inputTorque='522.00' torqueLoss='29.00'/> + <Entry inputSpeed='2100.00' inputTorque='754.00' torqueLoss='34.00'/> + <Entry inputSpeed='2100.00' inputTorque='986.00' torqueLoss='38.00'/> + <Entry inputSpeed='2100.00' inputTorque='1218.00' torqueLoss='43.00'/> + <Entry inputSpeed='2100.00' inputTorque='1450.00' torqueLoss='48.00'/> + <Entry inputSpeed='2100.00' inputTorque='1682.00' torqueLoss='52.00'/> + <Entry inputSpeed='2100.00' inputTorque='1914.00' torqueLoss='57.00'/> + <Entry inputSpeed='2100.00' inputTorque='2146.00' torqueLoss='61.00'/> + <Entry inputSpeed='2100.00' inputTorque='2378.00' torqueLoss='66.00'/> + <Entry inputSpeed='2100.00' inputTorque='2610.00' torqueLoss='71.00'/> + <Entry inputSpeed='2100.00' inputTorque='2842.00' torqueLoss='75.00'/> + </TorqueLossMap> + </Gear> + <Gear number="2"> + <Ratio>1.909</Ratio> + <MaxTorque>1900</MaxTorque> + <MaxSpeed>2500</MaxSpeed> + <TorqueLossMap> + <Entry inputSpeed='0.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='0.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='0.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='600.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='600.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='600.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='600.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='600.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='600.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='200.00' torqueLoss='65.00'/> + <Entry inputSpeed='900.00' inputTorque='400.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='600.00' torqueLoss='81.00'/> + <Entry inputSpeed='900.00' inputTorque='900.00' torqueLoss='93.00'/> + <Entry inputSpeed='900.00' inputTorque='1200.00' torqueLoss='105.00'/> + <Entry inputSpeed='900.00' inputTorque='1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='900.00' inputTorque='2000.00' torqueLoss='137.00'/> + <Entry inputSpeed='900.00' inputTorque='2500.00' torqueLoss='157.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='200.00' torqueLoss='74.00'/> + <Entry inputSpeed='1200.00' inputTorque='400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='600.00' torqueLoss='90.00'/> + <Entry inputSpeed='1200.00' inputTorque='900.00' torqueLoss='102.00'/> + <Entry inputSpeed='1200.00' inputTorque='1200.00' torqueLoss='114.00'/> + <Entry inputSpeed='1200.00' inputTorque='1600.00' torqueLoss='130.00'/> + <Entry inputSpeed='1200.00' inputTorque='2000.00' torqueLoss='146.00'/> + <Entry inputSpeed='1200.00' inputTorque='2500.00' torqueLoss='166.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='200.00' torqueLoss='86.00'/> + <Entry inputSpeed='1600.00' inputTorque='400.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='600.00' torqueLoss='102.00'/> + <Entry inputSpeed='1600.00' inputTorque='900.00' torqueLoss='114.00'/> + <Entry inputSpeed='1600.00' inputTorque='1200.00' torqueLoss='126.00'/> + <Entry inputSpeed='1600.00' inputTorque='1600.00' torqueLoss='142.00'/> + <Entry inputSpeed='1600.00' inputTorque='2000.00' torqueLoss='158.00'/> + <Entry inputSpeed='1600.00' inputTorque='2500.00' torqueLoss='178.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='200.00' torqueLoss='98.00'/> + <Entry inputSpeed='2000.00' inputTorque='400.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='600.00' torqueLoss='114.00'/> + <Entry inputSpeed='2000.00' inputTorque='900.00' torqueLoss='126.00'/> + <Entry inputSpeed='2000.00' inputTorque='1200.00' torqueLoss='138.00'/> + <Entry inputSpeed='2000.00' inputTorque='1600.00' torqueLoss='154.00'/> + <Entry inputSpeed='2000.00' inputTorque='2000.00' torqueLoss='170.00'/> + <Entry inputSpeed='2000.00' inputTorque='2500.00' torqueLoss='190.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='200.00' torqueLoss='113.00'/> + <Entry inputSpeed='2500.00' inputTorque='400.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='600.00' torqueLoss='129.00'/> + <Entry inputSpeed='2500.00' inputTorque='900.00' torqueLoss='141.00'/> + <Entry inputSpeed='2500.00' inputTorque='1200.00' torqueLoss='153.00'/> + <Entry inputSpeed='2500.00' inputTorque='1600.00' torqueLoss='169.00'/> + <Entry inputSpeed='2500.00' inputTorque='2000.00' torqueLoss='185.00'/> + <Entry inputSpeed='2500.00' inputTorque='2500.00' torqueLoss='205.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='200.00' torqueLoss='128.00'/> + <Entry inputSpeed='3000.00' inputTorque='400.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='600.00' torqueLoss='144.00'/> + <Entry inputSpeed='3000.00' inputTorque='900.00' torqueLoss='156.00'/> + <Entry inputSpeed='3000.00' inputTorque='1200.00' torqueLoss='168.00'/> + <Entry inputSpeed='3000.00' inputTorque='1600.00' torqueLoss='184.00'/> + <Entry inputSpeed='3000.00' inputTorque='2000.00' torqueLoss='200.00'/> + <Entry inputSpeed='3000.00' inputTorque='2500.00' torqueLoss='220.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='600.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='600.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='600.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='600.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='600.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='600.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='-200.00' torqueLoss='65.00'/> + <Entry inputSpeed='900.00' inputTorque='-400.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='-600.00' torqueLoss='81.00'/> + <Entry inputSpeed='900.00' inputTorque='-900.00' torqueLoss='93.00'/> + <Entry inputSpeed='900.00' inputTorque='-1200.00' torqueLoss='105.00'/> + <Entry inputSpeed='900.00' inputTorque='-1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='900.00' inputTorque='-2000.00' torqueLoss='137.00'/> + <Entry inputSpeed='900.00' inputTorque='-2500.00' torqueLoss='157.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='-200.00' torqueLoss='74.00'/> + <Entry inputSpeed='1200.00' inputTorque='-400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='-600.00' torqueLoss='90.00'/> + <Entry inputSpeed='1200.00' inputTorque='-900.00' torqueLoss='102.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1200.00' torqueLoss='114.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1600.00' torqueLoss='130.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2000.00' torqueLoss='146.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2500.00' torqueLoss='166.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='-200.00' torqueLoss='86.00'/> + <Entry inputSpeed='1600.00' inputTorque='-400.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='-600.00' torqueLoss='102.00'/> + <Entry inputSpeed='1600.00' inputTorque='-900.00' torqueLoss='114.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1200.00' torqueLoss='126.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1600.00' torqueLoss='142.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2000.00' torqueLoss='158.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2500.00' torqueLoss='178.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='-200.00' torqueLoss='98.00'/> + <Entry inputSpeed='2000.00' inputTorque='-400.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='-600.00' torqueLoss='114.00'/> + <Entry inputSpeed='2000.00' inputTorque='-900.00' torqueLoss='126.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1200.00' torqueLoss='138.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1600.00' torqueLoss='154.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2000.00' torqueLoss='170.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2500.00' torqueLoss='190.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='-200.00' torqueLoss='113.00'/> + <Entry inputSpeed='2500.00' inputTorque='-400.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='-600.00' torqueLoss='129.00'/> + <Entry inputSpeed='2500.00' inputTorque='-900.00' torqueLoss='141.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1200.00' torqueLoss='153.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1600.00' torqueLoss='169.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2000.00' torqueLoss='185.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2500.00' torqueLoss='205.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='-200.00' torqueLoss='128.00'/> + <Entry inputSpeed='3000.00' inputTorque='-400.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='-600.00' torqueLoss='144.00'/> + <Entry inputSpeed='3000.00' inputTorque='-900.00' torqueLoss='156.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1200.00' torqueLoss='168.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1600.00' torqueLoss='184.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2000.00' torqueLoss='200.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2500.00' torqueLoss='220.00'/> + </TorqueLossMap> + </Gear> + <Gear number="3"> + <Ratio>1.421</Ratio> + <MaxSpeed>2500</MaxSpeed> + <TorqueLossMap> + <Entry inputSpeed='0.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='0.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='0.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='600.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='600.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='600.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='600.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='600.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='600.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='200.00' torqueLoss='65.00'/> + <Entry inputSpeed='900.00' inputTorque='400.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='600.00' torqueLoss='81.00'/> + <Entry inputSpeed='900.00' inputTorque='900.00' torqueLoss='93.00'/> + <Entry inputSpeed='900.00' inputTorque='1200.00' torqueLoss='105.00'/> + <Entry inputSpeed='900.00' inputTorque='1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='900.00' inputTorque='2000.00' torqueLoss='137.00'/> + <Entry inputSpeed='900.00' inputTorque='2500.00' torqueLoss='157.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='200.00' torqueLoss='74.00'/> + <Entry inputSpeed='1200.00' inputTorque='400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='600.00' torqueLoss='90.00'/> + <Entry inputSpeed='1200.00' inputTorque='900.00' torqueLoss='102.00'/> + <Entry inputSpeed='1200.00' inputTorque='1200.00' torqueLoss='114.00'/> + <Entry inputSpeed='1200.00' inputTorque='1600.00' torqueLoss='130.00'/> + <Entry inputSpeed='1200.00' inputTorque='2000.00' torqueLoss='146.00'/> + <Entry inputSpeed='1200.00' inputTorque='2500.00' torqueLoss='166.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='200.00' torqueLoss='86.00'/> + <Entry inputSpeed='1600.00' inputTorque='400.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='600.00' torqueLoss='102.00'/> + <Entry inputSpeed='1600.00' inputTorque='900.00' torqueLoss='114.00'/> + <Entry inputSpeed='1600.00' inputTorque='1200.00' torqueLoss='126.00'/> + <Entry inputSpeed='1600.00' inputTorque='1600.00' torqueLoss='142.00'/> + <Entry inputSpeed='1600.00' inputTorque='2000.00' torqueLoss='158.00'/> + <Entry inputSpeed='1600.00' inputTorque='2500.00' torqueLoss='178.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='200.00' torqueLoss='98.00'/> + <Entry inputSpeed='2000.00' inputTorque='400.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='600.00' torqueLoss='114.00'/> + <Entry inputSpeed='2000.00' inputTorque='900.00' torqueLoss='126.00'/> + <Entry inputSpeed='2000.00' inputTorque='1200.00' torqueLoss='138.00'/> + <Entry inputSpeed='2000.00' inputTorque='1600.00' torqueLoss='154.00'/> + <Entry inputSpeed='2000.00' inputTorque='2000.00' torqueLoss='170.00'/> + <Entry inputSpeed='2000.00' inputTorque='2500.00' torqueLoss='190.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='200.00' torqueLoss='113.00'/> + <Entry inputSpeed='2500.00' inputTorque='400.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='600.00' torqueLoss='129.00'/> + <Entry inputSpeed='2500.00' inputTorque='900.00' torqueLoss='141.00'/> + <Entry inputSpeed='2500.00' inputTorque='1200.00' torqueLoss='153.00'/> + <Entry inputSpeed='2500.00' inputTorque='1600.00' torqueLoss='169.00'/> + <Entry inputSpeed='2500.00' inputTorque='2000.00' torqueLoss='185.00'/> + <Entry inputSpeed='2500.00' inputTorque='2500.00' torqueLoss='205.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='200.00' torqueLoss='128.00'/> + <Entry inputSpeed='3000.00' inputTorque='400.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='600.00' torqueLoss='144.00'/> + <Entry inputSpeed='3000.00' inputTorque='900.00' torqueLoss='156.00'/> + <Entry inputSpeed='3000.00' inputTorque='1200.00' torqueLoss='168.00'/> + <Entry inputSpeed='3000.00' inputTorque='1600.00' torqueLoss='184.00'/> + <Entry inputSpeed='3000.00' inputTorque='2000.00' torqueLoss='200.00'/> + <Entry inputSpeed='3000.00' inputTorque='2500.00' torqueLoss='220.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='600.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='600.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='600.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='600.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='600.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='600.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='-200.00' torqueLoss='65.00'/> + <Entry inputSpeed='900.00' inputTorque='-400.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='-600.00' torqueLoss='81.00'/> + <Entry inputSpeed='900.00' inputTorque='-900.00' torqueLoss='93.00'/> + <Entry inputSpeed='900.00' inputTorque='-1200.00' torqueLoss='105.00'/> + <Entry inputSpeed='900.00' inputTorque='-1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='900.00' inputTorque='-2000.00' torqueLoss='137.00'/> + <Entry inputSpeed='900.00' inputTorque='-2500.00' torqueLoss='157.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='-200.00' torqueLoss='74.00'/> + <Entry inputSpeed='1200.00' inputTorque='-400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='-600.00' torqueLoss='90.00'/> + <Entry inputSpeed='1200.00' inputTorque='-900.00' torqueLoss='102.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1200.00' torqueLoss='114.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1600.00' torqueLoss='130.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2000.00' torqueLoss='146.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2500.00' torqueLoss='166.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='-200.00' torqueLoss='86.00'/> + <Entry inputSpeed='1600.00' inputTorque='-400.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='-600.00' torqueLoss='102.00'/> + <Entry inputSpeed='1600.00' inputTorque='-900.00' torqueLoss='114.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1200.00' torqueLoss='126.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1600.00' torqueLoss='142.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2000.00' torqueLoss='158.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2500.00' torqueLoss='178.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='-200.00' torqueLoss='98.00'/> + <Entry inputSpeed='2000.00' inputTorque='-400.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='-600.00' torqueLoss='114.00'/> + <Entry inputSpeed='2000.00' inputTorque='-900.00' torqueLoss='126.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1200.00' torqueLoss='138.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1600.00' torqueLoss='154.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2000.00' torqueLoss='170.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2500.00' torqueLoss='190.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='-200.00' torqueLoss='113.00'/> + <Entry inputSpeed='2500.00' inputTorque='-400.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='-600.00' torqueLoss='129.00'/> + <Entry inputSpeed='2500.00' inputTorque='-900.00' torqueLoss='141.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1200.00' torqueLoss='153.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1600.00' torqueLoss='169.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2000.00' torqueLoss='185.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2500.00' torqueLoss='205.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='-200.00' torqueLoss='128.00'/> + <Entry inputSpeed='3000.00' inputTorque='-400.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='-600.00' torqueLoss='144.00'/> + <Entry inputSpeed='3000.00' inputTorque='-900.00' torqueLoss='156.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1200.00' torqueLoss='168.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1600.00' torqueLoss='184.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2000.00' torqueLoss='200.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2500.00' torqueLoss='220.00'/> + </TorqueLossMap> + </Gear> + <Gear number="4"> + <Ratio>1.000</Ratio> + <MaxSpeed>2500</MaxSpeed> + <TorqueLossMap> + <Entry inputSpeed='0.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='0.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='0.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='200.00' torqueLoss='50.00'/> + <Entry inputSpeed='600.00' inputTorque='400.00' torqueLoss='52.00'/> + <Entry inputSpeed='600.00' inputTorque='600.00' torqueLoss='54.00'/> + <Entry inputSpeed='600.00' inputTorque='900.00' torqueLoss='57.00'/> + <Entry inputSpeed='600.00' inputTorque='1200.00' torqueLoss='60.00'/> + <Entry inputSpeed='600.00' inputTorque='1600.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='2000.00' torqueLoss='68.00'/> + <Entry inputSpeed='600.00' inputTorque='2500.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='200.00' torqueLoss='59.00'/> + <Entry inputSpeed='900.00' inputTorque='400.00' torqueLoss='61.00'/> + <Entry inputSpeed='900.00' inputTorque='600.00' torqueLoss='63.00'/> + <Entry inputSpeed='900.00' inputTorque='900.00' torqueLoss='66.00'/> + <Entry inputSpeed='900.00' inputTorque='1200.00' torqueLoss='69.00'/> + <Entry inputSpeed='900.00' inputTorque='1600.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='2000.00' torqueLoss='77.00'/> + <Entry inputSpeed='900.00' inputTorque='2500.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='200.00' torqueLoss='68.00'/> + <Entry inputSpeed='1200.00' inputTorque='400.00' torqueLoss='70.00'/> + <Entry inputSpeed='1200.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='1200.00' inputTorque='900.00' torqueLoss='75.00'/> + <Entry inputSpeed='1200.00' inputTorque='1200.00' torqueLoss='78.00'/> + <Entry inputSpeed='1200.00' inputTorque='1600.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='2000.00' torqueLoss='86.00'/> + <Entry inputSpeed='1200.00' inputTorque='2500.00' torqueLoss='91.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='200.00' torqueLoss='80.00'/> + <Entry inputSpeed='1600.00' inputTorque='400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1600.00' inputTorque='600.00' torqueLoss='84.00'/> + <Entry inputSpeed='1600.00' inputTorque='900.00' torqueLoss='87.00'/> + <Entry inputSpeed='1600.00' inputTorque='1200.00' torqueLoss='90.00'/> + <Entry inputSpeed='1600.00' inputTorque='1600.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='2000.00' torqueLoss='98.00'/> + <Entry inputSpeed='1600.00' inputTorque='2500.00' torqueLoss='103.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='200.00' torqueLoss='92.00'/> + <Entry inputSpeed='2000.00' inputTorque='400.00' torqueLoss='94.00'/> + <Entry inputSpeed='2000.00' inputTorque='600.00' torqueLoss='96.00'/> + <Entry inputSpeed='2000.00' inputTorque='900.00' torqueLoss='99.00'/> + <Entry inputSpeed='2000.00' inputTorque='1200.00' torqueLoss='102.00'/> + <Entry inputSpeed='2000.00' inputTorque='1600.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='2000.00' torqueLoss='110.00'/> + <Entry inputSpeed='2000.00' inputTorque='2500.00' torqueLoss='115.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='200.00' torqueLoss='107.00'/> + <Entry inputSpeed='2500.00' inputTorque='400.00' torqueLoss='109.00'/> + <Entry inputSpeed='2500.00' inputTorque='600.00' torqueLoss='111.00'/> + <Entry inputSpeed='2500.00' inputTorque='900.00' torqueLoss='114.00'/> + <Entry inputSpeed='2500.00' inputTorque='1200.00' torqueLoss='117.00'/> + <Entry inputSpeed='2500.00' inputTorque='1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='2000.00' torqueLoss='125.00'/> + <Entry inputSpeed='2500.00' inputTorque='2500.00' torqueLoss='130.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='200.00' torqueLoss='122.00'/> + <Entry inputSpeed='3000.00' inputTorque='400.00' torqueLoss='124.00'/> + <Entry inputSpeed='3000.00' inputTorque='600.00' torqueLoss='126.00'/> + <Entry inputSpeed='3000.00' inputTorque='900.00' torqueLoss='129.00'/> + <Entry inputSpeed='3000.00' inputTorque='1200.00' torqueLoss='132.00'/> + <Entry inputSpeed='3000.00' inputTorque='1600.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='2000.00' torqueLoss='140.00'/> + <Entry inputSpeed='3000.00' inputTorque='2500.00' torqueLoss='145.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='-200.00' torqueLoss='50.00'/> + <Entry inputSpeed='600.00' inputTorque='-400.00' torqueLoss='52.00'/> + <Entry inputSpeed='600.00' inputTorque='-600.00' torqueLoss='54.00'/> + <Entry inputSpeed='600.00' inputTorque='-900.00' torqueLoss='57.00'/> + <Entry inputSpeed='600.00' inputTorque='-1200.00' torqueLoss='60.00'/> + <Entry inputSpeed='600.00' inputTorque='-1600.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='-2000.00' torqueLoss='68.00'/> + <Entry inputSpeed='600.00' inputTorque='-2500.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='-200.00' torqueLoss='59.00'/> + <Entry inputSpeed='900.00' inputTorque='-400.00' torqueLoss='61.00'/> + <Entry inputSpeed='900.00' inputTorque='-600.00' torqueLoss='63.00'/> + <Entry inputSpeed='900.00' inputTorque='-900.00' torqueLoss='66.00'/> + <Entry inputSpeed='900.00' inputTorque='-1200.00' torqueLoss='69.00'/> + <Entry inputSpeed='900.00' inputTorque='-1600.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='-2000.00' torqueLoss='77.00'/> + <Entry inputSpeed='900.00' inputTorque='-2500.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='-200.00' torqueLoss='68.00'/> + <Entry inputSpeed='1200.00' inputTorque='-400.00' torqueLoss='70.00'/> + <Entry inputSpeed='1200.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='1200.00' inputTorque='-900.00' torqueLoss='75.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1200.00' torqueLoss='78.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1600.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2000.00' torqueLoss='86.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2500.00' torqueLoss='91.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='-200.00' torqueLoss='80.00'/> + <Entry inputSpeed='1600.00' inputTorque='-400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1600.00' inputTorque='-600.00' torqueLoss='84.00'/> + <Entry inputSpeed='1600.00' inputTorque='-900.00' torqueLoss='87.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1200.00' torqueLoss='90.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1600.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2000.00' torqueLoss='98.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2500.00' torqueLoss='103.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='-200.00' torqueLoss='92.00'/> + <Entry inputSpeed='2000.00' inputTorque='-400.00' torqueLoss='94.00'/> + <Entry inputSpeed='2000.00' inputTorque='-600.00' torqueLoss='96.00'/> + <Entry inputSpeed='2000.00' inputTorque='-900.00' torqueLoss='99.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1200.00' torqueLoss='102.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1600.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2000.00' torqueLoss='110.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2500.00' torqueLoss='115.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='-200.00' torqueLoss='107.00'/> + <Entry inputSpeed='2500.00' inputTorque='-400.00' torqueLoss='109.00'/> + <Entry inputSpeed='2500.00' inputTorque='-600.00' torqueLoss='111.00'/> + <Entry inputSpeed='2500.00' inputTorque='-900.00' torqueLoss='114.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1200.00' torqueLoss='117.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2000.00' torqueLoss='125.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2500.00' torqueLoss='130.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='-200.00' torqueLoss='122.00'/> + <Entry inputSpeed='3000.00' inputTorque='-400.00' torqueLoss='124.00'/> + <Entry inputSpeed='3000.00' inputTorque='-600.00' torqueLoss='126.00'/> + <Entry inputSpeed='3000.00' inputTorque='-900.00' torqueLoss='129.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1200.00' torqueLoss='132.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1600.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2000.00' torqueLoss='140.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2500.00' torqueLoss='145.00'/> + </TorqueLossMap> + </Gear> + <Gear number="5"> + <Ratio>0.720</Ratio> + <MaxSpeed>2500</MaxSpeed> + <TorqueLossMap> + <Entry inputSpeed='0.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='0.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='0.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='600.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='600.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='600.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='600.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='600.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='600.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='200.00' torqueLoss='65.00'/> + <Entry inputSpeed='900.00' inputTorque='400.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='600.00' torqueLoss='81.00'/> + <Entry inputSpeed='900.00' inputTorque='900.00' torqueLoss='93.00'/> + <Entry inputSpeed='900.00' inputTorque='1200.00' torqueLoss='105.00'/> + <Entry inputSpeed='900.00' inputTorque='1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='900.00' inputTorque='2000.00' torqueLoss='137.00'/> + <Entry inputSpeed='900.00' inputTorque='2500.00' torqueLoss='157.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='200.00' torqueLoss='74.00'/> + <Entry inputSpeed='1200.00' inputTorque='400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='600.00' torqueLoss='90.00'/> + <Entry inputSpeed='1200.00' inputTorque='900.00' torqueLoss='102.00'/> + <Entry inputSpeed='1200.00' inputTorque='1200.00' torqueLoss='114.00'/> + <Entry inputSpeed='1200.00' inputTorque='1600.00' torqueLoss='130.00'/> + <Entry inputSpeed='1200.00' inputTorque='2000.00' torqueLoss='146.00'/> + <Entry inputSpeed='1200.00' inputTorque='2500.00' torqueLoss='166.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='200.00' torqueLoss='86.00'/> + <Entry inputSpeed='1600.00' inputTorque='400.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='600.00' torqueLoss='102.00'/> + <Entry inputSpeed='1600.00' inputTorque='900.00' torqueLoss='114.00'/> + <Entry inputSpeed='1600.00' inputTorque='1200.00' torqueLoss='126.00'/> + <Entry inputSpeed='1600.00' inputTorque='1600.00' torqueLoss='142.00'/> + <Entry inputSpeed='1600.00' inputTorque='2000.00' torqueLoss='158.00'/> + <Entry inputSpeed='1600.00' inputTorque='2500.00' torqueLoss='178.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='200.00' torqueLoss='98.00'/> + <Entry inputSpeed='2000.00' inputTorque='400.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='600.00' torqueLoss='114.00'/> + <Entry inputSpeed='2000.00' inputTorque='900.00' torqueLoss='126.00'/> + <Entry inputSpeed='2000.00' inputTorque='1200.00' torqueLoss='138.00'/> + <Entry inputSpeed='2000.00' inputTorque='1600.00' torqueLoss='154.00'/> + <Entry inputSpeed='2000.00' inputTorque='2000.00' torqueLoss='170.00'/> + <Entry inputSpeed='2000.00' inputTorque='2500.00' torqueLoss='190.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='200.00' torqueLoss='113.00'/> + <Entry inputSpeed='2500.00' inputTorque='400.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='600.00' torqueLoss='129.00'/> + <Entry inputSpeed='2500.00' inputTorque='900.00' torqueLoss='141.00'/> + <Entry inputSpeed='2500.00' inputTorque='1200.00' torqueLoss='153.00'/> + <Entry inputSpeed='2500.00' inputTorque='1600.00' torqueLoss='169.00'/> + <Entry inputSpeed='2500.00' inputTorque='2000.00' torqueLoss='185.00'/> + <Entry inputSpeed='2500.00' inputTorque='2500.00' torqueLoss='205.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='200.00' torqueLoss='128.00'/> + <Entry inputSpeed='3000.00' inputTorque='400.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='600.00' torqueLoss='144.00'/> + <Entry inputSpeed='3000.00' inputTorque='900.00' torqueLoss='156.00'/> + <Entry inputSpeed='3000.00' inputTorque='1200.00' torqueLoss='168.00'/> + <Entry inputSpeed='3000.00' inputTorque='1600.00' torqueLoss='184.00'/> + <Entry inputSpeed='3000.00' inputTorque='2000.00' torqueLoss='200.00'/> + <Entry inputSpeed='3000.00' inputTorque='2500.00' torqueLoss='220.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='600.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='600.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='600.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='600.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='600.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='600.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='-200.00' torqueLoss='65.00'/> + <Entry inputSpeed='900.00' inputTorque='-400.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='-600.00' torqueLoss='81.00'/> + <Entry inputSpeed='900.00' inputTorque='-900.00' torqueLoss='93.00'/> + <Entry inputSpeed='900.00' inputTorque='-1200.00' torqueLoss='105.00'/> + <Entry inputSpeed='900.00' inputTorque='-1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='900.00' inputTorque='-2000.00' torqueLoss='137.00'/> + <Entry inputSpeed='900.00' inputTorque='-2500.00' torqueLoss='157.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='-200.00' torqueLoss='74.00'/> + <Entry inputSpeed='1200.00' inputTorque='-400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='-600.00' torqueLoss='90.00'/> + <Entry inputSpeed='1200.00' inputTorque='-900.00' torqueLoss='102.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1200.00' torqueLoss='114.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1600.00' torqueLoss='130.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2000.00' torqueLoss='146.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2500.00' torqueLoss='166.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='-200.00' torqueLoss='86.00'/> + <Entry inputSpeed='1600.00' inputTorque='-400.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='-600.00' torqueLoss='102.00'/> + <Entry inputSpeed='1600.00' inputTorque='-900.00' torqueLoss='114.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1200.00' torqueLoss='126.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1600.00' torqueLoss='142.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2000.00' torqueLoss='158.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2500.00' torqueLoss='178.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='-200.00' torqueLoss='98.00'/> + <Entry inputSpeed='2000.00' inputTorque='-400.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='-600.00' torqueLoss='114.00'/> + <Entry inputSpeed='2000.00' inputTorque='-900.00' torqueLoss='126.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1200.00' torqueLoss='138.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1600.00' torqueLoss='154.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2000.00' torqueLoss='170.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2500.00' torqueLoss='190.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='-200.00' torqueLoss='113.00'/> + <Entry inputSpeed='2500.00' inputTorque='-400.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='-600.00' torqueLoss='129.00'/> + <Entry inputSpeed='2500.00' inputTorque='-900.00' torqueLoss='141.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1200.00' torqueLoss='153.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1600.00' torqueLoss='169.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2000.00' torqueLoss='185.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2500.00' torqueLoss='205.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='-200.00' torqueLoss='128.00'/> + <Entry inputSpeed='3000.00' inputTorque='-400.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='-600.00' torqueLoss='144.00'/> + <Entry inputSpeed='3000.00' inputTorque='-900.00' torqueLoss='156.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1200.00' torqueLoss='168.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1600.00' torqueLoss='184.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2000.00' torqueLoss='200.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2500.00' torqueLoss='220.00'/> + </TorqueLossMap> + </Gear> + <Gear number="6"> + <Ratio>0.615</Ratio> + <MaxSpeed>2500</MaxSpeed> + <TorqueLossMap> + <Entry inputSpeed='0.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='0.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='0.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='0.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='0.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='0.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='0.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='0.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='0.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='0.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='200.00' torqueLoss='56.00'/> + <Entry inputSpeed='600.00' inputTorque='400.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='600.00' torqueLoss='72.00'/> + <Entry inputSpeed='600.00' inputTorque='900.00' torqueLoss='84.00'/> + <Entry inputSpeed='600.00' inputTorque='1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='600.00' inputTorque='1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='600.00' inputTorque='2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='600.00' inputTorque='2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='200.00' torqueLoss='65.00'/> + <Entry inputSpeed='900.00' inputTorque='400.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='600.00' torqueLoss='81.00'/> + <Entry inputSpeed='900.00' inputTorque='900.00' torqueLoss='93.00'/> + <Entry inputSpeed='900.00' inputTorque='1200.00' torqueLoss='105.00'/> + <Entry inputSpeed='900.00' inputTorque='1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='900.00' inputTorque='2000.00' torqueLoss='137.00'/> + <Entry inputSpeed='900.00' inputTorque='2500.00' torqueLoss='157.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='200.00' torqueLoss='74.00'/> + <Entry inputSpeed='1200.00' inputTorque='400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='600.00' torqueLoss='90.00'/> + <Entry inputSpeed='1200.00' inputTorque='900.00' torqueLoss='102.00'/> + <Entry inputSpeed='1200.00' inputTorque='1200.00' torqueLoss='114.00'/> + <Entry inputSpeed='1200.00' inputTorque='1600.00' torqueLoss='130.00'/> + <Entry inputSpeed='1200.00' inputTorque='2000.00' torqueLoss='146.00'/> + <Entry inputSpeed='1200.00' inputTorque='2500.00' torqueLoss='166.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='200.00' torqueLoss='86.00'/> + <Entry inputSpeed='1600.00' inputTorque='400.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='600.00' torqueLoss='102.00'/> + <Entry inputSpeed='1600.00' inputTorque='900.00' torqueLoss='114.00'/> + <Entry inputSpeed='1600.00' inputTorque='1200.00' torqueLoss='126.00'/> + <Entry inputSpeed='1600.00' inputTorque='1600.00' torqueLoss='142.00'/> + <Entry inputSpeed='1600.00' inputTorque='2000.00' torqueLoss='158.00'/> + <Entry inputSpeed='1600.00' inputTorque='2500.00' torqueLoss='178.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='200.00' torqueLoss='98.00'/> + <Entry inputSpeed='2000.00' inputTorque='400.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='600.00' torqueLoss='114.00'/> + <Entry inputSpeed='2000.00' inputTorque='900.00' torqueLoss='126.00'/> + <Entry inputSpeed='2000.00' inputTorque='1200.00' torqueLoss='138.00'/> + <Entry inputSpeed='2000.00' inputTorque='1600.00' torqueLoss='154.00'/> + <Entry inputSpeed='2000.00' inputTorque='2000.00' torqueLoss='170.00'/> + <Entry inputSpeed='2000.00' inputTorque='2500.00' torqueLoss='190.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='200.00' torqueLoss='113.00'/> + <Entry inputSpeed='2500.00' inputTorque='400.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='600.00' torqueLoss='129.00'/> + <Entry inputSpeed='2500.00' inputTorque='900.00' torqueLoss='141.00'/> + <Entry inputSpeed='2500.00' inputTorque='1200.00' torqueLoss='153.00'/> + <Entry inputSpeed='2500.00' inputTorque='1600.00' torqueLoss='169.00'/> + <Entry inputSpeed='2500.00' inputTorque='2000.00' torqueLoss='185.00'/> + <Entry inputSpeed='2500.00' inputTorque='2500.00' torqueLoss='205.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='200.00' torqueLoss='128.00'/> + <Entry inputSpeed='3000.00' inputTorque='400.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='600.00' torqueLoss='144.00'/> + <Entry inputSpeed='3000.00' inputTorque='900.00' torqueLoss='156.00'/> + <Entry inputSpeed='3000.00' inputTorque='1200.00' torqueLoss='168.00'/> + <Entry inputSpeed='3000.00' inputTorque='1600.00' torqueLoss='184.00'/> + <Entry inputSpeed='3000.00' inputTorque='2000.00' torqueLoss='200.00'/> + <Entry inputSpeed='3000.00' inputTorque='2500.00' torqueLoss='220.00'/> + <Entry inputSpeed='600.00' inputTorque='0.00' torqueLoss='48.00'/> + <Entry inputSpeed='600.00' inputTorque='-200.00' torqueLoss='56.00'/> + <Entry inputSpeed='600.00' inputTorque='-400.00' torqueLoss='64.00'/> + <Entry inputSpeed='600.00' inputTorque='-600.00' torqueLoss='72.00'/> + <Entry inputSpeed='600.00' inputTorque='-900.00' torqueLoss='84.00'/> + <Entry inputSpeed='600.00' inputTorque='-1200.00' torqueLoss='96.00'/> + <Entry inputSpeed='600.00' inputTorque='-1600.00' torqueLoss='112.00'/> + <Entry inputSpeed='600.00' inputTorque='-2000.00' torqueLoss='128.00'/> + <Entry inputSpeed='600.00' inputTorque='-2500.00' torqueLoss='148.00'/> + <Entry inputSpeed='900.00' inputTorque='0.00' torqueLoss='57.00'/> + <Entry inputSpeed='900.00' inputTorque='-200.00' torqueLoss='65.00'/> + <Entry inputSpeed='900.00' inputTorque='-400.00' torqueLoss='73.00'/> + <Entry inputSpeed='900.00' inputTorque='-600.00' torqueLoss='81.00'/> + <Entry inputSpeed='900.00' inputTorque='-900.00' torqueLoss='93.00'/> + <Entry inputSpeed='900.00' inputTorque='-1200.00' torqueLoss='105.00'/> + <Entry inputSpeed='900.00' inputTorque='-1600.00' torqueLoss='121.00'/> + <Entry inputSpeed='900.00' inputTorque='-2000.00' torqueLoss='137.00'/> + <Entry inputSpeed='900.00' inputTorque='-2500.00' torqueLoss='157.00'/> + <Entry inputSpeed='1200.00' inputTorque='0.00' torqueLoss='66.00'/> + <Entry inputSpeed='1200.00' inputTorque='-200.00' torqueLoss='74.00'/> + <Entry inputSpeed='1200.00' inputTorque='-400.00' torqueLoss='82.00'/> + <Entry inputSpeed='1200.00' inputTorque='-600.00' torqueLoss='90.00'/> + <Entry inputSpeed='1200.00' inputTorque='-900.00' torqueLoss='102.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1200.00' torqueLoss='114.00'/> + <Entry inputSpeed='1200.00' inputTorque='-1600.00' torqueLoss='130.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2000.00' torqueLoss='146.00'/> + <Entry inputSpeed='1200.00' inputTorque='-2500.00' torqueLoss='166.00'/> + <Entry inputSpeed='1600.00' inputTorque='0.00' torqueLoss='78.00'/> + <Entry inputSpeed='1600.00' inputTorque='-200.00' torqueLoss='86.00'/> + <Entry inputSpeed='1600.00' inputTorque='-400.00' torqueLoss='94.00'/> + <Entry inputSpeed='1600.00' inputTorque='-600.00' torqueLoss='102.00'/> + <Entry inputSpeed='1600.00' inputTorque='-900.00' torqueLoss='114.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1200.00' torqueLoss='126.00'/> + <Entry inputSpeed='1600.00' inputTorque='-1600.00' torqueLoss='142.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2000.00' torqueLoss='158.00'/> + <Entry inputSpeed='1600.00' inputTorque='-2500.00' torqueLoss='178.00'/> + <Entry inputSpeed='2000.00' inputTorque='0.00' torqueLoss='90.00'/> + <Entry inputSpeed='2000.00' inputTorque='-200.00' torqueLoss='98.00'/> + <Entry inputSpeed='2000.00' inputTorque='-400.00' torqueLoss='106.00'/> + <Entry inputSpeed='2000.00' inputTorque='-600.00' torqueLoss='114.00'/> + <Entry inputSpeed='2000.00' inputTorque='-900.00' torqueLoss='126.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1200.00' torqueLoss='138.00'/> + <Entry inputSpeed='2000.00' inputTorque='-1600.00' torqueLoss='154.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2000.00' torqueLoss='170.00'/> + <Entry inputSpeed='2000.00' inputTorque='-2500.00' torqueLoss='190.00'/> + <Entry inputSpeed='2500.00' inputTorque='0.00' torqueLoss='105.00'/> + <Entry inputSpeed='2500.00' inputTorque='-200.00' torqueLoss='113.00'/> + <Entry inputSpeed='2500.00' inputTorque='-400.00' torqueLoss='121.00'/> + <Entry inputSpeed='2500.00' inputTorque='-600.00' torqueLoss='129.00'/> + <Entry inputSpeed='2500.00' inputTorque='-900.00' torqueLoss='141.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1200.00' torqueLoss='153.00'/> + <Entry inputSpeed='2500.00' inputTorque='-1600.00' torqueLoss='169.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2000.00' torqueLoss='185.00'/> + <Entry inputSpeed='2500.00' inputTorque='-2500.00' torqueLoss='205.00'/> + <Entry inputSpeed='3000.00' inputTorque='0.00' torqueLoss='120.00'/> + <Entry inputSpeed='3000.00' inputTorque='-200.00' torqueLoss='128.00'/> + <Entry inputSpeed='3000.00' inputTorque='-400.00' torqueLoss='136.00'/> + <Entry inputSpeed='3000.00' inputTorque='-600.00' torqueLoss='144.00'/> + <Entry inputSpeed='3000.00' inputTorque='-900.00' torqueLoss='156.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1200.00' torqueLoss='168.00'/> + <Entry inputSpeed='3000.00' inputTorque='-1600.00' torqueLoss='184.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2000.00' torqueLoss='200.00'/> + <Entry inputSpeed='3000.00' inputTorque='-2500.00' torqueLoss='220.00'/> + </TorqueLossMap> + </Gear> + </Gears> + </Data> + <Signature> + <di:Reference URI="#gbx-vi2Oak2N"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization"/> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <di:DigestValue>ieNmjofFObDBGnB7+GX9of3HYe3ydK/ra+YvmULVJIk=</di:DigestValue> + </di:Reference> + </Signature> + </v2.6:Gearbox> + <v2.6:TorqueConverter xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:type="TorqueConverterComponentDeclarationType"> + <Data id="tc-123xyz" xsi:type="TorqueConverterDataDeclarationType"> + <Manufacturer>Some Manufacturer</Manufacturer> + <Model>Some Model</Model> + <CertificationNumber>e12*0815/8051*2017/05E0000*00</CertificationNumber> + <Date>2017-02-15T11:00:00Z</Date> + <AppVersion>TC CalcApp 123</AppVersion> + <CertificationMethod>Standard values</CertificationMethod> + <Characteristics> + <Entry speedRatio='0.0000' torqueRatio='1.80' inputTorqueRef='367.68'/> + <Entry speedRatio='0.1000' torqueRatio='1.71' inputTorqueRef='355.43'/> + <Entry speedRatio='0.2000' torqueRatio='1.61' inputTorqueRef='343.17'/> + <Entry speedRatio='0.3000' torqueRatio='1.52' inputTorqueRef='330.92'/> + <Entry speedRatio='0.4000' torqueRatio='1.42' inputTorqueRef='318.66'/> + <Entry speedRatio='0.5000' torqueRatio='1.33' inputTorqueRef='306.40'/> + <Entry speedRatio='0.6000' torqueRatio='1.23' inputTorqueRef='294.15'/> + <Entry speedRatio='0.6500' torqueRatio='1.19' inputTorqueRef='275.76'/> + <Entry speedRatio='0.7000' torqueRatio='1.14' inputTorqueRef='257.38'/> + <Entry speedRatio='0.7500' torqueRatio='1.09' inputTorqueRef='238.99'/> + <Entry speedRatio='0.8000' torqueRatio='1.04' inputTorqueRef='220.61'/> + <Entry speedRatio='0.8500' torqueRatio='1.00' inputTorqueRef='202.23'/> + <Entry speedRatio='0.9000' torqueRatio='0.95' inputTorqueRef='183.84'/> + <Entry speedRatio='0.9500' torqueRatio='0.95' inputTorqueRef='91.92'/> + <Entry speedRatio='1.0000' torqueRatio='0.95' inputTorqueRef='0.00'/> + <Entry speedRatio='1.1000' torqueRatio='1.00' inputTorqueRef='-40.34'/> + <Entry speedRatio='1.2200' torqueRatio='1.00' inputTorqueRef='-80.34'/> + <Entry speedRatio='1.3800' torqueRatio='1.00' inputTorqueRef='-136.11'/> + <Entry speedRatio='1.5700' torqueRatio='1.00' inputTorqueRef='-216.52'/> + <Entry speedRatio='1.8300' torqueRatio='1.00' inputTorqueRef='-335.19'/> + <Entry speedRatio='2.2000' torqueRatio='1.00' inputTorqueRef='-528.77'/> + <Entry speedRatio='2.5000' torqueRatio='1.00' inputTorqueRef='-721.00'/> + <Entry speedRatio='3.0000' torqueRatio='1.00' inputTorqueRef='-1122.00'/> + <Entry speedRatio='3.5000' torqueRatio='1.00' inputTorqueRef='-1648.00'/> + <Entry speedRatio='4.0000' torqueRatio='1.00' inputTorqueRef='-2326.00'/> + <Entry speedRatio='4.5000' torqueRatio='1.00' inputTorqueRef='-3182.00'/> + <Entry speedRatio='5.0000' torqueRatio='1.00' inputTorqueRef='-4242.00'/> + </Characteristics> + </Data> + <Signature> + <di:Reference URI="#tc-123xyz"> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <di:DigestValue>q2sumDwsqQKLw4xwkEllgsygF5bHBwZPSS66UNaXXis=</di:DigestValue> + </di:Reference> + </Signature> + </v2.6:TorqueConverter> + <v2.6:Angledrive xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:type="AngledriveComponentDeclarationType"> + <Data id="agl-vi2Oak2N" xsi:type="AngledriveDataDeclarationType"> + <Manufacturer>Generic Gearbox Manufacturer</Manufacturer> + <Model>Generic primary bus 41 Gearbox</Model> + <CertificationNumber>e12*0815/8051*2017/05E0000*00</CertificationNumber> + <Date>2017-01-11T11:00:00Z</Date> + <AppVersion>3.0.1</AppVersion> + <Ratio>2.345</Ratio> + <CertificationMethod>Standard values</CertificationMethod> + <TorqueLossMap> + <Entry inputSpeed="0.00" inputTorque="-10000.00" torqueLoss="100.00"/> + <Entry inputSpeed="1000.00" inputTorque="-1000.00" torqueLoss="100.00"/> + <Entry inputSpeed="0.00" inputTorque="0.00" torqueLoss="10.00"/> + <Entry inputSpeed="1000.00" inputTorque="0.00" torqueLoss="10.00"/> + <Entry inputSpeed="0.00" inputTorque="10000.00" torqueLoss="100.00"/> + <Entry inputSpeed="1000.00" inputTorque="1000.00" torqueLoss="100.00"/> + </TorqueLossMap> + </Data> + <Signature> + <di:Reference URI="#agl-vi2Oak2N"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization"/> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <di:DigestValue>1tuF9SoA8luoUBQGym4bYi1TurDSmcYqBDJ6AP20OSs=</di:DigestValue> + </di:Reference> + </Signature> + </v2.6:Angledrive> + <v2.6:Retarder xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:type="RetarderComponentDeclarationType"> + <Data id="RET-Shai9imi" xsi:type="RetarderDataDeclarationType"> + <Manufacturer>Generic Retarder Manufacturer</Manufacturer> + <Model>Generic Retarder</Model> + <CertificationNumber>e12*0815/8051*2017/05E0000*00</CertificationNumber> + <Date>2017-01-11T11:00:00Z</Date> + <AppVersion>3.0.1</AppVersion> + <CertificationMethod>Standard values</CertificationMethod> + <RetarderLossMap> + <Entry retarderSpeed="0.00" torqueLoss="10.00"/> + <Entry retarderSpeed="100.00" torqueLoss="10.02"/> + <Entry retarderSpeed="200.00" torqueLoss="10.08"/> + <Entry retarderSpeed="300.00" torqueLoss="10.18"/> + <Entry retarderSpeed="400.00" torqueLoss="10.32"/> + <Entry retarderSpeed="500.00" torqueLoss="10.50"/> + <Entry retarderSpeed="600.00" torqueLoss="10.72"/> + <Entry retarderSpeed="700.00" torqueLoss="10.98"/> + <Entry retarderSpeed="800.00" torqueLoss="11.28"/> + <Entry retarderSpeed="900.00" torqueLoss="11.62"/> + <Entry retarderSpeed="1000.00" torqueLoss="12.00"/> + <Entry retarderSpeed="1100.00" torqueLoss="12.42"/> + <Entry retarderSpeed="1200.00" torqueLoss="12.88"/> + <Entry retarderSpeed="1300.00" torqueLoss="13.38"/> + <Entry retarderSpeed="1400.00" torqueLoss="13.92"/> + <Entry retarderSpeed="1500.00" torqueLoss="14.50"/> + <Entry retarderSpeed="1600.00" torqueLoss="15.12"/> + <Entry retarderSpeed="1700.00" torqueLoss="15.78"/> + <Entry retarderSpeed="1800.00" torqueLoss="16.48"/> + <Entry retarderSpeed="1900.00" torqueLoss="17.22"/> + <Entry retarderSpeed="2000.00" torqueLoss="18.00"/> + <Entry retarderSpeed="2100.00" torqueLoss="18.82"/> + <Entry retarderSpeed="2200.00" torqueLoss="19.68"/> + <Entry retarderSpeed="2300.00" torqueLoss="20.58"/> + <Entry retarderSpeed="4000.00" torqueLoss="42.00"/> + </RetarderLossMap> + </Data> + <Signature> + <di:Reference URI="#RET-Shai9imi"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization"/> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <di:DigestValue>fcEtYfDAbfuRq0xpuzapmEj+Py1PIPUZwVmx+amNvcc=</di:DigestValue> + </di:Reference> + </Signature> + </v2.6:Retarder> + <v2.6:Axlegear xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:type="AxlegearComponentDeclarationType"> + <Data id="AXL-EC3ohnoh" xsi:type="AxlegearDataDeclarationType"> + <Manufacturer>Generic Gearbox Manufacturer</Manufacturer> + <Model>Generic primary bus 41 AxleGear</Model> + <CertificationNumber>e12*0815/8051*2017/05E0000*00</CertificationNumber> + <Date>2017-01-11T11:00:00Z</Date> + <AppVersion>3.0.1</AppVersion> + <LineType>Single portal axle</LineType> + <Ratio>6.500</Ratio> + <CertificationMethod>Standard values</CertificationMethod> + <TorqueLossMap> + <Entry inputSpeed='0.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='0.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='0.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='0.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='0.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='0.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='0.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='0.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='0.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='0.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='0.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='0.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='0.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='0.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='0.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='0.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='0.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='0.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='0.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='0.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='0.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='0.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='0.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='0.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='0.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='0.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='0.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='0.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='0.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='0.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='0.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='0.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='0.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='0.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='0.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='325.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='325.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='325.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='325.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='325.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='325.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='325.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='325.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='325.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='325.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='325.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='325.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='325.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='325.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='325.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='325.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='325.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='325.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='325.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='325.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='325.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='325.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='325.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='325.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='325.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='325.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='325.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='325.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='325.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='325.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='325.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='325.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='325.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='325.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='325.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='650.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='650.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='650.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='650.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='650.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='650.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='650.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='650.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='650.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='650.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='650.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='650.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='650.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='650.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='650.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='650.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='650.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='650.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='650.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='650.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='650.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='650.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='650.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='650.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='650.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='650.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='650.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='650.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='650.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='650.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='650.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='650.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='650.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='650.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='650.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='975.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='975.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='975.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='975.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='975.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='975.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='975.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='975.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='975.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='975.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='975.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='975.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='975.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='975.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='975.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='975.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='975.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='975.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='975.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='975.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='975.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='975.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='975.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='975.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='975.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='975.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='975.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='975.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='975.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='975.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='975.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='975.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='975.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='975.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='975.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='1300.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='1300.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='1300.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='1300.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='1300.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='1300.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='1300.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='1300.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='1300.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='1300.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='1300.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='1300.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='1300.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='1300.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='1300.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='1300.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='1300.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='1300.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='1300.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='1300.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='1300.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='1300.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='1300.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='1300.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='1300.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='1300.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='1300.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='1300.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='1300.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='1300.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='1300.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='1300.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='1300.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='1300.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='1300.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='1625.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='1625.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='1625.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='1625.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='1625.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='1625.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='1625.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='1625.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='1625.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='1625.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='1625.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='1625.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='1625.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='1625.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='1625.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='1625.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='1625.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='1625.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='1625.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='1625.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='1625.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='1625.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='1625.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='1625.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='1625.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='1625.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='1625.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='1625.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='1625.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='1625.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='1625.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='1625.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='1625.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='1625.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='1625.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='1950.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='1950.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='1950.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='1950.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='1950.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='1950.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='1950.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='1950.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='1950.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='1950.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='1950.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='1950.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='1950.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='1950.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='1950.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='1950.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='1950.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='1950.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='1950.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='1950.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='1950.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='1950.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='1950.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='1950.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='1950.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='1950.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='1950.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='1950.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='1950.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='1950.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='1950.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='1950.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='1950.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='1950.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='1950.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='2275.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='2275.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='2275.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='2275.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='2275.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='2275.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='2275.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='2275.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='2275.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='2275.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='2275.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='2275.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='2275.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='2275.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='2275.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='2275.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='2275.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='2275.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='2275.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='2275.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='2275.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='2275.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='2275.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='2275.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='2275.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='2275.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='2275.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='2275.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='2275.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='2275.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='2275.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='2275.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='2275.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='2275.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='2275.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='2600.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='2600.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='2600.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='2600.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='2600.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='2600.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='2600.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='2600.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='2600.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='2600.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='2600.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='2600.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='2600.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='2600.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='2600.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='2600.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='2600.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='2600.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='2600.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='2600.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='2600.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='2600.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='2600.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='2600.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='2600.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='2600.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='2600.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='2600.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='2600.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='2600.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='2600.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='2600.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='2600.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='2600.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='2600.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='2925.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='2925.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='2925.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='2925.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='2925.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='2925.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='2925.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='2925.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='2925.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='2925.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='2925.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='2925.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='2925.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='2925.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='2925.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='2925.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='2925.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='2925.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='2925.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='2925.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='2925.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='2925.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='2925.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='2925.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='2925.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='2925.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='2925.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='2925.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='2925.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='2925.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='2925.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='2925.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='2925.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='2925.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='2925.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='3750.00' inputTorque='31.96' torqueLoss='31.96'/> + <Entry inputSpeed='3750.00' inputTorque='70.42' torqueLoss='31.96'/> + <Entry inputSpeed='3750.00' inputTorque='110.07' torqueLoss='33.15'/> + <Entry inputSpeed='3750.00' inputTorque='149.72' torqueLoss='34.34'/> + <Entry inputSpeed='3750.00' inputTorque='189.37' torqueLoss='35.53'/> + <Entry inputSpeed='3750.00' inputTorque='268.68' torqueLoss='37.91'/> + <Entry inputSpeed='3750.00' inputTorque='347.98' torqueLoss='40.29'/> + <Entry inputSpeed='3750.00' inputTorque='506.58' torqueLoss='45.04'/> + <Entry inputSpeed='3750.00' inputTorque='665.19' torqueLoss='49.80'/> + <Entry inputSpeed='3750.00' inputTorque='823.79' torqueLoss='54.56'/> + <Entry inputSpeed='3750.00' inputTorque='982.39' torqueLoss='59.32'/> + <Entry inputSpeed='3750.00' inputTorque='1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='3750.00' inputTorque='1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='3750.00' inputTorque='1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='3750.00' inputTorque='1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='3750.00' inputTorque='1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='3750.00' inputTorque='2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='3750.00' inputTorque='2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='3750.00' inputTorque='2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='3750.00' inputTorque='3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='3750.00' inputTorque='3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='3750.00' inputTorque='3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='3750.00' inputTorque='4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='3750.00' inputTorque='4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='3750.00' inputTorque='4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='3750.00' inputTorque='5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='3750.00' inputTorque='5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='3750.00' inputTorque='5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='3750.00' inputTorque='6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='3750.00' inputTorque='6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='3750.00' inputTorque='6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='3750.00' inputTorque='7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='3750.00' inputTorque='7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='3750.00' inputTorque='7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='3750.00' inputTorque='7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='0.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='0.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='0.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='0.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='0.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='0.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='0.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='0.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='0.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='0.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='0.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='0.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='0.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='0.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='0.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='0.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='0.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='0.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='0.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='0.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='0.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='0.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='0.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='0.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='0.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='0.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='0.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='0.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='0.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='0.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='0.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='0.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='0.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='0.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='0.00' inputTorque='-7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='325.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='325.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='325.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='325.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='325.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='325.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='325.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='325.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='325.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='325.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='325.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='325.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='325.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='325.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='325.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='325.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='325.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='325.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='325.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='325.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='325.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='325.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='325.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='325.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='325.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='325.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='325.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='325.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='325.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='325.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='325.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='325.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='325.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='325.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='325.00' inputTorque='-7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='650.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='650.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='650.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='650.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='650.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='650.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='650.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='650.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='650.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='650.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='650.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='650.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='650.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='650.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='650.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='650.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='650.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='650.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='650.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='650.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='650.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='650.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='650.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='650.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='650.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='650.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='650.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='650.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='650.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='650.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='650.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='650.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='650.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='650.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='650.00' inputTorque='-7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='975.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='975.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='975.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='975.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='975.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='975.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='975.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='975.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='975.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='975.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='975.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='975.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='975.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='975.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='975.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='975.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='975.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='975.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='975.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='975.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='975.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='975.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='975.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='975.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='975.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='975.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='975.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='975.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='975.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='975.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='975.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='975.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='975.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='975.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='975.00' inputTorque='-7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='1300.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='1300.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='1300.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='1300.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='1300.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='1300.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='1300.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='1300.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='1300.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='1300.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='1300.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='1300.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='1300.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='1300.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='1300.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='1300.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='1300.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='1300.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='1300.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='1300.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='1300.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='1300.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='1300.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='1300.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='1300.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='1300.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='1300.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='1300.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='1300.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='1300.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='1300.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='1300.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='1300.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='1300.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='1300.00' inputTorque='-7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='1625.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='1625.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='1625.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='1625.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='1625.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='1625.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='1625.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='1625.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='1625.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='1625.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='1625.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='1625.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='1625.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='1625.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='1625.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='1625.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='1625.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='1625.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='1625.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='1625.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='1625.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='1625.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='1625.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='1625.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='1625.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='1625.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='1625.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='1625.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='1625.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='1625.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='1625.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='1625.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='1625.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='1625.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='1625.00' inputTorque='-7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='1950.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='1950.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='1950.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='1950.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='1950.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='1950.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='1950.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='1950.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='1950.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='1950.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='1950.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='1950.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='1950.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='1950.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='1950.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='1950.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='1950.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='1950.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='1950.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='1950.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='1950.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='1950.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='1950.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='1950.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='1950.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='1950.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='1950.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='1950.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='1950.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='1950.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='1950.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='1950.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='1950.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='1950.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='1950.00' inputTorque='-7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='2275.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='2275.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='2275.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='2275.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='2275.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='2275.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='2275.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='2275.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='2275.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='2275.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='2275.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='2275.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='2275.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='2275.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='2275.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='2275.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='2275.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='2275.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='2275.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='2275.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='2275.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='2275.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='2275.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='2275.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='2275.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='2275.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='2275.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='2275.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='2275.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='2275.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='2275.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='2275.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='2275.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='2275.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='2275.00' inputTorque='-7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='2600.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='2600.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='2600.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='2600.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='2600.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='2600.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='2600.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='2600.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='2600.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='2600.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='2600.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='2600.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='2600.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='2600.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='2600.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='2600.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='2600.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='2600.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='2600.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='2600.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='2600.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='2600.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='2600.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='2600.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='2600.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='2600.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='2600.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='2600.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='2600.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='2600.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='2600.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='2600.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='2600.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='2600.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='2600.00' inputTorque='-7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='2925.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='2925.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='2925.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='2925.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='2925.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='2925.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='2925.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='2925.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='2925.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='2925.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='2925.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='2925.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='2925.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='2925.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='2925.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='2925.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='2925.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='2925.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='2925.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='2925.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='2925.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='2925.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='2925.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='2925.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='2925.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='2925.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='2925.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='2925.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='2925.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='2925.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='2925.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='2925.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='2925.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='2925.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='2925.00' inputTorque='-7960.98' torqueLoss='268.68'/> + <Entry inputSpeed='3250.00' inputTorque='-31.96' torqueLoss='31.96'/> + <Entry inputSpeed='3250.00' inputTorque='-70.42' torqueLoss='31.96'/> + <Entry inputSpeed='3250.00' inputTorque='-110.07' torqueLoss='33.15'/> + <Entry inputSpeed='3250.00' inputTorque='-149.72' torqueLoss='34.34'/> + <Entry inputSpeed='3250.00' inputTorque='-189.37' torqueLoss='35.53'/> + <Entry inputSpeed='3250.00' inputTorque='-268.68' torqueLoss='37.91'/> + <Entry inputSpeed='3250.00' inputTorque='-347.98' torqueLoss='40.29'/> + <Entry inputSpeed='3250.00' inputTorque='-506.58' torqueLoss='45.04'/> + <Entry inputSpeed='3250.00' inputTorque='-665.19' torqueLoss='49.80'/> + <Entry inputSpeed='3250.00' inputTorque='-823.79' torqueLoss='54.56'/> + <Entry inputSpeed='3250.00' inputTorque='-982.39' torqueLoss='59.32'/> + <Entry inputSpeed='3250.00' inputTorque='-1141.00' torqueLoss='64.08'/> + <Entry inputSpeed='3250.00' inputTorque='-1299.60' torqueLoss='68.83'/> + <Entry inputSpeed='3250.00' inputTorque='-1458.21' torqueLoss='73.59'/> + <Entry inputSpeed='3250.00' inputTorque='-1616.81' torqueLoss='78.35'/> + <Entry inputSpeed='3250.00' inputTorque='-1934.02' torqueLoss='87.87'/> + <Entry inputSpeed='3250.00' inputTorque='-2251.23' torqueLoss='97.38'/> + <Entry inputSpeed='3250.00' inputTorque='-2568.44' torqueLoss='106.90'/> + <Entry inputSpeed='3250.00' inputTorque='-2885.65' torqueLoss='116.42'/> + <Entry inputSpeed='3250.00' inputTorque='-3202.85' torqueLoss='125.93'/> + <Entry inputSpeed='3250.00' inputTorque='-3520.06' torqueLoss='135.45'/> + <Entry inputSpeed='3250.00' inputTorque='-3837.27' torqueLoss='144.96'/> + <Entry inputSpeed='3250.00' inputTorque='-4154.48' torqueLoss='154.48'/> + <Entry inputSpeed='3250.00' inputTorque='-4471.69' torqueLoss='164.00'/> + <Entry inputSpeed='3250.00' inputTorque='-4788.90' torqueLoss='173.51'/> + <Entry inputSpeed='3250.00' inputTorque='-5106.11' torqueLoss='183.03'/> + <Entry inputSpeed='3250.00' inputTorque='-5423.31' torqueLoss='192.55'/> + <Entry inputSpeed='3250.00' inputTorque='-5740.52' torqueLoss='202.06'/> + <Entry inputSpeed='3250.00' inputTorque='-6057.73' torqueLoss='211.58'/> + <Entry inputSpeed='3250.00' inputTorque='-6374.94' torqueLoss='221.09'/> + <Entry inputSpeed='3250.00' inputTorque='-6692.15' torqueLoss='230.61'/> + <Entry inputSpeed='3250.00' inputTorque='-7009.36' torqueLoss='240.13'/> + <Entry inputSpeed='3250.00' inputTorque='-7326.57' torqueLoss='249.64'/> + <Entry inputSpeed='3250.00' inputTorque='-7643.77' torqueLoss='259.16'/> + <Entry inputSpeed='3250.00' inputTorque='-7960.98' torqueLoss='268.68'/> + </TorqueLossMap> + </Data> + <Signature> + <di:Reference URI="#AXL-EC3ohnoh"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization"/> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <di:DigestValue>o4nYTajmWKaduxys5ShmnfJbYd23rpxZ01JbuG6dmzU=</di:DigestValue> + </di:Reference> + </Signature> + </v2.6:Axlegear> + <v2.6:AxleWheels xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:type="AxleWheelsComponentDeclarationType"> + <Data xsi:type="AxleWheelsDataDeclarationType"> + <Axles> + <Axle axleNumber="1" xsi:type="AxleDataDeclarationType"> + <AxleType>VehicleNonDriven</AxleType> + <TwinTyres>false</TwinTyres> + <Steered>true</Steered> + <Tyre> + <Data id="WHL-5432198760-315-70-R22.5" xsi:type="TyreDataDeclarationType"> + <Manufacturer>Generic Wheels Manufacturer</Manufacturer> + <Model>Generic Wheel</Model> + <CertificationNumber>e12*0815/8051*2017/05E0000*00</CertificationNumber> + <Date>2017-01-11T14:00:00Z</Date> + <AppVersion>Tyre Generation App 1.0</AppVersion> + <Dimension>315/70 R22.5</Dimension> + <RRCDeclared>0.0055</RRCDeclared> + <FzISO>31300</FzISO> + </Data> + <Signature> + <di:Reference URI="#WHL-5432198760-315-70-R22.5"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization"/> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <di:DigestValue>4TkUGQTX8tevHOU9Cj9uyCFuI/aqcEYlo/gyVjVQmv0=</di:DigestValue> + </di:Reference> + </Signature> + </Tyre> + </Axle> + <Axle axleNumber="2" xsi:type="AxleDataDeclarationType"> + <AxleType>VehicleDriven</AxleType> + <TwinTyres>true</TwinTyres> + <Steered>false</Steered> + <Tyre> + <Data id="WHL-5432198760-315-70-R22.5" xsi:type="TyreDataDeclarationType"> + <Manufacturer>Generic Wheels Manufacturer</Manufacturer> + <Model>Generic Wheel</Model> + <CertificationNumber>e12*0815/8051*2017/05E0000*00</CertificationNumber> + <Date>2017-01-11T14:00:00Z</Date> + <AppVersion>Tyre Generation App 1.0</AppVersion> + <Dimension>315/70 R22.5</Dimension> + <RRCDeclared>0.0063</RRCDeclared> + <FzISO>31300</FzISO> + </Data> + <Signature> + <di:Reference URI="#WHL-5432198760-315-70-R22.5"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization"/> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <di:DigestValue>KljvtvGUUQ/L7MiLVAqU+bckL5PNDNNwdeLH9kUVrfM=</di:DigestValue> + </di:Reference> + </Signature> + </Tyre> + </Axle> + </Axles> + </Data> + </v2.6:AxleWheels> + <v2.6:Auxiliaries xsi:type="PrimaryVehicleAuxiliariesComponentDeclarationType"> + <Data xsi:type="PrimaryVehicleAuxiliaryDataDeclarationType"> + <Fan> + <Technology>Hydraulic driven - Constant displacement pump</Technology> + </Fan> + <SteeringPump> + <Technology axleNumber="1">Variable displacement elec. controlled</Technology> + </SteeringPump> + <ElectricSystem> + <AlternatorTechnology>conventional</AlternatorTechnology> + <SupplyFromHEVPossible>false</SupplyFromHEVPossible> + </ElectricSystem> + <PneumaticSystem> + <SizeOfAirSupply>Large Supply 2-stage</SizeOfAirSupply> + <CompressorDrive>mechanically</CompressorDrive> + <Clutch>none</Clutch> + <CompressorRatio>1.120</CompressorRatio> + <SmartCompressionSystem>false</SmartCompressionSystem> + <SmartRegenerationSystem>false</SmartRegenerationSystem> + <AirsuspensionControl>electronically</AirsuspensionControl> + <PneumaticSCRReagentDosing>true</PneumaticSCRReagentDosing> + </PneumaticSystem> + <HVAC> + <AdjustableCoolantThermostat>true</AdjustableCoolantThermostat> + <EngineWasteGasHeatExchanger>true</EngineWasteGasHeatExchanger> + </HVAC> + </Data> + </v2.6:Auxiliaries> + </Components> + </v2.0:Vehicle> +</tns:VectoInputDeclaration> diff --git a/Vecto3GUI2020Test/TestData/exempted_primary_heavyBus.VIF.xml b/Vecto3GUI2020Test/TestData/exempted_primary_heavyBus.VIF.xml new file mode 100644 index 0000000000000000000000000000000000000000..ef4e364d6bba89cfea33a6752982ae9d1cd2d1a6 --- /dev/null +++ b/Vecto3GUI2020Test/TestData/exempted_primary_heavyBus.VIF.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<VectoOutputMultistage xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1" xmlns:di="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:v2.3="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3" xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:v2.8="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1 V:\VectoCore\VectoCore\Resources\XSD/VectoOutputMultistage.0.1.xsd"> + <PrimaryVehicle xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1"> + <Data id="VEH-4cb168560c0d4b3d886d" xsi:type="PrimaryVehicleDataType"> + <Vehicle xsi:type="VehicleExemptedPrimaryBusType"> + <ManufacturerPrimaryVehicle>Some Manufacturer</ManufacturerPrimaryVehicle> + <ManufacturerAddressPrimaryVehicle>Infinite Loop 1</ManufacturerAddressPrimaryVehicle> + <Model>Sample Bus Model</Model> + <VIN>VEH-1234567890</VIN> + <Date>2017-02-15T11:00:00Z</Date> + <LegislativeCategory>N2</LegislativeCategory> + <ChassisConfiguration>Bus</ChassisConfiguration> + <AxleConfiguration>6x2</AxleConfiguration> + <Articulated>false</Articulated> + <TechnicalPermissibleMaximumLadenMass unit="kg">15400.0</TechnicalPermissibleMaximumLadenMass> + <ZeroEmissionVehicle>true</ZeroEmissionVehicle> + <SumNetPower unit="W">350000</SumNetPower> + <Technology>Fuel cell vehicle</Technology> + </Vehicle> + <InputDataSignature> + <di:Reference URI="#VEH-1234567890"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>sYhNx2MDHaOAMTlPflP/qQbEkazmRDxY0Vw6yzwwcJc=</di:DigestValue> + </di:Reference> + </InputDataSignature> + <ManufacturerRecordSignature> + <di:Reference URI="#RESULT-4c4c52e522874a398b3a"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>guwkv90jOyWgDpgQwAEbLRkq7pWGeVaGA+dHizLYufQ=</di:DigestValue> + </di:Reference> + </ManufacturerRecordSignature> + <Results> + <Status>success</Status> + <ExemptedVehicle /> + </Results> + <ApplicationInformation> + <SimulationToolVersion>0.7.3.2247-DEV !!NOT FOR CERTIFICATION!!</SimulationToolVersion> + <Date>2021-06-15T16:00:43.6769906Z</Date> + </ApplicationInformation> + </Data> + <Signature> + <di:Reference URI="#VEH-4cb168560c0d4b3d886d"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>KeeEnRNO5Gjm7XB+YYx542ujYbE0k7a9SkWe/BWo7bI=</di:DigestValue> + </di:Reference> + </Signature> + </PrimaryVehicle> +</VectoOutputMultistage> \ No newline at end of file diff --git a/Vecto3GUI2020Test/TestData/exempted_vif_mandatory.xml b/Vecto3GUI2020Test/TestData/exempted_vif_mandatory.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d7c3952ba98fe996a7f480e313f1203691ce146 --- /dev/null +++ b/Vecto3GUI2020Test/TestData/exempted_vif_mandatory.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?> +<VectoOutputMultistage xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1" xmlns:di="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:v2.3="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3" xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:v2.8="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1 V:\VectoCore\VectoCore\Resources\XSD/VectoOutputMultistage.0.1.xsd"> + <PrimaryVehicle xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1"> + <Data id="VEH-4cb168560c0d4b3d886d" xsi:type="PrimaryVehicleDataType"> + <Vehicle xsi:type="VehicleExemptedPrimaryBusType"> + <ManufacturerPrimaryVehicle>Some Manufacturer</ManufacturerPrimaryVehicle> + <ManufacturerAddressPrimaryVehicle>Infinite Loop 1</ManufacturerAddressPrimaryVehicle> + <Model>Sample Bus Model</Model> + <VIN>VEH-1234567890</VIN> + <Date>2017-02-15T11:00:00Z</Date> + <LegislativeCategory>N2</LegislativeCategory> + <ChassisConfiguration>Bus</ChassisConfiguration> + <AxleConfiguration>6x2</AxleConfiguration> + <Articulated>false</Articulated> + <TechnicalPermissibleMaximumLadenMass unit="kg">15400.0</TechnicalPermissibleMaximumLadenMass> + <ZeroEmissionVehicle>true</ZeroEmissionVehicle> + <SumNetPower unit="W">350000</SumNetPower> + <Technology>Fuel cell vehicle</Technology> + </Vehicle> + <InputDataSignature> + <di:Reference URI="#VEH-1234567890"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>sYhNx2MDHaOAMTlPflP/qQbEkazmRDxY0Vw6yzwwcJc=</di:DigestValue> + </di:Reference> + </InputDataSignature> + <ManufacturerRecordSignature> + <di:Reference URI="#RESULT-4c4c52e522874a398b3a"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>guwkv90jOyWgDpgQwAEbLRkq7pWGeVaGA+dHizLYufQ=</di:DigestValue> + </di:Reference> + </ManufacturerRecordSignature> + <Results> + <Status>success</Status> + <ExemptedVehicle /> + </Results> + <ApplicationInformation> + <SimulationToolVersion>0.7.3.2247-DEV !!NOT FOR CERTIFICATION!!</SimulationToolVersion> + <Date>2021-06-15T16:00:43.6769906Z</Date> + </ApplicationInformation> + </Data> + <Signature> + <di:Reference URI="#VEH-4cb168560c0d4b3d886d"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>KeeEnRNO5Gjm7XB+YYx542ujYbE0k7a9SkWe/BWo7bI=</di:DigestValue> + </di:Reference> + </Signature> + </PrimaryVehicle> + <ManufacturingStage stageCount="2"> + <Data xsi:type="BusManufacturingStageDataType" id="MST-4c2c483e8feb4ebd8503"> + <HashPreviousStage> + <di:Reference URI="#VEH-4cb168560c0d4b3d886d"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>KeeEnRNO5Gjm7XB+YYx542ujYbE0k7a9SkWe/BWo7bI=</di:DigestValue> + </di:Reference> + </HashPreviousStage> + <Vehicle xsi:type="v2.8:ExemptedInterimStageInputType" id="VEH-c6ac253bde8b4bd49a9b"> + <v2.8:Manufacturer>123</v2.8:Manufacturer> + <v2.8:ManufacturerAddress>123</v2.8:ManufacturerAddress> + <v2.8:VIN>adsf1</v2.8:VIN> + <v2.8:Date>2021-06-22T22:00:00Z</v2.8:Date> + </Vehicle> + <ApplicationInformation> + <SimulationToolVersion>0.7.3.2247-DEV</SimulationToolVersion> + <Date>2021-06-23T08:19:04.8483845Z</Date> + </ApplicationInformation> + </Data> + <Signature> + <di:Reference URI="#MST-4c2c483e8feb4ebd8503"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>XH5k0TQWvBWs/aV6Zz0T/aggks5HgnLTvKtekiARewE=</di:DigestValue> + </di:Reference> + </Signature> + </ManufacturingStage> +</VectoOutputMultistage> \ No newline at end of file diff --git a/Vecto3GUI2020Test/inputdata/final.VIF_Report_4.xml b/Vecto3GUI2020Test/TestData/final.VIF_Report_4.xml similarity index 100% rename from Vecto3GUI2020Test/inputdata/final.VIF_Report_4.xml rename to Vecto3GUI2020Test/TestData/final.VIF_Report_4.xml diff --git a/Vecto3GUI2020Test/inputdata/interim2.VIF_Report_3.xml b/Vecto3GUI2020Test/TestData/interim2.VIF_Report_3.xml similarity index 100% rename from Vecto3GUI2020Test/inputdata/interim2.VIF_Report_3.xml rename to Vecto3GUI2020Test/TestData/interim2.VIF_Report_3.xml diff --git a/Vecto3GUI2020Test/TestData/newVifCompletedStage.json b/Vecto3GUI2020Test/TestData/newVifCompletedStage.json new file mode 100644 index 0000000000000000000000000000000000000000..29c1c7463c97a68966b38a3572a50afe4bf81160 --- /dev/null +++ b/Vecto3GUI2020Test/TestData/newVifCompletedStage.json @@ -0,0 +1,13 @@ +{ + "Header": { + "CreatedBy": "Harry", + "Date": "2021-07-13T00:00:00+02:00", + "AppVersion": "Vecto3GUI2020", + "FileVersion": 10 + }, + "Body": { + "PrimaryVehicle": "C:\\Users\\Harry\\source\\repos\\vecto-dev\\VectoCore\\VectoCoreTest\\TestData\\XML\\XMLReaderDeclaration\\SchemaVersion2.6_Buses\\vecto_vehicle-primary_heavyBus-sample.xml", + "InterimStage": "C:\\Users\\Harry\\source\\repos\\vecto-dev\\VectoCore\\VectoCoreTest\\TestData\\XML\\XMLReaderDeclaration\\SchemaVersion2.8\\vecto_vehicle-stage_input_full-sample.xml", + "Completed": true + } +} \ No newline at end of file diff --git a/Vecto3GUI2020Test/TestData/newVifInterimStage.json b/Vecto3GUI2020Test/TestData/newVifInterimStage.json new file mode 100644 index 0000000000000000000000000000000000000000..7f64bef871f18c99ec84c396e8b6e2c2bd8f1a48 --- /dev/null +++ b/Vecto3GUI2020Test/TestData/newVifInterimStage.json @@ -0,0 +1,13 @@ +{ + "Header": { + "CreatedBy": "Harry", + "Date": "2021-07-15T00:00:00+02:00", + "AppVersion": "Vecto3GUI2020", + "FileVersion": 10 + }, + "Body": { + "PrimaryVehicle": "C:\\Users\\Harry\\source\\repos\\vecto-dev\\VectoCore\\VectoCoreTest\\TestData\\XML\\XMLReaderDeclaration\\SchemaVersion2.6_Buses\\vecto_vehicle-primary_heavyBus-sample.xml", + "InterimStage": "C:\\Users\\Harry\\source\\repos\\vecto-dev\\VectoCore\\VectoCoreTest\\TestData\\XML\\XMLReaderDeclaration\\SchemaVersion2.8\\vecto_vehicle-stage_input_full-sample.xml", + "Completed": false + } +} \ No newline at end of file diff --git a/Vecto3GUI2020Test/TestData/test.VIF_Report_2.xml b/Vecto3GUI2020Test/TestData/test.VIF_Report_2.xml new file mode 100644 index 0000000000000000000000000000000000000000..95003c38d6c95d407123c97b46e746114c1b8cfc --- /dev/null +++ b/Vecto3GUI2020Test/TestData/test.VIF_Report_2.xml @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="utf-8"?> +<VectoOutputMultistage xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1" xmlns:di="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:v2.3="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3" xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:v2.8="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1 V:\VectoCore\VectoCore\Resources\XSD/VectoOutputMultistage.0.1.xsd"> + <PrimaryVehicle xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1"> + <Data id="VEH-4cb168560c0d4b3d886d" xsi:type="PrimaryVehicleDataType"> + <Vehicle xsi:type="VehicleExemptedPrimaryBusType"> + <ManufacturerPrimaryVehicle>Some Manufacturer</ManufacturerPrimaryVehicle> + <ManufacturerAddressPrimaryVehicle>Infinite Loop 1</ManufacturerAddressPrimaryVehicle> + <Model>Sample Bus Model</Model> + <VIN>VEH-1234567890</VIN> + <Date>2017-02-15T11:00:00Z</Date> + <LegislativeCategory>N2</LegislativeCategory> + <ChassisConfiguration>Bus</ChassisConfiguration> + <AxleConfiguration>6x2</AxleConfiguration> + <Articulated>false</Articulated> + <TechnicalPermissibleMaximumLadenMass unit="kg">15400.0</TechnicalPermissibleMaximumLadenMass> + <ZeroEmissionVehicle>true</ZeroEmissionVehicle> + <SumNetPower unit="W">350000</SumNetPower> + <Technology>Fuel cell vehicle</Technology> + </Vehicle> + <InputDataSignature> + <di:Reference URI="#VEH-1234567890"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>sYhNx2MDHaOAMTlPflP/qQbEkazmRDxY0Vw6yzwwcJc=</di:DigestValue> + </di:Reference> + </InputDataSignature> + <ManufacturerRecordSignature> + <di:Reference URI="#RESULT-4c4c52e522874a398b3a"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>guwkv90jOyWgDpgQwAEbLRkq7pWGeVaGA+dHizLYufQ=</di:DigestValue> + </di:Reference> + </ManufacturerRecordSignature> + <Results> + <Status>success</Status> + <ExemptedVehicle /> + </Results> + <ApplicationInformation> + <SimulationToolVersion>0.7.3.2247-DEV !!NOT FOR CERTIFICATION!!</SimulationToolVersion> + <Date>2021-06-15T16:00:43.6769906Z</Date> + </ApplicationInformation> + </Data> + <Signature> + <di:Reference URI="#VEH-4cb168560c0d4b3d886d"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>KeeEnRNO5Gjm7XB+YYx542ujYbE0k7a9SkWe/BWo7bI=</di:DigestValue> + </di:Reference> + </Signature> + </PrimaryVehicle> + <ManufacturingStage stageCount="2"> + <Data xsi:type="BusManufacturingStageDataType" id="MST-73e34e20c6ec4e98bac3"> + <HashPreviousStage> + <di:Reference URI="#VEH-4cb168560c0d4b3d886d"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>KeeEnRNO5Gjm7XB+YYx542ujYbE0k7a9SkWe/BWo7bI=</di:DigestValue> + </di:Reference> + </HashPreviousStage> + <Vehicle xsi:type="v2.8:ExemptedInterimStageInputType" id="VEH-b34a0bc66bcf46f18a04"> + <v2.8:Manufacturer>sdf</v2.8:Manufacturer> + <v2.8:ManufacturerAddress>asdf</v2.8:ManufacturerAddress> + <v2.8:VIN>afd</v2.8:VIN> + <v2.8:Date>2021-06-22T22:00:00Z</v2.8:Date> + <v2.8:CorrectedActualMass>12343</v2.8:CorrectedActualMass> + <v2.8:TechnicalPermissibleMaximumLadenMass>12354</v2.8:TechnicalPermissibleMaximumLadenMass> + </Vehicle> + <ApplicationInformation> + <SimulationToolVersion>0.7.3.2247-DEV</SimulationToolVersion> + <Date>2021-06-23T08:35:16.8844114Z</Date> + </ApplicationInformation> + </Data> + <Signature> + <di:Reference URI="#MST-73e34e20c6ec4e98bac3"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>1HzqGQs5vo59mNfInlO1sSMXdlFf1ExyIcV3Eh47+d4=</di:DigestValue> + </di:Reference> + </Signature> + </ManufacturingStage> +</VectoOutputMultistage> \ No newline at end of file diff --git a/Vecto3GUI2020Test/inputdata/vecto_vehicle-completed_heavyBus_31b.xml b/Vecto3GUI2020Test/TestData/vecto_vehicle-completed_heavyBus_31b.xml similarity index 100% rename from Vecto3GUI2020Test/inputdata/vecto_vehicle-completed_heavyBus_31b.xml rename to Vecto3GUI2020Test/TestData/vecto_vehicle-completed_heavyBus_31b.xml diff --git a/Vecto3GUI2020Test/TestHelper.cs b/Vecto3GUI2020Test/TestHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..0f800f625c404c350eeaf8e664fe342b627193d3 --- /dev/null +++ b/Vecto3GUI2020Test/TestHelper.cs @@ -0,0 +1,34 @@ +using System; +using System.CodeDom; +using System.Runtime.CompilerServices; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCore.InputData.FileIO.XML; + +namespace Vecto3GUI2020Test +{ + public class TestHelper + { + private IXMLInputDataReader _inputDataReader; + + public TestHelper(IXMLInputDataReader inputDataReader) + { + _inputDataReader = inputDataReader; + } + + + + + public IInputDataProvider GetInputDataProvider(string fileName) + { + return _inputDataReader.Create(fileName); + } + + public static string GetMethodName([CallerMemberName] string name = null) + { + if (name == null) { + throw new ArgumentException(); + } + return name; + } + } +} \ No newline at end of file diff --git a/Vecto3GUI2020Test/UI/UITests.cs b/Vecto3GUI2020Test/UI/UITests.cs index 969b9c5a054b5ede41a07d6416946dee45b1bfdd..436e722c67439205a97705b8cd1c6929ff5c1274 100644 --- a/Vecto3GUI2020Test/UI/UITests.cs +++ b/Vecto3GUI2020Test/UI/UITests.cs @@ -16,7 +16,9 @@ namespace Vecto3GUI2020Test {/// <summary> /// The Application under Test has to run on a Windows 10 Machine on a Desktop called "VE /// </summary> - [TestFixture] +/// + [Ignore("GUI tests are not working that good")] + [TestFixture] public class UITests : VECTO3GUI2020Session { [SetUp] diff --git a/Vecto3GUI2020Test/Vecto3GUI2020Test.csproj b/Vecto3GUI2020Test/Vecto3GUI2020Test.csproj index 61e6686bd13a15f88e9aba5aa5ff5159c7136733..f51a815c10de39022bce192f090038f6878035fa 100644 --- a/Vecto3GUI2020Test/Vecto3GUI2020Test.csproj +++ b/Vecto3GUI2020Test/Vecto3GUI2020Test.csproj @@ -43,6 +43,9 @@ <Content Include="..\VectoCore\VectoCoreTest\TestData\XML\XMLReaderDeclaration\SchemaVersionMultistage.0.1\AirdragLoadTestFile.xml" Link="Testdata\AirdragLoadTestFile.xml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> + <Content Include="..\VectoCore\VectoCoreTest\TestData\XML\XMLReaderDeclaration\SchemaVersionMultistage.0.1\AirdragLoadTestFilev2.xml" Link="Testdata\AirdragLoadTestFilev2.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> <Content Include="..\VectoCore\VectoCoreTest\TestData\XML\XMLReaderDeclaration\SchemaVersionMultistage.0.1\vecto_multistage_consolidated_multiple_stages.xml" Link="Testdata\vecto_multistage_consolidated_multiple_stages.xml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> @@ -80,6 +83,7 @@ <ItemGroup> <PackageReference Include="Appium.WebDriver" Version="4.3.1" /> + <PackageReference Include="Microsoft.Toolkit.Mvvm" Version="7.0.2" /> <PackageReference Include="Moq" Version="4.16.1" /> <PackageReference Include="Ninject" Version="3.3.4" /> <PackageReference Include="NUnit" Version="3.12.0" /> @@ -99,4 +103,43 @@ <Reference Include="PresentationFramework" /> </ItemGroup> + <ItemGroup> + <None Update="inputdata\final.VIF_Report_4.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Update="inputdata\interim2.VIF_Report_3.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Update="inputdata\vecto_vehicle-completed_heavyBus_31b.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Update="TestData\bugreports\PrimaryDecimal\primary_heavyBus group41_nonSmart_rounded_decimals.xml"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> + <None Update="TestData\exempted_primary_heavyBus.VIF.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Update="TestData\exempted_vif_mandatory.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Update="TestData\final.VIF_Report_4.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Update="TestData\interim2.VIF_Report_3.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Update="TestData\newVifCompletedStage.json"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Update="TestData\vecto_vehicle-completed_heavyBus_31b.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + </ItemGroup> + + <ItemGroup> + <Folder Include="HelperTests\" /> + <Folder Include="Testdata\bugreports\" /> + <Folder Include="TestData\output\" /> + </ItemGroup> + </Project> diff --git a/Vecto3GUI2020Test/ViewModelTests/AirdragTests.cs b/Vecto3GUI2020Test/ViewModelTests/AirdragTests.cs index 2aadd6117d635ea7a42f50356528eb49a07e4182..a53049065c0728849d9d7d99820feeda878133de 100644 --- a/Vecto3GUI2020Test/ViewModelTests/AirdragTests.cs +++ b/Vecto3GUI2020Test/ViewModelTests/AirdragTests.cs @@ -17,31 +17,31 @@ namespace Vecto3GUI2020Test.ViewModelTests #region Airdrag [Test] - public void airdragModifiedInPreviousStages() + public void AirdragModifiedInPreviousStages() { var vm = loadFile(consolidated_multiple_stages_airdrag); - var vehicleVM = vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - DeclarationInterimStageBusVehicleViewModel_v2_8; + var vehicleVm = vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as + InterimStageBusVehicleViewModel_v2_8; - Assert.IsTrue(vehicleVM.AirdragModifiedMultistageEditingEnabled); + Assert.IsTrue(vehicleVm.AirdragModifiedMultistageEditingEnabled); //try to change to false - vehicleVM.AirdragModifiedMultistage = false; //should not change the value - Assert.IsTrue(vehicleVM.AirdragModifiedMultistageEditingEnabled); + vehicleVm.AirdragModifiedMultistage = false; //should not change the value + Assert.IsTrue(vehicleVm.AirdragModifiedMultistageEditingEnabled); } [Test] - public void airdragNotModifiedInPreviousStages() + public void AirdragNotModifiedInPreviousStages() { var vm = loadFile(consolidated_multiple_stages); - var vehicleVM = + var vehicleVm = vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - DeclarationInterimStageBusVehicleViewModel_v2_8; + InterimStageBusVehicleViewModel_v2_8; - Assert.IsFalse(vehicleVM.AirdragModifiedMultistageEditingEnabled); + Assert.IsFalse(vehicleVm.AirdragModifiedMultistageEditingEnabled); } /// <summary> @@ -50,32 +50,32 @@ namespace Vecto3GUI2020Test.ViewModelTests /// => 'AirdragModifiedMultistage' required in all consecutive stages /// </summary> [Test] - public void airdragComponentLoadedFirstTime() + public void AirdragComponentLoadedFirstTime() { ///Load VIF without airdrag var vm = loadFile(primary_vehicle_only); - var vehicleVM = + var vehicleVm = vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - DeclarationInterimStageBusVehicleViewModel_v2_8; + InterimStageBusVehicleViewModel_v2_8; - Assert.IsNull(vehicleVM.AirdragModifiedMultistage); + Assert.IsNull(vehicleVm.AirdragModifiedMultistage); - var airdragViewModel = vehicleVM.MultistageAirdragViewModel as MultistageAirdragViewModel; - Assert.IsTrue(airdragViewModel.LoadAirdragFile(GetFullPath(airdragLoadTestFile))); + var airdragViewModel = vehicleVm.MultistageAirdragViewModel as MultistageAirdragViewModel; + Assert.IsTrue(airdragViewModel.LoadAirdragFile(GetTestDataPath(airdragLoadTestFile))); - Assert.IsNull(vehicleVM.AirdragModifiedMultistage); - Assert.IsFalse(vehicleVM.AirdragModifiedMultistageMandatory); + Assert.IsNull(vehicleVm.AirdragModifiedMultistage); + Assert.IsFalse(vehicleVm.AirdragModifiedMultistageMandatory); - vehicleVM.AirdragModifiedMultistageEditingEnabled = true; - Assert.IsFalse(vehicleVM.AirdragModifiedMultistageEditingEnabled); + vehicleVm.AirdragModifiedMultistageEditingEnabled = true; + Assert.IsFalse(vehicleVm.AirdragModifiedMultistageEditingEnabled); - Assert.IsNull(vehicleVM.AirdragModifiedMultistage); + Assert.IsNull(vehicleVm.AirdragModifiedMultistage); //Set Mandatory Fields - vehicleVM.Manufacturer = "testManufacturer"; - vehicleVM.ManufacturerAddress = "Address"; - vehicleVM.VIN = "123456789"; + vehicleVm.Manufacturer = "testManufacturer"; + vehicleVm.ManufacturerAddress = "Address"; + vehicleVm.VIN = "123456789"; //Save as new VIF var multistageJobViewModel = vm.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; @@ -84,41 +84,41 @@ namespace Vecto3GUI2020Test.ViewModelTests var resultFile = $"{outputName}.VIF_Report_2.xml"; Assert.IsTrue(checkFileNameExists(resultFile)); - var secondstageVM = loadFile(resultFile); - Assert.IsNotNull(secondstageVM); - var secondStageVehicleVM = - (secondstageVM.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel) as - DeclarationInterimStageBusVehicleViewModel_v2_8; - Assert.IsTrue(secondStageVehicleVM.AirdragModifiedMultistageEditingEnabled); - Assert.IsTrue(secondStageVehicleVM.AirdragModifiedMultistageMandatory); - Assert.IsNull(secondStageVehicleVM.ConsolidatedVehicleData.AirdragModifiedMultistage); + var secondstageVm = loadFile(resultFile); + Assert.IsNotNull(secondstageVm); + var secondStageVehicleVm = + (secondstageVm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel) as + InterimStageBusVehicleViewModel_v2_8; + Assert.IsTrue(secondStageVehicleVm.AirdragModifiedMultistageEditingEnabled); + Assert.IsTrue(secondStageVehicleVm.AirdragModifiedMultistageMandatory); + Assert.IsNull(secondStageVehicleVm.ConsolidatedVehicleData.AirdragModifiedMultistage); //try to disable AirdragModified - secondStageVehicleVM.AirdragModifiedMultistageEditingEnabled = false; - Assert.IsTrue(secondStageVehicleVM.AirdragModifiedMultistageEditingEnabled); + secondStageVehicleVm.AirdragModifiedMultistageEditingEnabled = false; + Assert.IsTrue(secondStageVehicleVm.AirdragModifiedMultistageEditingEnabled); } /// <summary> /// no airdrag component set in VIF => AirdragModifiedMultistage is disabled /// </summary> [Test] - public void airdragModifiedDisabled() + public void AirdragModifiedDisabled() { var vm = loadFile(primary_vehicle_only); - var vehicleVM = + var vehicleVm = vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - DeclarationInterimStageBusVehicleViewModel_v2_8; + InterimStageBusVehicleViewModel_v2_8; - Assert.IsNull(vehicleVM.AirdragModifiedMultistage); + Assert.IsNull(vehicleVm.AirdragModifiedMultistage); - Assert.IsNull(vehicleVM.AirdragModifiedMultistage); - Assert.IsFalse(vehicleVM.AirdragModifiedMultistageMandatory); + Assert.IsNull(vehicleVm.AirdragModifiedMultistage); + Assert.IsFalse(vehicleVm.AirdragModifiedMultistageMandatory); - var airdragViewModel = vehicleVM.MultistageAirdragViewModel; - Assert.IsTrue(airdragViewModel.LoadAirdragFile(GetFullPath(airdragLoadTestFile)), "Airdrag file not loaded"); - Assert.IsFalse(vehicleVM.AirdragModifiedMultistageMandatory); + var airdragViewModel = vehicleVm.MultistageAirdragViewModel; + Assert.IsTrue(airdragViewModel.LoadAirdragFile(GetTestDataPath(airdragLoadTestFile)), "Airdrag file not loaded"); + Assert.IsFalse(vehicleVm.AirdragModifiedMultistageMandatory); - vehicleVM.AirdragModifiedMultistageEditingEnabled = true; - Assert.IsFalse(vehicleVM.AirdragModifiedMultistageEditingEnabled); + vehicleVm.AirdragModifiedMultistageEditingEnabled = true; + Assert.IsFalse(vehicleVm.AirdragModifiedMultistageEditingEnabled); } /// <summary> @@ -126,12 +126,12 @@ namespace Vecto3GUI2020Test.ViewModelTests /// </summary> [Test] - public void airdragModifiedMandatory() + public void AirdragModifiedMandatory() { //var vm = loadFile(primary_vehicle_only); //var vehicleVM = // vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - // DeclarationInterimStageBusVehicleViewModel_v2_8; + // InterimStageBusVehicleViewModel_v2_8; //Assert.IsNull(vehicleVM.AirdragModifiedMultistage); @@ -144,17 +144,17 @@ namespace Vecto3GUI2020Test.ViewModelTests } [Test] - public void temporarySaveAirdragComponent1() + public void TemporarySaveAirdragComponent1() { var vm = loadFile(consolidated_multiple_stages_airdrag); - var vehicleViewModel = vm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as DeclarationInterimStageBusVehicleViewModel_v2_8; + var vehicleViewModel = vm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as InterimStageBusVehicleViewModel_v2_8; Assert.IsNull(vehicleViewModel.AirdragModifiedMultistage); //Load airdrag file - var airdragLoaded = vehicleViewModel.MultistageAirdragViewModel.LoadAirdragFile(GetFullPath(airdragLoadTestFile)); + var airdragLoaded = vehicleViewModel.MultistageAirdragViewModel.LoadAirdragFile(GetTestDataPath(airdragLoadTestFile)); var loadedAirdragComponent = vehicleViewModel.MultistageAirdragViewModel.AirDragViewModel; Assert.IsTrue(airdragLoaded, "Airdrag file was not loaded"); @@ -176,19 +176,18 @@ namespace Vecto3GUI2020Test.ViewModelTests } [Test] - public void temporarySaveAirdragComponent2() + public void TemporarySaveAirdragComponent2() { var vm = loadFile(consolidated_multiple_stages_airdrag); - var vehicleViewModel = vm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as DeclarationInterimStageBusVehicleViewModel_v2_8; + var vehicleViewModel = vm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as InterimStageBusVehicleViewModel_v2_8; Assert.IsNull(vehicleViewModel.AirdragModifiedMultistage); //Load input file var multistageJobViewModel = vm.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; - var mockDialogHelper = setMockDialogHelper(stageInputFullSample, null); - multistageJobViewModel.LoadVehicleDataCommand.Execute(null); + multistageJobViewModel.ManufacturingStageViewModel.LoadStageInputData(GetTestDataPath(stageInputFullSample)); @@ -214,19 +213,19 @@ namespace Vecto3GUI2020Test.ViewModelTests } [Test] - public void removeAirdragComponent() + public void RemoveAirdragComponent() { var vm = loadFile(consolidated_multiple_stages_airdrag); - var vehicleViewModel = vm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as DeclarationInterimStageBusVehicleViewModel_v2_8; + var vehicleViewModel = vm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as InterimStageBusVehicleViewModel_v2_8; Assert.IsNull(vehicleViewModel.AirdragModifiedMultistage); //Load input file var multistageJobViewModel = vm.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; - var mockDialogHelper = setMockDialogHelper(stageInputFullSample, null); - multistageJobViewModel.LoadVehicleDataCommand.Execute(null); + multistageJobViewModel.ManufacturingStageViewModel.LoadStageInputData( + GetTestDataPath(stageInputFullSample)); Assert.IsTrue(vehicleViewModel.AirdragModifiedMultistage); @@ -241,17 +240,17 @@ namespace Vecto3GUI2020Test.ViewModelTests [Test] - public void airdragModifiedSetToTrueWhenComponentIsLoaded() + public void AirdragModifiedSetToTrueWhenComponentIsLoaded() { var vm = loadFile(consolidated_multiple_stages_airdrag); - var vehicleViewModel = vm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as DeclarationInterimStageBusVehicleViewModel_v2_8; + var vehicleViewModel = vm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as InterimStageBusVehicleViewModel_v2_8; Assert.IsNull(vehicleViewModel.AirdragModifiedMultistage); //Load airdrag file - var airdragLoaded = vehicleViewModel.MultistageAirdragViewModel.LoadAirdragFile(GetFullPath(airdragLoadTestFile)); + var airdragLoaded = vehicleViewModel.MultistageAirdragViewModel.LoadAirdragFile(GetTestDataPath(airdragLoadTestFile)); Assert.IsTrue(airdragLoaded, "Airdrag file was not loaded"); //Airdrag modified set to true if a component is loaded and the field is mandatory @@ -264,7 +263,7 @@ namespace Vecto3GUI2020Test.ViewModelTests //AirdragComponent is removed when airdragmodified is set to false; //Load airdrag file - airdragLoaded = vehicleViewModel.MultistageAirdragViewModel.LoadAirdragFile(GetFullPath(airdragLoadTestFile)); + airdragLoaded = vehicleViewModel.MultistageAirdragViewModel.LoadAirdragFile(GetTestDataPath(airdragLoadTestFile)); Assert.IsTrue(airdragLoaded, "Airdrag file was not loaded"); vehicleViewModel.AirdragModifiedMultistage = false; diff --git a/Vecto3GUI2020Test/ViewModelTests/CreateVifViewModelTests.cs b/Vecto3GUI2020Test/ViewModelTests/CreateVifViewModelTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..bef354ab424c31591b3f0ec3c69759250c27822f --- /dev/null +++ b/Vecto3GUI2020Test/ViewModelTests/CreateVifViewModelTests.cs @@ -0,0 +1,200 @@ +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using System.Windows.Input; +using Ninject; +using NUnit.Framework; +using VECTO3GUI2020.ViewModel.Implementation; +using VECTO3GUI2020.ViewModel.Interfaces; +using VECTO3GUI2020.ViewModel.MultiStage.Implementation; + +namespace Vecto3GUI2020Test.ViewModelTests +{ + [TestFixture] + public class CreateVifViewModelTests : ViewModelTestBase + { + private ICreateVifViewModel _createVifViewModel; + + private const string testdata_2_6 = "XML\\XMLReaderDeclaration\\SchemaVersion2.6_Buses\\"; + private const string testdata_2_8 = "XML\\XMLReaderDeclaration\\SchemaVersion2.8\\"; + + private const string vecto_vehicle_primary_heavyBusSample = + testdata_2_6 + "vecto_vehicle-primary_heavyBus-sample.xml"; + + private const string vecto_vehicle_exempted_input_only_certain_entries = + "vecto_vehicle-exempted_input_only_certain_entries01-sample.xml"; + + private const string vecto_vehicle_primary_heavyBusExempted = testdata_2_6 + "exempted_primary_heavyBus.xml"; + + [SetUp] + public void SetUpCreateVif() + { + _createVifViewModel = _kernel.Get<ICreateVifViewModel>(); + } + + [TestCase(stageInputFullSample, TestName="InvalidPrimaryFile_StageInput")] + [TestCase(airdragLoadTestFile, TestName="InvalidPrimaryFile_Airdrag")] + [TestCase(consolidated_multiple_stages_airdrag, TestName = "InvalidPrimaryFile_VIF")] + [TestCase(vecto_vehicle_exempted_input_only_certain_entries, TestName="InvalidPrimaryFile_ExemptedStageInput")] + public void LoadInvalidPrimaryFile(string fileName) + { + var filePath = GetTestDataPath(fileName); + Assert.IsFalse(_createVifViewModel.LoadPrimaryInput(filePath)); + Assert.IsNull(_createVifViewModel.PrimaryInputPath); + Assert.IsNull(_createVifViewModel.IsPrimaryExempted); + } + + + [TestCase(vecto_vehicle_primary_heavyBusSample, TestName = "InvalidStageInput_Primary")] + [TestCase(airdragLoadTestFile, TestName = "InvalidStageInput_Airdrag")] + [TestCase(consolidated_multiple_stages_airdrag, TestName = "InvalidStageFile_VIF")] + public void LoadInvalidCompletedFile(string fileName) + { + var filePath = GetTestDataPath(fileName); + Assert.IsFalse(_createVifViewModel.LoadStageInput(filePath)); + Assert.IsNull(_createVifViewModel.IsStageInputExempted); + Assert.IsNull(_createVifViewModel.StageInputPath); + } + + [Ignore("incomplete")] + [Test] + public void LoadExemptedCompletedAndNonExemptedPrimary() + { + + } + + [Test] + public void SaveFile() + { + LoadValidNonExemptedFiles(); + var outputFile = "test.json"; + var outputPath = GetFullPath(outputFile); + _createVifViewModel.SaveJob(outputPath); + + FileAssert.Exists(outputPath); + + Assert.AreEqual(Path.GetDirectoryName(outputPath), _createVifViewModel.DataSource.SourcePath); + Assert.AreEqual(outputPath, _createVifViewModel.DataSource.SourceFile); + } + + + [Test] + public void LoadNonExemptedCompletedAndExemptedPrimary() + { + var exemptedPrimaryPath = GetTestDataPath(vecto_vehicle_primary_heavyBusExempted); + var stageInputPath = GetTestDataPath(stageInputFullSample); + + Assert.IsTrue(_createVifViewModel.LoadPrimaryInput(exemptedPrimaryPath)); + Assert.IsFalse(_createVifViewModel.LoadStageInput(stageInputPath)); + } + + + + [Test] + public void LoadValidPrimaryFile() + { + var filePath = GetTestDataPath(vecto_vehicle_primary_heavyBusSample); + Assert.IsTrue(_createVifViewModel.LoadPrimaryInput(filePath)); + Assert.AreEqual(filePath, _createVifViewModel.PrimaryInputPath); + } + + [TestCase(stageInputFullSample, TestName = "ValidStageInput_fullStageInput")] + [TestCase(vecto_vehicle_exempted_input_only_certain_entries, TestName = "ValidStageInput_exemptedStageInput")] + public void LoadValidStageInputFile(string fileName) + { + var filePath = GetTestDataPath(fileName); + Assert.IsTrue(_createVifViewModel.LoadStageInput(filePath)); + Assert.AreEqual(filePath, _createVifViewModel.StageInputPath); + } + + [Test] + public void LoadValidNonExemptedFilesTest() + { + LoadValidNonExemptedFiles(); + } + + + public void LoadValidNonExemptedFiles() + { + var primaryPath = GetTestDataPath(vecto_vehicle_primary_heavyBusSample); + var stageInputPath = GetTestDataPath(stageInputFullSample); + + Assert.IsTrue(_createVifViewModel.LoadPrimaryInput(primaryPath)); + Assert.IsTrue(_createVifViewModel.LoadStageInput(stageInputPath)); + } + + [Test] + public void LoadValidExemptedFiles() + { + var primaryPath = GetTestDataPath(vecto_vehicle_primary_heavyBusExempted); + var stageInputPath = GetTestDataPath(vecto_vehicle_exempted_input_only_certain_entries); + Assert.IsTrue(_createVifViewModel.LoadPrimaryInput(primaryPath)); + Assert.IsTrue(_createVifViewModel.LoadStageInput(stageInputPath)); + + } + + [Test] + public void RemoveInputs() + { + LoadValidNonExemptedFiles(); + Assert.NotNull(_createVifViewModel.PrimaryInputPath); + Assert.NotNull(_createVifViewModel.StageInputPath); + + bool removePrimaryNotified = false; + bool removeStageInputNotified = false; + _createVifViewModel.RemovePrimaryCommand.CanExecuteChanged += + ((sender, args) => removePrimaryNotified = true); + _createVifViewModel.RemoveStageInputCommand.CanExecuteChanged += + ((sender, args) => removeStageInputNotified = true); + + + //Remove Primary + Assert.IsTrue(_createVifViewModel.RemovePrimaryCommand.CanExecute(null)); + + _createVifViewModel.RemovePrimaryCommand.Execute(null); + Assert.IsTrue(removePrimaryNotified); + removePrimaryNotified = false; + + Assert.IsFalse(_createVifViewModel.RemovePrimaryCommand.CanExecute(null)); + Assert.IsNull(_createVifViewModel.PrimaryInputPath); + Assert.IsNull(_createVifViewModel.IsPrimaryExempted); + + + //Remove Stage Input + Assert.IsTrue(_createVifViewModel.RemoveStageInputCommand.CanExecute(null)); + + _createVifViewModel.RemoveStageInputCommand.Execute(null); + Assert.IsTrue(removeStageInputNotified); + removeStageInputNotified = false; + + Assert.IsFalse(_createVifViewModel.RemovePrimaryCommand.CanExecute(null)); + Assert.IsNull(_createVifViewModel.PrimaryInputPath); + Assert.IsNull(_createVifViewModel.IsPrimaryExempted); + } + + + [Test] + public async Task SaveAndReload() + { + LoadValidNonExemptedFiles(); + var primaryPath = _createVifViewModel.PrimaryInputPath; + var stagePath = _createVifViewModel.StageInputPath; + + var savedToPath = _createVifViewModel.SaveJob("non_exempted.json"); + WriteLine($"Saved to: {savedToPath}"); + + Assert.AreEqual(primaryPath, _createVifViewModel.PrimaryInputPath); + Assert.AreEqual(stagePath, _createVifViewModel.StageInputPath); + + var jobListVm = _kernel.Get<IJobListViewModel>() as JobListViewModel; + var loadedDoc = await jobListVm.AddJobAsync(savedToPath) as CreateVifViewModel; + + Assert.AreEqual(stagePath, loadedDoc.StageInputPath); + Assert.AreEqual(primaryPath, loadedDoc.PrimaryInputPath); + + + + + } + } +} \ No newline at end of file diff --git a/Vecto3GUI2020Test/ViewModelTests/ExemptedTests.cs b/Vecto3GUI2020Test/ViewModelTests/ExemptedTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..4a5e4b3c6de620e33bb83052314a1ff7ef0f25ef --- /dev/null +++ b/Vecto3GUI2020Test/ViewModelTests/ExemptedTests.cs @@ -0,0 +1,197 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Castle.Core.Logging; +using Ninject; +using NUnit.Framework; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using VECTO3GUI2020.ViewModel.Implementation; +using VECTO3GUI2020.ViewModel.Interfaces; +using VECTO3GUI2020.ViewModel.MultiStage.Implementation; + +namespace Vecto3GUI2020Test.ViewModelTests +{ + [TestFixture] + public class ExemptedTests : ViewModelTestBase + { + + public const string _exemptedMandatory = "exempted_vif_mandatory.xml"; + + [Test] + public void LoadAndSaveExemptedPrimary() + { + var newMultiStageJob = loadFile(exempted_primary_vif); + Assert.IsTrue(newMultiStageJob.MultiStageJobViewModel.Exempted); + + + var multistageJobViewModel = newMultiStageJob.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; + + var outputPath = GetFullPath("test1.xml"); + + var vehicleVm = + multistageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as + InterimStageBusVehicleViewModel_v2_8; + + Assert.IsTrue(vehicleVm.ExemptedVehicle); + + + var manufacturer = "TestManufacturer"; + var manufacturerAddress = "TestManufacturerAddress"; + var vehicleIdentificationNumber = "12345678"; + var model = "model"; + var curbMassChassis = Kilogram.Create(123456); + var technicalpermissableLadenMass = Kilogram.Create(654321); + var registeredClass = RegistrationClass.II_III; + var legislativeCategory = LegislativeClass.M3; + var bodyWorkCode = VehicleCode.CG; + var lowEntry = false; + var height = Meter.Create(1.5).ConvertToMilliMeter(); + var PassengerSeatsLowerDeck = 4; + var passengerSeatsUpperDeck = 12; + + vehicleVm.ParameterViewModels[nameof(vehicleVm.Manufacturer)].CurrentContent = manufacturer; + vehicleVm.ParameterViewModels[nameof(vehicleVm.ManufacturerAddress)].CurrentContent = manufacturerAddress; + vehicleVm.ParameterViewModels[nameof(vehicleVm.HeightInMm)].CurrentContent = height; + vehicleVm.ParameterViewModels[nameof(vehicleVm.VIN)].CurrentContent = vehicleIdentificationNumber; + vehicleVm.ParameterViewModels[nameof(vehicleVm.Model)].CurrentContent = model; + vehicleVm.ParameterViewModels[nameof(vehicleVm.LegislativeClass)].CurrentContent = legislativeCategory; + vehicleVm.ParameterViewModels[nameof(vehicleVm.CurbMassChassis)].CurrentContent = curbMassChassis; + vehicleVm.ParameterViewModels[nameof(vehicleVm.GrossVehicleMassRating)].CurrentContent = technicalpermissableLadenMass; + vehicleVm.ParameterViewModels[nameof(vehicleVm.RegisteredClass)].CurrentContent = registeredClass; + vehicleVm.ParameterViewModels[nameof(vehicleVm.VehicleCode)].CurrentContent = bodyWorkCode; + vehicleVm.ParameterViewModels[nameof(vehicleVm.LowEntry)].CurrentContent = lowEntry; + vehicleVm.ParameterViewModels[nameof(vehicleVm.NumberPassengerSeatsLowerDeck)].CurrentContent = PassengerSeatsLowerDeck; + vehicleVm.ParameterViewModels[nameof(vehicleVm.NumberPassengerSeatsUpperDeck)].CurrentContent = passengerSeatsUpperDeck; + + + multistageJobViewModel.ManufacturingStageViewModel.SaveInputDataExecute(outputPath); + + + Assert.AreEqual(outputPath, multistageJobViewModel.VehicleInputDataFilePath); + + Assert.AreEqual(manufacturer, vehicleVm.Manufacturer); + Assert.AreEqual(manufacturerAddress, vehicleVm.ManufacturerAddress); + Assert.AreEqual(height, vehicleVm.HeightInMm); + Assert.AreEqual(model, vehicleVm.Model); + Assert.AreEqual(legislativeCategory, vehicleVm.LegislativeClass); + Assert.AreEqual(curbMassChassis, vehicleVm.CurbMassChassis); + Assert.AreEqual(technicalpermissableLadenMass, vehicleVm.GrossVehicleMassRating); + Assert.AreEqual(registeredClass, vehicleVm.RegisteredClass); + Assert.AreEqual(bodyWorkCode, vehicleVm.VehicleCode); + Assert.AreEqual(lowEntry, vehicleVm.LowEntry); + Assert.AreEqual(passengerSeatsUpperDeck, vehicleVm.NumberPassengerSeatsUpperDeck); + Assert.AreEqual(PassengerSeatsLowerDeck, vehicleVm.NumberPassengerSeatsLowerDeck); + } + + [Test] + public async Task SaveAsNewVifAndSimulate() + { + var newMultiStageJob = loadFile(exempted_primary_vif); + Assert.IsTrue(newMultiStageJob.MultiStageJobViewModel.Exempted); + + + var multistageJobViewModel = newMultiStageJob.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; + + var outputFile = GetFullPath("exemptedNewVif/test1.xml"); + + var vehicleVm = + multistageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as + InterimStageBusVehicleViewModel_v2_8; + + Assert.IsTrue(vehicleVm.ExemptedVehicle); + + + var manufacturer = "TestManufacturer"; + var manufacturerAddress = "TestManufacturerAddress"; + var vehicleIdentificationNumber = "12345678"; + var model = "model"; + var curbMassChassis = Kilogram.Create(123456); + var technicalpermissableLadenMass = Kilogram.Create(654321); + var registeredClass = RegistrationClass.II_III; + var bodyWorkCode = VehicleCode.CG; + var legislativeCategory = LegislativeClass.M3; + var lowEntry = false; + var height = Meter.Create(1.5).ConvertToMilliMeter(); + var PassengerSeatsLowerDeck = 4; + var passengerSeatsUpperDeck = 12; + + vehicleVm.ParameterViewModels[nameof(vehicleVm.Manufacturer)].CurrentContent = manufacturer; + vehicleVm.ParameterViewModels[nameof(vehicleVm.ManufacturerAddress)].CurrentContent = manufacturerAddress; + vehicleVm.ParameterViewModels[nameof(vehicleVm.HeightInMm)].CurrentContent = height; + vehicleVm.ParameterViewModels[nameof(vehicleVm.VIN)].CurrentContent = vehicleIdentificationNumber; + vehicleVm.ParameterViewModels[nameof(vehicleVm.Model)].CurrentContent = model; + vehicleVm.ParameterViewModels[nameof(vehicleVm.LegislativeClass)].CurrentContent = legislativeCategory; + vehicleVm.ParameterViewModels[nameof(vehicleVm.CurbMassChassis)].CurrentContent = curbMassChassis; + vehicleVm.ParameterViewModels[nameof(vehicleVm.GrossVehicleMassRating)].CurrentContent = technicalpermissableLadenMass; + vehicleVm.ParameterViewModels[nameof(vehicleVm.RegisteredClass)].CurrentContent = registeredClass; + vehicleVm.ParameterViewModels[nameof(vehicleVm.VehicleCode)].CurrentContent = bodyWorkCode; + vehicleVm.ParameterViewModels[nameof(vehicleVm.LowEntry)].CurrentContent = lowEntry; + vehicleVm.ParameterViewModels[nameof(vehicleVm.NumberPassengerSeatsLowerDeck)].CurrentContent = PassengerSeatsLowerDeck; + vehicleVm.ParameterViewModels[nameof(vehicleVm.NumberPassengerSeatsUpperDeck)].CurrentContent = passengerSeatsUpperDeck; + + try { + Directory.Delete(Path.GetDirectoryName(outputFile), true); + } catch (Exception e) { + WriteLine(e.Message); + } + var result = multistageJobViewModel.SaveVif(outputFile); + + //Check that file exists + Assert.IsTrue(File.Exists(result)); + + //Check that file was added to JobList + var jobListVm = _kernel.Get<IJobListViewModel>() as JobListViewModel; + Assert.AreEqual(2, jobListVm.Jobs.Count); + Assert.AreEqual(result, jobListVm.Jobs[1].DataSource.SourceFile); + + var inputDataProvider = _testHelper.GetInputDataProvider(result) as IMultistageBusInputDataProvider; + Assert.NotNull(inputDataProvider); + + //Check added Manufacturing Stage + var lastManStage = inputDataProvider.JobInputData.ManufacturingStages.Last(); + + + Assert.AreEqual(manufacturer, lastManStage.Vehicle.Manufacturer); + Assert.AreEqual(manufacturerAddress, lastManStage.Vehicle.ManufacturerAddress); + Assert.AreEqual(height.ConvertToMeter(), lastManStage.Vehicle.Height); + Assert.AreEqual(model, lastManStage.Vehicle.Model); + Assert.AreEqual(legislativeCategory, lastManStage.Vehicle.LegislativeClass); + Assert.AreEqual(curbMassChassis, lastManStage.Vehicle.CurbMassChassis); + Assert.AreEqual(technicalpermissableLadenMass, lastManStage.Vehicle.GrossVehicleMassRating); + Assert.AreEqual(registeredClass, lastManStage.Vehicle.RegisteredClass); + Assert.AreEqual(bodyWorkCode, lastManStage.Vehicle.VehicleCode); + Assert.AreEqual(lowEntry, lastManStage.Vehicle.LowEntry); + Assert.AreEqual(passengerSeatsUpperDeck, lastManStage.Vehicle.NumberPassengerSeatsUpperDeck); + Assert.AreEqual(PassengerSeatsLowerDeck, lastManStage.Vehicle.NumberPassengerSeatsLowerDeck); + + + Write("Starting simulation ..."); + jobListVm.Jobs[1].Selected = true; + await jobListVm.RunSimulationExecute(); + + + Write("Done!"); + } + + [Test] + public async Task SimulateMinimalExemptedVif() + { + //Setup + var jobListViewModel = _kernel.Get<IJobListViewModel>() as JobListViewModel; + await jobListViewModel.AddJobAsync(GetTestDataPath(_exemptedMandatory)); + Assert.AreEqual(1, jobListViewModel.Jobs.Count); + + jobListViewModel.Jobs[0].Selected = true; + await jobListViewModel.RunSimulationExecute(); + + + } + + + + } +} \ No newline at end of file diff --git a/Vecto3GUI2020Test/ViewModelTests/ExtensionTests.cs b/Vecto3GUI2020Test/ViewModelTests/ExtensionTests.cs index 50d9531a52b15491bf75126f42deb6ff1e0c3818..7e758e678e7e7987f273b161713cfdc481a7200e 100644 --- a/Vecto3GUI2020Test/ViewModelTests/ExtensionTests.cs +++ b/Vecto3GUI2020Test/ViewModelTests/ExtensionTests.cs @@ -2,7 +2,8 @@ using System.Collections.ObjectModel; using NUnit.Framework; using TUGraz.VectoCommon.Models; -using VECTO3GUI2020.Helper; +using TUGraz.VectoCommon.Utils; +using EnumHelper = VECTO3GUI2020.Helper.EnumHelper; namespace Vecto3GUI2020Test.ViewModelTests { @@ -38,6 +39,25 @@ namespace Vecto3GUI2020Test.ViewModelTests Assert.False(collection2.Contains(VehicleCode.NOT_APPLICABLE)); } - + [Ignore("")] + [TestCase(1.000, 3U, "1.000")] + [TestCase(1.210, 3U, "1.210")] + [TestCase(1.201, 3U, "1.201")] + [TestCase(1.3, 3U, "1.300")] + public void ToMinSignificantDigitsExtensionTest(double input, uint significantDigits, string expected) + { + var result = input.ToMinSignificantDigits(significantDigits); //Called like this in XMLPrimaryBusVehicleReport; + Assert.AreEqual(expected, result); + } + + [TestCase(1.000, 3U, 3U, "1.000")] + [TestCase(1.210, 3U, 3U, "1.210")] + [TestCase(1.201, 3U, 3U, "1.201")] + [TestCase(1.3, 3U, 3U, "1.300")] + public void ToMinSignificantDigitsExtensionTest2(double input, uint significantDigits, uint decimals, string expected) + { + var result = input.ToMinSignificantDigits(significantDigits, decimals); //Called like this in XMLPrimaryBusVehicleReport; + Assert.AreEqual(expected, result); + } } } \ No newline at end of file diff --git a/Vecto3GUI2020Test/ViewModelTests/JobListViewModelTests.cs b/Vecto3GUI2020Test/ViewModelTests/JobListViewModelTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..cbf317ed64243b879a5ae21c922c7f84a71e9e34 --- /dev/null +++ b/Vecto3GUI2020Test/ViewModelTests/JobListViewModelTests.cs @@ -0,0 +1,132 @@ +using System.Diagnostics; +using System.Threading.Tasks; +using Ninject; +using NUnit.Framework; +using NUnit.Framework.Internal; +using VECTO3GUI2020.ViewModel; +using VECTO3GUI2020.ViewModel.Implementation; +using VECTO3GUI2020.ViewModel.Interfaces; +using VECTO3GUI2020.ViewModel.MultiStage.Implementation; +using Vecto3GUI2020Test.BugReports; + +namespace Vecto3GUI2020Test.ViewModelTests +{ + [TestFixture] + public class JobListViewModelTests : ViewModelTestBase + { + private const string finalVIF = "final.VIF_Report_4.xml"; + + private const string _newVifJob = "newVifCompletedStage.json"; + private JobListViewModel _jobListViewModel; + + [SetUp] + public void SetupViewModelTests() + { + _jobListViewModel = _kernel.Get<IJobListViewModel>() as JobListViewModel; + } + + [Test] + public async Task CancelSimulationWhileLoadingFiles() + { + var watch = new Stopwatch(); + watch.Start(); + //load final vif + var loadedFile = await _jobListViewModel.AddJobAsync(GetTestDataPath(finalVIF)).ConfigureAwait(false); + + //select vif for simulation + Assert.AreNotEqual(0, _jobListViewModel.Jobs.Count); + _jobListViewModel.Jobs[0].Selected = true; + + + _jobListViewModel.RunSimulationExecute(); + TestContext.Write("Canceling Simulation ... "); + Assert.IsTrue(_jobListViewModel.SimulationRunning); + _jobListViewModel.CancelSimulation.Execute(null); + + + //Wait + var constraint = Is.True.After(delayInMilliseconds: 100000, pollingInterval: 100); + Assert.That(() => _jobListViewModel.SimulationRunning == false, constraint); + TestContext.WriteLine("Done!"); + + watch.Stop(); + TestContext.WriteLine($"ExecutionTime {watch.Elapsed.TotalSeconds}s"); + } + + [TestCase(VIFTests.exempted_primary_vif, TestName="Exempted")] + public async Task AddJobAsyncTest(string fileName) + { + var path = GetTestDataPath(fileName); + Assert.AreEqual(0, _jobListViewModel.Jobs.Count); + + await _jobListViewModel.AddJobAsync(path); + Assert.AreEqual(1, _jobListViewModel.Jobs.Count); + + Assert.AreEqual(path, _jobListViewModel.Jobs[0].DataSource.SourceFile); + } + + [TestCase(true, TestName = "Exempted")] + [TestCase(false, TestName = "NotExempted")] + public void addNewFilesToJobList(bool exempted) + { + if (exempted) + { + _jobListViewModel.NewExemptedCompletedInputCommand.Execute(null); + } + else + { + _jobListViewModel.NewCompletedInputCommand.Execute(null); + } + + Assert.AreEqual(1, _jobListViewModel.Jobs.Count); + } + + + [Test] + public async Task CancelSimulationWhenJobContainerIsRunning() + { + var watch = new Stopwatch(); + watch.Start(); + + //load final vif + var loadedFile = await _jobListViewModel.AddJobAsync(GetTestDataPath(finalVIF)).ConfigureAwait(false); + + //select vif for simulation + Assert.AreNotEqual(0, _jobListViewModel.Jobs.Count); + _jobListViewModel.Jobs[0].Selected = true; + + + //Simulate for a while + var outputVm = _kernel.Get<IOutputViewModel>(); // SINGLETON + var simulationTask = _jobListViewModel.RunSimulationExecute(); + Assert.That(() => outputVm.Progress, Is.GreaterThanOrEqualTo(25).After(1 * 60 * 1000, 1), + () => $"Simulation reached {outputVm.Progress}%"); + + TestContext.Write("Canceling Simulation ... "); + Assert.IsTrue(_jobListViewModel.SimulationRunning); + _jobListViewModel.CancelSimulation.Execute(null); + Assert.That(() => _jobListViewModel.SimulationRunning, Is.False.After(20*1000, 50) ); + TestContext.WriteLine("Done!"); + + watch.Stop(); + TestContext.WriteLine($"ExecutionTime {watch.Elapsed.TotalSeconds}s"); + } + + [Test] + public async Task LoadStageInputOnly() + { + var documentViewModel = await _jobListViewModel.AddJobAsync(GetTestDataPath(stageInputFullSample)); + Assert.AreEqual(typeof(StageInputViewModel), documentViewModel.GetType()); + + var stageInputDocumentViewModel = documentViewModel.EditViewModel as StageInputViewModel; + Assert.NotNull(stageInputDocumentViewModel); + } + + [Test] + public async Task LoadNewVifJob() + { + var documentViewModel = await _jobListViewModel.AddJobAsync(GetTestDataPath(_newVifJob)); + Assert.NotNull(documentViewModel); + } + } +} \ No newline at end of file diff --git a/Vecto3GUI2020Test/ViewModelTests/JsonTests.cs b/Vecto3GUI2020Test/ViewModelTests/JsonTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..83aedfdca1f14e78787968998ca8023b5790811c --- /dev/null +++ b/Vecto3GUI2020Test/ViewModelTests/JsonTests.cs @@ -0,0 +1,23 @@ +using NUnit.Framework; +using VECTO3GUI2020.Model.Multistage; +using TUGraz.VectoCore; + +namespace Vecto3GUI2020Test.ViewModelTests +{ + [TestFixture] + public class JsonTests + { + [Test] + public void NamingTest() + { + //Membernames have to match JsonKeys for correct serialization/desirialization + Assert.AreEqual(JsonKeys.JsonHeader, nameof(JSONJob.Header)); + Assert.AreEqual(JsonKeys.JsonHeader_FileVersion, nameof(JSONJob.Header.FileVersion)); + + Assert.AreEqual(JsonKeys.JsonBody, nameof(JSONJob.Body)); + Assert.AreEqual(JsonKeys.PrimaryVehicle, nameof(JSONJob.Body.PrimaryVehicle)); + Assert.AreEqual(JsonKeys.InterimStage, nameof(JSONJob.Body.InterimStage)); + Assert.AreEqual(JsonKeys.Completed, nameof(JSONJob.Body.Completed)); + } + } +} \ No newline at end of file diff --git a/Vecto3GUI2020Test/ViewModelTests/LoadAndSaveVehicleData.cs b/Vecto3GUI2020Test/ViewModelTests/LoadAndSaveVehicleData.cs index 8758db065c94b238396213ab54a6c184dae73b8c..43d10665153d00b3f3c05249ee0c2c3e5e2bf48b 100644 --- a/Vecto3GUI2020Test/ViewModelTests/LoadAndSaveVehicleData.cs +++ b/Vecto3GUI2020Test/ViewModelTests/LoadAndSaveVehicleData.cs @@ -1,4 +1,5 @@ using System; +using System.Configuration; using System.IO; using System.Linq; using System.Runtime.CompilerServices; @@ -20,7 +21,9 @@ using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Strategies; using TUGraz.VectoCore.OutputData.FileIO; using TUGraz.VectoCore.Utils; +using VECTO3GUI2020; using VECTO3GUI2020.Helper; +using VECTO3GUI2020.ViewModel.Implementation.JobEdit.Vehicle.Components; using VECTO3GUI2020.ViewModel.MultiStage.Implementation; namespace Vecto3GUI2020Test @@ -29,17 +32,21 @@ namespace Vecto3GUI2020Test public class LoadAndSaveVehicleData : ViewModelTestBase { [Test] - public void loadInputFileMultipleStage() + public void LoadInputFileMultipleStage() { - loadFile(consolidated_multiple_stages); + Assert.NotNull(loadFile(consolidated_multiple_stages)); } - [Test] - public void loadPrimaryAndSaveVehicleData() + + [Test, Combinatorial] + public void LoadPrimaryAndEditHVACDriverCompartmentOnly( + [Values(BusHVACSystemConfiguration.Configuration2)] BusHVACSystemConfiguration configuration) { + var stageInputFileName = "stageinput.xml"; + //Load Primary Vehicle VIF var newMultiStageJob = loadFile(primary_vehicle_only); - var vehicle = newMultiStageJob.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as DeclarationInterimStageBusVehicleViewModel_v2_8; + var vehicle = newMultiStageJob.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as InterimStageBusVehicleViewModel_v2_8; Assert.NotNull(vehicle); vehicle.Manufacturer = "test1"; vehicle.ManufacturerAddress = "testAddress2"; @@ -47,110 +54,110 @@ namespace Vecto3GUI2020Test - var manufacturingStage = - newMultiStageJob.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; + var manufacturingStage = newMultiStageJob.MultiStageJobViewModel.ManufacturingStageViewModel as ManufacturingStageViewModel_v0_1; - Assert.NotNull(manufacturingStage); + var auxVm = manufacturingStage.VehicleViewModel.MultistageAuxiliariesViewModel as MultistageAuxiliariesViewModel; - var fileName = primary_vehicle_only.Replace(".xml", "") + "_output.xml"; - deleteFile(fileName); - setMockDialogHelper(null, fileToSave: fileName); + auxVm.SystemConfiguration = BusHVACSystemConfiguration.Configuration2; + auxVm.HeatPumpTypeDriverCompartment = HeatPumpType.non_R_744_2_stage; + auxVm.HeatPumpModeDriverCompartment = (HeatPumpMode)auxVm.HeatPumpModeDriverCompartmentAllowedValues[0]; + + var multistageJob = newMultiStageJob.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; + multistageJob.ManufacturingStageViewModel.SaveInputDataExecute(GetFullPath(stageInputFileName)); + Assert.IsTrue(checkFileNameExists(stageInputFileName)); + - manufacturingStage.SaveInputDataAsCommand.Execute(null); - Assert.True(checkFileNameExists(fileName)); } + + + [Test] - public void loadPrimaryAndSave() + public void LoadPrimaryAndSaveVehicleData() { - //load file + //Load Primary Vehicle VIF var newMultiStageJob = loadFile(primary_vehicle_only); - var vehicle = newMultiStageJob.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as DeclarationInterimStageBusVehicleViewModel_v2_8; + var vehicle = newMultiStageJob.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as InterimStageBusVehicleViewModel_v2_8; + Assert.NotNull(vehicle); + vehicle.Manufacturer = "test1"; + vehicle.ManufacturerAddress = "testAddress2"; + vehicle.VIN = "VIN123456789"; - } + var multistageJobViewModel = + newMultiStageJob.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; + Assert.NotNull(multistageJobViewModel); + var fileName = primary_vehicle_only.Replace(".xml", "") + "_output.xml"; + + multistageJobViewModel.ManufacturingStageViewModel.SaveInputDataExecute(GetFullPath(fileName)); + Assert.True(checkFileNameExists(fileName)); + } - [Ignore("Validation is only performed with gui")] - [TestCase(primary_vehicle_only)] - [TestCase(consolidated_multiple_stages)] - [TestCase(consolidated_one_stage)] - public void SaveVehicleDataWithMissingFields(string fileName) + [Test] + public void LoadPrimaryAndSaveAsVif() { - var newMultistageJobViewModel = loadFile(fileName); - var manstage = newMultistageJobViewModel.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; - Assert.NotNull(manstage); + //load file + var newMultiStageJob = loadFile(primary_vehicle_only); + var vehicle = newMultiStageJob.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as InterimStageBusVehicleViewModel_v2_8; - var saveFileName = fileName.Replace(".xml", "") + "_output.xml"; - deleteFile(saveFileName); - _kernel.Rebind<IDialogHelper>().ToConstant(setMockDialogHelper(fileToSave: saveFileName).Object); - manstage.SaveInputDataAsCommand.Execute(null); + } - Assert.False(checkFileNameExists(saveFileName)); - } [Test] - public void reloadInputFile() + public void ReloadInputFile() { var newMultistageJobViewModel = loadFile(consolidated_multiple_stages_airdrag) as NewMultiStageJobViewModel; var vehicle = newMultistageJobViewModel.MultiStageJobViewModel.VehicleInputData as - DeclarationInterimStageBusVehicleViewModel_v2_8; + InterimStageBusVehicleViewModel_v2_8; Assert.NotNull(vehicle); Assert.True(vehicle.AirdragModifiedMultistageEditingEnabled); - var mockDialog = setMockDialogHelper(consolidated_multiple_stages_hev); - newMultistageJobViewModel.AddVifFile.Execute(null); - Assert.AreEqual(mockDialog.Object.OpenXMLFileDialog(null), newMultistageJobViewModel.VifPath); - vehicle = newMultistageJobViewModel.MultiStageJobViewModel.VehicleInputData as DeclarationInterimStageBusVehicleViewModel_v2_8; + newMultistageJobViewModel.AddVifFile(GetTestDataPath(consolidated_multiple_stages_hev)); + Assert.AreEqual(GetTestDataPath(consolidated_multiple_stages_hev), newMultistageJobViewModel.VifPath); + vehicle = newMultistageJobViewModel.MultiStageJobViewModel.VehicleInputData as InterimStageBusVehicleViewModel_v2_8; Assert.IsFalse(vehicle.AirdragModifiedMultistageEditingEnabled); - - } [Test] - public void loadInputFileMultipleStageAirdrag() + public void LoadInputFileMultipleStageAirdrag() { loadFile(consolidated_multiple_stages_airdrag); } + [Ignore("incomplete")] [Test] - public void loadAndSaveFullInputDataSample() + public void LoadAndSaveFullInputDataSample() { var vm = loadFile(primary_vehicle_only); var multiStageJobViewModel = vm.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; var fileToSave = "loadAndSaveFullInputDataTest.xml"; - var mockDialogHelper = setMockDialogHelper(stageInputFullSample, fileToSave); - multiStageJobViewModel.LoadVehicleDataCommand.Execute(null); + var mockDialogHelper = SetMockDialogHelper(stageInputFullSample, fileToSave); + multiStageJobViewModel.ManufacturingStageViewModel.LoadStageInputData(GetFullPath(stageInputFullSample)); + var manufacturingStageViewModel = multiStageJobViewModel.ManufacturingStageViewModel as ManufacturingStageViewModel_v0_1; var vehicleViewModel = - manufacturingStageViewModel.VehicleViewModel as DeclarationInterimStageBusVehicleViewModel_v2_8; + manufacturingStageViewModel.VehicleViewModel as InterimStageBusVehicleViewModel_v2_8; - vehicleViewModel.AirdragModifiedMultistage = true; - Assert.AreEqual(ConsumerTechnology.Electrically, vehicleViewModel.DoorDriveTechnology); - Assert.AreEqual(ConsumerTechnology.Electrically, vm.MultiStageJobViewModel.VehicleInputData.DoorDriveTechnology); - Assert.IsNotNull(multiStageJobViewModel.VehicleInputData.ManufacturerAddress); - var fileExists = checkFilePathExists(mockDialogHelper.Object.OpenXMLFileDialog()); - Assert.IsTrue(fileExists); - File.Delete(mockDialogHelper.Object.SaveToXMLDialog()); } @@ -158,7 +165,7 @@ namespace Vecto3GUI2020Test [Test] public void loadVehicleInputDataOnly() { - string inputPath = Path.Combine(DirPath, stageInputFullSample); + string inputPath = GetTestDataPath(stageInputFullSample); var inputDataReader = _kernel.Get<IXMLInputDataReader>(); var inputData = (IDeclarationInputDataProvider)inputDataReader.Create(inputPath); var vehicleInputData = inputData.JobInputData.Vehicle; @@ -191,33 +198,33 @@ namespace Vecto3GUI2020Test Assert.IsTrue(vehicleViewModel.VIN.IsNullOrEmpty()); Assert.IsNull(vehicleViewModel.Model); - var vehicleViewModel_v2_8 = vehicleViewModel as DeclarationInterimStageBusVehicleViewModel_v2_8; - Assert.NotNull(vehicleViewModel_v2_8); + var vehicleViewModelV28 = vehicleViewModel as InterimStageBusVehicleViewModel_v2_8; + Assert.NotNull(vehicleViewModelV28); - Assert.Null(vehicleViewModel_v2_8.HeightInMm); - Assert.Null(vehicleViewModel_v2_8.LengthInMm); - Assert.Null(vehicleViewModel_v2_8.WidthInMm); - Assert.Null(vehicleViewModel_v2_8.EntranceHeightInMm); + Assert.Null(vehicleViewModelV28.HeightInMm); + Assert.Null(vehicleViewModelV28.LengthInMm); + Assert.Null(vehicleViewModelV28.WidthInMm); + Assert.Null(vehicleViewModelV28.EntranceHeightInMm); - Assert.Null(vehicleViewModel_v2_8.ConsolidatedHeightInMm); - Assert.Null(vehicleViewModel_v2_8.ConsolidatedLengthInMm); - Assert.Null(vehicleViewModel_v2_8.ConsolidatedWidthInMm); - Assert.Null(vehicleViewModel_v2_8.ConsolidatedEntranceHeightInMm); + Assert.Null(vehicleViewModelV28.ConsolidatedHeightInMm); + Assert.Null(vehicleViewModelV28.ConsolidatedLengthInMm); + Assert.Null(vehicleViewModelV28.ConsolidatedWidthInMm); + Assert.Null(vehicleViewModelV28.ConsolidatedEntranceHeightInMm); - Assert.IsFalse(vehicleViewModel_v2_8.AirdragModifiedMultistageEditingEnabled); + Assert.IsFalse(vehicleViewModelV28.AirdragModifiedMultistageEditingEnabled); - Assert.IsNull(vehicleViewModel_v2_8.AirdragModifiedMultistage); - Assert.IsNull(vehicleViewModel_v2_8.ConsolidatedAirdragModifiedEnum); - Assert.IsTrue(vehicleViewModel_v2_8.AirdragModifiedEnum == AIRDRAGMODIFIED.UNKNOWN || vehicleViewModel_v2_8.AirdragModifiedEnum == null); + Assert.IsNull(vehicleViewModelV28.AirdragModifiedMultistage); + Assert.IsNull(vehicleViewModelV28.ConsolidatedAirdragModifiedEnum); + Assert.IsTrue(vehicleViewModelV28.AirdragModifiedEnum == AIRDRAGMODIFIED.UNKNOWN || vehicleViewModelV28.AirdragModifiedEnum == null); - Assert.AreEqual(vehicleViewModel_v2_8.AirdragModifiedMultistageEditingEnabled, false); + Assert.AreEqual(vehicleViewModelV28.AirdragModifiedMultistageEditingEnabled, false); - Assert.Null(vehicleViewModel_v2_8.BusAuxiliaries); + Assert.Null(vehicleViewModelV28.BusAuxiliaries); var vifInputData = vm.MultiStageJobViewModel as IMultistageVIFInputData; @@ -225,20 +232,26 @@ namespace Vecto3GUI2020Test Assert.Null(vifInputData.VehicleInputData.Components); } - [TestCase(consolidated_multiple_stages_airdrag, true)] - [TestCase(consolidated_multiple_stages, null)] - [TestCase(consolidated_one_stage, null)] - [TestCase(primary_vehicle_only, null)] - public void loadAirdragComponentAndSaveVehicleData(string fileName, object expectedAirdragModifiedValue) + + + + + + + [TestCase(consolidated_multiple_stages_airdrag, true, TestName="LoadAirdragComponentConsolidatedMultipleStages")] + [TestCase(consolidated_multiple_stages, null, TestName="LoadAirdragConsolidatedMultipleStage")] + [TestCase(consolidated_one_stage, null, TestName="LoadAirdragOneStage")] + [TestCase(primary_vehicle_only, null, TestName= "LoadAirdragPrimaryVehicle")] + public void LoadAirdragComponentAndSaveVehicleData(string fileName, object expectedAirdragModifiedValue) { var vm = loadFile(fileName); var vehicleVm = vm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as - DeclarationInterimStageBusVehicleViewModel_v2_8; + InterimStageBusVehicleViewModel_v2_8; - var airdragLoadResult = vehicleVm.MultistageAirdragViewModel.LoadAirdragFile(GetFullPath(airdragLoadTestFile)); + var airdragLoadResult = vehicleVm.MultistageAirdragViewModel.LoadAirdragFile(GetTestDataPath(airdragLoadTestFile)); Assert.IsTrue(airdragLoadResult, "Airdrag file not loaded"); @@ -251,11 +264,11 @@ namespace Vecto3GUI2020Test var fileToSave = "stageInput.xml"; - var mockDialogHelper = setMockDialogHelper(null, fileToSave: fileToSave); + var mockDialogHelper = SetMockDialogHelper(null, fileToSave: fileToSave); TestContext.Write("Saving file with loaded Airdrag Component ... "); var multistageJobViewModel = vm.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; - multistageJobViewModel.SaveInputDataAsCommand.Execute(null); + multistageJobViewModel.ManufacturingStageViewModel.SaveInputDataAsCommand.Execute(null); var savePath = mockDialogHelper.Object.SaveToXMLDialog(); Assert.IsTrue(File.Exists(savePath)); @@ -269,75 +282,39 @@ namespace Vecto3GUI2020Test Assert.AreEqual(expectedAirdragModifiedValue, vehicleVm.AirdragModifiedMultistage); - - - TestContext.WriteLine("Done!"); - File.Delete(savePath); - - - - } - - - - - - - [Test] - public void loadVehicleDataTest() + public void LoadVehicleDataTest() { TestContext.WriteLine($"Loading {consolidated_multiple_stages}"); - + //New Manufacturing Stage var newMultistageJobViewModel = loadFile(consolidated_multiple_stages); - - //var dialogMockConsolidatedMultipleStage = new Mock<IDialogHelper>(); - //dialogMockConsolidatedMultipleStage.Setup(dialogHelper => dialogHelper.OpenXMLFileDialog(It.IsAny<string>())).Returns(multiplestages); - //dialogMockConsolidatedMultipleStage.Setup(dialogHelper => dialogHelper.OpenXMLFileDialog()).Returns(multiplestages); - //_kernel.Rebind<IDialogHelper>().ToConstant(dialogMockConsolidatedMultipleStage.Object); - - - //var newMultistageJobViewModel = _kernel.Get<NewMultiStageJobViewModel>(); - //newMultistageJobViewModel.AddVifFile.Execute(null); Assert.NotNull(newMultistageJobViewModel.MultiStageJobViewModel); - var manstageVehicleViewModel = newMultistageJobViewModel.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as IMultistageVehicleViewModel; Assert.NotNull(manstageVehicleViewModel); - var auxiliariesViewModel = manstageVehicleViewModel.MultistageAuxiliariesViewModel; Assert.NotNull(auxiliariesViewModel); - var multiStageViewModel = newMultistageJobViewModel.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; Assert.NotNull(multiStageViewModel); - var manStageViewModel = multiStageViewModel.ManufacturingStageViewModel as ManufacturingStageViewModel_v0_1; - var vehicleInputData = "vecto_vehicle-stage_input_full-sample.xml"; - var mockDialogHelper = setMockDialogHelper(fileToLoad: vehicleInputData, fileToSave: null); - var vehicleInputDataFilePath = mockDialogHelper.Object.OpenXMLFileDialog(); + + //Load Stage InputData + var vehicleInputDataFilePath = GetTestDataPath(stageInputFullSample); TestContext.WriteLine($"Loading {vehicleInputDataFilePath}"); Assert.IsTrue(File.Exists(vehicleInputDataFilePath)); + manStageViewModel.LoadStageInputData(vehicleInputDataFilePath); - - - //var vehicleInputDataFiledialogMock = new Mock<IDialogHelper>(); - //vehicleInputDataFiledialogMock.Setup(dialogHelper => dialogHelper.OpenXMLFileDialog(It.IsAny<string>())).Returns(vehicleInputData); - //vehicleInputDataFiledialogMock.Setup(dialogHelper => dialogHelper.OpenXMLFileDialog()).Returns(vehicleInputData); - //_kernel.Rebind<IDialogHelper>().ToConstant(vehicleInputDataFiledialogMock.Object); - - multiStageViewModel.LoadVehicleDataCommand.Execute(null); - - var vehicleViewModel = manStageViewModel.VehicleViewModel as DeclarationInterimStageBusVehicleViewModel_v2_8; + var vehicleViewModel = manStageViewModel.VehicleViewModel as InterimStageBusVehicleViewModel_v2_8; Assert.NotNull(vehicleViewModel); //Assert.IsFalse(getMockDialogHelper().Verify); @@ -350,9 +327,9 @@ namespace Vecto3GUI2020Test Assert.AreEqual(LegislativeClass.M3, vehicleViewModel.LegislativeClass); Assert.AreEqual(500, vehicleViewModel.CurbMassChassis.Value());//CorrectedActualMass Assert.AreEqual(3500, vehicleViewModel.GrossVehicleMassRating.Value());//TechnicalPermissibleMaximumLadenMass - Assert.AreEqual(false, vehicleViewModel.AirdragModifiedMultistage); - Assert.AreEqual(AIRDRAGMODIFIED.FALSE, vehicleViewModel.AirdragModifiedEnum); - Assert.AreEqual(AIRDRAGMODIFIED.FALSE, vehicleViewModel.ParameterViewModels[nameof(vehicleViewModel.AirdragModifiedEnum)].CurrentContent); + Assert.AreEqual(true, vehicleViewModel.AirdragModifiedMultistage); + Assert.AreEqual(AIRDRAGMODIFIED.TRUE, vehicleViewModel.AirdragModifiedEnum); + Assert.AreEqual(AIRDRAGMODIFIED.TRUE, vehicleViewModel.ParameterViewModels[nameof(vehicleViewModel.AirdragModifiedEnum)].CurrentContent); Assert.AreEqual(TankSystem.Compressed, vehicleViewModel.TankSystem);//NgTankSystem Assert.AreEqual(RegistrationClass.II_III, vehicleViewModel.RegisteredClass);//ClassBus Assert.AreEqual(1, vehicleViewModel.NumberPassengerSeatsLowerDeck); @@ -382,7 +359,7 @@ namespace Vecto3GUI2020Test Assert.NotNull(airdrag.AirDragViewModel.XMLSource); - TestADASInput(vehicleViewModel); + TestAdasInput(vehicleViewModel); TestComponents(vehicleViewModel.Components); TestAirdragComponent(vehicleViewModel.Components.AirdragInputData); TestAuxiliariesComponent(vehicleViewModel.BusAuxiliaries); @@ -392,7 +369,7 @@ namespace Vecto3GUI2020Test } - private void TestADASInput(IVehicleDeclarationInputData vehicle) + private void TestAdasInput(IVehicleDeclarationInputData vehicle) { Assert.AreEqual(true, vehicle.ADAS.EngineStopStart); Assert.AreEqual(EcoRollType.None, vehicle.ADAS.EcoRoll); diff --git a/Vecto3GUI2020Test/ViewModelTests/MultistageAuxiliariesViewModelTests.cs b/Vecto3GUI2020Test/ViewModelTests/MultistageAuxiliariesViewModelTests.cs index 07c2f96cb70c838b6c2e0afb2353d3f83328556b..801e095995c191e606368b3edbac1dd74d623a13 100644 --- a/Vecto3GUI2020Test/ViewModelTests/MultistageAuxiliariesViewModelTests.cs +++ b/Vecto3GUI2020Test/ViewModelTests/MultistageAuxiliariesViewModelTests.cs @@ -9,11 +9,11 @@ using VECTO3GUI2020.ViewModel.MultiStage.Implementation; namespace Vecto3GUI2020Test.ViewModelTests { - [TestFixture] - public class MultistageAuxiliariesViewModelTests : ViewModelTestBase - { + [TestFixture] + public class MultistageAuxiliariesViewModelTests : ViewModelTestBase + { + - [Test] public void TestAllowedValuesHeatPumpModePassenger() @@ -33,18 +33,18 @@ namespace Vecto3GUI2020Test.ViewModelTests [Test] public void TestAllowedValuesHeatPumpModeDriver() - { + { var auxVm = new MultistageAuxiliariesViewModel(null); auxVm.HeatPumpTypeDriverCompartment = HeatPumpType.none; - Assert.IsTrue(auxVm.HeatPumpModeDriverCompartmentAllowedValues.Contains(HeatPumpMode.N_A)); - Assert.IsFalse(auxVm.HeatPumpModeDriverCompartmentAllowedValues.Contains(HeatPumpMode.cooling)); - Assert.IsFalse(auxVm.HeatPumpModeDriverCompartmentAllowedValues.Contains(HeatPumpMode.heating)); - Assert.IsFalse(auxVm.HeatPumpModeDriverCompartmentAllowedValues.Contains(HeatPumpMode.heating_and_cooling)); + Assert.IsTrue(auxVm.HeatPumpModeDriverCompartmentAllowedValues.Contains(HeatPumpMode.N_A)); + Assert.IsFalse(auxVm.HeatPumpModeDriverCompartmentAllowedValues.Contains(HeatPumpMode.cooling)); + Assert.IsFalse(auxVm.HeatPumpModeDriverCompartmentAllowedValues.Contains(HeatPumpMode.heating)); + Assert.IsFalse(auxVm.HeatPumpModeDriverCompartmentAllowedValues.Contains(HeatPumpMode.heating_and_cooling)); - auxVm.HeatPumpTypeDriverCompartment = HeatPumpType.R_744; - Assert.IsFalse(auxVm.HeatPumpModeDriverCompartmentAllowedValues.Contains(HeatPumpMode.N_A)); - } + auxVm.HeatPumpTypeDriverCompartment = HeatPumpType.R_744; + Assert.IsFalse(auxVm.HeatPumpModeDriverCompartmentAllowedValues.Contains(HeatPumpMode.N_A)); + } [Test] @@ -80,13 +80,45 @@ namespace Vecto3GUI2020Test.ViewModelTests Assert.AreEqual(HeatPumpMode.N_A, auxVm.HeatPumpModeDriverCompartment); Assert.AreEqual(HeatPumpMode.N_A, auxVm.ParameterViewModels[nameof(auxVm.HeatPumpModeDriverCompartment)].CurrentContent); - } + [Test] + public void TestPassengerHeatPumpConfigurations() + { + var auxVm = new MultistageAuxiliariesViewModel(null); + auxVm.HeatPumpGroupEditingEnabled = true; + + Assert.AreEqual(1, auxVm.HeatPumpConfigurationsPassenger.Count); + Assert.IsFalse(auxVm.RemovePassengerHeatpumpCommand.CanExecute(null)); + bool canExecuteChangedFired = false; + auxVm.RemovePassengerHeatpumpCommand.CanExecuteChanged += (sender, args) => { + canExecuteChangedFired = true; + }; + //Add another configuration + + auxVm.AddPassengerHeatpumpCommand.Execute(null); + Assert.AreEqual(2, auxVm.HeatPumpConfigurationsPassenger.Count); + Assert.IsTrue(canExecuteChangedFired, "Can Execute Changed Not Fired"); + canExecuteChangedFired = false; + Assert.IsTrue(auxVm.RemovePassengerHeatpumpCommand.CanExecute(null)); + + //Remove configuration + auxVm.RemovePassengerHeatpumpCommand.Execute(auxVm.HeatPumpConfigurationsPassenger.Last()); + Assert.AreEqual(1, auxVm.HeatPumpConfigurationsPassenger.Count); + Assert.IsTrue(canExecuteChangedFired); + Assert.IsFalse(auxVm.RemovePassengerHeatpumpCommand.CanExecute(null)); + + + + + + + + } } } diff --git a/Vecto3GUI2020Test/ViewModelTests/MultistageParameterViewModelTests.cs b/Vecto3GUI2020Test/ViewModelTests/MultistageParameterViewModelTests.cs deleted file mode 100644 index 7d75d07611250678ca960b4d7bfc859afb046ab1..0000000000000000000000000000000000000000 --- a/Vecto3GUI2020Test/ViewModelTests/MultistageParameterViewModelTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -using NUnit.Framework; -using VECTO3GUI2020.Annotations; - -namespace Vecto3GUI2020Test.ViewModelTests -{ - [TestFixture] - public class MultistageParameterViewModelTests - { - [Test] - public void EditingEnabledOnContentChanged() - { - - - } - - - - - } -} \ No newline at end of file diff --git a/Vecto3GUI2020Test/ViewModelTests/StageViewModelTests.cs b/Vecto3GUI2020Test/ViewModelTests/StageViewModelTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..3cf07d8a49a5447f99da09fba33e3595ba8d48f5 --- /dev/null +++ b/Vecto3GUI2020Test/ViewModelTests/StageViewModelTests.cs @@ -0,0 +1,51 @@ +using System.IO; +using System.Runtime.InteropServices; +using Ninject; +using NUnit.Framework; +using TUGraz.VectoCore.Configuration; +using VECTO3GUI2020.ViewModel.Implementation; +using VECTO3GUI2020.ViewModel.Interfaces; +using VECTO3GUI2020.ViewModel.Interfaces.Document; +using VECTO3GUI2020.ViewModel.Interfaces.JobEdit; +using VECTO3GUI2020.ViewModel.MultiStage.Implementation; +using VECTO3GUI2020.ViewModel.MultiStage.Interfaces; + +namespace Vecto3GUI2020Test.ViewModelTests +{ + [TestFixture] + public class StageViewModelTests : ViewModelTestBase + { + + + [TestCase(true, TestName="Exempted")] + [TestCase(false, TestName="NotExempted")] + public void updateFilePathsWhenSavedAs_non_exempted(bool exempted) + { + IMultiStageViewModelFactory vmFactory = _kernel.Get<IMultiStageViewModelFactory>(); + + var StageInput = vmFactory.GetStageInputViewModel(exempted) as StageInputViewModel; + var vehicleVm = StageInput.VehicleViewModel as InterimStageBusVehicleViewModel_v2_8; + vehicleVm.Manufacturer = "adsf"; + vehicleVm.ManufacturerAddress = "asdf 123"; + vehicleVm.VIN = "1234567890"; + + var fileName = TestHelper.GetMethodName() + ".xml"; + StageInput.SaveInputDataExecute(GetFullPath(fileName)); + Assert.True(checkFileNameExists(fileName)); + Assert.AreEqual(GetFullPath(fileName), StageInput.InputDataFilePath); + + //Check if title is updated + StringAssert.Contains(fileName, StageInput.Title); + + //Check datasource + Assert.NotNull(StageInput.DataSource); + + File.Delete(GetFullPath(fileName)); + } + + + + + + } +} \ No newline at end of file diff --git a/Vecto3GUI2020Test/ViewModelTests/TestExtensions.cs b/Vecto3GUI2020Test/ViewModelTests/TestExtensions.cs deleted file mode 100644 index fbfecc557a577226d4337272c181ed4d244963ab..0000000000000000000000000000000000000000 --- a/Vecto3GUI2020Test/ViewModelTests/TestExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Vecto3GUI2020Test.ViewModelTests -{ - internal class TestExtensions - { - - - } -} diff --git a/Vecto3GUI2020Test/ViewModelTests/VIFTests.cs b/Vecto3GUI2020Test/ViewModelTests/VIFTests.cs index 03af649bf3d27161e6d8ab4794dc7ee91c4a8161..868e5033e1c069ba3e144df4acc4cb3033c93d23 100644 --- a/Vecto3GUI2020Test/ViewModelTests/VIFTests.cs +++ b/Vecto3GUI2020Test/ViewModelTests/VIFTests.cs @@ -1,13 +1,20 @@ -using System.IO; +using System; +using System.IO; +using System.Linq; using System.Xml; using Moq; using Ninject; using NUnit.Framework; +using NUnit.Framework.Internal; using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.OutputData.FileIO; using TUGraz.VectoCore.Utils; using VECTO3GUI2020.Helper; - +using VECTO3GUI2020.ViewModel.Implementation; +using VECTO3GUI2020.ViewModel.Implementation.Common; +using VECTO3GUI2020.ViewModel.Interfaces; using VECTO3GUI2020.ViewModel.MultiStage.Implementation; namespace Vecto3GUI2020Test.ViewModelTests @@ -15,17 +22,19 @@ namespace Vecto3GUI2020Test.ViewModelTests public class VIFTests : ViewModelTestBase { + public const string _finalVifReport4 = "final.VIF_Report_4.xml"; + [Test] public void loadPrimaryVehicleOnlyAndCreateNewVIF() { - var multistagevm = loadFile(primary_vehicle_only).MultiStageJobViewModel; + var multistagevm = loadFile(primary_vehicle_only).MultiStageJobViewModel as MultiStageJobViewModel_v0_1; var stage = multistagevm.ManufacturingStageViewModel.StageCount; Assert.AreEqual(2, stage); - //Set Necessary Fields + //Set Mandatory Fields var vehicle = - multistagevm.ManufacturingStageViewModel.Vehicle as DeclarationInterimStageBusVehicleViewModel_v2_8; + multistagevm.ManufacturingStageViewModel.Vehicle as InterimStageBusVehicleViewModel_v2_8; vehicle.ManufacturerAddress = "Address"; vehicle.Manufacturer = "Manufacturer"; vehicle.VIN = "VIN12345678"; @@ -33,10 +42,10 @@ namespace Vecto3GUI2020Test.ViewModelTests var writer = GetFileOutputVIFWriter(multistagevm); deleteFile(writer.XMLMultistageReportFileName); - setMockDialogHelper(null, writer.XMLMultistageReportFileName); - _kernel.Rebind<IDialogHelper>().ToConstant(setMockDialogHelper(null, writer.XMLMultistageReportFileName).Object); + SetMockDialogHelper(null, writer.XMLMultistageReportFileName); + _kernel.Rebind<IDialogHelper>().ToConstant(SetMockDialogHelper(null, writer.XMLMultistageReportFileName).Object); - MultiStageJobViewModel_v0_1.SaveVif(multistagevm, writer); + multistagevm.SaveVif(multistagevm, writer); Assert.IsTrue(File.Exists(writer.XMLMultistageReportFileName)); @@ -44,16 +53,154 @@ namespace Vecto3GUI2020Test.ViewModelTests Assert.True(validator.ValidateXML(TUGraz.VectoCore.Utils.XmlDocumentType.MultistageOutputData)); } + [Test, Combinatorial] + public void CreateVifAllParameters( + [Values("manufacturer")] string manufacturer, + [Values(LegislativeClass.M3)] LegislativeClass legCategory) + { + var multistagevm = loadFile(primary_vehicle_only).MultiStageJobViewModel as MultiStageJobViewModel_v0_1; + var stage = multistagevm.ManufacturingStageViewModel.StageCount; - [Test] - public void TestAirdragLoadAndSave() + Assert.AreEqual(2, stage); + + //Set Necessary Fields + var vehicle = + multistagevm.ManufacturingStageViewModel.Vehicle as InterimStageBusVehicleViewModel_v2_8; + + + vehicle.ManufacturerAddress = "Address"; + vehicle.Manufacturer = "Manufacturer"; + vehicle.VIN = "VIN12345678"; + vehicle.Model = "Model"; + + + } + + [TestCase(true, 1, TestName="With Airdrag Component v1")] + [TestCase(true, 2, TestName="With Airdrag Component v2")] + [TestCase(false, 0, TestName="Without Airdrag Component")] + public void CreateCompletedFinalVIFWithAirdrag(bool loadAirdrag, int airdragVersion) { + var multistagevm = loadFile(_finalVifReport4); + + var VehicleViewModel = multistagevm.MultiStageJobViewModel.ManufacturingStageViewModel.VehicleViewModel as InterimStageBusVehicleViewModel_v2_8; + + VehicleViewModel.Manufacturer = "Manufacturer"; + VehicleViewModel.ManufacturerAddress = "Manufacturer Address"; + VehicleViewModel.VIN = "1234567"; + VehicleViewModel.Model = "asdf"; + VehicleViewModel.AirdragModifiedEnum = loadAirdrag ? AIRDRAGMODIFIED.TRUE: AIRDRAGMODIFIED.FALSE; + VehicleViewModel.VehicleDeclarationType = VehicleDeclarationType.final; + + //SETADAS + VehicleViewModel.EngineStopStartNullable = true; + VehicleViewModel.EcoRollTypeNullable = EcoRollType.WithEngineStop; + VehicleViewModel.PredictiveCruiseControlNullable = PredictiveCruiseControlType.Option_1_2_3; + VehicleViewModel.ATEcoRollReleaseLockupClutch = false; + + + if (loadAirdrag) { + var airdragTestFile = airdragVersion == 2 ? airdragLoadTestFilev2 : airdragLoadTestFile; + Assert.IsTrue(VehicleViewModel.MultistageAirdragViewModel.LoadAirdragFile(GetTestDataPath(airdragTestFile))); + } + + var resultFile = multistagevm.MultiStageJobViewModel.SaveVif(GetFullPath( + "completed_final" + ".xml")); + + var jobListVm = _kernel.Get<IJobListViewModel>(); + Assert.That(() => jobListVm.Jobs.Count, Is.EqualTo(2)); + + Assert.IsTrue(jobListVm.Jobs[1].CanBeSimulated, String.Join("\n",((AdditionalJobInfoViewModelMultiStage) jobListVm.Jobs[1].AdditionalJobInfoVm).InvalidEntries)); + } + + [Test] + public void CreateCompletedExemptedVif() + { + var multistagevm = loadFile(exempted_primary_vif).MultiStageJobViewModel as MultiStageJobViewModel_v0_1; + var jobListVm = _kernel.Get<IJobListViewModel>(); + + var vehicleVm = + multistagevm.ManufacturingStageViewModel.VehicleViewModel as InterimStageBusVehicleViewModel_v2_8; + + Assert.IsTrue(vehicleVm.ExemptedVehicle); + vehicleVm.Manufacturer = "Test Manufacturer 1"; + vehicleVm.ManufacturerAddress = "Address"; + vehicleVm.VIN = "123456789"; + vehicleVm.Model = "Model"; + vehicleVm.LegislativeClass = LegislativeClass.M3; + vehicleVm.CurbMassChassis = Kilogram.Create(20000); + vehicleVm.GrossVehicleMassRating = Kilogram.Create(20000); + vehicleVm.RegisteredClass = RegistrationClass.I_II; + vehicleVm.VehicleCode = VehicleCode.CC; + vehicleVm.LowEntry = true; + vehicleVm.Height = Meter.Create(2.6); + vehicleVm.NumberPassengerSeatsUpperDeck = 2; + vehicleVm.NumberPassengersStandingLowerDeck = 13; + vehicleVm.NumberPassengerSeatsLowerDeck = 10; + vehicleVm.NumberPassengersStandingUpperDeck = 12; + - setMockDialogHelper(consolidated_multiple_stages, null); - var newMultistageJobViewModel = _kernel.Get<NewMultiStageJobViewModel>(); - newMultistageJobViewModel.AddVifFile.Execute(null); + + var vifName = multistagevm.SaveVif(TestHelper.GetMethodName() + ".xml"); + + Assert.NotNull(vifName); + WriteLine($"Written to {vifName}"); + Assert.IsTrue(checkFileNameExists(vifName)); + + Assert.AreEqual(2, jobListVm.Jobs.Count); + + Assert.IsTrue(jobListVm.Jobs[1].CanBeSimulated, string.Join("\n",((AdditionalJobInfoViewModelMultiStage)jobListVm.Jobs[1].AdditionalJobInfoVm).InvalidEntries)); + } + + + [Test] + public void CreateIncompletedExemptedVif() + { + var multistagevm = loadFile(exempted_primary_vif).MultiStageJobViewModel as MultiStageJobViewModel_v0_1; + var jobListVm = _kernel.Get<IJobListViewModel>(); + + var vehicleVm = + multistagevm.ManufacturingStageViewModel.VehicleViewModel as InterimStageBusVehicleViewModel_v2_8; + + Assert.IsTrue(vehicleVm.ExemptedVehicle); + vehicleVm.Manufacturer = "Test Manufacturer 1"; + vehicleVm.ManufacturerAddress = "Address"; + vehicleVm.VIN = "123456789"; + vehicleVm.Model = "Model"; + //vehicleVm.LegislativeClass = LegislativeClass.M3; + vehicleVm.CurbMassChassis = Kilogram.Create(20000); + vehicleVm.GrossVehicleMassRating = Kilogram.Create(20000); + //vehicleVm.RegisteredClass = RegistrationClass.I_II; + vehicleVm.VehicleCode = VehicleCode.CC; + vehicleVm.LowEntry = true; + vehicleVm.Height = Meter.Create(2.6); + vehicleVm.NumberPassengerSeatsUpperDeck = 2; + vehicleVm.NumberPassengerSeatsLowerDeck = 10; + + + + + var vifName = multistagevm.SaveVif(TestHelper.GetMethodName() + ".xml"); + + Assert.NotNull(vifName); + WriteLine($"Written to {vifName}"); + Assert.IsTrue(checkFileNameExists(vifName)); + + Assert.AreEqual(2, jobListVm.Jobs.Count); + + Assert.IsFalse(jobListVm.Jobs[1].CanBeSimulated); + var invalidEntries = (jobListVm.Jobs[1].AdditionalJobInfoVm as AdditionalJobInfoViewModelMultiStage).InvalidEntries; + Assert.Contains(nameof(vehicleVm.LegislativeClass), invalidEntries); + Assert.Contains(nameof(vehicleVm.RegisteredClass), invalidEntries); + } + + + [Test] + public void TestAirdragLoadAndSave() + { + var newMultistageJobViewModel = loadFile(consolidated_multiple_stages); Assert.NotNull(newMultistageJobViewModel.MultiStageJobViewModel); var manstageVehicleViewModel = newMultistageJobViewModel.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as IMultistageVehicleViewModel; @@ -65,12 +212,12 @@ namespace Vecto3GUI2020Test.ViewModelTests var multiStageViewModel = newMultistageJobViewModel.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; Assert.NotNull(multiStageViewModel); - setMockDialogHelper(stageInputFullSample, null); + SetMockDialogHelper(stageInputFullSample, null); - multiStageViewModel.LoadVehicleDataCommand.Execute(null); + multiStageViewModel.ManufacturingStageViewModel.LoadStageInputData(GetTestDataPath(stageInputFullSample)); var vehicle = - multiStageViewModel.ManufacturingStageViewModel.Vehicle as DeclarationInterimStageBusVehicleViewModel_v2_8; + multiStageViewModel.ManufacturingStageViewModel.Vehicle as InterimStageBusVehicleViewModel_v2_8; vehicle.ManufacturerAddress = "Address"; vehicle.Manufacturer = "Manufacturer"; vehicle.VIN = "VIN12345678"; @@ -80,9 +227,9 @@ namespace Vecto3GUI2020Test.ViewModelTests var writer = GetFileOutputVIFWriter(multiStageViewModel); deleteFile(writer.XMLMultistageReportFileName); - setMockDialogHelper(null, writer.XMLMultistageReportFileName); + SetMockDialogHelper(null, writer.XMLMultistageReportFileName); - MultiStageJobViewModel_v0_1.SaveVif(multiStageViewModel, writer); + multiStageViewModel.SaveVif(multiStageViewModel, writer); var validator = new XMLValidator(XmlReader.Create(writer.XMLMultistageReportFileName)); Assert.True(validator.ValidateXML(TUGraz.VectoCore.Utils.XmlDocumentType.MultistageOutputData)); @@ -92,7 +239,7 @@ namespace Vecto3GUI2020Test.ViewModelTests private FileOutputVIFWriter GetFileOutputVIFWriter(IMultiStageJobViewModel multistageViewModel) { var outputFileName = primary_vehicle_only.Replace(".xml", "_vif_output_mandatory_fields.xml"); - var outputFilePath = Path.Combine(DirPath, outputFileName); + var outputFilePath = GetFullPath(outputFileName); var currentStageCount = multistageViewModel.MultistageJobInputData.JobInputData.ManufacturingStages?.Count ?? 0; return new FileOutputVIFWriter(outputFilePath, currentStageCount); diff --git a/Vecto3GUI2020Test/ViewModelTests/VehicleViewModelTests.cs b/Vecto3GUI2020Test/ViewModelTests/VehicleViewModelTests.cs index 7f5d3ef5692cb23875978161f14ebb06728a06db..c814654b61c4c8f0f4ca1794492140a01b3d6764 100644 --- a/Vecto3GUI2020Test/ViewModelTests/VehicleViewModelTests.cs +++ b/Vecto3GUI2020Test/ViewModelTests/VehicleViewModelTests.cs @@ -25,7 +25,7 @@ namespace Vecto3GUI2020Test.ViewModelTests var vm = loadFile(primary_vehicle_only); var vehicleVM = vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - DeclarationInterimStageBusVehicleViewModel_v2_8; + InterimStageBusVehicleViewModel_v2_8; var enteredString = "test"; var modelParam = vehicleVM.ParameterViewModels[nameof(vehicleVM.Model)]; //Null after loading @@ -77,7 +77,7 @@ namespace Vecto3GUI2020Test.ViewModelTests var vm = loadFile(primary_vehicle_only); var vehicleVM = vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - DeclarationInterimStageBusVehicleViewModel_v2_8; + InterimStageBusVehicleViewModel_v2_8; Assert.IsNull(vehicleVM.CurbMassChassis?.Value()); var curbMassParameter = vehicleVM.ParameterViewModels[nameof(vehicleVM.CurbMassChassis)]; @@ -105,67 +105,25 @@ namespace Vecto3GUI2020Test.ViewModelTests var vm = loadFile(primary_vehicle_only); var vehicleVM = vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - DeclarationInterimStageBusVehicleViewModel_v2_8; - setMockDialogHelper(stageInputFullSample); + InterimStageBusVehicleViewModel_v2_8; var vmConc = vm.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; - vmConc.LoadVehicleDataCommand.Execute(null); + vmConc.ManufacturingStageViewModel.LoadStageInputData(stageInputFullSample); Assert.IsFalse(vmConc.ManufacturingStageViewModel.VehicleViewModel.HasErrors); } - //[Test] - //public void groupEditing() - //{ - // var vm = loadFile(primary_vehicle_only); - // var vehicleVM = - // vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - // DeclarationInterimStageBusVehicleViewModel_v2_8; - - // vehicleVM.NumberOfPassengersUpperDeck = 2; - - // Assert.IsTrue(vehicleVM.NumberOfPassengersEditingEnabled); - // Assert.AreEqual(2, vehicleVM.NumberOfPassengersUpperDeck); - // vehicleVM.NumberOfPassengersLowerDeck = 3; - // Assert.AreEqual(3, vehicleVM.NumberOfPassengersLowerDeck); - //} - - - //[Test] - //public void automaticallyEnableEditingWhenContentIsSet() - //{ - // var vm = loadFile(primary_vehicle_only); - // var vehicleVM = - // vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - // DeclarationInterimStageBusVehicleViewModel_v2_8; - - - // vehicleVM.NumberOfPassengersUpperDeck = 2; - // Assert.IsTrue(vehicleVM.NumberOfPassengersEditingEnabled); - - // vehicleVM.NumberOfPassengersUpperDeck = null; - - // getMockDialogHelper(stageInputFullSample); - // var vmConc = vm.MultiStageJobViewModel as MultiStageJobViewModel_v0_1; - // vmConc.LoadVehicleDataCommand.Execute(null); - - - // Assert.IsTrue(vehicleVM.ParameterViewModels[nameof(vehicleVM.NumberOfPassengersUpperDeck)].EditingEnabled); - // Assert.IsTrue(vehicleVM.NumberOfPassengersEditingEnabled); - //} - - #region ADAS [Test] - public void loadPrimaryAndEdit() + public void LoadPrimaryAndEdit() { var vm = loadFile(primary_vehicle_only); Assert.NotNull(vm); var vehicleViewModel = vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as - DeclarationInterimStageBusVehicleViewModel_v2_8; + InterimStageBusVehicleViewModel_v2_8; var vehicleData = vm.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle; @@ -176,13 +134,6 @@ namespace Vecto3GUI2020Test.ViewModelTests Assert.Null(vehicleData.ADAS); } - - - - - - - #endregion diff --git a/Vecto3GUI2020Test/ViewModelTests/ViewModelTestBase.cs b/Vecto3GUI2020Test/ViewModelTests/ViewModelTestBase.cs index de58ab608a5806d62e56487de319ef3759104b57..b809717d78e15428000f42e6fda53fcab6301cab 100644 --- a/Vecto3GUI2020Test/ViewModelTests/ViewModelTestBase.cs +++ b/Vecto3GUI2020Test/ViewModelTests/ViewModelTestBase.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Runtime.CompilerServices; using System.Windows; using Moq; using Ninject; @@ -10,6 +11,7 @@ using TUGraz.VectoCore.InputData.FileIO.XML; using VECTO3GUI2020.Helper; using VECTO3GUI2020.Ninject; using VECTO3GUI2020.Ninject.Vehicle; +using VECTO3GUI2020.ViewModel.Interfaces; using VECTO3GUI2020.ViewModel.MultiStage.Implementation; using VECTO3GUI2020.ViewModel.MultiStage.Interfaces; @@ -17,31 +19,38 @@ namespace Vecto3GUI2020Test { public class ViewModelTestBase { - protected const string DirPath = @"Testdata\"; + protected string TestDataFullPath; + protected string SourceDirectoryRoot; + protected string prevDirectory; protected const string consolidated_multiple_stages = "vecto_multistage_consolidated_multiple_stages.xml"; - - protected const string consolidated_multiple_stages_airdrag = - "vecto_multistage_consolidated_multiple_stages_airdrag.xml"; - - protected const string consolidated_multiple_stages_hev = - "vecto_multistage_consolidated_multiple_stages_hev.xml"; - + protected const string consolidated_multiple_stages_airdrag = "vecto_multistage_consolidated_multiple_stages_airdrag.xml"; + protected const string consolidated_multiple_stages_hev = "vecto_multistage_consolidated_multiple_stages_hev.xml"; protected const string consolidated_one_stage = "vecto_multistage_consolidated_one_stage.xml"; protected const string primary_vehicle_only = "vecto_multistage_primary_vehicle_only.xml"; - - - + protected const string exempted_primary_vif = "exempted_primary_heavyBus.VIF.xml"; protected const string stageInputFullSample = "vecto_vehicle-stage_input_full-sample.xml"; - protected const string airdragLoadTestFile = "AirdragLoadTestFile.xml"; + protected const string airdragLoadTestFilev2 = "AirdragLoadTestFilev2.xml"; //protected IXMLInputDataReader xmlInputReader; protected IKernel _kernel; - private Mock<IDialogHelper> _mockDialogHelper = new Mock<IDialogHelper>(); + private Mock<IDialogHelper> _mockDialogHelper; + + + protected TestHelper _testHelper; + + [OneTimeSetUp] + public void OneTimeSetup() + { + prevDirectory = Environment.CurrentDirectory; + SourceDirectoryRoot = Directory.GetParent(prevDirectory).Parent.Parent.FullName; + TestDataFullPath = Path.Combine(SourceDirectoryRoot + "\\Testdata\\"); + } + [SetUp] - public void OneTimeSetUp() + public void SetUp() { _kernel = new StandardKernel( new VectoNinjectModule(), @@ -50,23 +59,79 @@ namespace Vecto3GUI2020Test new DocumentModule(), new XMLWriterFactoryModule(), new FactoryModule(), - new MultistageModule() + new MultistageModule(), + new Vecto3GUI2020Module() ); //xmlInputReader = _kernel.Get<IXMLInputDataReader>(); - _kernel.Rebind<IDialogHelper>().ToConstant(_mockDialogHelper.Object); + _kernel.Rebind<IDialogHelper>().ToConstant(SetMockDialogHelper().Object); + _kernel.Rebind<IWindowHelper>().ToConstant(GetMockWindowHelper()); + _testHelper = new TestHelper(_kernel.Get<IXMLInputDataReader>()); + + + SetOutputDirectory(); + } + + private void SetOutputDirectory() + { + + prevDirectory = Environment.CurrentDirectory; + SourceDirectoryRoot = Directory.GetParent(prevDirectory).Parent.Parent.FullName; + TestDataFullPath = Path.GetFullPath(@"Testdata\"); + + + var className = TestContext.CurrentContext.Test.ClassName.Replace("Vecto3GUI2020Test.", ""); + var testName = TestContext.CurrentContext.Test.Name; + var invalidPathChars = Path.GetInvalidPathChars(); + foreach (var invalidPathChar in invalidPathChars) { + testName = testName.Replace(invalidPathChar, '_'); + } + + var testOutputDirPath = Path.Combine(SourceDirectoryRoot + @"\Testdata\output\" + className + "\\" + testName); + + //Create output directory + + if (Directory.Exists(testOutputDirPath)) { + Directory.Delete(testOutputDirPath, true); + } + Directory.CreateDirectory(testOutputDirPath); + _kernel.Get<ISettingsViewModel>().DefaultOutputPath = testOutputDirPath; + Directory.SetCurrentDirectory(testOutputDirPath); + + //var currentContext = TestContext.CurrentContext; + + //var outputPath = Path.GetFullPath(TestDataDirPath + CurrentTestOutputPath); + //TestContext.CurrentContext.Test.Name = currentContext. + //var SettingsVm = _kernel.Get<ISettingsViewModel>(); + //SettingsVm.DefaultOutputPath = + } + + protected string GetFullPath(string fileName) + { + return Path.GetFullPath(fileName); + } + + private IWindowHelper GetMockWindowHelper() + { + Mock<IWindowHelper> mockWindowHelper = new Mock<IWindowHelper>(); + mockWindowHelper.Setup(windowHelper => windowHelper.ShowWindow(It.IsAny<object>())) + .Callback<object>((obj) => WriteLine($"Window containing {obj.GetType().ToString()} was opened")); + return mockWindowHelper.Object; } + [TearDown] public void TearDown() { _kernel.Dispose(); _kernel = null; + + Directory.SetCurrentDirectory(prevDirectory); } public bool checkFileNameExists(string fileName) { - var filePath = Path.GetFullPath(DirPath + fileName); + var filePath = Path.GetFullPath(fileName); return checkFilePathExists(filePath); } @@ -87,39 +152,38 @@ namespace Vecto3GUI2020Test public void deleteFile(string fileName) { - var filePath = Path.GetFullPath(DirPath + fileName); + var filePath = Path.GetFullPath(fileName); File.Delete(fileName); } - public NewMultiStageJobViewModel loadFile(string fileName) + public virtual NewMultiStageJobViewModel loadFile(string fileName) { - var mockDialogHelper = setMockDialogHelper(fileName); + var newMultistageJobViewModel = _kernel.Get<NewMultiStageJobViewModel>(); - newMultistageJobViewModel.AddVifFile.Execute(null); + var filePath = GetTestDataPath(fileName); + newMultistageJobViewModel.AddVifFile(filePath); + Assert.NotNull(newMultistageJobViewModel.MultiStageJobViewModel); - var manstageVehicleViewModel = newMultistageJobViewModel.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as DeclarationInterimStageBusVehicleViewModel_v2_8; + var manstageVehicleViewModel = newMultistageJobViewModel.MultiStageJobViewModel.ManufacturingStageViewModel.Vehicle as InterimStageBusVehicleViewModel_v2_8; Assert.NotNull(manstageVehicleViewModel); - var auxiliariesViewModel = manstageVehicleViewModel.MultistageAuxiliariesViewModel; - Assert.NotNull(auxiliariesViewModel); - - - - - var airdragViewModel = (manstageVehicleViewModel as DeclarationInterimStageBusVehicleViewModel_v2_8)?.MultistageAirdragViewModel; - Assert.NotNull(airdragViewModel); - - Assert.AreEqual(mockDialogHelper.Object.OpenXMLFileDialog(), newMultistageJobViewModel.VifPath); - + Assert.AreEqual(GetTestDataPath(fileName), newMultistageJobViewModel.VifPath); + if (!manstageVehicleViewModel.ExemptedVehicle) { + var auxiliariesViewModel = manstageVehicleViewModel.MultistageAuxiliariesViewModel; + Assert.NotNull(auxiliariesViewModel); + var airdragViewModel = (manstageVehicleViewModel as InterimStageBusVehicleViewModel_v2_8)?.MultistageAirdragViewModel; + Assert.NotNull(airdragViewModel); + } return newMultistageJobViewModel; } - protected Mock<IDialogHelper> setMockDialogHelper(string fileToLoad = null, string fileToSave = null) + + protected virtual Mock<IDialogHelper> SetMockDialogHelper(string fileToLoad = null, string fileToSave = null) { if (_mockDialogHelper == null) { _mockDialogHelper = new Mock<IDialogHelper>(); @@ -131,9 +195,26 @@ namespace Vecto3GUI2020Test (message, caption, button, image) => { TestContext.WriteLine($"{caption}\n {message}"); })); + + _mockDialogHelper.Setup(dialogHelper => + dialogHelper.ShowMessageBox(It.IsAny<string>(), It.IsAny<string>())) + .Callback<string, string>((message, caption) => + TestContext.WriteLine($"{{caption}}\n {message}")); + + _mockDialogHelper.Setup(dialogHelper => + dialogHelper.ShowErrorMessage(It.IsAny<string>(), It.IsAny<string>())) + .Callback<string, string>((message, caption) => + TestContext.WriteLine($"{{caption}}\n {message}")); + + _mockDialogHelper.Setup(dialogHelper => + dialogHelper.ShowErrorMessage(It.IsAny<string>())) + .Callback<string>((message) => + TestContext.WriteLine($"{{Error}}\n {message}")); + + } if (fileToLoad != null) { - var filePath = Path.GetFullPath(DirPath + fileToLoad); + var filePath = fileToLoad; Assert.NotNull(filePath); _mockDialogHelper.Setup(dialogHelper => dialogHelper.OpenXMLFileDialog(It.IsAny<string>())).Returns(filePath); @@ -143,7 +224,7 @@ namespace Vecto3GUI2020Test } if (fileToSave != null) { - var filePath = Path.GetFullPath(DirPath + fileToSave); + var filePath = fileToLoad; _mockDialogHelper.Setup(dialogHelper => dialogHelper.SaveToXMLDialog(It.IsAny<string>())).Returns(filePath); _mockDialogHelper.Setup(dialogHelper => @@ -156,16 +237,24 @@ namespace Vecto3GUI2020Test return _mockDialogHelper; } - protected Mock<IDialogHelper> getMockDialogHelper() + protected Mock<IDialogHelper> GetMockDialogHelper() { return _mockDialogHelper; } - protected string GetFullPath(string fileName) + protected virtual string GetTestDataPath(string fileName) { - var path = Path.GetFullPath(DirPath + fileName); - Debug.WriteLine(path); + var path = Path.Combine(TestDataFullPath + fileName); return path; } + + protected void Write(string outputMessage) + { + TestContext.Write(outputMessage); + } + protected void WriteLine(string outputMessage) + { + TestContext.WriteLine(outputMessage); + } } } \ No newline at end of file diff --git a/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs b/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs index 3c485c752f789e8e704a82246fd4bd72137779f8..7e845fd2d0ed03467a8317ba69566a46b3b1caab 100644 --- a/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs +++ b/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs @@ -96,8 +96,6 @@ namespace TUGraz.VectoCommon.InputData string VIN { get; } - string LegislativeCategory { get; } - LegislativeClass? LegislativeClass { get; } /// <summary> @@ -166,6 +164,9 @@ namespace TUGraz.VectoCommon.InputData Watt MaxNetPower2 { get; } + string ExemptedTechnology { get; } + + RegistrationClass? RegisteredClass { get; } int? NumberPassengerSeatsUpperDeck { get; } diff --git a/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs b/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs index 8bead1e34001aca34fcbae46b53fed09fe4df9d8..15c4dcc6a941aadd1fa44f8d1195cfebef793444 100644 --- a/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs +++ b/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs @@ -341,6 +341,11 @@ namespace TUGraz.VectoCommon.InputData Second ATLookAheadTime { get; } double[][] ShiftSpeedsTCToLocked { get; } + + double? PEV_TargetSpeedBrakeNorm { get; } + + double? PEV_DeRatingDownshiftSpeedFactor { get; } + double? PEV_DownshiftMinSpeedFactor { get; } } public interface ITorqueConverterEngineeringShiftParameterInputData diff --git a/VectoCommon/VectoCommon/InputData/IInputDataProvider.cs b/VectoCommon/VectoCommon/InputData/IInputDataProvider.cs index 176ec2e93ba6fba19938ca48a577bc2bf46c9d18..66e6a172bab78bd27aaa89d0dbbecbaf2c1e3677 100644 --- a/VectoCommon/VectoCommon/InputData/IInputDataProvider.cs +++ b/VectoCommon/VectoCommon/InputData/IInputDataProvider.cs @@ -88,6 +88,8 @@ namespace TUGraz.VectoCommon.InputData IVehicleDeclarationInputData CompletedVehicle { get; } } + + public interface IMultistageBusInputDataProvider : IDeclarationInputDataProvider { @@ -105,6 +107,8 @@ namespace TUGraz.VectoCommon.InputData VectoSimulationJobType JobType { get; } bool InputComplete { get; } + + IList<string> InvalidEntries { get; } } diff --git a/VectoCommon/VectoCommon/Models/IResponse.cs b/VectoCommon/VectoCommon/Models/IResponse.cs index 15984e37ff64f469a95d3031c59a3b431becf25d..ad0e0d1d5dafd24c4492303d86cc9d0f3dab5e0c 100644 --- a/VectoCommon/VectoCommon/Models/IResponse.cs +++ b/VectoCommon/VectoCommon/Models/IResponse.cs @@ -165,6 +165,10 @@ namespace TUGraz.VectoCommon.Models public NewtonMeter TorqueRequest { get; set; } public NewtonMeter InertiaTorque { get; set; } public PerSecond AvgDrivetrainSpeed { get; set; } + public NewtonMeter MaxDriveTorqueEM { get; set; } + public NewtonMeter MaxRecuperationTorqueEM { get; set; } + public NewtonMeter TorqueRequestEmMap { get; set; } + public bool DeRatingActive { get; set; } } diff --git a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONComponentInputData.cs b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONComponentInputData.cs index b81a8918294544b9e8c92466fb9aa0b310a680d5..fc5da5301d7ce9b49ee311c8298794836e71828a 100644 --- a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONComponentInputData.cs +++ b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONComponentInputData.cs @@ -183,8 +183,6 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON public string VIN => VehicleData.VIN; - public string LegislativeCategory => null; - public LegislativeClass? LegislativeClass => VehicleData.LegislativeClass; public VehicleCategory VehicleCategory => VehicleData.VehicleCategory; @@ -334,6 +332,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON public Watt MaxNetPower2 => null; + public string ExemptedTechnology => null; + public RegistrationClass? RegisteredClass => RegistrationClass.unknown; public int? NumberPassengerSeatsUpperDeck => 0; diff --git a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONGearboxData.cs b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONGearboxData.cs index fb3a8be89a1e7b24584fc390e86c7d889520c6ab..088fdba8cdc0d50797209aef35b52fac0fd3be6a 100644 --- a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONGearboxData.cs +++ b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONGearboxData.cs @@ -375,6 +375,9 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON public PerSecond MinEngineSpeedPostUpshift => null; public Second ATLookAheadTime => null; public double[][] ShiftSpeedsTCToLocked => null; + public double? PEV_TargetSpeedBrakeNorm => null; + public double? PEV_DeRatingDownshiftSpeedFactor => null; + public double? PEV_DownshiftMinSpeedFactor => null; public double? VeloictyDropFactor => null; diff --git a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONInputData.cs b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONInputData.cs index 07b7db4ab710862123b087c404253d0929d8a5cd..440d086f52ea48277b5a112e0864c22515c5a992 100644 --- a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONInputData.cs +++ b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONInputData.cs @@ -978,7 +978,7 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON var kernel = new StandardKernel(new VectoNinjectModule()); _xmlInputReader = kernel.Get<IXMLInputDataReader>(); - var primaryInputData = Path.Combine(BasePath, Body.GetEx<string>("PrimaryVehicle")); + var primaryInputData = Path.Combine(BasePath, Body.GetEx<string>(JsonKeys.PrimaryVehicle)); var completedInputData = Path.Combine(BasePath, Body.GetEx<string>("CompletedVehicle")); PrimaryVehicle = CreateReader(primaryInputData); @@ -1122,4 +1122,51 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON ? null : JSONInputDataFactory.ReadShiftParameters(Path.Combine(BasePath, Body.GetEx<string>("TCU")), false); } + + + public class JSONInputDataV10_PrimaryAndStageInputBus : JSONFile, IInputDataProvider + { + private readonly IXMLInputDataReader _xmlInputReader; + private string _primaryVehicleInputDataPath; + private IVehicleDeclarationInputData _primaryVehicleInputData; + public IVehicleDeclarationInputData PrimaryVehicle => + _primaryVehicleInputData ?? (_primaryVehicleInputData = + _xmlInputReader.CreateDeclaration(_primaryVehicleInputDataPath).JobInputData.Vehicle); + + private string _stageInputDataPath; + private IVehicleDeclarationInputData _stageInputData; + + public IVehicleDeclarationInputData StageInputData => + _stageInputData ?? (_stageInputData = + _xmlInputReader.CreateDeclaration(_stageInputDataPath).JobInputData.Vehicle); + + private bool? _completed; + + public bool? Completed + { + get => _completed; + set => _completed = value; + } + + + public JSONInputDataV10_PrimaryAndStageInputBus(JObject data, string filename, bool tolerateMissing = false) : + base(data, filename, tolerateMissing) + { + var kernel = new StandardKernel(new VectoNinjectModule()); + _xmlInputReader = kernel.Get<IXMLInputDataReader>(); + + + _primaryVehicleInputDataPath = Body.GetEx<string>(JsonKeys.PrimaryVehicle); + _stageInputDataPath = Body.GetEx<string>(JsonKeys.InterimStage); + _completed = Body.GetValueOrDefault<bool>(JsonKeys.Completed); + + } + + private void checkFileExtension(string path) + { + if (Path.GetExtension(path) != ".xml") { + throw new VectoException("unsupported vehicle file format {0}", path); + } + } + } } diff --git a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONInputDataFactory.cs b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONInputDataFactory.cs index 075fe71dfeb1469afd34c3c1726f467cf96e1901..22aa7ac6ff894735318ee306296bf9c26b8fc87c 100644 --- a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONInputDataFactory.cs +++ b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONInputDataFactory.cs @@ -101,6 +101,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON return new JSONInputDataV8_Hybrid(json, filename, tolerateMissing); case 9: return new JSONInputDataV9_BEV(json, filename, tolerateMissing); + case 10: + return new JSONInputDataV10_PrimaryAndStageInputBus(json, filename, tolerateMissing); default: throw new VectoException("Job-File: Unsupported FileVersion. Got: {0} ", version); } diff --git a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs index 7339282b3a2313174cd02a63b0d3bdd938108f5e..29ff6cda9aeb3b6daf8122d743f8bce72ee6d87f 100644 --- a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs +++ b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs @@ -253,6 +253,42 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON } } + public double? PEV_TargetSpeedBrakeNorm + { + get + { + if (Body["PEV_TargetSpeedBrakeNorm"] != null) { + return Body.GetEx<double>("PEV_TargetSpeedBrakeNorm"); + } + + return null; + } + } + + public double? PEV_DeRatingDownshiftSpeedFactor + { + get + { + if (Body["PEV_DeRatingDownshiftSpeedFactor"] != null) { + return Body.GetEx<double>("PEV_DeRatingDownshiftSpeedFactor"); + } + + return null; + } + } + + public double? PEV_DownshiftMinSpeedFactor + { + get + { + if (Body["PEV_DownshiftMinSpeedFactor"] != null) { + return Body.GetEx<double>("PEV_DownshiftMinSpeedFactor"); + } + + return null; + } + } + public TableData LoadStageShiftLines { get { diff --git a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONVehicleData.cs b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONVehicleData.cs index e99c766fe29ccc20d7e20d632c27b3ee0fd45cd0..fbbca0739dbd1ab14e456a02f36d3c3a46aeab2e 100644 --- a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONVehicleData.cs +++ b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONVehicleData.cs @@ -237,8 +237,6 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON public virtual string VIN => Constants.NOT_AVAILABLE; - public string LegislativeCategory => null; - public virtual LegislativeClass? LegislativeClass => Body["LegislativeClass"]?.Value<string>().ParseEnum<LegislativeClass>() ?? VectoCommon.Models.LegislativeClass.Unknown; @@ -437,6 +435,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON public virtual Watt MaxNetPower2 => null; + public virtual string ExemptedTechnology => null; + public virtual RegistrationClass? RegisteredClass => RegistrationClass.unknown; public virtual int? NumberPassengerSeatsUpperDeck => 0; diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationJobInputDataProvider.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationJobInputDataProvider.cs index 70fc89dbd810ffa829806576728efff7599a12cb..119c1e6dc82479ad25437bfdda817dbd215ac9e0 100644 --- a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationJobInputDataProvider.cs +++ b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationJobInputDataProvider.cs @@ -133,5 +133,18 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider public IXMLPrimaryVehicleBusInputData InputData { get; } } + // --------------------------------------------------------------------------------------- + + public class XMLDeclarationMultistageExemptedPrimaryVehicleBusJobInputDataProviderV01 : + XMLDeclarationMultistagePrimaryVehicleBusJobInputDataProviderV01 + { + public new static readonly XNamespace NAMESPACE_URI = XMLDefinitions.DECLARATION_MULTISTAGE_BUS_VEHICLE_NAMESPACE_VO1; + + public new const string XSD_TYPE = "VehicleExemptedPrimaryBusType"; + public new static readonly string QUALIFIED_XSD_TYPE = XMLHelper.CombineNamespace(NAMESPACE_URI.NamespaceName, XSD_TYPE); + + + public XMLDeclarationMultistageExemptedPrimaryVehicleBusJobInputDataProviderV01(XmlNode node, IXMLPrimaryVehicleBusInputData inputProvider, string fileName) : base(node, inputProvider, fileName) { } + } } diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationMultistageInputData.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationMultistageInputData.cs index 225b6dfb808a01eb7d6746dd6546280c2099f80c..e65ddef508ad1f130fa9d3a3b00ecb82d12257c0 100644 --- a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationMultistageInputData.cs +++ b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationMultistageInputData.cs @@ -88,6 +88,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider public bool InputComplete => Reader.InputComplete; + public IList<string> InvalidEntries => Reader.InvalidEntries; + public IXMLMultistageJobReader Reader { protected get; set; } public IXMLMultistageInputDataProvider InputData { get; } @@ -120,6 +122,9 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider public XMLDeclarationMultistagePrimaryVehicleInputDataV01(XmlNode xmlNode, string fileName) : base(xmlNode, fileName) { + //var h = VectoHash.Load(xmlNode); + //XMLHash = h.ComputeXmlHash(); + _signatureNode = xmlNode.LastChild; } diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationVehicleDataProvider.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationVehicleDataProvider.cs index bd4cae6aa3bef4d0cedd06b3bde098773649524c..a8d5dbf9f7d60634e2bad6a4dd40f40d2158370a 100644 --- a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationVehicleDataProvider.cs +++ b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/DataProvider/XMLDeclarationVehicleDataProvider.cs @@ -108,9 +108,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider public virtual string VIN => GetString(XMLNames.Vehicle_VIN); - public virtual string LegislativeCategory => null; - public virtual LegislativeClass? LegislativeClass => GetString(XMLNames.Vehicle_LegislativeClass).ParseEnum<LegislativeClass>(); + //get { return GetString("LegislativeCategory").ParseEnum<LegislativeClass>(); } public virtual VehicleCategory VehicleCategory { @@ -128,6 +127,7 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider public virtual Kilogram GrossVehicleMassRating => GetDouble(XMLNames.Vehicle_GrossVehicleMass).SI<Kilogram>(); + //get { return GetDouble(XMLNames.Vehicle_TPMLM).SI<Kilogram>(); } public virtual IList<ITorqueLimitInputData> TorqueLimits { @@ -206,6 +206,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider ? GetDouble(XMLNames.Vehicle_MaxNetPower2).SI<Watt>() : null; + public virtual string ExemptedTechnology => null; + public virtual RegistrationClass? RegisteredClass => RegistrationClass.unknown; public virtual int? NumberPassengerSeatsUpperDeck => 0; @@ -478,6 +480,123 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider #endregion } + public class XMLDeclarationExemptedPrimaryBusDataProviderV26 : XMLDeclarationVehicleDataProviderV20 + { + public new static readonly XNamespace NAMESPACE_URI = XMLDefinitions.DECLARATION_DEFINITIONS_NAMESPACE_URI_V26; + + public new const string XSD_TYPE = "ExemptedPrimaryHeavyBusType"; + + public new static readonly string QUALIFIED_XSD_TYPE = + XMLHelper.CombineNamespace(NAMESPACE_URI.NamespaceName, XSD_TYPE); + + public XMLDeclarationExemptedPrimaryBusDataProviderV26( + IXMLDeclarationJobInputData jobData, XmlNode xmlNode, string sourceFile) : base(jobData, xmlNode, sourceFile) + { + SourceType = DataSourceType.XMLEmbedded; + + } + + #region Overrides of AbstractXMLResource + + protected override XNamespace SchemaNamespace { + get { return NAMESPACE_URI; } + } + + protected override DataSourceType SourceType { get; } + + #endregion + + public override VehicleCategory VehicleCategory { + get { return VehicleCategory.HeavyBusPrimaryVehicle; } + } + + public override bool ExemptedVehicle { + get { return true; } + } + + + public override IList<ITorqueLimitInputData> TorqueLimits { + get { return new List<ITorqueLimitInputData>(); } + } + + public override PerSecond EngineIdleSpeed { + get { return null; } + } + + public override bool VocationalVehicle { + get { return false; } + } + + public override bool SleeperCab { + get { return false; } + } + + public override TankSystem? TankSystem { + get { return null; } + } + + public override IAdvancedDriverAssistantSystemDeclarationInputData ADAS { + get { return null; } + } + + public override bool ZeroEmissionVehicle { + get { return XmlConvert.ToBoolean(GetString(XMLNames.Vehicle_ZeroEmissionVehicle)); } + } + + public override bool HybridElectricHDV { + get { return false; } + } + + public override bool DualFuelVehicle { + get { return false; } + } + + public override Watt MaxNetPower1 { + get { return GetDouble("SumNetPower").SI<Watt>(); } + } + + public override Watt MaxNetPower2 { + get { return null; } + } + + public override string ExemptedTechnology + { + get { return GetString("Technology"); } + } + + public override IVehicleComponentsDeclaration Components { + get { return null; } + } + + public override XmlElement ComponentNode { + get { return null; } + } + + public override XmlElement PTONode { + get { return null; } + } + + public override XmlElement ADASNode { + get { return null; } + } + + public override AngledriveType AngledriveType { + get { return AngledriveType.None; } + } + + public override RetarderType RetarderType { + get { return RetarderType.None; } + } + + public override double RetarderRatio { + get { return 0; } + } + + public override IPTOTransmissionInputData PTOTransmissionInputData { + get { return null; } + } + } + public class XMLDeclarationMediumLorryVehicleDataProviderV26 : XMLDeclarationVehicleDataProviderV21 { public new static readonly XNamespace NAMESPACE_URI = XMLDefinitions.DECLARATION_DEFINITIONS_NAMESPACE_URI_V26; @@ -523,6 +642,28 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider protected override DataSourceType SourceType { get; } #endregion + + public override XmlElement ComponentNode { + get { return null; } + } + + + public override XmlElement ADASNode { + get { return null; } + } + + public override AngledriveType AngledriveType { + get { return AngledriveType.None; } + } + + public override RetarderType RetarderType { + get { return RetarderType.None; } + } + + public override double RetarderRatio { + get { return 0; } + } + } public class XMLDeclarationCompletedBusDataProviderV26 : XMLDeclarationVehicleDataProviderV20 @@ -639,36 +780,44 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider public string VIN => GetString(XMLNames.Vehicle_VIN); - public string LegislativeCategory => GetString(XMLNames.Bus_LegislativeCategory); + public virtual LegislativeClass? LegislativeClass + { + get { return GetString(XMLNames.Bus_LegislativeCategory)?.ParseEnum<LegislativeClass>(); } + } - public VehicleCategory VehicleCategory => VehicleCategoryHelper.Parse(GetString("ChassisConfiguration")); + public virtual VehicleCategory VehicleCategory => VehicleCategoryHelper.Parse(GetString("ChassisConfiguration")); - public AxleConfiguration AxleConfiguration => AxleConfigurationHelper.Parse(GetString(XMLNames.Vehicle_AxleConfiguration)); + public virtual AxleConfiguration AxleConfiguration => AxleConfigurationHelper.Parse(GetString(XMLNames.Vehicle_AxleConfiguration)); //TechnicalPermissibleMaximumLadenMass - public Kilogram GrossVehicleMassRating => GetDouble(XMLNames.TPMLM).SI<Kilogram>(); + public virtual Kilogram GrossVehicleMassRating => GetDouble(XMLNames.TPMLM).SI<Kilogram>(); //IdlingSpeed - public PerSecond EngineIdleSpeed => GetDouble(XMLNames.Engine_IdlingSpeed).RPMtoRad(); + public virtual PerSecond EngineIdleSpeed => GetDouble(XMLNames.Engine_IdlingSpeed).RPMtoRad(); - public RetarderType RetarderType => GetString(XMLNames.Vehicle_RetarderType).ParseEnum<RetarderType>(); + + public virtual RetarderType RetarderType => GetString(XMLNames.Vehicle_RetarderType).ParseEnum<RetarderType>(); - public double RetarderRatio => GetDouble(XMLNames.Vehicle_RetarderRatio); + public virtual double RetarderRatio => GetDouble(XMLNames.Vehicle_RetarderRatio); - public AngledriveType AngledriveType => GetString(XMLNames.Vehicle_AngledriveType).ParseEnum<AngledriveType>(); + + public virtual AngledriveType AngledriveType => GetString(XMLNames.Vehicle_AngledriveType).ParseEnum<AngledriveType>(); - public bool ZeroEmissionVehicle => GetBool(XMLNames.Vehicle_ZeroEmissionVehicle); + + public virtual bool ZeroEmissionVehicle => GetBool(XMLNames.Vehicle_ZeroEmissionVehicle); - public XmlElement ADASNode => _adasNode ?? (_adasNode = GetNode(XMLNames.Vehicle_ADAS, required: false) as XmlElement); + + public virtual XmlElement ADASNode => _adasNode ?? (_adasNode = GetNode(XMLNames.Vehicle_ADAS, required: false) as XmlElement); - public IXMLADASReader ADASReader { get; set; } + public virtual IXMLADASReader ADASReader { get; set; } - public IAdvancedDriverAssistantSystemDeclarationInputData ADAS => _adas ?? (_adas = ADASReader.ADASInputData); + + public virtual IAdvancedDriverAssistantSystemDeclarationInputData ADAS => _adas ?? (_adas = ADASReader.ADASInputData); - public IList<ITorqueLimitInputData> TorqueLimits => ReadTorqueLimits(); + public virtual IList<ITorqueLimitInputData> TorqueLimits => ReadTorqueLimits(); - public XmlElement ComponentNode + public virtual XmlElement ComponentNode { get { @@ -681,23 +830,22 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider } } - public IXMLComponentReader ComponentReader { get; set; } + public virtual IXMLComponentReader ComponentReader { get; set; } - public Meter EntranceHeight { get; } + public virtual Meter EntranceHeight { get; } public virtual ConsumerTechnology? DoorDriveTechnology => ConsumerTechnology.Unknown; public virtual VehicleDeclarationType VehicleDeclarationType { get; } - public IVehicleComponentsDeclaration Components => _components ?? (_components = ComponentReader.ComponentInputData); + public virtual IVehicleComponentsDeclaration Components => _components ?? (_components = ComponentReader.ComponentInputData); #region Non seeded Properties public string Identifier { get; } - public bool ExemptedVehicle { get; } - public LegislativeClass? LegislativeClass { get; } + public virtual bool ExemptedVehicle { get; } public int? NumberPassengerSeatsUpperDeck { get; } public int? NumberPassengerSeatsLowerDeck { get; } public int? NumberPassengersStandingLowerDeck { get; } @@ -712,8 +860,9 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider public bool HybridElectricHDV { get; } public bool DualFuelVehicle { get; } - public Watt MaxNetPower1 { get; } + public virtual Watt MaxNetPower1 { get; } public Watt MaxNetPower2 { get; } + public virtual string ExemptedTechnology { get; } public RegistrationClass? RegisteredClass { get; } public VehicleCode? VehicleCode { get; } public bool? LowEntry { get; } @@ -761,7 +910,41 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider } } + // --------------------------------------------------------------------------------------- + + public class XMLDeclarationMultistageExemptedPrimaryVehicleBusDataProviderV01 : XMLDeclarationMultistagePrimaryVehicleBusDataProviderV01 + { + + public new static readonly XNamespace NAMESPACE_URI = XMLDefinitions.DECLARATION_MULTISTAGE_BUS_VEHICLE_NAMESPACE_VO1; + + public new const string XSD_TYPE = "VehicleExemptedPrimaryBusType"; + public new static readonly string QUALIFIED_XSD_TYPE = + XMLHelper.CombineNamespace(NAMESPACE_URI.NamespaceName, XSD_TYPE); + + public XMLDeclarationMultistageExemptedPrimaryVehicleBusDataProviderV01(IXMLPrimaryVehicleBusJobInputData busJobData, XmlNode xmlNode, string sourceFile) : base(busJobData, xmlNode, sourceFile) { } + + #region Overrides of XMLDeclarationMultistagePrimaryVehicleBusDataProviderV01 + + public override XmlElement ComponentNode + { + get { return null; } + } + + public override IVehicleComponentsDeclaration Components + { + get { return null; } + } + + public override bool ExemptedVehicle { get { return true; } } + + public override Watt MaxNetPower1 + { + get { return GetDouble("SumNetPower").SI<Watt>(); } + } + + #endregion + } // --------------------------------------------------------------------------------------- @@ -782,7 +965,10 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider { get { - return ElementExists(new [] {XMLNames.Component_Vehicle, XMLNames.Component_Model}) + if (BaseNode.LocalName == XMLNames.Component_Vehicle) { + return BaseNode.SelectSingleNode($"./*[local-name()='{XMLNames.Component_Model}']")?.InnerText; + } + return ElementExists(new [] { XMLNames.Component_Vehicle, XMLNames.Component_Model}) ? GetString(new[] { XMLNames.Component_Vehicle, XMLNames.Component_Model }) : null; } } @@ -1001,9 +1187,9 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider { get { - if (!ElementExists(XMLNames.Bus_NumberPassengersLowerDeck)) + if (!ElementExists(XMLNames.Bus_NumberPassengerSeatsLowerDeck)) return null; - var node = GetNode(XMLNames.Bus_NumberPassengersLowerDeck); + var node = GetNode(XMLNames.Bus_NumberPassengerSeatsLowerDeck); return XmlConvert.ToInt32(node.InnerText); } } @@ -1012,13 +1198,37 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider { get { - if (!ElementExists(XMLNames.Bus_NumberPassengersUpperDeck)) + if (!ElementExists(XMLNames.Bus_NumberPassengerSeatsUpperDeck)) return null; - var node = GetNode(XMLNames.Bus_NumberPassengersUpperDeck); + var node = GetNode(XMLNames.Bus_NumberPassengerSeatsUpperDeck); return XmlConvert.ToInt32(node.InnerText); } } + + public override int? NumberPassengersStandingLowerDeck + { + get + { + if (!ElementExists(XMLNames.Bus_NumberPassengersStandingLowerDeck)) + return null; + var node = GetNode(XMLNames.Bus_NumberPassengersStandingLowerDeck); + return XmlConvert.ToInt32(node.InnerText); + } + } + + public override int? NumberPassengersStandingUpperDeck + { + get + { + if (!ElementExists(XMLNames.Bus_NumberPassengersStandingUpperDeck)) + return null; + var node = GetNode(XMLNames.Bus_NumberPassengersStandingUpperDeck); + return XmlConvert.ToInt32(node.InnerText); + } + } + + public override VehicleCode? VehicleCode => ElementExists(XMLNames.Vehicle_BodyworkCode) ? GetString(XMLNames.Vehicle_BodyworkCode).ParseEnum<VehicleCode>() @@ -1039,6 +1249,9 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.DataProvider public override XmlElement ComponentNode => null; public override IVehicleComponentsDeclaration Components => null; + + + public override bool ExemptedVehicle => true; #region Overrides of AbstractXMLResource diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/IXMLDeclarationInputDataReader.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/IXMLDeclarationInputDataReader.cs index 60c24aeed47d0d135d3ee999a171021251685a44..7a2edd40e6f1d2fd25b3bef846cdd52951d5722d 100644 --- a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/IXMLDeclarationInputDataReader.cs +++ b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/IXMLDeclarationInputDataReader.cs @@ -65,6 +65,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration VectoSimulationJobType JobType { get; } bool InputComplete { get; } + + IList<string> InvalidEntries { get; } } public interface IXMLMultistageReader diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/NinjectModules/XMLDeclarationInputDataMultistageV01InjectModule.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/NinjectModules/XMLDeclarationInputDataMultistageV01InjectModule.cs index 1f50d3e2cf3f36e5ae92825eaa0da7f33a38fcf7..8f61766998e747ae0ca2b542dbf3a8f650fe4b6e 100644 --- a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/NinjectModules/XMLDeclarationInputDataMultistageV01InjectModule.cs +++ b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/NinjectModules/XMLDeclarationInputDataMultistageV01InjectModule.cs @@ -39,14 +39,20 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.NinjectModules Bind<IXMLPrimaryVehicleBusJobInputData>().To<XMLDeclarationMultistagePrimaryVehicleBusJobInputDataProviderV01>() .Named(XMLDeclarationMultistagePrimaryVehicleBusJobInputDataProviderV01.QUALIFIED_XSD_TYPE); + Bind<IXMLPrimaryVehicleBusJobInputData>().To<XMLDeclarationMultistageExemptedPrimaryVehicleBusJobInputDataProviderV01>() + .Named(XMLDeclarationMultistageExemptedPrimaryVehicleBusJobInputDataProviderV01.QUALIFIED_XSD_TYPE); - Bind<IXMLJobDataReader>().To<XMLJobDataMultistagePrimaryVehicleReaderV01>() + Bind<IXMLJobDataReader>().To<XMLJobDataMultistagePrimaryVehicleReaderV01>() .Named(XMLJobDataMultistagePrimaryVehicleReaderV01.QUALIFIED_XSD_TYPE); + Bind<IXMLJobDataReader>().To<XMLJobDataMultistageExemptedPrimaryVehicleReaderV01>() + .Named(XMLJobDataMultistageExemptedPrimaryVehicleReaderV01.QUALIFIED_XSD_TYPE); + Bind<IXMLDeclarationVehicleData>().To<XMLDeclarationMultistagePrimaryVehicleBusDataProviderV01>() .Named(XMLDeclarationMultistagePrimaryVehicleBusDataProviderV01.QUALIFIED_XSD_TYPE); - + Bind<IXMLDeclarationVehicleData>().To<XMLDeclarationMultistageExemptedPrimaryVehicleBusDataProviderV01>() + .Named(XMLDeclarationMultistageExemptedPrimaryVehicleBusDataProviderV01.QUALIFIED_XSD_TYPE); // ----------------------------------- Bind<IXMLComponentReader>().To<XMLMultistagePrimaryVehicleBusComponentReaderV01>() diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/NinjectModules/XMLDeclarationInputDataV26InjectModule.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/NinjectModules/XMLDeclarationInputDataV26InjectModule.cs index d2a946a414c4cdb9f521cf0bb662b866d5d027a3..ab7b6e506f1d8f1e309a108317c953ea8937663d 100644 --- a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/NinjectModules/XMLDeclarationInputDataV26InjectModule.cs +++ b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/NinjectModules/XMLDeclarationInputDataV26InjectModule.cs @@ -18,6 +18,9 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.NinjectModules { Bind<IXMLDeclarationVehicleData>().To<XMLDeclarationCompletedBusDataProviderV26>() .Named(XMLDeclarationCompletedBusDataProviderV26.QUALIFIED_XSD_TYPE); + Bind<IXMLDeclarationVehicleData>().To<XMLDeclarationExemptedPrimaryBusDataProviderV26>() + .Named(XMLDeclarationExemptedPrimaryBusDataProviderV26.QUALIFIED_XSD_TYPE); + Bind<IXMLVehicleComponentsDeclaration>().To<XMLDeclarationPrimaryBusComponentsDataProviderV26>() .Named(XMLDeclarationPrimaryBusComponentsDataProviderV26.QUALIFIED_XSD_TYPE); diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/Reader/Impl/XMLDeclarationMultistageInputReader.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/Reader/Impl/XMLDeclarationMultistageInputReader.cs index cea6b6469d69043bef63ad7cdb295b9bbb45c04d..0703208a179bdb24011e2c15d31997182b34f193 100644 --- a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/Reader/Impl/XMLDeclarationMultistageInputReader.cs +++ b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/Reader/Impl/XMLDeclarationMultistageInputReader.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Xml; using System.Xml.Linq; @@ -13,6 +14,7 @@ using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Factory; using TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Interfaces; using TUGraz.VectoCore.OutputData.XML; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.VehicleInformationFile; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl @@ -67,6 +69,7 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl protected IPrimaryVehicleInformationInputDataProvider _primaryVehicle; protected IList<IManufacturingStageInputData> _manufacturingStages; protected ConsolidateManufacturingStages _consolidateManufacturingStages; + private IList<string> _invalidEntries = new List<string>(); private XmlNodeList _manufacturingNodeStages; @@ -140,8 +143,10 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl { get { - if (ManufacturingStages.IsNullOrEmpty()) + if (ManufacturingStages.IsNullOrEmpty()) { + _invalidEntries.Add("no manufacturing stages"); return false; + } if (_consolidateManufacturingStages == null) _consolidateManufacturingStages = GetConsolidateManufacturingStage(); @@ -150,6 +155,20 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl } } + public IList<string> InvalidEntries + { + get + { + var consolidatedInvalidEntries = _consolidateManufacturingStages?.GetInvalidEntries(JobType); + if (consolidatedInvalidEntries != null) { + return _invalidEntries.Concat(consolidatedInvalidEntries).ToList(); + } else { + return _invalidEntries; + } + + } + } + private ConsolidateManufacturingStages GetConsolidateManufacturingStage() { return new ConsolidateManufacturingStages(PrimaryVehicle, ManufacturingStages.Reverse()); @@ -285,11 +304,34 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl #region Generate Consolidated Multistage InputData - public abstract class ConsolidatedDataBase { protected readonly IEnumerable<IManufacturingStageInputData> _manufacturingStages; - protected string InvalidEntry { get; private set; } + private string _invalidEntry; + protected IList<string> _invalidEntries = new List<string>(); + protected bool _fullChecked = false; + protected bool _checked = false; + protected bool _isComplete = true; + + protected string InvalidEntry + { + get => _invalidEntry; + private set + { + _invalidEntry = value; + + if (!_invalidEntries.Contains(_invalidEntry)) { + _invalidEntries.Add(_invalidEntry); + } + _isComplete = false; + } + } + + + + + + public ConsolidatedDataBase(IEnumerable<IManufacturingStageInputData> manufacturingStages) { @@ -320,10 +362,47 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl return obj; } - public abstract bool IsInputDataComplete(VectoSimulationJobType jobType); + protected abstract bool IsInputDataCompleteTemplate(VectoSimulationJobType jobType, bool fullCheck); + + + public bool IsInputDataComplete(VectoSimulationJobType jobType) + { + var result = (_checked && _isComplete) || IsInputDataCompleteTemplate(jobType, fullCheck: false); + _isComplete = result; + return result; + } + + public bool IsInputDataCompleteFullCheck(VectoSimulationJobType jobType) + { + if (_isComplete && _checked) { + return true; + } else { + var result = IsInputDataCompleteTemplate(jobType, fullCheck: true); + _isComplete = result; + _fullChecked = true; + _checked = true; + return result; + } + } + + + public abstract string GetInvalidEntry(); + protected abstract IList<string> GetInvalidEntriesTemplate(VectoSimulationJobType jobType); + + public IList<string> GetInvalidEntries(VectoSimulationJobType jobType) + { + if (_checked && _isComplete) { + return _invalidEntries; //<- empty + } else { + IsInputDataCompleteFullCheck(jobType); + return GetInvalidEntriesTemplate(jobType); + } + + } + protected bool MethodComplete(bool result, string methodName) { if (result) @@ -366,9 +445,12 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl public DigestData Signature => _manufacturingStages.First().Signature; - public override bool IsInputDataComplete(VectoSimulationJobType jobType) + + protected override bool IsInputDataCompleteTemplate(VectoSimulationJobType jobType, bool fullCheck) { - return GetConsolidatedVehicleData().IsInputDataComplete(jobType); + return fullCheck + ? GetConsolidatedVehicleData().IsInputDataCompleteFullCheck(jobType) + : GetConsolidatedVehicleData().IsInputDataComplete(jobType); } public override string GetInvalidEntry() @@ -376,6 +458,13 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl return _consolidatedVehicleData.GetInvalidEntry(); } + #region Overrides of ConsolidatedDataBase + protected override IList<string> GetInvalidEntriesTemplate(VectoSimulationJobType jobType) + { + return _invalidEntries.Concat(_consolidatedVehicleData.GetInvalidEntries(jobType)).ToList(); + } + #endregion + private ConsolidatedVehicleData GetConsolidatedVehicleData() { return _consolidatedVehicleData ?? @@ -408,8 +497,6 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl public string VIN => _manufacturingStages.First().Vehicle.VIN; - public string LegislativeCategory => null; - public VehicleDeclarationType VehicleDeclarationType => _manufacturingStages.First().Vehicle.VehicleDeclarationType; #endregion @@ -487,7 +574,10 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl public string CertificationNumber { get; } public DigestData DigestValue { get; } public string Identifier { get; } - public bool ExemptedVehicle { get; } + public bool ExemptedVehicle + { + get { return _manufacturingStages.Any(x => x.Vehicle.ExemptedVehicle); } + } public VehicleCategory VehicleCategory { get; } public AxleConfiguration AxleConfiguration { get; } public IList<ITorqueLimitInputData> TorqueLimits { get; } @@ -500,6 +590,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl public bool DualFuelVehicle { get; } public Watt MaxNetPower1 { get; } public Watt MaxNetPower2 { get; } + public string ExemptedTechnology { get; } + public CubicMeter CargoVolume { get; } public bool Articulated { get; } @@ -566,11 +658,70 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl return validAirdragEntries; } - public override bool IsInputDataComplete(VectoSimulationJobType jobType) + private bool IsInputDataCompleteExempted(VectoSimulationJobType jobType, bool fullCheck) { + if (fullCheck) + { + //use Binary AND to execute all Statements and gather information about missing parameters. + return InputComplete(Model, nameof(Model)) + & InputComplete(LegislativeClass, nameof(LegislativeClass)) + & InputComplete(CurbMassChassis, nameof(CurbMassChassis)) + & InputComplete(GrossVehicleMassRating, nameof(GrossVehicleMassRating)) + & InputComplete(RegisteredClass, nameof(RegisteredClass)) + & InputComplete(NumberPassengerSeatsLowerDeck, nameof(NumberPassengerSeatsLowerDeck)) + & InputComplete(NumberPassengersStandingLowerDeck, nameof(NumberPassengersStandingLowerDeck)) + & InputComplete(NumberPassengerSeatsUpperDeck, nameof(NumberPassengerSeatsUpperDeck)) + & InputComplete(NumberPassengersStandingUpperDeck, nameof(NumberPassengersStandingUpperDeck)) + & InputComplete(VehicleCode, nameof(VehicleCode)) + & InputComplete(LowEntry, nameof(LowEntry)) + & InputComplete(Height, nameof(Height)); + } + + + return InputComplete(Model, nameof(Model)) + && InputComplete(LegislativeClass, nameof(LegislativeClass)) + && InputComplete(CurbMassChassis, nameof(CurbMassChassis)) + && InputComplete(GrossVehicleMassRating, nameof(GrossVehicleMassRating)) + && InputComplete(RegisteredClass, nameof(RegisteredClass)) + && InputComplete(NumberPassengerSeatsLowerDeck, nameof(NumberPassengerSeatsLowerDeck)) + && InputComplete(NumberPassengerSeatsUpperDeck, nameof(NumberPassengerSeatsUpperDeck)) + && InputComplete(VehicleCode, nameof(VehicleCode)) + && InputComplete(LowEntry, nameof(LowEntry)) && InputComplete(Height, nameof(Height)); + } + + + protected override bool IsInputDataCompleteTemplate(VectoSimulationJobType jobType, bool fullCheck) + { + if (ExemptedVehicle) { + return IsInputDataCompleteExempted(jobType, fullCheck); + } GetADAS(); GetComponents(); + if (fullCheck) { + //use Binary AND to execute all Statements and gather information about missing parameters. + return InputComplete(Model, nameof(Model)) + & InputComplete(LegislativeClass, nameof(LegislativeClass)) + & InputComplete(CurbMassChassis, nameof(CurbMassChassis)) + & InputComplete(GrossVehicleMassRating, nameof(GrossVehicleMassRating)) + & MethodComplete(IsAirdragEntriesValid(), nameof(IsAirdragEntriesValid)) + & MethodComplete(IsTankSystemValid(), nameof(IsTankSystemValid)) + & InputComplete(RegisteredClass, nameof(RegisteredClass)) + & InputComplete(NumberPassengerSeatsLowerDeck, nameof(NumberPassengerSeatsLowerDeck)) + & InputComplete(NumberPassengerSeatsUpperDeck, nameof(NumberPassengerSeatsUpperDeck)) + & InputComplete(NumberPassengersStandingLowerDeck, nameof(NumberPassengersStandingLowerDeck)) + & InputComplete(NumberPassengersStandingUpperDeck, nameof(NumberPassengersStandingUpperDeck)) + & InputComplete(VehicleCode, nameof(VehicleCode)) + & InputComplete(LowEntry, nameof(LowEntry)) + & InputComplete(Height, nameof(Height)) + & InputComplete(Length, nameof(Length)) + & InputComplete(Width, nameof(Width)) + & InputComplete(EntranceHeight, nameof(EntranceHeight)) + & InputComplete(DoorDriveTechnology, nameof(DoorDriveTechnology)) + & (InputComplete(_consolidatedADAS, nameof(_consolidatedADAS)) && _consolidatedADAS.IsInputDataCompleteFullCheck(jobType)) + & (InputComplete(_consolidatedComponents, nameof(_consolidatedComponents)) && _consolidatedComponents.IsInputDataCompleteFullCheck(jobType)); + } + return InputComplete(Model, nameof(Model)) && InputComplete(LegislativeClass, nameof(LegislativeClass)) && InputComplete(CurbMassChassis, nameof(CurbMassChassis)) @@ -587,12 +738,11 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl && InputComplete(Length, nameof(Length)) && InputComplete(Width, nameof(Width)) && InputComplete(EntranceHeight, nameof(EntranceHeight)) && InputComplete(DoorDriveTechnology, nameof(DoorDriveTechnology)) - && InputComplete(_consolidatedADAS, nameof(_consolidatedADAS)) - && _consolidatedADAS.IsInputDataComplete(jobType) - && InputComplete(_consolidatedComponents, nameof(_consolidatedComponents)) - && _consolidatedComponents.IsInputDataComplete(jobType); + && InputComplete(_consolidatedADAS, nameof(_consolidatedADAS)) && _consolidatedADAS.IsInputDataComplete(jobType) + && InputComplete(_consolidatedComponents, nameof(_consolidatedComponents)) && _consolidatedComponents.IsInputDataComplete(jobType); } + public override string GetInvalidEntry() { if (InvalidEntry != null) @@ -606,6 +756,21 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl return null; } + + protected override IList<string> GetInvalidEntriesTemplate(VectoSimulationJobType jobType) + { + IEnumerable<string> concatenatedEntries = new List<string>(); + if (_consolidatedComponents != null) { + concatenatedEntries = concatenatedEntries.Concat(_consolidatedComponents.GetInvalidEntries(jobType)); + } + + if (_consolidatedADAS != null) { + concatenatedEntries = concatenatedEntries.Concat(_consolidatedADAS.GetInvalidEntries(jobType)); + } + + + return _invalidEntries.Concat(concatenatedEntries).ToList(); + } } // --------------------------------------------------------------------------------------- @@ -640,7 +805,7 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl return default; } - public override bool IsInputDataComplete(VectoSimulationJobType jobType) + protected override bool IsInputDataCompleteTemplate(VectoSimulationJobType jobType, bool fullCheck) { return InputComplete(ATEcoRollReleaseLockupClutch, nameof(ATEcoRollReleaseLockupClutch)); } @@ -649,6 +814,11 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl { return InvalidEntry; } + + protected override IList<string> GetInvalidEntriesTemplate(VectoSimulationJobType jobType) + { + return _invalidEntries; + } } // --------------------------------------------------------------------------------------- @@ -723,11 +893,15 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl } - public override bool IsInputDataComplete(VectoSimulationJobType jobType) + protected override bool IsInputDataCompleteTemplate(VectoSimulationJobType jobType, bool fullCheck) { GetAirdragInputData(); GetBusAuxiliaries(); - + if (fullCheck) { + //use Binary AND to execute all Statements and gather information about missing parameters. + return InputComplete(_consolidateBusAuxiliariesData, nameof(_consolidateBusAuxiliariesData)) + & _consolidateBusAuxiliariesData.IsInputDataCompleteFullCheck(jobType); + } return InputComplete(_consolidateBusAuxiliariesData, nameof(_consolidateBusAuxiliariesData)) && _consolidateBusAuxiliariesData.IsInputDataComplete(jobType); } @@ -745,6 +919,11 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl return InvalidEntry; } + + protected override IList<string> GetInvalidEntriesTemplate(VectoSimulationJobType jobType) + { + return _invalidEntries.Concat(_consolidateBusAuxiliariesData.GetInvalidEntries(jobType)).ToList(); + } } // --------------------------------------------------------------------------------------- @@ -798,7 +977,7 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl } } - public override bool IsInputDataComplete(VectoSimulationJobType jobType) + protected override bool IsInputDataCompleteTemplate(VectoSimulationJobType jobType, bool fullCheck) { return InputComplete(AirdragEntry, nameof(AirdragEntry)); } @@ -807,6 +986,11 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl { return InvalidEntry; } + + protected override IList<string> GetInvalidEntriesTemplate(VectoSimulationJobType jobType) + { + return _invalidEntries; + } } // --------------------------------------------------------------------------------------- @@ -870,11 +1054,18 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl } - public override bool IsInputDataComplete(VectoSimulationJobType jobType) + protected override bool IsInputDataCompleteTemplate(VectoSimulationJobType jobType, bool fullCheck) { GetElectricConsumers(); GetHVACAux(); + if (fullCheck) { + //use Binary AND to execute all Statements and gather information about missing parameters. + return InputComplete(_consolidateElectricConsumerData, nameof(_consolidateElectricConsumerData)) + & _consolidateElectricConsumerData.IsInputDataCompleteFullCheck(jobType) + & InputComplete(_consolidatedHVACBusAuxiliariesData, nameof(_consolidatedHVACBusAuxiliariesData)) + & _consolidatedHVACBusAuxiliariesData.IsInputDataCompleteFullCheck(jobType); + } return InputComplete(_consolidateElectricConsumerData, nameof(_consolidateElectricConsumerData)) && _consolidateElectricConsumerData.IsInputDataComplete(jobType) && InputComplete(_consolidatedHVACBusAuxiliariesData, nameof(_consolidatedHVACBusAuxiliariesData)) @@ -894,6 +1085,12 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl return null; } + protected override IList<string> GetInvalidEntriesTemplate(VectoSimulationJobType jobType) + { + return _invalidEntries.Concat(_consolidateElectricConsumerData.GetInvalidEntries(jobType)) + .Concat(_consolidatedHVACBusAuxiliariesData.GetInvalidEntries(jobType)).ToList(); + } + private XmlNode GetBusAuxXMLSource() { @@ -944,8 +1141,15 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl return default; } - public override bool IsInputDataComplete(VectoSimulationJobType jobType) + protected override bool IsInputDataCompleteTemplate(VectoSimulationJobType jobType, bool fullCheck) { + if (fullCheck) { + return InputComplete(InteriorLightsLED, nameof(InteriorLightsLED)) + & InputComplete(DayrunninglightsLED, nameof(DayrunninglightsLED)) + & InputComplete(PositionlightsLED, nameof(PositionlightsLED)) + & InputComplete(HeadlightsLED, nameof(HeadlightsLED)) + & InputComplete(BrakelightsLED, nameof(BrakelightsLED)); + } return InputComplete(InteriorLightsLED, nameof(InteriorLightsLED)) && InputComplete(DayrunninglightsLED, nameof(DayrunninglightsLED)) && InputComplete(PositionlightsLED, nameof(PositionlightsLED)) @@ -957,6 +1161,11 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl { return InvalidEntry; } + + protected override IList<string> GetInvalidEntriesTemplate(VectoSimulationJobType jobType) + { + return _invalidEntries; + } } // --------------------------------------------------------------------------------------- @@ -1039,8 +1248,19 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl } } - public override bool IsInputDataComplete(VectoSimulationJobType jobType) - { + protected override bool IsInputDataCompleteTemplate(VectoSimulationJobType jobType, bool fullCheck) + { + if (fullCheck) { + return MethodComplete(IsCorrectSystemConfiguration(), nameof(IsCorrectSystemConfiguration)) + & InputComplete(HeatPumpTypeDriverCompartment, nameof(HeatPumpTypeDriverCompartment)) + & InputComplete(HeatPumpModeDriverCompartment, nameof(HeatPumpModeDriverCompartment)) + & InputComplete(HeatPumpPassengerCompartments, nameof(HeatPumpPassengerCompartments)) + & InputComplete(AuxHeaterPower, nameof(AuxHeaterPower)) + & InputComplete(DoubleGlazing, nameof(DoubleGlazing)) + & InputComplete(AdjustableAuxiliaryHeater, nameof(AdjustableAuxiliaryHeater)) + & InputComplete(SeparateAirDistributionDucts, nameof(SeparateAirDistributionDucts)) + & MethodComplete(RequiredParametersForJobType(jobType), nameof(RequiredParametersForJobType)); + } return MethodComplete(IsCorrectSystemConfiguration(), nameof(IsCorrectSystemConfiguration)) && InputComplete(HeatPumpTypeDriverCompartment, nameof(HeatPumpTypeDriverCompartment)) && InputComplete(HeatPumpModeDriverCompartment, nameof(HeatPumpModeDriverCompartment)) @@ -1056,6 +1276,11 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl { return InvalidEntry; } + + protected override IList<string> GetInvalidEntriesTemplate(VectoSimulationJobType jobType) + { + return _invalidEntries; + } } #endregion diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/Reader/Impl/XMLJobDataReader.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/Reader/Impl/XMLJobDataReader.cs index 09f1efd57d1486751c3ec2e4fdd8ee719b775941..52d4631c79bfe8d3da587b5e276c413af565dc2a 100644 --- a/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/Reader/Impl/XMLJobDataReader.cs +++ b/VectoCore/VectoCore/InputData/FileIO/XML/Declaration/Reader/Impl/XMLJobDataReader.cs @@ -171,4 +171,16 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Declaration.Reader.Impl } } + // --------------------------------------------------------------------------------------- + + public class XMLJobDataMultistageExemptedPrimaryVehicleReaderV01 : XMLJobDataMultistagePrimaryVehicleReaderV01 + { + public new static readonly XNamespace NAMESPACE_URI = XMLDefinitions.DECLARATION_MULTISTAGE_BUS_VEHICLE_NAMESPACE_VO1; + + public new const string XSD_TYPE = "VehicleExemptedPrimaryBusType"; + + public new static readonly string QUALIFIED_XSD_TYPE = XMLHelper.CombineNamespace(NAMESPACE_URI.NamespaceName, XSD_TYPE); + + public XMLJobDataMultistageExemptedPrimaryVehicleReaderV01(IXMLPrimaryVehicleBusJobInputData busJobData, XmlNode jobNode) : base(busJobData, jobNode) { } + } } diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringGearshiftData.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringGearshiftData.cs index 41fbabdf1763e837b6d36e7230c7522e5cb5221c..9ad57f3e2e2ce0626148185739cf8be073b63e9f 100644 --- a/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringGearshiftData.cs +++ b/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringGearshiftData.cs @@ -121,6 +121,9 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Engineering.DataProvider public PerSecond MinEngineSpeedPostUpshift => null; public Second ATLookAheadTime => null; public double[][] ShiftSpeedsTCToLocked => null; + public double? PEV_TargetSpeedBrakeNorm => null; + public double? PEV_DeRatingDownshiftSpeedFactor => null; + public double? PEV_DownshiftMinSpeedFactor => null; public double? AccelerationFactor => null; diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringVehicleDataProvider.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringVehicleDataProvider.cs index fd6f9ccda3372030103c0c3dfae67b103e2c827a..30f573e8ee539531a322e797643f652666c36fe6 100644 --- a/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringVehicleDataProvider.cs +++ b/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringVehicleDataProvider.cs @@ -90,8 +90,6 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Engineering.DataProvider public virtual string VIN => GetString(XMLNames.Vehicle_VIN); - public string LegislativeCategory => null; - public virtual LegislativeClass? LegislativeClass => GetString(XMLNames.Vehicle_LegislativeClass).ParseEnum<LegislativeClass>(); public virtual VehicleCategory VehicleCategory => @@ -132,6 +130,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Engineering.DataProvider public Watt MaxNetPower2 => null; + public string ExemptedTechnology { get; } + public virtual RegistrationClass? RegisteredClass => RegistrationClass.unknown; public virtual int? NumberPassengerSeatsUpperDeck => 0; public virtual int? NumberPassengerSeatsLowerDeck => 0; diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs index 448157e3b1054f9d65f33f9d90865283f3958c5a..19690eae244a46f6e4f7c0ae845f13798d0d1775 100644 --- a/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs +++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/FuelConsumptionMapReader.cs @@ -31,6 +31,7 @@ using System; using System.Data; +using System.IO; using System.Linq; using TUGraz.VectoCommon.BusAuxiliaries; using TUGraz.VectoCommon.Exceptions; @@ -53,6 +54,16 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData } } + public static FuelConsumptionMap ReadFromStream(Stream stream) + { + try { + var data = VectoCSVFile.ReadStream(stream); + return Create(data); + } catch (Exception e) { + throw new VectoException($"Failed reading stream: {e.Message}", e); + } + } + public static FuelConsumptionMap Create(DataTable data) { var headerValid = HeaderIsValid(data.Columns); diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs index e57bba31347a7a553c5692b4d80e76953d2df729..584a23ad1fae3f64021c35f779564ff0fabecefa 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs @@ -368,11 +368,14 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter } // create new full-load curve with values closest to zero. - return new ElectricMotorFullLoadCurve(motorSpeeds.OrderBy(x => x.Value()).Distinct().Select(x => new ElectricMotorFullLoadCurve.FullLoadEntry() { - MotorSpeed = x, - FullDriveTorque = VectoMath.Max(fullLoadCurve.FullLoadDriveTorque(x), maxTorqueCurve.FullLoadDriveTorque(x)), - FullGenerationTorque = VectoMath.Min(fullLoadCurve.FullGenerationTorque(x), maxTorqueCurve.FullGenerationTorque(x)), - }).ToList()); + return new ElectricMotorFullLoadCurve(motorSpeeds.OrderBy(x => x.Value()).Distinct().Select(x => + new ElectricMotorFullLoadCurve.FullLoadEntry() { + MotorSpeed = x, + FullDriveTorque = VectoMath.Max(fullLoadCurve.FullLoadDriveTorque(x), + maxTorqueCurve.FullLoadDriveTorque(x)), + FullGenerationTorque = VectoMath.Min(fullLoadCurve.FullGenerationTorque(x), + maxTorqueCurve.FullGenerationTorque(x)), + }).ToList()); } diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterCompletedBusSpecific.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterCompletedBusSpecific.cs index 3ed44c304530824451009012db15f6572993d0ab..99b0390305e5d043bfbbed82d37f67cb18e2bb83 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterCompletedBusSpecific.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterCompletedBusSpecific.cs @@ -402,21 +402,24 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter #endregion - protected double GetNumberOfPassengers(Mission mission, Meter length, Meter width, double registeredPassengers, + protected double GetNumberOfPassengers(Mission mission, Meter length, Meter width, double registeredPassengerSeats, double registeredPassengersStanding, LoadingType loading) { var busFloorArea = DeclarationData.BusAuxiliaries.CalculateBusFloorSurfaceArea(length, width); var passengerCountRef = busFloorArea * (loading == LoadingType.LowLoading ? mission.BusParameter.PassengerDensityLow : mission.BusParameter.PassengerDensityRef); - //var passengerCountDecl = completedVehicle.NuberOfPassengersUpperDeck + completedVehicle.NumberOfPassengersLowerDeck; + if (loading != LoadingType.ReferenceLoad && loading != LoadingType.LowLoading) { throw new VectoException("Unhandled loading type: {0}", loading); } + var passengerCount = registeredPassengerSeats + + (mission.MissionType == MissionType.Coach ? 0 : registeredPassengersStanding); + return loading == LoadingType.ReferenceLoad - ? VectoMath.Min(passengerCountRef, registeredPassengers) - : VectoMath.Min(passengerCountRef * mission.MissionType.GetLowLoadFactorBus(), registeredPassengers); + ? VectoMath.Min(passengerCountRef, passengerCount) + : VectoMath.Min(passengerCountRef * mission.MissionType.GetLowLoadFactorBus(), passengerCount); } diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterPrimaryBus.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterPrimaryBus.cs index a41418f00e47f42e0c0534849eba307e1aa8addf..44814cf8d562daa3135bdf9cfea721f04e55e0f5 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterPrimaryBus.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterPrimaryBus.cs @@ -34,11 +34,41 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter public override VehicleData CreateVehicleData(IVehicleDeclarationInputData data, Segment segment, Mission mission, KeyValuePair<LoadingType, Tuple<Kilogram, double?>> loading, bool allowVocational) { var retVal = base.CreateVehicleData(data, segment, mission, loading, allowVocational); + if (data.ExemptedVehicle) { + return retVal; + } retVal.CurbMass = mission.CurbMass; retVal.GrossVehicleMass = 40000.SI<Kilogram>(); return retVal; } + protected override VehicleData CreateExemptedVehicleData(IVehicleDeclarationInputData data) + { + var exempted = new VehicleData { + InputData = data, + SavedInDeclarationMode = data.SavedInDeclarationMode, + Manufacturer = data.Manufacturer, + ModelName = data.Model, + Date = data.Date, + //CertificationNumber = data.CertificationNumber, + DigestValueInput = data.DigestValue != null ? data.DigestValue.DigestValue : "", + VehicleCategory = data.VehicleCategory, + //CurbMass = data.CurbMassChassis, + GrossVehicleMass = data.GrossVehicleMassRating, + AirDensity = Physics.AirDensity, + }; + exempted.VIN = data.VIN; + exempted.ManufacturerAddress = data.ManufacturerAddress; + exempted.LegislativeClass = data.LegislativeClass; + exempted.ZeroEmissionVehicle = data.ZeroEmissionVehicle; + exempted.HybridElectricHDV = data.HybridElectricHDV; + exempted.DualFuelVehicle = data.DualFuelVehicle; + exempted.MaxNetPower1 = data.MaxNetPower1; + exempted.MaxNetPower2 = data.MaxNetPower2; + exempted.AxleConfiguration = data.AxleConfiguration; + return exempted; + } + public override PTOData CreatePTOTransmissionData(IPTOTransmissionInputData pto) { return null; diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs index 7a122f0bdc5475bb6d01fc085556d96b61c8183b..a2a8599a5b77448173b07e8f805809cfbad6cde8 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs @@ -32,7 +32,12 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter var passengerCountRef = busFloorArea * (loading.Key == LoadingType.LowLoading ? mission.BusParameter.PassengerDensityLow : mission.BusParameter.PassengerDensityRef); - var passengerCountDecl = CompletedVehicle.NumberPassengerSeatsUpperDeck + CompletedVehicle.NumberPassengerSeatsLowerDeck; + var passengerCountDecl = CompletedVehicle.NumberPassengerSeatsUpperDeck + + CompletedVehicle.NumberPassengerSeatsLowerDeck + + (mission.MissionType == MissionType.Coach + ? 0 + : CompletedVehicle.NumberPassengersStandingLowerDeck + + CompletedVehicle.NumberPassengersStandingUpperDeck); //var refLoad = passengerCount * mission.MissionType.GetAveragePassengerMass(); if (loading.Key != LoadingType.ReferenceLoad && loading.Key != LoadingType.LowLoading) { diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs index 2dcf3166d74ffb3e830432e2292f2303ee908a75..c19b3ab671467f74d52973067f92dce741bb3b14 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs @@ -691,6 +691,18 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter LoadstageThresholds = gsInputData.LoadStageThresholdsUp != null && gsInputData.LoadStageThresholdsDown != null ? gsInputData.LoadStageThresholdsUp.Zip(gsInputData.LoadStageThresholdsDown, Tuple.Create) : null }; + if (gsInputData.PEV_DeRatingDownshiftSpeedFactor != null) { + retVal.PEV_DeRatedDownshiftSpeedFactor = gsInputData.PEV_DeRatingDownshiftSpeedFactor.Value; + } + + if (gsInputData.PEV_TargetSpeedBrakeNorm != null) { + retVal.PEV_TargetSpeedBrakeNorm = gsInputData.PEV_TargetSpeedBrakeNorm.Value; + } + + if (gsInputData.PEV_DownshiftMinSpeedFactor != null) { + retVal.PEV_DownshiftMinSpeedFactor = gsInputData.PEV_DownshiftMinSpeedFactor.Value; + } + return retVal; } diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedMultistageBusVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedMultistageBusVectoRunDataFactory.cs index 881941b8bb849a0b24225895545b854b75219e15..05d3dd421eee4e79fc4dee81c66d70bbdbcbb77c 100644 --- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedMultistageBusVectoRunDataFactory.cs +++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeCompletedMultistageBusVectoRunDataFactory.cs @@ -68,19 +68,45 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl protected virtual void InitializeReport() { - var powertrainConfig = _segmentCompletedBus.Missions.Select( - mission => CreateVectoRunDataSpecific( - mission, mission.Loadings.First(), 0)) - .FirstOrDefault(x => x != null); + var powertrainConfig = CompletedVehicle.ExemptedVehicle || PrimaryVehicle.ExemptedVehicle + ? GetExemptedVectoRunData() + :_segmentCompletedBus.Missions.Select( + mission => CreateVectoRunDataSpecific( + mission, mission.Loadings.First(), 0)) + .FirstOrDefault(x => x != null); Report.InitializeReport(powertrainConfig, new List<List<FuelData.Entry>>()); } + private VectoRunData GetExemptedVectoRunData() + { + return new VectoRunData() { + Exempted = true, + VehicleData = new VehicleData() { + ModelName = CompletedVehicle.Model, + Manufacturer = CompletedVehicle.Manufacturer, + ManufacturerAddress = CompletedVehicle.ManufacturerAddress, + VIN = CompletedVehicle.VIN, + LegislativeClass = CompletedVehicle.LegislativeClass, + RegisteredClass = CompletedVehicle.RegisteredClass, + VehicleCode = CompletedVehicle.VehicleCode, + CurbMass = CompletedVehicle.CurbMassChassis, + GrossVehicleMass = CompletedVehicle.GrossVehicleMassRating, + ZeroEmissionVehicle = PrimaryVehicle.ZeroEmissionVehicle, + MaxNetPower1 = PrimaryVehicle.MaxNetPower1, + InputData = CompletedVehicle + }, + Report = Report, + Mission = new Mission() { + MissionType = MissionType.ExemptedMission + } + }; + } protected virtual void Initialize() { - if (CompletedVehicle.ExemptedVehicle || PrimaryVehicle.ExemptedVehicle) + if (PrimaryVehicle.ExemptedVehicle || CompletedVehicle.ExemptedVehicle) { return; } @@ -121,9 +147,13 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl protected virtual IEnumerable<VectoRunData> GetNextRun() { + if (InputDataProvider.JobInputData.PrimaryVehicle.Vehicle.ExemptedVehicle) { + return new[] { GetExemptedVectoRunData() }; + } return VectoRunDataHeavyBusCompleted(); } + private IEnumerable<VectoRunData> VectoRunDataHeavyBusCompleted() { var engineModes = InputDataProvider.JobInputData.PrimaryVehicle.Vehicle.Components.EngineInputData.EngineModes; diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeHeavyLorryVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeHeavyLorryVectoRunDataFactory.cs index b047c5a1eafac5c2f0df95ae8b727cfbbe25ab01..37545d3f370f03cb8a7a9b1c7f7facd584bb0ff1 100644 --- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeHeavyLorryVectoRunDataFactory.cs +++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeHeavyLorryVectoRunDataFactory.cs @@ -191,6 +191,6 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl return simulationRunData; } - + } } diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeMultistageBusVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeMultistageBusVectoRunDataFactory.cs index 708b3efa8969ae980b3a742b842b5bcba4ee9cea..c2c3e20b12a7ccff214dbb7455b067ca4042f1d7 100644 --- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeMultistageBusVectoRunDataFactory.cs +++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeMultistageBusVectoRunDataFactory.cs @@ -26,15 +26,17 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl { return new VectoRunData { - Exempted = true, + Exempted = InputDataProvider.MultistageJobInputData.JobInputData.PrimaryVehicle.Vehicle.ExemptedVehicle, + MultistageRun = true, + ExecutionMode = ExecutionMode.Declaration, Report = Report, Mission = new Mission { MissionType = MissionType.ExemptedMission }, - VehicleData = CreateExemptedVehicleData(InputDataProvider.MultistageJobInputData.JobInputData.PrimaryVehicle.Vehicle), + VehicleData = CreateVehicleData(InputDataProvider.MultistageJobInputData.JobInputData.PrimaryVehicle.Vehicle), MultistageVIFInputData = InputDataProvider }; } - private VehicleData CreateExemptedVehicleData(IVehicleDeclarationInputData data) + private VehicleData CreateVehicleData(IVehicleDeclarationInputData data) { var exempted = SetCommonVehicleData(data); exempted.VIN = data.VIN; @@ -42,7 +44,7 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl exempted.LegislativeClass = data.LegislativeClass; exempted.ZeroEmissionVehicle = data.ZeroEmissionVehicle; exempted.HybridElectricHDV = data.HybridElectricHDV; - exempted.DualFuelVehicle = true; + exempted.DualFuelVehicle = data.DualFuelVehicle;// true; exempted.MaxNetPower1 = data.MaxNetPower1; exempted.MaxNetPower2 = data.MaxNetPower2; diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModePrimaryBusVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModePrimaryBusVectoRunDataFactory.cs index 4094685bc6e3f685ba3687c17aa189234a7124b7..5b54fb576f9f21e3bf02535fa314db9787acf377 100644 --- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModePrimaryBusVectoRunDataFactory.cs +++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModePrimaryBusVectoRunDataFactory.cs @@ -29,10 +29,19 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl protected override IEnumerable<VectoRunData> GetNextRun() { if (InputDataProvider.JobInputData.Vehicle.VehicleCategory == VehicleCategory.HeavyBusPrimaryVehicle) { - return VectoRunDataHeavyBusPrimary(); + if (InputDataProvider.JobInputData.Vehicle.ExemptedVehicle) { + yield return CreateVectoRunData(InputDataProvider.JobInputData.Vehicle, 0, null, + new KeyValuePair<LoadingType, Tuple<Kilogram, double?>>()); + } else { + foreach (var vectoRunData in VectoRunDataHeavyBusPrimary()) { + yield return vectoRunData; + } + } } - return new List<VectoRunData>(); + foreach (var entry in new List<VectoRunData>()) { + yield return entry; + } } protected override Segment GetSegment(IVehicleDeclarationInputData vehicle) @@ -77,6 +86,19 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl protected override VectoRunData CreateVectoRunData( IVehicleDeclarationInputData vehicle, int modeIdx, Mission mission, KeyValuePair<LoadingType, Tuple<Kilogram, double?>> loading) { + if (InputDataProvider.JobInputData.Vehicle.ExemptedVehicle) { + return new VectoRunData() { + Exempted = true, + Report = Report, + Mission = new Mission() { MissionType = MissionType.ExemptedMission }, + VehicleData = DataAdapter.CreateVehicleData(InputDataProvider.JobInputData.Vehicle, new Segment(), + null, + new KeyValuePair<LoadingType, Tuple<Kilogram, double?>>(LoadingType.ReferenceLoad, + Tuple.Create<Kilogram, double?>(0.SI<Kilogram>(), null)), _allowVocational), + InputDataHash = InputDataProvider.XMLHash + }; + } + var engine = vehicle.Components.EngineInputData; var engineModes = engine.EngineModes; var engineMode = engineModes[modeIdx]; diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs index 09ada9253aad937fd50b8ef91f6884dce60bdcb6..2334d5915440d9e888abb065c263a3cdf9ddb149 100644 --- a/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs +++ b/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs @@ -96,12 +96,16 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl AngledriveData angledriveData = null; if (electricMachinesData.Any(x => x.Item1 == PowertrainPosition.BatteryElectricE2)) { // gearbox required! + gearshiftParams = dao.CreateGearshiftData( + InputDataProvider.JobInputData.Vehicle.Components.GearboxInputData.Type, InputDataProvider.DriverInputData.GearshiftInputData, + axlegearData.AxleGear.Ratio * (angledriveData?.Angledrive.Ratio ?? 1.0), null); var tmpRunData = new VectoRunData() { JobType = VectoSimulationJobType.BatteryElectricVehicle, ShiftStrategy = InputDataProvider.JobInputData.ShiftStrategy, GearboxData = new GearboxData() { Type = vehicle.Components.GearboxInputData.Type, }, + GearshiftParameters = gearshiftParams //ElectricMachinesData = electricMachinesData, //VehicleData = dao.CreateVehicleData(vehicle) }; @@ -115,9 +119,7 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl ElectricMachinesData = electricMachinesData }, tmpStrategy); angledriveData = dao.CreateAngledriveData(vehicle.Components.AngledriveInputData); - gearshiftParams = dao.CreateGearshiftData( - gearboxData.Type, InputDataProvider.DriverInputData.GearshiftInputData, - axlegearData.AxleGear.Ratio * (angledriveData?.Angledrive.Ratio ?? 1.0),null); + } if (gearshiftParams == null) { diff --git a/VectoCore/VectoCore/JsonKeys.Designer.cs b/VectoCore/VectoCore/JsonKeys.Designer.cs index e4e7ed2fcc743ec532e0ae81f777a76a8eb76df8..635a01d099148c151fe468f853a4a73ab3068b0a 100644 --- a/VectoCore/VectoCore/JsonKeys.Designer.cs +++ b/VectoCore/VectoCore/JsonKeys.Designer.cs @@ -60,6 +60,15 @@ namespace TUGraz.VectoCore { } } + /// <summary> + /// Looks up a localized string similar to Completed. + /// </summary> + internal static string Completed { + get { + return ResourceManager.GetString("Completed", resourceCulture); + } + } + /// <summary> /// Looks up a localized string similar to VACC. /// </summary> @@ -483,6 +492,15 @@ namespace TUGraz.VectoCore { } } + /// <summary> + /// Looks up a localized string similar to InterimStage. + /// </summary> + internal static string InterimStage { + get { + return ResourceManager.GetString("InterimStage", resourceCulture); + } + } + /// <summary> /// Looks up a localized string similar to Cycles. /// </summary> @@ -528,6 +546,15 @@ namespace TUGraz.VectoCore { } } + /// <summary> + /// Looks up a localized string similar to PrimaryVehicle. + /// </summary> + internal static string PrimaryVehicle { + get { + return ResourceManager.GetString("PrimaryVehicle", resourceCulture); + } + } + /// <summary> /// Looks up a localized string similar to SavedInDeclMode. /// </summary> diff --git a/VectoCore/VectoCore/JsonKeys.resx b/VectoCore/VectoCore/JsonKeys.resx index a006cc08f083b9be4d8ec1c501841bc4b04ddb36..1a022153c6a6bf665f169cca44aec55a52a2a441 100644 --- a/VectoCore/VectoCore/JsonKeys.resx +++ b/VectoCore/VectoCore/JsonKeys.resx @@ -378,4 +378,13 @@ <data name="HEV_Vehicle_MaxDrivetrainPower" xml:space="preserve"> <value>MaxDrivetrainPower</value> </data> + <data name="PrimaryVehicle" xml:space="preserve"> + <value>PrimaryVehicle</value> + </data> + <data name="InterimStage" xml:space="preserve"> + <value>InterimStage</value> + </data> + <data name="Completed" xml:space="preserve"> + <value>Completed</value> + </data> </root> \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/BusAuxiliaries/BusAuxiliaries.cs b/VectoCore/VectoCore/Models/BusAuxiliaries/BusAuxiliaries.cs index 9a10e768bfe0a741da1b1d0f64122a31e8dbab73..5464820523b5acb4e5e6828fc13e66d02596fc8d 100644 --- a/VectoCore/VectoCore/Models/BusAuxiliaries/BusAuxiliaries.cs +++ b/VectoCore/VectoCore/Models/BusAuxiliaries/BusAuxiliaries.cs @@ -349,7 +349,7 @@ namespace TUGraz.VectoCore.Models.BusAuxiliaries - public virtual void CycleStep(Second seconds, double essFactor) + public virtual void CycleStep(Second seconds) { try { //M9.CycleStep(seconds); diff --git a/VectoCore/VectoCore/Models/BusAuxiliaries/Interfaces/IBusAuxiliaries.cs b/VectoCore/VectoCore/Models/BusAuxiliaries/Interfaces/IBusAuxiliaries.cs index 380797ff95bafe72f5216ac04bbe8abfb804f68a..92ba48b352ed929c869296745660de18b897c4ee 100644 --- a/VectoCore/VectoCore/Models/BusAuxiliaries/Interfaces/IBusAuxiliaries.cs +++ b/VectoCore/VectoCore/Models/BusAuxiliaries/Interfaces/IBusAuxiliaries.cs @@ -134,10 +134,9 @@ namespace TUGraz.VectoCore.Models.BusAuxiliaries.Interfaces /// Cycle Step - Used to calculate fuelling /// </summary> /// <param name="seconds"></param> - /// <param name="essFactor"></param> /// <returns></returns> /// <remarks></remarks> - void CycleStep(Second seconds, double essFactor); + void CycleStep(Second seconds); ///// <summary> ///// Initialises AAUX Environment ( Begin Processs ) diff --git a/VectoCore/VectoCore/Models/Declaration/CompletedBusSegments.cs b/VectoCore/VectoCore/Models/Declaration/CompletedBusSegments.cs index bbd03585ca561155665a11754a8a22b321294f5a..bb15f5da9ea6ea54ff16d19fa22a02512d110a56 100644 --- a/VectoCore/VectoCore/Models/Declaration/CompletedBusSegments.cs +++ b/VectoCore/VectoCore/Models/Declaration/CompletedBusSegments.cs @@ -24,23 +24,22 @@ namespace TUGraz.VectoCore.Models.Declaration protected override string ErrorMessage => "ERROR: Could not find the declaration segment for vehicle. numberOfAxles: {0}, vehicleCode: {1}, registrationClass: {2}, " + - "passengersLowerDeck: {3}, bodyHeight: {4} , lowEntry: {5}"; + "passengerSeatsLowerDeck: {3}, bodyHeight: {4} , lowEntry: {5}"; protected override void ParseData(DataTable table) { _segmentTable = table.Copy(); } - public override Segment Lookup(int numberOfAxles, VehicleCode? vehicleCode, RegistrationClass? registrationClass, int? passengersLowerDeck, Meter bodyHeight, bool? lowEntry) + public override Segment Lookup(int numberOfAxles, VehicleCode? vehicleCode, RegistrationClass? registrationClass, int? passengerSeatsLowerDeck, Meter bodyHeight, bool? lowEntry) { - return LookupCompletedBusVehicle(numberOfAxles, vehicleCode, registrationClass, passengersLowerDeck, bodyHeight, lowEntry); + return LookupCompletedBusVehicle(numberOfAxles, vehicleCode, registrationClass, passengerSeatsLowerDeck, bodyHeight, lowEntry); } - #endregion - private Segment LookupCompletedBusVehicle(int numberOfAxles, VehicleCode? vehicleCode, RegistrationClass? registrationClass, int? passengersLowerDeck, Meter bodyHeight, bool? lowEntry) + private Segment LookupCompletedBusVehicle(int numberOfAxles, VehicleCode? vehicleCode, RegistrationClass? registrationClass, int? passengerSeatsLowerDeck, Meter bodyHeight, bool? lowEntry) { var rows = _segmentTable.AsEnumerable().Where( r => { @@ -60,7 +59,7 @@ namespace TUGraz.VectoCore.Models.Declaration rows = rows.Where( r => { var limits = r.Field<string>("passengerslowerdeck").Split('-'); - return ((int)passengersLowerDeck).IsBetween(limits[0].ToInt(), limits[1].ToInt()); + return ((int)passengerSeatsLowerDeck).IsBetween(limits[0].ToInt(), limits[1].ToInt()); }).ToList(); } else if (rows.Any(r => r.Field<string>("bodyheight") != "-")) { rows = rows.Where( diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs index e8287a62cd6faa9417d403e2e07b79934affe74d..d0a44a5fd412ceca9acb5a6de68f09f7b83d8053 100644 --- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs @@ -104,7 +104,7 @@ namespace TUGraz.VectoCore.Models.Declaration public static readonly WeightingGroups WeightingGroup = new WeightingGroups(); public static readonly WeightingFactors WeightingFactors = new WeightingFactors(); - public const double AlternaterEfficiency = 0.7; + public const double AlternatorEfficiency = 0.7; /// <summary> /// Formula for calculating the payload for a given gross vehicle weight. @@ -260,7 +260,7 @@ namespace TUGraz.VectoCore.Models.Declaration } - public static Meter CalculateInternalLength(Meter vehicleLength, VehicleCode? vehicleCode, double numPassLowFloor) + public static Meter CalculateInternalLength(Meter vehicleLength, VehicleCode? vehicleCode, double numPassSeatsLowerDeck) { if (vehicleCode.GetFloorType() == FloorType.LowFloor) { return vehicleCode.IsDoubleDeckerBus() ? 2 * vehicleLength : vehicleLength; @@ -268,7 +268,7 @@ namespace TUGraz.VectoCore.Models.Declaration if (vehicleCode.GetFloorType() == FloorType.HighFloor) { if (vehicleCode.IsDoubleDeckerBus()) { - return numPassLowFloor > 6 ? 1.5 * vehicleLength : vehicleLength + 2.4.SI<Meter>(); + return numPassSeatsLowerDeck > 6 ? 1.5 * vehicleLength : vehicleLength + 2.4.SI<Meter>(); } return vehicleLength; @@ -601,9 +601,9 @@ namespace TUGraz.VectoCore.Models.Declaration switch (type) { case GearboxType.AMT: - // TODO MQ: 2020-10-14: compute for AMT with ICE and AMT with EM differently - //return ComputeEfficiencyShiftPolygon(gearIdx, fullLoadCurve, gears, engine, axlegearRatio, dynamicTyreRadius); - case GearboxType.MT: + // TODO MQ: 2020-10-14: compute for AMT with ICE and AMT with EM differently + return ComputeEfficiencyShiftPolygon(gearIdx, fullLoadCurve, gears, engine, axlegearRatio, dynamicTyreRadius); + case GearboxType.MT: return ComputeManualTransmissionShiftPolygon( gearIdx, fullLoadCurve, gears, engine, axlegearRatio, dynamicTyreRadius); case GearboxType.ATSerial: @@ -622,7 +622,7 @@ namespace TUGraz.VectoCore.Models.Declaration public static ShiftPolygon ComputeElectricMotorShiftPolygon(int gearIdx, ElectricMotorFullLoadCurve fullLoadCurve, double emRatio, IList<ITransmissionInputData> gears, - double axlegearRatio, Meter dynamicTyreRadius) + double axlegearRatio, Meter dynamicTyreRadius, PerSecond downshiftMaxSpeed = null, PerSecond downshiftMinSpeed = null) { if (gears.Count < 2) { throw new VectoException("ComputeShiftPolygon needs at least 2 gears. {0} gears given.", gears.Count); @@ -631,19 +631,125 @@ namespace TUGraz.VectoCore.Models.Declaration var downShift = new List<ShiftPolygon.ShiftPolygonEntry>(); var upShift = new List<ShiftPolygon.ShiftPolygonEntry>(); if (gearIdx > 0) { - downShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxGenerationTorque * emRatio * 1.1, 0.RPMtoRad())); - downShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxDriveTorque * emRatio * 1.1, 0.RPMtoRad())); + var nMax = downshiftMaxSpeed ?? fullLoadCurve.NP80low; + var nMin = downshiftMinSpeed ?? 0.1 * fullLoadCurve.RatedSpeed; + + downShift.AddRange(DownshiftLineDrive(fullLoadCurve, nMin, nMax)); + downShift.AddRange(DownshiftLineDrag(fullLoadCurve, nMin, nMax)); } if (gearIdx >= gears.Count - 1) { return new ShiftPolygon(downShift, upShift); } - upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxGenerationTorque * emRatio * 1.1, fullLoadCurve.MaxSpeed / emRatio * 0.9)); - upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxDriveTorque * emRatio * 1.1, fullLoadCurve.MaxSpeed / emRatio * 0.9)); + upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxGenerationTorque * 1.1, fullLoadCurve.MaxSpeed * 0.9)); + upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxDriveTorque * 1.1, fullLoadCurve.MaxSpeed * 0.9)); return new ShiftPolygon(downShift, upShift); } + private static List<ShiftPolygon.ShiftPolygonEntry> DownshiftLineDrive(ElectricMotorFullLoadCurve fullLoadCurve, PerSecond nMin, PerSecond nMax) + { + var retVal = new List<ShiftPolygon.ShiftPolygonEntry>(); + var downShiftPoints = fullLoadCurve + .FullLoadEntries.Where(fldEntry => fldEntry.MotorSpeed >= nMin && fldEntry.MotorSpeed <= nMax) + .Select( + fldEntry => + new Point(fldEntry.MotorSpeed.Value(), fldEntry.FullDriveTorque.Value() * ShiftPolygonEngineFldMargin)) + .ToList(); + //retVal.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxDriveTorque * 1.1, nMax)); + if (downShiftPoints.Count == 0) { + // coarse grid points in FLD + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.MaxDriveTorque * 1.1, + nMax)); + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullLoadDriveTorque(nMax) * ShiftPolygonEngineFldMargin, + nMax)); + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullLoadDriveTorque(nMin) * ShiftPolygonEngineFldMargin, + nMin)); + + } else { + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.MaxDriveTorque * 1.1, + nMax)); + if (downShiftPoints.Max(x => x.X) < nMax) { + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullLoadDriveTorque(nMax) * ShiftPolygonEngineFldMargin, + nMax)); + } + + retVal.AddRange( + downShiftPoints.Select( + x => new ShiftPolygon.ShiftPolygonEntry( + x.Y.SI<NewtonMeter>(), x.X.SI<PerSecond>())).OrderByDescending(x => x.AngularSpeed.Value())); + if (downShiftPoints.Min(x => x.X) > nMin) { + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullLoadDriveTorque(nMin) * ShiftPolygonEngineFldMargin, + nMin)); + } + } + + return retVal; + } + + private static List<ShiftPolygon.ShiftPolygonEntry> DownshiftLineDrag(ElectricMotorFullLoadCurve fullLoadCurve, PerSecond nMin, PerSecond nMax) + { + var retVal = new List<ShiftPolygon.ShiftPolygonEntry>(); + var downShiftPoints = fullLoadCurve + .FullLoadEntries.Where(fldEntry => fldEntry.MotorSpeed >= nMin && fldEntry.MotorSpeed <= nMax) + .Select( + fldEntry => + new Point(fldEntry.MotorSpeed.Value(), fldEntry.FullGenerationTorque.Value() * ShiftPolygonEngineFldMargin)) + .ToList(); + //retVal.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxGenerationTorque * 1.1, nMax)); + if (downShiftPoints.Count == 0) { + // coarse grid points in FLD + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullGenerationTorque(nMin) * ShiftPolygonEngineFldMargin, + nMin)); + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullGenerationTorque(nMax) * ShiftPolygonEngineFldMargin, + nMax)); + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.MaxGenerationTorque * 1.1, + nMax)); + } else { + if (downShiftPoints.Min(x => x.X) > nMin) { + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullGenerationTorque(nMin) * ShiftPolygonEngineFldMargin, + nMin)); + } + + retVal.AddRange( + downShiftPoints.Select( + x => new ShiftPolygon.ShiftPolygonEntry( + x.Y.SI<NewtonMeter>(), x.X.SI<PerSecond>()))); + if (downShiftPoints.Max(x => x.X) < nMax) { + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullGenerationTorque(nMax) * ShiftPolygonEngineFldMargin, + nMax)); + } + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.MaxGenerationTorque * 1.1, + nMax)); + } + + return retVal; + } + public static ShiftPolygon ComputeEfficiencyShiftPolygon( int gearIdx, EngineFullLoadCurve fullLoadCurve, IList<ITransmissionInputData> gears, CombustionEngineData engine, double axlegearRatio, Meter dynamicTyreRadius) diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs index 46d2c202b032fcc14ff6aebd3e184bb45162c08c..5d70de6d7b96c3569973e759548e1aafa5e10131 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs @@ -141,7 +141,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data /// <summary> /// [g/h] Fuel consumption after correction for ADAS technologies. (Based on FC-AAUXc.) /// </summary> - [ModalResultField(typeof(SI), name: "FC-ESS", caption: "FC-ESS{0} [g/h]", outputFactor: 3600 * 1000)] FCICEStopStart, + //[ModalResultField(typeof(SI), name: "FC-ESS", caption: "FC-ESS{0} [g/h]", outputFactor: 3600 * 1000)] FCICEStopStart, /// <summary> /// [g/h] Fuel consumption after WHTC Correction. (Based on FC-ADAS.) @@ -432,15 +432,15 @@ namespace TUGraz.VectoCore.Models.Simulation.Data P_electricMotor_mech_B2, // --> - [ModalResultField(typeof(SI), caption: "P_reess_T [kW]", outputFactor: 1e-3)] P_reess_terminal, - [ModalResultField(typeof(SI), caption: "P_reess_int [kW]", outputFactor: 1e-3)] P_reess_int, - [ModalResultField(typeof(SI), caption: "P_reess_loss [kW]", outputFactor: 1e-3)] P_reess_loss, + [ModalResultField(typeof(SI), caption: "P_REESS_T [kW]", outputFactor: 1e-3)] P_reess_terminal, + [ModalResultField(typeof(SI), caption: "P_REESS_int [kW]", outputFactor: 1e-3)] P_reess_int, + [ModalResultField(typeof(SI), caption: "P_REESS_loss [kW]", outputFactor: 1e-3)] P_reess_loss, [ModalResultField(typeof(SI), caption: "REESS SOC [%]", outputFactor: 100)] REESSStateOfCharge, - [ModalResultField(typeof(SI), caption: "P_reess charge max [kW]", outputFactor: 1e-3)] P_reess_charge_max, - [ModalResultField(typeof(SI), caption: "P_reess discharge max [kW]", outputFactor: 1e-3)] P_reess_discharge_max, - [ModalResultField(typeof(SI), caption: "U_reess_terminal [V]")] U_reess_terminal, - [ModalResultField(typeof(SI), caption: "U_0_reess [V]")] U0_reess, - [ModalResultField(typeof(SI), caption: "I_reess [A]")] I_reess, + [ModalResultField(typeof(SI), caption: "P_REESS_charge_max [kW]", outputFactor: 1e-3)] P_reess_charge_max, + [ModalResultField(typeof(SI), caption: "P_REESS_discharge_max [kW]", outputFactor: 1e-3)] P_reess_discharge_max, + [ModalResultField(typeof(SI), caption: "U_REESS_terminal [V]")] U_reess_terminal, + [ModalResultField(typeof(SI), caption: "U_0_REESS [V]")] U0_reess, + [ModalResultField(typeof(SI), caption: "I_REESS [A]")] I_reess, [ModalResultField(typeof(SI), caption: "T_max_propulsion [Nm]")] MaxPropulsionTorqe, [ModalResultField(typeof(SI), caption: "P_DC/DC_In [kW]", outputFactor: 1e-3)] P_DCDC_In, diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs b/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs index 031243119acc527d46102f117a22560324a66427..ce834f26fe7a532ef4f631de4642ac15b6ac989a 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs @@ -8,6 +8,13 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data.ShiftStrategy; namespace TUGraz.VectoCore.Models.Simulation.Data { public class ShiftStrategyParameters { + public ShiftStrategyParameters() + { + PEV_DownshiftMinSpeedFactor = 0.1; + PEV_TargetSpeedBrakeNorm = 0.7; + PEV_DeRatedDownshiftSpeedFactor = 1; + } + public MeterPerSecond StartVelocity { get; internal set; } //public MeterPerSquareSecond StartAcceleration { get; internal set; } @@ -101,5 +108,8 @@ namespace TUGraz.VectoCore.Models.Simulation.Data { public double[] LoadStageThresoldsUp { get; set; } public double[] LoadStageThresoldsDown { get; set; } public double[][] ShiftSpeedsTCToLocked { get; set; } + public double PEV_TargetSpeedBrakeNorm { get; set; } + public double PEV_DeRatedDownshiftSpeedFactor { get; set; } + public double PEV_DownshiftMinSpeedFactor { get; set; } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs b/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs index 97196d0176432e95f7fa761bf06de24b2fce5991..bb57cfc4460acb55eeca049457e81f636147ab82 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs @@ -134,12 +134,14 @@ namespace TUGraz.VectoCore.Models.Simulation.Data public SuperCapData SuperCapData { get; internal set; } - public SimulationType SimulationType { get; set; } + public SimulationType SimulationType { get; internal set; } - public VTPData VTPData { get; set; } + public VTPData VTPData { get; internal set; } - public ShiftStrategyParameters GearshiftParameters { get; set; } - public bool Exempted { get; set; } + public ShiftStrategyParameters GearshiftParameters { get; internal set; } + public bool Exempted { get; internal set; } + + public bool MultistageRun { get; internal set; } public IDrivingCycleData PTOCycleWhileDrive { get; internal set; } diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/ExemptedRun.cs b/VectoCore/VectoCore/Models/Simulation/Impl/ExemptedRun.cs index 01865075001a5d3da5991012565c5bfb70730be6..611fcfedbeaec3b22e34c04b1bd94010d53aaede 100644 --- a/VectoCore/VectoCore/Models/Simulation/Impl/ExemptedRun.cs +++ b/VectoCore/VectoCore/Models/Simulation/Impl/ExemptedRun.cs @@ -63,6 +63,9 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl { private void CheckValidInput() { + if (Container.RunData.MultistageRun) { + return; + } var vehicleData = Container.RunData.VehicleData; if (vehicleData.ZeroEmissionVehicle && vehicleData.DualFuelVehicle) { throw new VectoException("Invalid input: ZE-HDV and DualFuelVehicle are mutually exclusive!"); diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs b/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs index 3d7b1243e3bf60a1ce272132e21622b14835c4d9..afc3a8bdc44faeb5566c095bbd82836ff309733c 100644 --- a/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs +++ b/VectoCore/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs @@ -212,7 +212,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl var current = i++; var d = data; data.JobRunId = current; - yield return data.Exempted ? GetExemptedRun(data) : GetNonExemptedRun(data, current, d, ref warning1Hz); + yield return data.Exempted || data.MultistageRun ? GetExemptedRun(data) : GetNonExemptedRun(data, current, d, ref warning1Hz); } } diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/VectoRun.cs b/VectoCore/VectoCore/Models/Simulation/Impl/VectoRun.cs index 3770538e26a5de7b3ef1b56987666633cf563ad3..fd1fb036b33b8f77d530c1a0b7d763d525879dcf 100644 --- a/VectoCore/VectoCore/Models/Simulation/Impl/VectoRun.cs +++ b/VectoCore/VectoCore/Models/Simulation/Impl/VectoRun.cs @@ -124,7 +124,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl Container.AbsTime = AbsTime; } } while (response is ResponseSuccess); - if (!GetContainer().RunData.Exempted) { + if (!(GetContainer().RunData.Exempted || GetContainer().RunData.MultistageRun)) { //foreach (var fuel in GetContainer().RunData.EngineData.Fuels) { // calculate vehicleline correction here in local thread context because writing sum-data and report afterwards is synchronized //var cf = GetContainer().ModalData.VehicleLineCorrectionFactor(fuel.FuelData); @@ -171,7 +171,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl throw ex; } - Container.RunStatus = Container.RunData.Exempted + Container.RunStatus = Container.RunData.Exempted || Container.RunData.MultistageRun ? Status.Success : CyclePort.Progress < 1 ? (response is ResponseBatteryEmpty ? Status.REESSEmpty : Status.Aborted) diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorData.cs index 9c178e89ba6f0d0d2bf7723c0de443f67d821b88..5b0a938e674d29087e8071c5518d88ce90dbfc9d 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorData.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorData.cs @@ -55,7 +55,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data get { return _maxSpeed ?? (_maxSpeed = VoltageLevels - .Min(v => v.EfficiencyMap.MaxSpeed)); + .Min(v => VectoMath.Min(v.EfficiencyMap.MaxSpeed, v.FullLoadCurve.MaxSpeed))); } } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs index 224df5bf5d0723336826adaf408bdb5a6ca1ba7c..011f82f9c7d11213bcd64ebcdb8a434a07dd4b4e 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs @@ -1,16 +1,22 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; namespace TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor { - public class ElectricMotorFullLoadCurve + public class ElectricMotorFullLoadCurve : SimulationComponentData { internal readonly List<FullLoadEntry> FullLoadEntries; private NewtonMeter _maxDriveTorque; private NewtonMeter _maxGenerationTorque; private PerSecond _maxSpeed; + private PerSecond _nP80Low; + private Watt _maxPower; + private PerSecond _ratedSpeed; internal ElectricMotorFullLoadCurve(List<FullLoadEntry> entries) @@ -91,6 +97,131 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor { get { return FullLoadEntries.Select(x => $"{x.MotorSpeed.AsRPM} {x.FullDriveTorque} {x.FullGenerationTorque}").ToArray(); } } + public PerSecond NP80low => _nP80Low ?? (_nP80Low = ComputeNP80LowSpeed()); + public Watt MaxPower => _maxPower ?? (_maxPower = ComputeMaxPower().Item2); + + public PerSecond RatedSpeed => _ratedSpeed ?? (_ratedSpeed = ComputeMaxPower().Item1); + + private Tuple<PerSecond, Watt> ComputeMaxPower() + { + var max = new Tuple<PerSecond, Watt>(0.SI<PerSecond>(), 0.SI<Watt>()); + for (var idx = 1; idx < FullLoadEntries.Count; idx++) { + var entry2 = FullLoadEntries[idx]; + if (FullLoadEntries[idx].MotorSpeed > MaxSpeed) { + entry2 = new FullLoadEntry() { + MotorSpeed = MaxSpeed, + FullDriveTorque = FullLoadDriveTorque(MaxSpeed), + FullGenerationTorque = FullGenerationTorque(MaxSpeed) + }; + } + var currentMax = FindMaxPower(FullLoadEntries[idx - 1], entry2); + if (currentMax.Item2 > max.Item2) { + max = currentMax; + } + } + + return max; + } + + private Tuple<PerSecond, Watt> FindMaxPower(FullLoadEntry p1, FullLoadEntry p2) + { + if (p1.MotorSpeed.IsEqual(p2.MotorSpeed)) { + return Tuple.Create(p1.MotorSpeed, p1.FullDriveTorque * p1.MotorSpeed); + } + + if (p2.MotorSpeed < p1.MotorSpeed) { + var tmp = p1; + p1 = p2; + p2 = tmp; + } + + // y = kx + d + var k = (-p2.FullDriveTorque + p1.FullDriveTorque) / (p2.MotorSpeed - p1.MotorSpeed); + var d = -p2.FullDriveTorque - k * p2.MotorSpeed; + if (k.IsEqual(0)) { + return Tuple.Create(p2.MotorSpeed, -p2.FullDriveTorque * p2.MotorSpeed); + } + var engineSpeedMaxPower = -d / (2 * k); + if (engineSpeedMaxPower.IsSmaller(p1.MotorSpeed) || engineSpeedMaxPower.IsGreater(p2.MotorSpeed)) { + if (-p2.FullDriveTorque * p2.MotorSpeed > -p1.FullDriveTorque * p1.MotorSpeed) { + return Tuple.Create(p2.MotorSpeed, -p2.FullDriveTorque * p2.MotorSpeed); + } + return Tuple.Create(p1.MotorSpeed, -p1.FullDriveTorque * p1.MotorSpeed); + } + var engineTorqueMaxPower = FullLoadDriveTorque(engineSpeedMaxPower); + return Tuple.Create(engineSpeedMaxPower, -engineTorqueMaxPower * engineSpeedMaxPower); + } + + private PerSecond ComputeNP80LowSpeed() + { + var retVal = FindEngineSpeedForPower(0.8 * MaxPower).First(); + return retVal; + } + + private List<PerSecond> FindEngineSpeedForPower(Watt power) + { + var retVal = new List<PerSecond>(); + for (var idx = 1; idx < FullLoadEntries.Count; idx++) { + var solutions = FindEngineSpeedForPower(FullLoadEntries[idx - 1], FullLoadEntries[idx], power); + retVal.AddRange(solutions); + } + retVal.Sort(); + return retVal.Distinct(new SI.EqualityComparer<PerSecond>()).ToList(); + } + + private IEnumerable<PerSecond> FindEngineSpeedForPower(FullLoadEntry p1, FullLoadEntry p2, Watt power) + { + var k = (-p2.FullDriveTorque + p1.FullDriveTorque) / (p2.MotorSpeed - p1.MotorSpeed); + var d = -p2.FullDriveTorque - k * p2.MotorSpeed; + + if (k.IsEqual(0, 0.0001)) { + // constant torque: solve linear equation + // power = M * n_eng_avg + if (d.IsEqual(0, 0.0001)) { + return new List<PerSecond>(); + } + return FilterSolutions((power / d).ToEnumerable(), p1, p2); + } + + // non-constant torque: solve quadratic equation for engine speed (n_eng_avg) + // power = M(n_eng_avg) * n_eng_avg = (k * n_eng_avg + d) * n_eng_avg = k * n_eng_avg^2 + d * n_eng_avg + var retVal = VectoMath.QuadraticEquationSolver(k.Value(), d.Value(), -power.Value()); + if (retVal.Length == 0) { + Log.Info("No real solution found for requested power demand: P: {0}, p1: {1}, p2: {2}", power, p1, p2); + } + return FilterSolutions(retVal.Select(x => Math.Round(x, 6).SI<PerSecond>()), p1, p2); + } + + private IEnumerable<PerSecond> FilterSolutions(IEnumerable<PerSecond> solutions, FullLoadEntry p1, FullLoadEntry p2) + { + return solutions.Where( + x => x.IsGreaterOrEqual(p1.MotorSpeed.Value()) && x.IsSmallerOrEqual(p2.MotorSpeed.Value())); + } + + protected internal Watt ComputeArea(PerSecond lowEngineSpeed, PerSecond highEngineSpeed) + { + var startSegment = FindIndex(lowEngineSpeed); + var endSegment = FindIndex(highEngineSpeed); + + var area = 0.SI<Watt>(); + if (lowEngineSpeed < FullLoadEntries[startSegment].MotorSpeed) { + // add part of the first segment + area += (FullLoadEntries[startSegment].MotorSpeed - lowEngineSpeed) * + (FullLoadDriveTorque(lowEngineSpeed) + FullLoadEntries[startSegment].FullDriveTorque) / 2.0; + } + for (var i = startSegment + 1; i <= endSegment; i++) { + var speedHigh = FullLoadEntries[i].MotorSpeed; + var torqueHigh = FullLoadEntries[i].FullDriveTorque; + if (highEngineSpeed < FullLoadEntries[i].MotorSpeed) { + // add part of the last segment + speedHigh = highEngineSpeed; + torqueHigh = FullLoadDriveTorque(highEngineSpeed); + } + area += (speedHigh - FullLoadEntries[i - 1].MotorSpeed) * (torqueHigh + FullLoadEntries[i - 1].FullDriveTorque) / + 2.0; + } + return area; + } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs index dbdf8745f5eeb0992ce47d75e394cbadfff203c4..9a3609cfb983ec56cc95c4c4602a563fff13d1a0 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs @@ -32,7 +32,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { ? 0.SI<NewtonMeter>() : Formulas.InertiaPower(currOutAngularVelocity, prevOutAngularVelocity, ElectricMotorData.Inertia, dt) / avgSpeed; //var dragTorque = ElectricMotorData.DragCurve.Lookup() - return (-inertiaTorqueLoss).LimitTo(maxDriveTorque, maxRecuperationTorque); + return (-inertiaTorqueLoss); //.LimitTo(maxDriveTorque, maxRecuperationTorque); } if (DataBus.DriverInfo.DrivingAction == DrivingAction.Coast || DataBus.DriverInfo.DrivingAction == DrivingAction.Roll) { diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs index ed2d5bed7e495e86f31333f383fe463701fcb58f..9f96c6524e684c9a3b4ec5ab29f291ffe24f92ce 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BusAuxiliariesAdapter.cs @@ -52,7 +52,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl protected IBusAuxiliaries Auxiliaries; - private double EngineStopStartUtilityFactor; private bool SmartElectricSystem; private IAuxiliaryConfig AuxCfg; @@ -62,7 +61,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl IVehicleContainer container, IAuxiliaryConfig auxiliaryConfig, IAuxPort additionalAux = null) : base(container) { container.AddComponent(this); - EngineStopStartUtilityFactor = 1; // container.RunData?.DriverData?.EngineStopStart?.UtilityFactorStandstill ?? double.NaN; CurrentState = new BusAuxState(); PreviousState = new BusAuxState { AngularSpeed = container.EngineInfo.EngineIdleSpeed }; @@ -216,8 +214,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl absTime, dt, 0.SI<NewtonMeter>(), DataBus.EngineInfo.EngineIdleSpeed, true) - Auxiliaries.ElectricPowerDemandMech; //AdditionalAux = conventionalAux; - CurrentState.PowerDemand = ((AdditionalAux?.PowerDemandESSEngineOn(absTime, dt, DataBus.EngineInfo.EngineIdleSpeed) ?? 0.SI<Watt>()) + - busAuxPowerDemand) * (1 - EngineStopStartUtilityFactor); + CurrentState.PowerDemand = 0.SI<Watt>(); //CurrentState.ESPowerGeneratedICE_On = Auxiliaries.ElectricPowerGenerated; //CurrentState.ESPowerMech = Auxiliaries.ElectricPowerDemandMech; // @@ -227,7 +224,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl // absTime, dt, 0.SI<NewtonMeter>(), DataBus.EngineInfo.EngineIdleSpeed); //AdditionalAux = conventionalAux; - return EngineStopStartUtilityFactor * (busAuxPowerDemand - Auxiliaries.PSPowerDemandAirGenerated + (AdditionalAux?.PowerDemandESSEngineOff(absTime, dt) ?? 0.SI<Watt>())); + return (busAuxPowerDemand - Auxiliaries.PSPowerDemandAirGenerated + (AdditionalAux?.PowerDemandESSEngineOff(absTime, dt) ?? 0.SI<Watt>())); } @@ -238,7 +235,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var essUtilityFactor = 1.0; if (!DataBus.EngineCtl.CombustionEngineOn) { - essUtilityFactor = 1 - EngineStopStartUtilityFactor; + essUtilityFactor = 0.0; } var signals = Auxiliaries.Signals; @@ -248,7 +245,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl // cycleStep has to be called here and not in DoCommit, write is called before Commit! //var oldSOC = Auxiliaries.BatterySOC; - Auxiliaries.CycleStep(CurrentState.dt, DataBus.EngineCtl.CombustionEngineOn ? 1.0 : EngineStopStartUtilityFactor); + Auxiliaries.CycleStep(CurrentState.dt); //var newSOC = Auxiliaries.BatterySOC; //CurrentState.TotalFuelConsumption = Auxiliaries.TotalFuel; @@ -356,7 +353,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var maxChg = ElectricStorage.MaxChargeEnergy(); var maxDischg = ElectricStorage.MaxDischargeEnergy(); - var essFactor = DataBus.EngineCtl.CombustionEngineOn ? 0.0 : EngineStopStartUtilityFactor; + var essFactor = DataBus.EngineCtl.CombustionEngineOn ? 0.0 : 1.0; var elPwrGen = Auxiliaries.ElectricPowerGenerated; var elPwrConsumed = Auxiliaries.ElectricPowerConsumerSum; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index dc84bcf0edc9be725085fd03ab72339e91b0d0b9..ddd51308dc06011661cdd1c0595ae16d90034920 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -485,7 +485,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl container[ModalResultField.FCNCVc, fuel.FuelData] = fcNCVcorr; container[ModalResultField.FCWHTCc, fuel.FuelData] = fcWHTC; //container[ModalResultField.FCAAUX, fuel.FuelData] = fcAAUX; - container[ModalResultField.FCICEStopStart, fuel.FuelData] = fcFinal; + //container[ModalResultField.FCICEStopStart, fuel.FuelData] = fcFinal; container[ModalResultField.FCFinal, fuel.FuelData] = fcFinal; } } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs index ba785ec3398ef869da8238ae442cf2174f34e8ba..17da629f529fe3105350e225cfefb1d018c0e86a 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs @@ -343,11 +343,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } retVal.ElectricMotor.MaxDriveTorque = maxDriveTorqueDt; + retVal.ElectricMotor.MaxDriveTorqueEM = maxDriveTorqueEm; retVal.ElectricMotor.MaxRecuperationTorque = maxRecuperationTorqueDt; + retVal.ElectricMotor.MaxRecuperationTorqueEM = maxRecuperationTorqueEm; retVal.ElectricMotor.AngularVelocity = avgEmSpeed; retVal.ElectricMotor.AvgDrivetrainSpeed = avgDtSpeed; + retVal.ElectricMotor.DeRatingActive = DeRatingActive; retVal.ElectricMotor.TorqueRequest = outTorque; + retVal.ElectricMotor.TorqueRequestEmMap = emTorqueMap; retVal.ElectricMotor.InertiaTorque = avgDtSpeed.IsEqual(0) ? 0.SI<NewtonMeter>() : inertiaTorqueEm * avgEmSpeed / avgDtSpeed; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs index 15fff78cee5e84e6da58ca8fc11950232b0778f2..f9db0338a6647497c5e13478dbe8a373b8606ba2 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs @@ -6,6 +6,7 @@ using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Configuration; +using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation; @@ -33,22 +34,23 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl protected readonly VelocityRollingLookup VelocityDropData = new VelocityRollingLookup(); private SimplePowertrainContainer TestContainer; private Gearbox TestContainerGbx; - private Kilogram vehicleMass; + private VoltageLevelData VoltageLevels; private SI TransmissionRatio; private ShiftStrategyParameters GearshiftParams; private GearList GearList; + private Dictionary<uint, ShiftPolygon> DeRatedShiftpolygons; - public bool EarlyShiftUp { get; } - public bool SkipGears { get; } + public static string Name => "AMT - EffShift (BEV)"; - public static string Name => "AMT - EffShift (BEV)"; + protected bool DriveOffStandstill { get; set; } public PEVAMTShiftStrategy(IVehicleContainer dataBus) { var runData = dataBus.RunData; + shiftStrategyParameters = runData.GearshiftParameters; if (runData.VehicleData == null) { return; } @@ -59,25 +61,26 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl VoltageLevels = dataBus.RunData.ElectricMachinesData .FirstOrDefault(x => x.Item1 == PowertrainPosition.BatteryElectricE2)?.Item2.EfficiencyData; - - DataBus = dataBus; - EarlyShiftUp = true; - SkipGears = true; + DataBus = dataBus; TransmissionRatio = runData.AxleGearData.AxleGear.Ratio * (runData.AngledriveData?.Angledrive.Ratio ?? 1.0) / runData.VehicleData.DynamicTyreRadius; - //var minEngineSpeed = (runData.EngineData.FullLoadCurves[0].RatedSpeed - runData.EngineData.IdleSpeed) * - // Constants.SimulationSettings.ClutchClosingSpeedNorm + runData.EngineData.IdleSpeed; + //var minEngineSpeed = (runData.EngineData.FullLoadCurves[0].RatedSpeed - runData.EngineData.IdleSpeed) * + // Constants.SimulationSettings.ClutchClosingSpeedNorm + runData.EngineData.IdleSpeed; - shiftStrategyParameters = runData.GearshiftParameters; - vehicleMass = runData.VehicleData.TotalVehicleMass; + + if (shiftStrategyParameters == null) { throw new VectoException("Parameters for shift strategy missing!"); } SetupVelocityDropPreprocessor(dataBus); - } + + DeRatedShiftpolygons = CalculateDeratedShiftLines(runData.ElectricMachinesData.First(x => x.Item1 == PowertrainPosition.BatteryElectricE2).Item2, + runData.GearboxData.InputData.Gears, runData.VehicleData.DynamicTyreRadius, + runData.AxleGearData.AxleGear.Ratio, runData.GearboxData.Type); + } private void SetupVelocityDropPreprocessor(IVehicleContainer dataBus) { @@ -104,8 +107,70 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } - public bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, - NewtonMeter inTorque, + #region Implementation of IShiftPolygonCalculator + + public ShiftPolygon ComputeDeclarationShiftPolygon(GearboxType gearboxType, int i, EngineFullLoadCurve engineDataFullLoadCurve, + IList<ITransmissionInputData> gearboxGears, CombustionEngineData engineData, double axlegearRatio, Meter dynamicTyreRadius, + ElectricMotorData electricMotorData = null) + { + return ComputeDeclarationShiftPolygon(i, gearboxGears, axlegearRatio, dynamicTyreRadius, electricMotorData, + null, shiftStrategyParameters.PEV_DownshiftMinSpeedFactor * electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve.RatedSpeed); + } + + + public ShiftPolygon ComputeDeclarationShiftPolygon(int i, + IList<ITransmissionInputData> gearboxGears, double axlegearRatio, + Meter dynamicTyreRadius, + ElectricMotorData electricMotorData, PerSecond downshiftMaxSpeed, PerSecond downshiftMinSpeed) + { + return DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, + electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve, electricMotorData.RatioADC, + gearboxGears, axlegearRatio, dynamicTyreRadius, downshiftMaxSpeed, downshiftMinSpeed); + } + + #endregion + + protected internal Dictionary<uint, ShiftPolygon> CalculateDeratedShiftLines(ElectricMotorData em, + IList<ITransmissionInputData> gearData, Meter rDyn, double axleGearRatio, GearboxType gearboxType) + { + var retVal = new Dictionary<uint, ShiftPolygon>(); + var emFld = em.EfficiencyData.VoltageLevels.First().FullLoadCurve; + var contTqFld = new ElectricMotorFullLoadCurve(new List<ElectricMotorFullLoadCurve.FullLoadEntry>() { + new ElectricMotorFullLoadCurve.FullLoadEntry() { + MotorSpeed = 0.RPMtoRad(), + FullDriveTorque = -em.ContinuousTorque, + FullGenerationTorque = em.ContinuousTorque + }, + new ElectricMotorFullLoadCurve.FullLoadEntry() { + MotorSpeed = 1.1 * emFld.MaxSpeed, + FullDriveTorque = -em.ContinuousTorque, + FullGenerationTorque = em.ContinuousTorque + } + }); + var limitedFld = AbstractSimulationDataAdapter.IntersectEMFullLoadCurves(emFld, contTqFld); + var limitedEm = new ElectricMotorData() { + EfficiencyData = new VoltageLevelData() { + VoltageLevels = new List<ElectricMotorVoltageLevelData>() { + new ElectricMotorVoltageLevelData() { + FullLoadCurve = limitedFld + } + } + } + }; + for (var i = 0u; i < gearData.Count; i++) { + var shiftPolygon = ComputeDeclarationShiftPolygon((int)i, + gearData, axleGearRatio, + rDyn, limitedEm, shiftStrategyParameters.PEV_DeRatedDownshiftSpeedFactor * emFld.RatedSpeed, + shiftStrategyParameters.PEV_DownshiftMinSpeedFactor * emFld.RatedSpeed); + retVal[i + 1] = shiftPolygon; + } + + return retVal; + } + + #region Implementation of IShiftStrategy + + public bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition gear, Second lastShiftTime, IResponse response) { CheckGearshiftRequired = true; @@ -115,15 +180,26 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return retVal; } - private bool DoCheckShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, - PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition gear, - Second lastShiftTime, IResponse response) + private bool DoCheckShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition gear, Second lastShiftTime, IResponse response) { // no shift when vehicle stands if (DataBus.VehicleInfo.VehicleStopped) { return false; } + if (DriveOffStandstill && + DataBus.VehicleInfo.VehicleSpeed.IsGreaterOrEqual(DataBus.DrivingCycleInfo.TargetSpeed)) { + DriveOffStandstill = false; + } + if (DriveOffStandstill && response.ElectricMotor.AngularVelocity.IsGreater(VoltageLevels.VoltageLevels.First().FullLoadCurve.NP80low)) { + DriveOffStandstill = false; + } + + if (DriveOffStandstill && response.ElectricMotor.TorqueRequestEmMap != null && + response.ElectricMotor.TorqueRequestEmMap.IsEqual(response.ElectricMotor.MaxDriveTorqueEM)) { + DriveOffStandstill = false; + } + // emergency shift to not stall the engine ------------------------ while (GearList.HasSuccessor(_nextGear) && SpeedTooHighForEngine(_nextGear, inAngularVelocity / GearboxModelData.Gears[gear.Gear].Ratio)) { @@ -132,6 +208,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (_nextGear != gear) { return true; } + if (DriveOffStandstill) { + return false; + } // normal shift when all requirements are fullfilled ------------------ var minimumShiftTimePassed = (lastShiftTime + GearshiftParams.TimeBetweenGearshifts).IsSmallerOrEqual(absTime); @@ -155,7 +234,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return _nextGear != gear; } - protected virtual GearshiftPosition CheckUpshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response) + private GearshiftPosition CheckUpshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response) { // if the driver's intention is _not_ to accelerate or drive along then don't upshift if (DataBus.DriverInfo.DriverBehavior != DrivingBehavior.Accelerating && DataBus.DriverInfo.DriverBehavior != DrivingBehavior.Driving) { @@ -165,23 +244,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return currentGear; } var nextGear = DoCheckUpshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, currentGear, response); - if (nextGear.Equals(currentGear)) { + if (!nextGear.Equals(currentGear)) { return nextGear; } - // estimate acceleration for selected gear - if (EstimateAccelerationForGear(nextGear, outAngularVelocity).IsSmaller(GearshiftParams.UpshiftMinAcceleration)) { - // if less than 0.1 for next gear, don't shift - if (GearList.Distance(nextGear, currentGear) == 1) { - return currentGear; - } - // if a gear is skipped but acceleration is less than 0.1, try for next gear. if acceleration is still below 0.1 don't shift! - if (nextGear > currentGear && - EstimateAccelerationForGear(GearList.Successor(currentGear), outAngularVelocity) - .IsSmaller(GearshiftParams.UpshiftMinAcceleration)) { - return currentGear; - } - nextGear = GearList.Successor(currentGear); + // early up shift to higher gear --------------------------------------- + if (GearList.HasSuccessor(currentGear)) { + nextGear = CheckEarlyUpshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response); } return nextGear; @@ -189,127 +258,88 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl protected virtual GearshiftPosition DoCheckUpshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, - GearshiftPosition currentGear, IResponse response1) + GearshiftPosition currentGear, IResponse r) { + var nextGear = currentGear; // upshift - if (IsAboveUpShiftCurve(currentGear, inTorque, inAngularVelocity)) { - currentGear = GearList.Successor(currentGear); + if (IsAboveUpShiftCurve(currentGear, inTorque, inAngularVelocity, r.ElectricMotor.DeRatingActive)) { + nextGear = GearList.Successor(currentGear); - while (SkipGears && GearList.HasSuccessor(currentGear)) { - currentGear = GearList.Successor(currentGear); - var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); + while (GearList.HasSuccessor(nextGear)) { + // check skip gears + nextGear = GearList.Successor(nextGear); + var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, nextGear); - inAngularVelocity = - response.ElectricMotor - .AngularVelocity; //ModelData.Gears[currentGear].Ratio * outAngularVelocity; + inAngularVelocity = response.ElectricMotor.AngularVelocity; inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity; var maxTorque = VectoMath.Min(-response.ElectricMotor.MaxDriveTorque, - !currentGear.Equals(GearList.First()) - ? GearboxModelData.Gears[currentGear.Gear].ShiftPolygon + !nextGear.Equals(GearList.First()) + ? GearboxModelData.Gears[nextGear.Gear].ShiftPolygon .InterpolateDownshift(response.Engine.EngineSpeed) : double.MaxValue.SI<NewtonMeter>()); var reserve = 1 - inTorque / maxTorque; if (reserve >= 0 /*ModelData.TorqueReserve */ && - IsAboveDownShiftCurve(currentGear, inTorque, inAngularVelocity)) { + IsAboveDownShiftCurve(nextGear, inTorque, inAngularVelocity, r.ElectricMotor.DeRatingActive)) { continue; } - currentGear = GearList.Predecessor(currentGear); + nextGear = GearList.Predecessor(nextGear); break; } } - // early up shift to higher gear --------------------------------------- - if (EarlyShiftUp && GearList.HasSuccessor(currentGear)) { - currentGear = CheckEarlyUpshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response1); - } - - return currentGear; + return nextGear; } - protected virtual GearshiftPosition CheckEarlyUpshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse response1) + protected virtual GearshiftPosition CheckEarlyUpshift(Second absTime, Second dt, NewtonMeter outTorque, + PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse resp) { - //var minFcGear = currentGear; - //var minFc = double.MaxValue; - //IResponse minFCResponse = null; - //var fcCurrent = double.NaN; - - //var fcUpshiftPossible = true; - - // no eff-shift if torque demand is close to ICE drag load - //if (response1.Engine.TorqueOutDemand.IsSmaller(DeclarationData.GearboxTCU.DragMarginFactor * fld[currentGear].DragLoadStationaryTorque(response1.Engine.EngineSpeed))) { - // return currentGear; - //} - - var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); - if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION)) { + var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, + DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); + if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION) + ) { return currentGear; } var vDrop = DataBus.VehicleInfo.VehicleSpeed - estimatedVelocityPostShift; - var vehicleSpeedPostShift = DataBus.VehicleInfo.VehicleSpeed - vDrop * shiftStrategyParameters.VelocityDropFactor; + var vehicleSpeedPostShift = + DataBus.VehicleInfo.VehicleSpeed - vDrop * shiftStrategyParameters.VelocityDropFactor; - var totalTransmissionRatio = DataBus.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2).ElectricMotorSpeed / DataBus.VehicleInfo.VehicleSpeed; - //var totalTransmissionRatio = outAngularVelocity / DataBus.VehicleSpeed; + var totalTransmissionRatio = + DataBus.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2).ElectricMotorSpeed / + DataBus.VehicleInfo.VehicleSpeed; var results = new List<Tuple<GearshiftPosition, double>>(); - foreach (var tryNextGear in GearList.IterateGears(GearList.Successor(currentGear), GearList.Successor(currentGear, (uint)shiftStrategyParameters.AllowedGearRangeFC))) { - - //if (tryNextGear > GearboxModelData.Gears.Keys.Max() - // /*|| !(ModelData.Gears[tryNextGear].Ratio < shiftStrategyParameters.RatioEarlyUpshiftFC)*/) { - // continue; - //} - - //fcUpshiftPossible = true; - - //var response = RequestDryRunWithGear(absTime, dt, vehicleSpeedPostShift, DataBus.DriverAcceleration, tryNextGear); + foreach (var tryNextGear in GearList.IterateGears(GearList.Successor(currentGear), + GearList.Successor(currentGear, (uint)shiftStrategyParameters.AllowedGearRangeFC))) { var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tryNextGear); var inAngularVelocity = GearboxModelData.Gears[tryNextGear.Gear].Ratio * outAngularVelocity; var inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity; - // if next gear supplied enough power reserve: take it - // otherwise take - if (IsBelowDownShiftCurve(tryNextGear, inTorque, inAngularVelocity)) { + if (IsBelowDownShiftCurve(tryNextGear, inTorque, inAngularVelocity, resp.ElectricMotor.DeRatingActive)) { continue; } - var estimatedEngineSpeed = (vehicleSpeedPostShift * (totalTransmissionRatio / GearboxModelData.Gears[currentGear.Gear].Ratio * GearboxModelData.Gears[tryNextGear.Gear].Ratio)).Cast<PerSecond>(); + var estimatedEngineSpeed = (vehicleSpeedPostShift * (totalTransmissionRatio / + GearboxModelData.Gears[currentGear.Gear].Ratio * + GearboxModelData.Gears[tryNextGear.Gear].Ratio)) + .Cast<PerSecond>(); if (estimatedEngineSpeed.IsSmaller(shiftStrategyParameters.MinEngineSpeedPostUpshift)) { continue; } - //var pNextGearMax = DataBus.Engine Info.EngineStationaryFullPower(estimatedEngineSpeed); - - //if (!response.Engine.PowerRequest.IsSmaller(pNextGearMax)) { - // continue; - //} - var fullLoadPower = -response.ElectricMotor.MaxDriveTorque * response.ElectricMotor.AngularVelocity; var reserve = 1 - response.ElectricMotor.PowerRequest / fullLoadPower; + if (reserve < 0) { + continue; + } - //var reserve = 1 - response.EngineTorqueDemandTotal / response.EngineStationaryFullLoadTorque; - - - //if (double.IsNaN(fcCurrent)) { - // //var responseCurrent = RequestDryRunWithGear(absTime, dt, DataBus.VehicleSpeed, DataBus.DriverAcceleration, currentGear); - // var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); - // fcCurrent = GetFCRating(responseCurrent); - //} - var fcNext = GetFCRating(response); results.Add(Tuple.Create(tryNextGear, fcNext)); - //if (reserve < GearshiftParams.TorqueReserve || - // !fcNext.IsGreater(fcCurrent * shiftStrategyParameters.RatingFactorCurrentGear) || !fcNext.IsSmaller(minFc)) { - // continue; - //} - - //minFcGear = tryNextGear; - //minFc = fcNext; - //minFCResponse = response; } if (results.Count == 0) { @@ -330,183 +360,127 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } return currentGear; - //return fcUpshiftPossible - // ? currentGear - // : base.CheckEarlyUpshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response1); } - - private double GetFCRating(ResponseDryRun response)//PerSecond engineSpeed, NewtonMeter tqCurrent) - { - var currentGear = response.Gearbox.Gear; - - var maxGenTorque = VectoMath.Min(GearboxModelData.Gears[currentGear.Gear].MaxTorque, response.ElectricMotor.MaxRecuperationTorque); - var maxDriveTorque = GearboxModelData.Gears[currentGear.Gear].MaxTorque != null - ? VectoMath.Max(-GearboxModelData.Gears[currentGear.Gear].MaxTorque, response.ElectricMotor.MaxDriveTorque) - : response.ElectricMotor.MaxDriveTorque; - var tqCurrent = (response.ElectricMotor.ElectricMotorPowerMech / response.ElectricMotor.AngularVelocity); - if (!tqCurrent.IsBetween(maxDriveTorque, maxGenTorque)) { - return double.NaN; + private GearshiftPosition CheckDownshift(Second absTime, Second dt, NewtonMeter outTorque, + PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, + GearshiftPosition currentGear, IResponse response) + { + if ((absTime - _gearbox.LastUpshift).IsSmaller(GearshiftParams.DownshiftAfterUpshiftDelay)) { + return currentGear; } - var engineSpeed = response.ElectricMotor.AngularVelocity; - - var fcCurRes = VoltageLevels.LookupElectricPower(DataBus.BatteryInfo.InternalVoltage, engineSpeed, tqCurrent, true); - if (fcCurRes.Extrapolated) { - Log.Warn( - "EffShift Strategy: Extrapolation of power consumption for current gear! n: {0}, Tq: {1}", - engineSpeed, tqCurrent); + if (!GearList.HasPredecessor(currentGear)) { + return currentGear; } - return fcCurRes.ElectricalPower.Value(); - } + if (response.ElectricMotor.DeRatingActive) { + } + // check with shiftline + if (response.ElectricMotor.TorqueRequestEmMap != null && IsBelowDownShiftCurve(currentGear, + response.ElectricMotor.TorqueRequestEmMap, + response.ElectricMotor.AngularVelocity, response.ElectricMotor.DeRatingActive)) { + if (DataBus.DriverInfo.DriverBehavior == DrivingBehavior.Braking) { + var brakingGear = SelectBrakingGear(currentGear, response); + return brakingGear; + } - protected ResponseDryRun RequestDryRunWithGear( - Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition tryNextGear) - { - LogEnabled = false; - TestContainerGbx.Disengaged = false; - TestContainerGbx.Gear = tryNextGear; - - TestContainer.GearboxOutPort.Initialize(outTorque, outAngularVelocity); - var response = (ResponseDryRun)TestContainer.GearboxOutPort.Request( - 0.SI<Second>(), dt, outTorque, outAngularVelocity, true); - LogEnabled = true; - return response; - } - - protected MeterPerSquareSecond EstimateAccelerationForGear(GearshiftPosition gear, PerSecond gbxAngularVelocityOut) - { - if (!gear.Engaged || !GearList.Contains(gear)) { - throw new VectoSimulationException("EstimateAccelerationForGear: invalid gear: {0}", gear); - } + var nextGear = GearList.Predecessor(currentGear); - var vehicleSpeed = DataBus.VehicleInfo.VehicleSpeed; + while (GearList.HasPredecessor(nextGear)) { + // check skip gears + nextGear = GearList.Predecessor(nextGear); + var resp = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, nextGear); - var nextEngineSpeed = gbxAngularVelocityOut * GearboxModelData.Gears[gear.Gear].Ratio; - var maxEnginePower = -(VoltageLevels.FullLoadDriveTorque(DataBus.BatteryInfo.InternalVoltage, nextEngineSpeed) * nextEngineSpeed); - - var avgSlope = - ((DataBus.DrivingCycleInfo.CycleLookAhead(Constants.SimulationSettings.GearboxLookaheadForAccelerationEstimation).Altitude - - DataBus.DrivingCycleInfo.Altitude) / Constants.SimulationSettings.GearboxLookaheadForAccelerationEstimation).Value().SI<Radian>(); + inAngularVelocity = resp.ElectricMotor.AngularVelocity; + inTorque = resp.ElectricMotor.PowerRequest / inAngularVelocity; - var airDragLoss = DataBus.VehicleInfo.AirDragResistance(vehicleSpeed, vehicleSpeed) * DataBus.VehicleInfo.VehicleSpeed; - var rollResistanceLoss = DataBus.VehicleInfo.RollingResistance(avgSlope) * DataBus.VehicleInfo.VehicleSpeed; - var gearboxLoss = GearboxModelData.Gears[gear.Gear].LossMap.GetTorqueLoss(gbxAngularVelocityOut, - maxEnginePower / nextEngineSpeed * GearboxModelData.Gears[gear.Gear].Ratio).Value * nextEngineSpeed; - //DataBus.GearboxLoss(); - var slopeLoss = DataBus.VehicleInfo.SlopeResistance(avgSlope) * DataBus.VehicleInfo.VehicleSpeed; - var axleLoss = DataBus.AxlegearInfo.AxlegearLoss(); + var maxTorque = VectoMath.Min(-resp.ElectricMotor.MaxDriveTorque, + !nextGear.Equals(GearList.First()) + ? GearboxModelData.Gears[nextGear.Gear].ShiftPolygon + .InterpolateDownshift(resp.Engine.EngineSpeed) + : double.MaxValue.SI<NewtonMeter>()); + var reserve = 1 - inTorque / maxTorque; - var accelerationPower = maxEnginePower - gearboxLoss - axleLoss - airDragLoss - rollResistanceLoss - slopeLoss; + if (reserve >= 0 /*ModelData.TorqueReserve */ && + IsBelowDownShiftCurve(nextGear, inTorque, inAngularVelocity, resp.ElectricMotor.DeRatingActive)) { + continue; + } - var acceleration = accelerationPower / DataBus.VehicleInfo.VehicleSpeed / (DataBus.VehicleInfo.TotalMass + DataBus.WheelsInfo.ReducedMassWheels); + nextGear = GearList.Successor(nextGear); + break; + } - return acceleration.Cast<MeterPerSquareSecond>(); - } + return nextGear; + } - protected virtual GearshiftPosition CheckDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response) - { - if ((absTime - _gearbox.LastUpshift).IsSmaller(GearshiftParams.DownshiftAfterUpshiftDelay)) { + if (response.ElectricMotor.TorqueRequestEmMap != null && response.ElectricMotor.TorqueRequestEmMap.IsEqual( + response.ElectricMotor.MaxRecuperationTorqueEM, + response.ElectricMotor.MaxRecuperationTorqueEM * 0.1)) { + // no early downshift when close to max recuperation line return currentGear; } - return DoCheckDownshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, currentGear, response); - } - - protected virtual GearshiftPosition DoCheckDownshift( - Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, - NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response) - { - var nextGear = BaseDoCheckDownshift( - absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, currentGear, response); - if (nextGear.Equals(currentGear) && !currentGear.Equals(GearList.First())) { - nextGear = CheckEarlyDownshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response); - } - return nextGear; + // check early downshift + return CheckEarlyDownshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response); } - protected virtual GearshiftPosition BaseDoCheckDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, - NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response) + private GearshiftPosition SelectBrakingGear(GearshiftPosition currentGear, IResponse response) { - // down shift - if (IsBelowDownShiftCurve(currentGear, inTorque, inAngularVelocity)) { - currentGear = GearList.Predecessor(currentGear); - //while (SkipGears && currentGear > 1) { - // currentGear--; - // var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); - - // inAngularVelocity = ModelData.Gears[currentGear].Ratio * outAngularVelocity; - // inTorque = response.ClutchPowerRequest / inAngularVelocity; - // var maxTorque = VectoMath.Min(response.DynamicFullLoadPower / ((DataBus.EngineSpeed + response.EngineSpeed) / 2), - // currentGear > 1 - // ? ModelData.Gears[currentGear].ShiftPolygon.InterpolateDownshift(response.EngineSpeed) - // : double.MaxValue.SI<NewtonMeter>()); - // var reserve = maxTorque.IsEqual(0) ? -1 : (1 - inTorque / maxTorque).Value(); - // if (reserve >= ModelData.TorqueReserve && IsBelowUpShiftCurve(currentGear, inTorque, inAngularVelocity)) { - // continue; - // } - // currentGear++; - // break; - //} - } - return currentGear; + var tmpGear = new GearshiftPosition(currentGear.Gear, currentGear.TorqueConverterLocked); + var candidates = new Dictionary<GearshiftPosition, PerSecond>(); + var gbxOutSpeed = response.Engine.EngineSpeed / + GearboxModelData.Gears[tmpGear.Gear].Ratio; + var firstGear = GearList.Predecessor(currentGear, 1); + var lastGear = GearList.Predecessor(currentGear, (uint)GearshiftParams.AllowedGearRangeFC); + foreach (var gear in GearList.IterateGears(firstGear, lastGear)) { + var ratio = gear.IsLockedGear() + ? GearboxModelData.Gears[gear.Gear].Ratio + : GearboxModelData.Gears[gear.Gear].TorqueConverterRatio; + candidates[gear] = gbxOutSpeed * ratio; + } + + var ratedSpeed = VoltageLevels.VoltageLevels.First().FullLoadCurve.RatedSpeed; + var maxSpeedNorm = VoltageLevels.MaxSpeed / ratedSpeed; + var targetMotor = (shiftStrategyParameters.PEV_TargetSpeedBrakeNorm * (maxSpeedNorm - 1) + 1) * ratedSpeed; + + if (candidates.Any(x => x.Value > targetMotor && x.Value < VoltageLevels.MaxSpeed)) { + var best = candidates.Where(x => x.Value > targetMotor && x.Value < VoltageLevels.MaxSpeed) + .OrderBy(x => x.Value).First(); + return best.Key; + } + + var retVal = candidates.Where(x => x.Value < VoltageLevels.MaxSpeed).MaxBy(x => x.Value).Key; + return retVal; } - - protected virtual GearshiftPosition CheckEarlyDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse response1) + protected virtual GearshiftPosition CheckEarlyDownshift(Second absTime, Second dt, NewtonMeter outTorque, + PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse resp) { - //var minFcGear = currentGear; - //var minFc = double.MaxValue * Math.Sign(outTorque.Value()) ; - //var fcCurrent = double.NaN; - - var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); - if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION)) { + var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, + DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); + if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION) + ) { return currentGear; } - // no eff-shift if torque demand is close to ICE drag load - //if (response1.Engine.TorqueOutDemand.IsSmaller(DeclarationData.GearboxTCU.DragMarginFactor * fld[currentGear].DragLoadStationaryTorque(response1.Engine.EngineSpeed))) { - // return currentGear; - //} - var results = new List<Tuple<GearshiftPosition, double>>(); - foreach (var tryNextGear in GearList.IterateGears(GearList.Predecessor(currentGear), GearList.Predecessor(currentGear, (uint)shiftStrategyParameters.AllowedGearRangeFC))) { - - //if (tryNextGear < 1 /*|| !(ModelData.Gears[tryNextGear].Ratio <= shiftStrategyParameters.RatioEarlyDownshiftFC)*/) { - // continue; - //} + foreach (var tryNextGear in GearList.IterateGears(GearList.Predecessor(currentGear), + GearList.Predecessor(currentGear, (uint)shiftStrategyParameters.AllowedGearRangeFC))) { var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tryNextGear); - - //var response = RequestDryRunWithGear(absTime, dt, DataBus.VehicleSpeed, DataBus.DriverAcceleration, tryNextGear); - var inAngularVelocity = GearboxModelData.Gears[tryNextGear.Gear].Ratio * outAngularVelocity; var inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity; - if (IsAboveUpShiftCurve(tryNextGear, inTorque, inAngularVelocity)) { + if (IsAboveUpShiftCurve(tryNextGear, inTorque, inAngularVelocity, response.ElectricMotor.DeRatingActive)) { continue; } - //if (double.IsNaN(fcCurrent)) { - // var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); - - // //var responseCurrent = RequestDryRunWithGear(absTime, dt, DataBus.VehicleSpeed, DataBus.DriverAcceleration, currentGear); - // fcCurrent = GetFCRating(responseCurrent); - //} var fcNext = GetFCRating(response); - results.Add(Tuple.Create(tryNextGear,fcNext)); - - //if (!fcNext.IsGreater(fcCurrent * shiftStrategyParameters.RatingFactorCurrentGear) || - // !fcNext.IsGreater(minFc)) { - // continue; - //} - - //minFcGear = tryNextGear; - //minFc = fcNext; + results.Add(Tuple.Create(tryNextGear, fcNext)); } if (results.Count == 0) { @@ -515,22 +489,59 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); var fcCurrent = GetFCRating(responseCurrent); - var minFc = results.MinBy(x => x.Item2); - var ratingFactor = outTorque < 0 ? 1 / shiftStrategyParameters.RatingFactorCurrentGear : shiftStrategyParameters.RatingFactorCurrentGear; - if (minFc.Item2.IsGreater(fcCurrent * ratingFactor)) { return minFc.Item1; } - + return currentGear; } + protected double GetFCRating(ResponseDryRun response)//PerSecond engineSpeed, NewtonMeter tqCurrent) + { + var currentGear = response.Gearbox.Gear; + + var maxGenTorque = VectoMath.Min(GearboxModelData.Gears[currentGear.Gear].MaxTorque, response.ElectricMotor.MaxRecuperationTorque); + var maxDriveTorque = GearboxModelData.Gears[currentGear.Gear].MaxTorque != null + ? VectoMath.Max(-GearboxModelData.Gears[currentGear.Gear].MaxTorque, response.ElectricMotor.MaxDriveTorque) + : response.ElectricMotor.MaxDriveTorque; + + var tqCurrent = (response.ElectricMotor.ElectricMotorPowerMech / response.ElectricMotor.AngularVelocity); + if (!tqCurrent.IsBetween(maxDriveTorque, maxGenTorque)) { + return double.NaN; + } + var engineSpeed = response.ElectricMotor.AngularVelocity; + + + var fcCurRes = VoltageLevels.LookupElectricPower(DataBus.BatteryInfo.InternalVoltage, engineSpeed, tqCurrent, true); + if (fcCurRes.Extrapolated) { + Log.Warn( + "EffShift Strategy: Extrapolation of power consumption for current gear! n: {0}, Tq: {1}", + engineSpeed, tqCurrent); + } + return fcCurRes.ElectricalPower.Value(); + } + + protected ResponseDryRun RequestDryRunWithGear( + Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition tryNextGear) + { + LogEnabled = false; + TestContainerGbx.Disengaged = false; + TestContainerGbx.Gear = tryNextGear; + + TestContainer.GearboxOutPort.Initialize(outTorque, outAngularVelocity); + var response = (ResponseDryRun)TestContainer.GearboxOutPort.Request( + 0.SI<Second>(), dt, outTorque, outAngularVelocity, true); + LogEnabled = true; + return response; + } + + public GearshiftPosition InitGear(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) { if (DataBus.VehicleInfo.VehicleSpeed.IsEqual(0)) { @@ -545,7 +556,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var inTorque = response.ElectricMotor.PowerRequest / inAngularSpeed; // if in shift curve and torque reserve is provided: return the current gear - if (!IsBelowDownShiftCurve(gear, inTorque, inAngularSpeed) && !IsAboveUpShiftCurve(gear, inTorque, inAngularSpeed)) { + if (!IsBelowDownShiftCurve(gear, inTorque, inAngularSpeed, false) && !IsAboveUpShiftCurve(gear, inTorque, inAngularSpeed, false)) { _nextGear = gear; return gear; } @@ -557,7 +568,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl private GearshiftPosition InitStartGear(Second absTime, NewtonMeter outTorque, PerSecond outAngularVelocity) { - var emSpeeds = new Dictionary<GearshiftPosition, Tuple<PerSecond, PerSecond>>(); + DriveOffStandstill = true; + + var emSpeeds = new Dictionary<GearshiftPosition, Tuple<PerSecond, PerSecond, double>>(); foreach (var gear in GearList.Reverse()) { //for (var gear = (uint)GearboxModelData.Gears.Count; gear >= 1; gear--) { @@ -571,15 +584,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var response = _gearbox.Initialize(absTime, gear, outTorque, outAngularVelocity); var fullLoadPower = -(response.ElectricMotor.MaxDriveTorque * response.ElectricMotor.AngularVelocity); - //.DynamicFullLoadPower; //EnginePowerRequest - response.DeltaFullLoad; - var reserve = 1 - response.ElectricMotor.PowerRequest / fullLoadPower; + //.DynamicFullLoadPower; //EnginePowerRequest - response.DeltaFullLoad; + var reserve = 1 - response.ElectricMotor.TorqueRequestEmMap / response.ElectricMotor.MaxDriveTorqueEM; - if (reserve >= GearshiftParams.StartTorqueReserve) { + var isBelowDownshift = gear.Gear > 1 && + IsBelowDownshiftCurve(GearboxModelData.Gears[gear.Gear].ShiftPolygon, response.ElectricMotor.TorqueRequest, + response.ElectricMotor.AngularVelocity); + + if (reserve >= GearshiftParams.StartTorqueReserve && !isBelowDownshift) { //_nextGear = gear; //return gear; emSpeeds[gear] = Tuple.Create(response.ElectricMotor.AngularVelocity, (GearshiftParams.StartSpeed * TransmissionRatio * GearboxModelData.Gears[gear.Gear].Ratio) - .Cast<PerSecond>()); + .Cast<PerSecond>(), (response.ElectricMotor.ElectricMotorPowerMech / response.ElectricSystem.RESSPowerDemand).Value()); } } @@ -592,33 +609,84 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return _nextGear; } - protected bool IsBelowDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed) + + protected bool IsBelowDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed, + bool deRatingActive) { if (!GearList.HasPredecessor(gear)) { return false; } - return GearboxModelData.Gears[gear.Gear].ShiftPolygon.IsBelowDownshiftCurve(inTorque, inEngineSpeed); + + var shiftPolygon = GetShiftpolygon(gear, deRatingActive); + return IsBelowDownshiftCurve(shiftPolygon, inTorque, inEngineSpeed); } - protected bool IsAboveDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed) + + + protected bool IsAboveDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed, + bool deRatingActive) { if (!GearList.HasPredecessor(gear)) { return true; } - return GearboxModelData.Gears[gear.Gear].ShiftPolygon.IsAboveDownshiftCurve(inTorque, inEngineSpeed); + var shiftPolygon = GetShiftpolygon(gear, deRatingActive); + + return IsAboveDownshiftCurve(shiftPolygon, inTorque, inEngineSpeed); } - protected bool IsAboveUpShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed) + protected bool IsAboveUpShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed, + bool deRatingActive) { if (!GearList.HasSuccessor(gear)) { return false; } - return GearboxModelData.Gears[gear.Gear].ShiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed); + + var shiftPolygon = GetShiftpolygon(gear, deRatingActive); + return shiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed); + } + + private ShiftPolygon GetShiftpolygon(GearshiftPosition gear, bool deRatingActive) + { + if (deRatingActive) { + return DeRatedShiftpolygons[gear.Gear]; + } + return GearboxModelData.Gears[gear.Gear].ShiftPolygon; + } + + protected bool IsBelowDownshiftCurve(ShiftPolygon shiftPolygon, NewtonMeter emTorque, PerSecond emSpeed) + { + foreach (var entry in shiftPolygon.Downshift.Pairwise(Tuple.Create)) { + if (!emTorque.IsBetween(entry.Item1.Torque, entry.Item2.Torque)) { + continue; + } + + if (ShiftPolygon.IsLeftOf(emSpeed, emTorque, entry)) { + + return true; + } + } + + return false; + } + + protected bool IsAboveDownshiftCurve(ShiftPolygon shiftPolygon, NewtonMeter emTorque, PerSecond emSpeed) + { + foreach (var entry in shiftPolygon.Downshift.Pairwise(Tuple.Create)) { + if (!emTorque.IsBetween(entry.Item1.Torque, entry.Item2.Torque)) { + continue; + } + + if (ShiftPolygon.IsRightOf(emSpeed, emTorque, entry)) { + + return true; + } + } + + return false; } public GearshiftPosition Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) { - while (GearList.HasSuccessor(_nextGear) && SpeedTooHighForEngine(_nextGear, outAngularVelocity)) { _nextGear = GearList.Successor(_nextGear); } @@ -626,7 +694,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return _nextGear; } - protected bool SpeedTooHighForEngine(GearshiftPosition gear, PerSecond outAngularSpeed) { return @@ -648,20 +715,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } public GearshiftPosition NextGear => _nextGear; - - public bool CheckGearshiftRequired { get; protected set; } public GearshiftPosition MaxStartGear { get; } - public void Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) { } public void WriteModalResults(IModalDataContainer container) { } - public ShiftPolygon ComputeDeclarationShiftPolygon(GearboxType gearboxType, int i, EngineFullLoadCurve engineDataFullLoadCurve, - IList<ITransmissionInputData> gearboxGears, CombustionEngineData engineData, double axlegearRatio, Meter dynamicTyreRadius, ElectricMotorData electricMotorData) - { - return DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve, electricMotorData.RatioADC, gearboxGears, axlegearRatio, dynamicTyreRadius); - } + #endregion + #region Implementation of IShiftPolygonCalculator + + + #endregion } + } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/StopStartCombustionEngine.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/StopStartCombustionEngine.cs index 662712a887f29562e50f6022bfa51100ae871a5a..1d5fc0d48906d1e4839b9bc10e5e2cdfaf20c7c3 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/StopStartCombustionEngine.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/StopStartCombustionEngine.cs @@ -13,7 +13,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { public class StopStartCombustionEngine : CombustionEngine { - protected double EngineStopStartUtilityFactor; private WattSecond EngineStartEnergy; public StopStartCombustionEngine( @@ -21,13 +20,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl container, modelData, pt1Disabled) { CombustionEngineOn = true; - EngineStopStartUtilityFactor = 1; // container.RunData.DriverData.EngineStopStart.UtilityFactorStandstill; var engineRampUpEnergy = Formulas.InertiaPower(modelData.IdleSpeed, 0.RPMtoRad(), modelData.Inertia, modelData.EngineStartTime) * modelData.EngineStartTime; var engineDragEnergy = VectoMath.Abs(modelData.FullLoadCurves[0].DragLoadStationaryTorque(modelData.IdleSpeed)) * modelData.IdleSpeed / 2.0 * modelData.EngineStartTime; - EngineStartEnergy = (engineRampUpEnergy + engineDragEnergy) * EngineStopStartUtilityFactor / DeclarationData.AlternaterEfficiency / DeclarationData.AlternaterEfficiency; + EngineStartEnergy = (engineRampUpEnergy + engineDragEnergy) / DeclarationData.AlternatorEfficiency / DeclarationData.AlternatorEfficiency; } public override bool CombustionEngineOn { get; set; } @@ -151,7 +149,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl avgRampUpSpeed * 0.5.SI<Second>(); container[ModalResultField.P_ice_start] = - (EngineStartEnergy + (engineRampUpEnergy + engineDragEnergy) * EngineStopStartUtilityFactor) / + (EngineStartEnergy + (engineRampUpEnergy + engineDragEnergy)) / CurrentState.dt; } else { container[ModalResultField.P_ice_start] = 0.SI<Watt>(); @@ -207,35 +205,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl //fcAAUX = advancedAux.AAuxFuelConsumption; } - - var result = fuel.ConsumptionMap.GetFuelConsumption(auxDemandTq, ModelData.IdleSpeed); - - var fcESS = result.Value * (1 - EngineStopStartUtilityFactor) * fuel.FuelData.HeatingValueCorrection * WHTCCorrectionFactor(fuel.FuelData); + var fcESS = fcWHTC; var fcFinal = fcESS; container[ModalResultField.FCMap, fuel.FuelData] = fc; container[ModalResultField.FCNCVc, fuel.FuelData] = fcNCVcorr; container[ModalResultField.FCWHTCc, fuel.FuelData] = fcWHTC; //container[ModalResultField.FCAAUX, fuel.FuelData] = fcAAUX; - container[ModalResultField.FCICEStopStart, fuel.FuelData] = fcESS; + //container[ModalResultField.FCICEStopStart, fuel.FuelData] = fcESS; container[ModalResultField.FCFinal, fuel.FuelData] = fcFinal; } } protected virtual void WriteWHRPowerEngineOff(IModalDataContainer container, PerSecond engineSpeed, NewtonMeter engineTorque) { - var pWHRelMap = 0.SI<Watt>(); - var pWHRelCorr = 0.SI<Watt>(); - var pWHRmechMap = 0.SI<Watt>(); - var pWHRmechCorr = 0.SI<Watt>(); - GetWHRPower(ModelData.ElectricalWHR, engineSpeed, engineTorque, ref pWHRelMap, ref pWHRelCorr); - GetWHRPower(ModelData.MechanicalWHR, engineSpeed, engineTorque, ref pWHRmechMap, ref pWHRmechCorr); - - container[ModalResultField.P_WHR_el_map] = (1 - EngineStopStartUtilityFactor) * pWHRelMap; - container[ModalResultField.P_WHR_el_corr] = (1 - EngineStopStartUtilityFactor) * pWHRelCorr; - - container[ModalResultField.P_WHR_mech_map] = (1 - EngineStopStartUtilityFactor) * pWHRmechMap; - container[ModalResultField.P_WHR_mech_corr] = (1 - EngineStopStartUtilityFactor) * pWHRmechCorr; + container[ModalResultField.P_WHR_el_map] = 0.SI<Watt>(); + container[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + + container[ModalResultField.P_WHR_mech_map] = 0.SI<Watt>(); + container[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); } } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs index 0b2446c82e25aebf81051157b2221534d6971136..79f9e7d481a0897d5db65904b9ef073cf6b4d665 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs @@ -561,7 +561,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies var engineDragEnergy = VectoMath.Abs(ModelData.EngineData.FullLoadCurves[0].DragLoadStationaryTorque(ModelData.EngineData.IdleSpeed)) * ModelData.EngineData.IdleSpeed / 2.0 * ModelData.EngineData.EngineStartTime; - IceRampUpCosts = (engineRampUpEnergy + engineDragEnergy).Value() / DeclarationData.AlternaterEfficiency / DeclarationData.AlternaterEfficiency; + IceRampUpCosts = (engineRampUpEnergy + engineDragEnergy).Value() / DeclarationData.AlternatorEfficiency / DeclarationData.AlternatorEfficiency; IceIdlingCosts = ModelData.EngineData.Fuels.Sum( x => (x.ConsumptionMap.GetFuelConsumptionValue(0.SI<NewtonMeter>(), ModelData.EngineData.IdleSpeed) diff --git a/VectoCore/VectoCore/OutputData/IModalDataContainer.cs b/VectoCore/VectoCore/OutputData/IModalDataContainer.cs index e6c5818d404b537e0f017917ec5b5feec15238f0..de403071ed65754226d3be8a24bcaba7d166a54d 100644 --- a/VectoCore/VectoCore/OutputData/IModalDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/IModalDataContainer.cs @@ -141,7 +141,7 @@ namespace TUGraz.VectoCore.OutputData WattSecond ElectricMotorMotLosses(PowertrainPosition emPos); WattSecond ElectricMotorTransmissionLosses(PowertrainPosition emPos); - double BatteryStartSoC(); + double REESSStartSoC(); double REESSEndSoC(); WattSecond REESSLoss(); @@ -178,18 +178,25 @@ namespace TUGraz.VectoCore.OutputData IFuelProperties Fuel { get; } KilogramPerWattSecond EngineLineCorrectionFactor { get; } KilogramPerWattSecond VehicleLine { get; } + KilogramPerSecond FC_ESS_H { get; } KilogramPerSecond FC_ESS_CORR_H { get; } KilogramPerSecond FC_BusAux_PS_CORR_H { get; } KilogramPerSecond FC_BusAux_ES_CORR_H { get; } KilogramPerSecond FC_WHR_CORR_H { get; } KilogramPerSecond FC_AUXHTR_H { get; } KilogramPerSecond FC_AUXHTR_H_CORR { get; } + KilogramPerSecond FC_REESS_SOC_H { get; } + KilogramPerSecond FC_REESS_SOC_CORR_H { get; } KilogramPerSecond FC_FINAL_H { get; } KilogramPerMeter FC_WHR_CORR_KM { get; } KilogramPerMeter FC_BusAux_PS_CORR_KM { get; } KilogramPerMeter FC_BusAux_ES_CORR_KM { get; } KilogramPerMeter FC_AUXHTR_KM { get; } KilogramPerMeter FC_AUXHTR_KM_CORR { get; } + KilogramPerMeter FC_REESS_SOC_KM { get; } + KilogramPerMeter FC_REESS_SOC_CORR_KM { get; } + KilogramPerMeter FC_ESS_KM { get; } + KilogramPerMeter FC_ESS_CORR_KM { get; } KilogramPerMeter FC_FINAL_KM { get; } VolumePerMeter FuelVolumePerMeter { get; } diff --git a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs index 0fa117b265497b9b15f8e9b5e4319ec796591d02..95e86c5eed594e47697decf9cd5c6391e390e53a 100644 --- a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs @@ -110,7 +110,7 @@ namespace TUGraz.VectoCore.OutputData public static readonly IList<ModalResultField> FuelConsumptionSignals = new[] { ModalResultField.FCMap, ModalResultField.FCNCVc, ModalResultField.FCWHTCc, // ModalResultField.FCAAUX, - ModalResultField.FCICEStopStart, ModalResultField.FCFinal + /*ModalResultField.FCICEStopStart,*/ ModalResultField.FCFinal }; private readonly Dictionary<String, SI> _timeIntegrals = new Dictionary<string, SI>(); @@ -222,7 +222,7 @@ namespace TUGraz.VectoCore.OutputData x => x.Field<bool>(ModalResultField.ICEOn.GetName()) ? new Point( x.Field<SI>(ModalResultField.P_ice_fcmap.GetName()).Value(), - x.Field<SI>(GetColumnName(fuel, ModalResultField.FCFinal)).Value()) + x.Field<SI>(GetColumnName(fuel, ModalResultField.FCWHTCc)).Value()) : null).Where(x => x != null && x.Y > 0), out var k, out var d, out var r); if (double.IsInfinity(k) || double.IsNaN(k)) { @@ -482,14 +482,14 @@ namespace TUGraz.VectoCore.OutputData return (integral / Duration.Value()).SI<PerSecond>(); } - public double BatteryStartSoC() + public double REESSStartSoC() { - return Data.AsEnumerable().Cast<DataRow>().First().Field<SI>(ModalResultField.REESSStateOfCharge.GetName()).Value() * 100; + return (Data.AsEnumerable().Cast<DataRow>().First().Field<SI>(ModalResultField.REESSStateOfCharge.GetName())?.Value() ?? 0) * 100; } public double REESSEndSoC() { - return Data.AsEnumerable().Cast<DataRow>().Last().Field<SI>(ModalResultField.REESSStateOfCharge.GetName()).Value() * 100; + return (Data.AsEnumerable().Cast<DataRow>().Last().Field<SI>(ModalResultField.REESSStateOfCharge.GetName())?.Value() ?? 0) * 100; } public WattSecond REESSLoss() @@ -518,7 +518,7 @@ namespace TUGraz.VectoCore.OutputData //TimeIntegral<Kilogram>(GetColumnName(fuel, ModalResultField.FCAAUX)); TimeIntegral<Kilogram>(GetColumnName(fuel, ModalResultField.FCMap)); - TimeIntegral<Kilogram>(GetColumnName(fuel, ModalResultField.FCICEStopStart)); + //TimeIntegral<Kilogram>(GetColumnName(fuel, ModalResultField.FCICEStopStart)); TimeIntegral<Kilogram>(GetColumnName(fuel, ModalResultField.FCFinal)); } diff --git a/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs b/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs index cc2188ed1d2563ecee06d06a91fc23f72a654228..318a00d48eebf347d3fe84639e92a650dee9ba82 100644 --- a/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs +++ b/VectoCore/VectoCore/OutputData/ModalDataPostprocessingCorrection.cs @@ -5,8 +5,11 @@ using TUGraz.VectoCommon.BusAuxiliaries; using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Models.BusAuxiliaries; +using TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.Pneumatics; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data; namespace TUGraz.VectoCore.OutputData { @@ -20,45 +23,13 @@ namespace TUGraz.VectoCore.OutputData var r = new CorrectedModalData(); var duration = modData.Duration; var distance = modData.Distance; - var essParams = runData.DriverData.EngineStopStart; + + SetMissingEnergyICEOFf(modData, r); - var entriesAuxICEStandstill = modData.GetValues(x => new - { - dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), - P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(), - P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(), - v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()), - IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName()) - }).Where(x => x.v != null && x.v.IsEqual(0) && !x.IceOn).ToList(); - var entriesAuxICEDriving = modData.GetValues(x => new { - dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), - P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(), - P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(), - v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()), - IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName()) - }).Where(x => x.v != null && !x.v.IsEqual(0) && !x.IceOn).ToList(); + SetWHRWork(modData, runData, r); - r.ICEOffTimeStandstill = entriesAuxICEStandstill.Sum(x => x.dt) ?? 0.SI<Second>(); - r.EnergyAuxICEOffStandstill = entriesAuxICEStandstill.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>(); - r.EnergyAuxICEOnStandstill = entriesAuxICEStandstill.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>(); - - r.ICEOffTimeDriving = entriesAuxICEDriving.Sum(x => x.dt) ?? 0.SI<Second>(); - r.EnergyAuxICEOffDriving = entriesAuxICEDriving.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>(); - r.EnergyPowerICEOnDriving = entriesAuxICEDriving.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>(); - - - r.WorkWHREl = modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_el_corr); - r.WorkWHRElMech = -r.WorkWHREl / DeclarationData.AlternaterEfficiency; - r.WorkWHRMech = -modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_mech_corr); - if (runData.BusAuxiliaries != null) { - var workBusAuxPSCompOff = modData.EnergyPneumaticCompressorPowerOff(); - var workBusAuxPSCompOn = modData.EnergyPneumaticCompressorAlwaysOn(); - var airBusAuxPSON = modData.AirGeneratedAlwaysOn(); - var deltaAir = modData.AirConsumed() - modData.AirGenerated(); - - var kAir = airBusAuxPSON.IsEqual(0) ? 0.SI(Unit.SI.Watt.Second.Per.Cubic.Meter) :(workBusAuxPSCompOn - workBusAuxPSCompOff) / (airBusAuxPSON - 0.SI<NormLiter>()); - r.WorkBusAuxPSCorr = (kAir * deltaAir).Cast<WattSecond>(); + SetBusAuxMissingPSWork(modData, runData, r); var workBusAuxES = modData.EnergyBusAuxESConsumed() - modData.EnergyBusAuxESGenerated(); r.WorkBusAuxESMech = workBusAuxES / @@ -70,73 +41,22 @@ namespace TUGraz.VectoCore.OutputData r.WorkBusAuxESMech = 0.SI<WattSecond>(); } - var engineWasteheatSum = modData.FuelData.Aggregate( - 0.SI<Joule>(), - (current, fuel) => current + modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel) * - fuel.LowerHeatingValueVecto); r.EnergyDCDCMissing = 0.SI<WattSecond>(); if (runData.BusAuxiliaries != null && runData.BusAuxiliaries.ElectricalUserInputsConfig.ConnectESToREESS) { - // either case C1, C2a, or C3a - var missingDCDCEnergy = modData.TimeIntegral<WattSecond>(ModalResultField.P_DCDC_missing); - if (runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorType == AlternatorType.Smart) { - // case C3a - if (runData.ElectricMachinesData.Count != 1) { - throw new VectoException("exactly 1 electric machine is required. got {0} ({1})", - runData.ElectricMachinesData.Count, - string.Join(",", runData.ElectricMachinesData.Select(x => x.Item1.ToString()))); - } - var emPos = runData.ElectricMachinesData.First().Item1; - var averageEmEfficiencyCharging = modData.ElectricMotorEfficiencyGenerate(emPos); - r.EnergyDCDCMissing = missingDCDCEnergy / - runData.BusAuxiliaries.ElectricalUserInputsConfig.DCDCEfficiency / - averageEmEfficiencyCharging; - } else { - // case C1, C2a - r.EnergyDCDCMissing = missingDCDCEnergy / DeclarationData.AlternaterEfficiency; - } + SetMissingDCDCEnergy(modData, runData, r); } - r.AuxHeaterDemand = modData.AuxHeaterDemandCalc == null - ? 0.SI<Joule>() - : modData.AuxHeaterDemandCalc(duration, engineWasteheatSum); + SetAuxHeaterDemand(modData, r, duration); + + SetReesCorrectionDemand(modData, runData, r); var kilogramCO2PerMeter = 0.SI<KilogramPerMeter>(); var firstFuel = true; foreach (var fuel in modData.FuelData) { - var engFuel = runData.EngineData.Fuels.First(x => x.FuelData.Equals(fuel)); - var f = new FuelConsumptionCorrection(); - f.Fuel = fuel; - f.Distance = distance != null && distance.IsGreater(0) ? distance : null; - f.Duration = duration != null && duration.IsGreater(0) ? duration : null; - - f.EngineLineCorrectionFactor = modData.EngineLineCorrectionFactor(fuel); - f.VehicleLine = modData.VehicleLineSlope(fuel); - - f.FcModSum = modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel); - - var fcIceOnAuxStandstill = engFuel.ConsumptionMap.GetFuelConsumptionValue( - r.AvgAuxPowerICEOnStandstill / runData.EngineData.IdleSpeed, runData.EngineData.IdleSpeed); - var fcIceOnAuxDriving = engFuel.ConsumptionMap.GetFuelConsumptionValue( - r.AvgAuxPowerICEOnDriving / runData.EngineData.IdleSpeed, runData.EngineData.IdleSpeed); - - f.FcESS_EngineStart = f.EngineLineCorrectionFactor * modData.WorkEngineStart(); - f.FcESS_AuxStandstill_ICEOff = r.EnergyAuxICEOffStandstill * f.EngineLineCorrectionFactor * - essParams.UtilityFactorStandstill; - f.FcESS_AuxStandstill_ICEOn = fcIceOnAuxStandstill * r.ICEOffTimeStandstill * - (1 - essParams.UtilityFactorStandstill); - f.FcESS_AuxDriving_ICEOn = r.EnergyAuxICEOffDriving * f.EngineLineCorrectionFactor * - essParams.UtilityFactorDriving; - f.FcESS_AuxDriving_ICEOff = fcIceOnAuxDriving * r.ICEOffTimeDriving * - (1 - essParams.UtilityFactorDriving); - f.FcESS_DCDCMissing = - r.EnergyDCDCMissing * f.EngineLineCorrectionFactor * essParams.UtilityFactorStandstill; - - f.FcBusAuxPs = f.EngineLineCorrectionFactor * r.WorkBusAuxPSCorr; - f.FcBusAuxEs = f.EngineLineCorrectionFactor * r.WorkBusAuxESMech; - f.FcWHR = f.EngineLineCorrectionFactor * r.WorkWHR; - f.FcAuxHtr = 0.SI<Kilogram>(); + + var f = SetFuelConsumptionCorrection(modData, runData, r, fuel); if (firstFuel) { firstFuel = false; f.FcAuxHtr = r.AuxHeaterDemand / fuel.LowerHeatingValueVecto; @@ -146,7 +66,6 @@ namespace TUGraz.VectoCore.OutputData ? 0.SI<KilogramPerMeter>() : f.FcFinal * fuel.CO2PerFuelWeight / distance; - //-- r.FuelCorrection[fuel.FuelType] = f; } @@ -154,12 +73,225 @@ namespace TUGraz.VectoCore.OutputData return r; } + private void SetReesCorrectionDemand(IModalDataContainer modData, VectoRunData runData, + CorrectedModalData r) + { + var em = runData.ElectricMachinesData?.FirstOrDefault(); + + if (em != null) { + var deltaEReess = modData.TimeIntegral<WattSecond>(ModalResultField.P_reess_int.GetName()); + var startSoc = modData.REESSStartSoC(); + var endSoc = modData.REESSEndSoC(); + var emEff = 0.0; + if (endSoc < startSoc) { + var etaEmChg = modData.ElectricMotorEfficiencyGenerate(em.Item1); + var etaReessChg = (modData.WorkREESSChargeInternal() / modData.WorkREESSChargeTerminal()).Value(); + emEff = 1.0 / (etaEmChg * etaReessChg); + } + if (endSoc > startSoc) { + var etaEmDischg = modData.ElectricMotorEfficiencyDrive(em.Item1); + var etaReessDischg = modData.WorkREESSDischargeTerminal() / modData.WorkREESSDischargeInternal(); + emEff = etaEmDischg * etaReessDischg; + } + + r.DeltaEReessMech = -deltaEReess * emEff; + } else { + r.DeltaEReessMech = 0.SI<WattSecond>(); + } + } + + private static FuelConsumptionCorrection SetFuelConsumptionCorrection(IModalDataContainer modData, VectoRunData runData, + CorrectedModalData r, IFuelProperties fuel) + { + var duration = modData.Duration; + var distance = modData.Distance; + var essParams = runData.DriverData.EngineStopStart; + var engFuel = runData.EngineData.Fuels.First(x => x.FuelData.Equals(fuel)); + + var fcIceIdle = engFuel.ConsumptionMap.GetFuelConsumptionValue( + 0.SI<NewtonMeter>(), + runData.EngineData.IdleSpeed) * + engFuel.FuelConsumptionCorrectionFactor; + + + var engLine = modData.EngineLineCorrectionFactor(fuel); + var comp = + runData.BusAuxiliaries?.PneumaticUserInputsConfig.CompressorMap + .Interpolate(runData.EngineData.IdleSpeed); + + + + var f = new FuelConsumptionCorrection { + Fuel = fuel, + Distance = distance != null && distance.IsGreater(0) ? distance : null, + Duration = duration != null && duration.IsGreater(0) ? duration : null, + EngineLineCorrectionFactor = engLine, + VehicleLine = modData.VehicleLineSlope(fuel), + FcModSum = modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel), + FcESS_EngineStart = engLine * modData.WorkEngineStart(), + + FcESS_AuxStandstill_ICEOff = r.EnergyAuxICEOffStandstill * engLine * + essParams.UtilityFactorStandstill, + FcESS_AuxStandstill_ICEOn = + r.EnergyAuxICEOnStandstill * engLine * (1 - essParams.UtilityFactorStandstill) + + fcIceIdle * r.ICEOffTimeStandstill * (1 - essParams.UtilityFactorStandstill), + + FcESS_AuxDriving_ICEOff = r.EnergyAuxICEOffDriving * engLine * essParams.UtilityFactorDriving, + FcESS_AuxDriving_ICEOn = r.EnergyAuxICEOnDriving * engLine * (1 - essParams.UtilityFactorDriving) + + fcIceIdle * r.ICEOffTimeDriving * (1 - essParams.UtilityFactorDriving), + + FcESS_DCDCMissing = r.EnergyDCDCMissing * engLine, + FcBusAuxPSAirDemand = engLine * r.WorkBusAuxPSCorr, + + FcBusAuxPSDragICEOffStandstill = comp == null + ? 0.SI<Kilogram>() + : comp.PowerOff * r.ICEOffTimeStandstill * engLine * (1 - essParams.UtilityFactorStandstill), + FcBusAuxPSDragICEOffDriving = comp == null + ? 0.SI<Kilogram>() + : comp.PowerOff * r.ICEOffTimeDriving * engLine * (1 - essParams.UtilityFactorDriving), + FcREESSSoc = r.DeltaEReessMech * engLine, + FcBusAuxEs = engLine * r.WorkBusAuxESMech, + FcWHR = engLine * r.WorkWHR, + FcAuxHtr = 0.SI<Kilogram>() + }; + + return f; + } + + private static void SetAuxHeaterDemand(IModalDataContainer modData, CorrectedModalData r, Second duration) + { + var engineWasteheatSum = modData.FuelData.Aggregate( + 0.SI<Joule>(), + (current, fuel) => current + modData.TotalFuelConsumption(ModalResultField.FCFinal, fuel) * + fuel.LowerHeatingValueVecto); + r.AuxHeaterDemand = modData.AuxHeaterDemandCalc == null + ? 0.SI<Joule>() + : modData.AuxHeaterDemandCalc(duration, engineWasteheatSum); + } + + private static void SetMissingDCDCEnergy(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) + { + // either case C1, C2a, or C3a + var missingDCDCEnergy = modData.TimeIntegral<WattSecond>(ModalResultField.P_DCDC_missing); + if (missingDCDCEnergy.IsEqual(0)) { + r.EnergyDCDCMissing = missingDCDCEnergy; + return; + } + //if (runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorType == AlternatorType.Smart) { + // case C3a + if (runData.ElectricMachinesData.Count != 1) { + throw new VectoException("exactly 1 electric machine is required. got {0} ({1})", + runData.ElectricMachinesData.Count, + string.Join(",", runData.ElectricMachinesData.Select(x => x.Item1.ToString()))); + } + + var emPos = runData.ElectricMachinesData.First().Item1; + var averageEmEfficiencyCharging = modData.ElectricMotorEfficiencyGenerate(emPos); + r.EnergyDCDCMissing = missingDCDCEnergy / + runData.BusAuxiliaries.ElectricalUserInputsConfig.DCDCEfficiency / + averageEmEfficiencyCharging; + //} else { + // // case C1, C2a + // r.EnergyDCDCMissing = missingDCDCEnergy / + // runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorMap.GetEfficiency( + // 0.RPMtoRad(), 0.SI<Ampere>()); // DeclarationData.AlternaterEfficiency; + //} + } + + private static void SetBusAuxMissingPSWork(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) + { + var actuations = new Actuations() { + Braking = runData.BusAuxiliaries.Actuations.Braking, + ParkBrakeAndDoors = runData.BusAuxiliaries.Actuations.ParkBrakeAndDoors, + Kneeling = runData.BusAuxiliaries.Actuations.Kneeling, + CycleTime = modData.Duration + }; + r.CorrectedAirDemand = M03Impl.TotalAirDemandCalculation(runData.BusAuxiliaries, actuations); + + r.DeltaAir = r.CorrectedAirDemand - modData.AirGenerated(); + + var nonSmartAirGen = modData.GetValues(x => new { + dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), + airConsumed = x.Field<NormLiter>(ModalResultField.Nl_busAux_PS_consumer.GetName()), + airGenerated = x.Field<NormLiter>(ModalResultField.Nl_busAux_PS_generated.GetName()), + P_compOff = x.Field<Watt>(ModalResultField.P_busAux_PS_generated_dragOnly.GetName()), + P_compOn = x.Field<Watt>(ModalResultField.P_busAux_PS_generated_alwaysOn.GetName()), + Nl_alwaysOn = x.Field<NormLiter>(ModalResultField.Nl_busAux_PS_generated_alwaysOn.GetName()) + }).Where(x => x.airConsumed.IsEqual(x.airGenerated)).ToArray(); + + var workBusAuxPSCompOff = nonSmartAirGen.Sum(x => x.P_compOff * x.dt); + var workBusAuxPSCompOn = nonSmartAirGen.Sum(x => x.P_compOn * x.dt); + var airBusAuxPSON = nonSmartAirGen.Sum(x => x.Nl_alwaysOn); + + r.kAir = airBusAuxPSON.IsEqual(0) + ? 0.SI(Unit.SI.Watt.Second.Per.Cubic.Meter) + : (workBusAuxPSCompOn - workBusAuxPSCompOff) / (airBusAuxPSON - 0.SI<NormLiter>()); + r.WorkBusAuxPSCorr = (r.kAir * r.DeltaAir).Cast<WattSecond>(); + } + + private static void SetMissingEnergyICEOFf(IModalDataContainer modData, CorrectedModalData r) + { + var entriesAuxICEStandstill = modData.GetValues(x => new { + dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), + P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(), + P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(), + v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()), + IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName()) + }).Where(x => x.v != null && x.v.IsEqual(0) && !x.IceOn).ToArray(); + + var entriesAuxICEDriving = modData.GetValues(x => new { + dt = x.Field<Second>(ModalResultField.simulationInterval.GetName()), + P_off = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_off.GetName()) ?? 0.SI<Watt>(), + P_on = x.Field<Watt>(ModalResultField.P_aux_ESS_mech_ice_on.GetName()) ?? 0.SI<Watt>(), + v = x.Field<MeterPerSecond>(ModalResultField.v_act.GetName()), + IceOn = x.Field<bool>(ModalResultField.ICEOn.GetName()) + }).Where(x => x.v != null && !x.v.IsEqual(0) && !x.IceOn).ToArray(); + + r.ICEOffTimeStandstill = entriesAuxICEStandstill.Sum(x => x.dt) ?? 0.SI<Second>(); + + r.EnergyAuxICEOffStandstill = entriesAuxICEStandstill.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>(); + r.EnergyAuxICEOnStandstill = entriesAuxICEStandstill.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>(); + + r.ICEOffTimeDriving = entriesAuxICEDriving.Sum(x => x.dt) ?? 0.SI<Second>(); + + r.EnergyAuxICEOffDriving = entriesAuxICEDriving.Sum(x => x.P_off * x.dt) ?? 0.SI<WattSecond>(); + r.EnergyAuxICEOnDriving = entriesAuxICEDriving.Sum(x => x.P_on * x.dt) ?? 0.SI<WattSecond>(); + } + + private static void SetWHRWork(IModalDataContainer modData, VectoRunData runData, CorrectedModalData r) + { + r.WorkWHREl = modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_el_corr); + var altEff = DeclarationData.AlternatorEfficiency; + if (runData.BusAuxiliaries != null) { + if (runData.BusAuxiliaries.ElectricalUserInputsConfig.ConnectESToREESS && + runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorType == AlternatorType.Smart) { + // case C3a + if (runData.ElectricMachinesData.Count != 1) { + throw new VectoException("exactly 1 electric machine is required. got {0} ({1})", + runData.ElectricMachinesData.Count, + string.Join(",", runData.ElectricMachinesData.Select(x => x.Item1.ToString()))); + } + + var emPos = runData.ElectricMachinesData.First().Item1; + altEff = modData.ElectricMotorEfficiencyGenerate(emPos) * runData.BusAuxiliaries.ElectricalUserInputsConfig.DCDCEfficiency; + + } else { + altEff = runData.BusAuxiliaries.ElectricalUserInputsConfig.AlternatorMap.GetEfficiency( + 0.RPMtoRad(), 0.SI<Ampere>()); + } + } + + r.WorkWHRElMech = -r.WorkWHREl / altEff; + r.WorkWHRMech = -modData.TimeIntegral<WattSecond>(ModalResultField.P_WHR_mech_corr); + } + #endregion } public class CorrectedModalData : ICorrectedModalData { + public SI kAir { get; set; } public Dictionary<FuelType, IFuelConsumptionCorrection> FuelCorrection { get; } #region Implementation of ICorrectedModalData @@ -214,10 +346,13 @@ namespace TUGraz.VectoCore.OutputData public Second ICEOffTimeDriving { get; set; } public WattSecond EnergyAuxICEOffDriving { get; set; } - public WattSecond EnergyPowerICEOnDriving { get; set; } - public Watt AvgAuxPowerICEOnDriving => ICEOffTimeDriving.IsEqual(0) ? 0.SI<Watt>() : EnergyPowerICEOnDriving / ICEOffTimeDriving; + public WattSecond EnergyAuxICEOnDriving { get; set; } + public Watt AvgAuxPowerICEOnDriving => ICEOffTimeDriving.IsEqual(0) ? 0.SI<Watt>() : EnergyAuxICEOnDriving / ICEOffTimeDriving; public WattSecond EnergyDCDCMissing { get; set; } + public NormLiter CorrectedAirDemand { get; set; } + public NormLiter DeltaAir { get; set; } + public WattSecond DeltaEReessMech { get; set; } #endregion } @@ -243,9 +378,18 @@ namespace TUGraz.VectoCore.OutputData FcESS_EngineStart + FcESS_AuxStandstill_ICEOff + FcESS_AuxStandstill_ICEOn + FcESS_AuxDriving_ICEOn + FcESS_AuxDriving_ICEOff + FcESS_DCDCMissing; - public Kilogram FcBusAuxPs { get; set; } + public Kilogram FcBusAuxPSAirDemand { get; set; } + + public Kilogram FcBusAuxPSDragICEOffStandstill { get; set; } + public Kilogram FcBusAuxPSDragICEOffDriving { get; set; } + public Kilogram FcBusAuxPs + { + get => FcBusAuxPSAirDemand + FcBusAuxPSDragICEOffDriving + FcBusAuxPSDragICEOffStandstill; + } public Kilogram FcBusAuxEs { get; set; } public Kilogram FcWHR { get; set; } + public Kilogram FcREESSSoc { get; set; } + public Kilogram FcAuxHtr { get; set; } @@ -253,7 +397,9 @@ namespace TUGraz.VectoCore.OutputData public Kilogram FcBusAuxPsCorr => FcEssCorr + FcBusAuxPs; public Kilogram FcBusAuxEsCorr => FcBusAuxPsCorr + FcBusAuxEs; public Kilogram FcWHRCorr => FcBusAuxEsCorr + FcWHR; - public Kilogram FcAuxHtrCorr => FcWHRCorr + FcAuxHtr; + public Kilogram FcREESSSoCCorr => FcWHRCorr + FcREESSSoc; + + public Kilogram FcAuxHtrCorr => FcREESSSoCCorr + FcAuxHtr; public Kilogram FcFinal => FcAuxHtrCorr; @@ -261,14 +407,20 @@ namespace TUGraz.VectoCore.OutputData public KilogramPerWattSecond EngineLineCorrectionFactor { get; set; } public KilogramPerWattSecond VehicleLine { get; set; } + public KilogramPerSecond FC_ESS_H => Duration != null ? (FcESS / Duration) : null; public KilogramPerSecond FC_ESS_CORR_H => Duration != null ? (FcEssCorr / Duration) : null; public KilogramPerSecond FC_BusAux_PS_CORR_H => Duration != null ? (FcBusAuxPsCorr / Duration) : null; public KilogramPerSecond FC_BusAux_ES_CORR_H => Duration != null ? (FcBusAuxEsCorr / Duration) : null; public KilogramPerSecond FC_WHR_CORR_H => Duration != null ? (FcWHRCorr / Duration) : null; public KilogramPerSecond FC_AUXHTR_H => Duration != null ? (FcAuxHtr / Duration) : null; public KilogramPerSecond FC_AUXHTR_H_CORR => Duration != null ? (FcAuxHtrCorr / Duration) : null; + public KilogramPerSecond FC_REESS_SOC_H => Duration != null ? FcREESSSoc / Duration : null; + public KilogramPerSecond FC_REESS_SOC_CORR_H => Duration != null ? (FcREESSSoCCorr / Duration) : null; public KilogramPerSecond FC_FINAL_H => Duration != null ? FcFinal / Duration : null; + public KilogramPerMeter FC_REESS_SOC_KM => Distance != null ? FcREESSSoc / Distance : null; + public KilogramPerMeter FC_REESS_SOC_CORR_KM => Distance != null ? (FcREESSSoCCorr / Distance) : null; + public KilogramPerMeter FC_ESS_KM => Distance != null ? (FcESS / Distance) : null; public KilogramPerMeter FC_ESS_CORR_KM => Distance != null ? (FcEssCorr / Distance) : null; public KilogramPerMeter FC_WHR_CORR_KM => Distance != null ? (FcWHRCorr / Distance) : null; public KilogramPerMeter FC_BusAux_PS_CORR_KM => Distance != null ? (FcBusAuxPsCorr / Distance) : null; diff --git a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs index 47015a0310780ee39655a21a286272944fc4f97a..50163635a318861c360708d65f128973aad235c6 100644 --- a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs @@ -65,6 +65,8 @@ namespace TUGraz.VectoCore.OutputData Fields.FC_BusAux_PS_CORR_H, Fields.FC_BusAux_PS_CORR_KM, Fields.FC_BusAux_ES_CORR_H, Fields.FC_BusAux_ES_CORR_KM, Fields.FCWHR_H_CORR, Fields.FCWHR_KM_CORR, + Fields.FC_HEV_SOC_H, Fields.FC_HEV_SOC_KM, + Fields.FC_HEV_SOC_CORR_H, Fields.FC_HEV_SOC_CORR_KM, Fields.FC_AUXHTR_H, Fields.FC_AUXHTR_KM, Fields.FC_AUXHTR_H_CORR, Fields.FC_AUXHTR_KM_CORR, Fields.FCFINAL_H, Fields.FCFINAL_KM, Fields.FCFINAL_LITERPER100KM, Fields.FCFINAL_LITERPER100TKM, @@ -411,12 +413,12 @@ namespace TUGraz.VectoCore.OutputData row[FcCol(Fields.FCWHTCC_KM, suffix)] = modData.FuelConsumptionPerMeter(ModalResultField.FCWHTCc, fuel)?.ConvertToGrammPerKiloMeter(); - row[FcCol(Fields.FCESS_H, suffix)] = modData.FuelConsumptionPerSecond(ModalResultField.FCICEStopStart, fuel) - ?.ConvertToGrammPerHour(); - row[FcCol(Fields.FCESS_KM, suffix)] = modData.FuelConsumptionPerMeter(ModalResultField.FCICEStopStart, fuel) - ?.ConvertToGrammPerKiloMeter(); + //modData.FuelConsumptionPerSecond(ModalResultField.FCICEStopStart, fuel) + // ?.ConvertToGrammPerHour(); + //modData.FuelConsumptionPerMeter(ModalResultField.FCICEStopStart, fuel) + // ?.ConvertToGrammPerKiloMeter(); - var fuelConsumption = modData.CorrectedModalData.FuelConsumptionCorrection(fuel); + var fuelConsumption = modData.CorrectedModalData.FuelConsumptionCorrection(fuel); row[FcCol(Fields.K_ENGLINE, suffix)] = fuelConsumption.EngineLineCorrectionFactor.ConvertToGramPerKiloWattHour(); row[FcCol(Fields.K_VEHLINE, suffix)] = fuelConsumption.VehicleLine?.ConvertToGramPerKiloWattHour(); @@ -426,22 +428,27 @@ namespace TUGraz.VectoCore.OutputData row[FcCol(Fields.K_VEHLINE, suffix)] = vehLine.ConvertToGramPerKiloWattHour(); } + row[FcCol(Fields.FCESS_H, suffix)] = fuelConsumption.FC_ESS_H?.ConvertToGrammPerHour(); row[FcCol(Fields.FCESS_H_CORR, suffix)] = fuelConsumption.FC_ESS_CORR_H?.ConvertToGrammPerHour(); row[FcCol(Fields.FC_BusAux_PS_CORR_H, suffix)] = fuelConsumption.FC_BusAux_PS_CORR_H?.ConvertToGrammPerHour(); row[FcCol(Fields.FC_BusAux_ES_CORR_H, suffix)] = fuelConsumption.FC_BusAux_ES_CORR_H?.ConvertToGrammPerHour(); row[FcCol(Fields.FCWHR_H_CORR, suffix)] = fuelConsumption.FC_WHR_CORR_H?.ConvertToGrammPerHour(); + row[FcCol(Fields.FC_HEV_SOC_CORR_H, suffix)] = fuelConsumption.FC_REESS_SOC_CORR_H?.ConvertToGrammPerHour(); + row[FcCol(Fields.FC_HEV_SOC_H, suffix)] = fuelConsumption.FC_REESS_SOC_H?.ConvertToGrammPerHour(); row[FcCol(Fields.FC_AUXHTR_H, suffix)] = fuelConsumption.FC_AUXHTR_H?.ConvertToGrammPerHour(); row[FcCol(Fields.FC_AUXHTR_H_CORR, suffix)] = fuelConsumption.FC_AUXHTR_H_CORR?.ConvertToGrammPerHour(); - row[FcCol(Fields.FCFINAL_H, suffix)] = fuelConsumption.FC_FINAL_H?.ConvertToGrammPerHour(); row[FcCol(Fields.FCWHR_KM_CORR, suffix)] = fuelConsumption.FC_WHR_CORR_KM?.ConvertToGrammPerKiloMeter(); row[FcCol(Fields.FC_BusAux_PS_CORR_KM, suffix)] = fuelConsumption.FC_BusAux_PS_CORR_KM?.ConvertToGrammPerKiloMeter(); row[FcCol(Fields.FC_BusAux_ES_CORR_KM, suffix)] = fuelConsumption.FC_BusAux_ES_CORR_KM?.ConvertToGrammPerKiloMeter(); + row[FcCol(Fields.FC_HEV_SOC_CORR_KM, suffix)] = fuelConsumption.FC_REESS_SOC_CORR_KM?.ConvertToGrammPerKiloMeter(); + row[FcCol(Fields.FC_HEV_SOC_KM, suffix)] = fuelConsumption.FC_REESS_SOC_KM?.ConvertToGrammPerKiloMeter(); row[FcCol(Fields.FC_AUXHTR_KM, suffix)] = fuelConsumption.FC_AUXHTR_KM?.ConvertToGrammPerKiloMeter(); row[FcCol(Fields.FC_AUXHTR_KM_CORR, suffix)] = fuelConsumption.FC_AUXHTR_KM_CORR?.ConvertToGrammPerKiloMeter(); + row[FcCol(Fields.FCESS_KM, suffix)] = fuelConsumption.FC_ESS_KM?.ConvertToGrammPerKiloMeter(); row[FcCol(Fields.FCESS_KM_CORR, suffix)] = fuelConsumption.FC_ESS_CORR_KM?.ConvertToGrammPerKiloMeter(); row[FcCol(Fields.FCFINAL_KM, suffix)] = fuelConsumption.FC_FINAL_KM?.ConvertToGrammPerKiloMeter(); @@ -702,7 +709,7 @@ namespace TUGraz.VectoCore.OutputData } foreach (var field in new[] { - Fields.REESS_DeltaSoC, Fields.E_REESS_LOSS, Fields.E_REESS_T_chg, Fields.E_REESS_T_dischg, + Fields.REESS_DeltaEnergy, Fields.E_REESS_LOSS, Fields.E_REESS_T_chg, Fields.E_REESS_T_dischg, Fields.E_REESS_int_chg, Fields.E_REESS_int_dischg }) { if (Table.Columns.Contains(field)) { @@ -722,14 +729,14 @@ namespace TUGraz.VectoCore.OutputData if (runData.BatteryData != null) { row[Fields.REESS_StartSoC] = runData.BatteryData.InitialSoC * 100; row[Fields.REESS_EndSoC] = modData.REESSEndSoC(); - row[Fields.REESS_DeltaSoC] = modData.TimeIntegral<WattSecond>(ModalResultField.P_reess_int.GetName()) + row[Fields.REESS_DeltaEnergy] = modData.TimeIntegral<WattSecond>(ModalResultField.P_reess_int.GetName()) .ConvertToKiloWattHour(); } if (runData.SuperCapData != null) { row[Fields.REESS_StartSoC] = runData.SuperCapData.InitialSoC * 100; row[Fields.REESS_EndSoC] = modData.REESSEndSoC(); - row[Fields.REESS_DeltaSoC] = modData.TimeIntegral<WattSecond>(ModalResultField.P_reess_int.GetName()) + row[Fields.REESS_DeltaEnergy] = modData.TimeIntegral<WattSecond>(ModalResultField.P_reess_int.GetName()) .ConvertToKiloWattHour(); } } @@ -1095,6 +1102,11 @@ namespace TUGraz.VectoCore.OutputData public const string FCESS_KM_CORR = "FC-ESS_Corr{0} [g/km]"; public const string FCWHR_H_CORR = "FC-WHR_Corr{0} [g/h]"; public const string FCWHR_KM_CORR = "FC-WHR_Corr{0} [g/km]"; + public const string FC_HEV_SOC_H = "FC-SoC{0} [g/h]"; + public const string FC_HEV_SOC_KM = "FC-SoC{0} [g/km]"; + public const string FC_HEV_SOC_CORR_H = "FC-SoC_Corr{0} [g/h]"; + public const string FC_HEV_SOC_CORR_KM = "FC-SoC_Corr{0} [g/km]"; + public const string FC_BusAux_PS_CORR_H = "FC-BusAux_PS_Corr{0} [g/h]"; public const string FC_BusAux_PS_CORR_KM = "FC-BusAux_PS_Corr{0} [g/km]"; @@ -1267,7 +1279,7 @@ namespace TUGraz.VectoCore.OutputData public const string REESS_CAPACITY = "REESS Capacity"; public const string REESS_StartSoC = "REESS Start SoC [%]"; public const string REESS_EndSoC = "REESS End SoC [%]"; - public const string REESS_DeltaSoC = "ΔE_REESS [kWh]"; + public const string REESS_DeltaEnergy = "ΔE_REESS [kWh]"; public const string E_REESS_LOSS = "E_REESS_loss [kWh]"; public const string E_REESS_T_chg = "E_REESS_T_chg [kWh]"; diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/IXMLCustomerReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/IXMLCustomerReport.cs new file mode 100644 index 0000000000000000000000000000000000000000..dc7e48050a1b6f7231f33dc1115e4db6f7f820ef --- /dev/null +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/IXMLCustomerReport.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Xml.Linq; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; + +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile +{ + public interface IXMLCustomerReport + { + void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes); + XDocument Report { get; } + void WriteResult(XMLDeclarationReport.ResultEntry resultValue); + void GenerateReport(XElement resultSignature); + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/XML/XMLCustomerReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/XMLCustomerReport.cs similarity index 95% rename from VectoCore/VectoCore/OutputData/XML/XMLCustomerReport.cs rename to VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/XMLCustomerReport.cs index 21fe09bb6f0dea0c6ef1de9f6e10038fcf8e3714..fe28253da5cb0804ecdf0e6e294f4e4247a3cad1 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLCustomerReport.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/XMLCustomerReport.cs @@ -1,296 +1,319 @@ -/* -* This file is part of VECTO. -* -* Copyright © 2012-2019 European Union -* -* Developed by Graz University of Technology, -* Institute of Internal Combustion Engines and Thermodynamics, -* Institute of Technical Informatics -* -* VECTO is licensed under the EUPL, Version 1.1 or - as soon they will be approved -* by the European Commission - subsequent versions of the EUPL (the "Licence"); -* You may not use VECTO except in compliance with the Licence. -* You may obtain a copy of the Licence at: -* -* https://joinup.ec.europa.eu/community/eupl/og_page/eupl -* -* Unless required by applicable law or agreed to in writing, VECTO -* distributed under the Licence is distributed on an "AS IS" basis, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the Licence for the specific language governing permissions and -* limitations under the Licence. -* -* Authors: -* Stefan Hausberger, hausberger@ivt.tugraz.at, IVT, Graz University of Technology -* Christian Kreiner, christian.kreiner@tugraz.at, ITI, Graz University of Technology -* Michael Krisper, michael.krisper@tugraz.at, ITI, Graz University of Technology -* Raphael Luz, luz@ivt.tugraz.at, IVT, Graz University of Technology -* Markus Quaritsch, markus.quaritsch@tugraz.at, IVT, Graz University of Technology -* Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology -*/ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml; -using System.Xml.Linq; -using TUGraz.IVT.VectoXML.Writer; -using TUGraz.VectoCommon.InputData; -using TUGraz.VectoCommon.Models; -using TUGraz.VectoCommon.Resources; -using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore.Models.Declaration; -using TUGraz.VectoCore.Models.Simulation.Data; -using TUGraz.VectoCore.Models.Simulation.Impl; -using TUGraz.VectoCore.Models.SimulationComponent.Data; -using TUGraz.VectoCore.Utils; -using TUGraz.VectoHashing; - -namespace TUGraz.VectoCore.OutputData.XML -{ - public class XMLCustomerReport - { - public const string CURRENT_SCHEMA_VERSION = "0.8"; - - protected readonly XElement VehiclePart; - - protected XElement InputDataIntegrity; - - protected readonly XElement Results; - - protected readonly XNamespace rootNS = XNamespace.Get("urn:tugraz:ivt:VectoAPI:CustomerOutput"); - protected readonly XNamespace tns = XNamespace.Get("urn:tugraz:ivt:VectoAPI:CustomerOutput:v" + CURRENT_SCHEMA_VERSION); - protected readonly XNamespace di = XNamespace.Get("http://www.w3.org/2000/09/xmldsig#"); - protected readonly XNamespace xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance"); - - protected bool _allSuccess = true; - - protected KilogramPerMeter _weightedCo2 = 0.SI<KilogramPerMeter>(); - - protected Kilogram _weightedPayload = 0.SI<Kilogram>(); - protected double _passengerCount = 0; - - - public XMLCustomerReport() - { - - VehiclePart = new XElement(tns + XMLNames.Component_Vehicle); - Results = new XElement(tns + XMLNames.Report_Results); - } - - public virtual void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) - { - var exempted = modelData.Exempted; - VehiclePart.Add( - new XElement(tns + XMLNames.Component_Model, modelData.VehicleData.ModelName), - new XElement(tns + XMLNames.Component_Manufacturer, modelData.VehicleData.Manufacturer), - new XElement(tns + XMLNames.Component_ManufacturerAddress, modelData.VehicleData.ManufacturerAddress), - new XElement(tns + XMLNames.Vehicle_VIN, modelData.VehicleData.VIN), - new XElement(tns + XMLNames.Vehicle_LegislativeClass, modelData.VehicleData.LegislativeClass.ToXMLFormat()), - new XElement( - tns + XMLNames.Vehicle_GrossVehicleMass, - XMLHelper.ValueAsUnit(modelData.VehicleData.GrossVehicleMass, XMLNames.Unit_t, 1)), - new XElement( - tns + XMLNames.Vehicle_CurbMassChassis, XMLHelper.ValueAsUnit(modelData.VehicleData.CurbMass, XMLNames.Unit_kg)), - new XElement(tns + XMLNames.Vehicle_ZeroEmissionVehicle, modelData.VehicleData.ZeroEmissionVehicle), - new XElement(tns + XMLNames.Vehicle_HybridElectricHDV, modelData.VehicleData.HybridElectricHDV), - new XElement(tns + XMLNames.Vehicle_DualFuelVehicle, modelData.VehicleData.DualFuelVehicle) - ); - - if (exempted) { - VehiclePart.Add(new XAttribute(xsi + "type", "ExemptedVehicleType"), - ExemptedData(modelData)); - Results.Add(new XElement(tns + XMLNames.Report_ExemptedVehicle)); - } else { - VehiclePart.Add( - new XAttribute(xsi + "type", "VehicleType"), - new XElement(tns + XMLNames.Vehicle_AxleConfiguration, modelData.VehicleData.AxleConfiguration.GetName()), - new XElement(tns + XMLNames.Report_Vehicle_VehicleGroup, modelData.VehicleData.VehicleClass.GetClassNumber()), - new XElement(tns + XMLNames.Vehicle_VocationalVehicle, modelData.VehicleData.VocationalVehicle), - new XElement(tns + XMLNames.Vehicle_SleeperCab, modelData.VehicleData.SleeperCab), - GetADAS(modelData.VehicleData.ADAS), - ComponentData(modelData, fuelModes) - ); - } - InputDataIntegrity = new XElement(tns + XMLNames.Report_InputDataSignature, - modelData.InputDataHash == null ? XMLHelper.CreateDummySig(di) : new XElement(modelData.InputDataHash)); - } - - private object[] ExemptedData(VectoRunData modelData) - { - return new object[] { - modelData.VehicleData.HybridElectricHDV ? new XElement(tns + XMLNames.Vehicle_MaxNetPower1, XMLHelper.ValueAsUnit(modelData.VehicleData.MaxNetPower1, XMLNames.Unit_W)) : null, - modelData.VehicleData.HybridElectricHDV ? new XElement(tns + XMLNames.Vehicle_MaxNetPower2, XMLHelper.ValueAsUnit(modelData.VehicleData.MaxNetPower2, XMLNames.Unit_W)) : null - }; - } - - protected XElement GetADAS(VehicleData.ADASData adasData) - { - return new XElement(tns + XMLNames.Vehicle_ADAS, - new XElement(tns + XMLNames.Vehicle_ADAS_EngineStopStart, adasData.EngineStopStart), - new XElement(tns + XMLNames.Vehicle_ADAS_EcoRollWithoutEngineStop, adasData.EcoRoll.WithoutEngineStop()), - new XElement(tns + XMLNames.Vehicle_ADAS_EcoRollWithEngineStopStart, adasData.EcoRoll.WithEngineStop()), - new XElement(tns + XMLNames.Vehicle_ADAS_PCC, adasData.PredictiveCruiseControl != PredictiveCruiseControlType.None) - ); - } - - protected virtual XElement[] ComponentData(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) - { - return new[] { - new XElement( - tns + XMLNames.Report_Vehicle_EngineRatedPower, - XMLHelper.ValueAsUnit(modelData.EngineData.RatedPowerDeclared, XMLNames.Unit_kW)), - new XElement( - tns + XMLNames.Report_Vehicle_EngineDisplacement, - XMLHelper.ValueAsUnit(modelData.EngineData.Displacement, XMLNames.Unit_ltr, 1)), - new XElement( - tns + XMLNames.Report_Vehicle_FuelTypes, - fuelModes.SelectMany(x => x.Select(f => f.FuelType.ToXMLFormat())).Distinct() - .Select(x => new XElement(tns + XMLNames.Engine_FuelType, x)) - ), - new XElement( - tns + XMLNames.Report_Vehicle_TransmissionCertificationMethod, - modelData.GearboxData.CertificationMethod.ToXMLFormat()), - new XElement(tns + XMLNames.Gearbox_TransmissionType, modelData.GearboxData.Type.ToXMLFormat()), - new XElement(tns + XMLNames.Report_GetGearbox_GearsCount, modelData.GearboxData.Gears.Count), - new XElement(tns + XMLNames.Report_Vehicle_Retarder, modelData.Retarder.Type.IsDedicatedComponent()), - new XElement(tns + XMLNames.Report_Vehicle_AxleRatio, modelData.AxleGearData.AxleGear.Ratio.ToXMLFormat(3)), - new XElement( - tns + XMLNames.Report_Vehicle_AverageRRC, modelData.VehicleData.AverageRollingResistanceTruck.ToXMLFormat(4)), - - //new XElement( - // tns + XMLNames.Report_Vehicle_AverageRRCLabel, - // DeclarationData.Wheels.TyreClass.Lookup(modelData.VehicleData.AverageRollingResistanceTruck)) - }.Concat( - modelData.VehicleData.AxleData.Where(x => x.AxleType != AxleType.Trailer).Select( - (x, idx) => new XElement(tns + "FuelEfficiencyLabelMotorVehicleTyre", - new XAttribute("axleNbr", idx+1), - x.FuelEfficiencyClass))).ToArray(); - - } - - - - public virtual void WriteResult(XMLDeclarationReport.ResultEntry resultEntry) - { - //foreach (var resultEntry in entry.ResultEntry) { - _allSuccess &= resultEntry.Status == VectoRun.Status.Success; - if (resultEntry.Status == VectoRun.Status.Success) { - _weightedPayload += resultEntry.Payload * resultEntry.WeightingFactor; - _weightedCo2 += resultEntry.CO2Total / resultEntry.Distance * resultEntry.WeightingFactor; - _passengerCount += (resultEntry.PassengerCount ?? 0) * resultEntry.WeightingFactor; - } - Results.Add(resultEntry.Status == VectoRun.Status.Success ? GetSuccessResult(resultEntry) : GetErrorResult(resultEntry)); - } - - private XElement GetErrorResult(XMLDeclarationReport.ResultEntry resultEntry) - { - var content = new object[] { }; - switch (resultEntry.Status) { - case VectoRun.Status.Pending: - case VectoRun.Status.Running: - content = null; // should not happen! - break; - case VectoRun.Status.Canceled: - case VectoRun.Status.Aborted: - content = new object[] { - new XElement(tns + "Error", resultEntry.Error) - }; - break; - default: - throw new ArgumentOutOfRangeException(); - } - - return new XElement(tns + XMLNames.Report_Result_Result, - new XAttribute(XMLNames.Report_Result_Status_Attr, "error"), - new XAttribute(xsi + "type", "ResultErrorType"), - new XElement(tns + XMLNames.Report_Result_Mission, resultEntry.Mission.ToXMLFormat()), - content); - } - - private XElement GetSuccessResult(XMLDeclarationReport.ResultEntry result) - { - return new XElement( - tns + XMLNames.Report_Result_Result, - new XAttribute(XMLNames.Report_Result_Status_Attr, "success"), - new XAttribute(xsi + "type", "ResultSuccessType"), - new XElement(tns + XMLNames.Report_Result_Mission, result.Mission.ToXMLFormat()), - new XElement(tns + XMLNames.Report_ResultEntry_TotalVehicleMass, - XMLHelper.ValueAsUnit(result.TotalVehicleMass, XMLNames.Unit_kg)), - new XElement(tns + XMLNames.Report_ResultEntry_Payload, XMLHelper.ValueAsUnit(result.Payload, XMLNames.Unit_kg)), - result.PassengerCount.HasValue && result.PassengerCount.Value > 0 - ? new XElement(tns + "PassengerCount", result.PassengerCount.Value.ToMinSignificantDigits(3, 1)) - : null, - new XElement(tns + XMLNames.Report_Result_FuelMode, - result.FuelData.Count > 1 ? XMLNames.Report_Result_FuelMode_Val_Dual : XMLNames.Report_Result_FuelMode_Val_Single), - new XElement(tns + XMLNames.Report_Results_AverageSpeed, XMLHelper.ValueAsUnit(result.AverageSpeed, XMLNames.Unit_kmph, 1)), - XMLDeclarationReport.GetResults(result, tns, false).Cast<object>().ToArray() - ); - } - - protected XElement GetApplicationInfo() - { - var versionNumber = VectoSimulationCore.VersionNumber; -#if CERTIFICATION_RELEASE - // add nothing to version number -#else - versionNumber += " !!NOT FOR CERTIFICATION!!"; -#endif - return new XElement(tns + XMLNames.Report_ApplicationInfo_ApplicationInformation, - new XElement(tns + XMLNames.Report_ApplicationInfo_SimulationToolVersion, versionNumber), - new XElement(tns + XMLNames.Report_ApplicationInfo_Date, - XmlConvert.ToString(DateTime.Now, XmlDateTimeSerializationMode.Utc))); - } - - public virtual void GenerateReport(XElement resultSignature) - { - - var retVal = new XDocument(); - var results = new XElement(Results); - results.AddFirst(new XElement(tns + XMLNames.Report_Result_Status, _allSuccess ? "success" : "error")); - var summary = _allSuccess && _weightedPayload > 0 - ? new XElement(tns + XMLNames.Report_Results_Summary, - new XElement(tns + XMLNames.Report_SpecificCO2Emissions, - new XAttribute(XMLNames.Report_Results_Unit_Attr, XMLNames.Unit_gCO2Pertkm), - (_weightedCo2 / _weightedPayload).ConvertToGrammPerTonKilometer().ToXMLFormat(1) - ), - new XElement(tns + XMLNames.Report_AveragePayload, - new XAttribute(XMLNames.Report_Results_Unit_Attr, XMLNames.Unit_t), - _weightedPayload.ConvertToTon().ToXMLFormat(3) - ), - _passengerCount > 0 ? new XElement(tns + "AveragePAssengerCount", _passengerCount.ToMinSignificantDigits(2)) : null - ) - : null; - results.Add(summary); - var vehicle = new XElement(VehiclePart); - vehicle.Add(InputDataIntegrity); - retVal.Add(new XProcessingInstruction("xml-stylesheet", "href=\"https://webgate.ec.europa.eu/CITnet/svn/VECTO/trunk/Share/XML/CSS/VectoReports.css\"")); - retVal.Add(new XElement(rootNS + XMLNames.VectoCustomerReport, - //new XAttribute("schemaVersion", CURRENT_SCHEMA_VERSION), - new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName), - new XAttribute("xmlns", tns), - new XAttribute(XNamespace.Xmlns + "tns", rootNS), - new XAttribute(XNamespace.Xmlns + "di", di), - new XAttribute(xsi + "schemaLocation", - $"{rootNS} {AbstractXMLWriter.SchemaLocationBaseUrl}DEV/VectoOutputCustomer.xsd"), - new XElement(rootNS + XMLNames.Report_DataWrap, - new XAttribute(xsi + "type", "VectoOutputDataType"), - vehicle, - new XElement(tns + XMLNames.Report_ResultData_Signature, resultSignature), - results, - GetApplicationInfo()) - ) - ); - var stream = new MemoryStream(); - var writer = new StreamWriter(stream); - writer.Write(retVal); - writer.Flush(); - stream.Seek(0, SeekOrigin.Begin); - var h = VectoHash.Load(stream); - Report = h.AddHash(); - } - - public XDocument Report { get; protected set; } - } -} +/* +* This file is part of VECTO. +* +* Copyright © 2012-2019 European Union +* +* Developed by Graz University of Technology, +* Institute of Internal Combustion Engines and Thermodynamics, +* Institute of Technical Informatics +* +* VECTO is licensed under the EUPL, Version 1.1 or - as soon they will be approved +* by the European Commission - subsequent versions of the EUPL (the "Licence"); +* You may not use VECTO except in compliance with the Licence. +* You may obtain a copy of the Licence at: +* +* https://joinup.ec.europa.eu/community/eupl/og_page/eupl +* +* Unless required by applicable law or agreed to in writing, VECTO +* distributed under the Licence is distributed on an "AS IS" basis, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the Licence for the specific language governing permissions and +* limitations under the Licence. +* +* Authors: +* Stefan Hausberger, hausberger@ivt.tugraz.at, IVT, Graz University of Technology +* Christian Kreiner, christian.kreiner@tugraz.at, ITI, Graz University of Technology +* Michael Krisper, michael.krisper@tugraz.at, ITI, Graz University of Technology +* Raphael Luz, luz@ivt.tugraz.at, IVT, Graz University of Technology +* Markus Quaritsch, markus.quaritsch@tugraz.at, IVT, Graz University of Technology +* Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; +using System.Xml.Linq; +using TUGraz.IVT.VectoXML.Writer; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Resources; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Utils; +using TUGraz.VectoHashing; + +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile +{ + public class XMLCustomerReport : IXMLCustomerReport + { + public const string CURRENT_SCHEMA_VERSION = "0.8"; + + protected readonly XElement VehiclePart; + + protected XElement InputDataIntegrity; + + protected readonly XElement Results; + + protected readonly XNamespace rootNS = XNamespace.Get("urn:tugraz:ivt:VectoAPI:CustomerOutput"); + protected readonly XNamespace tns = XNamespace.Get("urn:tugraz:ivt:VectoAPI:CustomerOutput:v" + CURRENT_SCHEMA_VERSION); + protected readonly XNamespace di = XNamespace.Get("http://www.w3.org/2000/09/xmldsig#"); + protected readonly XNamespace xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance"); + + protected bool _allSuccess = true; + + protected KilogramPerMeter _weightedCo2 = 0.SI<KilogramPerMeter>(); + + protected Kilogram _weightedPayload = 0.SI<Kilogram>(); + protected double _passengerCount = 0; + + + public XMLCustomerReport() + { + + VehiclePart = new XElement(tns + XMLNames.Component_Vehicle); + Results = new XElement(tns + XMLNames.Report_Results); + } + + public virtual void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) + { + var exempted = modelData.Exempted; + VehiclePart.Add( + new XElement(tns + XMLNames.Component_Model, modelData.VehicleData.ModelName), + new XElement(tns + XMLNames.Component_Manufacturer, modelData.VehicleData.Manufacturer), + new XElement(tns + XMLNames.Component_ManufacturerAddress, modelData.VehicleData.ManufacturerAddress), + new XElement(tns + XMLNames.Vehicle_VIN, modelData.VehicleData.VIN), + new XElement(tns + XMLNames.Vehicle_LegislativeClass, modelData.VehicleData.LegislativeClass.ToXMLFormat()), + new XElement( + tns + XMLNames.Vehicle_GrossVehicleMass, + XMLHelper.ValueAsUnit(modelData.VehicleData.GrossVehicleMass, XMLNames.Unit_t, 1)), + new XElement( + tns + XMLNames.Vehicle_CurbMassChassis, XMLHelper.ValueAsUnit(modelData.VehicleData.CurbMass, XMLNames.Unit_kg)), + new XElement(tns + XMLNames.Vehicle_ZeroEmissionVehicle, modelData.VehicleData.ZeroEmissionVehicle), + new XElement(tns + XMLNames.Vehicle_HybridElectricHDV, modelData.VehicleData.HybridElectricHDV), + new XElement(tns + XMLNames.Vehicle_DualFuelVehicle, modelData.VehicleData.DualFuelVehicle) + ); + + if (exempted) { + VehiclePart.Add(new XAttribute(xsi + "type", "ExemptedVehicleType"), + ExemptedData(modelData)); + Results.Add(new XElement(tns + XMLNames.Report_ExemptedVehicle)); + } else { + VehiclePart.Add( + new XAttribute(xsi + "type", "VehicleType"), + new XElement(tns + XMLNames.Vehicle_AxleConfiguration, modelData.VehicleData.AxleConfiguration.GetName()), + new XElement(tns + XMLNames.Report_Vehicle_VehicleGroup, modelData.VehicleData.VehicleClass.GetClassNumber()), + new XElement(tns + XMLNames.Vehicle_VocationalVehicle, modelData.VehicleData.VocationalVehicle), + new XElement(tns + XMLNames.Vehicle_SleeperCab, modelData.VehicleData.SleeperCab), + GetADAS(modelData.VehicleData.ADAS), + ComponentData(modelData, fuelModes) + ); + } + InputDataIntegrity = new XElement(tns + XMLNames.Report_InputDataSignature, + modelData.InputDataHash == null ? XMLHelper.CreateDummySig(di) : new XElement(modelData.InputDataHash)); + } + + private object[] ExemptedData(VectoRunData modelData) + { + return new object[] { + modelData.VehicleData.HybridElectricHDV ? new XElement(tns + XMLNames.Vehicle_MaxNetPower1, XMLHelper.ValueAsUnit(modelData.VehicleData.MaxNetPower1, XMLNames.Unit_W)) : null, + modelData.VehicleData.HybridElectricHDV ? new XElement(tns + XMLNames.Vehicle_MaxNetPower2, XMLHelper.ValueAsUnit(modelData.VehicleData.MaxNetPower2, XMLNames.Unit_W)) : null + }; + } + + protected XElement GetADAS(VehicleData.ADASData adasData) + { + return new XElement(tns + XMLNames.Vehicle_ADAS, + new XElement(tns + XMLNames.Vehicle_ADAS_EngineStopStart, adasData.EngineStopStart), + new XElement(tns + XMLNames.Vehicle_ADAS_EcoRollWithoutEngineStop, adasData.EcoRoll.WithoutEngineStop()), + new XElement(tns + XMLNames.Vehicle_ADAS_EcoRollWithEngineStopStart, adasData.EcoRoll.WithEngineStop()), + new XElement(tns + XMLNames.Vehicle_ADAS_PCC, adasData.PredictiveCruiseControl != PredictiveCruiseControlType.None) + ); + } + + protected virtual XElement[] ComponentData(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) + { + return new[] { + new XElement( + tns + XMLNames.Report_Vehicle_EngineRatedPower, + XMLHelper.ValueAsUnit(modelData.EngineData.RatedPowerDeclared, XMLNames.Unit_kW)), + new XElement( + tns + XMLNames.Report_Vehicle_EngineDisplacement, + XMLHelper.ValueAsUnit(modelData.EngineData.Displacement, XMLNames.Unit_ltr, 1)), + new XElement( + tns + XMLNames.Report_Vehicle_FuelTypes, + fuelModes.SelectMany(x => x.Select(f => f.FuelType.ToXMLFormat())).Distinct() + .Select(x => new XElement(tns + XMLNames.Engine_FuelType, x)) + ), + new XElement( + tns + XMLNames.Report_Vehicle_TransmissionCertificationMethod, + modelData.GearboxData.CertificationMethod.ToXMLFormat()), + new XElement(tns + XMLNames.Gearbox_TransmissionType, modelData.GearboxData.Type.ToXMLFormat()), + new XElement(tns + XMLNames.Report_GetGearbox_GearsCount, modelData.GearboxData.Gears.Count), + new XElement(tns + XMLNames.Report_Vehicle_Retarder, modelData.Retarder.Type.IsDedicatedComponent()), + new XElement(tns + XMLNames.Report_Vehicle_AxleRatio, modelData.AxleGearData.AxleGear.Ratio.ToXMLFormat(3)), + new XElement( + tns + XMLNames.Report_Vehicle_AverageRRC, modelData.VehicleData.AverageRollingResistanceTruck.ToXMLFormat(4)), + + //new XElement( + // tns + XMLNames.Report_Vehicle_AverageRRCLabel, + // DeclarationData.Wheels.TyreClass.Lookup(modelData.VehicleData.AverageRollingResistanceTruck)) + }.Concat( + modelData.VehicleData.AxleData.Where(x => x.AxleType != AxleType.Trailer).Select( + (x, idx) => new XElement(tns + "FuelEfficiencyLabelMotorVehicleTyre", + new XAttribute("axleNbr", idx+1), + x.FuelEfficiencyClass))).ToArray(); + + } + + + + public virtual void WriteResult(XMLDeclarationReport.ResultEntry resultEntry) + { + //foreach (var resultEntry in entry.ResultEntry) { + _allSuccess &= resultEntry.Status == VectoRun.Status.Success; + if (resultEntry.Status == VectoRun.Status.Success) { + _weightedPayload += resultEntry.Payload * resultEntry.WeightingFactor; + _weightedCo2 += resultEntry.CO2Total / resultEntry.Distance * resultEntry.WeightingFactor; + _passengerCount += (resultEntry.PassengerCount ?? 0) * resultEntry.WeightingFactor; + } + Results.Add(resultEntry.Status == VectoRun.Status.Success ? GetSuccessResult(resultEntry) : GetErrorResult(resultEntry)); + } + + private XElement GetErrorResult(XMLDeclarationReport.ResultEntry resultEntry) + { + var content = new object[] { }; + switch (resultEntry.Status) { + case VectoRun.Status.Pending: + case VectoRun.Status.Running: + content = null; // should not happen! + break; + case VectoRun.Status.Canceled: + case VectoRun.Status.Aborted: + content = new object[] { + new XElement(tns + "Error", resultEntry.Error) + }; + break; + default: + throw new ArgumentOutOfRangeException(); + } + + return new XElement(tns + XMLNames.Report_Result_Result, + new XAttribute(XMLNames.Report_Result_Status_Attr, "error"), + new XAttribute(xsi + "type", "ResultErrorType"), + new XElement(tns + XMLNames.Report_Result_Mission, resultEntry.Mission.ToXMLFormat()), + content); + } + + private XElement GetSuccessResult(XMLDeclarationReport.ResultEntry result) + { + return new XElement( + tns + XMLNames.Report_Result_Result, + new XAttribute(XMLNames.Report_Result_Status_Attr, "success"), + new XAttribute(xsi + "type", "ResultSuccessType"), + new XElement(tns + XMLNames.Report_Result_Mission, result.Mission.ToXMLFormat()), + new XElement(tns + XMLNames.Report_ResultEntry_TotalVehicleMass, + XMLHelper.ValueAsUnit(result.TotalVehicleMass, XMLNames.Unit_kg)), + new XElement(tns + XMLNames.Report_ResultEntry_Payload, XMLHelper.ValueAsUnit(result.Payload, XMLNames.Unit_kg)), + result.PassengerCount.HasValue && result.PassengerCount.Value > 0 + ? new XElement(tns + "PassengerCount", result.PassengerCount.Value.ToMinSignificantDigits(3, 1)) + : null, + new XElement(tns + XMLNames.Report_Result_FuelMode, + result.FuelData.Count > 1 ? XMLNames.Report_Result_FuelMode_Val_Dual : XMLNames.Report_Result_FuelMode_Val_Single), + new XElement(tns + XMLNames.Report_Results_AverageSpeed, XMLHelper.ValueAsUnit(result.AverageSpeed, XMLNames.Unit_kmph, 1)), + XMLDeclarationReport.GetResults(result, tns, false).Cast<object>().ToArray() + ); + } + + protected XElement GetApplicationInfo() + { + var versionNumber = VectoSimulationCore.VersionNumber; +#if CERTIFICATION_RELEASE + // add nothing to version number +#else + versionNumber += " !!NOT FOR CERTIFICATION!!"; +#endif + return new XElement(tns + XMLNames.Report_ApplicationInfo_ApplicationInformation, + new XElement(tns + XMLNames.Report_ApplicationInfo_SimulationToolVersion, versionNumber), + new XElement(tns + XMLNames.Report_ApplicationInfo_Date, + XmlConvert.ToString(DateTime.Now, XmlDateTimeSerializationMode.Utc))); + } + + public virtual void GenerateReport(XElement resultSignature) + { + + var retVal = new XDocument(); + var results = new XElement(Results); + results.AddFirst(new XElement(tns + XMLNames.Report_Result_Status, _allSuccess ? "success" : "error")); + var summary = _allSuccess && _weightedPayload > 0 + ? new XElement(tns + XMLNames.Report_Results_Summary, + new XElement(tns + XMLNames.Report_SpecificCO2Emissions, + new XAttribute(XMLNames.Report_Results_Unit_Attr, XMLNames.Unit_gCO2Pertkm), + (_weightedCo2 / _weightedPayload).ConvertToGrammPerTonKilometer().ToXMLFormat(1) + ), + new XElement(tns + XMLNames.Report_AveragePayload, + new XAttribute(XMLNames.Report_Results_Unit_Attr, XMLNames.Unit_t), + _weightedPayload.ConvertToTon().ToXMLFormat(3) + ), + _passengerCount > 0 ? new XElement(tns + "AveragePAssengerCount", _passengerCount.ToMinSignificantDigits(2)) : null + ) + : null; + results.Add(summary); + var vehicle = new XElement(VehiclePart); + vehicle.Add(InputDataIntegrity); + retVal.Add(new XProcessingInstruction("xml-stylesheet", "href=\"https://webgate.ec.europa.eu/CITnet/svn/VECTO/trunk/Share/XML/CSS/VectoReports.css\"")); + retVal.Add(new XElement(rootNS + XMLNames.VectoCustomerReport, + //new XAttribute("schemaVersion", CURRENT_SCHEMA_VERSION), + new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName), + new XAttribute("xmlns", tns), + new XAttribute(XNamespace.Xmlns + "tns", rootNS), + new XAttribute(XNamespace.Xmlns + "di", di), + new XAttribute(xsi + "schemaLocation", + $"{rootNS} {AbstractXMLWriter.SchemaLocationBaseUrl}DEV/VectoOutputCustomer.xsd"), + new XElement(rootNS + XMLNames.Report_DataWrap, + new XAttribute(xsi + "type", "VectoOutputDataType"), + vehicle, + new XElement(tns + XMLNames.Report_ResultData_Signature, resultSignature), + results, + GetApplicationInfo()) + ) + ); + var stream = new MemoryStream(); + var writer = new StreamWriter(stream); + writer.Write(retVal); + writer.Flush(); + stream.Seek(0, SeekOrigin.Begin); + var h = VectoHash.Load(stream); + Report = h.AddHash(); + } + + public XDocument Report { get; protected set; } + } + + public class XMLCustomerReportExemptedPrimaryBus : IXMLCustomerReport + { + #region Implementation of IXMLCustomerReport + + public void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) + { + // MQ 2021-06-14 TODO: fill with meat + } + + public XDocument Report { get; } + public void WriteResult(XMLDeclarationReport.ResultEntry resultValue) + { + // MQ 2021-06-14 TODO: fill with meat + } + + public void GenerateReport(XElement resultSignature) + { + // MQ 2021-06-14 TODO: fill with meat + } + + #endregion + } +} diff --git a/VectoCore/VectoCore/OutputData/XML/XMLCustomerReportCompletedBus.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/XMLCustomerReportCompletedBus.cs similarity index 96% rename from VectoCore/VectoCore/OutputData/XML/XMLCustomerReportCompletedBus.cs rename to VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/XMLCustomerReportCompletedBus.cs index 735b0cb2f571cdffa1e7c176e273b902b1d49abe..32480f8721668c4f5414054c7e7fcb8dfb65e583 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLCustomerReportCompletedBus.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/XMLCustomerReportCompletedBus.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Xml.Linq; using TUGraz.IVT.VectoXML.Writer; -using TUGraz.VectoCommon.BusAuxiliaries; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Resources; @@ -12,13 +11,16 @@ using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport; using TUGraz.VectoCore.Utils; using TUGraz.VectoHashing; -namespace TUGraz.VectoCore.OutputData.XML { +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile +{ public class XMLCustomerReportCompletedBus : XMLCustomerReport { private int _resultCount = 0; + protected TankSystem? _tankSystem; public IPrimaryVehicleInformationInputDataProvider PrimaryVehicleRecordFile { get; set; } @@ -26,6 +28,7 @@ namespace TUGraz.VectoCore.OutputData.XML { public override void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) { + _tankSystem = modelData.VehicleData.InputData.TankSystem; VehiclePart.Add( new XAttribute(xsi + "type", "VehicleCompletedBusType"), new XElement(tns + XMLNames.Component_Model, modelData.VehicleData.ModelName), @@ -80,7 +83,7 @@ namespace TUGraz.VectoCore.OutputData.XML { modelData.InputDataHash == null ? XMLHelper.CreateDummySig(di) : new XElement(modelData.InputDataHash)); } - internal void WriteResult(XMLDeclarationReport.ResultEntry genericResult, XMLDeclarationReport.ResultEntry specificResult, IResult primaryResult) + public virtual void WriteResult(XMLDeclarationReport.ResultEntry genericResult, XMLDeclarationReport.ResultEntry specificResult, IResult primaryResult) { _allSuccess &= genericResult.Status == VectoRun.Status.Success; _allSuccess &= specificResult.Status == VectoRun.Status.Success; @@ -160,7 +163,7 @@ namespace TUGraz.VectoCore.OutputData.XML { var co2Sum = 0.SI<KilogramPerMeter>(); foreach (var entry in primaryResult.EnergyConsumption) { var fcEnergy = entry.Value * factor; // J/m - var fuelData = FuelData.Instance().Lookup(entry.Key); + var fuelData = FuelData.Instance().Lookup(entry.Key, _tankSystem); var fcMass = fcEnergy / fuelData.LowerHeatingValueVecto; // kg/m co2Sum += fcMass * fuelData.CO2PerFuelWeight; diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/XMLCustomerReportExemptedCompletedBus.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/XMLCustomerReportExemptedCompletedBus.cs new file mode 100644 index 0000000000000000000000000000000000000000..b9311f3be29972aed8e2f5c2de575c50a1b7178a --- /dev/null +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/CustomerInformationFile/XMLCustomerReportExemptedCompletedBus.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using System.Xml.Linq; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Resources; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile +{ + public class XMLCustomerReportExemptedCompletedBus : XMLCustomerReportCompletedBus + { + public override void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) + { + VehiclePart.Add( + new XAttribute(xsi + "type", "VehicleCompletedExemptedBusType"), + new XElement(tns + XMLNames.Component_Model, modelData.VehicleData.ModelName), + new XElement( + tns + "PrimaryVehicle", + new XElement(tns + XMLNames.Component_Manufacturer, PrimaryVehicle.Manufacturer), + new XElement(tns + XMLNames.Component_ManufacturerAddress, PrimaryVehicle.ManufacturerAddress), + new XElement(tns + XMLNames.Report_InputDataSignature, + PrimaryVehicleRecordFile.PrimaryVehicleInputDataHash.ToXML(di)), + new XElement(tns + "ManufacturerRecordSignature", + PrimaryVehicleRecordFile.ManufacturerRecordHash.ToXML(di)) + ), + new XElement( + tns + "CompletedVehicle", + + new XElement(tns + XMLNames.Component_Manufacturer, modelData.VehicleData.Manufacturer), + new XElement(tns + XMLNames.Component_ManufacturerAddress, + modelData.VehicleData.ManufacturerAddress) + ), + + new XElement(tns + XMLNames.Vehicle_VIN, modelData.VehicleData.VIN), + new XElement(tns + "VehicleCategory", modelData.VehicleData.LegislativeClass.ToXMLFormat()), + new XElement(tns + XMLNames.Report_Vehicle_VehicleGroup, + modelData.VehicleData.VehicleClass.GetClassNumber()), + new XElement(tns + XMLNames.Vehicle_RegisteredClass, + modelData.VehicleData.RegisteredClass.ToXMLFormat()), + new XElement(tns + XMLNames.Vehicle_VehicleCode, modelData.VehicleData.VehicleCode.ToXMLFormat()), + + new XElement( + tns + XMLNames.TPMLM, + XMLHelper.ValueAsUnit(modelData.VehicleData.GrossVehicleMass, XMLNames.Unit_t, 1)), + new XElement( + tns + XMLNames.Vehicle_CurbMassChassis, + XMLHelper.ValueAsUnit(modelData.VehicleData.CurbMass, XMLNames.Unit_kg)), + new XElement(tns + XMLNames.Vehicle_ZeroEmissionVehicle, modelData.VehicleData.ZeroEmissionVehicle), + + new XElement(tns + XMLNames.Vehicle_AxleConfiguration, + modelData.VehicleData.AxleConfiguration.GetName()), + //new XElement(tns + XMLNames.Vehicle_VocationalVehicle, modelData.VehicleData.VocationalVehicle), + //new XElement(tns + XMLNames.Vehicle_SleeperCab, modelData.VehicleData.SleeperCab), + new XElement( + tns + "RegisteredPassengers", + modelData.VehicleData.InputData.NumberPassengerSeatsLowerDeck + + modelData.VehicleData.InputData.NumberPassengerSeatsUpperDeck + ), + new XElement(tns + XMLNames.Bus_LowEntry, modelData.VehicleData.InputData.LowEntry), + new XElement(tns + XMLNames.Bus_HeighIntegratedBody, + modelData.VehicleData.InputData.Height.ToXMLFormat(3)) + ); + VehiclePart.Add( + new XElement(tns + "SumNetPower", XMLHelper.ValueAsUnit(modelData.VehicleData.MaxNetPower1, XMLNames.Unit_W)) + ); + + InputDataIntegrity = new XElement(tns + XMLNames.Report_InputDataSignature, + modelData.InputDataHash == null ? XMLHelper.CreateDummySig(di) : new XElement(modelData.InputDataHash)); + + Results.Add(new XElement(tns + XMLNames.Report_ExemptedVehicle)); + } + + public override void WriteResult(XMLDeclarationReport.ResultEntry genericResult, XMLDeclarationReport.ResultEntry specificResult, IResult primaryResult) + { + // no results for exempted + } + + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/XML/AbstractXMLManufacturerReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/AbstractXMLManufacturerReport.cs similarity index 97% rename from VectoCore/VectoCore/OutputData/XML/AbstractXMLManufacturerReport.cs rename to VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/AbstractXMLManufacturerReport.cs index cb7a0e1a59b73a61a402a03c5b20cb9238759edb..4d5f123ef363ab9f8c7ee63f73d7619f18f4b060 100644 --- a/VectoCore/VectoCore/OutputData/XML/AbstractXMLManufacturerReport.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/AbstractXMLManufacturerReport.cs @@ -18,16 +18,8 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; using TUGraz.VectoCore.Utils; using TUGraz.VectoHashing; -namespace TUGraz.VectoCore.OutputData.XML +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport { - public interface IXMLManufacturerReport - { - void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes); - XDocument Report { get; } - void WriteResult(XMLDeclarationReport.ResultEntry resultValue); - void GenerateReport(); - } - public abstract class AbstractXMLManufacturerReport : IXMLManufacturerReport { protected XElement VehiclePart; @@ -38,10 +30,12 @@ namespace TUGraz.VectoCore.OutputData.XML protected XNamespace xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance"); protected XNamespace tns = "urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.8"; + protected XNamespace vns; protected XNamespace di = "http://www.w3.org/2000/09/xmldsig#"; protected AbstractXMLManufacturerReport() { + vns = "urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.8"; VehiclePart = new XElement(tns + XMLNames.Component_Vehicle); Results = new XElement(tns + XMLNames.Report_Results); } @@ -67,16 +61,17 @@ namespace TUGraz.VectoCore.OutputData.XML //new XAttribute("schemaVersion", CURRENT_SCHEMA_VERSION), new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName), - new XAttribute("xmlns", tns), + new XAttribute("xmlns", vns), new XAttribute(XNamespace.Xmlns + "di", di), - //new XAttribute(XNamespace.Xmlns + "tns", tns), - new XAttribute(XNamespace.Xmlns + "mrf", mrf), + new XAttribute(XNamespace.Xmlns + "tns", tns), + new XAttribute(XNamespace.Xmlns + "vns", vns), + new XAttribute(XNamespace.Xmlns + "mrf", mrf), new XAttribute( xsi + "schemaLocation", $"{mrf} {AbstractXMLWriter.SchemaLocationBaseUrl}/DEV/VectoOutputManufacturer.xsd"), new XElement( mrf + XMLNames.Report_DataWrap, - new XAttribute(xsi + "type", "VectoOutputDataType"), + new XAttribute(xsi + "type", "tns:VectoOutputDataType"), vehicle, results, GetApplicationInfo()) @@ -229,7 +224,7 @@ namespace TUGraz.VectoCore.OutputData.XML protected virtual XElement GetInputDataSignature(VectoRunData modelData) { return new XElement( - tns + XMLNames.Report_Input_Signature, + vns + XMLNames.Report_Input_Signature, modelData.InputDataHash == null ? CreateDummySig() : new XElement(modelData.InputDataHash)); } diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/IXMLManufacturerReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/IXMLManufacturerReport.cs new file mode 100644 index 0000000000000000000000000000000000000000..7bc13048203c9b0ff9e7fdfcb92f36b5b4a96ef3 --- /dev/null +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/IXMLManufacturerReport.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Xml.Linq; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; + +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport +{ + public interface IXMLManufacturerReport + { + void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes); + XDocument Report { get; } + void WriteResult(XMLDeclarationReport.ResultEntry resultValue); + void GenerateReport(); + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/XML/XMLManufacturerReportCompletedBus.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportCompletedBus.cs similarity index 97% rename from VectoCore/VectoCore/OutputData/XML/XMLManufacturerReportCompletedBus.cs rename to VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportCompletedBus.cs index cd7913d111f4b0d351b50352cb99edfeb7e9de7f..bec09199c00db40d99da4d367038c4d9eaad783a 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLManufacturerReportCompletedBus.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportCompletedBus.cs @@ -14,9 +14,10 @@ using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Utils; -namespace TUGraz.VectoCore.OutputData.XML { +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport { public class XMLManufacturerReportCompletedBus : AbstractXMLManufacturerReport { + protected TankSystem? _tankSystem; public IPrimaryVehicleInformationInputDataProvider PrimaryVehicleRecordFile { get; set; } @@ -27,6 +28,7 @@ namespace TUGraz.VectoCore.OutputData.XML { public override void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) { + _tankSystem = modelData.VehicleData.InputData.TankSystem; VehiclePart.Add( new XAttribute(xsi + "type", "VehicleCompletedBusType"), GetPrimaryVehicleInformation(), @@ -65,7 +67,7 @@ namespace TUGraz.VectoCore.OutputData.XML { ); } - private XElement GetPrimaryVehicleInformation() + protected XElement GetPrimaryVehicleInformation() { return new XElement( tns + "PrimaryVehicle", @@ -74,8 +76,8 @@ namespace TUGraz.VectoCore.OutputData.XML { new XElement(tns + XMLNames.Vehicle_AxleConfiguration, PrimaryVehicle.AxleConfiguration.ToXMLFormat()), new XElement(tns + XMLNames.Report_InputDataSignature, PrimaryVehicleRecordFile.PrimaryVehicleInputDataHash.ToXML(di)), new XElement(tns + "ManufacturerRecordSignature", PrimaryVehicleRecordFile.ManufacturerRecordHash.ToXML(di)), - new XElement(tns + "VehicleInformationSignature", PrimaryVehicleRecordFile.XMLHash) - ); + new XElement(tns + "VehicleInformationSignature", CreateDummySig()) // PrimaryVehicleRecordFile.XMLHash) + ); } public virtual void WriteResult(XMLDeclarationReport.ResultEntry genericResult, XMLDeclarationReport.ResultEntry specificResult, IResult primaryResult) @@ -226,7 +228,7 @@ namespace TUGraz.VectoCore.OutputData.XML { //retVal.Add(new XElement(tns + "FuelConsumptionFactor", factor.ToMinSignificantDigits(4))); foreach (var entry in primaryResult.EnergyConsumption) { var fcEnergy = entry.Value * factor; // J/m - var fuelData = FuelData.Instance().Lookup(entry.Key); + var fuelData = FuelData.Instance().Lookup(entry.Key, _tankSystem); var fcMass = fcEnergy / fuelData.LowerHeatingValueVecto; // kg/m co2Sum += fcMass * fuelData.CO2PerFuelWeight; diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportExemptedCompletedBus.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportExemptedCompletedBus.cs new file mode 100644 index 0000000000000000000000000000000000000000..095ab3214d5d9d00d21a5e36d9266e3cb40b9a05 --- /dev/null +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportExemptedCompletedBus.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.Xml.Linq; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Resources; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport +{ + public class XMLManufacturerReportExemptedCompletedBus : XMLManufacturerReportCompletedBus + { + public override void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) + { + VehiclePart.Add( + new XAttribute(xsi + "type", "VehicleExemptedCompletedBusType"), + GetPrimaryVehicleInformation(), + new XElement( + tns + "CompletedVehicle", + new XElement(tns + XMLNames.Component_Model, modelData.VehicleData.ModelName), + new XElement(tns + XMLNames.Component_Manufacturer, modelData.VehicleData.Manufacturer), + new XElement(tns + XMLNames.Component_ManufacturerAddress, + modelData.VehicleData.ManufacturerAddress), + new XElement(tns + XMLNames.Vehicle_VIN, modelData.VehicleData.VIN), + new XElement(tns + XMLNames.Bus_LegislativeCategory, + modelData.VehicleData.LegislativeClass.ToXMLFormat()), + new XElement(tns + XMLNames.Report_Vehicle_VehicleGroup, + modelData.VehicleData.VehicleClass.GetClassNumber()), + new XElement(tns + XMLNames.Vehicle_RegisteredClass, + modelData.VehicleData.RegisteredClass.ToXMLFormat()), + new XElement(tns + XMLNames.Vehicle_BodyworkCode, modelData.VehicleData.VehicleCode.ToXMLFormat()), + new XElement(tns + XMLNames.Bus_CorrectedActualMass, + XMLHelper.ValueAsUnit(modelData.VehicleData.CurbMass, XMLNames.Unit_kg)), + new XElement(tns + XMLNames.TPMLM, + XMLHelper.ValueAsUnit(modelData.VehicleData.GrossVehicleMass, XMLNames.Unit_t, 2)), + + new XElement(tns + XMLNames.Bus_NumberPassengersLowerDeck, + modelData.VehicleData.InputData.NumberPassengerSeatsLowerDeck), + new XElement(tns + XMLNames.Bus_NumberPassengersUpperDeck, + modelData.VehicleData.InputData.NumberPassengerSeatsUpperDeck), + + new XElement(tns + XMLNames.Vehicle_ZeroEmissionVehicle, modelData.VehicleData.ZeroEmissionVehicle), + new XElement(tns + XMLNames.Bus_LowEntry, modelData.VehicleData.InputData.LowEntry), + new XElement(tns + XMLNames.Bus_HeighIntegratedBody, + modelData.VehicleData.InputData.Height.ToXMLFormat(3)), + + GetInputDataSignature(modelData) + ) + ); + + Results.Add(new XElement(tns + XMLNames.Report_ExemptedVehicle)); + } + + + public override void WriteResult(XMLDeclarationReport.ResultEntry genericResult, + XMLDeclarationReport.ResultEntry specificResult, IResult primaryResult) + { + + // no results to write... + } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/XML/XMLManufacturerReportExemptedTruck.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportExemptedTruck.cs similarity index 96% rename from VectoCore/VectoCore/OutputData/XML/XMLManufacturerReportExemptedTruck.cs rename to VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportExemptedTruck.cs index 510bae3f30ee10216dfb476141a512a27cdbaac8..1fe9400d30dc7511c957873c074bad77509cf8f8 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLManufacturerReportExemptedTruck.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportExemptedTruck.cs @@ -6,7 +6,8 @@ using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Utils; -namespace TUGraz.VectoCore.OutputData.XML { +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport +{ public class XMLManufacturerReportExemptedTruck : AbstractXMLManufacturerReport { public override void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportExeptedPrimaryBus.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportExeptedPrimaryBus.cs new file mode 100644 index 0000000000000000000000000000000000000000..018177047aeccd2ac9b40f807feda5a93b50b5af --- /dev/null +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportExeptedPrimaryBus.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Xml.Linq; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Resources; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport +{ + public class XMLManufacturerReportExeptedPrimaryBus : AbstractXMLManufacturerReport + { + + public XMLManufacturerReportExeptedPrimaryBus() + { + vns = "urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.8"; + } + + public override void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) + { + VehiclePart.Add( + new XAttribute(xsi + "type", "VehicleExemptedPrimaryBusType"), + new XElement(vns + XMLNames.Component_Manufacturer, modelData.VehicleData.Manufacturer), + new XElement(vns + XMLNames.Component_ManufacturerAddress, modelData.VehicleData.ManufacturerAddress), + new XElement(vns + XMLNames.Component_Model, modelData.VehicleData.ModelName), + new XElement(vns + XMLNames.Vehicle_VIN, modelData.VehicleData.VIN), + new XElement(vns + "LegislativeCategory", modelData.VehicleData.LegislativeClass.ToXMLFormat()), + new XElement(vns + XMLNames.Bus_ChassisConfiguration, "Bus"), + new XElement(vns + XMLNames.Vehicle_AxleConfiguration, modelData.VehicleData.AxleConfiguration.GetName()), + new XElement(vns + XMLNames.Vehicle_Articulated, modelData.VehicleData.InputData.Articulated), + new XElement( + vns + XMLNames.Vehicle_TPMLM, + XMLHelper.ValueAsUnit(modelData.VehicleData.GrossVehicleMass, XMLNames.Unit_kg, 1)), + //new XElement( + // tns + XMLNames.Vehicle_CurbMassChassis, XMLHelper.ValueAsUnit(modelData.VehicleData.CurbMass, XMLNames.Unit_kg)), + new XElement(vns + XMLNames.Vehicle_ZeroEmissionVehicle, modelData.VehicleData.ZeroEmissionVehicle), + new XElement(vns + "SumNetPower", XMLHelper.ValueAsUnit(modelData.VehicleData.MaxNetPower1, XMLNames.Unit_W)), + new XElement(vns + "Technology", modelData.VehicleData.InputData.ExemptedTechnology) + + ); + Results.Add(new XElement(tns + XMLNames.Report_ExemptedVehicle)); + + InputDataIntegrity = GetInputDataSignature(modelData); + } + + protected override XElement VehicleComponents(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) + { + return null; + } + + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/XML/XMLManufacturerReportPrimaryBus.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportPrimaryBus.cs similarity index 97% rename from VectoCore/VectoCore/OutputData/XML/XMLManufacturerReportPrimaryBus.cs rename to VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportPrimaryBus.cs index 5720b3f3f9ed9211b19f283842878b363825ba99..d3011bc2e24c6ec332db6655ccb50769df229bce 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLManufacturerReportPrimaryBus.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportPrimaryBus.cs @@ -5,6 +5,7 @@ using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Resources; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.OutputData.XML { diff --git a/VectoCore/VectoCore/OutputData/XML/XMLManufacturerReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportTruck.cs similarity index 98% rename from VectoCore/VectoCore/OutputData/XML/XMLManufacturerReport.cs rename to VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportTruck.cs index ac924037bf5b2c3d9034e47e95ff5cf607348c4b..610ba2f20e1d985d1f16c423f2c1b00f45bbc226 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLManufacturerReport.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/ManufacturerReport/XMLManufacturerReportTruck.cs @@ -38,7 +38,7 @@ using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Utils; -namespace TUGraz.VectoCore.OutputData.XML +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport { public class XMLManufacturerReportTruck : AbstractXMLManufacturerReport { diff --git a/VectoCore/VectoCore/OutputData/XML/XMLVTPReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VTPReport/XMLVTPReport.cs similarity index 100% rename from VectoCore/VectoCore/OutputData/XML/XMLVTPReport.cs rename to VectoCore/VectoCore/OutputData/XML/DeclarationReports/VTPReport/XMLVTPReport.cs diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/IXMLMultistageReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/IXMLMultistageReport.cs new file mode 100644 index 0000000000000000000000000000000000000000..8111f0f90327ad62916024eb1a0593f6d8343f86 --- /dev/null +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/IXMLMultistageReport.cs @@ -0,0 +1,12 @@ +using System.Xml.Linq; +using TUGraz.VectoCore.Models.Simulation.Data; + +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.VehicleInformationFile +{ + public interface IXMLMultistageReport + { + void Initialize(VectoRunData modelData); + XDocument Report { get; } + void GenerateReport(); + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/IXMLPrimaryVehicleReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/IXMLPrimaryVehicleReport.cs new file mode 100644 index 0000000000000000000000000000000000000000..f28672258a5e8043e12bedfe8736f3b5c85ba629 --- /dev/null +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/IXMLPrimaryVehicleReport.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Xml.Linq; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; + +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.VehicleInformationFile +{ + public interface IXMLPrimaryVehicleReport + { + void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes); + void WriteResult(XMLDeclarationReport.ResultEntry result); + void GenerateReport(XElement fullReportHash); + XDocument Report { get; } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/XMLExemptedPrimaryBusVehicleReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/XMLExemptedPrimaryBusVehicleReport.cs new file mode 100644 index 0000000000000000000000000000000000000000..7857a92f0ad86356aad18f5c8e50bfc8381b162c --- /dev/null +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/XMLExemptedPrimaryBusVehicleReport.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using System.Xml.Linq; +using TUGraz.VectoCommon.Hashing; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Resources; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.VehicleInformationFile +{ + public class XMLExemptedPrimaryBusVehicleReport : XMLPrimaryBusVehicleReport + { + #region Implementation of IXMLPrimaryVehicleReport + + public override void Initialize(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) + { + VehiclePart.Add( + new XAttribute(xsi + "type", "VehicleExemptedPrimaryBusType"), + new XElement(tns + XMLNames.Component_Manufacturer, modelData.VehicleData.Manufacturer), + new XElement(tns + XMLNames.Component_ManufacturerAddress, modelData.VehicleData.ManufacturerAddress), + new XElement(tns + XMLNames.Component_Model, modelData.VehicleData.ModelName), + new XElement(tns + XMLNames.Vehicle_VIN, modelData.VehicleData.VIN), + new XElement(tns + "LegislativeCategory", modelData.VehicleData.LegislativeClass.ToXMLFormat()), + new XElement(tns + XMLNames.Bus_ChassisConfiguration, "Bus"), + new XElement(tns + XMLNames.Vehicle_AxleConfiguration, modelData.VehicleData.AxleConfiguration.GetName()), + new XElement(tns + XMLNames.Vehicle_Articulated, modelData.VehicleData.InputData.Articulated), + new XElement( + tns + XMLNames.Vehicle_TPMLM, + XMLHelper.ValueAsUnit(modelData.VehicleData.GrossVehicleMass, XMLNames.Unit_kg, 1)), + //new XElement( + // tns + XMLNames.Vehicle_CurbMassChassis, XMLHelper.ValueAsUnit(modelData.VehicleData.CurbMass, XMLNames.Unit_kg)), + new XElement(tns + XMLNames.Vehicle_ZeroEmissionVehicle, modelData.VehicleData.ZeroEmissionVehicle), + new XElement(tns + "SumNetPower", XMLHelper.ValueAsUnit(modelData.VehicleData.MaxNetPower1, XMLNames.Unit_W)), + new XElement(tns + "Technology", modelData.VehicleData.InputData.ExemptedTechnology) + + ); + Results.Add(new XElement(tns + XMLNames.Report_ExemptedVehicle)); + + InputDataIntegrity = new XElement(tns + XMLNames.Report_InputDataSignature, + modelData.InputDataHash == null ? XMLHelper.CreateDummySig(di) : new XElement(modelData.InputDataHash)); + + } + + public override void WriteResult(XMLDeclarationReport.ResultEntry result) + { + // no results for exempted vehicle + } + + + #endregion + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/XML/XMLMultistageBusReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/XMLMultistageBusReport.cs similarity index 87% rename from VectoCore/VectoCore/OutputData/XML/XMLMultistageBusReport.cs rename to VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/XMLMultistageBusReport.cs index 106ef6b5d02102fa977ed58382f0fc881e618764..7548a6139dcc0cc77a77d8fcbf1086445d93df0b 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLMultistageBusReport.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/XMLMultistageBusReport.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Security.Cryptography; @@ -18,14 +19,46 @@ using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Utils; using TUGraz.VectoHashing; - -namespace TUGraz.VectoCore.OutputData.XML +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.VehicleInformationFile { - public interface IXMLMultistageReport + public class XMLMultistageExemptedBusReport : XMLMultistageBusReport { - void Initialize(VectoRunData modelData); - XDocument Report { get; } - void GenerateReport(); + protected override XElement GetVehicleElement(string vehicleId) + { + return new XElement(tns + XMLNames.Tag_Vehicle, + new XAttribute(xsi + XMLNames.Attr_Type, "v2.8:ExemptedInterimStageInputType"), + new XAttribute(XMLNames.Component_ID_Attr, vehicleId), + new XElement(v28 + XMLNames.Component_Manufacturer, _vehicleInputData.Manufacturer), + new XElement(v28 + XMLNames.Component_ManufacturerAddress, _vehicleInputData.ManufacturerAddress), + new XElement(v28 + XMLNames.Vehicle_VIN, _vehicleInputData.VIN), + new XElement(v28 + XMLNames.Component_Date, + XmlConvert.ToString(_vehicleInputData.Date, XmlDateTimeSerializationMode.Utc)), + _vehicleInputData.Model != null + ? new XElement(v28 + XMLNames.Component_Model, _vehicleInputData.Model) : null, + _vehicleInputData.LegislativeClass != null + ? new XElement(v28 + XMLNames.Bus_LegislativeCategory, _vehicleInputData.LegislativeClass.ToXMLFormat()) : null, + _vehicleInputData.CurbMassChassis != null + ? new XElement(v28 + XMLNames.Bus_CorrectedActualMass, _vehicleInputData.CurbMassChassis.ToXMLFormat(0)) : null, + _vehicleInputData.GrossVehicleMassRating != null + ? new XElement(v28 + XMLNames.TPMLM, _vehicleInputData.GrossVehicleMassRating.ToXMLFormat(0)) : null, + _vehicleInputData.RegisteredClass != null + ? new XElement(v28 + XMLNames.Vehicle_RegisteredClass, _vehicleInputData.RegisteredClass.ToXMLFormat()) : null, + _vehicleInputData.NumberPassengerSeatsLowerDeck != null + ? new XElement(v28 + XMLNames.Bus_NumberPassengerSeatsLowerDeck, _vehicleInputData.NumberPassengerSeatsLowerDeck) : null, + _vehicleInputData.NumberPassengersStandingLowerDeck != null + ? new XElement(v28 + XMLNames.Bus_NumberPassengersStandingLowerDeck, _vehicleInputData.NumberPassengersStandingLowerDeck) : null, + _vehicleInputData.NumberPassengerSeatsUpperDeck != null + ? new XElement(v28 + XMLNames.Bus_NumberPassengerSeatsUpperDeck, _vehicleInputData.NumberPassengerSeatsUpperDeck) : null, + _vehicleInputData.NumberPassengersStandingUpperDeck != null + ? new XElement(v28 + XMLNames.Bus_NumberPassengersStandingUpperDeck, _vehicleInputData.NumberPassengersStandingUpperDeck) : null, + _vehicleInputData.VehicleCode != null + ? new XElement(v28 + XMLNames.Vehicle_BodyworkCode, _vehicleInputData.VehicleCode.ToXMLFormat()) : null, + _vehicleInputData.LowEntry != null + ? new XElement(v28 + XMLNames.Bus_LowEntry, _vehicleInputData.LowEntry) : null, + _vehicleInputData.Height != null + ? new XElement(v28 + XMLNames.Bus_HeighIntegratedBody, _vehicleInputData.Height.ConvertToMilliMeter().ToXMLFormat(0)) : null + ); + } } public class XMLMultistageBusReport: IXMLMultistageReport @@ -38,7 +71,7 @@ namespace TUGraz.VectoCore.OutputData.XML protected XNamespace v23 = "urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3"; protected XNamespace v28 = "urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8"; protected XNamespace v10 = "urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0"; - + private XElement _primaryVehicle; private List<XElement> _manufacturingStages; private List<XAttribute> _namespaceAttributes; @@ -46,7 +79,7 @@ namespace TUGraz.VectoCore.OutputData.XML private IPrimaryVehicleInformationInputDataProvider _primaryVehicleInputData; private IList<IManufacturingStageInputData> _manufacturingStageInputData; private IManufacturingStageInputData _consolidatedInputData; - private IVehicleDeclarationInputData _vehicleInputData; + protected IVehicleDeclarationInputData _vehicleInputData; public XDocument Report { get; protected set; } @@ -57,7 +90,7 @@ namespace TUGraz.VectoCore.OutputData.XML _namespaceAttributes = new List<XAttribute>(); } - public void Initialize(VectoRunData modelData) + public virtual void Initialize(VectoRunData modelData) { _primaryVehicleInputData = modelData.MultistageVIFInputData.MultistageJobInputData.JobInputData.PrimaryVehicle; _manufacturingStageInputData = modelData.MultistageVIFInputData.MultistageJobInputData.JobInputData.ManufacturingStages; @@ -147,7 +180,7 @@ namespace TUGraz.VectoCore.OutputData.XML #endregion - public void GenerateReport() + public virtual void GenerateReport() { var retVal = new XDocument(); retVal.Add( @@ -218,7 +251,7 @@ namespace TUGraz.VectoCore.OutputData.XML } - private XElement GetVehicleElement(string vehicleId) + protected virtual XElement GetVehicleElement(string vehicleId) { return new XElement(tns + XMLNames.Tag_Vehicle, new XAttribute(xsi + XMLNames.Attr_Type, "v2.8:InterimStageInputType"), @@ -361,7 +394,8 @@ namespace TUGraz.VectoCore.OutputData.XML return new XElement(v28 + XMLNames.Component_AirDrag, new XElement(v20 + XMLNames.Report_DataWrap, new XAttribute(xsi + XMLNames.Component_Type_Attr, XMLNames.AirDrag_Data_Type_Attr), - new XAttribute("xmlns", v10.NamespaceName), + //new XAttribute("xmlns", v10.NamespaceName), + new XAttribute(XNamespace.Xmlns + "v1.0", v10.NamespaceName), dataNode.Attributes != null && dataNode.Attributes[XMLNames.Component_ID_Attr] != null ? new XAttribute(XMLNames.Component_ID_Attr, dataNode.Attributes[XMLNames.Component_ID_Attr].InnerText) : null, GetElements(dataNode.ChildNodes) diff --git a/VectoCore/VectoCore/OutputData/XML/XMLPrimaryVehicleReport.cs b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/XMLPrimaryBusVehicleReport.cs similarity index 94% rename from VectoCore/VectoCore/OutputData/XML/XMLPrimaryVehicleReport.cs rename to VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/XMLPrimaryBusVehicleReport.cs index 8d7a69cbe730936ccba434e253431ccccd74a178..a016a410dd9f68f0e61797cbf0daa8b3b1bb4d17 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLPrimaryVehicleReport.cs +++ b/VectoCore/VectoCore/OutputData/XML/DeclarationReports/VehicleInformationFile/XMLPrimaryBusVehicleReport.cs @@ -21,9 +21,9 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; using TUGraz.VectoCore.Utils; using TUGraz.VectoHashing; -namespace TUGraz.VectoCore.OutputData.XML +namespace TUGraz.VectoCore.OutputData.XML.DeclarationReports.VehicleInformationFile { - public class XMLPrimaryVehicleReport + public class XMLPrimaryBusVehicleReport : IXMLPrimaryVehicleReport { protected XNamespace tns = "urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1"; protected XNamespace di = "http://www.w3.org/2000/09/xmldsig#"; @@ -40,19 +40,19 @@ namespace TUGraz.VectoCore.OutputData.XML protected XElement InputDataIntegrity; protected XElement Results; - private bool _allSuccess = true; + protected bool _allSuccess = true; - public XMLPrimaryVehicleReport() + public XMLPrimaryBusVehicleReport() { VehiclePart = new XElement(tns + XMLNames.Component_Vehicle); Results = new XElement(tns + XMLNames.Report_Results); } - public XDocument Report { get; private set; } + public XDocument Report { get; protected set; } - public void GenerateReport(XElement resultSignature) + public virtual void GenerateReport(XElement resultSignature) { var retVal = new XDocument(); retVal.Add( @@ -73,7 +73,7 @@ namespace TUGraz.VectoCore.OutputData.XML Report = retVal; } - private XElement GeneratePrimaryVehicle(XElement resultSignature) + protected virtual XElement GeneratePrimaryVehicle(XElement resultSignature) { var results = new XElement(Results); results.AddFirst(new XElement(tns + XMLNames.Report_Result_Status, _allSuccess ? "success" : "error")); @@ -95,7 +95,7 @@ namespace TUGraz.VectoCore.OutputData.XML return primaryVehicle; } - private XElement GetSignatureElement(XElement stage) + protected XElement GetSignatureElement(XElement stage) { var stream = new MemoryStream(); var writer = new StreamWriter(stream); @@ -108,7 +108,7 @@ namespace TUGraz.VectoCore.OutputData.XML (VectoHash.DefaultCanonicalizationMethod, VectoHash.DefaultDigestMethod)); } - private XElement GetApplicationInfo() + protected XElement GetApplicationInfo() { var versionNumber = VectoSimulationCore.VersionNumber; #if CERTIFICATION_RELEASE // add nothing to version number @@ -342,15 +342,15 @@ namespace TUGraz.VectoCore.OutputData.XML private XElement GetPneumaticSystem(IPneumaticSupplyDeclarationData supply, IPneumaticConsumersDeclarationData consumer) { return new XElement(tns + XMLNames.BusAux_PneumaticSystem, - new XElement(tns + XMLNames.Bus_SizeOfAirSupply, supply.CompressorSize), - new XElement(tns + XMLNames.CompressorDrive, supply.CompressorDrive.GetLabel()), - new XElement(tns + XMLNames.Vehicle_Clutch, supply.Clutch), - new XElement(tns + XMLNames.Bus_CompressorRatio, supply.Ratio.ToMinSignificantDigits(3)), - new XElement(tns + XMLNames.Bus_SmartCompressionSystem, supply.SmartAirCompression), - new XElement(tns + XMLNames.Bus_SmartRegenerationSystem, supply.SmartRegeneration), - new XElement(tns + XMLNames.Bus_AirsuspensionControl, GetXMLAirsuspensionControl(consumer.AirsuspensionControl)), - new XElement(tns + XMLNames.BusAux_PneumaticSystem_SCRReagentDosing, consumer.AdBlueDosing == ConsumerTechnology.Pneumatically) - ); + new XElement(tns + XMLNames.Bus_SizeOfAirSupply, supply.CompressorSize), + new XElement(tns + XMLNames.CompressorDrive, supply.CompressorDrive.GetLabel()), + new XElement(tns + XMLNames.Vehicle_Clutch, supply.Clutch), + new XElement(tns + XMLNames.Bus_CompressorRatio, supply.Ratio.ToXMLFormat(3)), + new XElement(tns + XMLNames.Bus_SmartCompressionSystem, supply.SmartAirCompression), + new XElement(tns + XMLNames.Bus_SmartRegenerationSystem, supply.SmartRegeneration), + new XElement(tns + XMLNames.Bus_AirsuspensionControl, GetXMLAirsuspensionControl(consumer.AirsuspensionControl)), + new XElement(tns + XMLNames.BusAux_PneumaticSystem_SCRReagentDosing, consumer.AdBlueDosing == ConsumerTechnology.Pneumatically) + ); } private string GetXMLAirsuspensionControl(ConsumerTechnology airsuspensionControl) @@ -518,7 +518,7 @@ namespace TUGraz.VectoCore.OutputData.XML }; } - public void WriteResult(XMLDeclarationReport.ResultEntry resultEntry) + public virtual void WriteResult(XMLDeclarationReport.ResultEntry resultEntry) { _allSuccess &= resultEntry.Status == VectoRun.Status.Success; @@ -594,11 +594,10 @@ namespace TUGraz.VectoCore.OutputData.XML return retVal.Cast<object>().ToArray(); } - - private string GetGUID() + + protected string GetGUID() { return Guid.NewGuid().ToString("n").Substring(0, 20); } } - } diff --git a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs index cc7f166f39fc28ee77542a69b6e5f18cf1228666..46bec9b30a77f889c26d81e3bee348be4405cd4f 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs +++ b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReport.cs @@ -46,6 +46,8 @@ using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport; namespace TUGraz.VectoCore.OutputData.XML { @@ -53,7 +55,7 @@ namespace TUGraz.VectoCore.OutputData.XML { protected IXMLManufacturerReport ManufacturerRpt; - protected XMLCustomerReport CustomerRpt; + protected IXMLCustomerReport CustomerRpt; protected IDictionary<Tuple<MissionType, LoadingType>, double> _weightingFactors; diff --git a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportCompletedVehicle.cs b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportCompletedVehicle.cs index 850db9412d924e5e8ec3ef42cf45207855331f94..18d8a1e85ecdd895948090b3846024ae1743645a 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportCompletedVehicle.cs +++ b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportCompletedVehicle.cs @@ -7,6 +7,8 @@ using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport; namespace TUGraz.VectoCore.OutputData.XML { public class XMLDeclarationReportCompletedVehicle : XMLDeclarationReport @@ -19,12 +21,20 @@ namespace TUGraz.VectoCore.OutputData.XML { protected override void InstantiateReports(VectoRunData modelData) { - ManufacturerRpt = new XMLManufacturerReportCompletedBus() { - PrimaryVehicleRecordFile = PrimaryVehicleReportInputData - }; - CustomerRpt = new XMLCustomerReportCompletedBus() { - PrimaryVehicleRecordFile = PrimaryVehicleReportInputData - }; + ManufacturerRpt = modelData.Exempted + ? new XMLManufacturerReportExemptedCompletedBus() { + PrimaryVehicleRecordFile = PrimaryVehicleReportInputData + } + : new XMLManufacturerReportCompletedBus() { + PrimaryVehicleRecordFile = PrimaryVehicleReportInputData + }; + CustomerRpt = modelData.Exempted + ? new XMLCustomerReportExemptedCompletedBus() { + PrimaryVehicleRecordFile = PrimaryVehicleReportInputData + } + : new XMLCustomerReportCompletedBus() { + PrimaryVehicleRecordFile = PrimaryVehicleReportInputData + }; } public override void InitializeReport(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) diff --git a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportMultistageBusVehicle.cs b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportMultistageBusVehicle.cs index 09aff714f79cb82f3aeba8dd5481805f0428572a..c2ba05703732a8c25a4d0f5e6a8123828388ab17 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportMultistageBusVehicle.cs +++ b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportMultistageBusVehicle.cs @@ -5,21 +5,24 @@ using System.Text; using System.Threading.Tasks; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.VehicleInformationFile; namespace TUGraz.VectoCore.OutputData.XML { public class XMLDeclarationReportMultistageBusVehicle : XMLDeclarationReport { - private readonly XMLMultistageBusReport _multistageBusReport; + private IXMLMultistageReport _multistageBusReport; public XMLDeclarationReportMultistageBusVehicle(IReportWriter writer) : base(writer) { - _multistageBusReport = new XMLMultistageBusReport(); + //_multistageBusReport = new XMLMultistageBusReport(); } public override void InitializeReport(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) { + _multistageBusReport = + modelData.Exempted ? new XMLMultistageExemptedBusReport() : new XMLMultistageBusReport(); _multistageBusReport.Initialize(modelData); } diff --git a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportPrimaryVehicle.cs b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportPrimaryVehicle.cs index b175bac434da38fcbc56b375526f095b23c584e1..36bdb48f59d0c32501569a67a651132268576c30 100644 --- a/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportPrimaryVehicle.cs +++ b/VectoCore/VectoCore/OutputData/XML/XMLDeclarationReportPrimaryVehicle.cs @@ -3,35 +3,47 @@ using System.Collections.Generic; using System.Xml.Linq; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.CustomerInformationFile; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.VehicleInformationFile; namespace TUGraz.VectoCore.OutputData.XML { public class XMLDeclarationReportPrimaryVehicle : XMLDeclarationReport { - private XMLPrimaryVehicleReport _primaryReport; + protected IXMLPrimaryVehicleReport PrimaryReport; public XMLDeclarationReportPrimaryVehicle(IReportWriter writer, bool writePIF = false) : base(writer) { - _primaryReport = new XMLPrimaryVehicleReport(); } public override XDocument CustomerReport => null; - public override XDocument PrimaryVehicleReport => _primaryReport?.Report; + public override XDocument PrimaryVehicleReport => PrimaryReport?.Report; #region Overrides of XMLDeclarationReport protected override void InstantiateReports(VectoRunData modelData) { - ManufacturerRpt = new XMLManufacturerReportPrimaryBus(); - CustomerRpt = new XMLCustomerReport(); + if (modelData.Exempted) { + ManufacturerRpt = new XMLManufacturerReportExeptedPrimaryBus(); + CustomerRpt = new XMLCustomerReportExemptedPrimaryBus(); + PrimaryReport = new XMLExemptedPrimaryBusVehicleReport(); + + } else { + ManufacturerRpt = new XMLManufacturerReportPrimaryBus(); + CustomerRpt = new XMLCustomerReport(); + PrimaryReport = new XMLPrimaryBusVehicleReport(); + } + + } public override void InitializeReport(VectoRunData modelData, List<List<FuelData.Entry>> fuelModes) { base.InitializeReport(modelData, fuelModes); - _primaryReport.Initialize(modelData,fuelModes); + PrimaryReport.Initialize(modelData,fuelModes); } @@ -39,7 +51,7 @@ namespace TUGraz.VectoCore.OutputData.XML { protected override void WriteResult(ResultEntry result) { base.WriteResult(result); - _primaryReport.WriteResult(result); + PrimaryReport.WriteResult(result); } protected override void GenerateReports() @@ -47,7 +59,7 @@ namespace TUGraz.VectoCore.OutputData.XML { ManufacturerRpt.GenerateReport(); var fullReportHash = GetSignature(ManufacturerRpt.Report); CustomerRpt.GenerateReport(fullReportHash); - _primaryReport.GenerateReport(fullReportHash); + PrimaryReport.GenerateReport(fullReportHash); } @@ -55,7 +67,7 @@ namespace TUGraz.VectoCore.OutputData.XML { protected override void OutputReports() { Writer.WriteReport(ReportType.DeclarationReportManufacturerXML, ManufacturerRpt.Report); - Writer.WriteReport(ReportType.DeclarationReportPrimaryVehicleXML, _primaryReport.Report); + Writer.WriteReport(ReportType.DeclarationReportPrimaryVehicleXML, PrimaryReport.Report); } #endregion diff --git a/VectoCore/VectoCore/OutputData/XML/XMLMonitoringReport.cs b/VectoCore/VectoCore/OutputData/XML/XMLMonitoringReport.cs deleted file mode 100644 index 47aff5e005b6e0810cc1341ea5252d9a7f39e0fe..0000000000000000000000000000000000000000 --- a/VectoCore/VectoCore/OutputData/XML/XMLMonitoringReport.cs +++ /dev/null @@ -1,217 +0,0 @@ -/* -* This file is part of VECTO. -* -* Copyright © 2012-2019 European Union -* -* Developed by Graz University of Technology, -* Institute of Internal Combustion Engines and Thermodynamics, -* Institute of Technical Informatics -* -* VECTO is licensed under the EUPL, Version 1.1 or - as soon they will be approved -* by the European Commission - subsequent versions of the EUPL (the "Licence"); -* You may not use VECTO except in compliance with the Licence. -* You may obtain a copy of the Licence at: -* -* https://joinup.ec.europa.eu/community/eupl/og_page/eupl -* -* Unless required by applicable law or agreed to in writing, VECTO -* distributed under the Licence is distributed on an "AS IS" basis, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the Licence for the specific language governing permissions and -* limitations under the Licence. -* -* Authors: -* Stefan Hausberger, hausberger@ivt.tugraz.at, IVT, Graz University of Technology -* Christian Kreiner, christian.kreiner@tugraz.at, ITI, Graz University of Technology -* Michael Krisper, michael.krisper@tugraz.at, ITI, Graz University of Technology -* Raphael Luz, luz@ivt.tugraz.at, IVT, Graz University of Technology -* Markus Quaritsch, markus.quaritsch@tugraz.at, IVT, Graz University of Technology -* Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology -*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Xml; -using System.Xml.Linq; -using System.Xml.Schema; -using System.Xml.XPath; -using TUGraz.IVT.VectoXML.Writer; -using TUGraz.VectoCommon.Models; -using TUGraz.VectoCore.Models.Simulation.Data; -using TUGraz.VectoCore.Utils; -using XmlDocumentType = TUGraz.VectoCore.Utils.XmlDocumentType; - -namespace TUGraz.VectoCore.OutputData.XML -{ - public class XMLMonitoringReport - { - public const string CURRENT_SCHEMA_VERSION = "0.8"; - - public const string NAMESPACE_BASE_URI = "urn:tugraz:ivt:VectoAPI:MonitoringOutput"; - - private readonly IXMLManufacturerReport _manufacturerReport; - - protected XNamespace tns; - protected XNamespace di; - private XElement _additionalFields; - - - public XMLMonitoringReport(IXMLManufacturerReport manufacturerReport) - { - di = "http://www.w3.org/2000/09/xmldsig#"; - tns = NAMESPACE_BASE_URI + ":v" + CURRENT_SCHEMA_VERSION; - _manufacturerReport = manufacturerReport; - } - - public XDocument Report - { - get { - var mrf = _manufacturerReport.Report; - if (mrf == null) { - return null; - } - - var errors = new List<string>(); - var mrfErrors = false; - mrf.Validate(XMLValidator.GetXMLSchema(XmlDocumentType.ManufacturerReport), (o, e) => { - mrfErrors = true; - errors.Add(e.Message); - }, true); - if (mrfErrors) { - LogManager.GetLogger(typeof(XMLMonitoringReport).FullName).Warn("XML Validation of manufacturer record failed! errors: {0}", string.Join(Environment.NewLine, errors)); - } - - var mrfType = mrf.Root?.GetSchemaInfo()?.SchemaType?.QualifiedName ?? new XmlQualifiedName("urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:AbstractVectoOutputManufacturerType"); - - var retVal = GenerateReport(); - var prefix = "mrf" + mrfType.Namespace.Split(':').Last(); - - var xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance"); - - retVal.Root?.Add( - new XAttribute(XNamespace.Xmlns + prefix, mrfType.Namespace), - new XElement( - tns + "ManufacturerRecord", - new XAttribute(xsi + "type", $"{prefix}:{mrfType.Name}"), - new XAttribute("xmlns", mrfType.Namespace), - new XAttribute(XNamespace.Xmlns + "m", tns), - GetManufacturerData(mrf)), - _additionalFields - ); - return retVal; - } - } - - private XmlQualifiedName GetXMLType(XElement mrfRoot) - { - var si = mrfRoot.GetSchemaInfo(); - - return si?.SchemaType?.BaseXmlSchemaType.QualifiedName; - } - - - private object[] GetManufacturerData(XDocument mrf) - { - return mrf.Root?.XPathSelectElements("./*").ToArray<object>(); - } - - private XDocument GenerateReport() - { - var xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance"); - var retVal = new XDocument(); - - //retVal.Add( - // new XProcessingInstruction( - // "xml-stylesheet", "href=\"https://webgate.ec.europa.eu/CITnet/svn/VECTO/trunk/Share/XML/CSS/VectoReports.css\"")); - retVal.Add( - new XElement( - tns + "VectoMonitoring", - new XAttribute("schemaVersion", CURRENT_SCHEMA_VERSION), - new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName), - new XAttribute("xmlns", tns), - new XAttribute(XNamespace.Xmlns + "di", di), - new XAttribute( - xsi + "schemaLocation", - $"{NAMESPACE_BASE_URI} {AbstractXMLWriter.SchemaLocationBaseUrl}VectoMonitoring.xsd") - ) - ); - return retVal; - } - - public void Initialize(VectoRunData modelData) - { - var numAxles = modelData.VehicleData.AxleData?.Count(x => x.AxleType != AxleType.Trailer) ?? 0; - var axleData = new object[numAxles]; - for (var i = 0; i < axleData.Length; i++) { - axleData[i] = new XElement(tns + "Axle", - new XAttribute("axleNumber", i+1), - new XElement(tns + "Tyre", GetStandardFields($"TYRE_{i + 1}") - )); - } - - var components = new object[0]; - if (!modelData.Exempted) { - components = new object[] { - new XElement( - tns + "Engine", - new XElement( - tns + "WHTC", - new XElement(tns + "CO2", XMLHelper.ValueAsUnit(double.NaN, "g/kWh", 0)), - new XElement(tns + "FuelConsumption", XMLHelper.ValueAsUnit(double.NaN, "g/kWh", 0)) - ), - new XElement( - tns + "WHSC", - new XElement(tns + "CO2", XMLHelper.ValueAsUnit(double.NaN, "g/kWh", 0)), - new XElement(tns + "FuelConsumption", XMLHelper.ValueAsUnit(double.NaN, "g/kWh", 0)) - ) - ), - new XElement(tns + "Gearbox", GetStandardFields("GEARBOX")), - new XElement(tns + "Axlegear", GetStandardFields("AXLEGEAR")), - new XElement(tns + "AxleWheels", axleData), - }; - } - _additionalFields = new XElement( - tns + "AdditionalData", - new XElement(tns + "Vehicle", - new XElement(tns + "Make", "##VEHICLE_MAKE##")), - components, - new XElement(tns + "AdvancedReducingTechnologies", new XComment(GetReducingTechnologiesExample())), - new XElement(tns + "VectoLicenseNbr", "##VECTO_LICENSE_NUMBER##") - ); - } - - private object[] GetStandardFields(string prefix) - { - return new[] { - new XElement(tns + "Manufacturer", $"##{prefix}_MANUFACTURER##"), - new XElement(tns + "ManufacturerAddress", $"##{prefix}_MANUFACTURERADDRESS##"), - new XElement(tns + "Make", $"##{prefix}_MAKE##") - }; - } - - private string GetReducingTechnologiesExample() - { - var categories = new[] { - "advanced aerodynamic measures", - "advanced rolling resistance measures", - "advanced drivetrain technologies", - "advanced engine technologies", - "advanced auxiliary technologies", - "additional ADAS technologies", - "advanced powertrain integration and hybridisation", - "other" - }; - var retVal = new object[categories.Length]; - //var tmp = new XElement(tns + "foo"); - for (var i = 0; i < retVal.Length; i++) { - retVal[i] = new XElement("Entry", - new XAttribute("category", categories[i]), - "##TECHNOLOGY_BRAND_NAME##" - ); - } - - return Environment.NewLine + string.Join(Environment.NewLine, retVal.Select(x => x.ToString())) + Environment.NewLine; - } - } -} diff --git a/VectoCore/VectoCore/Properties/AssemblyInfo.cs b/VectoCore/VectoCore/Properties/AssemblyInfo.cs index 5fd395da17b9de7d1f42e61dcd4c457ded7b7d38..430c7daf2c2cdec2c544004c49a1898149c18402 100644 --- a/VectoCore/VectoCore/Properties/AssemblyInfo.cs +++ b/VectoCore/VectoCore/Properties/AssemblyInfo.cs @@ -55,3 +55,5 @@ using System.Runtime.InteropServices; [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("VectoAuxiliariesTests")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("VECTO3")] [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("VECTOMultistage")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Vecto3GUI2020Test")] + diff --git a/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.2.6_Buses.xsd b/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.2.6_Buses.xsd index d326dd477692891a60ebeaa3bba600af1ab05c09..6bb0fa8e1e20a64fc317c3642108a725dfca7c93 100644 --- a/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.2.6_Buses.xsd +++ b/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.2.6_Buses.xsd @@ -640,4 +640,73 @@ <xs:enumeration value="CJ"/> </xs:restriction> </xs:simpleType> + <xs:complexType name="ExemptedPrimaryHeavyBusType"> + <xs:complexContent> + <xs:extension base="v2.0:AbstractVehicleDeclarationType"> + <xs:sequence> + <xs:element name="Manufacturer" type="v1.0:ManufacturerType"/> + <xs:element name="ManufacturerAddress" type="v1.0:ManufacturerAddressType"/> + <xs:element name="Model" type="v1.0:ModelType"> + <xs:annotation> + <xs:documentation>P236</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="VIN" type="v1.0:VINType"> + <xs:annotation> + <xs:documentation>P238</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Date" type="v1.0:DateTimeWithTimezone"> + <xs:annotation> + <xs:documentation>P239</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="LegislativeCategory" type="v2.6:LegislativeClassDeclarationType"> + <xs:annotation> + <xs:documentation>P251 - enum</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ChassisConfiguration" type="v2.6:ChassisConfigurationDeclarationType"> + <xs:annotation> + <xs:documentation>P036 - enum</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="AxleConfiguration" type="v2.6:VehicleAxleConfigurationDeclarationType"> + <xs:annotation> + <xs:documentation>P037 - enum</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Articulated" type="xs:boolean"/> + <xs:element name="TechnicalPermissibleMaximumLadenMass" type="v1.0:VehicleGrossVehicleMassType"> + <xs:annotation> + <xs:documentation>P041 - [kg]</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ZeroEmissionVehicle" type="xs:boolean"/> + <xs:element name="SumNetPower" type="xs:int"> + <xs:annotation> + <xs:documentation>P331 - [W]</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Technology"> + <xs:annotation> + <xs:documentation>P332 - enum</xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="HEV Article 9 exempted"/> + <xs:enumeration value="PEV Article 9 exempted"/> + <xs:enumeration value="HV Article 9 exempted"/> + <xs:enumeration value="Fuel cell vehicle"/> + <xs:enumeration value="H2 ICE"/> + <xs:enumeration value="Dual fuel vehicle Article 9 exempted"/> + <xs:enumeration value="In-motion charging Article 9 exempted"/> + <xs:enumeration value="Other technology Article 9 exempted"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> </xs:schema> diff --git a/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.2.8_Stage.xsd b/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.2.8_Stage.xsd index cfa6dd856c1bd6b443f310632f6f4318c8e08b48..3665c25e457be7231a3ecb0ce59c46d2f078d6ff 100644 --- a/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.2.8_Stage.xsd +++ b/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.2.8_Stage.xsd @@ -203,16 +203,26 @@ </xs:annotation> </xs:element> <xs:sequence minOccurs="0"> - <xs:element name="NumberPassengersLowerDeck" type="v2.8:NumberOfPassengersType"> + <xs:element name="NumberPassengerSeatsLowerDeck" type="v2.8:NumberOfPassengersType"> <xs:annotation> <xs:documentation>P283 - [-]</xs:documentation> </xs:annotation> </xs:element> - <xs:element name="NumberPassengersUpperDeck" type="v2.8:NumberOfPassengersType"> + <xs:element name="NumberPassengersStandingLowerDeck" type="v2.8:NumberOfPassengersType"> + <xs:annotation> + <xs:documentation>P354 - [-]</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="NumberPassengerSeatsUpperDeck" type="v2.8:NumberOfPassengersType"> <xs:annotation> <xs:documentation>P284 - [-]</xs:documentation> </xs:annotation> </xs:element> + <xs:element name="NumberPassengersStandingUpperDeck" type="v2.8:NumberOfPassengersType"> + <xs:annotation> + <xs:documentation>P355 - [-]</xs:documentation> + </xs:annotation> + </xs:element> </xs:sequence> <xs:element name="BodyworkCode" type="v2.6:VehicleCodeType" minOccurs="0"> <xs:annotation> diff --git a/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.xsd b/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.xsd index b6bb8bdea932e537c34583f7c489ae9da1ac79a6..96eb24c72b0db3f994d4dd7ec83e86f030635c3b 100644 --- a/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.xsd +++ b/VectoCore/VectoCore/Resources/XSD/VectoDeclarationDefinitions.xsd @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- edited with XMLSpy v2016 rel. 2 sp1 (x64) (http://www.altova.com) by Helmut Eichlseder (TU Graz/Inst. f. VKM und THD) --> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:vectoParam="urn:tugraz:ivt:VectoAPI:ParameterDocumentation" xmlns:vdj="urn:tugraz:ivt:VectoAPI:DeclarationJob" xmlns:vdi="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" xmlns:vdd="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" xmlns:v1.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:v2.2="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.2" xmlns:v2.3="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3" xmlns:ns1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" targetNamespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" elementFormDefault="qualified" attributeFormDefault="unqualified" version="2.0" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:ParameterDocumentation ParameterDocumentation.xsd"> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:vectoParam="urn:tugraz:ivt:VectoAPI:ParameterDocumentation" xmlns:vdj="urn:tugraz:ivt:VectoAPI:DeclarationJob" xmlns:vdi="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" xmlns:vdd="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" xmlns:v1.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:v2.2="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.2" xmlns:v2.3="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3" xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:v2.8="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" targetNamespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" elementFormDefault="qualified" attributeFormDefault="unqualified" version="2.0" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:ParameterDocumentation ParameterDocumentation.xsd"> <!-- This is a convienience file that imports all supported declaration definitions diff --git a/VectoCore/VectoCore/Resources/XSD/VectoOutputCustomer.0.8.xsd b/VectoCore/VectoCore/Resources/XSD/VectoOutputCustomer.0.8.xsd index 4948d5c58ece856340d1771937158c43ad996d79..9a6d3a03c90661ffa6ba274dc15a76de6cc9dbb2 100644 --- a/VectoCore/VectoCore/Resources/XSD/VectoOutputCustomer.0.8.xsd +++ b/VectoCore/VectoCore/Resources/XSD/VectoOutputCustomer.0.8.xsd @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- edited with XMLSpy v2016 rel. 2 sp1 (x64) (http://www.altova.com) by Helmut Eichlseder (TU Graz/Inst. f. VKM und THD) --> +<!-- edited with XMLSpy v2021 (x64) (http://www.altova.com) by Markus Quaritsch (Technische Universität Graz) --> <!--W3C XML Schema generated by XMLSpy vXMLSpy Professional Edition v2016 rel. 2 (x64) (http://www.altova.com)--> <xs:schema xmlns="urn:tugraz:ivt:VectoAPI:CustomerOutput:v0.8" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vdecdef="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" xmlns:out="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" targetNamespace="urn:tugraz:ivt:VectoAPI:CustomerOutput:v0.8" elementFormDefault="qualified" attributeFormDefault="unqualified" version="0.8"> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" schemaLocation="VectoOutputDefinitions.xsd"/> @@ -799,6 +799,149 @@ </xs:extension> </xs:complexContent> </xs:complexType> + <xs:complexType name="VehicleCompletedExemptedBusType"> + <xs:complexContent> + <xs:extension base="AbstractVehicleType"> + <xs:sequence> + <xs:element name="Model" type="vdecdef:ModelType"> + <xs:annotation> + <xs:documentation>P236 / II.1.1.7</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="PrimaryVehicle"> + <xs:complexType> + <xs:sequence> + <xs:element name="Manufacturer" type="vdecdef:ManufacturerType"> + <xs:annotation> + <xs:documentation>P235 / II.1.1.6</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ManufacturerAddress" type="vdecdef:ManufacturerAddressType"> + <xs:annotation> + <xs:documentation>P252 / II.1.1.6</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="InputDataSignature" type="vdecdef:SignatureType"/> + <xs:element name="ManufacturerRecordSignature" type="vdecdef:SignatureType"/> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="CompletedVehicle"> + <xs:complexType> + <xs:sequence> + <xs:element name="Manufacturer" type="vdecdef:ManufacturerType"> + <xs:annotation> + <xs:documentation>P235 / II.1.1.6</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ManufacturerAddress" type="vdecdef:ManufacturerAddressType"> + <xs:annotation> + <xs:documentation>P252 / II.1.1.6</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="VIN" type="vdecdef:VINType"> + <xs:annotation> + <xs:documentation>P238 / II.1.1.1</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="VehicleCategory"> + <xs:annotation> + <xs:documentation>P251 / II.1.1.2</xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="VehicleGroup" type="VehicleGroupType"> + <xs:annotation> + <xs:documentation>VECTO / II.1.1.5</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ClassBus"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="VehicleCode"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="TechnicalPermissibleMaximumLadenMass"> + <xs:annotation> + <xs:documentation>P041 / II.1.1.4</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="xs:double"> + <xs:attribute name="unit" type="MassUnitType" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="CurbMassChassis"> + <xs:annotation> + <xs:documentation>P038 / II.1.1.8</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="vdecdef:VehicleCurbMassChassisType"> + <xs:attribute name="unit" type="MassUnitType" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="ZeroEmissionVehicle" type="xs:boolean"> + <xs:annotation> + <xs:documentation>P269 / II.1.1.10</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="AxleConfiguration" type="xs:string"> + <xs:annotation> + <xs:documentation>P037 / II.1.1.3</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="RegisteredPassengers"> + <xs:simpleType> + <xs:restriction base="xs:int"> + <xs:minInclusive value="0"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="LowEntry" type="xs:boolean"/> + <xs:element name="HeightIntegratedBody"> + <xs:simpleType> + <xs:restriction base="vdecdef:Double3"> + <xs:minExclusive value="0.000"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="SumNetPower"> + <xs:annotation> + <xs:documentation>P250 / II.1.2.1</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="vdecdef:EngineRatedPower"> + <xs:attribute name="unit" type="PowerUnitType" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="InputDataSignature" type="vdecdef:SignatureType"/> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> <xs:simpleType name="AccelerationUnitType"> <xs:restriction base="xs:token"> <xs:enumeration value="m/s²"/> diff --git a/VectoCore/VectoCore/Resources/XSD/VectoOutputDefinitions.xsd b/VectoCore/VectoCore/Resources/XSD/VectoOutputDefinitions.xsd index c04dc2a75dbde19273614fbe58362afd065ba69f..43f695abf03d9dea35bb2ed2c9c895186263f487 100644 --- a/VectoCore/VectoCore/Resources/XSD/VectoOutputDefinitions.xsd +++ b/VectoCore/VectoCore/Resources/XSD/VectoOutputDefinitions.xsd @@ -1,8 +1,35 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- edited with XMLSpy v2016 rel. 2 sp1 (x64) (http://www.altova.com) by Helmut Eichlseder (TU Graz/Inst. f. VKM und THD) --> +<!-- edited with XMLSpy v2021 (x64) (http://www.altova.com) by Markus Quaritsch (Technische Universität Graz) --> <xs:schema xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vdecdef="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" xmlns:common="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" xmlns:mrf="urn:tugraz:ivt:VectoAPI:DeclarationOutput" xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:ns1="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" targetNamespace="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" elementFormDefault="qualified" attributeFormDefault="unqualified" version="0.8"> - <xs:complexType name="AbstractVTPReportDataType" abstract="true"/> <xs:complexType name="AbstractPrimaryVehicleDataPIFType" abstract="true"/> - <xs:complexType name="AbstractVectoOutputManufacturerDataType" abstract="true"/> <xs:complexType name="AbstractVectoOutputCustomerDataType" abstract="true"/> + <xs:complexType name="AbstractVectoOutputManufacturerDataType" abstract="true"/> + <xs:complexType name="AbstractVTPReportDataType" abstract="true"/> + <xs:simpleType name="DistanceUnitType"> + <xs:restriction base="xs:token"> + <xs:enumeration value="km"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="MassUnitType"> + <xs:restriction base="xs:token"> + <xs:enumeration value="kg"/> + <xs:enumeration value="t"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="PercentType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="%"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="PowerUnitType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="kW"/> + <xs:enumeration value="W"/> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="SpeedUnitType"> + <xs:restriction base="xs:token"> + <xs:enumeration value="km/h"/> + </xs:restriction> + </xs:simpleType> </xs:schema> diff --git a/VectoCore/VectoCore/Resources/XSD/VectoOutputManufacturer.0.8.xsd b/VectoCore/VectoCore/Resources/XSD/VectoOutputManufacturer.0.8.xsd index e1bfb206fc04705a054f38d017b2744360ed5a9c..f8ed77809325131eef95a31b782ff5d3f8862e93 100644 --- a/VectoCore/VectoCore/Resources/XSD/VectoOutputManufacturer.0.8.xsd +++ b/VectoCore/VectoCore/Resources/XSD/VectoOutputManufacturer.0.8.xsd @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- edited with XMLSpy v2016 rel. 2 sp1 (x64) (http://www.altova.com) by Helmut Eichlseder (TU Graz/Inst. f. VKM und THD) --> +<!-- edited with XMLSpy v2021 (x64) (http://www.altova.com) by Markus Quaritsch (Technische Universität Graz) --> <!--W3C XML Schema generated by XMLSpy vXMLSpy Professional Edition v2016 rel. 2 (x64) (http://www.altova.com)--> -<xs:schema xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.8" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vdecdef="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" xmlns:common="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" xmlns:mrf="urn:tugraz:ivt:VectoAPI:DeclarationOutput" xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:out="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" targetNamespace="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.8" elementFormDefault="qualified" attributeFormDefault="unqualified" version="0.8"> +<xs:schema xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.8" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vdecdef="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" xmlns:common="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" xmlns:mrf="urn:tugraz:ivt:VectoAPI:DeclarationOutput" xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:v2.8="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" xmlns:out="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" targetNamespace="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.8" elementFormDefault="qualified" attributeFormDefault="unqualified" version="0.8"> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" schemaLocation="VectoDeclarationDefinitions.1.0.xsd"/> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" schemaLocation="VectoDeclarationDefinitions.2.0.xsd"/> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" schemaLocation="VectoDeclarationDefinitions.2.1.xsd"/> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" schemaLocation="VectoDeclarationDefinitions.2.6_Buses.xsd"/> + <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" schemaLocation="VectoDeclarationDefinitions.2.8_Stage.xsd"/> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" schemaLocation="VectoDeclarationDefinitions.xsd"/> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" schemaLocation="VectoOutputDefinitions.xsd"/> <xs:complexType name="AbstractComponentsType" abstract="true"/> @@ -817,6 +818,171 @@ </xs:extension> </xs:complexContent> </xs:complexType> + <xs:complexType name="VehicleExemptedPrimaryBusType"> + <xs:complexContent> + <xs:extension base="AbstractVehicleType"> + <xs:sequence> + <xs:element name="Manufacturer" type="vdecdef:ManufacturerType"> + <xs:annotation> + <xs:documentation>P235 / I.1.1.1 / #14</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ManufacturerAddress" type="vdecdef:ManufacturerAddressType"> + <xs:annotation> + <xs:documentation>P252 / I.1.1.1 / #14</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Model" type="vdecdef:ModelType"> + <xs:annotation> + <xs:documentation>P236 / I.1.1.2</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="VIN" type="vdecdef:VINType"> + <xs:annotation> + <xs:documentation>P238 / I.1.1.3 / #1</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="LegislativeCategory"> + <xs:annotation> + <xs:documentation>P251 / I.1.1.4 / #10</xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="ChassisConfiguration" type="v2.6:ChassisConfigurationDeclarationType"> + <xs:annotation> + <xs:documentation>P036 - enum</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="AxleConfiguration" type="v2.6:VehicleAxleConfigurationDeclarationType"> + <xs:annotation> + <xs:documentation>P037 - enum</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Articulated" type="xs:boolean"/> + <xs:element name="TechnicalPermissibleMaximumLadenMass"> + <xs:annotation> + <xs:documentation>P041 / I.1.1.6 / #12</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="xs:double"> + <xs:attribute name="unit" type="out:MassUnitType" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="ZeroEmissionVehicle" type="xs:boolean"> + <xs:annotation> + <xs:documentation>P269 / I.1.1.10</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="SumNetPower"> + <xs:annotation> + <xs:documentation>P277</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="xs:double"> + <xs:attribute name="unit" type="out:PowerUnitType" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="Technology"> + <xs:annotation> + <xs:documentation>P332 - enum</xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="HEV Article 9 exempted"/> + <xs:enumeration value="PEV Article 9 exempted"/> + <xs:enumeration value="HV Article 9 exempted"/> + <xs:enumeration value="Fuel cell vehicle"/> + <xs:enumeration value="H2 ICE"/> + <xs:enumeration value="Dual fuel vehicle Article 9 exempted"/> + <xs:enumeration value="In-motion charging Article 9 exempted"/> + <xs:enumeration value="Other technology Article 9 exempted"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="InputDataSignature" type="vdecdef:SignatureType"> + <xs:annotation> + <xs:documentation>I.3.1.3</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="VehicleExemptedCompletedBusType"> + <xs:complexContent> + <xs:extension base="AbstractVehicleType"> + <xs:sequence> + <xs:element name="PrimaryVehicle" type="CompletedVehiclePrimaryVehicleInformationType"/> + <xs:element name="CompletedVehicle"> + <xs:complexType> + <xs:sequence> + <xs:element name="Model" type="vdecdef:ModelType"/> + <xs:element name="Manufacturer" type="vdecdef:ManufacturerType"/> + <xs:element name="ManufacturerAddress" type="vdecdef:ManufacturerAddressType"/> + <xs:element name="VIN" type="vdecdef:VINType"/> + <xs:element name="LegislativeCategory" type="xs:string"/> + <xs:element name="VehicleGroup" type="xs:string"/> + <xs:element name="ClassBus" type="xs:string"/> + <xs:element name="BodyworkCode" type="xs:string"/> + <xs:element name="CorrectedActualMass"> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="vdecdef:VehicleCurbMassChassisType"> + <xs:attribute name="unit" type="MassUnitType" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="TechnicalPermissibleMaximumLadenMass"> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="vdecdef:Double2"> + <xs:attribute name="unit" type="MassUnitType" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="NumberPassengersLowerDeck"> + <xs:simpleType> + <xs:restriction base="xs:int"> + <xs:minInclusive value="0"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="NumberPassengersUpperDeck"> + <xs:simpleType> + <xs:restriction base="xs:int"> + <xs:minInclusive value="0"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="ZeroEmissionVehicle" type="xs:boolean"/> + <xs:element name="LowEntry" type="xs:boolean"/> + <xs:element name="HeightIntegratedBody"> + <xs:simpleType> + <xs:restriction base="vdecdef:Double3"> + <xs:minExclusive value="0.000"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="InputDataSignature" type="vdecdef:SignatureType"/> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> <xs:complexType name="VehicleCompletedBusType"> <xs:complexContent> <xs:extension base="AbstractVehicleType"> @@ -1126,6 +1292,9 @@ </xs:sequence> </xs:complexType> <xs:complexType name="VehiclePrimaryBusType"> + <xs:annotation> + <xs:documentation>No longer neede?</xs:documentation> + </xs:annotation> <xs:complexContent> <xs:extension base="AbstractVehicleType"> <xs:sequence> diff --git a/VectoCore/VectoCore/Resources/XSD/VectoOutputManufacturer.xsd b/VectoCore/VectoCore/Resources/XSD/VectoOutputManufacturer.xsd index 1c14db9cfee97f8591d562778b16f074e6af2593..41d4cca59b7dcc43c1f500b7137abc5dd31fab7a 100644 --- a/VectoCore/VectoCore/Resources/XSD/VectoOutputManufacturer.xsd +++ b/VectoCore/VectoCore/Resources/XSD/VectoOutputManufacturer.xsd @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- edited with XMLSpy v2016 rel. 2 sp1 (x64) (http://www.altova.com) by Helmut Eichlseder (TU Graz/Inst. f. VKM und THD) --> -<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mrf="urn:tugraz:ivt:VectoAPI:DeclarationOutput" xmlns:mrf0.5="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.5" xmlns:mrf0.6="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.6" xmlns:mrf0.7="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.7" xmlns:mrf0.8="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.8" xmlns:out="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" xmlns:common="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" xmlns:v1.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" targetNamespace="urn:tugraz:ivt:VectoAPI:DeclarationOutput" elementFormDefault="qualified" attributeFormDefault="unqualified" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:ParameterDocumentation ParameterDocumentation.xsd"> +<!-- edited with XMLSpy v2021 (x64) (http://www.altova.com) by Markus Quaritsch (Technische Universität Graz) --> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mrf="urn:tugraz:ivt:VectoAPI:DeclarationOutput" xmlns:mrf0.5="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.5" xmlns:mrf0.6="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.6" xmlns:mrf0.7="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.7" xmlns:mrf0.8="urn:tugraz:ivt:VectoAPI:DeclarationOutput:v0.8" xmlns:out="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" xmlns:common="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" xmlns:v1.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" xmlns:ns1="urn:tugraz:ivt:VectoAPI:DeclarationOutput:DEV:v0.9.1" targetNamespace="urn:tugraz:ivt:VectoAPI:DeclarationOutput" elementFormDefault="qualified" attributeFormDefault="unqualified" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:ParameterDocumentation ParameterDocumentation.xsd"> <!-- This is a convienience file that imports the schema for all supported versions of manufacturer records file and all supported declaration definitions diff --git a/VectoCore/VectoCore/Resources/XSD/VectoOutputMultistage.0.1.xsd b/VectoCore/VectoCore/Resources/XSD/VectoOutputMultistage.0.1.xsd index a85e0519d4d3deebc3ca5035b4cddf972fb61ad2..9204b1753719dd846d8299d925ac3942d71aea0a 100644 --- a/VectoCore/VectoCore/Resources/XSD/VectoOutputMultistage.0.1.xsd +++ b/VectoCore/VectoCore/Resources/XSD/VectoOutputMultistage.0.1.xsd @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- edited with XMLSpy v2021 (x64) (http://www.altova.com) by Franz Josef Kober (Technische Universität Graz) --> +<!-- edited with XMLSpy v2021 (x64) (http://www.altova.com) by Markus Quaritsch (Technische Universität Graz) --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:vif="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1" xmlns:v1.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v1.0" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:v2.3="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3" xmlns:v2.4="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.4" xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:v2.8="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" xmlns:out="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" xmlns:common="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" targetNamespace="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1" elementFormDefault="qualified" attributeFormDefault="unqualified" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:ParameterDocumentation ParameterDocumentation.xsd"> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationOutputDefinitions" schemaLocation="VectoOutputDefinitions.xsd"/> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions" schemaLocation="VectoDeclarationDefinitions.xsd"/> @@ -9,47 +9,88 @@ <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3" schemaLocation="VectoDeclarationDefinitions.2.3_DEV.xsd"/> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" schemaLocation="VectoDeclarationDefinitions.2.6_Buses.xsd"/> <xs:import namespace="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" schemaLocation="VectoDeclarationDefinitions.2.8_Stage.xsd"/> - <xs:complexType name="AbstractAxleWheelsComponentPIFType" abstract="true"/> - <xs:complexType name="AbstractAxleWheelsDataPIFType" abstract="true"/> - <xs:complexType name="AxleWheelsComponentPIFType"> - <xs:complexContent> - <xs:extension base="vif:AbstractAxleWheelsComponentPIFType"> - <xs:sequence> - <xs:element name="Data" type="vif:AbstractAxleWheelsDataPIFType"/> - </xs:sequence> - </xs:extension> - </xs:complexContent> - </xs:complexType> - <xs:complexType name="AxleWheelsDataPIFType"> - <xs:annotation> - <xs:documentation>Axles & Wheels Component</xs:documentation> - </xs:annotation> - <xs:complexContent> - <xs:extension base="vif:AbstractAxleWheelsDataPIFType"> - <xs:sequence> - <xs:element name="Axles"> - <xs:complexType> - <xs:sequence> - <xs:element name="Axle" type="v2.0:AbstractAxleDataDeclarationType" minOccurs="2" maxOccurs="4"/> - </xs:sequence> - </xs:complexType> - </xs:element> - </xs:sequence> - </xs:extension> - </xs:complexContent> - </xs:complexType> <xs:element name="VectoOutputMultistage" type="vif:VectoOutputMultistageType"> <xs:annotation> <xs:documentation>Comment describing your root element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="AbstractAngledriveDataPIFType" abstract="true"/> + <xs:complexType name="AbstractAuxiliaryDataPIFType" abstract="true"/> <xs:complexType name="AbstractAxlegearDataPIFType" abstract="true"/> + <xs:complexType name="AbstractAxleWheelsComponentPIFType" abstract="true"/> + <xs:complexType name="AbstractAxleWheelsDataPIFType" abstract="true"/> <xs:complexType name="AbstractEngineDataPIFType" abstract="true"/> <xs:complexType name="AbstractManufacturingStageDataType" abstract="true"> <xs:attribute name="id" type="xs:NCName" use="required"/> </xs:complexType> - <xs:complexType name="AbstractAuxiliaryDataPIFType" abstract="true"/> + <xs:complexType name="AbstractPrimaryVehicleType" abstract="true"/> + <xs:complexType name="AbstractTorqueConverterDataPIFType" abstract="true"/> + <xs:complexType name="AbstractTransmissionDataPIFType" abstract="true"/> + <xs:complexType name="AbstractTransmissionGearsPIFType" abstract="true"/> + <xs:complexType name="AbstractVehicleComponentsPIFType" abstract="true"/> + <xs:complexType name="AngledriveDataPIFType"> + <xs:complexContent> + <xs:extension base="vif:AbstractAngledriveDataPIFType"> + <xs:sequence> + <xs:element name="Manufacturer" type="v1.0:ManufacturerType"> + <xs:annotation> + <xs:documentation>P220</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Model" type="v1.0:ModelType"> + <xs:annotation> + <xs:documentation>P221</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="CertificationMethod" type="v1.0:AngledriveCertificationOptionType"> + <xs:annotation> + <xs:documentation>P258 - [-]</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="CertificationNumber" type="v1.0:CertificationNumberType" minOccurs="0"> + <xs:annotation> + <xs:documentation>P265</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Date" type="v1.0:DateTimeWithTimezone"> + <xs:annotation> + <xs:documentation>P223</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="AppVersion" type="v1.0:AppVersionType"> + <xs:annotation> + <xs:documentation>P224</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Ratio"/> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="AngledrivePIFType"> + <xs:sequence> + <xs:element name="Data" type="vif:AbstractAngledriveDataPIFType"/> + </xs:sequence> + </xs:complexType> + <xs:complexType name="ApplicationInformationPrimaryVehicleType"> + <xs:sequence> + <xs:element name="SimulationToolVersion" type="xs:string"> + <xs:annotation> + <xs:documentation>II.2.5</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Date" type="v1.0:DateTimeWithTimezone"> + <xs:annotation> + <xs:documentation>II.2.5</xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + <xs:complexType name="AuxiliaryComponentPIFType"> + <xs:sequence> + <xs:element name="Data" type="vif:AbstractAuxiliaryDataPIFType"/> + </xs:sequence> + </xs:complexType> <xs:complexType name="AuxiliaryDataPIFType"> <xs:complexContent> <xs:extension base="vif:AbstractAuxiliaryDataPIFType"> @@ -254,72 +295,9 @@ </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType name="AbstractPrimaryVehicleType" abstract="true"/> - <xs:complexType name="AbstractTorqueConverterDataPIFType" abstract="true"/> - <xs:complexType name="AbstractTransmissionDataPIFType" abstract="true"/> - <xs:complexType name="AbstractTransmissionGearsPIFType" abstract="true"/> - <xs:complexType name="AbstractVehicleComponentsPIFType" abstract="true"/> - <xs:complexType name="AngledriveDataPIFType"> - <xs:complexContent> - <xs:extension base="vif:AbstractAngledriveDataPIFType"> - <xs:sequence> - <xs:element name="Manufacturer" type="v1.0:ManufacturerType"> - <xs:annotation> - <xs:documentation>P220</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="Model" type="v1.0:ModelType"> - <xs:annotation> - <xs:documentation>P221</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="CertificationMethod" type="v1.0:AngledriveCertificationOptionType"> - <xs:annotation> - <xs:documentation>P258 - [-]</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="CertificationNumber" type="v1.0:CertificationNumberType" minOccurs="0"> - <xs:annotation> - <xs:documentation>P265</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="Date" type="v1.0:DateTimeWithTimezone"> - <xs:annotation> - <xs:documentation>P223</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="AppVersion" type="v1.0:AppVersionType"> - <xs:annotation> - <xs:documentation>P224</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="Ratio"/> - </xs:sequence> - </xs:extension> - </xs:complexContent> - </xs:complexType> - <xs:complexType name="AngledrivePIFType"> - <xs:sequence> - <xs:element name="Data" type="vif:AbstractAngledriveDataPIFType"/> - </xs:sequence> - </xs:complexType> - <xs:complexType name="ApplicationInformationPrimaryVehicleType"> - <xs:sequence> - <xs:element name="SimulationToolVersion" type="xs:string"> - <xs:annotation> - <xs:documentation>II.2.5</xs:documentation> - </xs:annotation> - </xs:element> - <xs:element name="Date" type="v1.0:DateTimeWithTimezone"> - <xs:annotation> - <xs:documentation>II.2.5</xs:documentation> - </xs:annotation> - </xs:element> - </xs:sequence> - </xs:complexType> - <xs:complexType name="AuxiliaryComponentPIFType"> + <xs:complexType name="AxlegearComponentPIFType"> <xs:sequence> - <xs:element name="Data" type="vif:AbstractAuxiliaryDataPIFType"/> + <xs:element name="Data" type="vif:AbstractAxlegearDataPIFType"/> </xs:sequence> </xs:complexType> <xs:complexType name="AxlegearDataPIFType"> @@ -362,10 +340,32 @@ </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType name="AxlegearComponentPIFType"> - <xs:sequence> - <xs:element name="Data" type="vif:AbstractAxlegearDataPIFType"/> - </xs:sequence> + <xs:complexType name="AxleWheelsComponentPIFType"> + <xs:complexContent> + <xs:extension base="vif:AbstractAxleWheelsComponentPIFType"> + <xs:sequence> + <xs:element name="Data" type="vif:AbstractAxleWheelsDataPIFType"/> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:complexType name="AxleWheelsDataPIFType"> + <xs:annotation> + <xs:documentation>Axles & Wheels Component</xs:documentation> + </xs:annotation> + <xs:complexContent> + <xs:extension base="vif:AbstractAxleWheelsDataPIFType"> + <xs:sequence> + <xs:element name="Axles"> + <xs:complexType> + <xs:sequence> + <xs:element name="Axle" type="v2.0:AbstractAxleDataDeclarationType" minOccurs="2" maxOccurs="4"/> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:extension> + </xs:complexContent> </xs:complexType> <xs:complexType name="BusManufacturingStageDataType"> <xs:complexContent> @@ -551,7 +551,12 @@ <xs:complexType name="ResultsPrimaryVehicleType"> <xs:sequence> <xs:element name="Status"/> - <xs:element name="Result" type="vif:ResultPrimaryVehicleType" maxOccurs="unbounded"/> + <xs:choice> + <xs:element name="Result" type="vif:ResultPrimaryVehicleType" maxOccurs="unbounded"/> + <xs:element name="ExemptedVehicle"> + <xs:complexType/> + </xs:element> + </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="SimulationParametersType"> @@ -717,6 +722,12 @@ </xs:extension> </xs:complexContent> </xs:complexType> + <xs:complexType name="VectoOutputMultistageType"> + <xs:sequence> + <xs:element name="PrimaryVehicle" type="vif:PrimaryVehicleType"/> + <xs:element name="ManufacturingStage" type="vif:ManufacturingStageType" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> <xs:complexType name="VehicleComponentsPIFType"> <xs:complexContent> <xs:extension base="vif:AbstractVehicleComponentsPIFType"> @@ -732,6 +743,102 @@ </xs:extension> </xs:complexContent> </xs:complexType> + <xs:complexType name="VehicleExemptedPrimaryBusType"> + <xs:complexContent> + <xs:extension base="vif:AbstractPrimaryVehicleType"> + <xs:sequence> + <xs:element name="ManufacturerPrimaryVehicle" type="v1.0:ManufacturerType"> + <xs:annotation> + <xs:documentation>P235 / I.1.1.1 / #14</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="ManufacturerAddressPrimaryVehicle" type="v1.0:ManufacturerAddressType"> + <xs:annotation> + <xs:documentation>P252 / I.1.1.1 / #14</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Model" type="v1.0:ModelType"> + <xs:annotation> + <xs:documentation>P236 / I.1.1.2</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="VIN" type="v1.0:VINType"> + <xs:annotation> + <xs:documentation>P238 / I.1.1.3 / #1</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Date" type="v1.0:DateTimeWithTimezone"/> + <xs:element name="LegislativeCategory"> + <xs:annotation> + <xs:documentation>P251 / I.1.1.4 / #10</xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + <xs:element name="ChassisConfiguration" type="v2.6:ChassisConfigurationDeclarationType"> + <xs:annotation> + <xs:documentation>P036 - enum</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="AxleConfiguration" type="v2.6:VehicleAxleConfigurationDeclarationType"> + <xs:annotation> + <xs:documentation>P037 - enum</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="Articulated" type="xs:boolean"/> + <xs:element name="TechnicalPermissibleMaximumLadenMass"> + <xs:annotation> + <xs:documentation>P041 / I.1.1.6 / #12</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="xs:double"> + <xs:attribute name="unit" type="out:MassUnitType" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="ZeroEmissionVehicle" type="xs:boolean"> + <xs:annotation> + <xs:documentation>P269 / I.1.1.10</xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="SumNetPower"> + <xs:annotation> + <xs:documentation>P277</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:simpleContent> + <xs:extension base="xs:double"> + <xs:attribute name="unit" type="out:PowerUnitType" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + </xs:element> + <xs:element name="Technology"> + <xs:annotation> + <xs:documentation>P332 - enum</xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="HEV Article 9 exempted"/> + <xs:enumeration value="PEV Article 9 exempted"/> + <xs:enumeration value="HV Article 9 exempted"/> + <xs:enumeration value="Fuel cell vehicle"/> + <xs:enumeration value="H2 ICE"/> + <xs:enumeration value="Dual fuel vehicle Article 9 exempted"/> + <xs:enumeration value="In-motion charging Article 9 exempted"/> + <xs:enumeration value="Other technology Article 9 exempted"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> <xs:complexType name="VehiclePIFType"> <xs:complexContent> <xs:extension base="vif:AbstractPrimaryVehicleType"> @@ -805,10 +912,4 @@ <xs:enumeration value="Coach"/> </xs:restriction> </xs:simpleType> - <xs:complexType name="VectoOutputMultistageType"> - <xs:sequence> - <xs:element name="PrimaryVehicle" type="vif:PrimaryVehicleType"/> - <xs:element name="ManufacturingStage" type="vif:ManufacturingStageType" minOccurs="0" maxOccurs="unbounded"/> - </xs:sequence> - </xs:complexType> </xs:schema> diff --git a/VectoCore/VectoCore/Utils/XMLValidator.cs b/VectoCore/VectoCore/Utils/XMLValidator.cs index 171ed8772b3baeea63b863f310811f1637771336..302f6860d6df7bf4006af225c50608adc126c7e1 100644 --- a/VectoCore/VectoCore/Utils/XMLValidator.cs +++ b/VectoCore/VectoCore/Utils/XMLValidator.cs @@ -30,6 +30,7 @@ */ using System; +using System.Collections.Generic; using System.IO; using System.Xml; using System.Xml.Schema; @@ -44,6 +45,7 @@ namespace TUGraz.VectoCore.Utils private readonly Action<bool> _resultAction; private bool _valid; private XmlDocument _doc; + private List<string> _validationErrors = new List<string>(); private XMLValidator(Action<bool> resultaction, Action<XmlSeverityType, ValidationEvent> validationErrorAction) { @@ -70,6 +72,7 @@ namespace TUGraz.VectoCore.Utils public bool ValidateXML(XmlDocumentType docType) { _valid = true; + _validationErrors.Clear(); if (_doc.DocumentElement == null) { throw new Exception("empty XML document"); } @@ -91,11 +94,14 @@ namespace TUGraz.VectoCore.Utils { _resultAction(false); _valid = false; - ValidationError = args?.Message ?? "no schema found"; + _validationErrors.Add(args?.Message ?? "no schema found"); _validationErrorAction(args?.Severity ?? XmlSeverityType.Error, new ValidationEvent { ValidationEventArgs = args }); } - public string ValidationError { get; private set; } + public string ValidationError + { + get { return string.Join(Environment.NewLine, _validationErrors); } + } public static void CallBackExceptionOnError(XmlSeverityType severity, ValidationEvent evt) { diff --git a/VectoCore/VectoCore/VectoCore.csproj b/VectoCore/VectoCore/VectoCore.csproj index ec72baab2cb4291565438bdda9f654a01dfb5ed4..206f76063133f7b17977ca1e42694f8cc6ab3c5b 100644 --- a/VectoCore/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore/VectoCore.csproj @@ -446,8 +446,14 @@ <Compile Include="OutputData\FileIO\FileOutputVIFWriter.cs" /> <Compile Include="OutputData\FileIO\JSONFileWriter.cs" /> <Compile Include="OutputData\ModalDataPostprocessingCorrection.cs" /> - <Compile Include="OutputData\XML\AbstractXMLManufacturerReport.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\CustomerInformationFile\IXMLCustomerReport.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\CustomerInformationFile\XMLCustomerReportExemptedCompletedBus.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\ManufacturerReport\AbstractXMLManufacturerReport.cs" /> <Compile Include="OutputData\XML\DeclarationJobs\XMLCompletedBusWriter.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\ManufacturerReport\IXMLManufacturerReport.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\ManufacturerReport\XMLManufacturerReportExemptedCompletedBus.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\VehicleInformationFile\IXMLMultistageReport.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\VehicleInformationFile\IXMLPrimaryVehicleReport.cs" /> <Compile Include="OutputData\XML\Engineering\Factory\EngineeringWriterFactory.cs" /> <Compile Include="OutputData\XML\Engineering\Factory\IEngineeringWriterInjectFactory.cs" /> <Compile Include="OutputData\XML\Engineering\Interfaces\IXMLEngineeringComponentWriter.cs" /> @@ -482,15 +488,17 @@ <Compile Include="OutputData\XML\Engineering\XMLEngineeringWriter.cs" /> <Compile Include="OutputData\XML\Engineering\XMLEngineeringWriterInjectModule.cs" /> <Compile Include="OutputData\XML\Engineering\XMLWriterMapping.cs" /> - <Compile Include="OutputData\XML\XMLCustomerReportCompletedBus.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\CustomerInformationFile\XMLCustomerReportCompletedBus.cs" /> <Compile Include="OutputData\XML\XMLDeclarationReportCompletedVehicle.cs" /> <Compile Include="OutputData\XML\XMLDeclarationReportMultistageBusVehicle.cs" /> <Compile Include="OutputData\XML\XMLDeclarationReportPrimaryVehicle.cs" /> - <Compile Include="OutputData\XML\XMLManufacturerReportCompletedBus.cs" /> - <Compile Include="OutputData\XML\XMLManufacturerReportExemptedTruck.cs" /> - <Compile Include="OutputData\XML\XMLManufacturerReportPrimaryBus.cs" /> - <Compile Include="OutputData\XML\XMLMultistageBusReport.cs" /> - <Compile Include="OutputData\XML\XMLPrimaryVehicleReport.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\ManufacturerReport\XMLManufacturerReportCompletedBus.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\ManufacturerReport\XMLManufacturerReportExemptedTruck.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\ManufacturerReport\XMLManufacturerReportExeptedPrimaryBus.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\ManufacturerReport\XMLManufacturerReportPrimaryBus.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\VehicleInformationFile\XMLExemptedPrimaryBusVehicleReport.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\VehicleInformationFile\XMLMultistageBusReport.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\VehicleInformationFile\XMLPrimaryBusVehicleReport.cs" /> <Compile Include="Utils\Ninject\UseFirstArgumentAsInstanceProvider.cs" /> <Compile Include="InputData\FileIO\XML\Declaration\NinjectModules\XMLDeclarationReaderInjectModule.cs" /> <Compile Include="InputData\FileIO\XML\Declaration\DataProvider\XMLDeclarationVehicleDataProvider.cs" /> @@ -579,17 +587,16 @@ <Compile Include="Models\SimulationComponent\Impl\VTPCycle.cs" /> <Compile Include="Models\Simulation\Data\ShiftStrategyParameters.cs" /> <Compile Include="Models\Simulation\Impl\ExemptedRun.cs" /> - <Compile Include="OutputData\XML\XMLMonitoringReport.cs" /> - <Compile Include="OutputData\XML\XMLVTPReport.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\VTPReport\XMLVTPReport.cs" /> <Compile Include="OutputData\VTPReport.cs" /> <Compile Include="OutputData\ModFilter\ActualModalDataFilter.cs" /> <Compile Include="OutputData\ModFilter\ModalData1HzFilter.cs" /> <Compile Include="OutputData\XML\AbstractXMLWriter.cs" /> <Compile Include="OutputData\XML\AttributeMappings.cs" /> - <Compile Include="OutputData\XML\XMLCustomerReport.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\CustomerInformationFile\XMLCustomerReport.cs" /> <Compile Include="OutputData\XML\XMLDeclarationReport.cs" /> <Compile Include="OutputData\XML\XMLDeclarationWriter.cs" /> - <Compile Include="OutputData\XML\XMLManufacturerReport.cs" /> + <Compile Include="OutputData\XML\DeclarationReports\ManufacturerReport\XMLManufacturerReportTruck.cs" /> <Compile Include="Utils\Interpolate2D.cs" /> <Compile Include="Utils\DataIntegrityHelper.cs" /> <Compile Include="Utils\MeanShiftClustering.cs" /> diff --git a/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs b/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs index 48f05dd1521e1bb4a46fd43ab8ae54bb9e92a2dd..babc9da2252811cb0e3d524e8f0973afc84c50f7 100644 --- a/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs +++ b/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs @@ -22,6 +22,7 @@ using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Strategies; using TUGraz.VectoCore.OutputData; using TUGraz.VectoCore.OutputData.FileIO; +using TUGraz.VectoCore.Tests.Models.SimulationComponentData; using TUGraz.VectoCore.Tests.Utils; using TUGraz.VectoCore.Utils; using ElectricSystem = TUGraz.VectoCore.Models.SimulationComponent.ElectricSystem; @@ -42,6 +43,7 @@ namespace TUGraz.VectoCore.Tests.Integration.BatteryElectric protected const string BEV_E2_Job = @"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG.vecto"; + protected const string BEV_E2_Job_3Speed = @"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_3speed.vecto"; protected const string BEV_E2_Job_Cont30kW = @"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_Cont30kW.vecto"; public const string MotorFile = @"TestData\BatteryElectric\GenericVehicleB4\GenericEMotor_125kW_485Nm.vem"; @@ -565,6 +567,17 @@ namespace TUGraz.VectoCore.Tests.Integration.BatteryElectric TestCase(BEV_E2_Job, 8, TestName = "PEV E2 Job Urban"), TestCase(BEV_E2_Job, 9, TestName = "PEV E2 Job UrbanDelivery"), + TestCase(BEV_E2_Job_3Speed, 0, TestName = "PEV E2 3Speed Job LongHaul"), + TestCase(BEV_E2_Job_3Speed, 1, TestName = "PEV E2 3Speed Job Coach"), + TestCase(BEV_E2_Job_3Speed, 2, TestName = "PEV E2 3Speed Job Construction"), + TestCase(BEV_E2_Job_3Speed, 3, TestName = "PEV E2 3Speed Job HeavyUrban"), + TestCase(BEV_E2_Job_3Speed, 4, TestName = "PEV E2 3Speed Job Interurban"), + TestCase(BEV_E2_Job_3Speed, 5, TestName = "PEV E2 3Speed Job MunicipalUtility"), + TestCase(BEV_E2_Job_3Speed, 6, TestName = "PEV E2 3Speed Job RegionalDelivery"), + TestCase(BEV_E2_Job_3Speed, 7, TestName = "PEV E2 3Speed Job Suburban"), + TestCase(BEV_E2_Job_3Speed, 8, TestName = "PEV E2 3Speed Job Urban"), + TestCase(BEV_E2_Job_3Speed, 9, TestName = "PEV E2 3Speed Job UrbanDelivery"), + TestCase(BEV_E2_Job_Cont30kW, 0, TestName = "PEV E2 Cont. 30kW Job LongHaul"), TestCase(BEV_E2_Job_Cont30kW, 1, TestName = "PEV E2 Cont. 30kW Job Coach"), TestCase(BEV_E2_Job_Cont30kW, 2, TestName = "PEV E2 Cont. 30kW Job Construction"), @@ -788,7 +801,12 @@ namespace TUGraz.VectoCore.Tests.Integration.BatteryElectric Inertia = 0.SI<KilogramSquareMeter>(), TractionInterruption = 1.SI<Second>(), - + InputData = new DummyGearboxData() { + Gears = new List<ITransmissionInputData>() { + new TransmissionInputData(), + new TransmissionInputData(), + } + } }; } diff --git a/VectoCore/VectoCoreTest/Integration/CompletedBus/CompletedBusFactorMethodTest.cs b/VectoCore/VectoCoreTest/Integration/CompletedBus/CompletedBusFactorMethodTest.cs index 52884da0ee1b4a13163a621dff94d11a1cb5e533..26720ddfeabce3d3bbcd7e2568ba875459fbd0c3 100644 --- a/VectoCore/VectoCoreTest/Integration/CompletedBus/CompletedBusFactorMethodTest.cs +++ b/VectoCore/VectoCoreTest/Integration/CompletedBus/CompletedBusFactorMethodTest.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Reflection; using System.Runtime.InteropServices.WindowsRuntime; using System.Xml; +using System.Xml.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Ninject; @@ -1132,6 +1133,146 @@ namespace TUGraz.VectoCore.Tests.Integration.CompletedBus //Assert.IsTrue(jobContainer.Runs.All(r => r.Success), String.Concat<Exception>(jobContainer.Runs.Select(r => r.ExecException))); } + private const string JobGrp32b = @"TestData\Integration\Buses\FactorMethod\CompletedBus_41-32b_ES-AUX.vecto"; + + [ + TestCase(JobGrp32b, 2, 20, 5, 17, 9, 51, TestName = "CompleteBus PassengerCount IU specific RL"), + TestCase(JobGrp32b, 3, 20, 5, 17, 9, 49.572, TestName = "CompleteBus PassengerCount IU generic RL"), + TestCase(JobGrp32b, 6, 20, 5, 17, 9, 37, TestName = "CompleteBus PassengerCount CO specific RL"), + TestCase(JobGrp32b, 7, 20, 5, 17, 9, 38.556, TestName = "CompleteBus PassengerCount CO generic RL"), + ] + public void TestPassengerCountAllocationCompletedBus(string jobName, int runIdx, int pSeatsLower, int pStdLower, int pSeatsUpper, int pStdUpper, double expectedPassengers) + { + var inputData = CompletedVIF.CreateCompletedVifXML( + JSONInputDataFactory.ReadJsonJob(JobFile_Group41) as JSONInputDataCompletedBusFactorMethodV7, + xmlInputReader); + + var modified = GetModifiedXML(inputData, pSeatsLower, pStdLower, pSeatsUpper, pStdUpper); + var completedVif = xmlInputReader.CreateDeclaration(XmlReader.Create(new StringReader(modified))); + + var writer = new FileOutputWriter("SanityCheckTest"); + //var inputData = new MockCompletedBusInputData(XmlReader.Create(PifFile_33_34), modified); + //var inputData = new MockCompletedBusInputData(modified); + + var factory = new SimulatorFactory(ExecutionMode.Declaration, new XMLDeclarationVIFInputData(completedVif as IMultistageBusInputDataProvider, null), writer) { + WriteModalResults = true, + Validate = false + }; + + var runs = factory.DataReader.NextRun().ToList(); + var run = runs[runIdx]; + + Assert.NotNull(run.VehicleData.PassengerCount); + Assert.AreEqual(expectedPassengers, run.VehicleData.PassengerCount.Value, 1e-3); + + var ssmInputs = run.BusAuxiliaries.SSMInputs as ISSMDeclarationInputs; + Assert.NotNull(ssmInputs); + Assert.AreEqual(expectedPassengers + 1, ssmInputs.NumberOfPassengers, 1e-3); // adding driver for SSM + } + + private const string PrimaryGrp41 = @"TestData\Integration\Buses\FactorMethod\primary_heavyBus group41_nonSmart.xml"; + private const string CompletedGrp41_32b = @"TestData\Integration\Buses\FactorMethod\vecto_vehicle-completed_heavyBus_41.xml"; + + [ + TestCase(PrimaryGrp41, CompletedGrp41_32b, 1, 20, 5, 17, 9, 51, TestName = "SingleBus PassengerCount IU RL"), + TestCase(PrimaryGrp41, CompletedGrp41_32b, 3, 20, 5, 17, 9, 37, TestName = "SingleBus PassengerCount CO RL"), + ] + public void TestPassengerCountAllocationSingleBus(string primaryFile, string completedFile, int runIdx, int pSeatsLower, int pStdLower, int pSeatsUpper, int pStdUpper, double expectedPassengers) + { + var primary = xmlInputReader.CreateDeclaration(primaryFile); + + var completedXml = new XmlDocument(); + completedXml.Load(completedFile); + var modified = GetModifiedXML(completedXml.OuterXml, pSeatsLower, pStdLower, pSeatsUpper, pStdUpper, VehicleCode.CB); + var modifiedCompleted = xmlInputReader.CreateDeclaration(XmlReader.Create(new StringReader(modified))); + + var inputData = new MockSingleBusInputDataProvider(primary.JobInputData.Vehicle, modifiedCompleted.JobInputData.Vehicle); + var factory = new SimulatorFactory(ExecutionMode.Declaration, inputData, null) { + WriteModalResults = true, + //ActualModalData = true, + Validate = false + }; + var runs = factory.DataReader.NextRun().ToList(); + var run = runs[runIdx]; + + Assert.NotNull(run.VehicleData.PassengerCount); + Assert.AreEqual(expectedPassengers, run.VehicleData.PassengerCount.Value, 1e-3); + + var ssmInputs = run.BusAuxiliaries.SSMInputs as ISSMDeclarationInputs; + Assert.NotNull(ssmInputs); + Assert.AreEqual(expectedPassengers + 1, ssmInputs.NumberOfPassengers, 1e-3); // adding driver for SSM + } + + public class MockSingleBusInputDataProvider : ISingleBusInputDataProvider, IDeclarationJobInputData + { + public MockSingleBusInputDataProvider(IVehicleDeclarationInputData primary, IVehicleDeclarationInputData completed) + { + PrimaryVehicle = primary; + CompletedVehicle = completed; + } + + #region Implementation of IInputDataProvider + + public DataSource DataSource { get; } + + #endregion + + #region Implementation of IDeclarationInputDataProvider + + public IDeclarationJobInputData JobInputData => this; + public IPrimaryVehicleInformationInputDataProvider PrimaryVehicleData { get; } + public XElement XMLHash { get; } + + #endregion + + #region Implementation of ISingleBusInputDataProvider + + public IVehicleDeclarationInputData PrimaryVehicle { get; set; } + public IVehicleDeclarationInputData CompletedVehicle { get; set; } + + #endregion + + #region Implementation of IDeclarationJobInputData + + public bool SavedInDeclarationMode => true; + public IVehicleDeclarationInputData Vehicle => PrimaryVehicle; + public string JobName { get; } + public string ShiftStrategy => ""; + public VectoSimulationJobType JobType => VectoSimulationJobType.ConventionalVehicle; + + #endregion + } + + private string GetModifiedXML(string vifXML, int pSeatsLower, int pStdLower, int pSeatsUpper, int pStdUpper, + VehicleCode? vehicleCode = null) + { + var vif = new XmlDocument(); + vif.LoadXml(vifXML); + + var pSeatsLowerNode = vif.SelectSingleNode("//*[local-name()='NumberPassengerSeatsLowerDeck']"); + pSeatsLowerNode.InnerText = pSeatsLower.ToString(); + + var pStdLowerNode = vif.SelectSingleNode("//*[local-name()='NumberPassengersStandingLowerDeck']"); + pStdLowerNode.InnerText = pStdLower.ToString(); + + var pSeatsUpperNode = vif.SelectSingleNode("//*[local-name()='NumberPassengerSeatsUpperDeck']"); + pSeatsUpperNode.InnerText = pSeatsUpper.ToString(); + + var pStdUpperNode = vif.SelectSingleNode("//*[local-name()='NumberPassengersStandingUpperDeck']"); + pStdUpperNode.InnerText = pStdUpper.ToString(); + + if (vehicleCode != null) { + var bodyWorkNode = vif.SelectSingleNode("//*[local-name()='BodyworkCode']"); + bodyWorkNode.InnerText = vehicleCode.ToXMLFormat(); + + } + + return vif.OuterXml; + + + } + + //[TestCase(@"E:\QUAM\tmp\primary_heavyBus group 42_SmartPS_spec engine map.xml", 0),] public void TestRunPrimaryBusSimulationSngle(string jobName, int runIdx) { diff --git a/VectoCore/VectoCoreTest/Integration/Declaration/ExemptedVehicleTest.cs b/VectoCore/VectoCoreTest/Integration/Declaration/ExemptedVehicleTest.cs index f487abd323e5431443375014ac40dbf5f458387b..eb012863b0f5d54765940435471c0296c7b2eff2 100644 --- a/VectoCore/VectoCoreTest/Integration/Declaration/ExemptedVehicleTest.cs +++ b/VectoCore/VectoCoreTest/Integration/Declaration/ExemptedVehicleTest.cs @@ -58,6 +58,8 @@ namespace TUGraz.VectoCore.Tests.Integration { const string ExemptedVehicle = @"Testdata\Integration\DeclarationMode\ExemptedVehicle\vecto_vehicle-sample_exempted.xml"; + const string ExemptedPrimaryBus = @"TestData\XML\XMLReaderDeclaration\SchemaVersion2.6_Buses\exempted_primary_heavyBus.xml"; + protected IXMLInputDataReader xmlInputReader; private IKernel _kernel; @@ -287,5 +289,57 @@ namespace TUGraz.VectoCore.Tests.Integration manager); hybridNode.SetValue(hybrid.ToString().ToLowerInvariant()); } + + [TestCase(ExemptedPrimaryBus, 1)] + public void TestSimulationExemptedPrimaryBusVehicle(string filename, int numRuns) + { + var writer = new FileOutputWriter(filename); + + var primaryReportFile = writer.XMLPrimaryVehicleReportName; + var manufactuerFile = writer.XMLFullReportName; + var monitoringFile = writer.XMLMonitoringReportName; + if (File.Exists(primaryReportFile)) { + File.Delete(primaryReportFile); + } + if (File.Exists(manufactuerFile)) { + File.Delete(manufactuerFile); + } + if (File.Exists(monitoringFile)) { + File.Delete(monitoringFile); + } + + var inputData = xmlInputReader.CreateDeclaration(filename); + + var factory = new SimulatorFactory(ExecutionMode.Declaration, inputData, writer) { + WriteModalResults = true, + ActualModalData = true + }; + var jobContainer = new JobContainer(new MockSumWriter()); + + var runs = factory.SimulationRuns().ToList(); + Assert.AreEqual(numRuns, runs.Count); + foreach (var run in runs) { + jobContainer.AddRun(run); + } + //jobContainer.AddRuns(factory); + + jobContainer.Execute(); + jobContainer.WaitFinished(); + var progress = jobContainer.GetProgress(); + Assert.IsTrue(progress.All(r => r.Value.Success), string.Concat<Exception>(progress.Select(r => r.Value.Error))); + + Assert.IsTrue(File.Exists(manufactuerFile)); + Assert.IsTrue(File.Exists(primaryReportFile)); + + var validator = new XMLValidator(XmlReader.Create(manufactuerFile)); + Assert.IsTrue(validator.ValidateXML(XmlDocumentType.ManufacturerReport), validator.ValidationError); + + var val2 = new XMLValidator(XmlReader.Create(primaryReportFile)); + Assert.IsTrue(val2.ValidateXML(XmlDocumentType.MultistageOutputData), val2.ValidationError); + + //var val3 = new XMLValidator(XmlReader.Create(monitoringFile)); + //Assert.IsTrue(val3.ValidateXML(XmlDocumentType.MonitoringReport), val3.ValidationError); + + } } } diff --git a/VectoCore/VectoCoreTest/Integration/Multistage/MultistageVehicleTest.cs b/VectoCore/VectoCoreTest/Integration/Multistage/MultistageVehicleTest.cs index 30eff5400243d28de14e78fa728cacdc65041640..7197eca49cd5e17e161245f86f5f738f6ab89e0e 100644 --- a/VectoCore/VectoCoreTest/Integration/Multistage/MultistageVehicleTest.cs +++ b/VectoCore/VectoCoreTest/Integration/Multistage/MultistageVehicleTest.cs @@ -20,6 +20,7 @@ using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.OutputData; using TUGraz.VectoCore.OutputData.FileIO; using TUGraz.VectoCore.OutputData.XML; +using TUGraz.VectoCore.Tests.Integration.Declaration; using TUGraz.VectoCore.Tests.Models.Simulation; using TUGraz.VectoCore.Utils; @@ -42,6 +43,10 @@ namespace TUGraz.VectoCore.Tests.Integration.Multistage const string InputFilePathGroup41 = InputDirPath + "vecto_vehicle-stage_input_full-sample_group41.xml"; const string VIFInputFileGroup41 = VIFDirPath + "vecto_multistage_primary_vehicle_stage_2_3_group41.xml"; + const string VIFExemptedPrimaryBus = VIFDirPath + "exempted_primary_heavyBus.VIF.xml"; + private const string ExepmtedCompletedBusInput = InputDirPath + "vecto_vehicle-exempted_input_full-sample.xml"; + + const string vifResult = VIFDirPath + "vif_vehicle-sample.VIF_Report_3.xml"; @@ -235,7 +240,7 @@ namespace TUGraz.VectoCore.Tests.Integration.Multistage Assert.AreEqual("Some Manufacturer", data.Vehicle.Manufacturer); Assert.AreEqual("Some Manufacturer Address", data.Vehicle.ManufacturerAddress); Assert.AreEqual("VEH-1234567890", data.Vehicle.VIN); - Assert.AreEqual(DateTime.Parse("2020-01-09T11:00:00Z").ToUniversalTime(), data.Vehicle.Date); + Assert.AreEqual(DateTime.Parse("2021-06-30T22:00:00Z").ToUniversalTime(), data.Vehicle.Date); Assert.AreEqual("Sample Bus Model", data.Vehicle.Model); Assert.AreEqual(LegislativeClass.M3, data.Vehicle.LegislativeClass); Assert.AreEqual(500, data.Vehicle.CurbMassChassis.Value()); @@ -327,7 +332,7 @@ namespace TUGraz.VectoCore.Tests.Integration.Multistage var vifDataProvider = xmlInputReader.Create(vifReader) as IMultistageBusInputDataProvider; var inputData = new XMLDeclarationVIFInputData(vifDataProvider, null); - var writer = new FileOutputWriter("vif_vehicle-sample_test.xml"); + var writer = new MockDeclarationWriter("vif_vehicle-sample_test.xml"); var factory = new SimulatorFactory(ExecutionMode.Declaration, inputData, writer) @@ -347,6 +352,35 @@ namespace TUGraz.VectoCore.Tests.Integration.Multistage Assert.IsTrue(jobContainer.Runs.All(r => r.Success), string.Concat(jobContainer.Runs.Select(r => r.ExecException))); } + [TestCase()] + public void TestMultistageExemptedSimulationRun() + { + TestSimulationMultistageVehicle(VIFExemptedPrimaryBus, ExepmtedCompletedBusInput, 1); + + var vifReader = XmlReader.Create(_generatedVIFFilepath); + var vifDataProvider = xmlInputReader.Create(vifReader) as IMultistageBusInputDataProvider; + + var inputData = new XMLDeclarationVIFInputData(vifDataProvider, null); + var writer = new FileOutputWriter("vif_vehicle-sample_test.xml"); + + + var factory = new SimulatorFactory(ExecutionMode.Declaration, inputData, writer) { + WriteModalResults = true, + //ActualModalData = true, + Validate = false + }; + + var jobContainer = new JobContainer(new SummaryDataContainer(writer)); + jobContainer.AddRuns(factory); + + jobContainer.Execute(); + jobContainer.WaitFinished(); + var progress = jobContainer.GetProgress(); + Assert.IsTrue(progress.All(r => r.Value.Success), string.Concat<Exception>(progress.Select(r => r.Value.Error))); + Assert.IsTrue(jobContainer.Runs.All(r => r.Success), string.Concat<Exception>(jobContainer.Runs.Select(r => r.ExecException))); + } + + [NonParallelizable] [TestCase(PrimaryBus, TestName = "Multistage Write VIF Primary"), TestCase(PrimaryBus_SmartES, TestName = "Multistage Write VIF Primary SmartES")] @@ -354,7 +388,7 @@ namespace TUGraz.VectoCore.Tests.Integration.Multistage { var inputData = xmlInputReader.Create(primaryFile); - var writer = new FileOutputWriter("vif_writing_test.xml"); + var writer = new MockDeclarationWriter("vif_writing_test.xml"); //var xmlreport = new XMLDeclarationReportMultistageBusVehicle(writer); var xmlreport = new XMLDeclarationReportPrimaryVehicle(writer); @@ -377,7 +411,7 @@ namespace TUGraz.VectoCore.Tests.Integration.Multistage { var inputData = xmlInputReader.Create(primaryFile); - var writer = new FileOutputWriter(outputFile); + var writer = new MockDeclarationWriter(outputFile); var factory = new SimulatorFactory(ExecutionMode.Declaration, inputData, writer) { WriteModalResults = true, @@ -451,7 +485,7 @@ namespace TUGraz.VectoCore.Tests.Integration.Multistage Assert.AreEqual("Generic Model", vehicleData.Model); Assert.AreEqual("VEH-1234567890", vehicleData.VIN); Assert.AreEqual(DateTime.Parse("2017-02-15T11:00:00Z").ToUniversalTime(), vehicleData.Date); - Assert.AreEqual("M3", vehicleData.LegislativeCategory); + Assert.AreEqual(LegislativeClass.M3, vehicleData.LegislativeClass); Assert.AreEqual("Bus", vehicleData.VehicleCategory.ToXMLFormat()); Assert.AreEqual(AxleConfiguration.AxleConfig_4x2, vehicleData.AxleConfiguration); Assert.AreEqual(false, vehicleData.Articulated); diff --git a/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs b/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs index 45bad7552f1271ba7fbf06ad9db49781b3b0e331..fe3bcbe00805121cd35d78216d00292e61065b0a 100644 --- a/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs +++ b/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs @@ -43,9 +43,13 @@ using TUGraz.VectoCore.InputData.FileIO.XML; using TUGraz.VectoCore.InputData.Reader.ComponentData; using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter; using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor; using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Tests.Utils; using TUGraz.VectoCore.Utils; using Point = TUGraz.VectoCommon.Utils.Point; @@ -864,9 +868,10 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration } - [TestCase(@"E:\QUAM\Workspace\VECTO-Bugreports\BugReportTests\Bugreport Jobs\20190307_VECTO-904_Extrapolation\OM-18173493.xml")] + [TestCase(@"E:\QUAM\Workspace\VECTO-Bugreports\BugReportTests\Bugreport Jobs\20190307_VECTO-904_Extrapolation\OM-18173493.xml")] + //[TestCase(@"E:\QUAM\Workspace\VECTO_DEV_Hybrid\Generic Vehicles\Declaration Mode\Group5_Tractor_4x2\Class5_Tractor_DECL.xml")] [Ignore("Confidential data")] - public void ComputeShiftPolygonXML(string xmlJob) + public void ComputeShiftPolygonXML(string xmlJob) { var inputData = xmlInputReader.CreateDeclaration(xmlJob); var dao = new DeclarationDataAdapterHeavyLorry(); @@ -920,5 +925,104 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration g++; } } + + [TestCase(@"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG.vecto"), + TestCase(@"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_cont30kW.vecto")] + public void ComputePEVShiftLines(string pevE2Job) + { + var inputData = JSONInputDataFactory.ReadJsonJob(pevE2Job) as IEngineeringInputDataProvider; + var gearboxData = inputData.JobInputData.Vehicle.Components.GearboxInputData; + var dao = new EngineeringDataAdapter(); + var emData = dao.CreateElectricMachines(inputData.JobInputData.Vehicle.Components.ElectricMachines, + null).FirstOrDefault()?.Item2; + var axlegearRatio = inputData.JobInputData.Vehicle.Components.AxleGearInputData.Ratio; + var vehicleData = dao.CreateVehicleData(inputData.JobInputData.Vehicle); + var r_dyn = vehicleData.DynamicTyreRadius; + + var fullLoadCurve = emData.EfficiencyData.VoltageLevels.First().FullLoadCurve.FullLoadEntries.Select(x => + new EngineFullLoadCurve.FullLoadCurveEntry() { + EngineSpeed = x.MotorSpeed, + TorqueFullLoad = -x.FullDriveTorque, + TorqueDrag = -x.FullGenerationTorque + }).ToList(); + var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(); + var engineData = new CombustionEngineData() { + IdleSpeed = 600.RPMtoRad() + }; + fullLoadCurves[(uint)(0)] = new EngineFullLoadCurve(fullLoadCurve, null) { EngineData = engineData}; + var shiftPolygons = new List<ShiftPolygon>(); + for (var i = 0; i < gearboxData.Gears.Count; i++) { + shiftPolygons.Add(DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, emData.EfficiencyData.VoltageLevels.First().FullLoadCurve, 1.0, gearboxData.Gears, + axlegearRatio, r_dyn)); + fullLoadCurves[(uint)(i + 1)] = new EngineFullLoadCurve(fullLoadCurve, null) { EngineData = engineData}; + } + var imageFile = Path.Combine(Path.GetDirectoryName(pevE2Job), Path.GetFileNameWithoutExtension(pevE2Job) + "_shiftlines.png"); + + ShiftPolygonDrawer.DrawShiftPolygons(Path.GetDirectoryName(pevE2Job), fullLoadCurves, shiftPolygons, + imageFile, + DeclarationData.Gearbox.TruckMaxAllowedSpeed / r_dyn * axlegearRatio * gearboxData.Gears.Last().Ratio); + } + + [TestCase()] + public void ComputePEVShiftLinesDeRated() + { + var pevE2Job = @"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_cont30kW.vecto"; + + var inputData = JSONInputDataFactory.ReadJsonJob(pevE2Job) as IEngineeringInputDataProvider; + var gearboxData = inputData.JobInputData.Vehicle.Components.GearboxInputData; + var dao = new EngineeringDataAdapter(); + var emData = dao.CreateElectricMachines(inputData.JobInputData.Vehicle.Components.ElectricMachines, + null).FirstOrDefault()?.Item2; + + var axlegearRatio = inputData.JobInputData.Vehicle.Components.AxleGearInputData.Ratio; + var vehicleData = dao.CreateVehicleData(inputData.JobInputData.Vehicle); + var r_dyn = vehicleData.DynamicTyreRadius; + + //emData.ContinuousTorque = 500.SI<NewtonMeter>(); + var contTqFld = new ElectricMotorFullLoadCurve(new List<ElectricMotorFullLoadCurve.FullLoadEntry>() { + new ElectricMotorFullLoadCurve.FullLoadEntry() { + MotorSpeed = 0.RPMtoRad(), + FullDriveTorque = -emData.ContinuousTorque, + FullGenerationTorque = emData.ContinuousTorque + }, + new ElectricMotorFullLoadCurve.FullLoadEntry() { + MotorSpeed = 1.1 * emData.EfficiencyData.VoltageLevels.First().FullLoadCurve.MaxSpeed, + FullDriveTorque = -emData.ContinuousTorque, + FullGenerationTorque = emData.ContinuousTorque + } + }); + var limitedFld = AbstractSimulationDataAdapter.IntersectEMFullLoadCurves(emData.EfficiencyData.VoltageLevels.First().FullLoadCurve, contTqFld); + + var fullLoadCurve = limitedFld.FullLoadEntries.Select(x => + new EngineFullLoadCurve.FullLoadCurveEntry() { + EngineSpeed = x.MotorSpeed, + TorqueFullLoad = -x.FullDriveTorque, + TorqueDrag = -x.FullGenerationTorque + }).ToList(); + var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(); + var engineData = new CombustionEngineData() { + IdleSpeed = 600.RPMtoRad() + }; + fullLoadCurves[(uint)(0)] = new EngineFullLoadCurve(fullLoadCurve, null) { EngineData = engineData }; + + + var shiftPolygons = new List<ShiftPolygon>(); + + var shiftStrategy = new PEVAMTShiftStrategy(new VehicleContainer(ExecutionMode.Engineering) { RunData = new VectoRunData() { GearshiftParameters = new ShiftStrategyParameters()}}); + var deRatedShiftLines = shiftStrategy.CalculateDeratedShiftLines(emData, gearboxData.Gears, + r_dyn, axlegearRatio, gearboxData.Type); + for (var i = 0; i < gearboxData.Gears.Count; i++) { + + shiftPolygons.Add(deRatedShiftLines[(uint)(i + 1)]); + + + fullLoadCurves[(uint)(i + 1)] = new EngineFullLoadCurve(fullLoadCurve, null) { EngineData = engineData }; + } + var imageFile = Path.Combine(Path.GetDirectoryName(pevE2Job), Path.GetFileNameWithoutExtension(pevE2Job) + "_shiftlines_DeRated.png"); + + ShiftPolygonDrawer.DrawShiftPolygons(Path.GetDirectoryName(pevE2Job), fullLoadCurves, shiftPolygons, + imageFile, + DeclarationData.Gearbox.TruckMaxAllowedSpeed / r_dyn * axlegearRatio * gearboxData.Gears.Last().Ratio); + } } } \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/Reports/ModDataPostprocessingTest.cs b/VectoCore/VectoCoreTest/Reports/ModDataPostprocessingTest.cs new file mode 100644 index 0000000000000000000000000000000000000000..ecf3fab04ffc80426fd8861429bc9c5855cbc359 --- /dev/null +++ b/VectoCore/VectoCoreTest/Reports/ModDataPostprocessingTest.cs @@ -0,0 +1,2706 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.IO; +using System.Linq; +using NUnit.Framework; +using TUGraz.VectoCommon.BusAuxiliaries; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Configuration; +using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.Models.BusAuxiliaries; +using TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.Electrics; +using TUGraz.VectoCore.Models.BusAuxiliaries.DownstreamModules.Impl.Pneumatics; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Battery; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; +using TUGraz.VectoCore.OutputData; +using TUGraz.VectoCore.OutputData.FileIO; +using TUGraz.VectoCore.Tests.Utils; + +namespace TUGraz.VectoCore.Tests.Reports +{ + [TestFixture] + //[Parallelizable] + public class ModDataPostprocessingTest + { + private double busAuxAlternatorEff = 0.753; + private AmpereSecond BatCapacity = 10000.SI<AmpereSecond>(); + const double dcdc_efficiency = 0.926; + const double UF_ESS_Driving = 0.821; + const double UF_ESS_Standstill = 0.753; + const double emEff = 0.95; + const double batEff = 0.982; + + private const PowertrainPosition emPos = PowertrainPosition.HybridP2; + + [OneTimeSetUp] + public void RunBeforeAnyTests() + { + Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); + } + + + [TestCase()] + public void TestAuxESSStandstill_ModDataCorrection() + { + var runData = GetRunData(); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 51.171787824561704 ["s"] + var T3 = 0.SI<Second>(); // 50.195047986970792 ["s"] + + var P_off = 300.SI<Watt>(); + var P_on = 900.SI<Watt>(); + + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // standstill + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 0.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = false; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = P_off; + modData[ModalResultField.P_aux_ESS_mech_ice_on] = P_on; + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T3 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var fcIdle = + fuel.ConsumptionMap.GetFuelConsumption(0.SI<NewtonMeter>(), runData.EngineData.IdleSpeed).Value + .Value() * fuel.FuelConsumptionCorrectionFactor; // 0.0002929177777777778 + + var k_engline = 2.6254521511724e-8; + var E_auxICEOnStandstill = (P_on * T2).Value(); // 46054.609042105534 + var E_auxICEOffStandstill = (P_off * T2).Value(); // 15351.536347368512 + + var fcEssStandStillOff = E_auxICEOffStandstill * k_engline * UF_ESS_Standstill; // 0.0003034945726763096 + var fcEssStandStillOn = + (E_auxICEOnStandstill * k_engline + (fcIdle * T2).Value()) * (1 - UF_ESS_Standstill); // 0.00400097222027925 + + var fcModSum = 0.195725; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(E_auxICEOnStandstill, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(E_auxICEOffStandstill, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(fcEssStandStillOff, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(fcEssStandStillOn, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcEssStandStillOff + fcEssStandStillOn , f.FcEssCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcEssStandStillOff + fcEssStandStillOn, f.FcFinal.Value(), 1e-6); + } + + + + [TestCase()] + public void TestAuxESSDriving_ModDataCorrection() + { + var runData = GetRunData(); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 51.171787824561704 ["s"] + var T3 = 0.SI<Second>(); // 50.195047986970792 ["s"] + + var P_off = 300.SI<Watt>(); + var P_on = 900.SI<Watt>(); + + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // driving ICE Off + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = false; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = P_off; + modData[ModalResultField.P_aux_ESS_mech_ice_on] = P_on; + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T3 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + var E_auxICEOnDriving = (P_on * T2).Value(); // 46054.609042105534; + var E_auxICEOffDriving = (P_off * T2).Value(); // 15351.536347368512 + + var fcIdle = + fuel.ConsumptionMap.GetFuelConsumption(0.SI<NewtonMeter>(), runData.EngineData.IdleSpeed).Value + .Value() * fuel.FuelConsumptionCorrectionFactor; // 0.0002929177777777778 + + var fcEssDrivingOff = E_auxICEOffDriving * k_engline * UF_ESS_Driving; // 0.00033090178508266954; + var fcEssDrivingOn = (E_auxICEOnDriving * k_engline + (fcIdle * T2).Value()) * (1 - UF_ESS_Driving); // 0.002899489989595085; + + var fcModSum = 0.195725; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(E_auxICEOnDriving, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(E_auxICEOffDriving, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(fcEssDrivingOff, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(fcEssDrivingOn, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcEssDrivingOff + fcEssDrivingOn, f.FcEssCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcEssDrivingOff + fcEssDrivingOn, f.FcFinal.Value(), 1e-6); + } + + [TestCase()] + public void TestAuxESSEngineStart_ModDataCorrection() + { + var runData = GetRunData(); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + Second dt; + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 51.171787824561704 ["s"] + var T3 = 0.SI<Second>(); // 50.195047986970792 ["s"] + Second tStart = null; + + var P_off = 300.SI<Watt>(); + var P_on = 900.SI<Watt>(); + var P_ICEStart = 20000.SI<Watt>(); + + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // standstill + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 0.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = false; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = P_off; + modData[ModalResultField.P_aux_ESS_mech_ice_on] = P_on; + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = P_ICEStart; + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T3 += dt; + if (tStart == null) tStart = dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var fcIdle = + fuel.ConsumptionMap.GetFuelConsumption(0.SI<NewtonMeter>(), runData.EngineData.IdleSpeed).Value + .Value() * fuel.FuelConsumptionCorrectionFactor; // 0.0002929177777777778 + + var k_engline = 2.6254521511724e-8; + var E_auxICEOnStandstill = (P_on * T2).Value(); // 46054.609042105534 + var E_auxICEOffStandstill = (P_off * T2).Value(); // 15351.536347368512 + var E_ICEStart = (P_ICEStart * tStart).Value(); // 11525.53891554733 + + + var fcEssStandStillOff = E_auxICEOffStandstill * k_engline * UF_ESS_Standstill; // 0.0003034945726763096 + var fcEssStandStillOn = + (E_auxICEOnStandstill * k_engline + (fcIdle * T2).Value()) * (1 - UF_ESS_Standstill); // 0.00400097222027925 + var fcEngineStart = E_ICEStart * k_engline; // 0.00030259750939244944 + + var fcModSum = 0.195725; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(E_auxICEOnStandstill, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(E_auxICEOffStandstill, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + Assert.AreEqual(E_ICEStart, modData.WorkEngineStart().Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(fcEssStandStillOff, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(fcEssStandStillOn, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(fcEngineStart, f.FcESS_EngineStart.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcEssStandStillOff + fcEssStandStillOn + fcEngineStart, f.FcEssCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcEssStandStillOff + fcEssStandStillOn + fcEngineStart, f.FcFinal.Value(), 1e-6); + } + + [TestCase()] + public void TestBusAuxPsESSStandstill_ModDataCorrection() + { + var runData = GetRunData(true); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice1 = 800.RPMtoRad(); + var n_ice2 = 1200.RPMtoRad(); + var n_ice = n_ice1; + var t_ice = 400.SI<NewtonMeter>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 51.171787824561704 ["s"] + var T3 = 0.SI<Second>(); // 50.195047986970792 ["s"] + + var Nl_consumed = 0.7.SI<NormLiterPerSecond>(); + var Nl_generated = Nl_consumed; + + var compressorMap = runData.BusAuxiliaries.PneumaticUserInputsConfig.CompressorMap; + + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + + modData[ModalResultField.Nl_busAux_PS_generated] = Nl_generated * dt; + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + var comp = compressorMap.Interpolate(n_ice); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // standstill + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 0.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = false; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + var comp = compressorMap.Interpolate(runData.EngineData.IdleSpeed); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = n_ice2; + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T3 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + + modData[ModalResultField.Nl_busAux_PS_generated] = Nl_generated * dt; + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + var comp = compressorMap.Interpolate(n_ice); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var fcIdle = + fuel.ConsumptionMap.GetFuelConsumption(0.SI<NewtonMeter>(), runData.EngineData.IdleSpeed).Value + .Value() * fuel.FuelConsumptionCorrectionFactor; // 0.0002929177777777778 + + var k_engline = 2.6254521511724e-8; + + var airDemand = (Nl_generated * (T1 + T2 + T3)).Value(); // 106.05137005359465 + var deltaAir = (Nl_generated * T2).Value(); // 35.820251477193189 + + var comp1 = compressorMap.Interpolate(n_ice1); // rad/s: 83.775804095727821 | rpm: 800 4.1756093266666667 ["Nl/s"] 3139.5 ["W"] 340.79499999999996 ["W"] (exceeded: false) + var comp2 = compressorMap.Interpolate(runData.EngineData.IdleSpeed); // rad/s: 83.775804095727821 | rpm: 800 4.1756093266666667 ["Nl/s"] 3139.5 ["W"] 340.79499999999996 ["W"] (exceeded: true) + var comp3 = compressorMap.Interpolate(n_ice2); // rad/s: 125.66370614359173 | rpm: 1200 6.23922331 ["Nl/s"] 4609.5 ["W"] 667.68000000000006 ["W"] (exceeded: false) + + var workCompOff = comp1.PowerOff * T1 + comp3.PowerOff * T3; // 50600.028340142 ["Ws"] + var workCompOn = comp1.PowerOn * T1 + comp3.PowerOn * T3; // 388773.28735600761 ["Ws"] + var airOn = comp1.FlowRate * T1 + comp3.FlowRate * T3; // 522.52279399122142 ["Nl"] + + var kAir = ((workCompOn - workCompOff) / airOn).Value(); // 647193.31463566166 + var E_busAuxPS = kAir * deltaAir / 1e3; // 23182.627284607614 convert Nl to m^3 + + var fcPSAir = k_engline * E_busAuxPS; // 0.00060864878674201034 + var fcPSICEOffStop = (comp2.PowerOff * k_engline * (1-UF_ESS_Standstill) * T2).Value(); // 0.00011309017231128844 + + var fcESS = fcIdle * T2.Value() * (1 - UF_ESS_Standstill); // 0.0037023142144981809 + + var fcModSum = 0.195725; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(deltaAir, (modData.AirConsumed() - modData.AirGenerated()).Value(), 1e-6); + Assert.AreEqual(airDemand, corr.CorrectedAirDemand.Value(), 1e-6); + Assert.AreEqual(deltaAir, corr.DeltaAir.Value(), 1e-6); + + Assert.AreEqual(kAir, corr.kAir.Value(), 1e-3); + Assert.AreEqual(E_busAuxPS, corr.WorkBusAuxPSCorr.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(fcESS, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + + Assert.AreEqual(fcPSAir, f.FcBusAuxPSAirDemand.Value(), 1e-12); + Assert.AreEqual(fcPSICEOffStop, f.FcBusAuxPSDragICEOffStandstill.Value(), 1e-12); + Assert.AreEqual(0, f.FcBusAuxPSDragICEOffDriving.Value(), 1e-12); + Assert.AreEqual(fcPSAir + fcPSICEOffStop, f.FcBusAuxPs.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcESS, f.FcEssCorr.Value(), 1e-6); + Assert.AreEqual(fcModSum + fcPSAir + fcPSICEOffStop + fcESS, f.FcBusAuxPsCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcPSAir + fcPSICEOffStop + fcESS, f.FcFinal.Value(), 1e-6); + + } + + [TestCase()] + public void TestBusAuxPsESSDriving_ModDataCorrection() + { + var runData = GetRunData(true); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice1 = 800.RPMtoRad(); + var n_ice2 = 1200.RPMtoRad(); + var n_ice = n_ice1; + var t_ice = 400.SI<NewtonMeter>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 51.171787824561704 ["s"] + var T3 = 0.SI<Second>(); // 50.195047986970792 ["s"] + + var Nl_consumed = 0.7.SI<NormLiterPerSecond>(); + var Nl_generated = Nl_consumed; + + var compressorMap = runData.BusAuxiliaries.PneumaticUserInputsConfig.CompressorMap; + + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + + modData[ModalResultField.Nl_busAux_PS_generated] = Nl_generated * dt; + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + var comp = compressorMap.Interpolate(n_ice); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // driving, ice off + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = false; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + var comp = compressorMap.Interpolate(runData.EngineData.IdleSpeed); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = n_ice2; + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T3 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + + modData[ModalResultField.Nl_busAux_PS_generated] = Nl_generated * dt; + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + var comp = compressorMap.Interpolate(n_ice); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var fcIdle = + fuel.ConsumptionMap.GetFuelConsumption(0.SI<NewtonMeter>(), runData.EngineData.IdleSpeed).Value + .Value() * fuel.FuelConsumptionCorrectionFactor; + + var dts = modData.GetValues(x => x.Field<Second>(ModalResultField.simulationInterval.GetName())).ToArray(); + + var time = modData.GetValues<Second>(ModalResultField.time).ToArray(); + + var k_engline = 2.6254521511724e-8; + + var airDemand = (Nl_generated * (T1 + T2 + T3)).Value(); // 106.05137005359465 + var deltaAir = (Nl_generated * T2).Value(); // 35.820251477193189 + + var comp1 = compressorMap.Interpolate(n_ice1); // rpm: 800 4.1756093266666667 ["Nl/s"] 3139.5 ["W"] 340.79499999999996 ["W"] (exceeded: false) + var comp2 = compressorMap.Interpolate(runData.EngineData.IdleSpeed); // rpm: 800 4.1756093266666667 ["Nl/s"] 3139.5 ["W"] 340.79499999999996 ["W"] (exceeded: true) + var comp3 = compressorMap.Interpolate(n_ice2); // rpm: 1200 6.23922331 ["Nl/s"] 4609.5 ["W"] 667.68000000000006 ["W"] (exceeded: false) + + var workCompOff = comp1.PowerOff * T1 + comp3.PowerOff * T3; // 50600.028340142 ["Ws"] + var workCompOn = comp1.PowerOn * T1 + comp3.PowerOn * T3; // 388773.28735600761 ["Ws"] + var airOn = comp1.FlowRate * T1 + comp3.FlowRate * T3; // 522.52279399122142 ["Nl"] + + var kAir = ((workCompOn - workCompOff) / airOn).Value(); // 647193.31463566166 + var E_busAuxPS = kAir * deltaAir / 1e3; // 23182.627284607614 convert Nl to m^3 + + var fcPSAir = k_engline * E_busAuxPS; // 0.00060864878674201034 + var fcPSICEOffDriving = (comp2.PowerOff * k_engline * (1 - UF_ESS_Driving) * T2).Value(); // 8.1956035804536988E-05 + + var fcESS = fcIdle * T2.Value() * (1 - UF_ESS_Driving); // 0.0026830536210330951 + + var fcModSum = 0.195725; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(deltaAir, (modData.AirConsumed() - modData.AirGenerated()).Value(), 1e-6); + Assert.AreEqual(airDemand, corr.CorrectedAirDemand.Value(), 1e-6); + Assert.AreEqual(deltaAir, corr.DeltaAir.Value(), 1e-6); + + Assert.AreEqual(kAir, corr.kAir.Value(), 1e-3); + Assert.AreEqual(E_busAuxPS, corr.WorkBusAuxPSCorr.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(fcESS, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + + Assert.AreEqual(fcPSAir, f.FcBusAuxPSAirDemand.Value(), 1e-12); + Assert.AreEqual(0, f.FcBusAuxPSDragICEOffStandstill.Value(), 1e-12); + Assert.AreEqual(fcPSICEOffDriving, f.FcBusAuxPSDragICEOffDriving.Value(), 1e-12); + Assert.AreEqual(fcPSAir + fcPSICEOffDriving, f.FcBusAuxPs.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcESS, f.FcEssCorr.Value(), 1e-6); + Assert.AreEqual(fcModSum + fcPSAir + fcPSICEOffDriving + fcESS, f.FcBusAuxPsCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcPSAir + fcPSICEOffDriving + fcESS, f.FcFinal.Value(), 1e-6); + } + + [TestCase(500, 0, 4000), + TestCase(500, 500, 4000), + TestCase(500, 0, 550)] + public void TestBusAuxSmartES_ModDataCorrection(double p_es_cons, double p_es_gen, double p_es_smartgen) + { + var runData = GetRunData(true); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name + $"_{p_es_cons}_{p_es_gen}_{p_es_smartgen}"; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 51.171787824561704 ["s"] + var T3 = 0.SI<Second>(); // 50.195047986970792 ["s"] + + var P_ES_cons = p_es_cons.SI<Watt>(); + var P_ES_gen = p_es_gen.SI<Watt>(); + var P_ES_smartGen = p_es_smartgen.SI<Watt>(); + + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_busAux_ES_generated] = P_ES_gen; + modData[ModalResultField.P_busAux_ES_consumer_sum] = P_ES_cons; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // driving battery empty + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_busAux_ES_generated] = P_ES_smartGen; + modData[ModalResultField.P_busAux_ES_consumer_sum] = P_ES_cons; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T3 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_busAux_ES_generated] = P_ES_gen; + modData[ModalResultField.P_busAux_ES_consumer_sum] = P_ES_cons; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + + var E_es_missing_mech = (P_ES_cons * (T1 + T2 + T3) - (P_ES_gen * (T1 + T3) + P_ES_smartGen * T2)).Value() / busAuxAlternatorEff; // -171229.97701000841 + // -237850.27541296941 + // 63222.43732563284 + var fcModSum = 0.195725; // + + var fcEs = E_es_missing_mech * k_engline; // -0.0044955611148612719 + // -0.0062446451723992833 + // 0.0016598748407894498 + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyDCDCMissing.Value(), 1e-3); + + Assert.AreEqual(E_es_missing_mech, corr.WorkBusAuxESMech.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(fcEs, f.FcBusAuxEs.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcEs, f.FcBusAuxEsCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcEs, f.FcFinal.Value(), 1e-6); + + } + + [TestCase()] + public void TestBusAuxDCDCMissingConventional_ModDataCorrection() + { + var runData = GetRunData(true, alternatorType: AlternatorType.None); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + modData.AddElectricMotor(emPos); + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + + var P_DCDC = 3000.SI<Watt>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 51.171787824561704 ["s"] + var T3 = 0.SI<Second>(); // 50.195047986970792 ["s"] + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // driving battery empty + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = P_DCDC; + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T3 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + var E_dcdc_missing = (T2 * P_DCDC).Value() / emEff / dcdc_efficiency; // 174508.76830019907 + var fcDCDCMissing = E_dcdc_missing * k_engline; // 0.0045816442113220356 + var fcModSum = 0.195725; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(E_dcdc_missing, corr.EnergyDCDCMissing.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(fcDCDCMissing, f.FcESS_DCDCMissing.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcDCDCMissing, f.FcEssCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcDCDCMissing, f.FcFinal.Value(), 1e-6); + } + + [TestCase()] + public void TestBusAuxDCDCMissingHEV_ModDataCorrection() + { + var runData = GetRunData(true, alternatorType: AlternatorType.Smart); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + modData.AddElectricMotor(emPos); + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + + var P_DCDC = 3000.SI<Watt>(); + var T1 = 0.SI<Second>(); + var T2 = 0.SI<Second>(); + var T3 = 0.SI<Second>(); + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // driving battery empty + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 300.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 900.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = P_DCDC; + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T3 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + var E_dcdc_missing = (T2 * P_DCDC).Value() / emEff / dcdc_efficiency; + var fcDCDCMissing = E_dcdc_missing * k_engline; + var fcModSum = 0.195725; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(E_dcdc_missing, corr.EnergyDCDCMissing.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(fcDCDCMissing, f.FcESS_DCDCMissing.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcDCDCMissing, f.FcEssCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcDCDCMissing, f.FcFinal.Value(), 1e-6); + } + + [TestCase()] + public void TestBusAuxSmartPS_ModDataCorrection() + { + var runData = GetRunData(true); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice1 = 800.RPMtoRad(); + var n_ice2 = 1200.RPMtoRad(); + var n_ice = n_ice1; + var t_ice = 400.SI<NewtonMeter>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 51.171787824561704 ["s"] + var T3 = 0.SI<Second>(); // 50.195047986970792 ["s"] + + var Nl_consumed = 0.7.SI<NormLiterPerSecond>(); + var Nl_generated = Nl_consumed; + + var compressorMap = runData.BusAuxiliaries.PneumaticUserInputsConfig.CompressorMap; + + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + + modData[ModalResultField.Nl_busAux_PS_generated] = Nl_generated * dt; + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + var comp = compressorMap.Interpolate(n_ice); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // smart PS action + for (; i < 200; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = 0.RPMtoRad(); + modData[ModalResultField.P_ice_fcmap] = 0.SI<Watt>(); + modData[ModalResultField.FCWHTCc] = 0.SI<KilogramPerSecond>(); + modData[ModalResultField.FCFinal] = 0.SI<KilogramPerSecond>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + var comp = compressorMap.Interpolate(runData.EngineData.IdleSpeed); + modData[ModalResultField.Nl_busAux_PS_generated] = comp.FlowRate * dt; + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = n_ice2; + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T3 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + + modData[ModalResultField.Nl_busAux_PS_generated] = Nl_generated * dt; + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + var comp = compressorMap.Interpolate(n_ice); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + + var comp1 = compressorMap.Interpolate(n_ice1); // rad/s: 83.775804095727821 | rpm: 800 4.1756093266666667 ["Nl/s"] 3139.5 ["W"] 340.79499999999996 ["W"] (exceeded: false) + var comp2 = compressorMap.Interpolate(runData.EngineData.IdleSpeed); // rad/s: 83.775804095727821 | rpm: 800 4.1756093266666667 ["Nl/s"] 3139.5 ["W"] 340.79499999999996 ["W"] (exceeded: true) + var comp3 = compressorMap.Interpolate(n_ice2); // rad/s: 125.66370614359173 | rpm: 1200 6.23922331 ["Nl/s"] 4609.5 ["W"] 667.68000000000006 ["W"] (exceeded: false) + + var airDemand = (Nl_generated * (T1 + T2 + T3)).Value(); // 106.05137005359465 + var deltaAir = ((Nl_consumed - comp2.FlowRate) * T2).Value(); // -177.85314302525444 + + var workCompOff = comp1.PowerOff * T1 + comp3.PowerOff * T3; // 50600.028340142 ["Ws"] + var workCompOn = comp1.PowerOn * T1 + comp3.PowerOn * T3; // 388773.28735600761 ["Ws"] + var airOn = comp1.FlowRate * T1 + comp3.FlowRate * T3; // 522.52279399122142 ["Nl"] + + var kAir = ((workCompOn - workCompOff) / airOn).Value(); // 647193.31463566166 + var E_busAuxPS = kAir * deltaAir / 1e3; // -115105.36515288483 convert Nl to m^3 + + var fcPSAir = k_engline * E_busAuxPS; // -0.0030220362855212608 + var fcPSICEOffDriving = 0; + + var fcESS = 0; + + var fcModSum = 0.195725; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(deltaAir, (modData.AirConsumed() - modData.AirGenerated()).Value(), 1e-6); + Assert.AreEqual(airDemand, corr.CorrectedAirDemand.Value(), 1e-6); + Assert.AreEqual(deltaAir, corr.DeltaAir.Value(), 1e-6); + + Assert.AreEqual(kAir, corr.kAir.Value(), 1e-3); + Assert.AreEqual(E_busAuxPS, corr.WorkBusAuxPSCorr.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(fcESS, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + + Assert.AreEqual(fcPSAir, f.FcBusAuxPSAirDemand.Value(), 1e-12); + Assert.AreEqual(0, f.FcBusAuxPSDragICEOffStandstill.Value(), 1e-12); + Assert.AreEqual(fcPSICEOffDriving, f.FcBusAuxPSDragICEOffDriving.Value(), 1e-12); + Assert.AreEqual(fcPSAir + fcPSICEOffDriving, f.FcBusAuxPs.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcESS, f.FcEssCorr.Value(), 1e-6); + Assert.AreEqual(fcModSum + fcPSAir + fcPSICEOffDriving + fcESS, f.FcBusAuxPsCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcPSAir + fcPSICEOffDriving + fcESS, f.FcFinal.Value(), 1e-6); + + } + + [TestCase(0.5), // lower actual average air demand + TestCase(0.7), // no difference in air demand + TestCase(0.8), // higher actual average air demand + ] + public void TestBusAuxPSDemand_ModDataCorrection(double nlConsumedCorrected) + { + var runData = GetRunData(true); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name + $"_{nlConsumedCorrected}"; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice1 = 800.RPMtoRad(); + var n_ice2 = 1200.RPMtoRad(); + var n_ice = n_ice1; + var t_ice = 400.SI<NewtonMeter>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 101.36683581153247 ["s"] + + var Nl_consumed = 0.7.SI<NormLiterPerSecond>(); + var Nl_generated = Nl_consumed; + + var compressorMap = runData.BusAuxiliaries.PneumaticUserInputsConfig.CompressorMap; + + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + + modData[ModalResultField.Nl_busAux_PS_generated] = Nl_generated * dt; + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + var comp = compressorMap.Interpolate(n_ice); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = n_ice2; + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + + modData[ModalResultField.Nl_busAux_PS_generated] = Nl_generated * dt; + modData[ModalResultField.Nl_busAux_PS_consumer] = Nl_consumed * dt; + var comp = compressorMap.Interpolate(n_ice); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = comp.FlowRate * dt; + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = comp.PowerOff; + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = comp.PowerOn; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + + // fake that the actual air deman is different than initially assumed + var NlConsumedCorrected = nlConsumedCorrected.SI<NormLiterPerSecond>(); + (runData.BusAuxiliaries.PneumaticAuxillariesConfig as PneumaticsConsumersDemand).AirControlledSuspension = NlConsumedCorrected; + + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + + var airDemand = (NlConsumedCorrected * (T1 + T2)); // 75.750978609710458 ["Nl"] + // 106.05137005359464 ["Nl"] + // 121.20156577553674 ["Nl"] + var deltaAir = (airDemand - Nl_generated * (T1 + T2)).Value(); // -30.30039144388418 + // 0 + // 15.150195721942097 + + var comp1 = compressorMap.Interpolate(n_ice1); // rpm: 800 4.1756093266666667 ["Nl/s"] 3139.5 ["W"] 340.79499999999996 ["W"] (exceeded: false) + var comp3 = compressorMap.Interpolate(n_ice2); // rpm: 1200 6.23922331 ["Nl/s"] 4609.5 ["W"] 667.68000000000006 ["W"] (exceeded: false) + + var workCompOff = comp1.PowerOff * T1 + comp3.PowerOff * T2; // 84766.407634845338 ["Ws"] + var workCompOn = comp1.PowerOn * T1 + comp3.PowerOn * T2; // 624649.6433333247 ["Ws"] + var airOn = comp1.FlowRate * T1 + comp3.FlowRate * T2; // 841.79500540060076 ["Nl"] + + var kAir = ((workCompOn - workCompOff) / airOn).Value(); // 641347.63479804085 + + var E_busAuxPS = kAir * deltaAir / 1e3; // -19433.084385989911 convert Nl to m^3 + // 0 + // 9716.54219299496 + + var fcPSAir = k_engline * E_busAuxPS; // -0.00051020633205111981 + // 0 + // 0.00025510316602556007 + var fcPSICEOffDriving = 0; + + var fcESS = 0; + + var fcModSum = 0.306799952; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value()); + Assert.AreEqual(0, corr.WorkWHRElMech.Value()); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(0, (modData.AirConsumed() - modData.AirGenerated()).Value(), 1e-6); + Assert.AreEqual(airDemand.Value(), corr.CorrectedAirDemand.Value(), 1e-6); + Assert.AreEqual(deltaAir, corr.DeltaAir.Value(), 1e-6); + + Assert.AreEqual(kAir, corr.kAir.Value(), 1e-3); + Assert.AreEqual(E_busAuxPS, corr.WorkBusAuxPSCorr.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(fcESS, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + + Assert.AreEqual(fcPSAir, f.FcBusAuxPSAirDemand.Value(), 1e-12); + Assert.AreEqual(0, f.FcBusAuxPSDragICEOffStandstill.Value(), 1e-12); + Assert.AreEqual(fcPSICEOffDriving, f.FcBusAuxPSDragICEOffDriving.Value(), 1e-12); + Assert.AreEqual(fcPSAir + fcPSICEOffDriving, f.FcBusAuxPs.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcESS, f.FcEssCorr.Value(), 1e-6); + Assert.AreEqual(fcModSum + fcPSAir + fcPSICEOffDriving + fcESS, f.FcBusAuxPsCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcPSAir + fcPSICEOffDriving + fcESS, f.FcFinal.Value(), 1e-6); + } + + [TestCase()] + public void TestWHRElTruckAlternator_ModDataCorrection() + { + var runData = GetRunData(); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + + var P_WHR = 300.SI<Watt>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 101.36683581153247 ["s"] + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = P_WHR; + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = P_WHR; + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + var E_WHR_el = ((T1 + T2) * P_WHR).Value(); // 45450.587165826277 + var E_WHR_mech = -E_WHR_el / DeclarationData.AlternatorEfficiency; // -64929.410236894684 + + var fcWHR = (E_WHR_mech) * k_engline; // -0.0017046905978081038 + var fcModSum = 0.306799952; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(E_WHR_el, corr.WorkWHREl.Value(), 1e-3); + Assert.AreEqual(E_WHR_mech, corr.WorkWHRElMech.Value(), 1e-3); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyDCDCMissing.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(fcWHR, f.FcWHR.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcWHR, f.FcWHRCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcWHR, f.FcFinal.Value(), 1e-6); + + } + + [TestCase()] + public void TestWHRElBusAuxAlternator_ModDataCorrection() + { + var runData = GetRunData(true, alternatorType: AlternatorType.Conventional); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + modData.AddElectricMotor(emPos); + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + + var P_WHR = 300.SI<Watt>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 101.36683581153247 ["s"] + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + + // WHR + modData[ModalResultField.P_WHR_el_corr] = P_WHR; + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = P_WHR; + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + var E_WHR_el = ((T1 + T2) * P_WHR).Value(); // 45450.587165826277 + var E_WHR_mech = -E_WHR_el / busAuxAlternatorEff; // -60359.34550574539 + + var fcWHR = (E_WHR_mech) * k_engline; // -0.0015847057350141737 + var fcModSum = 0.306799952; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(E_WHR_el, corr.WorkWHREl.Value(), 1e-3); + Assert.AreEqual(E_WHR_mech, corr.WorkWHRElMech.Value(), 1e-3); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyDCDCMissing.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(fcWHR, f.FcWHR.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcWHR, f.FcWHRCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcWHR, f.FcFinal.Value(), 1e-6); + + } + + [TestCase()] + public void TestWHRElBusAuxNoAlternator_ModDataCorrection() + { + var runData = GetRunData(true, alternatorType: AlternatorType.Smart); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + modData.AddElectricMotor(emPos); + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + + var P_WHR = 300.SI<Watt>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 101.36683581153247 ["s"] + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + + // WHR + modData[ModalResultField.P_WHR_el_corr] = P_WHR; + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = P_WHR; + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + var E_WHR_el = ((T1 + T2) * P_WHR).Value(); // 45450.587165826277 + var E_WHR_mech = -E_WHR_el / emEff / dcdc_efficiency; // -51666.007918411138 + + var fcWHR = (E_WHR_mech) * k_engline; // -0.0013564663163188277 + var fcModSum = 0.306799952; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(E_WHR_el, corr.WorkWHREl.Value(), 1e-3); + Assert.AreEqual(E_WHR_mech, corr.WorkWHRElMech.Value(), 1e-3); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyDCDCMissing.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(fcWHR, f.FcWHR.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcWHR, f.FcWHRCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcWHR, f.FcFinal.Value(), 1e-6); + + } + + [TestCase] + public void TestWHRMech_ModDataCorrection() + { + var runData = GetRunData(); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + + var P_WHR = 300.SI<Watt>(); + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 101.36683581153247 ["s"] + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>() ; + modData[ModalResultField.P_WHR_mech_corr] = P_WHR; + + modData.CommitSimulationStep(); + absTime += dt; + } + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = P_WHR; + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + var E_WHR_mech = -((T1 + T2) * P_WHR).Value(); // -45450.587165826277 + + var fcWHR = (E_WHR_mech) * k_engline; // -0.0011932834184656728 + var fcModSum = 0.306799952; + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value(), 1e-3); + Assert.AreEqual(0, corr.WorkWHRElMech.Value(), 1e-3); + Assert.AreEqual(E_WHR_mech, corr.WorkWHRMech.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyDCDCMissing.Value(), 1e-3); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(fcWHR, f.FcWHR.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcWHR, f.FcWHRCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcWHR, f.FcFinal.Value(), 1e-6); + + } + + + [TestCase(10), + TestCase(-10)] + public void TestREESSoC_ModDataCorrection(double batPowerDemand) + { + var runData = GetRunData(true, alternatorType: AlternatorType.Smart); + runData.JobName = new StackTrace().GetFrame(0).GetMethod().Name; + var writer = new FileOutputWriter("."); + var modData = new ModalDataContainer(runData, writer, null) { + WriteModalResults = true + }; + + modData.AddElectricMotor(emPos); + + var fuel = runData.EngineData.Fuels[0]; + + var absTime = 0.SI<Second>(); + var rnd = new Random(210629); + var dt = 0.SI<Second>(); + + var i = 0; + // constant driving + var n_ice = 800.RPMtoRad(); + var t_ice = 400.SI<NewtonMeter>(); + + var batConditioning = (Math.Sign(batPowerDemand) * -1e3).SI<Watt>(); + var P_bat = batConditioning; + var T1 = 0.SI<Second>(); // 50.135121407888441 ["s"] + var T2 = 0.SI<Second>(); // 101.36683581153247 ["s"] + var soc = 0.5; + + for (; i < 100; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T1 += dt; + soc += (P_bat / 600.SI<Volt>() * dt) / BatCapacity; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(t_ice, n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = 120.SI<Watt>() * emEff; + modData[ModalResultField.P_EM_mech_, emPos] = 120.SI<Watt>(); + + modData[ModalResultField.P_reess_int] = P_bat; + modData[ModalResultField.P_reess_terminal] = P_bat * (P_bat < 0 ? batEff : 1/batEff); + modData[ModalResultField.REESSStateOfCharge] = soc.SI(); + + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + P_bat = (batPowerDemand * 1e3).SI<Watt>(); + + // constant driving different speed + modData[ModalResultField.P_ice_start] = 0000.SI<Watt>(); + n_ice = 1200.RPMtoRad(); + for (; i < 300; i++) { + dt = (rnd.NextDouble() * 0.2 + 0.4).SI<Second>(); + T2 += dt; + soc += (P_bat / 600.SI<Volt>() * dt) / BatCapacity; + + modData[ModalResultField.time] = absTime + dt / 2; + modData[ModalResultField.simulationInterval] = dt; + + modData[ModalResultField.v_act] = 50.KMPHtoMeterPerSecond(); + modData[ModalResultField.ICEOn] = true; + + modData[ModalResultField.n_ice_avg] = n_ice; + modData[ModalResultField.P_ice_fcmap] = n_ice * t_ice; + var fc = fuel.ConsumptionMap.GetFuelConsumption(400.SI<NewtonMeter>(), n_ice).Value * + fuel.FuelConsumptionCorrectionFactor; + modData[ModalResultField.FCWHTCc] = fc; + modData[ModalResultField.FCFinal] = fc; + + + modData[ModalResultField.P_aux_ESS_mech_ice_off] = 0.SI<Watt>(); + modData[ModalResultField.P_aux_ESS_mech_ice_on] = 0.SI<Watt>(); + + modData[ModalResultField.P_DCDC_missing] = 0.SI<Watt>(); + modData[ModalResultField.Nl_busAux_PS_generated] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_consumer] = 0.SI<NormLiter>(); + modData[ModalResultField.Nl_busAux_PS_generated_alwaysOn] = 0.SI<NormLiter>(); + modData[ModalResultField.P_busAux_PS_generated_dragOnly] = 0.SI<Watt>(); + modData[ModalResultField.P_busAux_PS_generated_alwaysOn] = 0.SI<Watt>(); + + modData[ModalResultField.P_EM_electricMotor_el_, emPos] = -120.SI<Watt>() / emEff; + modData[ModalResultField.P_EM_mech_, emPos] = -120.SI<Watt>(); + + modData[ModalResultField.P_reess_int] = P_bat; + modData[ModalResultField.P_reess_terminal] = P_bat * (P_bat < 0 ? batEff : 1 / batEff); + modData[ModalResultField.REESSStateOfCharge] = soc.SI(); + + // WHR + modData[ModalResultField.P_WHR_el_corr] = 0.SI<Watt>(); + modData[ModalResultField.P_WHR_mech_corr] = 0.SI<Watt>(); + + modData.CommitSimulationStep(); + absTime += dt; + } + + modData.Finish(VectoRun.Status.Success); + var corr = modData.CorrectedModalData as CorrectedModalData; + + var k_engline = 2.6254521511724e-8; + var E_REESS = (T2 * P_bat + batConditioning * T1).Value(); // 963533.23670743615 + var E_REESS_mech = -E_REESS * (P_bat > 0 ? emEff * batEff : 1 / (emEff * batEff)); // -898880.15652436716 + + var fcModSum = 0.306799952; + var fcReessSoc = E_REESS_mech * k_engline; // -0.023599668405930831 + + Assert.AreEqual(k_engline, modData.EngineLineCorrectionFactor(fuel.FuelData).Value(), 1e-15); + Assert.AreEqual(0, corr.WorkWHREl.Value(), 1e-3); + Assert.AreEqual(0, corr.WorkWHRElMech.Value(), 1e-3); + Assert.AreEqual(0, corr.WorkWHRMech.Value()); + + Assert.AreEqual(0, corr.EnergyAuxICEOnStandstill.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffStandstill.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyAuxICEOnDriving.Value(), 1e-3); + Assert.AreEqual(0, corr.EnergyAuxICEOffDriving.Value(), 1e-3); + + Assert.AreEqual(0, corr.EnergyDCDCMissing.Value(), 1e-3); + + Assert.AreEqual(E_REESS, modData.TimeIntegral<WattSecond>(ModalResultField.P_reess_int.GetName()).Value(), 1e-6); + Assert.AreEqual(E_REESS_mech, corr.DeltaEReessMech.Value(), 1e-6); + + var f = corr.FuelCorrection[fuel.FuelData.FuelType] as FuelConsumptionCorrection; + + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxStandstill_ICEOn.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOff.Value(), 1e-12); + Assert.AreEqual(0, f.FcESS_AuxDriving_ICEOn.Value(), 1e-12); + + Assert.AreEqual(0, f.FcWHR.Value(), 1e-12); + + Assert.AreEqual(fcReessSoc, f.FcREESSSoc.Value(), 1e-12); + + Assert.AreEqual(fcModSum, modData.TotalFuelConsumption(ModalResultField.FCWHTCc, fuel.FuelData).Value(), 1e-6); + Assert.AreEqual(fcModSum + fcReessSoc, f.FcREESSSoCCorr.Value(), 1e-6); + + Assert.AreEqual(fcModSum + fcReessSoc, f.FcFinal.Value(), 1e-6); + + } + + + private VectoRunData GetRunData(bool withBusAux = false, bool smartCompressor = false, AlternatorType alternatorType = AlternatorType.Conventional) + { + var fcMapHeader = "engine speed [rpm],torque [Nm],fuel consumption [g/h]"; + var fcMapEntries = new[] { + "600,-107,0", + "600,0,1042", + "600,916,10963", + "2000,-215,0", + "2000,0,6519", + "2000,966,40437" + }; + + var retVal = new VectoRunData() { + DriverData = new DriverData() { + EngineStopStart = new DriverData.EngineStopStartData() { + UtilityFactorDriving = UF_ESS_Driving, + UtilityFactorStandstill = UF_ESS_Standstill, + } + }, + EngineData = new CombustionEngineData() { + IdleSpeed = 600.RPMtoRad(), + Fuels = new List<CombustionEngineFuelData>() { + new CombustionEngineFuelData() { + FuelData = FuelData.Diesel, + FuelConsumptionCorrectionFactor = 1.012, + ConsumptionMap = FuelConsumptionMapReader.ReadFromStream(InputDataHelper.InputDataAsStream(fcMapHeader, fcMapEntries)) + } + } + }, + }; + + if (withBusAux) { + retVal.BusAuxiliaries = new AuxiliaryConfig() { + ElectricalUserInputsConfig = new ElectricsUserInputsConfig() { + ConnectESToREESS = true, + AlternatorMap = new SimpleAlternator(busAuxAlternatorEff), + AlternatorType = alternatorType, + AlternatorGearEfficiency = 1, + DCDCEfficiency = dcdc_efficiency, + }, + PneumaticAuxillariesConfig = CreatePneumaticAuxConfig(0.7.SI<NormLiterPerSecond>()), + PneumaticUserInputsConfig = CreatePneumaticUserInputsConfig(smartCompressor), + Actuations = new Actuations() { + Braking = 0, + Kneeling = 0, + ParkBrakeAndDoors = 0, + CycleTime = 1.SI<Second>() + }, + VehicleData = new VehicleData() { + CurbMass = 14000.SI<Kilogram>() + } + }; + retVal.ElectricMachinesData = new List<Tuple<PowertrainPosition, ElectricMotorData>>() { + Tuple.Create(emPos, new ElectricMotorData()) + }; + } + + return retVal; + } + + protected internal virtual IPneumaticsConsumersDemand CreatePneumaticAuxConfig(NormLiterPerSecond averageAirDemand) + { + return new PneumaticsConsumersDemand() { + AdBlueInjection = 0.SI<NormLiterPerSecond>(), + AirControlledSuspension = averageAirDemand, + Braking = 0.SI<NormLiterPerKilogram>(), + BreakingWithKneeling = 0.SI<NormLiterPerKilogramMeter>(), + DeadVolBlowOuts = 0.SI<PerSecond>(), + DeadVolume = 0.SI<NormLiter>(), + NonSmartRegenFractionTotalAirDemand = 0, + SmartRegenFractionTotalAirDemand = 0, + OverrunUtilisationForCompressionFraction = + Constants.BusAuxiliaries.PneumaticConsumersDemands.OverrunUtilisationForCompressionFraction, + DoorOpening = 0.SI<NormLiter>(), + StopBrakeActuation = 0.SI<NormLiterPerKilogram>(), + }; + } + + protected PneumaticUserInputsConfig CreatePneumaticUserInputsConfig(bool smartCompressor) + { + return new PneumaticUserInputsConfig() { + CompressorMap = + DeclarationData.BusAuxiliaries.GetCompressorMap("Medium Supply 2-stage", "visco"), + CompressorGearEfficiency = Constants.BusAuxiliaries.PneumaticUserConfig.CompressorGearEfficiency, + CompressorGearRatio = 1.0, + SmartAirCompression = smartCompressor, + SmartRegeneration = false, + KneelingHeight = 0.SI<Meter>(), + AirSuspensionControl = ConsumerTechnology.Pneumatically, + AdBlueDosing = ConsumerTechnology.Electrically, + Doors = ConsumerTechnology.Electrically + }; + } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/3speedEV.vgbx b/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/3speedEV.vgbx new file mode 100644 index 0000000000000000000000000000000000000000..2899660e38bff86e3e841df4b2b7ad87aaaca0b0 --- /dev/null +++ b/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/3speedEV.vgbx @@ -0,0 +1,54 @@ +{ + "Header": { + "CreatedBy": "", + "Date": "2020-11-03T14:19:09.9858299Z", + "AppVersion": "3", + "FileVersion": 6 + }, + "Body": { + "SavedInDeclMode": false, + "ModelName": "3_speed_AMT", + "Inertia": 0.0, + "TracInt": 0.8, + "Gears": [ + { + "Ratio": 2.64, + "LossMap": "Transmission\\Axle_4x2_Tractor.vtlm" + }, + { + "Ratio": 17.5, + "LossMap": "Transmission\\Gear_1.vtlm", + "ShiftPolygon": "", + "MaxTorque": "", + "MaxSpeed": "" + }, + { + "Ratio": 6.49, + "LossMap": "Transmission\\Gear_2.vtlm", + "ShiftPolygon": "", + "MaxTorque": "", + "MaxSpeed": "" + }, + { + "Ratio": 2.48, + "LossMap": "Transmission\\Gear_3.vtlm", + "ShiftPolygon": "", + "MaxTorque": "", + "MaxSpeed": "" + } + ], + "TqReserve": 0.0, + "ShiftTime": 2.0, + "StartTqReserve": 20.0, + "StartSpeed": 2.22222222222222, + "StartAcc": 0.8, + "GearboxType": "AMT", + "TorqueConverter": { + "Enabled": false + }, + "DownshiftAfterUpshiftDelay": 6.0, + "UpshiftAfterDownshiftDelay": 6.0, + "UpshiftMinAcceleration": 0.1, + "PowershiftShiftTime": 0.0 + } +} \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/BEV_ENG_3speed.vecto b/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/BEV_ENG_3speed.vecto new file mode 100644 index 0000000000000000000000000000000000000000..ec266b20cc3dc2fc8c20f670fae33786d01c5ab8 --- /dev/null +++ b/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/BEV_ENG_3speed.vecto @@ -0,0 +1,45 @@ +{ + "Header": { + "CreatedBy": " ()", + "Date": "2016-10-13T08:55:18.2100810Z", + "AppVersion": "3", + "FileVersion": 9 + }, + "Body": { + "SavedInDeclMode": false, + "EngineOnlyMode": false, + "VehicleFile": "BatteryElectricVehicle.vveh", + "GearboxFile": "3speedEV.vgbx", + "TCU": "3speedEV.vgbx", + "Padd_electric": 3540.0, + + "VACC": "Truck.vacc", + + "LAC": { + "Enabled": true, + "PreviewDistanceFactor": 10.0, + "DF_offset": 2.5, + "DF_scaling": 1.5, + "DF_targetSpeedLookup": "", + "Df_velocityDropLookup": "" + }, + "OverSpeedEcoRoll": { + "Mode": "Off", + "MinSpeed": 50.0, + "OverSpeed": 5.0, + "UnderSpeed": 5.0 + }, + "Cycles": [ + "LongHaul", + "Coach", + "Construction", + "HeavyUrban", + "Interurban", + "MunicipalUtility", + "RegionalDelivery", + "Suburban", + "Urban", + "UrbanDelivery" + ] + } +} \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/Integration/Buses/FactorMethod/vecto_vehicle-completed_heavyBus_41.xml b/VectoCore/VectoCoreTest/TestData/Integration/Buses/FactorMethod/vecto_vehicle-completed_heavyBus_41.xml index 95cf175667d01c6c17614c00c3e49ddafcd1b2c2..c9db0481c519a1fab72f7b3ce821c71351e5c0e3 100644 --- a/VectoCore/VectoCoreTest/TestData/Integration/Buses/FactorMethod/vecto_vehicle-completed_heavyBus_41.xml +++ b/VectoCore/VectoCoreTest/TestData/Integration/Buses/FactorMethod/vecto_vehicle-completed_heavyBus_41.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob v:\VectoCore\VectoCor <LegislativeCategory>M3</LegislativeCategory> <CorrectedActualMass>8300</CorrectedActualMass> <TechnicalPermissibleMaximumLadenMass>18000</TechnicalPermissibleMaximumLadenMass> - <AirdragModifiedMultistage>false</AirdragModifiedMultistage> + <AirdragModifiedMultistage>true</AirdragModifiedMultistage> <NgTankSystem>Compressed</NgTankSystem> <ClassBus>II+III</ClassBus> <NumberPassengerSeatsLowerDeck>30</NumberPassengerSeatsLowerDeck> diff --git a/VectoCore/VectoCoreTest/TestData/Integration/Buses/FactorMethod/vecto_vehicle-completed_heavyBus_41_mixed.xml b/VectoCore/VectoCoreTest/TestData/Integration/Buses/FactorMethod/vecto_vehicle-completed_heavyBus_41_mixed.xml index 3379693363ea865a1587972bd5c7c309716a4eb5..0fe54266ec17ef49046ea9f5c5aa41c36db79bec 100644 --- a/VectoCore/VectoCoreTest/TestData/Integration/Buses/FactorMethod/vecto_vehicle-completed_heavyBus_41_mixed.xml +++ b/VectoCore/VectoCoreTest/TestData/Integration/Buses/FactorMethod/vecto_vehicle-completed_heavyBus_41_mixed.xml @@ -19,8 +19,10 @@ xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob v:\VectoCore\VectoCor <AirdragModifiedMultistage>true</AirdragModifiedMultistage> <NgTankSystem>Compressed</NgTankSystem> <ClassBus>II+III</ClassBus> - <NumberPassengersLowerDeck>30</NumberPassengersLowerDeck> - <NumberPassengersUpperDeck>0</NumberPassengersUpperDeck> + <NumberPassengerSeatsLowerDeck>30</NumberPassengerSeatsLowerDeck> + <NumberPassengersStandingLowerDeck>0</NumberPassengersStandingLowerDeck> + <NumberPassengerSeatsUpperDeck>0</NumberPassengerSeatsUpperDeck> + <NumberPassengersStandingUpperDeck>0</NumberPassengersStandingUpperDeck> <BodyworkCode>CA</BodyworkCode> <LowEntry>true</LowEntry> <HeightIntegratedBody>3000</HeightIntegratedBody> diff --git a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.6_Buses/exempted_primary_heavyBus.xml b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.6_Buses/exempted_primary_heavyBus.xml new file mode 100644 index 0000000000000000000000000000000000000000..aef216779b96bd7d1342f7324dd2323928faf9fe --- /dev/null +++ b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.6_Buses/exempted_primary_heavyBus.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:VectoInputDeclaration schemaVersion="2.0" +xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" +xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" +xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" +xmlns:di="http://www.w3.org/2000/09/xmldsig#" +xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob v:\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> + <v2.0:Vehicle id="VEH-1234567890" xsi:type="v2.6:ExemptedPrimaryHeavyBusType"> + <Manufacturer>Some Manufacturer</Manufacturer> + <ManufacturerAddress>Infinite Loop 1</ManufacturerAddress> + <Model>Sample Bus Model</Model> + <VIN>VEH-1234567890</VIN> + <Date>2020-01-09T11:00:00Z</Date> + <LegislativeCategory>N2</LegislativeCategory> + <ChassisConfiguration>Bus</ChassisConfiguration> + <AxleConfiguration>6x2</AxleConfiguration> + <Articulated>false</Articulated> + <TechnicalPermissibleMaximumLadenMass>15400</TechnicalPermissibleMaximumLadenMass> + <ZeroEmissionVehicle>true</ZeroEmissionVehicle> + <SumNetPower>350000</SumNetPower> + <Technology>Fuel cell vehicle</Technology> + </v2.0:Vehicle> +</tns:VectoInputDeclaration> diff --git a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-exempted_input_full-sample.xml b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-exempted_input_full-sample.xml index b6069da5a5049db6e1487e69ca57609b1e78efc3..c8f44fc1b3bb0d1c4f800d92383c39cb6692142e 100644 --- a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-exempted_input_full-sample.xml +++ b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-exempted_input_full-sample.xml @@ -1 +1,25 @@ -<?xml version="1.0" encoding="UTF-8"?> <tns:VectoInputDeclaration schemaVersion="2.8" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob v:\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> <v2.0:Vehicle id="VEH-1234567890" xsi:type="ExemptedInterimStageInputType"> <Manufacturer>Some Manufacturer</Manufacturer> <ManufacturerAddress>Infinite Loop</ManufacturerAddress> <VIN>VEH-1234567891</VIN> <Date>2021-01-09T11:00:00Z</Date> <Model>Sample Bus Model 2</Model> <LegislativeCategory>M3</LegislativeCategory> <CorrectedActualMass>7000</CorrectedActualMass> <TechnicalPermissibleMaximumLadenMass>10000</TechnicalPermissibleMaximumLadenMass> <ClassBus>A</ClassBus> <NumberPassengersLowerDeck>10</NumberPassengersLowerDeck> <NumberPassengersUpperDeck>20</NumberPassengersUpperDeck> <BodyworkCode>CC</BodyworkCode> <LowEntry>true</LowEntry> <HeightIntegratedBody>2500</HeightIntegratedBody> </v2.0:Vehicle> </tns:VectoInputDeclaration> \ No newline at end of file +<?xml version="1.0" encoding="UTF-8"?> +<tns:VectoInputDeclaration schemaVersion="2.8" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" +xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" +xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob v:\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> + <v2.0:Vehicle id="VEH-1234567890" xsi:type="ExemptedInterimStageInputType"> + <Manufacturer>Some Manufacturer</Manufacturer> + <ManufacturerAddress>Infinite Loop</ManufacturerAddress> + <VIN>VEH-1234567891</VIN> + <Date>2021-01-09T11:00:00Z</Date> + <Model>Sample Bus Model 2</Model> + <LegislativeCategory>M3</LegislativeCategory> + <CorrectedActualMass>7000</CorrectedActualMass> + <TechnicalPermissibleMaximumLadenMass>10000</TechnicalPermissibleMaximumLadenMass> + <ClassBus>A</ClassBus> + <NumberPassengerSeatsLowerDeck>10</NumberPassengerSeatsLowerDeck> + <NumberPassengersStandingLowerDeck>42</NumberPassengersStandingLowerDeck> + <NumberPassengerSeatsUpperDeck>20</NumberPassengerSeatsUpperDeck> + <NumberPassengersStandingUpperDeck>13</NumberPassengersStandingUpperDeck> + <BodyworkCode>CE</BodyworkCode> + <LowEntry>true</LowEntry> + <HeightIntegratedBody>2500</HeightIntegratedBody> + </v2.0:Vehicle> +</tns:VectoInputDeclaration> \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-exempted_input_only_certain_entries02-sample.xml b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-exempted_input_only_certain_entries02-sample.xml index a580db7446d77a5ac44a28e6284b220ebfc0e9f9..7c9454e563e8bbe3283a2361f19032c6ef2ebf79 100644 --- a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-exempted_input_only_certain_entries02-sample.xml +++ b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-exempted_input_only_certain_entries02-sample.xml @@ -1 +1,17 @@ -<?xml version="1.0" encoding="UTF-8"?> <tns:VectoInputDeclaration schemaVersion="2.8" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob v:\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> <v2.0:Vehicle id="VEH-1234567890" xsi:type="ExemptedInterimStageInputType"> <Manufacturer>Some Manufacturer 2</Manufacturer> <ManufacturerAddress>Some Manufacturer Address 2</ManufacturerAddress> <VIN>VEH-1234567891</VIN> <Date>2021-01-09T11:00:00Z</Date> <NumberPassengersLowerDeck>10</NumberPassengersLowerDeck> <NumberPassengersUpperDeck>20</NumberPassengersUpperDeck> </v2.0:Vehicle> </tns:VectoInputDeclaration> \ No newline at end of file +<?xml version="1.0" encoding="UTF-8"?> +<tns:VectoInputDeclaration schemaVersion="2.8" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" +xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" +xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob v:\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> + <v2.0:Vehicle id="VEH-1234567890" xsi:type="ExemptedInterimStageInputType"> + <Manufacturer>Some Manufacturer 2</Manufacturer> + <ManufacturerAddress>Some Manufacturer Address 2</ManufacturerAddress> + <VIN>VEH-1234567891</VIN> + <Date>2021-01-09T11:00:00Z</Date> + <NumberPassengerSeatsLowerDeck>10</NumberPassengerSeatsLowerDeck> + <NumberPassengersStandingLowerDeck>42</NumberPassengersStandingLowerDeck> + <NumberPassengerSeatsUpperDeck>20</NumberPassengerSeatsUpperDeck> + <NumberPassengersStandingUpperDeck>13</NumberPassengersStandingUpperDeck> + </v2.0:Vehicle> +</tns:VectoInputDeclaration> \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-stage_input_full-sample.xml b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-stage_input_full-sample.xml index 85f865e71925dbca4a77fc9246cadbfcf02df70b..24f2810fdf692cbe4e1f1f7af756eddf86f2e8fd 100644 --- a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-stage_input_full-sample.xml +++ b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersion2.8/vecto_vehicle-stage_input_full-sample.xml @@ -1,95 +1,90 @@ -<?xml version="1.0" encoding="UTF-8"?> -<tns:VectoInputDeclaration schemaVersion="2.8" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" -xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" -xmlns:v2.3="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3" -xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" -xmlns:di="http://www.w3.org/2000/09/xmldsig#" -xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob v:\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> - <v2.0:Vehicle id="VEH-1234567890" xsi:type="InterimStageInputType"> - <Manufacturer>Some Manufacturer</Manufacturer> - <ManufacturerAddress>Some Manufacturer Address</ManufacturerAddress> - <VIN>VEH-1234567890</VIN> - <Date>2020-01-09T11:00:00Z</Date> - <Model>Sample Bus Model</Model> - <LegislativeCategory>M3</LegislativeCategory> - <CorrectedActualMass>500</CorrectedActualMass> - <TechnicalPermissibleMaximumLadenMass>3500</TechnicalPermissibleMaximumLadenMass> - <NgTankSystem>Compressed</NgTankSystem> - <ClassBus>II+III</ClassBus> - <NumberPassengerSeatsLowerDeck>1</NumberPassengerSeatsLowerDeck> - <NumberPassengersStandingLowerDeck>10</NumberPassengersStandingLowerDeck> - <NumberPassengerSeatsUpperDeck>11</NumberPassengerSeatsUpperDeck> - <NumberPassengersStandingUpperDeck>2</NumberPassengersStandingUpperDeck> - <BodyworkCode>CB</BodyworkCode> - <LowEntry>false</LowEntry> - <HeightIntegratedBody>2500</HeightIntegratedBody> - <VehicleLength>9500</VehicleLength> - <VehicleWidth>2500</VehicleWidth> - <EntranceHeight>2000</EntranceHeight> - <DoorDriveTechnology>electric</DoorDriveTechnology> - <VehicleDeclarationType>interim</VehicleDeclarationType> - <ADAS> - <v2.3:EngineStopStart>true</v2.3:EngineStopStart> - <v2.3:EcoRollWithoutEngineStop>false</v2.3:EcoRollWithoutEngineStop> - <v2.3:EcoRollWithEngineStop>false</v2.3:EcoRollWithEngineStop> - <v2.3:PredictiveCruiseControl>none</v2.3:PredictiveCruiseControl> - <v2.3:APTEcoRollReleaseLockupClutch>true</v2.3:APTEcoRollReleaseLockupClutch> - </ADAS> - <Components xsi:type="CompletedVehicleComponentsDeclarationType"> - <AirDrag> - <v2.0:Data xsi:type="v2.0:AirDragDataDeclarationType" id="CabinX23h"> - <v2.0:Manufacturer>Generic Manufacturer</v2.0:Manufacturer> - <v2.0:Model>Generic Model</v2.0:Model> - <v2.0:CertificationNumber>e12*0815/8051*2017/05E0000*00</v2.0:CertificationNumber> - <v2.0:Date>2017-03-24T15:00:00Z</v2.0:Date> - <v2.0:AppVersion>Vecto AirDrag x.y</v2.0:AppVersion> - <v2.0:CdxA_0>6.31</v2.0:CdxA_0> - <v2.0:TransferredCdxA>6.32</v2.0:TransferredCdxA> - <v2.0:DeclaredCdxA>6.34</v2.0:DeclaredCdxA> - </v2.0:Data> - <v2.0:Signature> - <di:Reference URI="#CabinX23h"> - <di:Transforms> - <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization"/> - <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> - </di:Transforms> - <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> - <di:DigestValue>b9SHCfOoVrBxFQ8wwDK32OO+9bd85DuaUdgs6j/29N8=</di:DigestValue> - </di:Reference> - </v2.0:Signature> - </AirDrag> - <Auxiliaries> - <Data xsi:type="CompletedVehicleAuxiliaryDataDeclarationType"> - <ElectricSystem> - <LEDLights> - <Interiorlights>false</Interiorlights> - <Dayrunninglights>true</Dayrunninglights> - <Positionlights>true</Positionlights> - <Brakelights>true</Brakelights> - <Headlights>false</Headlights> - </LEDLights> - </ElectricSystem> - <HVAC> - <SystemConfiguration>0</SystemConfiguration> - <HeatPumpTypeDriverCompartment>none</HeatPumpTypeDriverCompartment> - <HeatPumpModeDriverCompartment>heating</HeatPumpModeDriverCompartment> - <HeatPumpTypePassengerCompartment>non R-744 2-stage</HeatPumpTypePassengerCompartment> - <HeatPumpModePassengerCompartment>cooling</HeatPumpModePassengerCompartment> - <HeatPumpTypePassengerCompartment>non R-744 3-stage</HeatPumpTypePassengerCompartment> - <HeatPumpModePassengerCompartment>heating</HeatPumpModePassengerCompartment> - <HeatPumpTypePassengerCompartment>non R-744 2-stage</HeatPumpTypePassengerCompartment> - <HeatPumpModePassengerCompartment>cooling</HeatPumpModePassengerCompartment> - <AuxiliaryHeaterPower>50</AuxiliaryHeaterPower> - <DoubleGlazing>false</DoubleGlazing> - <AdjustableAuxiliaryHeater>true</AdjustableAuxiliaryHeater> - <SeparateAirDistributionDucts>false</SeparateAirDistributionDucts> - <WaterElectricHeater>true</WaterElectricHeater> - <AirElectricHeater>false</AirElectricHeater> - <OtherHeatingTechnology>false</OtherHeatingTechnology> - </HVAC> - </Data> - </Auxiliaries> - </Components> - </v2.0:Vehicle> +<?xml version="1.0" encoding="utf-8"?> +<tns:VectoInputDeclaration xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" schemaVersion="2.8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xmlns:v2.3="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3" xmlns:di="http://www.w3.org/2000/09/xmldsig#" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob V:\VectoCore\VectoCore\Resources\XSD\VectoDeclarationJob.xsd"> + <v2.0:Vehicle id="VEH-1234567890" xsi:type="InterimStageInputType"> + <Manufacturer>Some Manufacturer</Manufacturer> + <ManufacturerAddress>Some Manufacturer Address</ManufacturerAddress> + <VIN>VEH-1234567890</VIN> + <Date>2021-06-30T22:00:00Z</Date> + <Model>Sample Bus Model</Model> + <LegislativeCategory>M3</LegislativeCategory> + <CorrectedActualMass>500</CorrectedActualMass> + <TechnicalPermissibleMaximumLadenMass>3500</TechnicalPermissibleMaximumLadenMass> + <AirdragModifiedMultistage>true</AirdragModifiedMultistage> + <NgTankSystem>Compressed</NgTankSystem> + <ClassBus>II+III</ClassBus> + <NumberPassengerSeatsLowerDeck>1</NumberPassengerSeatsLowerDeck> + <NumberPassengersStandingLowerDeck>10</NumberPassengersStandingLowerDeck> + <NumberPassengerSeatsUpperDeck>11</NumberPassengerSeatsUpperDeck> + <NumberPassengersStandingUpperDeck>2</NumberPassengersStandingUpperDeck> + <BodyworkCode>CB</BodyworkCode> + <LowEntry>false</LowEntry> + <HeightIntegratedBody>2500</HeightIntegratedBody> + <VehicleLength>9500</VehicleLength> + <VehicleWidth>2500</VehicleWidth> + <EntranceHeight>2000</EntranceHeight> + <DoorDriveTechnology>electric</DoorDriveTechnology> + <VehicleDeclarationType>interim</VehicleDeclarationType> + <ADAS> + <v2.3:EngineStopStart>true</v2.3:EngineStopStart> + <v2.3:EcoRollWithoutEngineStop>false</v2.3:EcoRollWithoutEngineStop> + <v2.3:EcoRollWithEngineStop>false</v2.3:EcoRollWithEngineStop> + <v2.3:PredictiveCruiseControl>none</v2.3:PredictiveCruiseControl> + <v2.3:APTEcoRollReleaseLockupClutch>true</v2.3:APTEcoRollReleaseLockupClutch> + </ADAS> + <Components xsi:type="CompletedVehicleComponentsDeclarationType"> + <AirDrag> + <v2.0:Data id="CabinX23h" xsi:type="v2.0:AirDragDataDeclarationType"> + <v2.0:Manufacturer>Generic Manufacturer</v2.0:Manufacturer> + <v2.0:Model>Generic Model</v2.0:Model> + <v2.0:CertificationNumber>e12*0815/8051*2017/05E0000*00</v2.0:CertificationNumber> + <v2.0:Date>2017-03-24T15:00:00Z</v2.0:Date> + <v2.0:AppVersion>Vecto AirDrag x.y</v2.0:AppVersion> + <v2.0:CdxA_0>6.31</v2.0:CdxA_0> + <v2.0:TransferredCdxA>6.32</v2.0:TransferredCdxA> + <v2.0:DeclaredCdxA>6.34</v2.0:DeclaredCdxA> + </v2.0:Data> + <v2.0:Signature> + <di:Reference URI="#CabinX23h"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>b9SHCfOoVrBxFQ8wwDK32OO+9bd85DuaUdgs6j/29N8=</di:DigestValue> + </di:Reference> + </v2.0:Signature> + </AirDrag> + <Auxiliaries> + <Data xsi:type="CompletedVehicleAuxiliaryDataDeclarationType"> + <ElectricSystem> + <LEDLights> + <Interiorlights>false</Interiorlights> + <Dayrunninglights>true</Dayrunninglights> + <Positionlights>true</Positionlights> + <Brakelights>true</Brakelights> + <Headlights>false</Headlights> + </LEDLights> + </ElectricSystem> + <HVAC> + <SystemConfiguration>0</SystemConfiguration> + <HeatPumpTypeDriverCompartment>none</HeatPumpTypeDriverCompartment> + <HeatPumpModeDriverCompartment>heating</HeatPumpModeDriverCompartment> + <HeatPumpTypePassengerCompartment>non R-744 2-stage</HeatPumpTypePassengerCompartment> + <HeatPumpModePassengerCompartment>cooling</HeatPumpModePassengerCompartment> + <HeatPumpTypePassengerCompartment>non R-744 3-stage</HeatPumpTypePassengerCompartment> + <HeatPumpModePassengerCompartment>heating</HeatPumpModePassengerCompartment> + <HeatPumpTypePassengerCompartment>non R-744 2-stage</HeatPumpTypePassengerCompartment> + <HeatPumpModePassengerCompartment>cooling</HeatPumpModePassengerCompartment> + <AuxiliaryHeaterPower>50</AuxiliaryHeaterPower> + <DoubleGlazing>false</DoubleGlazing> + <AdjustableAuxiliaryHeater>true</AdjustableAuxiliaryHeater> + <SeparateAirDistributionDucts>false</SeparateAirDistributionDucts> + <WaterElectricHeater>true</WaterElectricHeater> + <AirElectricHeater>false</AirElectricHeater> + <OtherHeatingTechnology>false</OtherHeatingTechnology> + </HVAC> + </Data> + </Auxiliaries> + </Components> + </v2.0:Vehicle> </tns:VectoInputDeclaration> \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersionMultistage.0.1/AirdragLoadTestFilev2.xml b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersionMultistage.0.1/AirdragLoadTestFilev2.xml new file mode 100644 index 0000000000000000000000000000000000000000..45cc6f8f24c4475d5cf9c26215e4ac6e5a8a3c5d --- /dev/null +++ b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersionMultistage.0.1/AirdragLoadTestFilev2.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<tns:VectoInputDeclaration xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationComponent:v2.0" xmlns:di="http://www.w3.org/2000/09/xmldsig#" schemaVersion="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationComponent:v2.0 https://webgate.ec.europa.eu/CITnet/svn/VECTO/trunk/Share/XML/XSD/VectoComponent.xsd"> + <tns:AirDrag> + <Data id="TestAirDrag1234" xsi:type="AirDragDataDeclarationType"> + <Manufacturer>Test AirDrag Manufacturer</Manufacturer> + <Model>Test AirDrag Model</Model> + <CertificationNumber>e12*0815/8051*2020/05E0000*66</CertificationNumber> + <Date>2020-04-28T09:16:15.1270795Z</Date> + <AppVersion>Vecto AirDrag Test Load</AppVersion> + <CdxA_0>6.12</CdxA_0> + <TransferredCdxA>7.12</TransferredCdxA> + <DeclaredCdxA>8.12</DeclaredCdxA> + </Data> + <Signature> + <di:Reference URI="#TestAirDrag1234"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>Yd3UDJ/zKPhsmPadJeC4Ez/q7o3G82Zbq3mX3tSqLDw=</di:DigestValue> + </di:Reference> + </Signature> + </tns:AirDrag> +</tns:VectoInputDeclaration> \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersionMultistage.0.1/exempted_primary_heavyBus.VIF.xml b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersionMultistage.0.1/exempted_primary_heavyBus.VIF.xml new file mode 100644 index 0000000000000000000000000000000000000000..ef4e364d6bba89cfea33a6752982ae9d1cd2d1a6 --- /dev/null +++ b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/SchemaVersionMultistage.0.1/exempted_primary_heavyBus.VIF.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<VectoOutputMultistage xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1" xmlns:di="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xmlns:v2.1="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.1" xmlns:v2.3="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.3" xmlns:v2.6="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.6" xmlns:v2.8="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1 V:\VectoCore\VectoCore\Resources\XSD/VectoOutputMultistage.0.1.xsd"> + <PrimaryVehicle xmlns="urn:tugraz:ivt:VectoAPI:DeclarationOutput:VehicleInterimFile:v0.1"> + <Data id="VEH-4cb168560c0d4b3d886d" xsi:type="PrimaryVehicleDataType"> + <Vehicle xsi:type="VehicleExemptedPrimaryBusType"> + <ManufacturerPrimaryVehicle>Some Manufacturer</ManufacturerPrimaryVehicle> + <ManufacturerAddressPrimaryVehicle>Infinite Loop 1</ManufacturerAddressPrimaryVehicle> + <Model>Sample Bus Model</Model> + <VIN>VEH-1234567890</VIN> + <Date>2017-02-15T11:00:00Z</Date> + <LegislativeCategory>N2</LegislativeCategory> + <ChassisConfiguration>Bus</ChassisConfiguration> + <AxleConfiguration>6x2</AxleConfiguration> + <Articulated>false</Articulated> + <TechnicalPermissibleMaximumLadenMass unit="kg">15400.0</TechnicalPermissibleMaximumLadenMass> + <ZeroEmissionVehicle>true</ZeroEmissionVehicle> + <SumNetPower unit="W">350000</SumNetPower> + <Technology>Fuel cell vehicle</Technology> + </Vehicle> + <InputDataSignature> + <di:Reference URI="#VEH-1234567890"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>sYhNx2MDHaOAMTlPflP/qQbEkazmRDxY0Vw6yzwwcJc=</di:DigestValue> + </di:Reference> + </InputDataSignature> + <ManufacturerRecordSignature> + <di:Reference URI="#RESULT-4c4c52e522874a398b3a"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>guwkv90jOyWgDpgQwAEbLRkq7pWGeVaGA+dHizLYufQ=</di:DigestValue> + </di:Reference> + </ManufacturerRecordSignature> + <Results> + <Status>success</Status> + <ExemptedVehicle /> + </Results> + <ApplicationInformation> + <SimulationToolVersion>0.7.3.2247-DEV !!NOT FOR CERTIFICATION!!</SimulationToolVersion> + <Date>2021-06-15T16:00:43.6769906Z</Date> + </ApplicationInformation> + </Data> + <Signature> + <di:Reference URI="#VEH-4cb168560c0d4b3d886d"> + <di:Transforms> + <di:Transform Algorithm="urn:vecto:xml:2017:canonicalization" /> + <di:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </di:Transforms> + <di:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <di:DigestValue>KeeEnRNO5Gjm7XB+YYx542ujYbE0k7a9SkWe/BWo7bI=</di:DigestValue> + </di:Reference> + </Signature> + </PrimaryVehicle> +</VectoOutputMultistage> \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/vecto_vehicle-exempted_input_full-sample.xml b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/vecto_vehicle-exempted_input_full-sample.xml index 9e20d2cd2d4e3791611918ac7b389c79169f1984..57659cef43c4d0b34fa9e642d9fb832a5070197e 100644 --- a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/vecto_vehicle-exempted_input_full-sample.xml +++ b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/vecto_vehicle-exempted_input_full-sample.xml @@ -1 +1,25 @@ -<?xml version="1.0" encoding="UTF-8"?> <tns:VectoInputDeclaration schemaVersion="2.8" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob E:\VECTO_DEV\fk_vecto-dev\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> <v2.0:Vehicle id="VEH-1234567890" xsi:type="ExemptedInterimStageInputType"> <Manufacturer>Some Manufacturer</Manufacturer> <ManufacturerAddress>Infinite Loop</ManufacturerAddress> <VIN>VEH-1234567891</VIN> <Date>2021-01-09T11:00:00Z</Date> <Model>Sample Bus Model 2</Model> <LegislativeCategory>M3</LegislativeCategory> <CorrectedActualMass>7000</CorrectedActualMass> <TechnicalPermissibleMaximumLadenMass>10000</TechnicalPermissibleMaximumLadenMass> <ClassBus>A</ClassBus> <NumberPassengersLowerDeck>10</NumberPassengersLowerDeck> <NumberPassengersUpperDeck>20</NumberPassengersUpperDeck> <BodyworkCode>CC</BodyworkCode> <LowEntry>true</LowEntry> <HeightIntegratedBody>2500</HeightIntegratedBody> </v2.0:Vehicle> </tns:VectoInputDeclaration> \ No newline at end of file +<?xml version="1.0" encoding="UTF-8"?> +<tns:VectoInputDeclaration schemaVersion="2.8" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" +xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" +xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob E:\VECTO_DEV\fk_vecto-dev\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> + <v2.0:Vehicle id="VEH-1234567890" xsi:type="ExemptedInterimStageInputType"> + <Manufacturer>Some Manufacturer</Manufacturer> + <ManufacturerAddress>Infinite Loop</ManufacturerAddress> + <VIN>VEH-1234567891</VIN> + <Date>2021-01-09T11:00:00Z</Date> + <Model>Sample Bus Model 2</Model> + <LegislativeCategory>M3</LegislativeCategory> + <CorrectedActualMass>7000</CorrectedActualMass> + <TechnicalPermissibleMaximumLadenMass>10000</TechnicalPermissibleMaximumLadenMass> + <ClassBus>A</ClassBus> + <NumberPassengerSeatsLowerDeck>10</NumberPassengerSeatsLowerDeck> + <NumberPassengersStandingLowerDeck>42</NumberPassengersStandingLowerDeck> + <NumberPassengerSeatsUpperDeck>20</NumberPassengerSeatsUpperDeck> + <NumberPassengersStandingUpperDeck>13</NumberPassengersStandingUpperDeck> + <BodyworkCode>CC</BodyworkCode> + <LowEntry>true</LowEntry> + <HeightIntegratedBody>2500</HeightIntegratedBody> + </v2.0:Vehicle> +</tns:VectoInputDeclaration> \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/vecto_vehicle-exempted_input_only_certain_entries02-sample.xml b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/vecto_vehicle-exempted_input_only_certain_entries02-sample.xml index 6404f3d41e9b2c384697e1762cc46bf9a919d79a..9a6adaf176806f20f62ebdccdf56a5ee7ebbe527 100644 --- a/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/vecto_vehicle-exempted_input_only_certain_entries02-sample.xml +++ b/VectoCore/VectoCoreTest/TestData/XML/XMLReaderDeclaration/vecto_vehicle-exempted_input_only_certain_entries02-sample.xml @@ -1 +1,17 @@ -<?xml version="1.0" encoding="UTF-8"?> <tns:VectoInputDeclaration schemaVersion="2.8" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob E:\VECTO_DEV\fk_vecto-dev\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> <v2.0:Vehicle id="VEH-1234567890" xsi:type="ExemptedInterimStageInputType"> <Manufacturer>Some Manufacturer 2</Manufacturer> <ManufacturerAddress>Some Manufacturer Address 2</ManufacturerAddress> <VIN>VEH-1234567891</VIN> <Date>2021-01-09T11:00:00Z</Date> <NumberPassengersLowerDeck>10</NumberPassengersLowerDeck> <NumberPassengersUpperDeck>20</NumberPassengersUpperDeck> </v2.0:Vehicle> </tns:VectoInputDeclaration> \ No newline at end of file +<?xml version="1.0" encoding="UTF-8"?> +<tns:VectoInputDeclaration schemaVersion="2.8" xmlns="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:DEV:v2.8" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xmlns:tns="urn:tugraz:ivt:VectoAPI:DeclarationInput:v2.0" +xmlns:v2.0="urn:tugraz:ivt:VectoAPI:DeclarationDefinitions:v2.0" +xsi:schemaLocation="urn:tugraz:ivt:VectoAPI:DeclarationJob E:\VECTO_DEV\fk_vecto-dev\VectoCore\VectoCore\Resources\XSD/VectoDeclarationJob.xsd"> + <v2.0:Vehicle id="VEH-1234567890" xsi:type="ExemptedInterimStageInputType"> + <Manufacturer>Some Manufacturer 2</Manufacturer> + <ManufacturerAddress>Some Manufacturer Address 2</ManufacturerAddress> + <VIN>VEH-1234567891</VIN> + <Date>2021-01-09T11:00:00Z</Date> + <NumberPassengerSeatsLowerDeck>10</NumberPassengerSeatsLowerDeck> + <NumberPassengersStandingLowerDeck>42</NumberPassengersStandingLowerDeck> + <NumberPassengerSeatsUpperDeck>20</NumberPassengerSeatsUpperDeck> + <NumberPassengersStandingUpperDeck>13</NumberPassengersStandingUpperDeck> + </v2.0:Vehicle> +</tns:VectoInputDeclaration> \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/Utils/CompletedVIF.cs b/VectoCore/VectoCoreTest/Utils/CompletedVIF.cs index cfb858ef85dcabc4feebf1ec0620ba540a599ee5..422e16c9762caf89a0367b3ef515c38e776ade62 100644 --- a/VectoCore/VectoCoreTest/Utils/CompletedVIF.cs +++ b/VectoCore/VectoCoreTest/Utils/CompletedVIF.cs @@ -14,7 +14,8 @@ namespace TUGraz.VectoCore.Tests.Utils { public static class CompletedVIF { - public static XMLDeclarationVIFInputData CreateCompletedVif(JSONInputDataCompletedBusFactorMethodV7 completedJson, + public static string CreateCompletedVifXML( + JSONInputDataCompletedBusFactorMethodV7 completedJson, IXMLInputDataReader xmlInputReader) { var vifDataProvider = xmlInputReader.Create(completedJson.PrimaryInputDataFile); @@ -33,10 +34,17 @@ namespace TUGraz.VectoCore.Tests.Utils var completedVifXML = new XmlDocument(); completedVifXML.Load(writerAsm.XMLMultistageReportFileName); + var retVal = completedVifXML.OuterXml; + File.Delete(writerAsm.XMLMultistageReportFileName); + return retVal; + } + public static XMLDeclarationVIFInputData CreateCompletedVif(JSONInputDataCompletedBusFactorMethodV7 completedJson, + IXMLInputDataReader xmlInputReader) + { var completedVif = - xmlInputReader.CreateDeclaration(XmlReader.Create(new StringReader(completedVifXML.OuterXml))); - File.Delete(writerAsm.XMLMultistageReportFileName); + xmlInputReader.CreateDeclaration(XmlReader.Create(new StringReader(CreateCompletedVifXML(completedJson, xmlInputReader)))); + return new XMLDeclarationVIFInputData(completedVif as IMultistageBusInputDataProvider, null); } } diff --git a/VectoCore/VectoCoreTest/Utils/MockDeclarationVehicleInputData.cs b/VectoCore/VectoCoreTest/Utils/MockDeclarationVehicleInputData.cs index b83bde203d76065e11904f94aec270d5bcb1efb7..b491470cb4459565e2c68edf3daef6ed8429a61a 100644 --- a/VectoCore/VectoCoreTest/Utils/MockDeclarationVehicleInputData.cs +++ b/VectoCore/VectoCoreTest/Utils/MockDeclarationVehicleInputData.cs @@ -29,7 +29,6 @@ namespace TUGraz.VectoCore.Tests.Utils { public string Identifier { get; } public bool ExemptedVehicle { get; } public string VIN { get; } - public string LegislativeCategory { get; } public LegislativeClass? LegislativeClass { get; } public VehicleCategory VehicleCategory { get; } public AxleConfiguration AxleConfiguration { get; } @@ -48,6 +47,7 @@ namespace TUGraz.VectoCore.Tests.Utils { public bool DualFuelVehicle { get; } public Watt MaxNetPower1 { get; } public Watt MaxNetPower2 { get; } + public string ExemptedTechnology { get; } public RegistrationClass? RegisteredClass { get; set; } public int? NumberPassengerSeatsUpperDeck { get; set; } public int? NumberPassengerSeatsLowerDeck { get; set; } @@ -121,6 +121,7 @@ namespace TUGraz.VectoCore.Tests.Utils { public ConsumerTechnology? DoorDriveTechnology { get; } public VehicleDeclarationType VehicleDeclarationType { get; } public Watt MaxNetPower2 { get; } + public string ExemptedTechnology { get; } public RegistrationClass? RegisteredClass { get; set; } public int? NumberPassengerSeatsUpperDeck { get; set; } public int? NumberPassengerSeatsLowerDeck { get; set; } @@ -138,7 +139,6 @@ namespace TUGraz.VectoCore.Tests.Utils { public string Identifier { get; } public bool ExemptedVehicle { get; } public string VIN { get; } - public string LegislativeCategory { get; } public LegislativeClass? LegislativeClass { get; } public VehicleCategory VehicleCategory { get; } public AxleConfiguration AxleConfiguration { get; } diff --git a/VectoCore/VectoCoreTest/Utils/MockModalDataContainer.cs b/VectoCore/VectoCoreTest/Utils/MockModalDataContainer.cs index 0d67379cba3a0fa92df9843ce0e8bb05b9e07221..27edbefb67992127a800f007700abf75cb767af5 100644 --- a/VectoCore/VectoCoreTest/Utils/MockModalDataContainer.cs +++ b/VectoCore/VectoCoreTest/Utils/MockModalDataContainer.cs @@ -354,7 +354,7 @@ namespace TUGraz.VectoCore.Tests.Utils throw new NotImplementedException(); } - public double BatteryStartSoC() + public double REESSStartSoC() { throw new NotImplementedException(); } diff --git a/VectoCore/VectoCoreTest/Utils/ShiftPolygonDrawer.cs b/VectoCore/VectoCoreTest/Utils/ShiftPolygonDrawer.cs index f0a8b95586e6e36b8b42cdafe0a980db949b4b7c..c4895538f51c960d1550ea1f7d5d1e690a3f3b2e 100644 --- a/VectoCore/VectoCoreTest/Utils/ShiftPolygonDrawer.cs +++ b/VectoCore/VectoCoreTest/Utils/ShiftPolygonDrawer.cs @@ -202,14 +202,14 @@ namespace TUGraz.VectoCore.Tests.Utils PlotDragLoad(engineFld, chartArea, chart, name); - PlotEngineSpeedLine(engineFld, chartArea, chart, "nPref " + name, Color.DeepSkyBlue, - engineFld.PreferredSpeed.Value() / Constants.RPMToRad); + //PlotEngineSpeedLine(engineFld, chartArea, chart, "nPref " + name, Color.DeepSkyBlue, + // engineFld.PreferredSpeed.Value() / Constants.RPMToRad); - PlotEngineSpeedLine(engineFld, chartArea, chart, "n95h " + name, Color.Red, - engineFld.N95hSpeed.Value() / Constants.RPMToRad); + //PlotEngineSpeedLine(engineFld, chartArea, chart, "n95h " + name, Color.Red, + // engineFld.N95hSpeed.Value() / Constants.RPMToRad); - PlotEngineSpeedLine(engineFld, chartArea, chart, "n85kmh " + name, Color.LimeGreen, - speed85kmh.Value() / Constants.RPMToRad); + //PlotEngineSpeedLine(engineFld, chartArea, chart, "n85kmh " + name, Color.LimeGreen, + // speed85kmh.Value() / Constants.RPMToRad); PlotEngineSpeedLine(engineFld, chartArea, chart, "nPmax " + name, Color.Coral, engineFld.RatedSpeed.Value() / Constants.RPMToRad); diff --git a/VectoCore/VectoCoreTest/VectoCoreTest.csproj b/VectoCore/VectoCoreTest/VectoCoreTest.csproj index bfbdc378cb15b942bbff642cdec30255439eb36e..eadf0faaef7d60ca26ac98e81f5683892e8d31b1 100644 --- a/VectoCore/VectoCoreTest/VectoCoreTest.csproj +++ b/VectoCore/VectoCoreTest/VectoCoreTest.csproj @@ -154,6 +154,7 @@ <Compile Include="Models\SimulationComponent\EngineFanAuxTest.cs" /> <Compile Include="Models\SimulationComponent\GearboxShiftLossesTest.cs" /> <Compile Include="Models\SimulationComponent\SuperCapTest.cs" /> + <Compile Include="Reports\ModDataPostprocessingTest.cs" /> <Compile Include="Utils\CompletedVIF.cs" /> <Compile Include="Utils\MockElectricConsumer.cs" /> <Compile Include="Utils\MockHybridControl.cs" /> @@ -251,6 +252,9 @@ <SubType>Designer</SubType> </None> <None Include="default.runsettings" /> + <None Include="TestData\BatteryElectric\GenericVehicleB2\3speedEV.vgbx"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> <None Include="TestData\BatteryElectric\GenericVehicleB2\BatteryElectricVehicle.vveh"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> @@ -260,6 +264,9 @@ <None Include="TestData\BatteryElectric\GenericVehicleB2\BEV_ENG.vecto"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> + <None Include="TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_3speed.vecto"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> <None Include="TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_Cont30kW.vecto"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> @@ -5961,6 +5968,9 @@ <Content Include="TestData\XML\XMLReaderDeclaration\SchemaVersion2.3\vehicle_sampleDualModeDualFuel.xml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> + <Content Include="TestData\XML\XMLReaderDeclaration\SchemaVersion2.6_Buses\exempted_primary_heavyBus.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> <Content Include="TestData\XML\XMLReaderDeclaration\SchemaVersion2.6_Buses\PIF-heavyBus-sample.xml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> @@ -6021,6 +6031,9 @@ <Content Include="TestData\XML\XMLReaderDeclaration\SchemaVersion2.8\vecto_vehicle-stage_vif_input.xml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> + <Content Include="TestData\XML\XMLReaderDeclaration\SchemaVersionMultistage.0.1\exempted_primary_heavyBus.VIF.xml"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> <Content Include="TestData\XML\XMLReaderDeclaration\SchemaVersionMultistage.0.1\vecto_multistage_consolidated_multiple_stages.xml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> diff --git a/VectoCore/VectoCoreTest/XML/XMLCompleteBusReaderTest.cs b/VectoCore/VectoCoreTest/XML/XMLCompleteBusReaderTest.cs index 444bb17a9bd769843018af9518bb7eb097ac8b04..4bceadbd97b62b68f2db214d2ee3608095fe5f06 100644 --- a/VectoCore/VectoCoreTest/XML/XMLCompleteBusReaderTest.cs +++ b/VectoCore/VectoCoreTest/XML/XMLCompleteBusReaderTest.cs @@ -36,7 +36,8 @@ namespace TUGraz.VectoCore.Tests.XML } - [TestCase] + [TestCase, + Ignore("CompleteBus no longer used - new multistep approach")] public void TestCompleteBusVehicleData() { var reader = XmlReader.Create(CompleteBusExample); diff --git a/VectoCore/VectoCoreTest/XML/XMLMultistageBusDataTest.cs b/VectoCore/VectoCoreTest/XML/XMLMultistageBusDataTest.cs index 6a337e3dace079efaf26bb6f597f22ec8429f4db..3f32009dea4d138c7d586b2e699900819b738c70 100644 --- a/VectoCore/VectoCoreTest/XML/XMLMultistageBusDataTest.cs +++ b/VectoCore/VectoCoreTest/XML/XMLMultistageBusDataTest.cs @@ -71,7 +71,7 @@ namespace TUGraz.VectoCore.Tests.XML Assert.AreEqual("Generic Model", vehicleData.Model); Assert.AreEqual("VEH-1234567890_nonSmart-ESS", vehicleData.VIN); Assert.AreEqual(DateTime.Parse("2017-02-15T11:00:00Z").ToUniversalTime(), vehicleData.Date); - Assert.AreEqual("M3", vehicleData.LegislativeCategory); + Assert.AreEqual(LegislativeClass.M3, vehicleData.LegislativeClass); Assert.AreEqual("Bus", vehicleData.VehicleCategory.ToXMLFormat()); Assert.AreEqual(AxleConfiguration.AxleConfig_8x2, vehicleData.AxleConfiguration); Assert.AreEqual(true, vehicleData.Articulated); diff --git a/VectoCore/VectoCoreTest/XML/XMLMultistageBusInputDataTest.cs b/VectoCore/VectoCoreTest/XML/XMLMultistageBusInputDataTest.cs index c3be89ee5b145013a5f6503292e93dbe380e104a..04127d5f4f065075535a015d32563b68c11ae934 100644 --- a/VectoCore/VectoCoreTest/XML/XMLMultistageBusInputDataTest.cs +++ b/VectoCore/VectoCoreTest/XML/XMLMultistageBusInputDataTest.cs @@ -54,12 +54,12 @@ namespace TUGraz.VectoCore.Tests.XML Assert.AreEqual("Some Manufacturer", vehicle.Manufacturer); Assert.AreEqual("Some Manufacturer Address", vehicle.ManufacturerAddress); Assert.AreEqual("VEH-1234567890", vehicle.VIN); - Assert.AreEqual(DateTime.Parse("2020-01-09T11:00:00Z").ToUniversalTime(), vehicle.Date); + Assert.AreEqual(DateTime.Parse("2021-06-30T22:00:00Z").ToUniversalTime(), vehicle.Date); Assert.AreEqual("Sample Bus Model", vehicle.Model); Assert.AreEqual(LegislativeClass.M3, vehicle.LegislativeClass); Assert.AreEqual(500, vehicle.CurbMassChassis.Value());//CorrectedActualMass Assert.AreEqual(3500, vehicle.GrossVehicleMassRating.Value());//TechnicalPermissibleMaximumLadenMass - Assert.AreEqual(null, vehicle.AirdragModifiedMultistage); + Assert.AreEqual(true, vehicle.AirdragModifiedMultistage); Assert.AreEqual(TankSystem.Compressed, vehicle.TankSystem);//NgTankSystem Assert.AreEqual(RegistrationClass.II_III, vehicle.RegisteredClass);//ClassBus Assert.AreEqual(1, vehicle.NumberPassengerSeatsLowerDeck); @@ -158,8 +158,10 @@ namespace TUGraz.VectoCore.Tests.XML Assert.AreEqual(10000, vehicle.GrossVehicleMassRating.Value());//TechnicalPermissibleMaximumLadenMass Assert.AreEqual(RegistrationClass.A, vehicle.RegisteredClass);//ClassBus Assert.AreEqual(10, vehicle.NumberPassengerSeatsLowerDeck); + Assert.AreEqual(42, vehicle.NumberPassengersStandingLowerDeck); Assert.AreEqual(20, vehicle.NumberPassengerSeatsUpperDeck); - Assert.AreEqual(VehicleCode.CC, vehicle.VehicleCode); + Assert.AreEqual(13, vehicle.NumberPassengersStandingUpperDeck); + Assert.AreEqual(VehicleCode.CE, vehicle.VehicleCode); Assert.AreEqual(true, vehicle.LowEntry); Assert.AreEqual(2.5, vehicle.Height.Value()); } diff --git a/VectoCore/VectoXML.spp b/VectoCore/VectoXML.spp index a18bdad0c3e962a29e4afe556f0a5240f7d01bf0..e776a5e7ab55e1e9b4a2c74f6e95757891ce3e4d 100644 --- a/VectoCore/VectoXML.spp +++ b/VectoCore/VectoXML.spp @@ -15,6 +15,7 @@ <File FilePath="VectoCoreTest\TestData\XML\XMLReaderDeclaration\SchemaVersion2.3\vehicle_sampleDualModeDualFuel.xml" HomeFolder="Yes"/> </Folder> <Folder FolderName="Schema 2.6DEV Buses ML"> + <File FilePath="E:\QUAM\Workspace\VECTO_DEV_Buses\VectoCore\VectoCoreTest\bin\Debug\TestData\XML\XMLReaderDeclaration\SchemaVersion2.6_Buses\exempted_primary_heavyBus.xml" HomeFolder="Yes"/> <File FilePath="VectoCoreTest\TestData\XML\XMLReaderDeclaration\SchemaVersion2.6_Buses\PIF-heavyBus-sample.xml" HomeFolder="Yes"/> <File FilePath="VectoCoreTest\TestData\XML\XMLReaderDeclaration\SchemaVersion2.6_Buses\vecto_vehicle-completed_heavyBus-sample.xml" HomeFolder="Yes"/> <File FilePath="VectoCoreTest\TestData\XML\XMLReaderDeclaration\SchemaVersion2.6_Buses\vecto_vehicle-medium_lorryFWD-sample.xml" HomeFolder="Yes"/>