diff --git a/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs b/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs index cc9375df..37f47302 100644 --- a/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs +++ b/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs @@ -28,7 +28,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// The maximum value (optional). /// If max is exclusive or not. /// A random integer between the specified minimum and maximum values. - public int GetInt(int min, int max = int.MaxValue, bool exclusive = false) + public virtual int GetInt(int min, int max = int.MaxValue, bool exclusive = false) { // Prevents a potential integer overflow. if (exclusive && max == int.MaxValue) @@ -45,7 +45,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// The minimum value of the range (inclusive). /// The maximum value of the range (exclusive). /// A random floating-point number between `min` (inclusive) and `max` (exclusive). - public double GetDouble(double min, double max) + public virtual double GetDouble(double min, double max) { var realMin = (long)(min * DecimalPointRandomPrecisionMultiplier); var realMax = (long)(max * DecimalPointRandomPrecisionMultiplier); @@ -60,12 +60,12 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// Generates a random boolean value. /// /// A random boolean value, where the probability of `true` and `false` is approximately equal. - public bool GetBool() + public virtual bool GetBool() { return Random.Next(0, 2) == 1; } - public void NextBytes(Span bytes) + public virtual void NextBytes(Span bytes) { Random.Shared.NextBytes(bytes); } @@ -77,7 +77,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// The number to calculate the percentage of. /// The number of decimal places to round the result to (default is 2). /// The calculated percentage of the given number, rounded to the specified number of decimal places. - public double GetPercentOfValue(double percent, double number, int toFixed = 2) + public virtual double GetPercentOfValue(double percent, double number, int toFixed = 2) { var num = percent * (number / 100); @@ -90,7 +90,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// The original number to be reduced. /// The percentage by which to reduce the number. /// The reduced number after applying the percentage reduction. - public double ReduceValueByPercent(double number, double percentage) + public virtual double ReduceValueByPercent(double number, double percentage) { var reductionAmount = number * percentage / 100; @@ -102,7 +102,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// /// The percentage chance (0-100) that the event will occur. /// `true` if the event occurs, `false` otherwise. - public bool GetChance100(double? chancePercent) + public virtual bool GetChance100(double? chancePercent) { chancePercent = Math.Clamp(chancePercent ?? 0, 0D, 100D); @@ -115,7 +115,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// /// The collection of strings to select a random value from. /// A randomly selected string from the array. - public T GetCollectionValue(IEnumerable collection) + public virtual T GetCollectionValue(IEnumerable collection) { // We can call `count` directly if it's a list if (collection is IList list) @@ -144,7 +144,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// Type of key /// Type of Value /// A random TKey representing one of the keys of the dictionary. - public TKey GetKey(Dictionary dictionary) + public virtual TKey GetKey(Dictionary dictionary) where TKey : notnull { return GetCollectionValue(dictionary.Keys); @@ -157,7 +157,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// Type of key /// Type of Value /// A random TVal representing one of the values of the dictionary. - public TVal GetVal(Dictionary dictionary) + public virtual TVal GetVal(Dictionary dictionary) where TKey : notnull { return GetCollectionValue(dictionary.Values); @@ -175,7 +175,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// If the generated number is less than 0, it will recursively attempt to generate a valid number up to 100 times. /// If it fails to generate a valid number after 100 attempts, it will return a random float between 0.01 and twice the mean. /// - public double GetNormallyDistributedRandomNumber(double mean, double sigma, int attempt = 0) + public virtual double GetNormallyDistributedRandomNumber(double mean, double sigma, int attempt = 0) { double u, v; @@ -211,7 +211,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// The lower bound of the range (inclusive). /// The upper bound of the range (exclusive). If not provided, the range will be from 0 to `low`. /// A random integer within the specified range. - public int RandInt(int low, int? high = null) + public virtual int RandInt(int low, int? high = null) { // Return a random integer from 0 to low if high is not provided if (high is null) @@ -233,7 +233,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// and MaxSignificantDigits(15), inclusive. If not provided, precision is determined by the input values. /// /// - public double RandNum(double val1, double val2 = 0, int precision = DecimalPointRandomPrecision) + public virtual double RandNum(double val1, double val2 = 0, int precision = DecimalPointRandomPrecision) { if (!double.IsFinite(val1) || !double.IsFinite(val2)) { @@ -262,7 +262,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// Whether to draw with replacement. Defaults to true. /// The type of elements in the list. /// A List containing the drawn elements. - public List DrawRandomFromList( + public virtual List DrawRandomFromList( List originalList, int count = 1, bool replacement = true @@ -307,7 +307,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// The type of elements in keys /// The type of elements in values /// A list of randomly drawn keys from the dictionary. - public List DrawRandomFromDict( + public virtual List DrawRandomFromDict( Dictionary dict, int count = 1, bool replacement = true @@ -327,7 +327,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// The bias shift to apply to the random number generation. /// The number of iterations to use for generating a Gaussian random number. /// A biased random number within the specified range. - public double GetBiasedRandomNumber(double min, double max, double shift, double n) + public virtual double GetBiasedRandomNumber(double min, double max, double shift, double n) { // This function generates a random number based on a gaussian distribution with an option to add a bias via shifting. @@ -408,7 +408,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// The list to shuffle. /// The type of elements in the list. /// The shuffled list. - public List Shuffle(List originalList) + public virtual List Shuffle(List originalList) { var currentIndex = originalList.Count; @@ -444,7 +444,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// /// The number to analyze. /// The number of decimal places, or 0 if none exist. - public int GetNumberPrecision(double num) + public virtual int GetNumberPrecision(double num) { var preciseNum = (decimal)num; var factor = 0; @@ -457,7 +457,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) return factor; } - public T? GetArrayValue(IEnumerable list) + public virtual T? GetArrayValue(IEnumerable list) { return GetCollectionValue(list); } @@ -468,7 +468,7 @@ public class RandomUtil(ISptLogger _logger, ICloner _cloner) /// Percentage chance roll should success /// scale of chance to allow support of numbers > 1-100 /// true if success - public bool RollChance(double chance, double scale = 1) + public virtual bool RollChance(double chance, double scale = 1) { return GetInt(1, (int)(100 * scale)) / (1 * scale) <= chance; } diff --git a/UnitTests/DI.cs b/UnitTests/DI.cs index e0e9a7b8..6b1b4d47 100644 --- a/UnitTests/DI.cs +++ b/UnitTests/DI.cs @@ -1,4 +1,7 @@ using Microsoft.Extensions.DependencyInjection; +using SPTarkov.DI; +using SPTarkov.Server.Core.DI; +using SPTarkov.Server.Core.Models.Spt.Mod; using SPTarkov.Server.Core.Models.Utils; using SPTarkov.Server.Core.Utils; using SPTarkov.Server.Core.Utils.Cloners; @@ -21,17 +24,22 @@ public class DI } var services = new ServiceCollection(); - var jsonUtil = new JsonUtil([new SptJsonConverterRegistrator()]); - var mathUtil = new MathUtil(); - services.AddSingleton(jsonUtil); - services.AddSingleton(mathUtil); - services.AddSingleton(); - services.AddSingleton, MockLogger>(); - services.AddSingleton(); - services.AddSingleton(); + var diHandler = new DependencyInjectionHandler(services); + + diHandler.AddInjectableTypesFromTypeAssembly(typeof(App)); + diHandler.AddInjectableTypesFromTypeList([typeof(MockLogger<>)/* TODO: this needs to be enabled but the randomizer needs to NOT be random, typeof(MockRandomUtil)*/]); + + diHandler.InjectAll(); + + services.AddSingleton>(_ => []); _serviceProvider = services.BuildServiceProvider(); + + foreach (var onLoad in _serviceProvider.GetServices()) + { + onLoad.OnLoad().Wait(); + } } public static T GetService() diff --git a/UnitTests/Mock/MockLogger.cs b/UnitTests/Mock/MockLogger.cs index a0cd3705..66547480 100644 --- a/UnitTests/Mock/MockLogger.cs +++ b/UnitTests/Mock/MockLogger.cs @@ -16,7 +16,7 @@ public class MockLogger : ISptLogger Exception? ex = null ) { - throw new NotImplementedException(); + Console.WriteLine(data); } public void Success(string data, Exception? ex = null) diff --git a/UnitTests/Mock/MockRandomUtil.cs b/UnitTests/Mock/MockRandomUtil.cs new file mode 100644 index 00000000..fc66c1d4 --- /dev/null +++ b/UnitTests/Mock/MockRandomUtil.cs @@ -0,0 +1,121 @@ +using SPTarkov.DI.Annotations; +using SPTarkov.Server.Core.Models.Utils; +using SPTarkov.Server.Core.Utils; +using SPTarkov.Server.Core.Utils.Cloners; + +namespace UnitTests.Mock; + +[Injectable(TypeOverride = typeof(RandomUtil))] +public class MockRandomUtil(ISptLogger _logger, ICloner _cloner) : RandomUtil(_logger, _cloner) +{ + public override int GetInt(int min, int max = Int32.MaxValue, bool exclusive = false) + { + return min; + } + + public override double GetDouble(double min, double max) + { + return min; + } + + public override bool GetBool() + { + return true; + } + + public override void NextBytes(Span bytes) + { + // TODO: No idea what this does + base.NextBytes(bytes); + } + + public override double GetPercentOfValue(double percent, double number, int toFixed = 2) + { + // TODO: No idea what this does + return base.GetPercentOfValue(percent, number, toFixed); + } + + public override double ReduceValueByPercent(double number, double percentage) + { + // TODO: No idea what this does + return base.ReduceValueByPercent(number, percentage); + } + + public override bool GetChance100(double? chancePercent) + { + return true; + } + + public override T GetCollectionValue(IEnumerable collection) + { + if (!collection.Any()) + { + throw new InvalidOperationException("Sequence contains no elements."); + } + + return collection.First(); + } + + public override TKey GetKey(Dictionary dictionary) + { + return GetCollectionValue(dictionary.Keys); + } + + public override TVal GetVal(Dictionary dictionary) + { + return GetCollectionValue(dictionary.Values); + } + + public override double GetNormallyDistributedRandomNumber(double mean, double sigma, int attempt = 0) + { + // TODO: No idea what to do with this + return base.GetNormallyDistributedRandomNumber(mean, sigma, attempt); + } + + public override int RandInt(int low, int? high = null) + { + return low; + } + + public override double RandNum(double val1, double val2 = 0, int precision = 6) + { + return val1; + } + + public override List DrawRandomFromList(List originalList, int count = 1, bool replacement = true) + { + return originalList.Slice(0, count); + } + + public override List DrawRandomFromDict(Dictionary dict, int count = 1, bool replacement = true) + { + // TODO: derandomize + return base.DrawRandomFromDict(dict, count, replacement); + } + + public override double GetBiasedRandomNumber(double min, double max, double shift, double n) + { + return min; + } + + public override List Shuffle(List originalList) + { + return originalList; + } + + public override int GetNumberPrecision(double num) + { + // TODO: derandomize + return base.GetNumberPrecision(num); + } + + public override T? GetArrayValue(IEnumerable list) where T : default + { + return GetCollectionValue(list); + } + + public override bool RollChance(double chance, double scale = 1) + { + return true; + } +} diff --git a/UnitTests/Tests/Test.cs b/UnitTests/Tests/Test.cs deleted file mode 100644 index 51063fce..00000000 --- a/UnitTests/Tests/Test.cs +++ /dev/null @@ -1,29 +0,0 @@ -using SPTarkov.Server.Core.Models.Spt.Templates; -using SPTarkov.Server.Core.Utils; -using UnitTests.Mock; - -namespace UnitTests.Tests; - -[TestClass] -public class Test -{ - private Templates? _templates; - - [TestInitialize] - public async Task Setup() - { - var importer = new ImporterUtil( - new MockLogger(), - new FileUtil(), - DI.GetService() - ); - _templates = await importer.LoadRecursiveAsync("./TestAssets/"); - } - - [TestMethod] - public void TestMethod1() - { - var result = DI.GetService().Serialize(_templates); - Console.WriteLine(result); - } -}