Module: YaKansuji

Defined in:
lib/ya_kansuji.rb,
lib/ya_kansuji/version.rb,
lib/ya_kansuji/formatter.rb,
lib/ya_kansuji/core_refine.rb,
lib/ya_kansuji/formatter/gov.rb,
lib/ya_kansuji/formatter/lawyer.rb,
lib/ya_kansuji/formatter/simple.rb,
lib/ya_kansuji/formatter/judic_h.rb,
lib/ya_kansuji/formatter/judic_v.rb

Overview

Simple kansuji formatter

Defined Under Namespace

Modules: CoreRefine, Formatter

Constant Summary collapse

UNIT_EXP3 =
%w(  ).freeze
UNIT_EXP4 =
%w(     𥝱       恒河沙 阿僧祇 那由他 不可思議 無量大数).freeze
MAX_VALUE =
(10_000**(UNIT_EXP4.size + 1)) - 1
UNIT_FRAC =
%w(           
模糊 逡巡 須臾 瞬息 弾指 刹那 六徳 虚空 清浄).freeze
FRAC_BASE =
10**UNIT_FRAC.size
NUM_ALT_CHARS =
'〇一二三四五六七八九0123456789零壱壹弌弐貳貮参參弎肆伍陸漆質柒捌玖拾什陌佰阡仟萬秭'
NUM_NORMALIZED_CHARS =
'01234567890123456789011122233345677789十十百百千千万𥝱'
REGEXP_PART =

rubocop:disable Lint/DuplicateRegexpCharacterClassElement

%r{
  [
    #{(NUM_ALT_CHARS + NUM_NORMALIZED_CHARS).chars.uniq.join}
    #{(UNIT_EXP3 + UNIT_EXP4).find_all { |u| u.length == 1 }.join}
    卄廿卅丗卌皕
  ] |
  #{UNIT_EXP4.find_all { |u| u.length > 1 }.join('|')}
}x.freeze
REGEXP =

rubocop:enable Lint/DuplicateRegexpCharacterClassElement

/(?:マイナス)?(?:#{REGEXP_PART})+/.freeze
VERSION =
'1.3.0'
@@formatters =
{}

Class Method Summary collapse

Class Method Details

.formatter(sym) ⇒ Object



135
136
137
# File 'lib/ya_kansuji.rb', line 135

def formatter(sym)
  @@formatters[sym]
end

.formattersObject



139
140
141
# File 'lib/ya_kansuji.rb', line 139

def formatters
  @@formatters
end

.normalize_value(num) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/ya_kansuji.rb', line 87

def normalize_value(num)
  return num if num.is_a?(Integer)

  unless num.is_a?(Numeric)
    return num._to_i_ya_kansuji_orig if num.respond_to?(:_to_i_ya_kansuji_orig)

    return num.to_i
  end

  return num.to_i unless num.respond_to?(:truncate)

  num = rational_from_float(num) if num.is_a?(Float)
  num = num.to_r if num.respond_to?(:to_r)
  int = num.truncate
  scaled = ((num - int) * FRAC_BASE).round
  if scaled.abs >= FRAC_BASE
    if scaled.negative?
      int -= 1
    else
      int += 1
    end
    scaled = 0
  end
  scaled.zero? ? int : Rational((int * FRAC_BASE) + scaled, FRAC_BASE)
end

.rational_from_float(num) ⇒ Object

Raises:

  • (FloatDomainError)


113
114
115
116
117
118
119
120
121
122
123
# File 'lib/ya_kansuji.rb', line 113

def rational_from_float(num)
  raise FloatDomainError, num.to_s if num.nan? || num.infinite?

  m = /\A(-?)(\d+)(?:\.(\d+))?(?:e([+-]?\d+))?\z/.match(num.to_s)
  raise FloatDomainError, num.to_s unless m

  ret = Rational(Integer(m[2] + (m[3] || ''), 10))
  ret = -ret unless m[1].empty?
  exp = (m[4] ? Integer(m[4], 10) : 0) - (m[3] ? m[3].size : 0)
  exp >= 0 ? ret * (10**exp) : ret / (10**-exp)
end

.register_formatter(sym, proc = nil, &block) ⇒ Object



125
126
127
128
129
130
131
132
133
# File 'lib/ya_kansuji.rb', line 125

def register_formatter(sym, proc = nil, &block)
  if block_given?
    @@formatters[sym] = block
  elsif proc.respond_to? :call
    @@formatters[sym] = proc
  else
    raise ArgumentError, 'Registering invalid formatter.'
  end
end

.to_i(str) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/ya_kansuji.rb', line 30

def to_i(str)
  str = str.to_s.tr(NUM_ALT_CHARS, NUM_NORMALIZED_CHARS)
  str.gsub!(/[,,、[:space:]]/, '')
  matched = REGEXP.match(str) or return 0
  ret3 = 0
  ret4 = 0
  curnum = nil
  if str.respond_to? :_to_i_ya_kansuji_orig
    to_i_meth = :_to_i_ya_kansuji_orig
  else
    to_i_meth = :to_i
  end
  matched[0].scan(REGEXP_PART).each do |c|
    case c
    when '1', '2', '3', '4', '5', '6', '7', '8', '9'
      if curnum
        curnum *= 10
      else
        curnum = 0
      end
      curnum += c.public_send(to_i_meth)
    when '0'
      curnum and curnum *= 10
    when '', '廿'
      ret3 += 20
      curnum = nil
    when '', ''
      ret3 += 30
      curnum = nil
    when ''
      ret3 += 40
      curnum = nil
    when ''
      ret3 += 200
      curnum = nil
    when *UNIT_EXP4
      if curnum
        ret3 += curnum
        curnum = nil
      end
      ret3 = 1 if ret3.zero?
      ret4 += ret3 * (10**((UNIT_EXP4.index(c) + 1) * 4))
      ret3 = 0
    when *UNIT_EXP3
      curnum ||= 1
      ret3 += curnum * (10**(UNIT_EXP3.index(c) + 1))
      curnum = nil
    end
  end
  if curnum
    ret3 += curnum
    curnum = nil
  end
  ret = ret4 + ret3
  matched[0].start_with?('マイナス') ? -ret : ret
end

.to_kan(num, formatter = :simple, options = {}) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/ya_kansuji.rb', line 143

def to_kan(num, formatter = :simple, options = {})
  num = normalize_value(num)
  if num.truncate.abs > MAX_VALUE
    raise RangeError, "Value must be between #{-MAX_VALUE} and #{MAX_VALUE}"
  end

  return "マイナス#{to_kan(-num, formatter, options)}" if num.negative?

  if formatter.respond_to? :call
    formatter.call num, options
  elsif @@formatters[formatter]
    @@formatters[formatter].call num, options
  else
    raise ArgumentError, "Unable to find formatter #{formatter}"
  end
end