public override void clearState() { gapsInFront = new List<float>(); gapsBehind = new List<float>(); lastGapBehindReport = GapStatus.NONE; lastGapInFrontReport = GapStatus.NONE; gapBehindAtLastReport = -1; gapInFrontAtLastReport = -1; sectorsSinceLastReport = 0; sectorsUntilNextReport = 0; drsRange = 2; // TODO: get the DRS range from somewhere hasDRS = false; }
public void SetStatus(GapStatus status, Context context) { Status = status; ((FragmentActivity)context).RunOnUiThread(() => { switch (status) { case GapStatus.EMPTY: case GapStatus.PENDING: Visual.SetBackgroundColor(Color.White); Visual.SetTextColor(Color.Black); Visual.Text = "-"; break; case GapStatus.FILLING: Visual.SetBackgroundColor(Color.LightGreen); Visual.SetTextColor(Color.Black); break; case GapStatus.FILLED: Visual.SetBackgroundColor(Color.LightBlue); Visual.SetTextColor(Color.Black); break; case GapStatus.ERASED: Visual.SetBackgroundColor(Color.White); Visual.SetTextColor(Color.Black); Visual.Text = "-"; break; case GapStatus.ERROR: Visual.SetBackgroundColor(Color.Red); Visual.SetTextColor(Color.White); break; } }); }
//max number of lines present in the xml is 12 public void SetStatus(string location, GapStatus status) { Activity.RunOnUiThread(() => { switch (status) { case GapStatus.EMPTY: trolleyArray[location].SetBackgroundColor(Color.White); break; case GapStatus.FILLING: trolleyArray[location].SetBackgroundColor(Color.Green); break; case GapStatus.FILLED: trolleyArray[location].SetBackgroundColor(Color.Blue); break; case GapStatus.ERROR: trolleyArray[location].SetBackgroundColor(Color.Red); break; } }); }
protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { isLeading = currentGameState.SessionData.Position == 1; isLast = currentGameState.isLast(); isRace = currentGameState.SessionData.SessionType == SessionType.Race; currentGapInFront = currentGameState.SessionData.TimeDeltaFront; currentGapBehind = currentGameState.SessionData.TimeDeltaBehind; if (currentGameState.SessionData.IsNewLap) { playedGapBehindForThisLap = false; } if (gapsInFront == null || gapsBehind == null) { clearState(); } if (!currentGameState.SessionData.IsRacingSameCarInFront) { gapsInFront.Clear(); gapInFrontAtLastReport = -1; } if (!currentGameState.SessionData.IsRacingSameCarBehind) { gapsBehind.Clear(); gapBehindAtLastReport = -1; } if (previousGameState != null && previousGameState.SessionData.CompletedLaps <= currentGameState.FlagData.lapCountWhenLastWentGreen) { return; } if (!currentGameState.PitData.InPitlane && enableGapMessages) { if (isRace && !CrewChief.readOpponentDeltasForEveryLap && IsNewSectorOrGapPoint(previousGameState, currentGameState)) { sectorsSinceLastGapAheadReport++; sectorsSinceLastGapBehindReport++; sectorsSinceLastCloseCarAheadReport++; sectorsSinceLastCloseCarBehindReport++; GapStatus gapInFrontStatus = GapStatus.NONE; GapStatus gapBehindStatus = GapStatus.NONE; if (currentGameState.SessionData.Position != 1) { // AMS / RF1 hack - sometimes the gap data is stale, so don't put the exact same gap in the list if (gapsInFront.Count == 0 || gapsInFront[0] != currentGameState.SessionData.TimeDeltaFront) { gapsInFront.Insert(0, currentGameState.SessionData.TimeDeltaFront); gapInFrontStatus = getGapStatus(gapsInFront, gapInFrontAtLastReport); } } if (!isLast) { // AMS / RF1 hack - sometimes the gap data is stale, so don't put the exact same gap in the list if (gapsBehind.Count == 0 || gapsBehind[0] != currentGameState.SessionData.TimeDeltaBehind) { gapsBehind.Insert(0, currentGameState.SessionData.TimeDeltaBehind); gapBehindStatus = getGapStatus(gapsBehind, gapBehindAtLastReport); } } // Play which ever is the smaller gap, but we're not interested if the gap is < 0.5 or > 20 seconds or hasn't changed: Boolean playGapInFront = gapInFrontStatus != GapStatus.NONE && (gapBehindStatus == GapStatus.NONE || (gapsInFront.Count() > 0 && gapsBehind.Count() > 0 && gapsInFront[0] < gapsBehind[0])); Boolean playGapBehind = !playGapInFront && gapBehindStatus != GapStatus.NONE; if (playGapInFront) { if (gapInFrontStatus == GapStatus.CLOSE) { if (sectorsSinceLastCloseCarAheadReport >= sectorsUntilNextCloseCarAheadReport) { sectorsSinceLastCloseCarAheadReport = 0; // only prefer mid-lap gap reports if we're on a track with no ad-hoc gapPoints if (currentGameState.SessionData.TrackDefinition.gapPoints.Count() > 0) { sectorsUntilNextCloseCarAheadReport = rand.Next(closeAheadMinSectorWait, closeAheadMaxSectorWait); } else { sectorsUntilNextCloseCarAheadReport = adjustForMidLapPreference(currentGameState.SessionData.SectorNumber, rand.Next(closeAheadMinSectorWait, closeAheadMaxSectorWait)); } audioPlayer.playMessage(new QueuedMessage(folderBeingHeldUp, 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); OpponentData opponent = currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position - 1, false); if (!trackLandmarkAttackDriverNamesUsed.ContainsKey(opponent.DriverRawName) || trackLandmarkAttackDriverNamesUsed[opponent.DriverRawName] + minTimeBetweenAttackOrDefendByDriver < currentGameState.Now) { CrewChiefV4.GameState.TrackLandmarksTiming.LandmarkAndDeltaType landmarkAndDeltaType = currentGameState.SessionData.trackLandmarksTiming.getLandmarkWhereIAmFaster(opponent.trackLandmarksTiming, true); if (landmarkAndDeltaType.landmarkName != null) { // either we're faster on entry or faster through String attackFolder = landmarkAndDeltaType.deltaType == TrackLandmarksTiming.DeltaType.Time ? folderHeIsSlowerThroughCorner : folderHeIsSlowerEnteringCorner; audioPlayer.playMessage(new QueuedMessage("Timings/corner_to_attack_in", MessageContents(Pause(200), attackFolder, "corners/" + landmarkAndDeltaType.landmarkName), 0, this)); trackLandmarkAttackDriverNamesUsed[opponent.DriverRawName] = currentGameState.Now; } } gapInFrontAtLastReport = gapsInFront[0]; } } else if (gapInFrontStatus != GapStatus.NONE && sectorsSinceLastGapAheadReport >= sectorsUntilNextGapAheadReport) { sectorsSinceLastGapAheadReport = 0; // only prefer mid-lap gap reports if we're on a track with no ad-hoc gapPoints if (currentGameState.SessionData.TrackDefinition.gapPoints.Count() > 0) { sectorsUntilNextGapAheadReport = rand.Next(gapAheadMinSectorWait, gapAheadMaxSectorWait); } else { sectorsUntilNextGapAheadReport = adjustForMidLapPreference(currentGameState.SessionData.SectorNumber, rand.Next(gapAheadMinSectorWait, gapAheadMaxSectorWait)); } TimeSpan gapInFront = TimeSpan.FromMilliseconds(gapsInFront[0] * 1000); Boolean readGap = gapInFront.Seconds > 0 || gapInFront.Milliseconds > 50; if (readGap) { if (gapInFrontStatus == GapStatus.INCREASING) { audioPlayer.playMessage(new QueuedMessage("Timings/gap_in_front", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position - 1, false), folderAheadIsIncreasing, gapInFront), MessageContents(folderGapInFrontIncreasing, gapInFront), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); } else if (gapInFrontStatus == GapStatus.DECREASING) { OpponentData opponent = currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position - 1, false); audioPlayer.playMessage(new QueuedMessage("Timings/gap_in_front", MessageContents(folderYoureReeling, opponent, folderInTheGapIsNow, gapInFront), MessageContents(folderGapInFrontDecreasing, gapInFront), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); if (!trackLandmarkAttackDriverNamesUsed.ContainsKey(opponent.DriverRawName) || trackLandmarkAttackDriverNamesUsed[opponent.DriverRawName] + minTimeBetweenAttackOrDefendByDriver < currentGameState.Now) { CrewChiefV4.GameState.TrackLandmarksTiming.LandmarkAndDeltaType landmarkAndDeltaType = currentGameState.SessionData.trackLandmarksTiming.getLandmarkWhereIAmFaster(opponent.trackLandmarksTiming, true); if (landmarkAndDeltaType.landmarkName != null) { // either we're faster on entry or faster through String attackFolder = landmarkAndDeltaType.deltaType == TrackLandmarksTiming.DeltaType.Time ? folderHeIsSlowerThroughCorner : folderHeIsSlowerEnteringCorner; audioPlayer.playMessage(new QueuedMessage("Timings/corner_to_attack_in", MessageContents(Pause(200), attackFolder, "corners/" + landmarkAndDeltaType.landmarkName), 0, this)); trackLandmarkAttackDriverNamesUsed[opponent.DriverRawName] = currentGameState.Now; } } } else if (gapInFrontStatus == GapStatus.OTHER) { audioPlayer.playMessage(new QueuedMessage("Timings/gap_in_front", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position - 1, false), folderAheadIsNow, gapInFront), MessageContents(folderGapInFrontIsNow, gapInFront), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); } } gapInFrontAtLastReport = gapsInFront[0]; } } else if (playGapBehind) { if (gapBehindStatus == GapStatus.CLOSE) { if (sectorsSinceLastCloseCarBehindReport >= sectorsUntilNextCloseCarBehindReport) { sectorsSinceLastCloseCarBehindReport = 0; // only prefer mid-lap gap reports if we're on a track with no ad-hoc gapPoints if (currentGameState.SessionData.TrackDefinition.gapPoints.Count() > 0) { sectorsUntilNextCloseCarBehindReport = rand.Next(closeBehindMinSectorWait, closeBehindMaxSectorWait); } else { sectorsUntilNextCloseCarBehindReport = adjustForMidLapPreference(currentGameState.SessionData.SectorNumber, rand.Next(closeBehindMinSectorWait, closeBehindMaxSectorWait)); } audioPlayer.playMessage(new QueuedMessage(folderBeingPressured, 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); OpponentData opponent = currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position + 1, false); if (!trackLandmarkDefendDriverNamesUsed.ContainsKey(opponent.DriverRawName) || trackLandmarkDefendDriverNamesUsed[opponent.DriverRawName] + minTimeBetweenAttackOrDefendByDriver < currentGameState.Now) { CrewChiefV4.GameState.TrackLandmarksTiming.LandmarkAndDeltaType landmarkAndDeltaType = currentGameState.SessionData.trackLandmarksTiming.getLandmarkWhereIAmSlower(opponent.trackLandmarksTiming, true); if (landmarkAndDeltaType.landmarkName != null) { // either we're slower on entry or slower through String defendFolder = landmarkAndDeltaType.deltaType == TrackLandmarksTiming.DeltaType.Time ? folderHeIsFasterThroughCorner : folderHeIsFasterEnteringCorner; audioPlayer.playMessage(new QueuedMessage("Timings/corner_to_defend_in", MessageContents(Pause(200), defendFolder, "corners/" + landmarkAndDeltaType.landmarkName), 0, this)); trackLandmarkDefendDriverNamesUsed[opponent.DriverRawName] = currentGameState.Now; } } gapBehindAtLastReport = gapsBehind[0]; } } else if (gapBehindStatus != GapStatus.NONE && sectorsSinceLastGapBehindReport >= sectorsUntilNextGapBehindReport) { sectorsSinceLastGapBehindReport = 0; // only prefer mid-lap gap reports if we're on a track with no ad-hoc gapPoints if (currentGameState.SessionData.TrackDefinition.gapPoints.Count() > 0) { sectorsUntilNextGapBehindReport = rand.Next(gapBehindMinSectorWait, gapBehindMaxSectorWait); } else { sectorsUntilNextGapBehindReport = adjustForMidLapPreference(currentGameState.SessionData.SectorNumber, rand.Next(gapBehindMinSectorWait, gapBehindMaxSectorWait)); } TimeSpan gapBehind = TimeSpan.FromMilliseconds(gapsBehind[0] * 1000); Boolean readGap = gapBehind.Seconds > 0 || gapBehind.Milliseconds > 50; if (readGap) { if (gapBehindStatus == GapStatus.INCREASING) { audioPlayer.playMessage(new QueuedMessage("Timings/gap_behind", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position + 1, false), folderBehindIsIncreasing, gapBehind), MessageContents(folderGapBehindIncreasing, gapBehind), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); } else if (gapBehindStatus == GapStatus.DECREASING) { OpponentData opponent = currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position + 1, false); audioPlayer.playMessage(new QueuedMessage("Timings/gap_behind", MessageContents(opponent, folderIsReelingYouIn, gapBehind), MessageContents(folderGapBehindDecreasing, gapBehind), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); if (!trackLandmarkDefendDriverNamesUsed.ContainsKey(opponent.DriverRawName) || trackLandmarkDefendDriverNamesUsed[opponent.DriverRawName] + minTimeBetweenAttackOrDefendByDriver < currentGameState.Now) { CrewChiefV4.GameState.TrackLandmarksTiming.LandmarkAndDeltaType landmarkAndDeltaType = currentGameState.SessionData.trackLandmarksTiming.getLandmarkWhereIAmSlower(opponent.trackLandmarksTiming, true); if (landmarkAndDeltaType.landmarkName != null) { // either we're slower on entry or slower through String defendFolder = landmarkAndDeltaType.deltaType == TrackLandmarksTiming.DeltaType.Time ? folderHeIsFasterThroughCorner : folderHeIsFasterEnteringCorner; audioPlayer.playMessage(new QueuedMessage("Timings/corner_to_defend_in", MessageContents(Pause(200), defendFolder, "corners/" + landmarkAndDeltaType.landmarkName), 0, this)); trackLandmarkDefendDriverNamesUsed[opponent.DriverRawName] = currentGameState.Now; } } } else if (gapBehindStatus == GapStatus.OTHER) { audioPlayer.playMessage(new QueuedMessage("Timings/gap_behind", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position + 1, false), folderBehindIsNow, gapBehind), MessageContents(folderGapBehindIsNow, gapBehind), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); } } gapBehindAtLastReport = gapsBehind[0]; } } } if (isRace && CrewChief.readOpponentDeltasForEveryLap && currentGameState.SessionData.CompletedLaps > 0) { if (currentGameState.SessionData.Position > 1 && currentGameState.SessionData.IsNewLap) { if (currentGapInFront > 0.05) { TimeSpan gap = TimeSpan.FromSeconds(currentGapInFront); QueuedMessage message = new QueuedMessage("Timings/gap_ahead", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position - 1, false), folderAheadIsNow, gap), MessageContents(folderGapInFrontIsNow, gap), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } }); message.playEvenWhenSilenced = true; audioPlayer.playMessage(message); } } if (!currentGameState.isLast()) { if (!playedGapBehindForThisLap && currentGapBehind > 0.05 && currentGameState.SessionData.LapTimeCurrent > 0 && currentGameState.SessionData.LapTimeCurrent >= currentGapBehind && currentGameState.SessionData.LapTimeCurrent <= currentGapBehind + CrewChief._timeInterval.TotalSeconds) { playedGapBehindForThisLap = true; TimeSpan gap = TimeSpan.FromSeconds(currentGapBehind); QueuedMessage message = new QueuedMessage("Timings/gap_behind", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position + 1, false), folderBehindIsNow, gap), MessageContents(folderGapBehindIsNow, gap), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } }); message.playEvenWhenSilenced = true; audioPlayer.playMessage(message); } } } } }
protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { isLeading = currentGameState.SessionData.Position == 1; isLast = currentGameState.isLast(); isRace = currentGameState.SessionData.SessionType == SessionType.Race; currentGapInFront = currentGameState.SessionData.TimeDeltaFront; currentGapBehind = currentGameState.SessionData.TimeDeltaBehind; if (currentGameState.SessionData.IsNewLap) { playedGapBehindForThisLap = false; } if (gapsInFront == null || gapsBehind == null) { clearState(); } if (!currentGameState.SessionData.IsRacingSameCarInFront) { gapsInFront.Clear(); } if (!currentGameState.SessionData.IsRacingSameCarBehind) { gapsBehind.Clear(); } if (!currentGameState.PitData.InPitlane && enableGapMessages) { if (isRace && !CrewChief.readOpponentDeltasForEveryLap && IsNewSectorOrGapPoint(previousGameState, currentGameState)) { sectorsSinceLastGapAheadReport++; sectorsSinceLastGapBehindReport++; sectorsSinceLastCloseCarAheadReport++; sectorsSinceLastCloseCarBehindReport++; GapStatus gapInFrontStatus = GapStatus.NONE; GapStatus gapBehindStatus = GapStatus.NONE; if (currentGameState.SessionData.Position != 1) { gapsInFront.Insert(0, currentGameState.SessionData.TimeDeltaFront); gapInFrontStatus = getGapStatus(gapsInFront, gapInFrontAtLastReport); } if (!isLast) { gapsBehind.Insert(0, currentGameState.SessionData.TimeDeltaBehind); gapBehindStatus = getGapStatus(gapsBehind, gapBehindAtLastReport); } // Play which ever is the smaller gap, but we're not interested if the gap is < 0.5 or > 20 seconds or hasn't changed: Boolean playGapInFront = gapInFrontStatus != GapStatus.NONE && (gapBehindStatus == GapStatus.NONE || (gapsInFront.Count() > 0 && gapsBehind.Count() > 0 && gapsInFront[0] < gapsBehind[0])); Boolean playGapBehind = !playGapInFront && gapBehindStatus != GapStatus.NONE; if (playGapInFront) { if (gapInFrontStatus == GapStatus.CLOSE) { if (sectorsSinceLastCloseCarAheadReport >= sectorsUntilNextCloseCarAheadReport) { sectorsSinceLastCloseCarAheadReport = 0; // only prefer mid-lap gap reports if we're on a track with no ad-hoc gapPoints if (currentGameState.SessionData.TrackDefinition.gapPoints.Count() > 0) { sectorsUntilNextCloseCarAheadReport = rand.Next(closeAheadMinSectorWait, closeAheadMaxSectorWait); } else { sectorsUntilNextCloseCarAheadReport = adjustForMidLapPreference(currentGameState.SessionData.SectorNumber, rand.Next(closeAheadMinSectorWait, closeAheadMaxSectorWait)); } audioPlayer.playMessage(new QueuedMessage(folderBeingHeldUp, 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); gapInFrontAtLastReport = gapsInFront[0]; } } else if (gapInFrontStatus != GapStatus.NONE && sectorsSinceLastGapAheadReport >= sectorsUntilNextGapAheadReport) { sectorsSinceLastGapAheadReport = 0; // only prefer mid-lap gap reports if we're on a track with no ad-hoc gapPoints if (currentGameState.SessionData.TrackDefinition.gapPoints.Count() > 0) { sectorsUntilNextGapAheadReport = rand.Next(gapAheadMinSectorWait, gapAheadMaxSectorWait); } else { sectorsUntilNextGapAheadReport = adjustForMidLapPreference(currentGameState.SessionData.SectorNumber, rand.Next(gapAheadMinSectorWait, gapAheadMaxSectorWait)); } TimeSpan gapInFront = TimeSpan.FromMilliseconds(gapsInFront[0] * 1000); Boolean readGap = gapInFront.Seconds > 0 || gapInFront.Milliseconds > 50; if (readGap) { if (gapInFrontStatus == GapStatus.INCREASING) { audioPlayer.playMessage(new QueuedMessage("Timings/gap_in_front", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position - 1, false), folderAheadIsIncreasing, gapInFront), MessageContents(folderGapInFrontIncreasing, gapInFront), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); } else if (gapInFrontStatus == GapStatus.DECREASING) { audioPlayer.playMessage(new QueuedMessage("Timings/gap_in_front", MessageContents(folderYoureReeling, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position - 1, false), folderInTheGapIsNow, gapInFront), MessageContents(folderGapInFrontDecreasing, gapInFront), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); } else if (gapInFrontStatus == GapStatus.OTHER) { audioPlayer.playMessage(new QueuedMessage("Timings/gap_in_front", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position - 1, false), folderAheadIsNow, gapInFront), MessageContents(folderGapInFrontIsNow, gapInFront), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); } } gapInFrontAtLastReport = gapsInFront[0]; } } else if (playGapBehind) { if (gapBehindStatus == GapStatus.CLOSE) { if (sectorsSinceLastCloseCarBehindReport >= sectorsUntilNextCloseCarBehindReport) { sectorsSinceLastCloseCarBehindReport = 0; // only prefer mid-lap gap reports if we're on a track with no ad-hoc gapPoints if (currentGameState.SessionData.TrackDefinition.gapPoints.Count() > 0) { sectorsUntilNextCloseCarBehindReport = rand.Next(closeBehindMinSectorWait, closeBehindMaxSectorWait); } else { sectorsUntilNextCloseCarBehindReport = adjustForMidLapPreference(currentGameState.SessionData.SectorNumber, rand.Next(closeBehindMinSectorWait, closeBehindMaxSectorWait)); } audioPlayer.playMessage(new QueuedMessage(folderBeingPressured, 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); gapBehindAtLastReport = gapsBehind[0]; } } else if (gapBehindStatus != GapStatus.NONE && sectorsSinceLastGapBehindReport >= sectorsUntilNextGapBehindReport) { sectorsSinceLastGapBehindReport = 0; // only prefer mid-lap gap reports if we're on a track with no ad-hoc gapPoints if (currentGameState.SessionData.TrackDefinition.gapPoints.Count() > 0) { sectorsUntilNextGapBehindReport = rand.Next(gapBehindMinSectorWait, gapBehindMaxSectorWait); } else { sectorsUntilNextGapBehindReport = adjustForMidLapPreference(currentGameState.SessionData.SectorNumber, rand.Next(gapBehindMinSectorWait, gapBehindMaxSectorWait)); } TimeSpan gapBehind = TimeSpan.FromMilliseconds(gapsBehind[0] * 1000); Boolean readGap = gapBehind.Seconds > 0 || gapBehind.Milliseconds > 50; if (readGap) { if (gapBehindStatus == GapStatus.INCREASING) { audioPlayer.playMessage(new QueuedMessage("Timings/gap_behind", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position + 1, false), folderBehindIsIncreasing, gapBehind), MessageContents(folderGapBehindIncreasing, gapBehind), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); } else if (gapBehindStatus == GapStatus.DECREASING) { audioPlayer.playMessage(new QueuedMessage("Timings/gap_behind", MessageContents(currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position + 1, false), folderIsReelingYouIn, gapBehind), MessageContents(folderGapBehindDecreasing, gapBehind), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); } else if (gapBehindStatus == GapStatus.OTHER) { audioPlayer.playMessage(new QueuedMessage("Timings/gap_behind", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position + 1, false), folderBehindIsNow, gapBehind), MessageContents(folderGapBehindIsNow, gapBehind), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } })); } } gapBehindAtLastReport = gapsBehind[0]; } } } if (isRace && CrewChief.readOpponentDeltasForEveryLap && currentGameState.SessionData.CompletedLaps > 0) { if (currentGameState.SessionData.Position > 1 && currentGameState.SessionData.IsNewLap) { if (currentGapInFront > 0.05) { TimeSpan gap = TimeSpan.FromSeconds(currentGapInFront); QueuedMessage message = new QueuedMessage("Timings/gap_ahead", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position - 1, false), folderAheadIsNow, gap), MessageContents(folderGapInFrontIsNow, gap), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } }); message.playEvenWhenSilenced = true; audioPlayer.playMessage(message); } } if (!currentGameState.isLast()) { if (!playedGapBehindForThisLap && currentGapBehind > 0.05 && currentGameState.SessionData.LapTimeCurrent > 0 && currentGameState.SessionData.LapTimeCurrent >= currentGapBehind && currentGameState.SessionData.LapTimeCurrent <= currentGapBehind + CrewChief._timeInterval.TotalSeconds) { playedGapBehindForThisLap = true; TimeSpan gap = TimeSpan.FromSeconds(currentGapBehind); QueuedMessage message = new QueuedMessage("Timings/gap_behind", MessageContents(folderTheGapTo, currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position + 1, false), folderBehindIsNow, gap), MessageContents(folderGapBehindIsNow, gap), 0, this, new Dictionary <string, object> { { "position", currentGameState.SessionData.Position } }); message.playEvenWhenSilenced = true; audioPlayer.playMessage(message); } } } } }
protected override void triggerInternal(Data.Shared lastState, Data.Shared currentState) { if (!hasDRS && currentState.DrsAvailable == 1) { hasDRS = true; } if (gapsInFront == null || gapsBehind == null) { clearState(); } if (CommonData.isRaceStarted && CommonData.isNewSector) { sectorsSinceLastReport++; if (!CommonData.racingSameCarInFront) { gapsInFront.Clear(); } if (!CommonData.racingSameCarBehind) { gapsBehind.Clear(); } GapStatus gapInFrontStatus = GapStatus.NONE; GapStatus gapBehindStatus = GapStatus.NONE; if (currentState.Position != 1) { gapsInFront.Insert(0, currentState.TimeDeltaFront); gapInFrontStatus = getGapStatus(gapsInFront, gapInFrontAtLastReport); } if (!CommonData.isLast) { gapsBehind.Insert(0, currentState.TimeDeltaBehind); gapBehindStatus = getGapStatus(gapsBehind, gapBehindAtLastReport); } // Play which ever is the smaller gap, but we're not interested if the gap is < 0.5 or > 20 seconds or hasn't changed: Boolean playGapInFront = gapInFrontStatus != GapStatus.NONE && (gapBehindStatus == GapStatus.NONE || (gapsInFront.Count() > 0 && gapsBehind.Count() > 0 && gapsInFront[0] < gapsBehind[0])); Boolean playGapBehind = !playGapInFront && gapBehindStatus != GapStatus.NONE; if (playGapInFront && sectorsSinceLastReport >= sectorsUntilNextReport) { sectorsSinceLastReport = 0; // here we report on gaps semi-randomly, we'll see how this sounds... sectorsUntilNextReport = rand.Next(3, 5); switch (gapInFrontStatus) { case GapStatus.INCREASING: audioPlayer.queueClip(QueuedMessage.compoundMessageIdentifier + "Timings/gaps", new QueuedMessage(folderGapInFrontIncreasing, folderSeconds, TimeSpan.FromMilliseconds(gapsInFront[0] * 1000), 0, this)); lastGapInFrontReport = GapStatus.INCREASING; gapInFrontAtLastReport = gapsInFront[0]; break; case GapStatus.DECREASING: audioPlayer.queueClip(QueuedMessage.compoundMessageIdentifier + "Timings/gaps", new QueuedMessage(folderGapInFrontDecreasing, folderSeconds, TimeSpan.FromMilliseconds(gapsInFront[0] * 1000), 0, this)); lastGapInFrontReport = GapStatus.DECREASING; gapInFrontAtLastReport = gapsInFront[0]; break; case GapStatus.CLOSE: audioPlayer.queueClip(folderBeingHeldUp, 0, this); lastGapInFrontReport = GapStatus.CLOSE; gapInFrontAtLastReport = gapsInFront[0]; break; } } if (playGapBehind && sectorsSinceLastReport > sectorsUntilNextReport) { sectorsSinceLastReport = 0; sectorsUntilNextReport = rand.Next(2, 6); switch (gapBehindStatus) { case GapStatus.INCREASING: audioPlayer.queueClip(QueuedMessage.compoundMessageIdentifier + "Timings/gaps", new QueuedMessage(folderGapBehindIncreasing, folderSeconds, TimeSpan.FromMilliseconds(gapsBehind[0] * 1000), 0, this)); lastGapBehindReport = GapStatus.INCREASING; gapBehindAtLastReport = gapsBehind[0]; break; case GapStatus.DECREASING: audioPlayer.queueClip(QueuedMessage.compoundMessageIdentifier + "Timings/gaps", new QueuedMessage(folderGapBehindDecreasing, folderSeconds, TimeSpan.FromMilliseconds(gapsBehind[0] * 1000), 0, this)); lastGapBehindReport = GapStatus.DECREASING; gapBehindAtLastReport = gapsBehind[0]; break; case GapStatus.CLOSE: audioPlayer.queueClip(folderBeingPressured, 0, this); lastGapBehindReport = GapStatus.CLOSE; gapBehindAtLastReport = gapsBehind[0]; break; } } } }