class RMB

Constants

DECIMAL_UNIT
INTEGER_UNIT
NUMBERS
PART_UNIT

Attributes

decimal[R]
integer[R]
parts[R]
words[R]

Public Class Methods

new(money) click to toggle source
# File lib/rmb_chinese_yuan.rb, line 16
def initialize(money)
  @integer, @decimal = preprocess(money)
end

Public Instance Methods

convert() click to toggle source
# File lib/rmb_chinese_yuan.rb, line 20
def convert
  join(convert_integer, convert_decimal)
end

Private Instance Methods

convert_decimal() click to toggle source
# File lib/rmb_chinese_yuan.rb, line 54
def convert_decimal
  return DECIMAL_UNIT[0] if decimal.to_i.zero?

  jiao, fen = split_into_digits(decimal, direction: :tail, count: 2)

  if jiao.zero? && fen.nonzero?
    [NUMBERS[0], NUMBERS[fen], DECIMAL_UNIT[2]].join
  else
    res = [NUMBERS[jiao], DECIMAL_UNIT[1]].join
    res << [NUMBERS[fen],  DECIMAL_UNIT[2]].join if fen.nonzero?
    res
  end
end
convert_integer() click to toggle source
# File lib/rmb_chinese_yuan.rb, line 48
def convert_integer
  split_into_parts
  read_into_words
  join_words
end
join(integer_words, decimal_words) click to toggle source
# File lib/rmb_chinese_yuan.rb, line 68
def join(integer_words, decimal_words)
  if integer.to_i.zero? && decimal.to_i.nonzero?
    decimal_words
  else
    [integer_words, decimal_words].join
  end
end
join_words() click to toggle source
# File lib/rmb_chinese_yuan.rb, line 117
def join_words
  res = [part_yi, part_wan, part_ge].join
  res << INTEGER_UNIT[2]
end
part_ge() click to toggle source
# File lib/rmb_chinese_yuan.rb, line 140
def part_ge
  yi, wan, ge = parts

  if ge.zero?
    if yi.zero? && wan.zero?
      words[2]
    end
  else
    res = [words[2]]
    res.unshift NUMBERS[0] if wan.nonzero? && (ge / 1000).zero?
    res.join
  end

end
part_wan() click to toggle source
# File lib/rmb_chinese_yuan.rb, line 126
def part_wan
  yi, wan, ge = parts

  if wan.zero?
    if yi.nonzero? && ge.nonzero?
      NUMBERS[0]
    end
  else
    res = [words[1], INTEGER_UNIT[1]]
    res.unshift NUMBERS[0] if yi.nonzero? && (wan / 1000).zero?
    res.join
  end
end
part_yi() click to toggle source
# File lib/rmb_chinese_yuan.rb, line 122
def part_yi
  [words[0], INTEGER_UNIT[0]].join unless parts[0].zero?
end
preprocess(money) click to toggle source

Private: Process for type conversion, ‘,’ substitution, and ‘.’ split.

# File lib/rmb_chinese_yuan.rb, line 27
def preprocess(money)
  money = money.to_s

  fail ArgumentError, "Not a valid money<#{money}>" \
    unless money.match(/^[\d|,|\.]+/)

  integer, decimal = money.delete(',').split('.')
  decimal = decimal ? decimal[0, 2] : ''

  fail ArgumentError, "Integer part of money<#{money}> is invalid" \
    unless integer.match(/^\d*$/)

  fail ArgumentError, "Decimal part of money<#{money}> is invalid" \
    unless decimal.match(/^\d*$/)

  fail ArgumentError, "Integer part of money<#{money}> is longer than 12" \
    if integer.length > 12

  [integer, decimal]
end
read_integer(number) click to toggle source
# File lib/rmb_chinese_yuan.rb, line 91
def read_integer(number)
  return NUMBERS[0] if number.zero?

  numbers = split_into_digits(number)

  numbers.each_with_index.reduce('') do |str, (n, i)|
    if n.nonzero?
      str << [NUMBERS[n], PART_UNIT[i]].join
    elsif !str.empty? && i + 1 < 4 && numbers[i+1].nonzero?
      str << NUMBERS[0]
    else
      str
    end
  end
end
read_into_words() click to toggle source
# File lib/rmb_chinese_yuan.rb, line 87
def read_into_words
  @words = parts.reduce([]){ |ar, part| ar << read_integer(part) }
end
split_into_digits(number, direction: :head, count: 4) click to toggle source
# File lib/rmb_chinese_yuan.rb, line 107
def split_into_digits(number, direction: :head, count: 4)
  digits = number.to_s.chars.map(&:to_i)
  if direction == :head
    digits.unshift 0 while digits.count < count
  else
    digits.push 0 while digits.count < count
  end
  digits
end
split_into_parts() click to toggle source

Split money into three parts, each part is under 9999

# File lib/rmb_chinese_yuan.rb, line 77
def split_into_parts
  number = integer.to_i

  @parts = [
    number / 10**8,
    (number / 10**4) % 10**4,
    number % 10**4
  ]
end