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

24
lib/clock.rb Normal file
View file

@ -0,0 +1,24 @@
class Clock
EARTH_TO_EORZEA = 3600.0 / 175.0
EORZEA_TO_EARTH = 1.0 / EARTH_TO_EORZEA
def self.get_current_eorzea_time
to_eorzea_time(Time.now.utc)
end
def self.to_eorzea_time(earth_time)
et_ts = earth_time.to_i
new_ts = et_ts.abs * EARTH_TO_EORZEA
Time.at(new_ts)
end
def self.to_earth_time(ez_time)
ez_ts = ez_time.to_i
new_ts = (ez_ts * EORZEA_TO_EARTH).ceil
Time.at(new_ts)
end
def self.display_ez_time(ez_time)
ez_time.strftime("%H:%M")
end
end

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