Seasonal weather types per theater.

Adjusts the weather conditions per theater and  per season.
This commit is contained in:
Magnus Wolffelt 2021-07-31 12:57:23 +02:00 committed by GitHub
parent f5dea4935c
commit 4c51b4b822
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 346 additions and 66 deletions

View File

@ -51,6 +51,7 @@ from .controlpoint import (
MissionTarget,
OffMapSpawn,
)
from .seasonalconditions import SeasonalConditions
from .frontline import FrontLine
from .landmap import Landmap, load_landmap, poly_contains
from .latlon import LatLon
@ -527,17 +528,6 @@ class ReferencePoint:
image_coordinates: Point
@dataclass(frozen=True)
class SeasonalConditions:
# Units are inHg and degrees Celsius
# Future improvement: add clouds/precipitation
summer_avg_pressure: float
winter_avg_pressure: float
summer_avg_temperature: float
winter_avg_temperature: float
temperature_day_night_difference: float
class ConflictTheater:
terrain: Terrain
@ -799,13 +789,9 @@ class CaucasusTheater(ConflictTheater):
@property
def seasonal_conditions(self) -> SeasonalConditions:
return SeasonalConditions(
summer_avg_pressure=30.02, # TODO: More science
winter_avg_pressure=29.72, # TODO: More science
summer_avg_temperature=22.5,
winter_avg_temperature=3.0,
temperature_day_night_difference=6.0,
)
from .seasonalconditions.caucasus import CONDITIONS
return CONDITIONS
@property
def projection_parameters(self) -> TransverseMercator:
@ -831,13 +817,9 @@ class PersianGulfTheater(ConflictTheater):
@property
def seasonal_conditions(self) -> SeasonalConditions:
return SeasonalConditions(
summer_avg_pressure=29.98, # TODO: More science
winter_avg_pressure=29.80, # TODO: More science
summer_avg_temperature=32.5,
winter_avg_temperature=15.0,
temperature_day_night_difference=2.0,
)
from .seasonalconditions.persiangulf import CONDITIONS
return CONDITIONS
@property
def projection_parameters(self) -> TransverseMercator:
@ -863,13 +845,9 @@ class NevadaTheater(ConflictTheater):
@property
def seasonal_conditions(self) -> SeasonalConditions:
return SeasonalConditions(
summer_avg_pressure=30.02, # TODO: More science
winter_avg_pressure=29.72, # TODO: More science
summer_avg_temperature=31.5,
winter_avg_temperature=5.0,
temperature_day_night_difference=6.0,
)
from .seasonalconditions.nevada import CONDITIONS
return CONDITIONS
@property
def projection_parameters(self) -> TransverseMercator:
@ -895,13 +873,9 @@ class NormandyTheater(ConflictTheater):
@property
def seasonal_conditions(self) -> SeasonalConditions:
return SeasonalConditions(
summer_avg_pressure=30.02, # TODO: More science
winter_avg_pressure=29.72, # TODO: More science
summer_avg_temperature=20.0,
winter_avg_temperature=0.0,
temperature_day_night_difference=5.0,
)
from .seasonalconditions.normandy import CONDITIONS
return CONDITIONS
@property
def projection_parameters(self) -> TransverseMercator:
@ -927,13 +901,9 @@ class TheChannelTheater(ConflictTheater):
@property
def seasonal_conditions(self) -> SeasonalConditions:
return SeasonalConditions(
summer_avg_pressure=30.02, # TODO: More science
winter_avg_pressure=29.72, # TODO: More science
summer_avg_temperature=20.0,
winter_avg_temperature=0.0,
temperature_day_night_difference=5.0,
)
from .seasonalconditions.thechannel import CONDITIONS
return CONDITIONS
@property
def projection_parameters(self) -> TransverseMercator:
@ -959,13 +929,9 @@ class SyriaTheater(ConflictTheater):
@property
def seasonal_conditions(self) -> SeasonalConditions:
return SeasonalConditions(
summer_avg_pressure=29.98, # TODO: More science
winter_avg_pressure=29.86, # TODO: More science
summer_avg_temperature=28.5,
winter_avg_temperature=10.0,
temperature_day_night_difference=8.0,
)
from .seasonalconditions.syria import CONDITIONS
return CONDITIONS
@property
def projection_parameters(self) -> TransverseMercator:
@ -988,13 +954,9 @@ class MarianaIslandsTheater(ConflictTheater):
@property
def seasonal_conditions(self) -> SeasonalConditions:
return SeasonalConditions(
summer_avg_pressure=30.02, # TODO: More science
winter_avg_pressure=29.82, # TODO: More science
summer_avg_temperature=28.0,
winter_avg_temperature=27.0,
temperature_day_night_difference=1.0,
)
from .seasonalconditions.marianaislands import CONDITIONS
return CONDITIONS
@property
def projection_parameters(self) -> TransverseMercator:

View File

@ -0,0 +1 @@
from .seasonalconditions import *

View File

@ -0,0 +1,36 @@
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
CONDITIONS = SeasonalConditions(
summer_avg_pressure=30.02, # TODO: Find real-world data
winter_avg_pressure=29.72, # TODO: Find real-world data
summer_avg_temperature=22.5,
winter_avg_temperature=3.0,
temperature_day_night_difference=6.0,
weather_type_chances={
# TODO: Find real-world data for all these values
Season.Winter: WeatherTypeChances(
thunderstorm=1,
raining=20,
cloudy=60,
clear_skies=20,
),
Season.Spring: WeatherTypeChances(
thunderstorm=1,
raining=20,
cloudy=40,
clear_skies=40,
),
Season.Summer: WeatherTypeChances(
thunderstorm=1,
raining=10,
cloudy=30,
clear_skies=60,
),
Season.Fall: WeatherTypeChances(
thunderstorm=1,
raining=30,
cloudy=50,
clear_skies=20,
),
},
)

View File

@ -0,0 +1,38 @@
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
CONDITIONS = SeasonalConditions(
summer_avg_pressure=30.02, # TODO: Find real-world data
winter_avg_pressure=29.82, # TODO: Find real-world data
summer_avg_temperature=28.0,
winter_avg_temperature=27.0,
temperature_day_night_difference=1.0,
weather_type_chances={
# TODO: Find real-world data for all these values
Season.Winter: WeatherTypeChances(
thunderstorm=2,
raining=20,
cloudy=40,
clear_skies=40,
),
Season.Spring: WeatherTypeChances(
# Spring is dry/sunny in Marianas
thunderstorm=1,
raining=10,
cloudy=30,
clear_skies=60,
),
Season.Summer: WeatherTypeChances(
thunderstorm=2,
raining=20,
cloudy=40,
clear_skies=40,
),
Season.Fall: WeatherTypeChances(
# Rain season
thunderstorm=5,
raining=45,
cloudy=30,
clear_skies=20,
),
},
)

View File

@ -0,0 +1,36 @@
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
CONDITIONS = SeasonalConditions(
summer_avg_pressure=30.02, # TODO: Find real-world data
winter_avg_pressure=29.72, # TODO: Find real-world data
summer_avg_temperature=31.5,
winter_avg_temperature=5.0,
temperature_day_night_difference=6.0,
weather_type_chances={
# TODO: Find real-world data for all these values
Season.Winter: WeatherTypeChances(
thunderstorm=1,
raining=10,
cloudy=50,
clear_skies=40,
),
Season.Spring: WeatherTypeChances(
thunderstorm=1,
raining=5,
cloudy=45,
clear_skies=50,
),
Season.Summer: WeatherTypeChances(
thunderstorm=1,
raining=5,
cloudy=25,
clear_skies=70,
),
Season.Fall: WeatherTypeChances(
thunderstorm=1,
raining=10,
cloudy=45,
clear_skies=45,
),
},
)

View File

@ -0,0 +1,36 @@
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
CONDITIONS = SeasonalConditions(
summer_avg_pressure=30.02, # TODO: Find real-world data
winter_avg_pressure=29.72, # TODO: Find real-world data
summer_avg_temperature=20.0,
winter_avg_temperature=0.0,
temperature_day_night_difference=5.0,
weather_type_chances={
# TODO: Find real-world data for all these values
Season.Winter: WeatherTypeChances(
thunderstorm=1,
raining=20,
cloudy=60,
clear_skies=20,
),
Season.Spring: WeatherTypeChances(
thunderstorm=1,
raining=20,
cloudy=40,
clear_skies=40,
),
Season.Summer: WeatherTypeChances(
thunderstorm=1,
raining=10,
cloudy=30,
clear_skies=60,
),
Season.Fall: WeatherTypeChances(
thunderstorm=1,
raining=30,
cloudy=50,
clear_skies=20,
),
},
)

View File

@ -0,0 +1,37 @@
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
CONDITIONS = SeasonalConditions(
summer_avg_pressure=29.98, # TODO: Find real-world data
winter_avg_pressure=29.80, # TODO: Find real-world data
summer_avg_temperature=32.5,
winter_avg_temperature=15.0,
temperature_day_night_difference=2.0,
weather_type_chances={
# TODO: Find real-world data for all these values
Season.Winter: WeatherTypeChances(
# Winter there is some rain in PG (Dubai)
thunderstorm=1,
raining=15,
cloudy=35,
clear_skies=50,
),
Season.Spring: WeatherTypeChances(
thunderstorm=1,
raining=2,
cloudy=18,
clear_skies=80,
),
Season.Summer: WeatherTypeChances(
thunderstorm=1,
raining=1,
cloudy=8,
clear_skies=90,
),
Season.Fall: WeatherTypeChances(
thunderstorm=1,
raining=2,
cloudy=18,
clear_skies=80,
),
},
)

View File

@ -0,0 +1,48 @@
import datetime
from dataclasses import dataclass
from enum import Enum
class Season(Enum):
Winter = "winter"
Spring = "spring"
Summer = "summer"
Fall = "fall"
def determine_season(day: datetime.date) -> Season:
# Note: This logic doesn't need to be very precise
# Currently refers strictly to northern-hemisphere seasons
day_of_year = day.timetuple().tm_yday
season_length = 365.0 / 4
winter_end_day = season_length / 2
if day_of_year < winter_end_day:
return Season.Winter
elif day_of_year < winter_end_day + season_length:
return Season.Spring
elif day_of_year < winter_end_day + season_length * 2:
return Season.Summer
elif day_of_year < winter_end_day + season_length * 3:
return Season.Fall
else:
return Season.Winter
@dataclass(frozen=True)
class WeatherTypeChances:
thunderstorm: float
raining: float
cloudy: float
clear_skies: float
@dataclass(frozen=True)
class SeasonalConditions:
# Units are inHg and degrees Celsius
summer_avg_pressure: float
winter_avg_pressure: float
summer_avg_temperature: float
winter_avg_temperature: float
temperature_day_night_difference: float
weather_type_chances: dict[Season, WeatherTypeChances]

View File

@ -0,0 +1,36 @@
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
CONDITIONS = SeasonalConditions(
summer_avg_pressure=29.98, # TODO: Find real-world data
winter_avg_pressure=29.86, # TODO: Find real-world data
summer_avg_temperature=28.5,
winter_avg_temperature=10.0,
temperature_day_night_difference=8.0,
weather_type_chances={
# TODO: Find real-world data for all these values
Season.Winter: WeatherTypeChances(
thunderstorm=1,
raining=25,
cloudy=25,
clear_skies=50,
),
Season.Spring: WeatherTypeChances(
thunderstorm=1,
raining=10,
cloudy=30,
clear_skies=60,
),
Season.Summer: WeatherTypeChances(
thunderstorm=1,
raining=3,
cloudy=20,
clear_skies=77,
),
Season.Fall: WeatherTypeChances(
thunderstorm=1,
raining=10,
cloudy=30,
clear_skies=60,
),
},
)

View File

@ -0,0 +1,36 @@
from .seasonalconditions import SeasonalConditions, Season, WeatherTypeChances
CONDITIONS = SeasonalConditions(
summer_avg_pressure=30.02, # TODO: Find real-world data
winter_avg_pressure=29.72, # TODO: Find real-world data
summer_avg_temperature=20.0,
winter_avg_temperature=0.0,
temperature_day_night_difference=5.0,
weather_type_chances={
# TODO: Find real-world data for all these values
Season.Winter: WeatherTypeChances(
thunderstorm=1,
raining=20,
cloudy=60,
clear_skies=20,
),
Season.Spring: WeatherTypeChances(
thunderstorm=1,
raining=20,
cloudy=40,
clear_skies=40,
),
Season.Summer: WeatherTypeChances(
thunderstorm=1,
raining=10,
cloudy=30,
clear_skies=60,
),
Season.Fall: WeatherTypeChances(
thunderstorm=1,
raining=30,
cloudy=50,
clear_skies=20,
),
},
)

View File

@ -14,9 +14,11 @@ from game.savecompat import has_save_compat_for
from game.settings import Settings
from game.utils import Distance, Heading, meters, interpolate, Pressure, inches_hg
from game.theater.seasonalconditions import determine_season
if TYPE_CHECKING:
from game.theater import ConflictTheater
from game.theater.conflicttheater import SeasonalConditions
from game.theater.seasonalconditions import SeasonalConditions
class TimeOfDay(Enum):
@ -119,10 +121,18 @@ class Weather:
temperature -= seasonal_conditions.temperature_day_night_difference / 2
pressure += self.pressure_adjustment
temperature += self.temperature_adjustment
logging.debug(
"Weather: Before random: temp {} press {}".format(temperature, pressure)
)
conditions = AtmosphericConditions(
qnh=self.random_pressure(pressure),
temperature_celsius=self.random_temperature(temperature),
)
logging.debug(
"Weather: After random: temp {} press {}".format(
conditions.temperature_celsius, conditions.qnh.pressure_in_inches_hg
)
)
return conditions
@property
@ -334,14 +344,18 @@ class Conditions:
day: datetime.date,
time_of_day: TimeOfDay,
) -> Weather:
# Future improvement: use seasonal weights for theaters
season = determine_season(day)
logging.debug("Weather: Season {}".format(season))
weather_chances = seasonal_conditions.weather_type_chances[season]
chances = {
Thunderstorm: 1,
Raining: 20,
Cloudy: 60,
ClearSkies: 20,
Thunderstorm: weather_chances.thunderstorm,
Raining: weather_chances.raining,
Cloudy: weather_chances.cloudy,
ClearSkies: weather_chances.clear_skies,
}
logging.debug("Weather: Chances {}".format(weather_chances))
weather_type = random.choices(
list(chances.keys()), weights=list(chances.values())
)[0]
logging.debug("Weather: Type {}".format(weather_type))
return weather_type(seasonal_conditions, day, time_of_day)