<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CrewChiefV2.Data;

namespace CrewChiefV2.Events
{
    class TyreMonitor : AbstractEvent
    {
        private String folderHotLeftFront = "tyre_monitor/hot_left_front";
        private String folderHotLeftRear = "tyre_monitor/hot_left_rear";
        private String folderHotRightFront = "tyre_monitor/hot_right_front";
        private String folderHotRightRear = "tyre_monitor/hot_right_rear";
        private String folderHotFronts = "tyre_monitor/hot_fronts";
        private String folderHotRears = "tyre_monitor/hot_rears";
        private String folderHotLefts = "tyre_monitor/hot_lefts";
        private String folderHotRights = "tyre_monitor/hot_rights";
        private String folderHotAllRound = "tyre_monitor/hot_all_round";
        private String folderGoodTemps = "tyre_monitor/good_temps";

        private String folderKnackeredLeftFront = "tyre_monitor/knackered_left_front";
        private String folderKnackeredLeftRear = "tyre_monitor/knackered_left_rear";
        private String folderKnackeredRightFront = "tyre_monitor/knackered_right_front";
        private String folderKnackeredRightRear = "tyre_monitor/knackered_right_rear";
        private String folderKnackeredFronts = "tyre_monitor/knackered_fronts";
        private String folderKnackeredRears = "tyre_monitor/knackered_rears";
        private String folderKnackeredLefts = "tyre_monitor/knackered_lefts";
        private String folderKnackeredRights = "tyre_monitor/knackered_rights";
        private String folderKnackeredAllRound = "tyre_monitor/knackered_all_round";
        private String folderGoodWear = "tyre_monitor/good_wear";

        private String folderWornLeftFront = "tyre_monitor/worn_left_front";
        private String folderWornLeftRear = "tyre_monitor/worn_left_rear";
        private String folderWornRightFront = "tyre_monitor/worn_right_front";
        private String folderWornRightRear = "tyre_monitor/worn_right_rear";
        private String folderWornFronts = "tyre_monitor/worn_fronts";
        private String folderWornRears = "tyre_monitor/worn_rears";
        private String folderWornLefts = "tyre_monitor/worn_lefts";
        private String folderWornRights = "tyre_monitor/worn_rights";
        private String folderWornAllRound = "tyre_monitor/worn_all_round";

        private String folderLapsOnCurrentTyresIntro = "tyre_monitor/laps_on_current_tyres_intro";
        private String folderLapsOnCurrentTyresOutro = "tyre_monitor/laps_on_current_tyres_outro";
        private String folderMinutesOnCurrentTyresIntro = "tyre_monitor/minutes_on_current_tyres_intro";
        private String folderMinutesOnCurrentTyresOutro = "tyre_monitor/minutes_on_current_tyres_outro";

        private static float maxColdTemp = UserSettings.GetUserSettings().getFloat("max_cold_tyre_temp");
        private static float maxGoodTemp = UserSettings.GetUserSettings().getFloat("max_good_tyre_temp");
        private static Boolean enableTyreTempWarnings = UserSettings.GetUserSettings().getBoolean("enable_tyre_temp_warnings");
        private static Boolean enableTyreWearWarnings = UserSettings.GetUserSettings().getBoolean("enable_tyre_wear_warnings");

        private int tyreTempMessageDelay = 0;

        private int lapsIntoSessionBeforeTempMessage = 2;

        private TyreTemps lastLapTyreTemps;
        private TyreTemps thisLapTyreTemps;

        private TyreTempStatus lastReportedStatus;

        private Boolean checkedTempsAtSector3;

        // -1 means we only check at the end of the lap
        private int checkAtSector = -1;

        // tyre wear - 0 is new, 1 or more is knackered
        public float leftFrontWear;
        public float rightFrontWear;
        public float leftRearWear;
        public float rightRearWear;
        private float newTyreWearValue = 1f;

        // This will change when S3 sort out tyre wear...
        // this is the % damage the tyre can have before it's knackered - in the 
        // current game, damage level <90% means the tyre is effectly dead
        private float maxTyreWearBeforeKnackered = 0.1f;

        private float knackeredTyreThreshold = 1f;
        private float warningTyreThreshold = 0.5f;

        private TyreWearStatus lastReportedKnackeredTyreStatus;
        private TyreWearStatus lastReportedWornTyreStatus;

        private Boolean reportedTyreWearForCurrentPitEntry;

        private Boolean reportedEstimatedTimeLeft;

        public TyreMonitor(AudioPlayer audioPlayer)
        {
            this.audioPlayer = audioPlayer;
        }

        public override void clearState()
        {
            lastLapTyreTemps = null;
            thisLapTyreTemps = null;
            lastReportedStatus = TyreTempStatus.NO_DATA;
            lastReportedKnackeredTyreStatus = TyreWearStatus.NOT_TRIGGERED;
            lastReportedWornTyreStatus = TyreWearStatus.NOT_TRIGGERED;
            checkedTempsAtSector3 = false;
            leftFrontWear = 0;
            rightFrontWear = 0;
            leftRearWear = 0;
            rightRearWear = 0;
            reportedTyreWearForCurrentPitEntry = false;
            reportedEstimatedTimeLeft = false;
        }

        public override bool isClipStillValid(string eventSubType)
        {
            return CommonData.isSessionRunning;
        }

        private void checkTemps(TyreTemps tyreTempsToCheck)
        {
            // only give a message if we've completed more than the minimum laps here
            if (tyreTempsToCheck != null)
            {
                tyreTempsToCheck.displayAverages();
                TyreTempStatus tempsStatus = tyreTempsToCheck.getAverageTempStatus();
                if (tempsStatus != lastReportedStatus)
                {
                    String messageFolder = getMessage(tempsStatus);
                    if (messageFolder != null)
                    {
                        Console.WriteLine("Reporting tyre temp status: " + tempsStatus);
                        audioPlayer.queueClip(messageFolder, tyreTempMessageDelay, this);
                    }
                    lastReportedStatus = tempsStatus;
                }
                else
                {
                    Console.WriteLine("No tyre temp status change: " + tempsStatus);
                }
            }
        }

        override protected void triggerInternal(Shared lastState, Shared currentState)
        {
            if (CommonData.isSessionRunning)
            {
                if (currentState.TireWearActive == 1)
                {
                    leftFrontWear = (newTyreWearValue - currentState.CarDamage.TireFrontLeft) / maxTyreWearBeforeKnackered;
                    rightFrontWear = (newTyreWearValue - currentState.CarDamage.TireFrontRight) / maxTyreWearBeforeKnackered;
                    leftRearWear = (newTyreWearValue - currentState.CarDamage.TireRearLeft) / maxTyreWearBeforeKnackered;
                    rightRearWear = (newTyreWearValue - currentState.CarDamage.TireRearRight) / maxTyreWearBeforeKnackered;
                    
                    if (CommonData.isPittingInRace)
                    {
                        if (enableTyreWearWarnings && !reportedTyreWearForCurrentPitEntry)
                        {
                            playTyreWearMessages(true, true);
                            reportedTyreWearForCurrentPitEntry = true;
                        }
                    }
                    else
                    {
                        reportedTyreWearForCurrentPitEntry = false;
                    }
                    if (CommonData.isNewLap && !CommonData.isPittingInRace && enableTyreWearWarnings)
                    {
                        playTyreWearMessages(true, false);
                    }
                    if (!CommonData.isPittingInRace && !reportedEstimatedTimeLeft && enableTyreWearWarnings)
                    {
                        float maxWear = Math.Max(leftFrontWear, Math.Max(rightFrontWear, Math.Max(rightRearWear, leftRearWear)));
                        if (maxWear >= knackeredTyreThreshold / 3)
                        {
                            // 1/3 through the tyre's life
                            reportedEstimatedTimeLeft = true;
                            if (currentState.NumberOfLaps > 0)
                            {
                                int lapsRemainingOnTheseTyres = (currentState.CompletedLaps * 3) - 1;
                                if (lapsRemainingOnTheseTyres < 59 && lapsRemainingOnTheseTyres > 1 && 
                                    lapsRemainingOnTheseTyres <= currentState.NumberOfLaps - currentState.CompletedLaps)
                                {
                                    List<String> messages = new List<String>();
                                    messages.Add(folderLapsOnCurrentTyresIntro);
                                    messages.Add(QueuedMessage.folderNameNumbersStub + lapsRemainingOnTheseTyres);
                                    messages.Add(folderLapsOnCurrentTyresOutro);
                                    audioPlayer.queueClip(QueuedMessage.compoundMessageIdentifier + "laps_on_current_tyres",
                                        new QueuedMessage(messages, 0, this));
                                }
                            }
                            else
                            {
                                int minutesRemainingOnTheseTyres = ((int) Math.Round((currentState.Player.GameSimulationTime / 60d) * 3d)) - 1;
                                if (minutesRemainingOnTheseTyres < 59 && minutesRemainingOnTheseTyres > 1 && 
                                    minutesRemainingOnTheseTyres <= currentState.SessionTimeRemaining / 60)
                                {
                                    List<String> messages = new List<String>();
                                    messages.Add(folderMinutesOnCurrentTyresIntro);
                                    messages.Add(QueuedMessage.folderNameNumbersStub + minutesRemainingOnTheseTyres);
                                    messages.Add(folderMinutesOnCurrentTyresOutro);
                                    audioPlayer.queueClip(QueuedMessage.compoundMessageIdentifier + "minutes_on_current_tyres",
                                        new QueuedMessage(messages, 0, this));
                                }
                            }
                        }
                    }                     
                }
                if (CommonData.isNewLap)
                {
                    lastLapTyreTemps = thisLapTyreTemps;    // this might still be null
                    thisLapTyreTemps = new TyreTemps();
                    updateTyreTemps(currentState, thisLapTyreTemps);
                    if (!CommonData.isPittingInRace && enableTyreTempWarnings && !checkedTempsAtSector3 && currentState.CompletedLaps >= lapsIntoSessionBeforeTempMessage)
                    {
                        checkTemps(lastLapTyreTemps);
                    }
                    checkedTempsAtSector3 = false;                                                       
                }
                else
                {
                    if (thisLapTyreTemps == null)
                    {
                        thisLapTyreTemps = new TyreTemps();
                    }
                    updateTyreTemps(currentState, thisLapTyreTemps);
                    if (enableTyreTempWarnings && checkAtSector > 0 && CommonData.isNewSector && CommonData.currentLapSector == checkAtSector)
                    {
                        checkedTempsAtSector3 = true;
                        if (!CommonData.isPittingInRace && currentState.CompletedLaps >= lapsIntoSessionBeforeTempMessage)
                        {
                            checkTemps(thisLapTyreTemps);
                        }
                    }
                }
            }
        }
<commit_msg>more tyre wear fixes<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CrewChiefV2.Data;

namespace CrewChiefV2.Events
{
    class TyreMonitor : AbstractEvent
    {
        private String folderHotLeftFront = "tyre_monitor/hot_left_front";
        private String folderHotLeftRear = "tyre_monitor/hot_left_rear";
        private String folderHotRightFront = "tyre_monitor/hot_right_front";
        private String folderHotRightRear = "tyre_monitor/hot_right_rear";
        private String folderHotFronts = "tyre_monitor/hot_fronts";
        private String folderHotRears = "tyre_monitor/hot_rears";
        private String folderHotLefts = "tyre_monitor/hot_lefts";
        private String folderHotRights = "tyre_monitor/hot_rights";
        private String folderHotAllRound = "tyre_monitor/hot_all_round";
        private String folderGoodTemps = "tyre_monitor/good_temps";

        private String folderKnackeredLeftFront = "tyre_monitor/knackered_left_front";
        private String folderKnackeredLeftRear = "tyre_monitor/knackered_left_rear";
        private String folderKnackeredRightFront = "tyre_monitor/knackered_right_front";
        private String folderKnackeredRightRear = "tyre_monitor/knackered_right_rear";
        private String folderKnackeredFronts = "tyre_monitor/knackered_fronts";
        private String folderKnackeredRears = "tyre_monitor/knackered_rears";
        private String folderKnackeredLefts = "tyre_monitor/knackered_lefts";
        private String folderKnackeredRights = "tyre_monitor/knackered_rights";
        private String folderKnackeredAllRound = "tyre_monitor/knackered_all_round";
        private String folderGoodWear = "tyre_monitor/good_wear";

        private String folderWornLeftFront = "tyre_monitor/worn_left_front";
        private String folderWornLeftRear = "tyre_monitor/worn_left_rear";
        private String folderWornRightFront = "tyre_monitor/worn_right_front";
        private String folderWornRightRear = "tyre_monitor/worn_right_rear";
        private String folderWornFronts = "tyre_monitor/worn_fronts";
        private String folderWornRears = "tyre_monitor/worn_rears";
        private String folderWornLefts = "tyre_monitor/worn_lefts";
        private String folderWornRights = "tyre_monitor/worn_rights";
        private String folderWornAllRound = "tyre_monitor/worn_all_round";

        private String folderLapsOnCurrentTyresIntro = "tyre_monitor/laps_on_current_tyres_intro";
        private String folderLapsOnCurrentTyresOutro = "tyre_monitor/laps_on_current_tyres_outro";
        private String folderMinutesOnCurrentTyresIntro = "tyre_monitor/minutes_on_current_tyres_intro";
        private String folderMinutesOnCurrentTyresOutro = "tyre_monitor/minutes_on_current_tyres_outro";

        private static float maxColdTemp = UserSettings.GetUserSettings().getFloat("max_cold_tyre_temp");
        private static float maxGoodTemp = UserSettings.GetUserSettings().getFloat("max_good_tyre_temp");
        private static Boolean enableTyreTempWarnings = UserSettings.GetUserSettings().getBoolean("enable_tyre_temp_warnings");
        private static Boolean enableTyreWearWarnings = UserSettings.GetUserSettings().getBoolean("enable_tyre_wear_warnings");

        private int tyreTempMessageDelay = 0;

        private int lapsIntoSessionBeforeTempMessage = 2;

        private TyreTemps lastLapTyreTemps;
        private TyreTemps thisLapTyreTemps;

        private TyreTempStatus lastReportedStatus;

        private Boolean checkedTempsAtSector3;

        // -1 means we only check at the end of the lap
        private int checkAtSector = -1;

        // tyre wear - 0 is new, 1 or more is knackered
        public float leftFrontWear;
        public float rightFrontWear;
        public float leftRearWear;
        public float rightRearWear;
        private float newTyreWearValue = 1f;

        // This will change when S3 sort out tyre wear...
        // this is the % damage the tyre can have before it's knackered - in the 
        // current game, damage level <90% means the tyre is effectly dead
        private float maxTyreWearBeforeKnackered = 0.1f;

        private float knackeredTyreThreshold = 1f;
        private float warningTyreThreshold = 0.5f;

        private TyreWearStatus lastReportedKnackeredTyreStatus;
        private TyreWearStatus lastReportedWornTyreStatus;

        private Boolean reportedTyreWearForCurrentPitEntry;

        private Boolean reportedEstimatedTimeLeft;

        public TyreMonitor(AudioPlayer audioPlayer)
        {
            this.audioPlayer = audioPlayer;
        }

        public override void clearState()
        {
            lastLapTyreTemps = null;
            thisLapTyreTemps = null;
            lastReportedStatus = TyreTempStatus.NO_DATA;
            lastReportedKnackeredTyreStatus = TyreWearStatus.NOT_TRIGGERED;
            lastReportedWornTyreStatus = TyreWearStatus.NOT_TRIGGERED;
            checkedTempsAtSector3 = false;
            leftFrontWear = 0;
            rightFrontWear = 0;
            leftRearWear = 0;
            rightRearWear = 0;
            reportedTyreWearForCurrentPitEntry = false;
            reportedEstimatedTimeLeft = false;
        }

        public override bool isClipStillValid(string eventSubType)
        {
            return CommonData.isSessionRunning;
        }

        private void checkTemps(TyreTemps tyreTempsToCheck)
        {
            // only give a message if we've completed more than the minimum laps here
            if (tyreTempsToCheck != null)
            {
                tyreTempsToCheck.displayAverages();
                TyreTempStatus tempsStatus = tyreTempsToCheck.getAverageTempStatus();
                if (tempsStatus != lastReportedStatus)
                {
                    String messageFolder = getMessage(tempsStatus);
                    if (messageFolder != null)
                    {
                        Console.WriteLine("Reporting tyre temp status: " + tempsStatus);
                        audioPlayer.queueClip(messageFolder, tyreTempMessageDelay, this);
                    }
                    lastReportedStatus = tempsStatus;
                }
                else
                {
                    Console.WriteLine("No tyre temp status change: " + tempsStatus);
                }
            }
        }

        override protected void triggerInternal(Shared lastState, Shared currentState)
        {
            if (CommonData.isSessionRunning)
            {
                if (currentState.TireWearActive == 1)
                {
                    leftFrontWear = (newTyreWearValue - currentState.CarDamage.TireFrontLeft) / maxTyreWearBeforeKnackered;
                    rightFrontWear = (newTyreWearValue - currentState.CarDamage.TireFrontRight) / maxTyreWearBeforeKnackered;
                    leftRearWear = (newTyreWearValue - currentState.CarDamage.TireRearLeft) / maxTyreWearBeforeKnackered;
                    rightRearWear = (newTyreWearValue - currentState.CarDamage.TireRearRight) / maxTyreWearBeforeKnackered;
                    
                    if (CommonData.isPittingInRace)
                    {
                        if (enableTyreWearWarnings && !reportedTyreWearForCurrentPitEntry)
                        {
                            playTyreWearMessages(true, true);
                            reportedTyreWearForCurrentPitEntry = true;
                        }
                    }
                    else
                    {
                        reportedTyreWearForCurrentPitEntry = false;
                    }
                    if (CommonData.isNewLap && !CommonData.isPittingInRace && enableTyreWearWarnings)
                    {
                        playTyreWearMessages(true, false);
                    }
                    if (!CommonData.isPittingInRace && !reportedEstimatedTimeLeft && enableTyreWearWarnings)
                    {
                        reportEstimatedTyreLife(currentState);
                    }
                    // if the tyre wear has actually decreased, reset the 'reportdEstimatedTyreWear flag
                    if (currentState.CarDamage.TireFrontLeft < lastState.CarDamage.TireFrontLeft ||
                        currentState.CarDamage.TireFrontRight < lastState.CarDamage.TireFrontRight ||
                        currentState.CarDamage.TireRearLeft < lastState.CarDamage.TireRearLeft ||
                        currentState.CarDamage.TireRearRight < lastState.CarDamage.TireRearRight)
                    {
                        Console.WriteLine("The tyres have been changed");
                        reportedEstimatedTimeLeft = true;
                    }
                }
                if (CommonData.isNewLap)
                {
                    lastLapTyreTemps = thisLapTyreTemps;    // this might still be null
                    thisLapTyreTemps = new TyreTemps();
                    updateTyreTemps(currentState, thisLapTyreTemps);
                    if (!CommonData.isPittingInRace && enableTyreTempWarnings && !checkedTempsAtSector3 && currentState.CompletedLaps >= lapsIntoSessionBeforeTempMessage)
                    {
                        checkTemps(lastLapTyreTemps);
                    }
                    checkedTempsAtSector3 = false;                                                       
                }
                else
                {
                    if (thisLapTyreTemps == null)
                    {
                        thisLapTyreTemps = new TyreTemps();
                    }
                    updateTyreTemps(currentState, thisLapTyreTemps);
                    if (enableTyreTempWarnings && checkAtSector > 0 && CommonData.isNewSector && CommonData.currentLapSector == checkAtSector)
                    {
                        checkedTempsAtSector3 = true;
                        if (!CommonData.isPittingInRace && currentState.CompletedLaps >= lapsIntoSessionBeforeTempMessage)
                        {
                            checkTemps(thisLapTyreTemps);
                        }
                    }
                }
            }
        }

        private void reportEstimatedTyreLife(Data.Shared currentState)
        {
            float maxWear = Math.Max(leftFrontWear, Math.Max(rightFrontWear, Math.Max(rightRearWear, leftRearWear)));
            if (maxWear >= knackeredTyreThreshold / 3)
            {
                // 1/3 through the tyre's life
                reportedEstimatedTimeLeft = true;
                if (currentState.NumberOfLaps > 0)
                {
                    int lapsRemainingOnTheseTyres = (currentState.CompletedLaps * 3) - 1;
                    if (lapsRemainingOnTheseTyres < 59 && lapsRemainingOnTheseTyres > 1 &&
                        lapsRemainingOnTheseTyres <= currentState.NumberOfLaps - currentState.CompletedLaps)
                    {
                        List<String> messages = new List<String>();
                        messages.Add(folderLapsOnCurrentTyresIntro);
                        messages.Add(QueuedMessage.folderNameNumbersStub + lapsRemainingOnTheseTyres);
                        messages.Add(folderLapsOnCurrentTyresOutro);
                        audioPlayer.queueClip(QueuedMessage.compoundMessageIdentifier + "laps_on_current_tyres",
                            new QueuedMessage(messages, 0, this));
                    }
                }
                else
                {
                    int minutesRemainingOnTheseTyres = ((int)Math.Round((currentState.Player.GameSimulationTime / 60d) * 3d)) - 1;
                    if (minutesRemainingOnTheseTyres < 59 && minutesRemainingOnTheseTyres > 1 &&
                        minutesRemainingOnTheseTyres <= currentState.SessionTimeRemaining / 60)
                    {
                        List<String> messages = new List<String>();
                        messages.Add(folderMinutesOnCurrentTyresIntro);
                        messages.Add(QueuedMessage.folderNameNumbersStub + minutesRemainingOnTheseTyres);
                        messages.Add(folderMinutesOnCurrentTyresOutro);
                        audioPlayer.queueClip(QueuedMessage.compoundMessageIdentifier + "minutes_on_current_tyres",
                            new QueuedMessage(messages, 0, this));
                    }
                }
            }
        }

{'fraction_non_alphanumeric': 0.06096514526212561, 'fraction_numerical': 0.003922690311772157, 'mean_word_length': 1.8438298861259586, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3595146', 'n_tokens_mistral': 6690, 'n_tokens_neox': 6193, 'n_words': 1130}