<commit_before># encoding: utf-8
require 'i18n'
require 'm9t'

module Metar
  locales_path = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'locales'))
  I18n.load_path += Dir.glob("#{ locales_path }/*.yml")

  class Distance < M9t::Distance
    attr_accessor :units

    # nil is taken to mean 'data unavailable'
    def initialize(meters = nil)
      @units = :meters
      if meters
        super
      else
        @value = nil
      end
    end

    # Handles nil case differently to M9t::Distance
    def to_s(options = {})
      options = {
        :units       => @units,
        :precision   => 0,
        :abbreviated => true
      }.merge(options)
      return I18n.t('metar.distance.unknown') if @value.nil?
      super(options)
    end
  end

  # Adds a parse method to the M9t base class
  class Speed < M9t::Speed
    METAR_UNITS = {
      ''    => :kilometers_per_hour,
      'KMH' => :kilometers_per_hour,
      'MPS' => :meters_per_second,
      'KT'  => :knots,
    }

    def Speed.parse(s)
      case
      when s =~ /^(\d+)(|KT|MPS|KMH)$/
        # Call the appropriate factory method for the supplied units
        send(METAR_UNITS[$2], $1.to_i)
      else
        nil
      end
    end
  end

  # Adds a parse method to the M9t base class
  class Temperature < M9t::Temperature
    def Temperature.parse(s)
      if s =~ /^(M?)(\d+)$/
        sign = $1
        value = $2.to_i
        value *= -1 if sign == 'M'
        new(value)
      else
        nil
      end
    end

    def to_s(options = {})
      options = {:abbreviated => true, :precision => 0}.merge(options)
      super(options)
    end
  end

  # Adds a parse method to the M9t base class
  class Pressure < M9t::Pressure
    def Pressure.parse(pressure)
      case
      when pressure =~ /^Q(\d{4})$/
        hectopascals($1.to_f)
      when pressure =~ /^A(\d{4})$/
        inches_of_mercury($1.to_f / 100.0)
      else
        nil
      end
    end
  end

  class Direction < M9t::Direction
    def initialize(direction)
      direction = M9t::Direction::normalize(direction.to_f)
      super(direction)
    end
  end

  class Wind
    def Wind.parse(s)
      case
      when s =~ /^(\d{3})(\d{2}(|MPS|KMH|KT))$/
        return nil if $1.to_i > 360
        new(Direction.new($1), Speed.parse($2))
      when s =~ /^(\d{3})(\d{2})G(\d{2,3}(|MPS|KMH|KT))$/
        return nil if $1.to_i > 360
        new(Direction.new($1), Speed.parse($2 + $4), Speed.parse($3))
      when s =~ /^VRB(\d{2})G(\d{2,3})(|MPS|KMH|KT)$/
        speed = $1 + $3
        gusts = $2 + $3
        new(:variable_direction, Speed.parse(speed), Speed.parse(gusts))
      when s =~ /^VRB(\d{2}(|MPS|KMH|KT))$/
        new(:variable_direction, Speed.parse($1))
      when s =~ /^\/{3}(\d{2}(|MPS|KMH|KT))$/
        new(:unknown_direction, Speed.parse($1))
      when s =~ %r(^/////(|MPS|KMH|KT)$)
        new(:unknown_direction, :unknown_speed)
      else
        nil
      end
    end

    attr_reader :direction, :speed, :gusts

    def initialize(direction, speed, gusts = nil)
      @direction, @speed, @gusts = direction, speed, gusts
    end

    def to_s(options = {})
      options = {
        :direction_units => :compass,
        :speed_units     => :kilometers_per_hour}.merge(options)
      speed =
        case @speed
        when :unknown_speed
          I18n.t('metar.wind.unknown_speed')
        else
          @speed.to_s(
            :abbreviated => true,
            :precision   => 0,
            :units       => options[:speed_units]
          )
        end
      direction =
        case @direction
        when :variable_direction
          I18n.t('metar.wind.variable_direction')
        when :unknown_direction
          I18n.t('metar.wind.unknown_direction')
        else
          @direction.to_s(:units => options[:direction_units])
        end
      s = "#{speed} #{direction}"
      if not @gusts.nil?
        g = @gusts.to_s(
          :abbreviated => true,
          :precision   => 0,
          :units       => options[:speed_units]
        )
        s += " #{I18n.t('metar.wind.gusts')} #{g}"
      end
      s
    end
  end

  class VariableWind
    def VariableWind.parse(variable_wind)
      if variable_wind =~ /^(\d+)V(\d+)$/
        new(Direction.new($1), Direction.new($2))
      else
        nil
      end
    end

    attr_reader :direction1, :direction2

    def initialize(direction1, direction2)
      @direction1, @direction2 = direction1, direction2
    end

    def to_s
      "#{@direction1.to_s(:units => :compass)} - #{@direction2.to_s(:units => :compass)}"
    end
  end

  class Visibility
    def Visibility.parse(s)
      case
      when s == '9999'
        new(Distance.new(10000), nil, :more_than)
      when s =~ /(\d{4})NDV/ # WMO
        new(Distance.new($1.to_f)) # Assuming meters
      when (s =~ /^((1|2)\s|)([1357])\/([248]|16)SM$/) # US
        miles          = $1.to_f + $3.to_f / $4.to_f
        distance       = Distance.miles(miles)
        distance.units = :miles
        new(distance)
      when s =~ /^(\d+)SM$/ # US
        distance       = Distance.miles($1.to_f)
        distance.units = :miles
        new(distance)
      when s == 'M1/4SM' # US
        distance       = Distance.miles(0.25)
        distance.units = :miles
        new(distance, nil, :less_than)
      when s =~ /^(\d+)KM$/
        new(Distance.kilometers($1))
      when s =~ /^(\d+)$/ # We assume meters
        new(Distance.new($1))
      when s =~ /^(\d+)(N|NE|E|SE|S|SW|W|NW)$/
        new(Distance.meters($1), M9t::Direction.compass($2))
      else
        nil
      end
    end

    attr_reader :distance, :direction, :comparator

    def initialize(distance, direction = nil, comparator = nil)
      @distance, @direction, @comparator = distance, direction, comparator
    end

    def to_s(options = {})
      distance_options = {
        :abbreviated => true,
        :precision   => 0,
        :units       => :kilometers
      }.merge(options)
      direction_options = {:units => :compass}
      case
      when (@direction.nil? and @comparator.nil?)
        @distance.to_s(distance_options)
      when @comparator.nil?
        "%s %s" % [
          @distance.to_s(distance_options),
          @direction.to_s(direction_options)
        ]
      when @direction.nil?
        "%s %s" % [
          I18n.t('comparison.' + @comparator.to_s),
          @distance.to_s(distance_options)
        ]
      else
        "%s %s %s" % [
          I18n.t('comparison.' + @comparator.to_s),
          @distance.to_s(distance_options),
          @direction.to_s(direction_options)
        ]
      end
    end
  end

  class RunwayVisibleRange
    TENDENCY   = {'' => nil, 'N' => :no_change, 'U' => :improving, 'D' => :worsening}<commit_msg>Improve string concatenation<commit_after># encoding: utf-8
require 'i18n'
require 'm9t'

module Metar
  locales_path = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'locales'))
  I18n.load_path += Dir.glob("#{ locales_path }/*.yml")

  class Distance < M9t::Distance
    attr_accessor :units

    # nil is taken to mean 'data unavailable'
    def initialize(meters = nil)
      @units = :meters
      if meters
        super
      else
        @value = nil
      end
    end

    # Handles nil case differently to M9t::Distance
    def to_s(options = {})
      options = {
        :units       => @units,
        :precision   => 0,
        :abbreviated => true
      }.merge(options)
      return I18n.t('metar.distance.unknown') if @value.nil?
      super(options)
    end
  end

  # Adds a parse method to the M9t base class
  class Speed < M9t::Speed
    METAR_UNITS = {
      ''    => :kilometers_per_hour,
      'KMH' => :kilometers_per_hour,
      'MPS' => :meters_per_second,
      'KT'  => :knots,
    }

    def Speed.parse(s)
      case
      when s =~ /^(\d+)(|KT|MPS|KMH)$/
        # Call the appropriate factory method for the supplied units
        send(METAR_UNITS[$2], $1.to_i)
      else
        nil
      end
    end
  end

  # Adds a parse method to the M9t base class
  class Temperature < M9t::Temperature
    def Temperature.parse(s)
      if s =~ /^(M?)(\d+)$/
        sign = $1
        value = $2.to_i
        value *= -1 if sign == 'M'
        new(value)
      else
        nil
      end
    end

    def to_s(options = {})
      options = {:abbreviated => true, :precision => 0}.merge(options)
      super(options)
    end
  end

  # Adds a parse method to the M9t base class
  class Pressure < M9t::Pressure
    def Pressure.parse(pressure)
      case
      when pressure =~ /^Q(\d{4})$/
        hectopascals($1.to_f)
      when pressure =~ /^A(\d{4})$/
        inches_of_mercury($1.to_f / 100.0)
      else
        nil
      end
    end
  end

  class Direction < M9t::Direction
    def initialize(direction)
      direction = M9t::Direction::normalize(direction.to_f)
      super(direction)
    end
  end

  class Wind
    def Wind.parse(s)
      case
      when s =~ /^(\d{3})(\d{2}(|MPS|KMH|KT))$/
        return nil if $1.to_i > 360
        new(Direction.new($1), Speed.parse($2))
      when s =~ /^(\d{3})(\d{2})G(\d{2,3}(|MPS|KMH|KT))$/
        return nil if $1.to_i > 360
        new(Direction.new($1), Speed.parse($2 + $4), Speed.parse($3))
      when s =~ /^VRB(\d{2})G(\d{2,3})(|MPS|KMH|KT)$/
        speed = $1 + $3
        gusts = $2 + $3
        new(:variable_direction, Speed.parse(speed), Speed.parse(gusts))
      when s =~ /^VRB(\d{2}(|MPS|KMH|KT))$/
        new(:variable_direction, Speed.parse($1))
      when s =~ /^\/{3}(\d{2}(|MPS|KMH|KT))$/
        new(:unknown_direction, Speed.parse($1))
      when s =~ %r(^/////(|MPS|KMH|KT)$)
        new(:unknown_direction, :unknown_speed)
      else
        nil
      end
    end

    attr_reader :direction, :speed, :gusts

    def initialize(direction, speed, gusts = nil)
      @direction, @speed, @gusts = direction, speed, gusts
    end

    def to_s(options = {})
      options = {
        :direction_units => :compass,
        :speed_units     => :kilometers_per_hour}.merge(options)
      speed =
        case @speed
        when :unknown_speed
          I18n.t('metar.wind.unknown_speed')
        else
          @speed.to_s(
            :abbreviated => true,
            :precision   => 0,
            :units       => options[:speed_units]
          )
        end
      direction =
        case @direction
        when :variable_direction
          I18n.t('metar.wind.variable_direction')
        when :unknown_direction
          I18n.t('metar.wind.unknown_direction')
        else
          @direction.to_s(:units => options[:direction_units])
        end
      s = "#{speed} #{direction}"
      if not @gusts.nil?
        g = @gusts.to_s(
          :abbreviated => true,
          :precision   => 0,
          :units       => options[:speed_units]
        )
        s += " #{I18n.t('metar.wind.gusts')} #{g}"
      end
      s
    end
  end

  class VariableWind
    def VariableWind.parse(variable_wind)
      if variable_wind =~ /^(\d+)V(\d+)$/
        new(Direction.new($1), Direction.new($2))
      else
        nil
      end
    end

    attr_reader :direction1, :direction2

    def initialize(direction1, direction2)
      @direction1, @direction2 = direction1, direction2
    end

    def to_s
      "#{@direction1.to_s(:units => :compass)} - #{@direction2.to_s(:units => :compass)}"
    end
  end

  class Visibility
    def Visibility.parse(s)
      case
      when s == '9999'
        new(Distance.new(10000), nil, :more_than)
      when s =~ /(\d{4})NDV/ # WMO
        new(Distance.new($1.to_f)) # Assuming meters
      when (s =~ /^((1|2)\s|)([1357])\/([248]|16)SM$/) # US
        miles          = $1.to_f + $3.to_f / $4.to_f
        distance       = Distance.miles(miles)
        distance.units = :miles
        new(distance)
      when s =~ /^(\d+)SM$/ # US
        distance       = Distance.miles($1.to_f)
        distance.units = :miles
        new(distance)
      when s == 'M1/4SM' # US
        distance       = Distance.miles(0.25)
        distance.units = :miles
        new(distance, nil, :less_than)
      when s =~ /^(\d+)KM$/
        new(Distance.kilometers($1))
      when s =~ /^(\d+)$/ # We assume meters
        new(Distance.new($1))
      when s =~ /^(\d+)(N|NE|E|SE|S|SW|W|NW)$/
        new(Distance.meters($1), M9t::Direction.compass($2))
      else
        nil
      end
    end

    attr_reader :distance, :direction, :comparator

    def initialize(distance, direction = nil, comparator = nil)
      @distance, @direction, @comparator = distance, direction, comparator
    end

    def to_s(options = {})
      distance_options = {
        :abbreviated => true,
        :precision   => 0,
        :units       => :kilometers
      }.merge(options)
      direction_options = {:units => :compass}
      case
      when (@direction.nil? and @comparator.nil?)
        @distance.to_s(distance_options)
      when @comparator.nil?
        [
          @distance.to_s(distance_options),
          @direction.to_s(direction_options)
        ].join(' ')
      when @direction.nil?
        [
          I18n.t('comparison.' + @comparator.to_s),
          @distance.to_s(distance_options)
        ].join(' ')
      else
        [
          I18n.t('comparison.' + @comparator.to_s),
          @distance.to_s(distance_options),
          @direction.to_s(direction_options)
        ].join(' ')
      end
    end
  end

  class RunwayVisibleRange
    TENDENCY   = {'' => nil, 'N' => :no_change, 'U' => :improving, 'D' => :worsening}
{'fraction_non_alphanumeric': 0.14966740576496673, 'fraction_numerical': 0.01892091648189209, 'mean_word_length': 1.984998896977719, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6768439', 'n_tokens_mistral': 4902, 'n_tokens_neox': 4663, 'n_words': 975}