Farmbot-Web-App/app/mutations/farm_events/generate_calendar.rb

78 lines
2.4 KiB
Ruby

module FarmEvents
# Used to calculate next 60ish occurrences or so of a FarmEvent.
class GenerateCalendar < Mutations::Command
GRACE_PERIOD = 5.minutes
NEVER = FarmEvent::NEVER.to_s
TIME = { "minutely" => 60,
"hourly" => 60 * 60,
"daily" => 60 * 60 * 24,
"weekly" => 60 * 60 * 24 * 7,
"monthly" => 60 * 60 * 24 * 30, # Not perfect...
"yearly" => 60 * 60 * 24 * 365 }
UNIT_TRANSLATION = { "minutely" => :minutes,
"hourly" => :hours,
"daily" => :days,
"weekly" => :weeks,
"monthly" => :months,
"yearly" => :years }
required do
integer :repeat
string :time_unit, in: FarmEvent::UNITS_OF_TIME
time :origin
time :lower_limit
end
optional do
time :upper_limit
end
def execute
# Does the input have a valid repeat?
# Is it in the future?
# Then generate a calendar.
# Otherwise, return a "partial calendar" that is either empty or (in the
# case of one-off events) has only one date in it (origin).
(is_repeating ? full_calendar : partial_calendar)
end
def full_calendar
interval_sec = TIME[time_unit] * repeat
upper = compute_endtime
# Current time, plus a 5 minute grace period.
now = Time.now - GRACE_PERIOD
# How many items must we skip to get to the first occurence?
skip_intervals = ((lower_limit - origin) / interval_sec).ceil
# At what time does the first event occur?
first_item = origin + (skip_intervals * interval_sec).seconds
list = [first_item]
60.times do
item = list.last + interval_sec.seconds
list.push(item) unless (item >= upper) || (item <= now)
end
return list
end
def partial_calendar
in_future? ? [origin] : []
end
def the_unit
UNIT_TRANSLATION[time_unit]
end
def is_repeating
(the_unit != NEVER) && the_unit && repeat.send(the_unit)
end
def in_future?
origin > (Time.now - GRACE_PERIOD)
end
def compute_endtime
next_year = (Time.now + 1.year)
(upper_limit && (upper_limit < next_year)) ? upper_limit : next_year
end
end
end