<commit_before>module MusicTheory
  class Scale

    attr_reader :name, :intervals, :root

    def initialize(intervals, name, root=nil)
      @intervals = intervals
      @name = name
      @root = root
    end

    def with_name(name)
      Scale.new(intervals, name, root)
    end

    def with_root(root)
      Scale.new(intervals, name, root)
    end

    def without_root
      Scale.new(intervals, name)
    end

    def interval(i)
      if i.respond_to? :each
        i.map{|j| interval(j)}
      else
        raise ArgumentError, "interval must be non-zero" if i == 0
        i += i < 0 ? 1 : -1
        zero_based_interval(i)
      end
    end

    def note(i)
      raise ArgumentError, "Cannot get note for scale without a root" unless root

      if i.respond_to? :each
        i.map{|j| interval(j) + root}
      else
        interval(i) + root
      end
    end

    alias notes note

    def zero_based_interval(i)
      d = i % length
      o = i / length
      result = intervals[d]
      result = result + Interval.octave(o) if o != 0
      result
    end

    def length
      intervals.length
    end

    def [](i)
      if root
        root + zero_based_interval(i)
      else
        zero_based_interval(i)
      end
    end

    def to_s
      if root && name
        "#{root} #{name}"
      elsif name
        name
      elsif root
        "#{name} [#{intervals_s}]"
      else
        "[#{intervals_s}]"
      end
    end

    def inspect
      to_s
    end

    def intervals_s
      if root
        intervals.map{|i| (root + i).to_s}.join(' ')
      else
        intervals.map(&:scale_shorthand).join(' ')
      end
    end

    def rotate(n=1, new_name=nil)
      basis = zero_based_interval(n)
      new_intervals = intervals.rotate(n).map{|i| (i - basis).modulo_octave}
      Scale.new(new_intervals, new_name || name, root)
    end

    def transpose(interval)
      raise ArgumentError, "Cannot transpose scale unless unless it has a root" unless root
      Scale.new(intervals, name, root + interval)
    end

    def +(interval)
      transpose(interval)
    end

    def -(interval)
      self + -interval
    end

    def ==(scale)
      return false unless scale.intervals == self.intervals
      if self.root && scale.root
        return false unless self.root == scale.root
      end<commit_msg>Don't default to existing name when rotating a scale<commit_after>module MusicTheory
  class Scale

    attr_reader :name, :intervals, :root

    def initialize(intervals, name, root=nil)
      @intervals = intervals
      @name = name
      @root = root
    end

    def with_name(name)
      Scale.new(intervals, name, root)
    end

    def with_root(root)
      Scale.new(intervals, name, root)
    end

    def without_root
      Scale.new(intervals, name)
    end

    def interval(i)
      if i.respond_to? :each
        i.map{|j| interval(j)}
      else
        raise ArgumentError, "interval must be non-zero" if i == 0
        i += i < 0 ? 1 : -1
        zero_based_interval(i)
      end
    end

    def note(i)
      raise ArgumentError, "Cannot get note for scale without a root" unless root

      if i.respond_to? :each
        i.map{|j| interval(j) + root}
      else
        interval(i) + root
      end
    end

    alias notes note

    def zero_based_interval(i)
      d = i % length
      o = i / length
      result = intervals[d]
      result = result + Interval.octave(o) if o != 0
      result
    end

    def length
      intervals.length
    end

    def [](i)
      if root
        root + zero_based_interval(i)
      else
        zero_based_interval(i)
      end
    end

    def to_s
      if root && name
        "#{root} #{name}"
      elsif name
        name
      elsif root
        "#{name} [#{intervals_s}]"
      else
        "[#{intervals_s}]"
      end
    end

    def inspect
      to_s
    end

    def intervals_s
      if root
        intervals.map{|i| (root + i).to_s}.join(' ')
      else
        intervals.map(&:scale_shorthand).join(' ')
      end
    end

    def rotate(n=1, new_name=nil)
      basis = zero_based_interval(n)
      new_intervals = intervals.rotate(n).map{|i| (i - basis).modulo_octave}
      Scale.new(new_intervals, new_name, root)
    end

    def transpose(interval)
      raise ArgumentError, "Cannot transpose scale unless unless it has a root" unless root
      Scale.new(intervals, name, root + interval)
    end

    def +(interval)
      transpose(interval)
    end

    def -(interval)
      self + -interval
    end

    def ==(scale)
      return false unless scale.intervals == self.intervals
      if self.root && scale.root
        return false unless self.root == scale.root
      end
{'fraction_non_alphanumeric': 0.09500531349628055, 'fraction_numerical': 0.0025504782146652497, 'mean_word_length': 1.9175449473031618, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, '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': '5597920', 'n_tokens_mistral': 1550, 'n_tokens_neox': 1487, 'n_words': 436}