module Faker module Russian module Okato def okato(options = {}) options.assert_valid_keys(:sequence_number, :okato_region_number, :length) sequence = find_sequence(options[:sequence_number]) okato_region_number = find_region_number(options[:okato_region_number], sequence, :okato_region_numbers) okato_without_calc = okato_region_number + find_length_digits(options[:length], sequence) okato_without_calc + calc_okato(okato_without_calc) end private def find_length_digits(length, sequence) if length.present? raise 'no such length for okato' unless %w{3 6 9}.include?(length.to_s) else length = [3, 6, 9][sequence.rand(3)] end sprintf("%06d", sequence.rand(1_000_000)).split(//).first(length.to_i - 3).join end def calc_okato(okato_without_calc) ((calc_okato_digit(okato_without_calc, 1) < 10) ? calc_okato_digit(okato_without_calc, 1) : calc_okato_digit(okato_without_calc, 3) % 10).to_s end def calc_okato_digit(okato_without_calc, adding_number) okato_without_calc.split(//).map(&:to_i).each_with_index.inject(0){ |s, p| s + p[0] * (p[1] + adding_number) } % 11 end end end end