;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;   Modular Simulator Controller System - Weather Notifications           ;;;
;;;                                                                         ;;;
;;;   Author:     Oliver Juwig (TheBigO)                                    ;;;
;;;   License:    (2026) Creative Commons - BY-NC-SA                        ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;-------------------------------------------------------------------------;;;
;;;                            Rule Include Section                         ;;;
;;;-------------------------------------------------------------------------;;;

#Include %kResourcesDirectory%Rules\Tyre Information Retrieval.rules
#Include %kResourcesDirectory%Rules\Session Information Retrieval.rules
#Include %kResourcesDirectory%Rules\Weather Information Retrieval.rules


;;;-------------------------------------------------------------------------;;;
;;;                            Public Rules Section                         ;;;
;;;-------------------------------------------------------------------------;;;

priority: 5, {Any: [?Weather.Weather.Now], {None: [?Weather.Weather.Now.Index]}} => (Prove: updateWeatherIndex(Now))
priority: 5, {Any: [?Weather.Weather.10Min], {None: [?Weather.Weather.10Min.Index]}} => (Prove: updateWeatherIndex(10Min))
priority: 5, {Any: [?Weather.Weather.30Min], {None: [?Weather.Weather.30Min.Index]}} => (Prove: updateWeatherIndex(30Min))

updateWeatherIndex(?time) <= Get(Weather.Weather, ?time, ?weather), weatherIndex(?weather, ?index), Set(Weather.Weather, ?time, Index, ?index)

priority: 5, {Any: [?Track.Grip], {None: [?Track.Grip.Index]}} => (Prove: updateGripIndex())

updateGripIndex() <= gripIndex(!Track.Grip, ?index), Set(Track.Grip.Index, ?index)

priority: 2,
	{All: [?Lap > 0], [?Tyre.Compound = Dry], {None: [?Weather.Tyre.Change.Recommended]}} =>
		(Set: Weather.Tyre.Compound.Target, Dry), (Set: Weather.Tyre.Compound.Color.Target, !Tyre.Compound.Color)
priority: 1,
	{All: [?Lap > 0], [?Tyre.Compound = Dry], {None: [?Weather.Tyre.Change.Recommended]},
		  {Prove: availableTyreCompound(Intermediate, ?)},
		  {Any: [?Weather.Weather.10Min = Drizzle], [?Weather.Weather.10Min = LightRain]},
		  [?Track.Grip.Index > 2]} =>
		(Prove: weatherTyreChangeRecommendation(!Lap, ?Weather.Weather.10Min, 10, Intermediate))
priority: 1,
	{All: [?Lap > 0], [?Tyre.Compound = Dry], {None: [?Weather.Tyre.Change.Recommended]},
		  {Prove: availableTyreCompound(Wet, ?)},
		  [?Weather.Weather.10Min != Dry], [?Track.Grip.Index > 3],
		  {None: {Prove: availableTyreCompound(Intermediate, ?)}}} =>
		(Prove: weatherTyreChangeRecommendation(!Lap, ?Weather.Weather.10Min, 10, Wet))
priority: 1,
	{All: [?Lap > 0], [?Tyre.Compound = Dry], {None: [?Weather.Tyre.Change.Recommended]},
		  {Prove: availableTyreCompound(Wet, ?)}, [?Weather.Weather.10Min.Index >= 4],
		  [?Track.Grip.Index > 3]} =>
		(Prove: weatherTyreChangeRecommendation(!Lap, ?Weather.Weather.10Min, 10, Wet))
; priority: 1,
;	{All: [?Lap > 0], [?Tyre.Compound = Dry],
;		  {Any: [?Weather.Weather.10Min = Dry],
;				{All: [?Weather.Weather.10Min = Drizzle], {None: {Prove: availableTyreCompound(Intermediate, ?)}}},
;				{All: {None: {Prove: availableTyreCompound(Intermediate, ?)}}, {None: {Prove: availableTyreCompound(Wet, ?)}}}}} =>
;			(Set: Weather.Tyre.Compound.Target, Dry), (Set: Weather.Tyre.Compound.Color.Target, !Tyre.Compound.Color)

priority: 2,
	{All: [?Lap > 0], [?Tyre.Compound = Intermediate], {None: [?Weather.Tyre.Change.Recommended]}} =>
		(Set: Weather.Tyre.Compound.Target, Intermediate), (Set: Weather.Tyre.Compound.Color.Target, !Tyre.Compound.Color)		
priority: 1,
	{All: [?Lap > 0], [?Tyre.Compound = Intermediate], {None: [?Weather.Tyre.Change.Recommended]},
		  {Prove: availableTyreCompound(Dry, ?)}, [?Weather.Weather.10Min = Dry],
		  [?Track.Grip.Index < 5]} =>
		(Prove: weatherTyreChangeRecommendation(!Lap, ?Weather.Weather.10Min, 10, Dry))
priority: 1,
	{All: [?Lap > 0], [?Tyre.Compound = Intermediate], {None: [?Weather.Tyre.Change.Recommended]},
		  {Prove: availableTyreCompound(Wet, ?)}, [?Weather.Weather.10Min.Index >= 4],
		  [?Track.Grip.Index > 4]} =>
		(Prove: weatherTyreChangeRecommendation(!Lap, ?Weather.Weather.10Min, 10, Wet))
; priority: 1,
;	{All: [?Lap > 0], [?Tyre.Compound = Intermediate],
;		  {Any: [?Weather.Weather.10Min = Drizzle], [?Weather.Weather.10Min = LightRain],
;				{All: [?Weather.Weather.10Min = Dry], {None: {Prove: availableTyreCompound(Dry, ?)}}},
;				{All: [?Weather.Weather.10Min.Index >= 4],
;					  {None: {Prove: availableTyreCompound(Wet, ?)}}}}} =>
;			(Set: Weather.Tyre.Compound.Target, Intermediate), (Set: Weather.Tyre.Compound.Color.Target, !Tyre.Compound.Color)

priority: 2,
	{All: [?Lap > 0], [?Tyre.Compound = Wet], {None: [?Weather.Tyre.Change.Recommended]}} =>
		(Set: Weather.Tyre.Compound.Target, Wet), (Set: Weather.Tyre.Compound.Color.Target, !Tyre.Compound.Color)		
priority: 1,
	{All: [?Lap > 0], [?Tyre.Compound = Wet], {None: [?Weather.Tyre.Change.Recommended]},
		  {Prove: availableTyreCompound(Dry, ?)}, [?Weather.Weather.10Min = Dry],
		  [?Track.Grip.Index < 6]} =>
		(Prove: weatherTyreChangeRecommendation(!Lap, ?Weather.Weather.10Min, 10, Dry))
priority: 1,
	{All: [?Lap > 0], [?Tyre.Compound = Wet], {None: [?Weather.Tyre.Change.Recommended]},
		  {Prove: availableTyreCompound(Intermediate, ?)},
		  {Any: [?Weather.Weather.10Min = Drizzle], [?Weather.Weather.10Min = LightRain],
		  [?Track.Grip.Index < 6]}} =>
		(Prove: weatherTyreChangeRecommendation(!Lap, ?Weather.Weather.10Min, 10, Intermediate))
priority: 1,
	{All: [?Lap > 0], [?Tyre.Compound = Wet], {None: [?Weather.Tyre.Change.Recommended]},
		  {None: {Prove: availableTyreCompound(Intermediate, ?)}},
		  [?Weather.Weather.10Min = Drizzle], [?Track.Grip.Index < 5]} =>
		(Prove: weatherTyreChangeRecommendation(!Lap, ?Weather.Weather.10Min, 10, Dry))
; priority: 1,
;	{All: [?Lap > 0], [?Tyre.Compound = Wet],
;		  {Any: [?Weather.Weather.10Min.Index >= 4],
;		        {All: {None: {Prove: availableTyreCompound(Intermediate, ?)}}, [?Weather.Weather.10Min = LightRain]},
;				{All: {None: {Prove: availableTyreCompound(Dry, ?)}}, {None: {Prove: availableTyreCompound(Intermediate, ?)}}}}} =>
;		(Set: Weather.Tyre.Compound.Target, Wet), (Set: Weather.Tyre.Compound.Color.Target, !Tyre.Compound.Color)

{All: [?Lap > 1], [?Tyre.Compound = Dry],
	  {Any: {All: {None: [?Weather.Change.Notified]}, [?Weather.Weather.Now.Index <= 2], [?Weather.Weather.30Min.Index >= 3]},
			[?Weather.Change.Notified < ?Weather.Weather.30Min.Index]}} =>
		(Prove: weatherForecastNotification(?Lap, !Weather.Weather.30Min, 30))
{All: [?Lap > 1], [?Tyre.Compound = Intermediate],
	  {Any: {All: {None: [?Weather.Change.Notified]},
				  {Any: [?Weather.Weather.Now = Drizzle], [?Weather.Weather.Now = LightRain]},
				  {Any: [?Weather.Weather.30Min = Dry], [?Weather.Weather.30Min.Index >= 4]}},
			[?Weather.Change.Notified > ?Weather.Weather.30Min.Index]}} =>
		(Prove: weatherForecastNotification(?Lap, !Weather.Weather.30Min, 30))
{All: [?Lap > 1], [?Tyre.Compound = Wet],
	  {Any: {All: {None: [?Weather.Change.Notified]}, [?Weather.Weather.Now.Index >= 3], [?Weather.Weather.30Min.Index <= 2]},
			[?Weather.Change.Notified > ?Weather.Weather.30Min.Index]}} =>
		(Prove: weatherForecastNotification(?Lap, !Weather.Weather.30Min, 30))

priority: -10, [?Pitstop.Lap = ?Lap] => (Prove: clearWeatherTyreChangeNotification(?Lap)),
										(Clear: Weather.Tyre.Compound.Target), (Clear: Weather.Tyre.Compound.Color.Target)

clearWeatherTyreChangeNotification(?lap) <= ?temp = ?lap + 2, ?clearLap = ?temp + !Session.Settings.Lap.Learning.Laps,
											Set(Weather.Tyre.Change.Clear, ?clearLap)

priority: -10, [?Weather.Tyre.Change.Clear = ?Lap] => (Clear: Weather.Tyre.Change.Recommended)

weatherForecastNotification(?lap, ?weather, ?minutes) <= remainingStintTime(?lap, ?stintTime), ?remainingMinutes = ?stintTime / 60000,
														 ?remainingMinutes > ?minutes, notifyWeatherForecast(?weather, ?minutes, true),
														 weatherIndex(?weather, ?index), Set(Weather.Change.Notified, ?index)
weatherForecastNotification(?lap, ?weather, ?minutes) <= remainingStintTime(?lap, ?stintTime), ?remainingMinutes = ?stintTime / 60000,
														 =<(?remainingMinutes, ?minutes), notifyWeatherForecast(?weather, ?minutes, false),
														 weatherIndex(?weather, ?index), Set(Weather.Change.Notified, ?index)

notifyWeatherForecast(?weather, ?minutes, ?change) <= Call(raiseEvent, WeatherForecast, ?weather, ?minutes,  ?change), !
notifyWeatherForecast(?weather, ?minutes, ?change) <= Call(notifyWeatherForecast, ?weather, ?minutes, ?change)

weatherTyreChangeRecommendation(?lap, ?weather, ?minutes, ?compound) <=
		remainingStintTime(?lap, ?stintTime), ?remainingMinutes = ?stintTime / 60000, ?remainingMinutes > ?minutes,
		requestTyreChange(?weather, ?minutes, ?compound),
		updateWeatherNotified(?compound, ?weather), updateTyreChangeRecommended(?lap, ?weather),
		Set(Weather.Tyre.Compound.Target, ?compound), tyreCompoundColor(?compound, ?color), Set(Weather.Tyre.Compound.Color.Target, ?color)
weatherTyreChangeRecommendation(?lap, ?weather, ?minutes, ?compound) <=
		remainingStintTime(?lap, ?stintTime), ?remainingMinutes = ?stintTime / 60000, =<(?remainingMinutes, ?minutes),
		notifyWeatherForecast(?weather, ?minutes, false),
		updateWeatherNotified(?compound, ?weather), updateTyreChangeRecommended(?lap, ?weather)

gripTyreChangeRecommendation(?lap, ?compound) <=
		requestTyreChange(!Weather.Weather.10Min, 0, ?compound),
		updateWeatherNotified(?compound, !Weather.Weather.10Min),
		updateTyreChangeRecommended(?lap, !Weather.Weather.10Min)

requestTyreChange(?weather, ?minutes, ?compound) <= Call(raiseEvent, WeatherForecast, ?weather, ?minutes, true, ?compound), !
requestTyreChange(?weather, ?minutes, ?compound) <= Call(requestTyreChange, ?weather, ?minutes, ?compound)

updateTyreChangeRecommended(?lap, ?weather) <= ?lap > !Session.Settings.Lap.Learning.Laps, !,
											   weatherIndex(?weather, ?index), Set(Weather.Tyre.Change.Recommended, ?index)
updateTyreChangeRecommended(?, ?)

updateWeatherNotified(?, ?weather) <=
		unbound?(!Weather.Change.Notified), !, weatherIndex(?weather, ?index), Set(Weather.Change.Notified, ?index)
updateWeatherNotified(Dry, ?weather) <=
		weatherIndex(?weather, ?index), ?index < !Weather.Change.Notified, !, Set(Weather.Change.Notified, ?index)
updateWeatherNotified(Intermediate, ?weather) <=
		weatherIndex(?weather, ?index), ?index > !Weather.Change.Notified, !, Set(Weather.Change.Notified, ?index)
updateWeatherNotified(Wet, ?weather) <=
		weatherIndex(?weather, ?index), ?index > !Weather.Change.Notified, !, Set(Weather.Change.Notified, ?index)
updateWeatherNotified(?, ?)
