diff --git a/Core/Controllers/WeatherController.cs b/Core/Controllers/WeatherController.cs index db582754..c80d6f1d 100644 --- a/Core/Controllers/WeatherController.cs +++ b/Core/Controllers/WeatherController.cs @@ -1,19 +1,65 @@ using Core.Annotations; +using Core.Generators; +using Core.Helpers; using Core.Models.Eft.Weather; +using Core.Models.Enums; +using Core.Models.Spt.Config; using Core.Models.Spt.Weather; +using Core.Servers; +using Core.Services; namespace Core.Controllers; [Injectable] public class WeatherController { + private readonly ILogger _logger; + private readonly WeatherGenerator _weatherGenerator; + private readonly SeasonalEventService _seasonalEventService; + private readonly RaidWeatherService _raidWeatherService; + private readonly WeatherHelper _weatherHelper; + private readonly ConfigServer _configServer; + + private readonly WeatherConfig _weatherConfig; + + public WeatherController( + ILogger logger, + WeatherGenerator weatherGenerator, + SeasonalEventService seasonalEventService, + RaidWeatherService raidWeatherService, + WeatherHelper weatherHelper, + ConfigServer configServer + ) + { + _logger = logger; + _weatherGenerator = weatherGenerator; + _seasonalEventService = seasonalEventService; + _raidWeatherService = raidWeatherService; + _weatherHelper = weatherHelper; + _configServer = configServer; + + _weatherConfig = _configServer.GetConfig(ConfigTypes.WEATHER); + } + /// /// Handle client/weather /// /// public WeatherData Generate() { - throw new NotImplementedException(); + var result = new WeatherData + { + Acceleration = 0, + Time = "", + Date = "", + Weather = null, + Season = Season.AUTUMN + }; + + _weatherGenerator.CalculateGameTime(result); + result.Weather = _weatherGenerator.GenerateWeather(result.Season.Value); + + return result; } /// @@ -23,6 +69,14 @@ public class WeatherController /// public GetLocalWeatherResponseData GenerateLocal(string sessionId) { - throw new NotImplementedException(); + var result = new GetLocalWeatherResponseData() + { + Season = (int)_seasonalEventService.GetActiveWeatherSeason(), + Weather = [] + }; + + result.Weather.AddRange(_raidWeatherService.GetUpcomingWeather()); + + return result; } } diff --git a/Core/Generators/WeatherGenerator.cs b/Core/Generators/WeatherGenerator.cs index dc1d7114..8631667a 100644 --- a/Core/Generators/WeatherGenerator.cs +++ b/Core/Generators/WeatherGenerator.cs @@ -1,15 +1,36 @@ -using Core.Annotations; +using Core.Annotations; +using Core.Helpers; using Core.Models.Eft.Weather; using Core.Models.Enums; using Core.Models.Spt.Config; +using Core.Servers; +using Core.Services; +using Core.Utils; namespace Core.Generators; [Injectable] public class WeatherGenerator { - public WeatherGenerator() + private readonly TimeUtil _timeUtil; + private readonly SeasonalEventService _seasonalEventService; + private readonly WeatherHelper _weatherHelper; + private readonly ConfigServer _configServer; + + private readonly WeatherConfig _weatherConfig; + + public WeatherGenerator( + TimeUtil timeUtil, + SeasonalEventService seasonalEventService, + WeatherHelper weatherHelper, + ConfigServer configServer) { + _timeUtil = timeUtil; + _seasonalEventService = seasonalEventService; + _weatherHelper = weatherHelper; + _configServer = configServer; + + _weatherConfig = _configServer.GetConfig(ConfigTypes.WEATHER); } /** @@ -17,9 +38,16 @@ public class WeatherGenerator * @param data Weather data * @returns WeatherData */ - public WeatherData CalculateGameTime(WeatherData data) + public void CalculateGameTime(WeatherData data) { - throw new NotImplementedException(); + var computedDate = new DateTime(); + var formattedDate = this._timeUtil.FormatDate(computedDate); + + data.Date = formattedDate; + data.Time = GetBsgFormattedInRaidTime(); + data.Acceleration = this._weatherConfig.Acceleration; + + data.Season = this._seasonalEventService.GetActiveWeatherSeason(); } /** @@ -30,7 +58,9 @@ public class WeatherGenerator */ protected string GetBsgFormattedInRaidTime() { - throw new NotImplementedException(); + var clientAcceleratedDate = this._weatherHelper.GetInRaidTime(); + + return GetBsgFormattedTime(clientAcceleratedDate); } /** @@ -40,7 +70,7 @@ public class WeatherGenerator */ protected string GetBsgFormattedTime(DateTime date) { - throw new NotImplementedException(); + return _timeUtil.FormatTime(date).Replace("-", ":").Replace("-", ":"); } /** @@ -49,14 +79,20 @@ public class WeatherGenerator * @param timestamp OPTIONAL what timestamp to generate the weather data at, defaults to now when not supplied * @returns Randomised weather data */ - public Weather GenerateWeather(Season currentSeason, int? timestamp = null) + public Weather GenerateWeather(Season currentSeason, long? timestamp = null) { throw new NotImplementedException(); } protected SeasonalValues GetWeatherValuesBySeason(Season currentSeason) { - throw new NotImplementedException(); + var result = this._weatherConfig.Weather.SeasonValues.TryGetValue(currentSeason.ToString(), out var value); + if (!result) + { + return this._weatherConfig.Weather.SeasonValues["default"]; + } + + return value; } /** diff --git a/Core/Helpers/WeightedRandomHelper.cs b/Core/Helpers/WeightedRandomHelper.cs index cc7eedf0..090186fe 100644 --- a/Core/Helpers/WeightedRandomHelper.cs +++ b/Core/Helpers/WeightedRandomHelper.cs @@ -1,4 +1,4 @@ -using Core.Annotations; +using Core.Annotations; namespace Core.Helpers; @@ -33,8 +33,9 @@ public class WeightedRandomHelper /// List of items /// List of weights /// Dictionary with item and index - public Dictionary WeightedRandom(List items, List weights) + public object WeightedRandom(List items, List weights) { + // TODO - create return type { item: any; index: number } throw new NotImplementedException(); } diff --git a/Core/Services/RaidWeatherService.cs b/Core/Services/RaidWeatherService.cs index 9e94e567..ce07588b 100644 --- a/Core/Services/RaidWeatherService.cs +++ b/Core/Services/RaidWeatherService.cs @@ -1,26 +1,86 @@ -using Core.Annotations; +using Core.Annotations; +using Core.Generators; +using Core.Helpers; using Core.Models.Eft.Weather; using Core.Models.Enums; +using Core.Models.Spt.Config; +using Core.Servers; +using Core.Utils; namespace Core.Services; [Injectable(InjectionType.Singleton)] public class RaidWeatherService { + private readonly ILogger _logger; + private readonly DatabaseService _databaseService; + private readonly TimeUtil _timeUtil; + private readonly WeatherGenerator _weatherGenerator; + private readonly SeasonalEventService _seasonalEventService; + private readonly WeightedRandomHelper _weightedRandomHelper; + private readonly ConfigServer _configServer; + + private readonly List _weatherForecast = []; + + private readonly WeatherConfig _weatherConfig; + + public RaidWeatherService( + ILogger logger, + DatabaseService databaseService, + TimeUtil timeUtil, + WeatherGenerator weatherGenerator, + SeasonalEventService seasonalEventService, + WeightedRandomHelper weightedRandomHelper, + ConfigServer configServer) + { + _logger = logger; + _databaseService = databaseService; + _timeUtil = timeUtil; + _weatherGenerator = weatherGenerator; + _seasonalEventService = seasonalEventService; + _weightedRandomHelper = weightedRandomHelper; + _configServer = configServer; + + _weatherConfig = _configServer.GetConfig(ConfigTypes.WEATHER); + } + /// /// Generate 24 hours of weather data starting from midnight today /// public void GenerateWeather(Season currentSeason) { - throw new NotImplementedException(); + // When to start generating weather from in milliseconds + var staringTimestampMs = _timeUtil.GetTodayMidnightTimeStamp(); + + // How far into future do we generate weather + var futureTimestampToReachMs = staringTimestampMs + _timeUtil.GetHoursAsSeconds(_weatherConfig.Weather.GenerateWeatherAmountHours) * 1000; // Convert to milliseconds + + // Keep adding new weather until we have reached desired future date + var nextTimestampMs = staringTimestampMs; + while (nextTimestampMs <= futureTimestampToReachMs) + { + var newWeatherToAddToCache = _weatherGenerator.GenerateWeather(currentSeason, nextTimestampMs); + + // Add generated weather for time period to cache + _weatherForecast.Add(newWeatherToAddToCache); + + // Increment timestamp so next loop can begin at correct time + nextTimestampMs += GetWeightedWeatherTimePeriodMs(); + } } /// - /// Get a time period to increment by, e.g 15 or 30 minutes as milliseconds + /// Get a time period to increment by, e.g. 15 or 30 minutes as milliseconds /// /// milliseconds protected long GetWeightedWeatherTimePeriodMs() { + //var chosenTimePeriodMinutes = _weightedRandomHelper.WeightedRandom( + // _weatherConfig.Weather.TimePeriod.Values, + // _weatherConfig.Weather.TimePeriod.Weights).Item; + + //return chosenTimePeriodMinutes * 60 * 1000; // Convert to milliseconds + throw new NotImplementedException(); } @@ -29,15 +89,21 @@ public class RaidWeatherService /// public Weather GetCurrentWeather() { - throw new NotImplementedException(); + var currentSeason = _seasonalEventService.GetActiveWeatherSeason(); + ValidateWeatherDataExists(currentSeason); + + return _weatherForecast.Find((weather) => weather.Timestamp >= _timeUtil.GetTimeStamp()); } /// - /// Find the first matching weather object that applies to the current time + all following weather data generated + /// Find all matching weather objects that applies to the current time + future /// - public List GetUpcomingWeather() + public IEnumerable GetUpcomingWeather() { - throw new NotImplementedException(); + var currentSeason = _seasonalEventService.GetActiveWeatherSeason(); + ValidateWeatherDataExists(currentSeason); + + return _weatherForecast.Where((weather) => weather.Timestamp >= _timeUtil.GetTimeStamp()); } /// @@ -45,6 +111,15 @@ public class RaidWeatherService /// protected void ValidateWeatherDataExists(Season currentSeason) { - throw new NotImplementedException(); + // Clear expired weather data + _weatherForecast.RemoveAll(weather => weather.Timestamp < _timeUtil.GetTimeStamp()); + + // Check data exists for current time + var result = _weatherForecast.Where((weather) => weather.Timestamp >= _timeUtil.GetTimeStamp()); + if (!result.Any()) + { + GenerateWeather(currentSeason); + } + } } diff --git a/Core/Utils/TimeUtil.cs b/Core/Utils/TimeUtil.cs index 29a98d9f..16440e2b 100644 --- a/Core/Utils/TimeUtil.cs +++ b/Core/Utils/TimeUtil.cs @@ -1,4 +1,4 @@ -using Core.Annotations; +using Core.Annotations; namespace Core.Utils; @@ -149,7 +149,7 @@ public class TimeUtil /// e.g. current time: 13th March 14:22 will return 13th March 00:00 /// /// Timestamp - public long GetTodayMidNightTimeStamp() + public long GetTodayMidnightTimeStamp() { var now = DateTime.UtcNow; @@ -175,4 +175,4 @@ public class TimeUtil { return number.ToString().PadLeft(2, '0'); } -} \ No newline at end of file +}