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); }
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); }