Moved values into config

moved code to more appropriate locations
Reduced duplicate code
Added comments
This commit is contained in:
Dev 2024-10-17 10:27:37 +01:00
parent 3d4c7795f7
commit eb6e61c1f0
4 changed files with 79 additions and 41 deletions

View File

@ -1,6 +1,7 @@
{
"acceleration": 7,
"weather": {
"generateWeatherAmountHours": 24,
"clouds": {
"values": [-1.5, -1, 0, 0.5, 1, 1.5],
"weights": [60, 50, 15, 5, 4, 3]
@ -36,7 +37,11 @@
"pressure": {
"min": 760,
"max": 764
}
},
"timePeriod": {
"values": [15, 30],
"weights": [1, 2]
}
},
"seasonDates": [
{

View File

@ -6,7 +6,7 @@ import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig";
export interface IWeatherConfig extends IBaseConfig {
kind: "spt-weather";
acceleration: number;
weather: Weather;
weather: IWeatherValues;
seasonDates: ISeasonDateTimes[];
overrideSeason?: Season;
}
@ -20,7 +20,9 @@ export interface ISeasonDateTimes {
endMonth: number;
}
export interface Weather {
export interface IWeatherValues {
/** How many hours to generate weather data into the future */
generateWeatherAmountHours: number;
clouds: WeatherSettings<string>;
windSpeed: WeatherSettings<number>;
windDirection: WeatherSettings<WindDirection>;
@ -30,6 +32,8 @@ export interface Weather {
fog: WeatherSettings<string>;
temp: MinMax;
pressure: MinMax;
/** Length of each weather period */
timePeriod: WeatherSettings<number>;
}
export interface WeatherSettings<T> {

View File

@ -1,4 +1,5 @@
import { WeatherGenerator } from "@spt/generators/WeatherGenerator";
import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper";
import { IWeather } from "@spt/models/eft/weather/IWeatherData";
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
import { IWeatherConfig } from "@spt/models/spt/config/IWeatherConfig";
@ -18,6 +19,7 @@ export class RaidWeatherService {
@inject("DatabaseService") protected databaseService: DatabaseService,
@inject("TimeUtil") protected timeUtil: TimeUtil,
@inject("WeatherGenerator") protected weatherGenerator: WeatherGenerator,
@inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper,
@inject("ConfigServer") protected configServer: ConfigServer,
) {
this.weatherConfig = this.configServer.getConfig(ConfigTypes.WEATHER);
@ -25,62 +27,67 @@ export class RaidWeatherService {
this.generateWeather();
}
/**
* Generate 24 hours of weather data starting from midnight today
*/
public generateWeather() {
// When to start generating weather from
const staringTimestamp = this.getLastFullHourTimestamp();
// When to start generating weather from in milliseconds
const staringTimestampMs = this.timeUtil.getTodaysMidnightTimestamp();
// How far into future do we generate weather
const futureTimestampToReach = staringTimestamp + this.timeUtil.getHoursAsSeconds(24) * 1000; // TODO move 24 to config
const futureTimestampToReachMs =
staringTimestampMs +
this.timeUtil.getHoursAsSeconds(this.weatherConfig.weather.generateWeatherAmountHours) * 1000; // Convert to milliseconds
// Keep adding new weather until we have reached desired future date
let nextTimestamp = staringTimestamp;
while (nextTimestamp <= futureTimestampToReach) {
const newWeather = this.weatherGenerator.generateWeather(nextTimestamp);
this.logger.warning(`Handling ${new Date(nextTimestamp)}`);
let nextTimestampMs = staringTimestampMs;
while (nextTimestampMs <= futureTimestampToReachMs) {
const newWeather = this.weatherGenerator.generateWeather(nextTimestampMs);
this.logger.warning(`Handling ${new Date(nextTimestampMs)}`);
this.weatherForecast.push(newWeather);
nextTimestamp += 30 * 60 * 1000; // TODO move to config
nextTimestampMs += this.getWeightedWeatherTimePeriodMs();
}
}
protected getLastFullHourTimestamp() {
const now = new Date();
let hours = now.getHours();
const minutes = now.getMinutes();
protected getWeightedWeatherTimePeriodMs(): number {
const chosenTimePeriodMinutes = this.weightedRandomHelper.weightedRandom(
this.weatherConfig.weather.timePeriod.values,
this.weatherConfig.weather.timePeriod.weights,
).item;
// If minutes are greater than 0, subtract 1 hour to get last full hour
if (minutes > 0) {
hours--;
}
// Create a new Date object with the last full hour, 0 minutes, and 0 seconds
const lastFullHour = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hours, 0, 0);
// Return timestamp of last full hour
return lastFullHour.getTime();
return chosenTimePeriodMinutes * 60 * 1000; // Convert to milliseconds
}
/**
* Find the first matching weather object that applies to the current time
*/
public getCurrentWeather(): IWeather {
// Clear expired weather data
this.weatherForecast = this.weatherForecast.filter((x) => x.timestamp < this.timeUtil.getTimestamp());
// return first weather object that is greater than/equal to now
const result = this.weatherForecast.find((x) => x.timestamp >= this.timeUtil.getTimestamp());
if (!result) {
this.generateWeather();
}
this.validateWeatherDataExists();
return this.weatherForecast.find((x) => x.timestamp >= this.timeUtil.getTimestamp());
}
/**
* Find the first matching weather object that applies to the current time + all following weather data generated
*/
public getUpcomingWeather(): IWeather[] {
// Clear expired weather data
this.weatherForecast = this.weatherForecast.filter((x) => x.timestamp < this.timeUtil.getTimestamp());
// return first weather object that is greater than/equal to now
const result = this.weatherForecast.filter((x) => x.timestamp >= this.timeUtil.getTimestamp());
if (result.length === 0) {
this.generateWeather();
}
this.validateWeatherDataExists();
return this.weatherForecast.filter((x) => x.timestamp >= this.timeUtil.getTimestamp());
}
/**
* Ensure future weather data exists
*/
protected validateWeatherDataExists() {
// Clear expired weather data
this.weatherForecast = this.weatherForecast.filter((x) => x.timestamp < this.timeUtil.getTimestamp());
// Check data exists for current time
const result = this.weatherForecast.filter((x) => x.timestamp >= this.timeUtil.getTimestamp());
if (result.length === 0) {
// TODO - replace with better check, if < 1 hours worth of data exists?
this.generateWeather();
}
}
}

View File

@ -138,4 +138,26 @@ export class TimeUtil {
(60 - now.getMinutes()) * 60 * 1000 - now.getSeconds() * 1000 - now.getMilliseconds();
return (now.getTime() + millisecondsUntilNextHour) / 1000;
}
/**
* Returns the current days timestamp at 00:00
* e.g. current time: 13th march 14:22 will return 13th march 00:00
* @returns Timestamp
*/
public getTodaysMidnightTimestamp(): number {
const now = new Date();
let hours = now.getHours();
const minutes = now.getMinutes();
// If minutes greater than 0, subtract 1 hour to get last full hour
if (minutes > 0) {
hours--;
}
// Create a new Date object with the last full hour, 0 minutes, and 0 seconds
const lastFullHour = new Date(now.getFullYear(), now.getMonth(), now.getDate(), hours, 0, 0);
// Return above as timestamp
return lastFullHour.getTime();
}
}