guilhermeteodoro
10/11/2017 - 7:28 PM

Generates and validates a pis/pasep number

Generates and validates a pis/pasep number

# frozen_string_literal: true

module PisNumber
  class Calculator
    WEIGHTS = [3, 2, 9, 8, 7, 6, 5, 4, 3, 2].freeze

    def generate
      random_number = rand(1_000_000_000..9_999_999_999).to_s
      digit = calculate_digit to_a(random_number)

      "#{random_number}#{digit}"
    end

    def valid?(number)
      number_array = to_a(Sanitizer.strip_non_numeric(number.to_s))
      return false if number_array.size != 11

      digit = calculate_digit number_array

      number_array.last == digit
    end

    private

    def calculate_digit(number_array)
      number_with_weight = PisNumber::Calculator::WEIGHTS.zip(number_array)

      sum = number_with_weight.reduce(0) do |acc, (weight, number)|
        acc + weight * number
      end

      digit = 11 - (sum % 11)
      digit = 0 if digit > 9

      digit
    end

    def to_a(arr)
      arr.chars.map(&:to_i)
    end
  end

  def generate
    Calculator.new.generate
  end

  def valid?(number)
    Calculator.new.valid?(number)
  end

  module_function :generate, :valid?
end