public void addNewOpponentName(String rawDriverName) { try { String usableName = DriverNameHelper.getUsableDriverName(rawDriverName); if (usableName != null && usableName.Length > 0) { if (driverNamesInUse.Contains(rawDriverName)) { return; } if (initialised) { Console.WriteLine("adding opponent name to speech recogniser: " + Environment.NewLine + usableName); Choices opponentChoices = new Choices(); opponentChoices.Add(WHERE_IS + " " + usableName); opponentChoices.Add(WHATS + " " + usableName + POSSESSIVE + " " + LAST_LAP); opponentChoices.Add(WHATS + " " + usableName + POSSESSIVE + " " + BEST_LAP); opponentChoices.Add(WHAT_TYRES_IS + " " + usableName + " " + ON); opponentChoices.Add(WHAT_TYRE_IS + " " + usableName + " " + ON); GrammarBuilder opponentGrammarBuilder = new GrammarBuilder(); opponentGrammarBuilder.Culture = cultureInfo; opponentGrammarBuilder.Append(opponentChoices); Grammar newOpponentGrammar = new Grammar(opponentGrammarBuilder); sre.LoadGrammar(newOpponentGrammar); opponentGrammarList.Add(newOpponentGrammar); } driverNamesInUse.Add(rawDriverName); } } catch (Exception e) { Console.WriteLine("Unable to add new driver to speech recognition engine - " + e.Message); } }
public CrewChief() { speechRecogniser = new SpeechRecogniser(this); audioPlayer = new AudioPlayer(this); audioPlayer.initialise(); eventsList.Add("Timings", new Timings(audioPlayer)); eventsList.Add("Position", new Position(audioPlayer)); eventsList.Add("LapCounter", new LapCounter(audioPlayer)); eventsList.Add("LapTimes", new LapTimes(audioPlayer)); eventsList.Add("Penalties", new Penalties(audioPlayer)); eventsList.Add("MandatoryPitStops", new MandatoryPitStops(audioPlayer)); eventsList.Add("Fuel", new Fuel(audioPlayer)); eventsList.Add("Opponents", new Opponents(audioPlayer)); eventsList.Add("RaceTime", new RaceTime(audioPlayer)); eventsList.Add("TyreMonitor", new TyreMonitor(audioPlayer)); eventsList.Add("EngineMonitor", new EngineMonitor(audioPlayer)); eventsList.Add("DamageReporting", new DamageReporting(audioPlayer)); eventsList.Add("PushNow", new PushNow(audioPlayer)); eventsList.Add("FlagsMonitor", new FlagsMonitor(audioPlayer)); eventsList.Add("ConditionsMonitor", new ConditionsMonitor(audioPlayer)); eventsList.Add("OvertakingAidsMonitor", new OvertakingAidsMonitor(audioPlayer)); sessionEndMessages = new SessionEndMessages(audioPlayer); DriverNameHelper.readRawNamesToUsableNamesFiles(AudioPlayer.soundFilesPath); }
private List <String> getMessageFolders(List <MessageFragment> messageFragments, Boolean hasAlternative) { List <String> messages = new List <String>(); for (int i = 0; i < messageFragments.Count; i++) { MessageFragment messageFragment = messageFragments[i]; if (messageFragment == null) { Console.WriteLine("Message " + this.messageName + " can't be played because it has no contents"); canBePlayed = false; break; } // if this fragment is not the last message fragment, then some languages (Italian only at the time of writing) // require a different inflection to the final part of a time / number sound. Boolean useMoreInflection = i < messageFragments.Count - 1; switch (messageFragment.type) { case FragmentType.Text: if (messageFragment.text.StartsWith(AudioPlayer.PAUSE_ID) || SoundCache.availableSounds.Contains(messageFragment.text) || SoundCache.hasSingleSound(messageFragment.text)) { messages.Add(messageFragment.text); } else { Console.WriteLine("Message " + this.messageName + " can't be played because there is no sound for text fragment " + messageFragment.text); canBePlayed = false; } break; case FragmentType.Time: if (numberReader != null) { List <String> timeFolders = numberReader.ConvertTimeToSounds(messageFragment.timeSpan, useMoreInflection); if (timeFolders.Count == 0) { Console.WriteLine("Message " + this.messageName + " can't be played because the number reader found no sounds for timespan " + messageFragment.timeSpan.timeSpan.ToString() + " precision " + messageFragment.timeSpan.getPrecision()); canBePlayed = false; } else { foreach (String timeFolder in timeFolders) { if (!timeFolder.StartsWith(AudioPlayer.PAUSE_ID) && !SoundCache.availableSounds.Contains(timeFolder)) { Console.WriteLine("Message " + this.messageName + " can't be played because there is no sound for time fragment " + timeFolder); canBePlayed = false; break; } } messages.AddRange(timeFolders); } } else { Console.WriteLine("Message " + this.messageName + " can't be played because the number reader is not available"); canBePlayed = false; } break; case FragmentType.Opponent: canBePlayed = false; if (messageFragment.opponent != null && messageFragment.opponent.CanUseName) { String usableName = DriverNameHelper.getUsableDriverName(messageFragment.opponent.DriverRawName); if (SoundCache.availableDriverNames.Contains(usableName)) { messages.Add(usableName); canBePlayed = true; } else if (usableName != null && usableName.Count() > 0 && AudioPlayer.ttsOption != AudioPlayer.TTS_OPTION.NEVER && (!hasAlternative || AudioPlayer.ttsOption == AudioPlayer.TTS_OPTION.ANY_TIME)) { messages.Add(SoundCache.TTS_IDENTIFIER + usableName); canBePlayed = true; } else { Console.WriteLine("Message " + this.messageName + " can't be played because there is no sound for opponent name " + usableName); } } else { Console.WriteLine("Message " + this.messageName + " can't be played because the opponent is null or unusable"); } break; case FragmentType.Integer: if (numberReader != null) { List <String> integerFolders = numberReader.GetIntegerSounds(messageFragment.integer, messageFragment.allowShortHundreds, useMoreInflection); if (integerFolders.Count() == 0) { Console.WriteLine("Message " + this.messageName + " can't be played because the number reader found no sounds for number " + messageFragment.integer); canBePlayed = false; break; } else { foreach (String integerFolder in integerFolders) { if (!integerFolder.StartsWith(AudioPlayer.PAUSE_ID) && !SoundCache.availableSounds.Contains(integerFolder)) { Console.WriteLine("Message " + this.messageName + " can't be played because there is no sound for number fragment " + integerFolder); canBePlayed = false; break; } } } messages.AddRange(integerFolders); } else { Console.WriteLine("Message " + this.messageName + " can't be played because the number reader is not available"); canBePlayed = false; } break; } if (!canBePlayed) { break; } } return(messages); }
public Boolean Run(String filenameToRun, int interval, Boolean dumpToFile) { loadDataFromFile = false; audioPlayer.mute = false; if (filenameToRun != null && System.Diagnostics.Debugger.IsAttached) { loadDataFromFile = true; spotterEnabled = false; if (interval > 0) { _timeInterval = TimeSpan.FromMilliseconds(interval); audioPlayer.mute = false; } else { _timeInterval = TimeSpan.Zero; audioPlayer.mute = true; } dumpToFile = false; } gameStateMapper = GameStateReaderFactory.getInstance().getGameStateMapper(gameDefinition); gameStateMapper.setSpeechRecogniser(speechRecogniser); gameDataReader = GameStateReaderFactory.getInstance().getGameStateReader(gameDefinition); gameDataReader.ResetGameDataFromFile(); gameDataReader.dumpToFile = System.Diagnostics.Debugger.IsAttached && dumpToFile; if (gameDefinition.spotterName != null) { spotter = (Spotter)Activator.CreateInstance(Type.GetType(gameDefinition.spotterName), audioPlayer, spotterEnabled); } else { Console.WriteLine("No spotter defined for game " + gameDefinition.friendlyName); spotter = null; } running = true; DateTime nextRunTime = DateTime.Now; if (!audioPlayer.initialised) { Console.WriteLine("Failed to initialise audio player"); return(false); } audioPlayer.startMonitor(); Boolean attemptedToRunGame = false; Console.WriteLine("Polling for shared data every " + _timeInterval.Milliseconds + "ms"); Boolean sessionFinished = false; while (running) { DateTime now = DateTime.Now; if (now > nextRunTime) { // ensure the updates don't get synchronised with the spotter / UDP receiver int updateTweak = random.Next(10) - 5; nextRunTime = DateTime.Now.Add(_timeInterval); nextRunTime.Add(TimeSpan.FromMilliseconds(updateTweak)); if (!loadDataFromFile) { if (gameDefinition.processName == null || Utilities.IsGameRunning(gameDefinition.processName)) { if (!mapped) { mapped = gameDataReader.Initialise(); } } else if (UserSettings.GetUserSettings().getBoolean(gameDefinition.gameStartEnabledProperty) && !attemptedToRunGame) { Utilities.runGame(UserSettings.GetUserSettings().getString(gameDefinition.gameStartCommandProperty), UserSettings.GetUserSettings().getString(gameDefinition.gameStartCommandOptionsProperty)); attemptedToRunGame = true; } } if (loadDataFromFile || mapped) { stateCleared = false; Object rawGameData; if (loadDataFromFile) { rawGameData = gameDataReader.ReadGameDataFromFile(filenameToRun); if (rawGameData == null) { Console.WriteLine("Reached the end of the data file, sleeping to clear queued messages"); Thread.Sleep(5000); audioPlayer.purgeQueues(); running = false; continue; } } else { rawGameData = gameDataReader.ReadGameData(false); } gameStateMapper.versionCheck(rawGameData); GameStateData nextGameState = null; try { nextGameState = gameStateMapper.mapToGameStateData(rawGameData, currentGameState); } catch (Exception e) { Console.WriteLine("Error mapping game data: " + e.StackTrace); } // if we're paused or viewing another car, the mapper will just return the previous game state so we don't lose all the // persistent state information. If this is the case, don't process any stuff if (nextGameState != null && nextGameState != currentGameState) { previousGameState = currentGameState; currentGameState = nextGameState; if (!sessionFinished && currentGameState.SessionData.SessionPhase == SessionPhase.Finished && previousGameState != null) { Console.WriteLine("Session finished"); audioPlayer.purgeQueues(); if (displaySessionLapTimes) { Console.WriteLine("Session lap times:"); Console.WriteLine(String.Join(";", currentGameState.SessionData.formattedPlayerLapTimes)); } sessionEndMessages.trigger(previousGameState.SessionData.SessionRunningTime, previousGameState.SessionData.SessionType, currentGameState.SessionData.SessionPhase, previousGameState.SessionData.SessionStartPosition, previousGameState.SessionData.Position, previousGameState.SessionData.NumCarsAtStartOfSession, previousGameState.SessionData.CompletedLaps, previousGameState.SessionData.IsDisqualified); sessionFinished = true; audioPlayer.disablePearlsOfWisdom = false; if (loadDataFromFile) { Thread.Sleep(2000); } } float prevTime = previousGameState == null ? 0 : previousGameState.SessionData.SessionRunningTime; if (currentGameState.SessionData.IsNewSession) { Console.WriteLine("New session"); audioPlayer.disablePearlsOfWisdom = false; displayNewSessionInfo(currentGameState); sessionFinished = false; if (!stateCleared) { Console.WriteLine("Clearing game state..."); audioPlayer.purgeQueues(); foreach (KeyValuePair <String, AbstractEvent> entry in eventsList) { entry.Value.clearState(); } faultingEvents.Clear(); faultingEventsCount.Clear(); stateCleared = true; } if (enableDriverNames) { List <String> rawDriverNames = currentGameState.getRawDriverNames(); if (currentGameState.SessionData.DriverRawName != null && currentGameState.SessionData.DriverRawName.Length > 0 && !rawDriverNames.Contains(currentGameState.SessionData.DriverRawName)) { rawDriverNames.Add(currentGameState.SessionData.DriverRawName); } if (rawDriverNames.Count > 0) { List <String> usableDriverNames = DriverNameHelper.getUsableDriverNames(rawDriverNames); if (speechRecogniser != null && speechRecogniser.initialised) { speechRecogniser.addOpponentSpeechRecognition(usableDriverNames, enableDriverNames); } } } } // TODO: for AC free practice sessions, the SessionRunningTime is set to 1 hour in the mapper and stays there so this block never triggers else if (!sessionFinished && previousGameState != null && (currentGameState.SessionData.SessionRunningTime > previousGameState.SessionData.SessionRunningTime || (previousGameState.SessionData.SessionPhase != currentGameState.SessionData.SessionPhase)) || ((gameDefinition.gameEnum == GameEnum.PCARS_32BIT || gameDefinition.gameEnum == GameEnum.PCARS_64BIT || gameDefinition.gameEnum == GameEnum.PCARS_NETWORK) && currentGameState.SessionData.SessionHasFixedTime && currentGameState.SessionData.SessionTotalRunTime == -1)) { if (spotter != null) { if (currentGameState.FlagData.isFullCourseYellow) { spotter.pause(); } else { spotter.unpause(); } } if (currentGameState.SessionData.IsNewLap) { currentGameState.display(); } stateCleared = false; foreach (KeyValuePair <String, AbstractEvent> entry in eventsList) { if (entry.Value.isApplicableForCurrentSessionAndPhase(currentGameState.SessionData.SessionType, currentGameState.SessionData.SessionPhase)) { triggerEvent(entry.Key, entry.Value, previousGameState, currentGameState); } } if (spotter != null && spotterEnabled && !spotterIsRunning && !loadDataFromFile) { Console.WriteLine("********** starting spotter***********"); spotter.clearState(); startSpotterThread(); } else if (spotterIsRunning && !spotterEnabled) { runSpotterThread = false; } } else if (spotter != null) { spotter.pause(); } } } } else { // ensure the updates don't get synchronised with the spotter / UDP receiver int threadSleepTime = 5 + random.Next(10); Thread.Sleep(threadSleepTime); continue; } } foreach (KeyValuePair <String, AbstractEvent> entry in eventsList) { entry.Value.clearState(); } if (spotter != null) { spotter.clearState(); } stateCleared = true; currentGameState = null; previousGameState = null; sessionFinished = false; Console.WriteLine("Stopping queue monitor"); audioPlayer.stopMonitor(); audioPlayer.disablePearlsOfWisdom = false; if (gameDataReader != null && gameDataReader.dumpToFile) { gameDataReader.DumpRawGameData(); } gameDataReader.stop(); return(true); }
private List <String> getMessageFolders(List <MessageFragment> messageFragments, Boolean hasAlternative) { List <String> messages = new List <String>(); for (int i = 0; i < messageFragments.Count; i++) { MessageFragment messageFragment = messageFragments[i]; if (messageFragment == null) { canBePlayed = false; break; } switch (messageFragment.type) { case FragmentType.Text: if (messageFragment.text.StartsWith(AudioPlayer.PAUSE_ID) || SoundCache.availableSounds.Contains(messageFragment.text) || SoundCache.availableDriverNames.Contains(messageFragment.text)) { messages.Add(messageFragment.text); } else { canBePlayed = false; } break; case FragmentType.Time: // if this time fragment is not the last message fragment, then some languages (Italian only at the time of writing) // require a different inflection to their tenths sounds Boolean useMoreInflection = i < messageFragments.Count - 1; if (numberReader != null) { List <String> timeFolders = numberReader.ConvertTimeToSounds(messageFragment.timeSpan, useMoreInflection); if (timeFolders.Count == 0) { canBePlayed = false; } else { foreach (String timeFolder in timeFolders) { if (!timeFolder.StartsWith(AudioPlayer.PAUSE_ID) && !SoundCache.availableSounds.Contains(timeFolder)) { canBePlayed = false; break; } } messages.AddRange(timeFolders); } } else { Console.WriteLine("Number reader is not available"); canBePlayed = false; } break; case FragmentType.Opponent: canBePlayed = false; if (messageFragment.opponent != null) { String usableName = DriverNameHelper.getUsableDriverName(messageFragment.opponent.DriverRawName); if (SoundCache.availableDriverNames.Contains(usableName)) { messages.Add(usableName); canBePlayed = true; } else if (usableName != null && usableName.Count() > 0 && SoundCache.useTTS && !hasAlternative) { messages.Add(SoundCache.TTS_IDENTIFIER + usableName); canBePlayed = true; } } break; case FragmentType.Integer: if (numberReader != null) { List <String> integerFolders = numberReader.GetIntegerSounds(messageFragment.integer); if (integerFolders.Count() == 0) { canBePlayed = false; break; } else { foreach (String integerFolder in integerFolders) { if (!integerFolder.StartsWith(AudioPlayer.PAUSE_ID) && !SoundCache.availableSounds.Contains(integerFolder)) { canBePlayed = false; break; } } } messages.AddRange(integerFolders); } else { Console.WriteLine("Number reader is not available"); canBePlayed = false; } break; } if (!canBePlayed) { break; } } return(messages); }