/// <summary> /// Perform actions based on current status and prediction. /// </summary> /// <param name="prediction"></param> private void DispatchPrediction(PredictionArgs prediction) { if (prediction == null) { Debug.WriteLine("DISPATCH: null prediction"); // do nothing return; } lock (_lockStatus) { if (ServiceState == ServiceStateCode.Idle || ServiceState == ServiceStateCode.Training) { Debug.WriteLine("DISPATCH: skip state " + ServiceState.ToString()); // do nothing return; } // update prediction counter var previousCounter = ConsecutiveCorrectPredictions; var currentCounter = (prediction.Success ? previousCounter + 1 : 0); ConsecutiveCorrectPredictions = currentCounter; if ( (previousCounter >= NotificationThreshold && currentCounter == 0) || (previousCounter < NotificationThreshold && currentCounter == NotificationThreshold)) { Debug.WriteLine("DISPATCH: prediction threshold passed"); // notify all subscribers about prediction var contextId = prediction.PredictedScenario == null ? null : prediction.PredictedScenario.ContextId.ToString(); DoReportPrediction(contextId); } if (ServiceState == ServiceStateCode.Tracking) { if (prediction.Success) { Debug.WriteLine("DISPATCH: success in tracking state."); // no need to track _tracker.Enabled = false; } else { Debug.WriteLine("DISPATCH: failure in tracking state."); // training needed _tracker.ScenarioId = prediction.PredictedScenario == null ? null : prediction.PredictedScenario.Id.ToString(); _tracker.Enabled = true; } } } }
/// <summary> /// Try to find a scenario for the target context. On failure, a new /// scenario is created if the creation is allowed, otherwise the /// predicted scenario is returned. /// </summary> /// <returns>A prediction, or null in case of error.</returns> public PredictionArgs Prediction() { Context context = null; PredictionArgs prediction = null; lock (_localizerLock) { if (ContextId != null) { try { context = _contextService.GetById(ContextId); if (context == null) { // notify error if (LocalizerErrorNotification != null) { var args = new LocalizerErrorNotificationEventArgs( LocalizerErrorNotificationCode.UnknownContext); ThreadPool.QueueUserWorkItem(new WaitCallback(DoNotification), args); } } } catch (Exception ex) { if (LocalizerErrorNotification != null) { // notify error var args = new LocalizerErrorNotificationEventArgs( LocalizerErrorNotificationCode.DatabaseError, ex); ThreadPool.QueueUserWorkItem(new WaitCallback(DoNotification), args); } } } if (context != null) { // context found in the database prediction = new PredictionArgs { Success = false }; IEnumerable <ContextPreference> pref = null; for (var attempts = this.Retries + 1; attempts > 0; attempts--) { prediction.PredictedScenario = GetScenarioForCurrentPosition(out pref); if (prediction.PredictedScenario == null) { // retry, eventually.. continue; } if (ContextId.Equals(prediction.PredictedScenario.ContextId.ToString())) { // correct prediction _scenarioService.IncreaseAccuracy(prediction.PredictedScenario); prediction.Success = true; break; } // wrong prediction _scenarioService.DecreaseAccuracy(prediction.PredictedScenario); } if (!prediction.Success && CreationAllowed) { // create a new scenario for the requested context prediction.PredictedScenario = new Scenario { ContextId = new ObjectId(ContextId), CreationTime = DateTime.Now }; try { _scenarioService.Create(prediction.PredictedScenario); } catch (Exception ex) { if (LocalizerErrorNotification != null) { // notify error var args = new LocalizerErrorNotificationEventArgs( LocalizerErrorNotificationCode.DatabaseError, ex); ThreadPool.QueueUserWorkItem(new WaitCallback(DoNotification), args); } prediction = null; } } } // end if(context != null) } // unlock return(prediction); }