andycroll/odeon_uk

View on GitHub
lib/odeon_uk/internal/parser/api/performance_day.rb

Summary

Maintainability
A
0 mins
Test Coverage
module OdeonUk
  # @api private
  module Internal
    module Parser
      module Api
        # A single day of performances for a particular film
        class PerformanceDay
          def initialize(data)
            @data = data
          end

          def to_a
            performance_kinds.each_with_index.flat_map do |_, index|
              starting_times(index).map do |time|
                {
                  dimension: dimension(index),
                  starting_at: TimeParser.new(date, time).to_utc,
                  variant: variant(index)
                }
              end
            end
          end

          private

          def date
            @data['date']
          end

          def dimension(index)
            performance_kind(index).include?('3D') ? '3d' : '2d'
          end

          def performance_kinds
            @data['attributes']
          end

          def performance_kind(index)
            performance_kinds[index]['attribute']
          end

          def starting_times(index)
            performance_kinds[index]['showtimes'][0].map do |h|
              h['performanceTime']
            end
          end

          def variant(index)
            {
              'Culture'       => 'arts',
              'Kids'          => 'kids',
              'IMAX'          => 'imax',
              'Newbies'       => 'baby',
              'Silver Cinema' => 'senior'
            }.select { |k, _| performance_kind(index).include?(k) }.values.uniq
          end

          # parse a time to utc time
          TimeParser = Struct.new(:date, :time) do
            def to_utc
              tz.local_to_utc(parsed_time)
            end

            private

            def early_morning_screening?
              time.match(/\A00/)
            end

            def parsed_date
              case date
              when 'Today'    then Time.now.strftime '%Y-%m-%d'
              when 'Tomorrow' then (Time.now + 60 * 60 * 24).strftime '%Y-%m-%d'
              else date.gsub('.', '').match(/\d+\s\w+\z/)[0]
              end
            end

            def parsed_time
              parsed_time = Time.parse("#{parsed_date} #{time} UTC")
              # Odeon deliberately mislabel their 00:01 screenings as the day before
              early_morning_screening? ? parsed_time + 60 * 60 * 24 : parsed_time
            end

            def tz
              @tz ||= TZInfo::Timezone.get('Europe/London')
            end
          end
        end
      end
    end
  end
end