|
| 1 | +#!/usr/bin/env ruby |
| 2 | + |
| 3 | +require "#{ENV['HOME']}/programming/scripts/moon_info.rb" |
| 4 | +require 'json' |
| 5 | +require 'date' |
| 6 | + |
| 7 | +class Forecaster |
| 8 | + URL = 'https://api.openweathermap.org/data/3.0/onecall' |
| 9 | + API_KEY = ENV['OPENWEATHER_API_KEY'] |
| 10 | + |
| 11 | + def self.call(latitude, longitude) |
| 12 | + new(latitude, longitude).call |
| 13 | + end |
| 14 | + |
| 15 | + def initialize(latitude, longitude) |
| 16 | + @latitude = latitude |
| 17 | + @longitude = longitude |
| 18 | + end |
| 19 | + |
| 20 | + def call |
| 21 | + build_structure(fetch_forecast) |
| 22 | + end |
| 23 | + |
| 24 | + private |
| 25 | + attr_reader :latitude, :longitude |
| 26 | + |
| 27 | + def build_structure(forecast) |
| 28 | + current = { |
| 29 | + temp: forecast['current']['temp'], |
| 30 | + desc: forecast['current']['weather'][0]['description'], |
| 31 | + icon_url: icon_url(forecast['current']['weather'][0]['icon']) |
| 32 | + } |
| 33 | + |
| 34 | + daily = forecast['daily'].map do |day| |
| 35 | + { |
| 36 | + date: Time.at(day['dt']).to_date.to_s, |
| 37 | + sunrise: Time.at(day['sunrise']).strftime("%H:%M"), |
| 38 | + sunset: Time.at(day['sunset']).strftime("%H:%M"), |
| 39 | + moon_info: MoonInfo.new(day['moon_phase']), |
| 40 | + uvi: day['uvi'], |
| 41 | + uv_risk: risk_from_uv(day['uvi']), |
| 42 | + min_temp: day['temp']['min'], |
| 43 | + max_temp: day['temp']['max'], |
| 44 | + desc: day['weather'][0]['description'], |
| 45 | + icon_url: icon_url(day['weather'][0]['icon']) |
| 46 | + } |
| 47 | + end |
| 48 | + |
| 49 | + OpenStruct.new(current: current, daily: daily) |
| 50 | + end |
| 51 | + |
| 52 | + def risk_from_uv(uvi) |
| 53 | + case uvi |
| 54 | + when 0..2 then 'low' |
| 55 | + when 2..5 then 'moderate' |
| 56 | + when 5..7 then 'high' |
| 57 | + when 7..10 then 'very_high' |
| 58 | + else |
| 59 | + 'extreme' |
| 60 | + end |
| 61 | + end |
| 62 | + |
| 63 | + def fetch_forecast |
| 64 | + url = URL |
| 65 | + url += "?lat=#{latitude}" |
| 66 | + url += "&lon=#{longitude}" |
| 67 | + url += "&appid=#{API_KEY}" |
| 68 | + url += "&units=metric" |
| 69 | + url += "&exclude=minutely,hourly" |
| 70 | + |
| 71 | + JSON.parse(`curl -s '#{url}'`) |
| 72 | + end |
| 73 | + |
| 74 | + def icon_url(icon) |
| 75 | + "https://openweathermap.org/img/wn/#{icon}@2x.png" |
| 76 | + end |
| 77 | +end |
0 commit comments