示例#1
0
        //TODO: save information persistently between sessions

        /// <summary>
        /// Based on last statistics it calculates the time the current interaction queue will take
        /// </summary>
        /// <returns>Time in seconds</returns>
        public static double TimeForecast()
        {
            // it should be run only if there are already some statistics about how much an interaction takes time

            float time = 0;

            foreach (var category in CategoryNInter)
            {
                if (averageTimeOfInteractionPerCategory.Exists(x => x.Item1 == category.Key))
                {
                    var categoryStat = averageTimeOfInteractionPerCategory.Find(x => x.Item1 == category.Key);

                    // N interactions scheduled * ( Average time per category + Average pause time)
                    time = time + category.Value * (categoryStat.Item2 + AveragePauseTime());
                }
                else
                {
                    SharedHelper.Log("Unacounted category in TimeForecast'" + category + "'");
                }
            }

            // TODO: consider that reaction interactions take less pause time
            // TODO: reactions are not acounted (category "MakeStatement" for example)

            return(time);
        }
示例#2
0
        public static void SetAsUsed(string Name)
        {
            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].Name == Name)
                {
                    list[i].IsUsed = true;

                    SharedHelper.Log("Uncertain question " + Name + " is set to used.");

                    list[i].TimeLastAsked = DateTime.Now;

                    if (allRepeatingQuestionsTimeoutsInMinutes.Count == 0)
                    {
                        GenerateRepeatingQuestionsTimeouts();
                    }

                    list[i].TimeOutSeconds = allRepeatingQuestionsTimeoutsInMinutes.Dequeue() * 60;

                    return;
                }
            }

            SharedHelper.LogError("Uncertain Fact Name '" + Name + "' not found in SetAsUsed!");
        }
示例#3
0
        //TODO: addt the ability the N distribution to be changed over time
        float IBaseDistributions.GetNextInteactionPause(bool isReacting)
        {
            if (!isReacting)
            {
                //SharedHelper.Log("Pause time set following default distribution.");

                if (allInteractionPauses.Count == 0)
                {
                    var normalDist = from seconds in Normal(3.7, 0.25) //default 4.7, 1
                                     select seconds;

                    string singleStringAllPauses = "";

                    for (var i = 0; i < 101; i++)
                    {
                        float value = (float)normalDist.Sample(); //sampling
                        singleStringAllPauses = singleStringAllPauses + "," + value;
                        allInteractionPauses.Enqueue(value);
                    }
                }

                return(allInteractionPauses.Dequeue());
            }
            else //if it is a response, we try to react quicker than starting a new interaction
            {
                float value = pauseUniformAfterReaction.Next(1, 2) / 10f;
                SharedHelper.Log("Pause time set as a reaction to question: " + value);
                return(value);
            }
        }
示例#4
0
        public bool AdjustProbVariablesDuringPlanning(int bufferedInteractionsCount)
        {
            bool regenerate = false;

            //1. About bot
            //exclude this action because there are no items for it
            if (ProbVariables.Bot.PrSharePureFactInfoAboutBot[(int)PV.Current].Value != 0 && KorraModelHelper.GetItemsLeftForSubCategory(ActionsEnum.SharePureFactInfoAboutBot, ItemProviders) == 0)
            {
                //adjust pure facts probabilities: disable AboutBot and boost AboutUser

                ProbVariables.Bot.PrSharePureFactInfoAboutBot[(int)PV.Current] = Prob(0);
                SharedHelper.LogWarning("Disabled all pure facts about bot, because there were no items.");

                //we re-inforce AboutUser so that it is stronger than Suggestion action
                if (ProbVariables.Bot.PrAskPureFactQuestionAboutUser[(int)PV.Current].Value > 0)
                {
                    ProbVariables.Bot.PrAskPureFactQuestionAboutUser[(int)PV.Current] = ProbVariables.Bot.PrAskPureFactQuestionAboutUser[(int)PV.Increased];
                }

                regenerate = true;
            }

            //2. About User
            //exclude this action because there are no items for it
            if (ProbVariables.Bot.PrAskPureFactQuestionAboutUser[(int)PV.Current].Value != 0 && KorraModelHelper.GetItemsLeftForSubCategory(ActionsEnum.AskPureFactQuestionAboutUser, ItemProviders) == 0)
            {
                //adjust pure facts probabilities: disable AboutUser and boost AboutBot

                ProbVariables.Bot.PrAskPureFactQuestionAboutUser[(int)PV.Current] = Prob(0);
                SharedHelper.Log("Disabled all pure facts about user, because there were no items.");

                //we re-inforce AboutBot so that it is stronger than Suggestion action
                if (ProbVariables.Bot.PrSharePureFactInfoAboutBot[(int)PV.Current].Value > 0)
                {
                    ProbVariables.Bot.PrSharePureFactInfoAboutBot[(int)PV.Current] = ProbVariables.Bot.PrSharePureFactInfoAboutBot[(int)PV.Increased];
                }

                regenerate = true;
            }

            //3. Suggestions
            //if there are no Pure or Uncertain facts left then we boost suggestions
            bool noFactsLeft = (ProbVariables.Bot.PrAskPureFactQuestionAboutUser[(int)PV.Current].Value == 0 && ProbVariables.Bot.PrSharePureFactInfoAboutBot[(int)PV.Current].Value == 0);

            if (noFactsLeft && ProbVariables.Bot.PrMakeSuggestion[(int)PV.Current] != ProbVariables.Bot.PrMakeSuggestion[(int)PV.Default])
            {
                ProbVariables.Bot.PrMakeSuggestion[(int)PV.Current] = ProbVariables.Bot.PrMakeSuggestion[(int)PV.Default];
                SharedHelper.Log("All pure facts used. PrMakeSuggestion changed to: " + ProbVariables.Bot.PrMakeSuggestion[(int)PV.Current]);
            }

            //Keep suggestions decreased if there are more pure facts
            if (!noFactsLeft && ProbVariables.Bot.PrMakeSuggestion[(int)PV.Current] != ProbVariables.Bot.PrMakeSuggestion[(int)PV.Descreased])
            {
                SharedHelper.Log("PrMakeSuggestion changed decreased.");
                ProbVariables.Bot.PrMakeSuggestion[(int)PV.Current] = ProbVariables.Bot.PrMakeSuggestion[(int)PV.Descreased];
            }

            return(regenerate);
        }
示例#5
0
        //NOT ADAPTED for category and subcategory
        private static void DisableAcion(ref ItemProb <string>[] items, string actionToRemove)
        {
            SharedHelper.Log("Error category PureFact");

            SharedHelper.Log("Action removed: " + actionToRemove.ToString());

            items = items.Where(x => x.Item != actionToRemove).ToArray();
        }
示例#6
0
        private Queue <string> GenerateActions(string[] disabledActions)
        {
            allActions.Clear();

            #region Create a list of all possible actions

            ItemProb <string>[] items =
            {
                ItemProb(ActionsEnum.MakeSuggestion,               ProbVariables.Bot.PrMakeSuggestion[(int)PV.Current]),

                ItemProb(ActionsEnum.AskUncertanFactQuestion,      ProbVariables.Bot.PrAskUncertanFactQuestion),

                ItemProb(ActionsEnum.AskPureFactQuestionAboutUser, ProbVariables.Bot.PrAskPureFactQuestionAboutUser[(int)PV.Current]), //to be packed as one

                ItemProb(ActionsEnum.SharePureFactInfoAboutBot,    ProbVariables.Bot.PrSharePureFactInfoAboutBot[(int)PV.Current]),    //to be packed as one

                ItemProb(ActionsEnum.ChangeVisualAppearance,       SharedHelper.GetProb(ProbVariables.Bot.ChangeVisualAppearance)),

                ItemProb(ActionsEnum.ExpressMentalState,           SharedHelper.GetProb(ProbVariables.Bot.ExpressMentalState)),
            };

            #endregion

            #region Disable actions - NOT ADAPTED for category and subcategory
            if (BotConfigShared.DisableAskQuestions)
            {
                SharedHelper.LogError("NOT ADAPTED for category and subcategory");

                //two actions are removed
                //DisableAcion(ref items, ActionsEnum.AskPureFactQuestionAboutUser);
                //DisableAcion(ref items, ActionsEnum.AskUncertanFactQuestion);
            }

            //foreach (string da in disabledActions)
            //{
            //    DisableAcion(ref items, da);
            //}
            #endregion

            #region Sampling

            var Action = CategoricalF(items).Normalize();

            SharedHelper.Log("Actions Histogram:\r\n" + Action.Histogram());

            var actionDist = Action.ToSampleDist();

            for (var i = 0; i < 100; i++)
            {
                string sample = actionDist.Sample();

                allActions.Enqueue(sample);
            }
            #endregion

            return(allActions);
        }
示例#7
0
 public static void PrintSuggestionsProbabilities()
 {
     SharedHelper.Log("SUGGESTIONS Probabilities: \r\n"
                      + "Suggest Go out: " + SharedHelper.GetProb(Bot.SuggestGoOut).Value.ToString() + "\r\n"
                      + "Tell Joke: " + SharedHelper.GetProb(Bot.TellJoke).Value.ToString() + "\r\n"
                      + "Suggest To WatchMovie: " + SharedHelper.GetProb(Bot.SuggestToWatchMovie).Value.ToString() + "\r\n"
                      + "Tell Weather Forecast: " + SharedHelper.GetProb(Bot.TellWeatherForecast).Value.ToString() + "\r\n"                          //not used
                      + "Suggest Listen To Song: " + Bot.PrSuggestListenToSong.Value.ToString() + "\r\n"
                      );
 }
示例#8
0
 public static void PrintActionsProbabilities()
 {
     SharedHelper.Log("ACTIONS Probabilities: \r\n"
                      + "PrMakeSuggestion: " + Bot.PrMakeSuggestion[(int)PV.Current].Value.ToString() + "\r\n"
                      + "PrAskUncertanFactQuestion: " + Bot.PrAskUncertanFactQuestion.Value.ToString() + "\r\n"
                      + "PrAskPureFactQuestionAboutUser: "******"\r\n"
                      + "PrSharePureFactInfoAboutBot: " + Bot.PrSharePureFactInfoAboutBot[(int)PV.Current].Value.ToString() + "\r\n"
                      + "PrChangeVisualAppearance: " + SharedHelper.GetProb(Bot.ChangeVisualAppearance).Value.ToString() + "\r\n"
                      + "PrExpressMentalState: " + SharedHelper.GetProb(Bot.ExpressMentalState).Value.ToString() + "\r\n"
                      );
 }
示例#9
0
 public static void SetProb(string Name, double newProb)
 {
     foreach (var q in list)
     {
         if (q.Name == Name)
         {
             SharedHelper.Log("'" + Name + "' prob variable has been updated from " + q.ProbVariable.RefValue.ProbOf(e => e == true).Value + " to " + newProb);
             q.ProbVariable.RefValue = BernoulliF(Prob(newProb));
         }
     }
 }
示例#10
0
        public void BeforeAnalyseUserResponse(PureFact pfact)
        {
            //Here you change the responses that were encoded when creating this PureFact, even replace the function responsible for the answers.
            //This can be useful if you have new information about the user and its environment and this could not be encoded in advance.

            bool   isAnswerd     = pfact.IsAnswered;
            string responseValue = pfact.Value;

            //if (context.Phrases.IsYes(responseValue))
            //{
            //    fact.StatementOnPositiveResponse = "";
            //}
            SharedHelper.Log("Pure fact updated: " + pfact.Name);
        }
示例#11
0
        public static void PrintSummary()
        {
            string result = "";
            int    i      = 0;

            foreach (var key in CategoryNInter.Keys)
            {
                i++;
                result += "|" + key + ": " + CategoryNInter[key] + Environment.NewLine;
            }
            SharedHelper.LogWarning("Interactions statistics: " + Environment.NewLine + result);

            TimeSpan time = TimeSpan.FromSeconds(TimeForecast());

            SharedHelper.Log("Time (hh:mm) forecast scheduled interactions will take: " + time.ToString(@"hh\:mm"));
        }
示例#12
0
        public static void CoupleTwoInteractionsTogether(ref List <CommItem> list, string name1, string name2)
        {
            int p            = 0;
            int itemNamePos1 = -1;
            int itemNamePos2 = -1;

            for (p = 0; p < list.Count; p++)
            {
                if (list[p].IsPureFact)
                {
                    if (list[p].Name == name1)
                    {
                        itemNamePos2 = p;
                    }
                    if (list[p].Name == name2)
                    {
                        itemNamePos1 = p;
                    }
                    if (itemNamePos2 != -1 && itemNamePos1 != -1)
                    {
                        break;
                    }
                }
            }

            if (itemNamePos2 != -1 && itemNamePos1 != -1 && (Math.Abs(itemNamePos2 - itemNamePos1) != 1))
            {
                int pos1 = Math.Min(itemNamePos1, itemNamePos2);
                int pos2 = Math.Max(itemNamePos1, itemNamePos2);

                var temp = list[pos2];
                list.RemoveAt(pos2);
                list.Insert(pos1 + 1, temp);

                SharedHelper.Log("Two interactions were coupled together: " + name1 + " and " + name2);

                //string DebugItem = "";
                //int i = 0;
                //foreach (string e in interactions.Select(e => e.TextToSay))
                //{
                //    i++;
                //    DebugItem += "|" + i + ". " + e;
                //}
                //SharedHelper.LogWarning("Interactions list: " + DebugItem);
            }
        }
示例#13
0
        public static void SetJokeAsUsed(string Name)
        {
            for (int i = 0; i < jokes.Count; i++)
            {
                if (jokes[i].Name == Name)
                {
                    jokes[i].IsUsed = true;

                    SharedHelper.Log("Joke '" + Name + "' is set to used. Joke text: '" + jokes[i].Text + "'");

                    FlagsShared.RequestSavePersistentData = true;

                    return;
                }
            }

            SharedHelper.LogError("Joke '" + Name + "' not found in SetJokeAsUsed!");
        }
示例#14
0
        private Queue <string> GenerateSuggestions()
        {
            #region Update suggstions based on new information

            allSuggestions.Clear();

            ProbVariables.PrintSuggestionsProbabilities();

            var Suggestion = CategoricalF(

                //Multiple times
                ItemProb(SuggestionsEnum.ListenToSong, ProbVariables.Bot.PrSuggestListenToSong),

                //Can be multiple times
                ItemProb(SuggestionsEnum.TellJoke, SharedHelper.GetProb(ProbVariables.Bot.TellJoke)),     //we can say several jokes in a row, no need to reduce the probability of saying a joke

                //A few times per evening
                ItemProb(SuggestionsEnum.GoOut, SharedHelper.GetProb(ProbVariables.Bot.SuggestGoOut)),

                //A few times per evening
                ItemProb(SuggestionsEnum.WatchMovie, SharedHelper.GetProb(ProbVariables.Bot.SuggestToWatchMovie)),

                //NOT USED!
                //Once per Morning (current day) / evening (tomorrow)
                //ItemProb(Suggestions.TellWeatherForecast, ProbVariables.PrTellWeatherForecast),

                ItemProb(SuggestionsEnum.DoSport, SharedHelper.GetProb(ProbVariables.Bot.SuggestDoSport))

                ).Normalize();

            SharedHelper.Log("Suggestion Histogram:\r\n" + Suggestion.Histogram());

            var suggestionDist = Suggestion.ToSampleDist();

            for (var i = 0; i < 100; i++)
            {
                string sample = suggestionDist.Sample();

                allSuggestions.Enqueue(sample);
            }
            #endregion

            return(allSuggestions);
        }
示例#15
0
        //public override void Add(Item fact)
        //{
        //    //check if ID already exists
        //    bool existsAlready = list.Any(cus => cus.Name == fact.Name);

        //    if (existsAlready)
        //        SharedHelper.Log("Pure Fact with this Name already exists: '" + fact.Name + "'. Second one was ignored.");
        //    else
        //    list.Add((PureFact)fact);
        //}

        //public override PureFact[] GetAll()
        //{
        //    return list.ToArray();
        //}

        //public static void SetAsUsed(string name)
        //{
        //    SetAsUsed(name, true);
        //}

        //public static void SetAsUsed(string name, bool isUsed)
        //{
        //    for (int i = 0; i < list.Count; i++)
        //    {
        //        if (list[i].Name == name)
        //        {
        //            SharedHelper.Log("Set used to " + isUsed + " : " + list[i].Name);
        //            list[i].IsUsed = isUsed;

        //            return;
        //        }
        //    }

        //    SharedHelper.LogError("Pure Fact Name '" + name + "' not found in SetAsUsed!");
        //}

        public void MarkForSaving(string name)
        {
            SharedHelper.Log("Marking for saving: " + name);

            for (int i = 0; i < items.Count; i++)
            {
                if (items[i].Name == name)
                {
                    if (items[i].Name != "UserMovieYesterday")
                    {
                        FlagsShared.RequestSavePersistentData = true;
                    }

                    return;
                }
            }

            SharedHelper.LogError("Pure Fact Name '" + name + "'not found in MarkForSaving!");
        }
示例#16
0
        public bool ModelUpdate(TimeSpan timeSinceStart, bool isPureFactUpdated, bool isUncertainFactUpdated)
        {
            bool regenerationRequested = false;

            if (!isInitialized)
            {
                SharedHelper.LogError("Not initialized."); return(regenerationRequested);
            }

            //Execute triggers that perform inference and update probabilistic variables
            foreach (var trigger in ModelTriggers)
            {
                int oldExecuteCount = trigger.TriggeredCount;

                if (
                    (trigger is IModelUpdateTrigger)
                    &&
                    (
                        (trigger.IsTimeBased || (isPureFactUpdated && trigger.IsUserResponseBased))
                        &&
                        ((trigger.IsOneTimeTrigger && trigger.TriggeredCount == 0) || !trigger.IsOneTimeTrigger)

                    )
                    )
                {
                    //Updating model
                    regenerationRequested = ((IModelUpdateTrigger)trigger).Process(isPureFactUpdated, timeSinceStart, this);

                    if (trigger.TriggeredCount > oldExecuteCount)
                    {
                        SharedHelper.Log("Trigger executed: '" + trigger.ToString() + "'");
                    }
                }
            }

            if (isUncertainFactUpdated)
            {
                regenerationRequested = true;
            }

            return(regenerationRequested);
        }
示例#17
0
        public void InteractionsUpdate(TimeSpan timeSinceStart, int interactionsDoneSinceStart, ref Queue <CommItem> interactions)
        {
            if (!isInitialized)
            {
                SharedHelper.LogError("Not initialized."); return;
            }

            //Evaluate triggers that represent 'Surprise' for example
            //These triggers evaluate a model and add a new interaction
            foreach (var trigger in ModelTriggers)
            {
                int oldExecuteCount = trigger.TriggeredCount;

                if (trigger is IModelEvaluateTrigger &&
                    (
                        (trigger.IsOneTimeTrigger && trigger.TriggeredCount == 0)
                        ||
                        (!trigger.IsOneTimeTrigger)
                    )
                    )
                {
                    CommItem?newInteraction = ((IModelEvaluateTrigger)trigger).Process(this);

                    if (newInteraction != null)
                    {
                        if (interactions.Peek().Name != newInteraction.Value.Name)
                        {
                            KorraModelHelper.InsertFirstInteractionList(ref interactions, newInteraction.Value);

                            //TODO: this custom code should be moved to another place
                            if (trigger is VideoGameSurpriseTrigger)
                            {
                                FlagsShared.RequestSurpriseExpression = true;
                            }

                            SharedHelper.Log("Trigger executed: '" + trigger.ToString() + "'");
                        }
                    }
                }
            }
        }
示例#18
0
        public static void AddInteractionTimeElapsed(string category, float time)
        {
            bool categoryExists = averageTimeOfInteractionPerCategory.Exists(x => x.Item1 == category);

            if (!categoryExists)
            {
                averageTimeOfInteractionPerCategory.Add(new Tuple <string, float, int>(category, time, 1));
            }
            else
            {
                var itemOld = averageTimeOfInteractionPerCategory.First(x => x.Item1 == category);

                //Calculate Incremental Averaging : https://math.stackexchange.com/questions/106700/incremental-averageing
                Tuple <string, float, int> itemNew = new Tuple <string, float, int>(category, itemOld.Item2 + (time - itemOld.Item2) / (itemOld.Item3 + 1), itemOld.Item3 + 1);

                averageTimeOfInteractionPerCategory.Remove(itemOld);
                averageTimeOfInteractionPerCategory.Add(itemNew);
            }

            SharedHelper.Log("The elapsed time of an interaction of type '" + category + "' is: " + time);
        }
示例#19
0
文件: Items.cs 项目: toncho11/KorraAI
        public void LoadAll(ItemManager[] providers)
        {
            this.providers = providers;

            LoadAllPureFacts();
            LoadAllUncertainFacts();

            LoadAllJokes(); //PureFacts must be already loaded because some PureFacts are used as jokes
            LoadAllSongs();
            LoadSports();
            LoadMovies();

            int count = UncertainFacts.GetList().Count
                        + JokesProvider.GetAll().Count();

            foreach (var manager in providers)
            {
                count += manager.Count();
            }

            SharedHelper.Log("All items loaded: " + count + " " + BotConfigShared.Language);
        }
示例#20
0
        public static void RemoveInteraction(ref List <CommItem> list, int position, ItemManager[] managers)
        {
            if (position < list.Count)
            {
                CommItem tobeRemoved = list[position];

                ItemManager manager = managers.SingleOrDefault(x => x.Is(tobeRemoved));

                if (manager != null)
                {
                    list.RemoveAt(position);
                    manager.SetAsPlanned(tobeRemoved.Name, false);
                    SharedHelper.Log("Interaction removed: " + tobeRemoved.Name);
                }
                else
                {
                    SharedHelper.LogError("Could not remove interaction from list:" + tobeRemoved.Name + " " + tobeRemoved.Category + " " + tobeRemoved.SubCategory);
                }
            }
            else
            {
                SharedHelper.LogError("Could not remove interaction at position: " + position);
            }
        }
示例#21
0
        public bool Process(bool isPureFactUpdated, TimeSpan timeSinceStart, IKorraAIModel model)
        {
            //SharedHelper.LogWarning("Inside movies trigger");
            #region Get Fact Manager
            PureFacts pfManager = (PureFacts)model.ItemProviders.SingleOrDefault(x => x is PureFacts);
            if (pfManager == null)
            {
                SharedHelper.LogError("No manager in Process in MoviesModelUpdateTrigger.");
                return(false);
            }
            #endregion

            var context = model.GetContext();

            PureFact factJob = (PureFact)pfManager.GetByName("UserHasJob");
            PureFact factWatchedMovieYesterday = (PureFact)pfManager.GetByName("UserMovieYesterday");

            if (factJob == null || factWatchedMovieYesterday == null)
            {
                SharedHelper.LogError("factJob or factWatchedMovieYesterday is NULL in MoviesModelUpdateTrigger.");
            }

            if (!IsTimeOfDayUpdated && !isPureFactUpdated)
            {
                return(false);
            }

            SharedHelper.Log("Inside MoviesModelUpdateTrigger");

            var oldSuggestToWatchMovie = SharedHelper.GetProb(ProbVariables.Bot.SuggestToWatchMovie).Value;

            //TODO: this model can be replaced by a Bayesian network, because of the too many IFs

            //if no job or weekend
            if ((factJob.IsAnswered && context.BasePhrases.IsNo(factJob.Value)) || StatesShared.IsWeekend)
            {
                ProbVariables.Bot.SuggestToWatchMovie = BernoulliF(Prob(0.18));
                //KorraBaseHelper.Log("Prob SuggestToWatchMovie changed to: 0.18, no job or weekend");
            }
            else if (factJob.IsAnswered && context.BasePhrases.IsYes(factJob.Value)) //if has job
            {
                #region working and evening
                if (StatesShared.IsEvening /*TODO: or after work hours*/)
                {
                    //has NOT watched movie yesterday (is working and evening)
                    if (factWatchedMovieYesterday.IsAnswered && context.BasePhrases.IsNo(factJob.Value))
                    {
                        ProbVariables.Bot.SuggestToWatchMovie = BernoulliF(Prob(0.18));
                        //KorraBaseHelper.Log("Prob SuggestToWatchMovie changed to: 0.18, evening");
                    }
                    //has watched movie yesterday (is working and evening)
                    else if (factWatchedMovieYesterday.IsAnswered && context.BasePhrases.IsYes(factJob.Value))
                    {
                        ProbVariables.Bot.SuggestToWatchMovie = BernoulliF(Prob(0.12));
                        // KorraBaseHelper.Log("Prob SuggestToWatchMovie changed to: 0.12. Watched movie yesterday.");
                    }
                }
                #endregion
                else //is working and not evening, no time because working and not evening
                {
                    ProbVariables.Bot.SuggestToWatchMovie = BernoulliF(Prob(0.05));
                    //KorraBaseHelper.Log("Prob SuggestToWatchMovie changed to: 0.05");
                }
            }
            else //has job is unknown
            {
                ProbVariables.Bot.SuggestToWatchMovie = BernoulliF(Prob(0.10));
            }

            double newSuggestToWatchMovie = SharedHelper.GetProb(ProbVariables.Bot.SuggestToWatchMovie).Value;

            if (Math.Abs(oldSuggestToWatchMovie - newSuggestToWatchMovie) > (1 / 1000))
            {
                executedCount = executedCount + 1;

                SharedHelper.Log("Prob SuggestToWatchMovie changed from " + oldSuggestToWatchMovie + " to: " + SharedHelper.GetProb(ProbVariables.Bot.SuggestToWatchMovie));
                //return new ModelUpdateTriggerReturn { IsTriggered = true, IsResamplingRequired = true, Value = "" };
                return(true); //re-sampling requested
            }
            else
            {
                return(false); //no re-sampling
            }
        }