private int iterationResult; // Stores result of iteration #endregion Fields #region Constructors /// <summary> /// Class constructor /// </summary> /// <param name="_iterationResult"></param> /// <param name="_category"></param> /// <param name="_callerData"></param> /// <param name="_calleeData"></param> /// <param name="_spResult"></param> private IterationResult(int _iterationResult, CallerIterationInfo _callerData, CalleeIterationInfo _calleeData, SpeechRecognizerResult _callerSpResult, SpeechRecognizerResult _calleeSpResult) { iterationResult = _iterationResult; callerData = _callerData; calleeData = _calleeData; callerSpeechResult = _callerSpResult; calleeSpeechResult = _calleeSpResult; audioPowerResult = AudioVolume.NOT_ATTENUATED; audioVolConf = AudioVolumeConfidence.GOOD_CONFIDENCE; // determine the classification (category) for IterationResult if (iterationResult == ValidationErrors.NO_ERROR) category = TestIterationCategory.PASSED; else if (conditionExists(iterationResult, ValidationErrors.FAILED_CALL) || conditionExists(iterationResult, ValidationErrors.MISSING_HANGUP) || conditionExists(iterationResult, ValidationErrors.ECHO_DETECTED) || conditionExists(iterationResult, ValidationErrors.CALLER_NOISE_DETECTED) || conditionExists(iterationResult, ValidationErrors.CALLEE_NOISE_DETECTED) || conditionExists(iterationResult, ValidationErrors.CALLEE_NOT_HEARD) || conditionExists(iterationResult, ValidationErrors.CALLER_NOT_HEARD)) category = TestIterationCategory.FAILED; //if(iterationResult == ValidationErrors.FAILED_CALL || iterationResult == ValidationErrors.NOISE_DETECTED || iterationResult == ValidationErrors.ECHO_DETECTED) // category = TestIterationCategory.FAILED; else { // Use invalid for all others errors such as callee could not play prompt, execution error etc category = TestIterationCategory.INVALID; } }
/// <summary> /// Method that applies various validation rules to interpret the result of the iteration /// </summary> /// <param name="callerInfo"></param> /// <param name="calleeInfo"></param> /// <returns></returns> public IterationResult applyValidationRules(CallerIterationInfo callerInfo, CalleeIterationInfo calleeInfo) { IterationResult result = null; SpeechRecognizerResult callerSpeechResult = null; SpeechRecognizerResult calleeSpeechResult = null; callerData = callerInfo; calleeData = calleeInfo; int hangupRuleOutcome = ValidationErrors.NO_ERROR; int timestampRuleOutcome = ValidationErrors.NO_ERROR; int latencyRuleResult = ValidationErrors.NO_ERROR; int speechRecoRuleResult = ValidationErrors.NO_ERROR; NextRule rule = NextRule.None; // First rule - check if call was completed end to end between caller and callee. // If not, fail the iteration and return the result if (applyCallFailureValidationRule() == ValidationErrors.FAILED_CALL) { result = IterationResult.getInstance(ValidationErrors.FAILED_CALL, callerData, calleeData, null, null); return result; } hangupRuleOutcome = applyHangupValidationRule(); timestampRuleOutcome = applyTimeStampValidationRule(out rule); // Next apply timestamp validation rule and if we encounter a failure in that, and, we find that we don't need // to apply another rule, return result. if (rule == NextRule.None) { result = IterationResult.getInstance(hangupRuleOutcome | timestampRuleOutcome, callerData, calleeData, null, null); return result; } latencyRuleResult = applyLatencyValidationRule(); speechRecoRuleResult = applySpeechRecognitionRule(out calleeSpeechResult, out callerSpeechResult); result = IterationResult.getInstance(hangupRuleOutcome | timestampRuleOutcome | latencyRuleResult | speechRecoRuleResult, callerData, calleeData, callerSpeechResult, calleeSpeechResult); return result; }
/// <summary> /// A private method that sends the iteration result (calleeData in this case) to the watcher. /// </summary> private void sendCalleeDataToWatcher() { if (calleeData != null && OnIterationCompleted != null) OnIterationCompleted(this, calleeData); // Resetting calleeData to null because if a duplicate connection cleared is received, calleeData instance should // not be written again to the calleelog. calleeData = null; }
/// <summary> /// Method invoked when call is established /// </summary> /// <param name="sender"></param> /// <param name="args"></param> void phone_Established(object sender, EstablishedEventArgs args) { DateTime connEstablishedTimeStamp = DateTime.Now; /** * When call is connected, create a new instance of calleeIterationInfo * and set the time stamp of the instant when call was connected. * Also set the caller ID */ calleeData = null; calleeData = new CalleeIterationInfo(); calleeData.callConnectTime = connEstablishedTimeStamp; calleeData.remotePartyExtension = args.CallingDevice; // Preserve the connection object conn = args.EstablishedConnection; ++currIter; // Increment the iteration number try { ll.Start(); } catch (Exception e) { display("Exception in phone_Established.Message = " + e.Message + " StackTrace = " + e.StackTrace, MessageType.WARNING); } try { if (recorder != null) { recorder.Filename = inputParam.resultDirName + "\\Callee_RecordedWav_" + currIter.ToString() + ".wav"; recorder.Start(); } } catch(Exception e2) { display("Exception in phone_Established.Message = " + e2.Message + " StackTrace = " + e2.StackTrace, MessageType.WARNING); } promptTimer.Enabled = true; setState(CurrentState.CONNECTED); missingHangupDetectionTimer.Enabled = true; }
/// <summary> /// Private helper method for the constructors /// </summary> private void initializeCallee() { conn = null; phone = null; pm = null; ll = null; recorder = null; calleeData = null; isRegistered = false; /** * Read the configuration params file and populate suitable parameters */ readConfigParams(); display("Configration file = " + inputParam.configFile); // this.numIterations = totalIter * totalSets; display("Extension = " + inputParam.myExtension); /** * Create an instance of prompt wait timer */ promptTimer = new System.Windows.Forms.Timer(); promptTimer.Enabled = false; promptTimer.Interval = promptWaitDuration * 1000; promptTimer.Tick += new System.EventHandler(promptTimer_Tick); missingHangupDetectionTimer = new System.Windows.Forms.Timer(); missingHangupDetectionTimer.Enabled = false; // Missing hangup detection timer is set to 5 times maximum call duration and wait time between calls missingHangupDetectionTimer.Interval = 5 * (maxCallDuration + waitTimeBetweenCalls) * 1000; missingHangupDetectionTimer.Enabled = false; missingHangupDetectionTimer.Tick += new System.EventHandler(missingHangupDetectionTimer_Tick); initializeVoiceDevice(); }
/// <summary> /// Method to create an instance of IterationResult. /// </summary> /// <param name="_iterationResult"></param> /// <param name="_category"></param> /// <param name="_callerData"></param> /// <param name="_calleeData"></param> /// <param name="_spResult"></param> /// <returns></returns> public static IterationResult getInstance(int _iterationResult, CallerIterationInfo _callerData, CalleeIterationInfo _calleeData, SpeechRecognizerResult _callerSpResult, SpeechRecognizerResult _calleeSpResult) { try { return new IterationResult(_iterationResult, _callerData, _calleeData, _callerSpResult, _calleeSpResult); } catch (Exception e) { return null; } }
/// <summary> /// Method that reads the corresponding callee and caller log files and finds out which lines of caller /// and callee belong to same call and processes them /// </summary> public void generateResults() { string callerLine; string calleeLine; CallerIterationInfo callerInfo = null; // Caller's iteration info CalleeIterationInfo calleeInfo = null; // Callee's iteration info int returnCode; bool calleeFileEmpty = false; while (true) { // If callerInfo is null, read the next line and create a callerInfo from it. // If callerFile is empty or exception in creating callerInfo, break. if (callerInfo == null) { callerLine = callerFileReader.ReadLine(); currentCallerLineNum++; if (callerLine == null) { break; } else { try { callerInfo = new CallerIterationInfo(callerLine); } catch(Exception e) { Console.WriteLine("Error in Analyer.generateResults. Could not create CallerIterationInfo instance. Terminating reading of input logs"); Trace.TraceError("Exception while creating callerInfo: " + e.Message + "\r\nStack Trace : " + e.StackTrace); break; } } } // If calleeInfo is null, read the next line and create a calleeInfo from it. // If calleeFile is empty then create a dummy callee object. Exception in creating calleeInfo, break. if (calleeInfo == null) { calleeLine = calleeFileReader.ReadLine(); currentCalleeLineNum++; if (calleeLine == null) { calleeFileEmpty = true; calleeInfo = new CalleeIterationInfo(); } else { try { calleeInfo = new CalleeIterationInfo(calleeLine); } catch(Exception e2) { Console.WriteLine("Error in Analyer.generateResults. Could not create CalleeIterationInfo instance. Terminating reading of input logs"); Trace.TraceError("Exception while creating calleeInfo: " + e2.Message + "\r\nStack Trace : " + e2.StackTrace); break; } } } if (!calleeFileEmpty) { returnCode = causalOrderBetweenCallerAndCallee(callerInfo, calleeInfo); switch (returnCode) { case 0: // both belong to same call case -3: // both have uninitialized connect timestamps processTokens(callerInfo, calleeInfo, true); callerInfo = null; calleeInfo = null; break; case 1: // caller's current call after callee's call case -2: // callee's current call had uninitialized connection timestamp // discard calleeInfo as it could not be matched with caller // continue to store callerInfo calleeInfo = null; break; case 2: // callee's current call after caller's call case -1: // caller's current call had uninitialized conneciton timestamp // processTokens with callerInfo and dummy calleeInfo // and discard callerInfo processTokens(callerInfo, new CalleeIterationInfo(), false); callerInfo = null; break; } } else { processTokens(callerInfo, new CalleeIterationInfo(), false); callerInfo = null; } } aggResult.displayResult(resultDir + "\\GatewayTestResults.txt"); }
/// <summary> /// Private method that applies the token validation rules and generates iteration result instances /// </summary> /// <param name="callerInfo"></param> /// <param name="calleeInfo"></param> private void processTokens(CallerIterationInfo callerInfo, CalleeIterationInfo calleeInfo, bool matchRecordedWav) { IterationResult result = null; /** * If the current objects indeed belong to a same call, we can locate corresponding wav files and rename them * to ensure that the file from caller and the callee can be correlated. */ if (matchRecordedWav == true) { string callerFile = resultDir + "\\Caller_RecordedWav_" + currentCallerLineNum + ".wav"; string calleeFile = resultDir + "\\Callee_RecordedWav_" + currentCalleeLineNum + ".wav"; string newCallerFile = resultDir + "\\Caller_RecordedWav_" + currentCallerLineNum + "_matched.wav"; string newCalleeFile = resultDir + "\\Callee_RecordedWav_" + currentCallerLineNum + "_matched.wav"; try { if (File.Exists(callerFile) && File.Exists(calleeFile)) { File.Move(callerFile, newCallerFile); File.Move(calleeFile, newCalleeFile); } } catch (Exception e) { Console.WriteLine("Exception encountered in matching " + callerFile + " with " + calleeFile + ". Message:\n" + e.Message); Trace.TraceError("Exception occurred. Message : " + e.Message + "\r\nStack Trace : " + e.StackTrace); } } result = ri.applyValidationRules(callerInfo, calleeInfo); Console.WriteLine("\nIteration = " + ++iterationNum + "\n" + result.ToString()); aggResult.addIterationResult(result); }
/// <summary> /// Method to determine causal ordering between caller and callee's current call /// </summary> /// <param name="callerInfo"></param> /// <param name="calleeInfo"></param> /// <returns></returns> private int causalOrderBetweenCallerAndCallee(CallerIterationInfo callerInfo, CalleeIterationInfo calleeInfo) { DateTime uninitDate = new DateTime(); // Uninitialized date int result = -1; /** * If either caller or callee did not have valid connection time, return -1 to indicate that no matching is possible * with this caller callee pair */ if (callerInfo.callConnectTime == uninitDate && calleeInfo.callConnectTime == uninitDate) { return -3; } else if(callerInfo.callConnectTime == uninitDate) { result = -1; } else if (calleeInfo.callConnectTime == uninitDate) { result = -2; } else if ((callerInfo.callConnectTime <= calleeInfo.callConnectTime && calleeInfo.callConnectTime < callerInfo.callReleaseTime) || (calleeInfo.callConnectTime <= callerInfo.callConnectTime && callerInfo.callConnectTime < calleeInfo.callReleaseTime)) { /** * If caller and callee belong to same call return 0 */ result = 0; } else if (calleeInfo.callConnectTime >= callerInfo.callReleaseTime) { /** * If callee's current call is causally after caller's current call, return 2. */ result = 2; } else if (calleeInfo.callReleaseTime <= callerInfo.callConnectTime) { /** * If caller's current call is causally before caller's current call, return 2 */ result = 1; } return result; }
private WavFileInfo wInfo; // WavFileInfo instance #endregion Fields #region Constructors /// <summary> /// Class constructor /// </summary> public ResultInterpreter(WavFileInfo _wInfo) { wInfo = _wInfo; callerData = null; calleeData = null; }