/// <summary> /// Checks for proper, valid input combination of the dialog turns. /// </summary> /// <param name="turn">A turn object.</param> /// <param name="botGreeting">Bot greeting value from the application settings.</param> /// <param name="singleConnection">Single connection value from the test settings.</param> /// <param name="firstDialog">true if this is the first dialog in the test file.</param> /// <param name="firstTurn">true if this is the first turn in the dialog.</param> /// <returns>A tuple of a boolean and a list of strings. The boolean is set to true if the string is valid and the list of strings captures the error messages if the turn is not valid.</returns> private static (bool ValidTurn, List <string> ExceptionMesssage) ValidateTurnInput(Turn turn, bool botGreeting, bool singleConnection, bool firstDialog, bool firstTurn) { bool utterancePresentValid = CheckNotNullNotEmptyString(turn.Utterance); bool activityPresentValid = CheckNotNullNotEmptyString(turn.Activity); bool wavFilePresentValid = CheckNotNullNotEmptyString(turn.WAVFile); bool expectedLatencyPresentValid = CheckNotNullNotEmptyString(turn.ExpectedUserPerceivedLatency); List <string> exceptionMessage = new List <string>(); if (activityPresentValid) { var(activityObjectValid, errorMsg) = CheckValidActivity(turn.Activity); if (!activityObjectValid) { exceptionMessage.Add(errorMsg); } } if (expectedLatencyPresentValid) { if (turn.ExpectedResponses != null && turn.ExpectedResponses.Count != 0) { var expectedLatencyObjectValid = CheckValidExpectedLatency(turn.ExpectedUserPerceivedLatency, turn.ExpectedResponses.Count); if (!expectedLatencyObjectValid) { exceptionMessage.Add(ErrorStrings.LATENCY_STRING_MALFORMED); } } else { exceptionMessage.Add(ErrorStrings.LATENCY_STRING_PRESENT); } } if (turn.ExpectedResponses != null && turn.ExpectedResponses.Count != 0 && turn.ExpectedTTSAudioResponseDurations != null) { if (turn.ExpectedTTSAudioResponseDurations.Count != turn.ExpectedResponses.Count) { exceptionMessage.Add(ErrorStrings.TTS_AUDIO_DURATION_INVALID); } else { for (int i = 0; i < turn.ExpectedResponses.Count; i++) { Activity expectedResponse = turn.ExpectedResponses[i]; int orsInText = (expectedResponse.Text == null) ? 0 : expectedResponse.Text.Split(ProgramConstants.OROperator).Length - 1; int orsInSpeak = (expectedResponse.Speak == null) ? 0 : expectedResponse.Speak.Split(ProgramConstants.OROperator).Length - 1; int orsInExpectedTTSAudioResponseDuration = turn.ExpectedTTSAudioResponseDurations[i].Split(ProgramConstants.OROperator).Length - 1; if (orsInText != orsInSpeak || orsInSpeak != orsInExpectedTTSAudioResponseDuration) { exceptionMessage.Add(ErrorStrings.OR_OCCURRENCE_INCONSISTENT); } } if (!CheckValidExpectedTTSAudioDuration(turn.ExpectedTTSAudioResponseDurations)) { exceptionMessage.Add(ErrorStrings.TTS_AUDIO_DURATION_VALUES_INVALID); } } } if ((turn.ExpectedResponses == null || turn.ExpectedResponses.Count == 0) && turn.ExpectedTTSAudioResponseDurations != null) { exceptionMessage.Add(ErrorStrings.TTS_AUDIO_DURATION_PRESENT); } if (utterancePresentValid && wavFilePresentValid && activityPresentValid) { exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.ALL_PRESENT}"); } if (wavFilePresentValid && !utterancePresentValid && activityPresentValid) { exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.WAV_FILE_ACTIVITY_PRESENT}"); } if (utterancePresentValid && !wavFilePresentValid && activityPresentValid) { exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.UTTERANCE_ACTIVITY_PRESENT}"); } // By default, assume there should be an input ("Utterance", "Activity" or "WAVFile") bool inputExpected = true; // Change the default for the case where a turn checking bot greeting is expected. For bot greeting, there should be no input. if (botGreeting && firstTurn && ((firstDialog && singleConnection) || !singleConnection)) { inputExpected = false; } // Does the current dialog have input? bool inputPresent = utterancePresentValid || wavFilePresentValid || activityPresentValid; if (inputExpected && !inputPresent) { // There should have been an input specified ("Utterance", "Activity" or "WAVFile"), but there are none. That's an error. exceptionMessage.Add($"{ErrorStrings.AMBIGUOUS_TURN_INPUT} - {ErrorStrings.NONE_PRESENT}"); } if (!inputExpected && inputPresent) { // There is an input specified ("Utterance", "Activity" or "WAVFile"), but there should be no input. That's an error exceptionMessage.Add(ErrorStrings.BOT_GREETING_MISSING); } if (turn.Sleep < 0) { // Sleep duration in msec - The value should be non-negative exceptionMessage.Add(ErrorStrings.NEGATIVE_SLEEP_DURATION); } if (exceptionMessage.Count > 0) { return(false, exceptionMessage); } return(true, exceptionMessage); }
/// <summary> /// Builds the output. /// </summary> /// <param name="turns"> Input Turns.</param> /// <param name="bootstrapMode">Boolean which defines if turn is in bootstrapping mode or not.</param> /// <param name="recognizedText">Recognized text from Speech Recongition.</param> /// <param name="recognizedKeyword">Recogized Keyword from Keyword Recognition.</param> /// <returns>TurnsOutput.</returns> public TurnResult BuildOutput(Turn turns, bool bootstrapMode, string recognizedText, string recognizedKeyword) { TurnResult turnsOutput = new TurnResult(turns) { ActualResponses = new List <Activity>(), ActualTTSAudioResponseDuration = new List <int>(), }; turnsOutput.ActualRecognizedText = recognizedText; if (recognizedKeyword != null) { turnsOutput.KeywordVerified = recognizedKeyword; } foreach (BotReply botReply in this.BotResponses) { turnsOutput.ActualResponses.Add(botReply.Activity); turnsOutput.ActualTTSAudioResponseDuration.Add(botReply.TTSAudioDuration); } if (bootstrapMode) { // In bootstrapping mode, ExpectedResponses field does not exist (or is null), and ExpectedResponseLatency does not exist if (this.BotResponses.Count > 0) { // Report the latency of the last bot response turnsOutput.ActualResponseLatency = this.BotResponses[this.BotResponses.Count - 1].Latency; } } else { // In normal mode, ExpectedResponses exists with one or more activities. ExpectedResponseLatency may or may not exist int activityIndexForLatency = 0; if (string.IsNullOrWhiteSpace(turnsOutput.ExpectedResponseLatency)) { activityIndexForLatency = turns.ExpectedResponses.Count - 1; } else { if (turnsOutput.ExpectedResponseLatency.Split(",").Length == 2) { // The user has specified an expected response latency in the two-integer string format "latency,index". Extract the index // Note: the index has already been verified to be in the range [0, turns.ExpectedResponses.Count - 1] activityIndexForLatency = int.Parse(turnsOutput.ExpectedResponseLatency.Split(",")[1], CultureInfo.CurrentCulture); } else { // The user has specified an expected response latency in the single integer string format, without an index activityIndexForLatency = turns.ExpectedResponses.Count - 1; } } if (activityIndexForLatency < this.BotResponses.Count) { turnsOutput.ActualResponseLatency = this.BotResponses[activityIndexForLatency].Latency; } } return(turnsOutput); }