require 'papla/backend' require 'papla/version' module Papla # Converts a number to Polish or English words, # capitalizing the first letter of the whole phrase. # # Localisation is provided by I18n, the language # of the result depends on I18n.locale. # # Currently numbers from 0 up to 999 999 999 # are supported. If you pass a bigger number, # an ArgumentError is raised. # # To convert a number, simply call: # # Papla[your_number] # # Examples: # # I18n.locale # => :pl # Papla[0] # => "Zero" # Papla[22] # => "Dwadzieścia dwa" # Papla[150] # => "Sto pięćdziesiąt" # Papla[999] # => "Dziewięćset dziewięćdziesiąt dziewięć" # Papla[12345] # => "Dwanaście tysięcy trzysta czterdzieści pięć" # Papla[1_000_001] # => "Jeden milion jeden" # # When given a Float, Papla will assume that # the decimal part represents cents. It will then # round the number using Float#round to # two decimal places, and append the number # of cents divided by hundred to the resulting string. # # Example: # # Papla[1.0] # => "Jeden 00/100" # Papla[87.654321] # => "Osiemdziesiąt siedem 65/100" # Papla[2.999] # => "Trzy 00/100" # # @param [Fixnum] number the number to convert # @return [String] the phrase in Polish or English def self.[](number) validate!(number) number = prepare(number) basic_number = number.to_i basic_phrase = build_basic_phrase(basic_number) case number when Float; append_cents(basic_phrase, number) else basic_phrase end end private def self.prepare(number) case number when Float; number.round(2) else number end end def self.build_basic_phrase(basic_number) if basic_number.zero? spell_zero else groups = group(basic_number) groups_as_words = convert_groups(groups) groups_as_words.flatten.join(' ') end.capitalize end def self.group(number) groups = [] while number > 0 number, group = number.divmod(1000) groups.unshift(group) end groups end def self.convert_groups(groups) bound = groups.count - 1 result = [] groups.each_with_index do |group, i| if group > 0 result << convert_small_number(group) result << spell_rank(bound - i, group) if i < bound end end result end def self.convert_small_number(number) if number.zero? [] elsif number < 20 [spell_ones(number)] elsif number < 100 tens, remainder = number.divmod(10) [spell_tens(tens), convert_small_number(remainder)] else hundreds, remainder = number.divmod(100) [spell_hundreds(hundreds), convert_small_number(remainder)] end end def self.validate!(number) max = 999_999_999 raise ArgumentError, "#{number} is too big, only numbers up to #{max} are supported" if number > max end def self.append_cents(basic_phrase, number) cents = 100 * (number - number.to_i) spell_cents(basic_phrase, cents) end def self.backend @backend ||= Backend.new end def self.spell_zero; backend.zero; end def self.spell_ones(index); backend.ones(index); end def self.spell_tens(index); backend.tens(index); end def self.spell_hundreds(index); backend.hundreds(index); end def self.spell_rank(index, number); backend.rank(index, number); end def self.spell_cents(basic_phrase, cents); backend.cents(basic_phrase, cents); end end