public override float?GetStateFraction()
        {
            if (EmergencyBrakingPushButton() || TCSEmergencyBraking() || TCSFullServiceBraking() || QuickReleaseButtonPressed() || OverchargeButtonPressed())
            {
                return(null);
            }
            else if (NotchController != null)
            {
                if (NotchController.NotchCount() == 0)
                {
                    return(NotchController.CurrentValue);
                }
                else
                {
                    INotchController notch = NotchController.GetCurrentNotch();

                    if (!notch.Smooth)
                    {
                        if (notch.NotchStateType == ControllerState.Dummy)
                        {
                            return(NotchController.CurrentValue);
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        return(NotchController.GetNotchFraction());
                    }
                }
            }
            else
            {
                return(null);
            }
        }
        // Train Brake Controllers
        public override Tuple <double, double> UpdatePressure(double pressureBar, double epPressureBar, double elapsedClockSeconds)
        {
            double epState = -1.0;

            if (EmergencyBrakingPushButton() || TCSEmergencyBraking())
            {
                pressureBar -= EmergencyRateBarpS() * elapsedClockSeconds;
            }
            else if (TCSFullServiceBraking())
            {
                if (pressureBar > MaxPressureBar() - FullServReductionBar())
                {
                    pressureBar -= ApplyRateBarpS() * elapsedClockSeconds;
                }
                else if (pressureBar < MaxPressureBar() - FullServReductionBar())
                {
                    pressureBar = MaxPressureBar() - FullServReductionBar();
                }
            }
            else
            {
                INotchController notch = NotchController.GetCurrentNotch();

                if (!brakeControllerInitialised) // The first time around loop, PreviousNotchPosition will be set up front with current value, this will stop crashes due to vsalue not being initialised.
                {
                    previousNotchPosition      = NotchController.GetCurrentNotch();
                    brakeControllerInitialised = true;
                }
                if (notch == null)
                {
                    pressureBar = MaxPressureBar() - FullServReductionBar() * CurrentValue();
                }
                else
                {
                    epState = 0;
                    double          x         = NotchController.GetNotchFraction();
                    ControllerState notchType = notch.NotchStateType;
                    if (OverchargeButtonPressed())
                    {
                        notchType = ControllerState.Overcharge;
                    }
                    else if (QuickReleaseButtonPressed())
                    {
                        switch (notchType)
                        {
                        case ControllerState.Hold:
                        case ControllerState.Lap:
                        case ControllerState.MinimalReduction:
                            if (EnforceMinimalReduction)
                            {
                                pressureBar = DecreasePressure(pressureBar, MaxPressureBar() - MinReductionBar(), ApplyRateBarpS(), elapsedClockSeconds);
                            }
                            break;

                        default:
                            EnforceMinimalReduction = false;
                            break;
                        }
                    }
                    switch (notchType)
                    {
                    case ControllerState.Release:
                        pressureBar = IncreasePressure(pressureBar, MaxPressureBar(), ReleaseRateBarpS(), elapsedClockSeconds);
                        pressureBar = DecreasePressure(pressureBar, MaxPressureBar(), OverchargeEliminationRateBarpS(), elapsedClockSeconds);
                        epState     = -1;
                        break;

                    case ControllerState.FullQuickRelease:
                    case ControllerState.SMEReleaseStart:
                        pressureBar = IncreasePressure(pressureBar, MaxPressureBar(), QuickReleaseRateBarpS(), elapsedClockSeconds);
                        pressureBar = DecreasePressure(pressureBar, MaxPressureBar(), OverchargeEliminationRateBarpS(), elapsedClockSeconds);
                        epState     = -1;
                        break;

                    case ControllerState.Overcharge:
                        pressureBar = IncreasePressure(pressureBar, Math.Min(MaxOverchargePressureBar(), MainReservoirPressureBar()), QuickReleaseRateBarpS(), elapsedClockSeconds);
                        epState     = -1;
                        break;

                    case ControllerState.SlowService:
                        if (pressureBar > MaxPressureBar() - MinReductionBar())
                        {
                            pressureBar = MaxPressureBar() - MinReductionBar();
                        }
                        pressureBar = DecreasePressure(pressureBar, MaxPressureBar() - FullServReductionBar(), SlowApplicationRateBarpS(), elapsedClockSeconds);
                        break;

                    case ControllerState.StraightLap:
                    case ControllerState.StraightApply:
                    case ControllerState.StraightApplyAll:
                    case ControllerState.StraightEmergency:
                        // Nothing is done in these positions, instead they are controlled by the steam ejector in straight brake module
                        break;

                    case ControllerState.StraightRelease:
                    case ControllerState.StraightReleaseOn:
                        // This position is an on position so pressure will be zero (reversed due to vacuum brake operation)
                        pressureBar = 0;
                        break;

                    case ControllerState.StraightReleaseOff:     //(reversed due to vacuum brake operation)
                    case ControllerState.Apply:
                        pressureBar -= x * ApplyRateBarpS() * elapsedClockSeconds;
                        break;

                    case ControllerState.FullServ:
                        epState = x;
                        EnforceMinimalReduction = true;
                        if (pressureBar > MaxPressureBar() - MinReductionBar())
                        {
                            pressureBar = MaxPressureBar() - MinReductionBar();
                        }
                        pressureBar = DecreasePressure(pressureBar, MaxPressureBar() - FullServReductionBar(), ApplyRateBarpS(), elapsedClockSeconds);
                        break;

                    case ControllerState.Lap:
                        // Lap position applies min service reduction when first selected, and previous contoller position was Running, then no change in pressure occurs
                        if (previousNotchPosition.NotchStateType == ControllerState.Running)
                        {
                            EnforceMinimalReduction = true;
                            epState = -1;
                        }
                        break;

                    case ControllerState.MinimalReduction:
                        // Lap position applies min service reduction when first selected, and previous contoller position was Running or Release, then no change in pressure occurs
                        if (previousNotchPosition.NotchStateType == ControllerState.Running || previousNotchPosition.NotchStateType == ControllerState.Release || previousNotchPosition.NotchStateType == ControllerState.FullQuickRelease)
                        {
                            EnforceMinimalReduction = true;
                            epState = -1;
                        }
                        break;

                    case ControllerState.ManualBraking:
                    case ControllerState.VacContServ:
                        // Continuous service positions for vacuum brakes - allows brake to be adjusted up and down continuously between the ON and OFF position
                        pressureBar = (1 - x) * MaxPressureBar();
                        epState     = -1;
                        break;

                    case ControllerState.EPApply:
                    case ControllerState.EPOnly:
                    case ControllerState.SMEOnly:
                    case ControllerState.ContServ:
                    case ControllerState.EPFullServ:
                    case ControllerState.SMEFullServ:
                        epState = x;
                        if (notch.NotchStateType == ControllerState.EPApply || notch.NotchStateType == ControllerState.ContServ)
                        {
                            EnforceMinimalReduction = true;
                            x = MaxPressureBar() - MinReductionBar() * (1 - x) - FullServReductionBar() * x;
                            if (pressureBar > MaxPressureBar() - MinReductionBar())
                            {
                                pressureBar = MaxPressureBar() - MinReductionBar();
                            }
                            pressureBar = DecreasePressure(pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                            if (ForceControllerReleaseGraduated || notch.NotchStateType == ControllerState.EPApply)
                            {
                                pressureBar = IncreasePressure(pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                            }
                        }
                        break;

                    case ControllerState.GSelfLapH:
                    case ControllerState.Suppression:
                    case ControllerState.GSelfLap:
                        EnforceMinimalReduction = true;
                        x           = MaxPressureBar() - MinReductionBar() * (1 - x) - FullServReductionBar() * x;
                        pressureBar = DecreasePressure(pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                        if (ForceControllerReleaseGraduated || notch.NotchStateType == ControllerState.GSelfLap)
                        {
                            pressureBar = IncreasePressure(pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                        }
                        break;

                    case ControllerState.Emergency:
                        pressureBar -= EmergencyRateBarpS() * elapsedClockSeconds;
                        epState      = 1;
                        break;

                    case ControllerState.Dummy:
                        x           = MaxPressureBar() - FullServReductionBar() * (notch.Smooth ? x : CurrentValue());
                        pressureBar = IncreasePressure(pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                        pressureBar = DecreasePressure(pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                        epState     = -1;
                        break;
                    }

                    previousNotchPosition = NotchController.GetCurrentNotch();
                }
            }

            if (pressureBar < 0)
            {
                pressureBar = 0;
            }
            return(new Tuple <double, double>(pressureBar, epState));
        }
        // Engine Brake Controllers
        public override double UpdateEngineBrakePressure(double pressureBar, double elapsedClockSeconds)
        {
            INotchController notch = NotchController.GetCurrentNotch();

            if (notch == null)
            {
                pressureBar = (MaxPressureBar() - FullServReductionBar()) * CurrentValue();
            }
            else
            {
                double x = NotchController.GetNotchFraction();
                switch (notch.NotchStateType)
                {
                case ControllerState.Neutral:
                case ControllerState.Running:
                case ControllerState.Lap:
                    break;

                case ControllerState.FullQuickRelease:
                    pressureBar -= x * QuickReleaseRateBarpS() * elapsedClockSeconds;
                    break;

                case ControllerState.Release:
                    pressureBar -= x * ReleaseRateBarpS() * elapsedClockSeconds;
                    break;

                case ControllerState.Apply:
                case ControllerState.FullServ:
                    pressureBar = IncreasePressure(pressureBar, x * (MaxPressureBar() - FullServReductionBar()), ApplyRateBarpS(), elapsedClockSeconds);
                    break;

                case ControllerState.ManualBraking:
                case ControllerState.VacContServ:
                    // Continuous service positions for vacuum brakes - allows brake to be adjusted up and down continuously between the ON and OFF position
                    pressureBar = (1 - x) * MaxPressureBar();
                    break;

                case ControllerState.BrakeNotch:
                    // Notch position for brakes - allows brake to be adjusted up and down continuously between specified notches
                    pressureBar = (1 - x) * MaxPressureBar();
                    break;

                case ControllerState.Emergency:
                    pressureBar += EmergencyRateBarpS() * elapsedClockSeconds;
                    break;

                case ControllerState.Dummy:
                    pressureBar = (MaxPressureBar() - FullServReductionBar()) * CurrentValue();
                    break;

                default:
                    x          *= MaxPressureBar() - FullServReductionBar();
                    pressureBar = IncreasePressure(pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                    pressureBar = DecreasePressure(pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                    break;
                }
                if (pressureBar > MaxPressureBar())
                {
                    pressureBar = MaxPressureBar();
                }
                if (pressureBar < 0)
                {
                    pressureBar = 0;
                }
            }
            return(pressureBar);
        }