From 44ee0f11d536bcbc1bdf87f179baac8dd039dfc6 Mon Sep 17 00:00:00 2001 From: Chomp Date: Sun, 12 Jan 2025 16:37:28 +0000 Subject: [PATCH] Expanded `WeightedRandom()` and `GetWeightedWeatherTimePeriodMs()` implementation --- Core/Helpers/WeightedRandomHelper.cs | 51 +++++++++++++++++-- Core/Models/Spt/Config/WeatherConfig.cs | 6 +-- .../Models/Spt/Helper/WeightedRandomResult.cs | 7 +++ Core/Services/RaidWeatherService.cs | 10 ++-- 4 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 Core/Models/Spt/Helper/WeightedRandomResult.cs diff --git a/Core/Helpers/WeightedRandomHelper.cs b/Core/Helpers/WeightedRandomHelper.cs index 090186fe..4bbf62b1 100644 --- a/Core/Helpers/WeightedRandomHelper.cs +++ b/Core/Helpers/WeightedRandomHelper.cs @@ -1,12 +1,17 @@ using Core.Annotations; +using Core.Models.Spt.Helper; namespace Core.Helpers; [Injectable] public class WeightedRandomHelper { - public WeightedRandomHelper() + private readonly ILogger _logger; + + public WeightedRandomHelper( + ILogger logger) { + _logger = logger; } /// @@ -33,10 +38,48 @@ public class WeightedRandomHelper /// List of items /// List of weights /// Dictionary with item and index - public object WeightedRandom(List items, List weights) + public WeightedRandomResult WeightedRandom(List items, List weights) { - // TODO - create return type { item: any; index: number } - throw new NotImplementedException(); + if (items.Count == 0) + { + _logger.LogError("Items must not be empty"); + } + + if (weights.Count == 0) + { + _logger.LogError("Item weights must not be empty"); + } + + if (items.Count != weights.Count) + { + _logger.LogError("Items and weight inputs must be of the same length"); + } + + // Preparing the cumulative weights list. + List cumulativeWeights = []; + for (var i = 0; i < weights.Count; i++) + { + cumulativeWeights.Add(weights[i] + (i > 0 ? cumulativeWeights[i - 1] : 0)); + } + + // Getting the random number in a range of [0...sum(weights)] + int maxCumulativeWeight = cumulativeWeights[cumulativeWeights.Count - 1]; + double randomNumber = maxCumulativeWeight * new Random().NextDouble(); + + // Picking the random item based on its weight. + for (int itemIndex = 0; itemIndex < items.Count; itemIndex++) + { + if (cumulativeWeights[itemIndex] >= randomNumber) + { + return new WeightedRandomResult() + { + Item = items[itemIndex], + Index = itemIndex, + }; + } + } + + throw new InvalidOperationException("No item was picked."); } /// diff --git a/Core/Models/Spt/Config/WeatherConfig.cs b/Core/Models/Spt/Config/WeatherConfig.cs index 3f8f1478..aa553dd7 100644 --- a/Core/Models/Spt/Config/WeatherConfig.cs +++ b/Core/Models/Spt/Config/WeatherConfig.cs @@ -1,4 +1,4 @@ -using System.Text.Json.Serialization; +using System.Text.Json.Serialization; using Core.Models.Common; using Core.Models.Enums; using Core.Utils.Json.Converters; @@ -107,5 +107,5 @@ public class WeatherSettings public List Values { get; set; } [JsonPropertyName("weights")] - public List Weights { get; set; } -} \ No newline at end of file + public List Weights { get; set; } +} diff --git a/Core/Models/Spt/Helper/WeightedRandomResult.cs b/Core/Models/Spt/Helper/WeightedRandomResult.cs new file mode 100644 index 00000000..a9532f59 --- /dev/null +++ b/Core/Models/Spt/Helper/WeightedRandomResult.cs @@ -0,0 +1,7 @@ +namespace Core.Models.Spt.Helper; + +public class WeightedRandomResult +{ + public T Item { get; set; } + public int Index { get; set; } +} diff --git a/Core/Services/RaidWeatherService.cs b/Core/Services/RaidWeatherService.cs index ce07588b..992bd6ae 100644 --- a/Core/Services/RaidWeatherService.cs +++ b/Core/Services/RaidWeatherService.cs @@ -75,13 +75,11 @@ public class RaidWeatherService /// milliseconds protected long GetWeightedWeatherTimePeriodMs() { - //var chosenTimePeriodMinutes = _weightedRandomHelper.WeightedRandom( - // _weatherConfig.Weather.TimePeriod.Values, - // _weatherConfig.Weather.TimePeriod.Weights).Item; + var chosenTimePeriodMinutes = _weightedRandomHelper.WeightedRandom( + _weatherConfig.Weather.TimePeriod.Values, + _weatherConfig.Weather.TimePeriod.Weights).Item; - //return chosenTimePeriodMinutes * 60 * 1000; // Convert to milliseconds - - throw new NotImplementedException(); + return chosenTimePeriodMinutes * 60 * 1000; // Convert to milliseconds } ///