#include "simulation/big/normaldrivestate.h"
#include "simulation/big/drivetrain.h"
#include "MotorCluster/TellTalesModel.h"
using namespace MotorCluster;
namespace {
const uint8_t StateUpdatePeriod = 100 ;
const uint16_t ExtraTimeToFinishState = 1000 ;
const uint16_t LongExtraTimeToFinishState = 3000 ;
MainModel & mainModel = MainModel:: instance();
TellTalesModel & tellTalesModel = TellTalesModel:: instance();
static Simulation:: Drivetrain:: Config drivetrainConfig = {17000 ,
0 ,
14000 ,
5500 ,
207.3f ,
12.f ,
7 ,
{10000.f , 2.97f , 2.07f , 1.43f , 1.00f , 0.84f , 0.56f }};
Simulation:: Drivetrain drivetrain(drivetrainConfig);
}
namespace Simulation {
NormalDriveState:: NormalDriveState(StateId nextState)
: _step(Step_Start)
, _timeToFinishStepWhenTargetSpeedWasMet(0 )
, _wasSpeedToFinishStepMet(true )
, _nextState(nextState)
{}
void NormalDriveState:: onEnter(const StateId & , const Layer & layer, Machine & sm)
{
_step = Step_Start;
drivetrain. reset();
updateModel();
mainModel. rpmAnimationTime. setValue(500 );
sm. requestUpdate(StateUpdatePeriod, true , layer);
}
void NormalDriveState:: onLeave(const StateId & , const Layer & layer, Machine & sm)
{
sm. dismissUpdate(layer);
tellTalesModel. engineFailure. setValue(false );
tellTalesModel. engineOil. setValue(false );
tellTalesModel. highBeamsActive. setValue(false );
}
void NormalDriveState:: onUpdate(const uint32_t tick, const Layer & layer, Machine & sm)
{
if (_timeToFinishStepWhenTargetSpeedWasMet < = 0 & & _wasSpeedToFinishStepMet) {
moveToNextStep(layer, sm);
} else if (_wasSpeedToFinishStepMet) {
_timeToFinishStepWhenTargetSpeedWasMet - = tick;
} else if (drivetrain. isTargetSpeedReached()) {
_wasSpeedToFinishStepMet = true ;
}
calculateDriveData(tick);
updateModel();
}
void NormalDriveState:: moveToNextStep(const Layer & layer, Machine & sm)
{
_step = static_cast < Step> (_step + 1 );
_wasSpeedToFinishStepMet = false ;
_timeToFinishStepWhenTargetSpeedWasMet = ExtraTimeToFinishState;
switch (_step) {
case Step_GoingOut:
setSpeedTarget(60.f );
setFuelTarget(27.f , 0.02f );
break ;
case Step_FirstCorner:
setSpeedTarget(30.f );
break ;
case Step_FirstStright:
setSpeedTarget(70.f );
break ;
case Step_SecondCorner:
setSpeedTarget(40.f );
_timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState;
mainModel. leftTurnSignal. setValue(true );
break ;
case Step_BeginnigOfLongStright:
setSpeedTarget(200.f );
setFuelTarget(25.f , 0.3f );
mainModel. leftTurnSignal. setValue(false );
break ;
case Step_ElectricalProblems:
setSpeedTarget(210.f );
_timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState;
tellTalesModel. battery. setValue(true );
break ;
case Step_SlowingDownToPetrolStation:
setSpeedTarget(110.f );
setFuelTarget(2.f , 0.3f );
break ;
case Step_TurningToPetrolStation:
setSpeedTarget(20.f );
_timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState;
mainModel. rightTurnSignal. setValue(true );
break ;
case Step_PetrolStation:
setSpeedTarget(0.f , false );
mainModel. rightTurnSignal. setValue(false );
break ;
case Step_FillingTheTank:
drivetrain. forceNeutraulGear(true );
setFuelTarget(80.f , 5.f );
_timeToFinishStepWhenTargetSpeedWasMet = LongExtraTimeToFinishState;
mainModel. rightTurnSignal. setValue(false );
tellTalesModel. battery. setValue(false );
break ;
case Step_LeavingPetrolStation:
drivetrain. forceNeutraulGear(false );
setSpeedTarget(110.f );
setFuelTarget(80.f , . 0f );
tellTalesModel. battery. setValue(false );
tellTalesModel. highBeamsActive. setValue(true );
break ;
case Step_SecondStright:
setSpeedTarget(280.f );
break ;
case Step_OilProblems:
tellTalesModel. engineOil. setValue(true );
break ;
case Step_EngineProblems:
tellTalesModel. engineFailure. setValue(true );
break ;
case Step_EndOfSecondStright:
mainModel. rightTurnSignal. setValue(true );
mainModel. leftTurnSignal. setValue(true );
setSpeedTarget(200.f );
setFuelTarget(20.f , . 15f );
break ;
case Step_MoveToNextState:
mainModel. rightTurnSignal. setValue(false );
mainModel. leftTurnSignal. setValue(false );
sm. changeState(_nextState, layer, 10 );
break ;
default :
break ;
}
}
template < class T, class U>
void updateIfChanged(T & modelElement, U newValue)
{
if (modelElement. value() ! = newValue) {
modelElement. setValue(newValue);
}
}
void NormalDriveState:: updateModel()
{
const Drivetrain:: DriveData & data = drivetrain. getDriveData();
updateIfChanged(mainModel. rpm, std:: max(data. rpm - data. rpm % 1000 , 1000 ));
updateIfChanged(mainModel. isOver13kRpm, data. rpm > 13000 );
updateIfChanged(mainModel. speedValue, data. speed);
updateIfChanged(mainModel. gear, data. gear);
updateIfChanged(mainModel. fuelLevel, data. fuelLevel);
updateIfChanged(mainModel. odoValue, data. odometer);
updateIfChanged(mainModel. tripValue, data. tripDistance);
}
void NormalDriveState:: calculateDriveData(const uint32_t tick)
{
drivetrain. update(tick);
}
void NormalDriveState:: setSpeedTarget(const int targetSpeed, const bool withRandomAccChanges)
{
drivetrain. setSpeedTarget(targetSpeed, withRandomAccChanges);
}
void NormalDriveState:: setFuelTarget(const float fuelTarget, const float fuelSpeed)
{
drivetrain. setFuelTarget(fuelTarget, fuelSpeed);
}
}