Files
project-work/worker-toolkit-flaredown/repo/backend/app/services/weather_retriever.rb

94 lines
3.0 KiB
Ruby

class WeatherRetriever
class << self
def get(date, postal_code)
position = Position.find_or_create_by(postal_code: postal_code)
weather = Weather.find_by(date: date, position_id: position&.id)
return weather if weather.present?
if position&.latitude.blank? || position&.longitude.blank?
Rails.logger.warn "No coordinates found for postal_code #{postal_code}: #{position.inspect}"
return
end
forecast = get_forecast(date, position)
if forecast.status != 200
Rails.logger.warn "No forecast found for position #{position.inspect}: response code was #{forecast.status}, headers were #{forecast.headers}, body contained #{forecast.body}"
return
end
create_weather(forecast, position.id)
end
private
def get_forecast(date, position)
Tomorrowiorb.forecast(
"#{position.latitude},#{position.longitude}",
["1d"],
"imperial"
)
end
def create_weather(forecast, position_id)
today = JSON.parse(forecast.body, symbolize_names: true).dig(:timelines, :daily, 0)
the_time = today.dig(:time)
today = today.dig(:values)
rain_intensity = today.dig(:rainIntensityAvg)
sleet_intensity = today.dig(:sleetIntensityAvg)
snow_intensity = today.dig(:snowIntensityAvg)
icon = get_icon_legacy(today)
summary = "General conditions are #{icon}, with an average temperature of #{today[:temperatureAvg]}."
Weather.create(
date: Date.strptime(the_time, "%Y-%m-%d"),
humidity: today.dig(:humidityAvg).round,
icon: icon,
position_id: position_id,
precip_intensity: rain_intensity + sleet_intensity + snow_intensity,
pressure: today.dig(:pressureSurfaceLevelAvg),
summary: summary,
temperature_max: today.dig(:temperatureMax),
temperature_min: today.dig(:temperatureMin)
)
end
def get_icon_legacy(today)
# Our icons do not coverage their full range of weather codes. We could pull in their icons (linked below) on the frontend to expand options
# This method adapts their weather codes to our existing icons as best as possible
# Icons and codes found here: https://docs.tomorrow.io/reference/data-layers-weather-codes
# Icon files here: https://github.com/Tomorrow-IO-API/tomorrow-weather-codes
# Daily forecast is always daytime weather codes / icons regardless of actual time
code = if today["weatherCodeMin"]
today["weatherCodeMin"]
elsif today["weatherCodeFullDay"]
today["weatherCodeFullDay"]
else
today["weatherCode"]
end
case code
when 1000, 1100
"clear-day"
when 1101
"partly-cloudy-day"
when 1102, 1001, 8000
"cloudy"
when 2000, 2100
"fog"
when 4000, 4001, 4200, 4201
"rain"
when 5000, 5001, 5100, 5101
"snow"
when 6000, 6001, 6200, 6201, 7000, 7101, 7102
"sleet"
else
"default"
end
end
end
end