using AIXM::Refinements module AIXM class Component # Timesheets define customized activity time windows. # # AIXM supports only yearless dates whereas OFMX extends the model to # accommodate years as well, therefore, the year part is ignored for AIXM. # # ===Cheat Sheat in Pseudo Code: # timesheet = AIXM.timesheet( # adjust_to_dst: Boolean # dates: (AIXM.date..AIXM.date) # days: (AIXM.day..AIXM..day) # either: range of days # day: AIXM.day (default: :any) # or: single day # ) # timesheet.times = (AIXM.time..AIXM_time) # # @see https://gitlab.com/openflightmaps/ofmx/-/wikis/Timetable#custom-timetable class Timesheet < Component DAYS = { MON: :monday, TUE: :tuesday, WED: :wednesday, THU: :thursday, FRI: :friday, SAT: :saturday, SUN: :sunday, WD: :workday, PWD: :day_preceding_workday, AWD: :day_following_workday, LH: :holiday, PLH: :day_preceding_holiday, ALH: :day_following_holiday, ANY: :any } EVENTS = { SR: :sunrise, SS: :sunset } PRECEDENCES = { E: :first, L: :last } # Range of schedule dates for which this timesheet is active. # # @note Neither open beginning nor open ending is allowed. # # @overload dates # @return [Range] # @overload dates=(value) # @param value [Range] range of schedule dates # either all with year or all yearless attr_reader :dates # Day or days for which this timesheet is active. # # @note Neither open beginning nor open ending is allowed. # # @overload day # @return [AIXM::Schedule::Day] # @overload days # @return [Range] # @overload day=(value) # @param value [AIXM::Schedule::Day] schedule day # @overload days=(value) # @param value [Range] range of schedule days attr_reader :days # Range of schedule times for which this timesheet is active. # # @note Either open beginning or open ending is allowed. # # @overload times # @return [Range, nil] range of schedule times # @overload times=(value) # @param value [Range, nil] range of schedule times attr_reader :times # See the {cheat sheet}[AIXM::Component::Timesheet] for examples on how to # create instances of this class. def initialize(adjust_to_dst:, dates:, days: nil, day: AIXM::ANY_DAY) self.adjust_to_dst, self.dates = adjust_to_dst, dates if days self.days = days else self.day = day end end # @return [String] def inspect %Q(#<#{self.class} dates=#{dates.inspect}>) end # Whether to adjust to dayight savings time. # # @note See the {OFMX docs}[https://gitlab.com/openflightmaps/ofmx/-/wikis/Timetable#custom-timetable] # for how exactly this affects dates and times. # # @!attribute adjust_to_dst # @overload adjust_to_dst? # @return [Boolean] # @overload adjust_to_dst=(value) # @param value [Boolean] def adjust_to_dst? @adjust_to_dst end def adjust_to_dst=(value) fail(ArgumentError, "invalid adjust_to_dst") unless [true, false].include? value @adjust_to_dst = value end def dates=(value) fail(ArgumentError, 'invalid dates') unless value.instance_of?(Range) && value.begin && value.end @dates = value end def days=(value) fail(ArgumentError, 'invalid days') unless value.instance_of?(Range) && value.begin && value.end @days = value end def times=(value) fail(ArgumentError, 'invalid times') unless value.nil? || (value.instance_of?(Range) && value.begin && value.end) @times = value end def day @days unless @days.instance_of? Range end def day=(value) fail(ArgumentError, 'invalid day') unless value.instance_of? AIXM::Schedule::Day @days = value end # @return [String] AIXM or OFMX markup def to_xml builder = Builder::XmlMarkup.new(indent: 2) builder.Timsh do |timsh| timsh.codeTimeRef(adjust_to_dst? ? 'UTCW' : 'UTC') timsh.dateValidWef(dates.begin.to_s('%d-%m')) timsh.dateYearValidWef(dates.begin.year) if AIXM.ofmx? && !dates.begin.yearless? timsh.dateValidTil(dates.end.to_s('%d-%m')) timsh.dateYearValidTil(dates.end.year) if AIXM.ofmx? && !dates.end.yearless? if days.instance_of? Range timsh.codeDay(DAYS.key(days.begin.day).to_s) timsh.codeDayTil(DAYS.key(days.end.day).to_s) else timsh.codeDay(DAYS.key(days.day).to_s) end if times if times.begin timsh.timeWef(times.begin.to_s('%R')) timsh.codeEventWef(EVENTS.key(times.begin.event).to_s) if times.begin.event timsh.timeRelEventWef(times.begin.delta) unless times.begin.delta.zero? timsh.codeCombWef(PRECEDENCES.key(times.begin.precedence).to_s) if times.begin.precedence end if times.end timsh.timeTil(times.end.to_s('%R')) timsh.codeEventTil(EVENTS.key(times.end.event).to_s) if times.end.event timsh.timeRelEventTil(times.end.delta) unless times.end.delta.zero? timsh.codeCombTil(PRECEDENCES.key(times.end.precedence).to_s) if times.end.precedence end end end end end end end