Beispiel #1
0
        private List <T> WeightedDataSelect <T>(List <T> source_data_list, HashSet <T> currentPSData, int nToSelect, DbTables table, SelectionSeverity severity) where T : IData
        {
            // Given a (filtered) list of data, select some using weights
            List <ScoreData> score_data_list = dbManager.FindScoreDataByQuery("SELECT * FROM ScoreData WHERE TableName = '" + table.ToString() + "'");

            string debugString = "-- Teacher Selection Weights";

            List <float> weights_list = new List <float>();

            foreach (var sourceData in source_data_list)
            {
                float cumulativeWeight = 0;
                debugString += "\n" + sourceData.GetId() + " ---";

                // Get score data
                var   score_data         = score_data_list.Find(x => x.ElementId == sourceData.GetId());
                float currentScore       = 0;
                int   daysSinceLastScore = 0;
                if (score_data != null)
                {
                    var timespanFromLastScoreToNow = GenericUtilities.GetTimeSpanBetween(score_data.LastAccessTimestamp, GenericUtilities.GetTimestampForNow());
                    daysSinceLastScore = timespanFromLastScoreToNow.Days;
                    currentScore       = score_data.Score;
                }
                //UnityEngine.Debug.Log("Data " + id + " score: " + currentScore + " days " + daysSinceLastScore);

                // Score Weight [0,1]: higher the lower the score [-1,1] is
                var scoreWeight = 0.5f * (1 - currentScore);
                cumulativeWeight += scoreWeight * ConfigAI.data_scoreWeight;
                debugString      += " \tScore: " + scoreWeight * ConfigAI.data_scoreWeight + "(" + scoreWeight + ")";

                // RecentPlay Weight  [1,0]: higher the more in the past we saw that data
                const float dayLinerWeightDecrease = 1f / ConfigAI.daysForMaximumRecentPlayMalus;
                float       weightMalus            = daysSinceLastScore * dayLinerWeightDecrease;
                float       recentPlayWeight       = 1f - UnityEngine.Mathf.Min(1, weightMalus);
                cumulativeWeight += recentPlayWeight * ConfigAI.data_recentPlayWeight;
                debugString      += " \tRecent: " + recentPlayWeight * ConfigAI.data_recentPlayWeight + "(" + recentPlayWeight + ")";

                // Current focus weight [1,0]: higher if the data is part of the current play session
                float currentPlaySessionWeight = currentPSData.Contains(sourceData) ? 1 : 0f;
                cumulativeWeight += currentPlaySessionWeight * ConfigAI.data_currentPlaySessionWeight;
                debugString      += " \tCurrentPS: " + currentPlaySessionWeight * ConfigAI.data_currentPlaySessionWeight + "(" + currentPlaySessionWeight + ")";

                // If the cumulative weight goes to the negatives, we give it a fixed weight
                if (cumulativeWeight <= 0)
                {
                    cumulativeWeight = ConfigAI.data_minimumTotalWeight;
                    continue;
                }

                // Save cumulative weight
                weights_list.Add(cumulativeWeight);
                debugString += " TOTw: " + cumulativeWeight;
            }

            if (ConfigAI.verboseDataSelection)
            {
                UnityEngine.Debug.Log(debugString);
            }

            // Select data from the list
            List <T> selected_data_list = new List <T>();

            if (source_data_list.Count > 0)
            {
                int      nToSelectFromCurrentList = 0;
                List <T> chosenData = null;
                switch (severity)
                {
                case SelectionSeverity.AsManyAsPossible:
                case SelectionSeverity.AllRequired:
                    nToSelectFromCurrentList = UnityEngine.Mathf.Min(source_data_list.Count, nToSelect);
                    chosenData = RandomHelper.RouletteSelectNonRepeating(source_data_list, weights_list, nToSelectFromCurrentList);
                    selected_data_list.AddRange(chosenData);
                    break;

                case SelectionSeverity.MayRepeatIfNotEnough:
                    int nRemainingToSelect = nToSelect;
                    while (nRemainingToSelect > 0)
                    {
                        var listCopy = new List <T>(source_data_list);
                        nToSelectFromCurrentList = UnityEngine.Mathf.Min(source_data_list.Count, nRemainingToSelect);
                        chosenData = RandomHelper.RouletteSelectNonRepeating(listCopy, weights_list, nToSelectFromCurrentList);
                        selected_data_list.AddRange(chosenData);
                        nRemainingToSelect -= nToSelectFromCurrentList;
                    }
                    break;
                }
            }
            return(selected_data_list);
        }
Beispiel #2
0
        private List <Db.MiniGameData> PerformSelection_Random(Db.PlaySessionData playSessionData, int numberToSelect)
        {
            // Get all minigames ids for the given playsession (from PlaySessionData)
            // ... also, keep the weights around
            Dictionary <MiniGameCode, float> playsession_weights_dict = new Dictionary <MiniGameCode, float>();
            List <string> minigame_id_list = new List <string>();

            foreach (var minigameInPlaySession in playSessionData.Minigames)
            {
                minigame_id_list.Add(minigameInPlaySession.MiniGameCode.ToString());
                playsession_weights_dict[minigameInPlaySession.MiniGameCode] = minigameInPlaySession.Weight;
            }

            // Get all minigame data, filter by availability (from the static DB)
            List <Db.MiniGameData> minigame_data_list = dbManager.FindMiniGameData(x => x.Available && minigame_id_list.Contains(x.GetId()));

            // Create the weights list too
            List <float> weights_list = new List <float>(minigame_data_list.Count);

            // Retrieve the current score data (state) for each minigame (from the dynamic DB)
            List <Db.ScoreData> minigame_score_list = dbManager.FindScoreDataByQuery("SELECT * FROM ScoreData WHERE TableName = 'MiniGames'");

            //UnityEngine.Debug.Log("M GAME SCORE LIST: " + minigame_score_list.Count);
            //foreach(var l in minigame_score_list) UnityEngine.Debug.Log(l.ElementId);

            // Determine the final weight for each minigame
            string debugString = "----- TEACHER: MiniGameSelection ----- \n";

            foreach (var minigame_data in minigame_data_list)
            {
                float cumulativeWeight   = 0;
                var   minigame_scoredata = minigame_score_list.Find(x => x.ElementId == minigame_data.GetId());
                int   daysSinceLastScore = 0;
                if (minigame_scoredata != null)
                {
                    var timespanFromLastScoreToNow = GenericUtilities.GetTimeSpanBetween(minigame_scoredata.LastAccessTimestamp, GenericUtilities.GetTimestampForNow());
                    daysSinceLastScore = timespanFromLastScoreToNow.Days;
                }
                debugString += minigame_data.Code + " --- \t";

                // PlaySession Weight [0,1]
                float playSessionWeight = playsession_weights_dict[minigame_data.Code] / 100f; //  [0-100]
                cumulativeWeight += playSessionWeight * ConfigAI.minigame_playSessionWeight;
                debugString      += " PSw: " + playSessionWeight * ConfigAI.minigame_playSessionWeight + "(" + playSessionWeight + ")";

                // RecentPlay Weight  [1,0]
                const float dayLinerWeightDecrease = 1f / ConfigAI.daysForMaximumRecentPlayMalus;
                float       weightMalus            = daysSinceLastScore * dayLinerWeightDecrease;
                float       recentPlayWeight       = 1f - UnityEngine.Mathf.Min(1, weightMalus);
                cumulativeWeight += recentPlayWeight * ConfigAI.minigame_recentPlayWeight;
                debugString      += " RPw: " + recentPlayWeight * ConfigAI.minigame_recentPlayWeight + "(" + recentPlayWeight + ")";

                // Save cumulative weight
                weights_list.Add(cumulativeWeight);
                debugString += " TOTw: " + cumulativeWeight;
                debugString += "\n";
            }
            if (ConfigAI.verboseTeacher)
            {
                UnityEngine.Debug.Log(debugString);
            }


            // Number checks
            int actualNumberToSelect = UnityEngine.Mathf.Min(numberToSelect, minigame_data_list.Count);

            if (minigame_data_list.Count == 0)
            {
                throw new System.Exception("Cannot find even a single minigame for play session " + playSessionData.Id);
            }
            if (numberToSelect > minigame_data_list.Count)
            {
                UnityEngine.Debug.LogWarning("Could not select the requested number of " + numberToSelect + " minigames for play session " + playSessionData.Id + " (only " + minigame_data_list.Count + " are available)");
            }

            // Choose N minigames based on these weights
            var selectedMiniGameData = RandomHelper.RouletteSelectNonRepeating(minigame_data_list, weights_list, actualNumberToSelect);

            return(selectedMiniGameData);
        }