feat: add weather forecasting

This commit is contained in:
insects 2025-03-11 14:57:28 +01:00
parent 6eea0dc29f
commit 705e7b1dc0
20 changed files with 181 additions and 19 deletions

64
lib/weather.rb Normal file
View file

@ -0,0 +1,64 @@
class Weather
def self.get_weather(zone, hash = hash(get_seed))
total = 0
APP_DATA[zone][:weather].each do |arr|
name, rate = arr
if (total += rate) > hash
return name
end
end
end
def self.forecast(zone, seed = get_seed, count = 10)
res = []
prev_hash = hash(seed - 1)
prev_weather = get_weather(zone, prev_hash)
count.times do |_|
curr_hash = hash(seed)
curr_weather = get_weather(zone, curr_hash)
res.push({ zone: zone, prev_weather: prev_weather, curr_weather: curr_weather, weather_name: get_weather_name(curr_weather), seed: seed, time: Time.at(seed * 1400000.0 / 1000) })
prev_hash = curr_hash
prev_weather = curr_weather
seed += 1
end
res
end
def self.round_to_last_weather_time(time)
last_hour = time.hour / 8 * 8
time.change(hour: last_hour)
end
def self.get_weather_name(name)
case name
when "fair" then "Fair Skies"
when "showers" then "Showers"
when "gales" then "Gales"
when "blizzards" then "Blizzards"
when "heat" then "Heat"
when "thunder" then "Thunderstorms"
when "gloom" then "Gloom"
when "snow" then "Snow"
when "fog" then "Fog"
when "umbral_wind" then "Umbral Wind"
else "Unknown Weather"
end
end
def self.get_seed
(Time.now.utc.to_i * 1000 / 1400000.0).floor
end
def self.hash(seed = get_seed)
base = (seed / 3).floor * 100 + ((seed + 1) % 3) * 8
# Ruby has no other convenient way to convert a signed integer into an unsigned one
step1 = [ ((base << 11) ^ base) ].pack("L").unpack("L").first
step2 = [ (([ (step1 >> 8) ].pack("L").unpack("L").first.to_i ^ step1)) ].pack("L").unpack("L").first.to_i
step2 % 100
end
def self.unsigned_right(input, by)
input << by & 0xFF00 | input >> by & 0xFF
end
end