ru_propisju 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gemtest ADDED
File without changes
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ === 1.0.0 / 2011-03-18
2
+
3
+ * Модуль вынут из RuTils
4
+
data/Manifest.txt ADDED
@@ -0,0 +1,6 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/ru_propisju.rb
6
+ test/test_ru_propisju.rb
data/README.rdoc ADDED
@@ -0,0 +1,48 @@
1
+ = ru_propisju
2
+
3
+ * http://github.com/julik/ru_propisju
4
+
5
+ == DESCRIPTION:
6
+
7
+ Выводит сумму прописью и суммы копеек, рублей и гривен. Помогает в выборе правильного числительного.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ Прекрасность.
12
+
13
+ == SYNOPSIS:
14
+
15
+ RuPropisju.propisju_shtuk(212.40, 2, "сволочь", "сволочи", "сволочей") #=> "двести двенадцать целых четыре десятых сволочи"
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * Прямые руки
20
+
21
+ == INSTALL:
22
+
23
+ sudo gem install ru_propisju
24
+
25
+ == LICENSE:
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2011 me@julik.nl
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ 'Software'), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.spec 'ru_propisju' do | p |
7
+ p.readme_file = 'README.rdoc'
8
+ p.extra_rdoc_files = FileList['*.rdoc'] + FileList['*.txt']
9
+
10
+ p.developer('Julik Tarkhanov', 'me@julik.nl')
11
+ end
12
+
13
+ # vim: syntax=ruby
@@ -0,0 +1,269 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $KCODE = 'u' if RUBY_VERSION < '1.9.0'
3
+
4
+ # Самый лучший, прекрасный, кривой и неотразимый суперпечататель суммы прописью для Ruby.
5
+ #
6
+ # RuPropisju.rublej(123) # "сто двадцать три рубля"
7
+ module RuPropisju
8
+
9
+ VERSION = '1.0.0'
10
+
11
+ # Выбирает нужный падеж существительного в зависимости от числа
12
+ #
13
+ # choose_plural(3, "штука", "штуки", "штук") #=> "штуки"
14
+ def choose_plural(amount, *variants)
15
+ mod_ten = amount % 10
16
+ mod_hundred = amount % 100
17
+ variant = if (mod_ten == 1 && mod_hundred != 11)
18
+ 1
19
+ else
20
+ if mod_ten >= 2 && mod_ten <= 4 && (mod_hundred <10 || mod_hundred % 100>=20)
21
+ 2
22
+ else
23
+ 3
24
+ end
25
+ end
26
+ variants[variant-1]
27
+ end
28
+
29
+
30
+ # Выводит целое или дробное число как сумму в рублях прописью
31
+ #
32
+ # rublej(345.2) #=> "триста сорок пять рублей двадцать копеек"
33
+ def rublej(amount)
34
+ pts = []
35
+
36
+ pts << propisju_shtuk(amount.to_i, 1, "рубль", "рубля", "рублей") unless amount.to_i == 0
37
+
38
+ if amount.kind_of?(Float)
39
+ remainder = (amount.divmod(1)[1]*100).round
40
+ if (remainder == 100)
41
+ pts = [propisju_shtuk(amount.to_i+1, 1, 'рубль', 'рубля', 'рублей')]
42
+ else
43
+ pts << propisju_shtuk(remainder.to_i, 2, 'копейка', 'копейки', 'копеек') unless remainder.to_i.zero?
44
+ end
45
+ end
46
+
47
+ pts.join(' ')
48
+ end
49
+
50
+ # Выбирает корректный вариант числительного в зависимости от рода и числа и оформляет сумму прописью
51
+ #
52
+ # propisju(243) => "двести сорок три"
53
+ # propisju(221, 2) => "двести двадцать одна"
54
+ def propisju(amount, gender = 1)
55
+ if amount.is_a?(Integer) || amount.is_a?(Bignum)
56
+ propisju_int(amount, gender)
57
+ else # также сработает для Decimal, дробные десятичные числительные в долях поэтому женского рода
58
+ propisju_float(amount)
59
+ end
60
+ end
61
+
62
+ # Выводит целое или дробное число как сумму в гривнах прописью
63
+ #
64
+ # griven(32) #=> "тридцать две гривны"
65
+ def griven(amount)
66
+ pts = []
67
+
68
+ pts << propisju_int(amount.to_i, 2, "гривна", "гривны", "гривен") unless amount.to_i == 0
69
+ if amount.kind_of?(Float)
70
+ remainder = (amount.divmod(1)[1]*100).round
71
+ if (remainder == 100)
72
+ pts = [propisju_int(amount.to_i + 1, 2, 'гривна', 'гривны', 'гривен')]
73
+ else
74
+ pts << propisju_int(remainder.to_i, 2, 'копейка', 'копейки', 'копеек')
75
+ end
76
+ end
77
+
78
+ pts.join(' ')
79
+ end
80
+
81
+ # Выводит сумму прописью в рублях по количеству копеек
82
+ #
83
+ # kopeek(343) #=> "три рубля сорок три копейки"
84
+ def kopeek(amount)
85
+ rublej(amount / 100.0)
86
+ end
87
+
88
+ # Выводит сумму данного существительного прописью и выбирает правильное число и падеж
89
+ #
90
+ # RuPropisju.propisju_shtuk(21, 3, "колесо", "колеса", "колес") #=> "двадцать одно колесо"
91
+ # RuPropisju.propisju_shtuk(21, 1, "мужик", "мужика", "мужиков") #=> "двадцать один мужик"
92
+ def propisju_shtuk(items, gender = 1, *forms)
93
+ r = if items == items.to_i
94
+ [propisju(items, gender), choose_plural(items, *forms)]
95
+ else
96
+ [propisju(items, gender), forms[1]]
97
+ end
98
+
99
+ r.join(" ")
100
+ end
101
+
102
+ private
103
+
104
+ def compose_ordinal(into, remaining_amount, gender, one_item='', two_items='', five_items='')
105
+ rest, rest1, chosen_ordinal, ones, tens, hundreds = [nil]*6
106
+ #
107
+ rest = remaining_amount % 1000
108
+ remaining_amount = remaining_amount / 1000
109
+ if rest == 0
110
+ # последние три знака нулевые
111
+ into = five_items + " " if into == ""
112
+ return [into, remaining_amount]
113
+ end
114
+ #
115
+ # начинаем подсчет с Rest
116
+ chosen_ordinal = five_items
117
+
118
+ # сотни
119
+ hundreds = case rest / 100
120
+ when 0 then ""
121
+ when 1 then "сто "
122
+ when 2 then "двести "
123
+ when 3 then "триста "
124
+ when 4 then "четыреста "
125
+ when 5 then "пятьсот "
126
+ when 6 then "шестьсот "
127
+ when 7 then "семьсот "
128
+ when 8 then "восемьсот "
129
+ when 9 then "девятьсот "
130
+ end
131
+
132
+ # десятки
133
+ rest = rest % 100
134
+ rest1 = rest / 10
135
+ ones = ""
136
+ tens = case rest1
137
+ when 0 then ""
138
+ when 1 # особый случай
139
+ case rest
140
+ when 10 then "десять "
141
+ when 11 then "одиннадцать "
142
+ when 12 then "двенадцать "
143
+ when 13 then "тринадцать "
144
+ when 14 then "четырнадцать "
145
+ when 15 then "пятнадцать "
146
+ when 16 then "шестнадцать "
147
+ when 17 then "семнадцать "
148
+ when 18 then "восемнадцать "
149
+ when 19 then "девятнадцать "
150
+ end
151
+ when 2 then "двадцать "
152
+ when 3 then "тридцать "
153
+ when 4 then "сорок "
154
+ when 5 then "пятьдесят "
155
+ when 6 then "шестьдесят "
156
+ when 7 then "семьдесят "
157
+ when 8 then "восемьдесят "
158
+ when 9 then "девяносто "
159
+ end
160
+ #
161
+ if rest1 < 1 or rest1 > 1 # единицы
162
+ case rest % 10
163
+ when 1
164
+ ones = case gender
165
+ when 1 then "один "
166
+ when 2 then "одна "
167
+ when 3 then "одно "
168
+ end
169
+ chosen_ordinal = one_item
170
+ when 2
171
+ if gender == 2
172
+ ones = "две "
173
+ else
174
+ ones = "два "
175
+ end
176
+ chosen_ordinal = two_items
177
+ when 3
178
+ ones = "три "
179
+ chosen_ordinal = two_items
180
+ when 4
181
+ ones = "четыре "
182
+ chosen_ordinal = two_items
183
+ when 5
184
+ ones = "пять "
185
+ when 6
186
+ ones = "шесть "
187
+ when 7
188
+ ones = "семь "
189
+ when 8
190
+ ones = "восемь "
191
+ when 9
192
+ ones = "девять "
193
+ end
194
+ end
195
+
196
+ plural = [hundreds, tens, ones, chosen_ordinal, " ", into].join.strip
197
+ return [plural, remaining_amount]
198
+ end
199
+
200
+ DECIMALS = %w( целая десятая сотая тысячная десятитысячная стотысячная
201
+ миллионная десятимиллионная стомиллионная миллиардная десятимиллиардная
202
+ стомиллиардная триллионная
203
+ ).map{|e| [e, e.gsub(/ая$/, "ых"), e.gsub(/ая$/, "ых"), ] }.freeze
204
+
205
+ # Выдает сумму прописью с учетом дробной доли. Дробная доля округляется до миллионной, или (если
206
+ # дробная доля оканчивается на нули) до ближайшей доли ( 500 тысячных округляется до 5 десятых).
207
+ # Дополнительный аргумент - род существительного (1 - мужской, 2- женский, 3-средний)
208
+ def propisju_float(num)
209
+
210
+ # Укорачиваем до триллионной доли
211
+ formatted = ("%0.#{DECIMALS.length}f" % num).gsub(/0+$/, '')
212
+ wholes, decimals = formatted.split(/\./)
213
+
214
+ return propisju_int(wholes.to_i) if decimals.to_i.zero?
215
+
216
+ whole_st = propisju_shtuk(wholes.to_i, 2, *DECIMALS[0])
217
+
218
+ rem_st = propisju_shtuk(decimals.to_i, 2, *DECIMALS[decimals.length])
219
+ [whole_st, rem_st].compact.join(" ")
220
+ end
221
+
222
+ # Выполняет преобразование числа из цифрого вида в символьное
223
+ #
224
+ # amount - числительное
225
+ # gender = 1 - мужской, = 2 - женский, = 3 - средний
226
+ # one_item - именительный падеж единственного числа (= 1)
227
+ # two_items - родительный падеж единственного числа (= 2-4)
228
+ # five_items - родительный падеж множественного числа ( = 5-10)
229
+ #
230
+ # Примерно так:
231
+ # propisju(42, 1, "сволочь", "сволочи", "сволочей") # => "сорок две сволочи"
232
+ def propisju_int(amount, gender = 1, one_item = '', two_items = '', five_items = '')
233
+
234
+ return "ноль " + five_items if amount.zero?
235
+
236
+ # единицы
237
+ into, remaining_amount = compose_ordinal('', amount, gender, one_item, two_items, five_items)
238
+
239
+ return into if remaining_amount == 0
240
+
241
+ # тысячи
242
+ into, remaining_amount = compose_ordinal(into, remaining_amount, 2, "тысяча", "тысячи", "тысяч")
243
+
244
+ return into if remaining_amount == 0
245
+
246
+ # миллионы
247
+ into, remaining_amount = compose_ordinal(into, remaining_amount, 1, "миллион", "миллиона", "миллионов")
248
+
249
+ return into if remaining_amount == 0
250
+
251
+ # миллиарды
252
+ into, remaining_amount = compose_ordinal(into, remaining_amount, 1, "миллиард", "миллиарда", "миллиардов")
253
+ return into
254
+ end
255
+
256
+ alias_method :rublja, :rublej
257
+ alias_method :rubl, :rublej
258
+
259
+ alias_method :kopeika, :kopeek
260
+ alias_method :kopeiki, :kopeek
261
+
262
+ alias_method :grivna, :griven
263
+ alias_method :grivny, :griven
264
+
265
+
266
+ public_instance_methods(true).map{|m| module_function(m) }
267
+
268
+ module_function :propisju_int, :propisju_float, :compose_ordinal
269
+ end
@@ -0,0 +1,69 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $KCODE = 'u' if RUBY_VERSION < '1.9.0'
3
+
4
+ require "test/unit"
5
+ require "ru_propisju"
6
+
7
+ class TestRuPropisju < Test::Unit::TestCase
8
+
9
+ def test_propisju_for_ints
10
+ assert_equal "пятьсот двадцать три", RuPropisju.propisju(523)
11
+ assert_equal "шесть тысяч семьсот двадцать семь", RuPropisju.propisju(6727)
12
+ assert_equal "восемь миллионов шестьсот пятьдесят два", RuPropisju.propisju(8000652, 1)
13
+ assert_equal "восемь миллионов шестьсот пятьдесят две", RuPropisju.propisju(8000652, 2)
14
+ assert_equal "восемь миллионов шестьсот пятьдесят два", RuPropisju.propisju(8000652, 3)
15
+ assert_equal "сорок пять", RuPropisju.propisju(45)
16
+ assert_equal "пять", RuPropisju.propisju(5)
17
+ assert_equal "шестьсот двенадцать", RuPropisju.propisju(612)
18
+ end
19
+
20
+ def test_propisju_shtuk
21
+ assert_equal "шесть целых", RuPropisju.propisju_shtuk(6, 2, "целая", "целых", "целых")
22
+ assert_equal "двадцать пять колес", RuPropisju.propisju_shtuk(25, 3, "колесо", "колеса", "колес")
23
+ assert_equal "двадцать одна подстава", RuPropisju.propisju_shtuk(21, 2, "подстава", "подставы", "подстав")
24
+ assert_equal "двести двенадцать сволочей", RuPropisju.propisju_shtuk(212.00, 2, "сволочь", "сволочи", "сволочей")
25
+ assert_equal "двести двенадцать целых четыре десятых куска", RuPropisju.propisju_shtuk(212.40, 2, "кусок", "куска", "кусков")
26
+ end
27
+
28
+ def test_propisju_for_floats
29
+ assert_equal "шесть целых пять десятых", RuPropisju.propisju(6.50)
30
+ assert_equal "триста сорок одна целая девять десятых", RuPropisju.propisju(341.9)
31
+ assert_equal "триста сорок одна целая двести сорок пять тысячных", RuPropisju.propisju(341.245)
32
+ assert_equal "двести три целых сорок одна сотая", RuPropisju.propisju(203.41)
33
+ assert_equal "четыреста сорок две целых пять десятых", RuPropisju.propisju(442.50000)
34
+ end
35
+
36
+ def test_choose_plural
37
+ assert_equal "чемодана", RuPropisju.choose_plural(523, "чемодан", "чемодана", "чемоданов")
38
+ assert_equal "партий", RuPropisju.choose_plural(6727, "партия", "партии", "партий")
39
+ assert_equal "козлов", RuPropisju.choose_plural(45, "козел", "козла", "козлов")
40
+ assert_equal "колес", RuPropisju.choose_plural(260, "колесо", "колеса", "колес")
41
+ end
42
+
43
+ def test_rublej
44
+ assert_equal "сто двадцать три рубля", RuPropisju.rublej(123)
45
+ assert_equal "триста сорок три рубля двадцать копеек", RuPropisju.rublej(343.20)
46
+ assert_equal "сорок две копейки", RuPropisju.rublej(0.4187)
47
+ assert_equal "триста тридцать два рубля", RuPropisju.rublej(331.995)
48
+ assert_equal "один рубль", RuPropisju.rubl(1)
49
+ assert_equal "три рубля четырнадцать копеек", RuPropisju.rublja(3.14)
50
+ end
51
+
52
+ def test_griven
53
+ assert_equal "сто двадцать три гривны", RuPropisju.griven(123)
54
+ assert_equal "сто двадцать четыре гривны", RuPropisju.griven(124)
55
+ assert_equal "триста сорок три гривны двадцать копеек", RuPropisju.griven(343.20)
56
+ assert_equal "сорок две копейки", RuPropisju.griven(0.4187)
57
+ assert_equal "триста тридцать две гривны", RuPropisju.griven(331.995)
58
+ assert_equal "одна гривна", RuPropisju.grivna(1)
59
+ assert_equal "три гривны четырнадцать копеек", RuPropisju.grivny(3.14)
60
+ end
61
+
62
+ def test_kopeek
63
+ assert_equal "сто двадцать три рубля", RuPropisju.kopeek(12300)
64
+ assert_equal "три рубля четырнадцать копеек", RuPropisju.kopeek(314)
65
+ assert_equal "тридцать две копейки", RuPropisju.kopeek(32)
66
+ assert_equal "двадцать одна копейка", RuPropisju.kopeika(21)
67
+ assert_equal "три копейки", RuPropisju.kopeiki(3)
68
+ end
69
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ru_propisju
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Julik Tarkhanov
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-28 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: hoe
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 41
30
+ segments:
31
+ - 2
32
+ - 9
33
+ - 1
34
+ version: 2.9.1
35
+ type: :development
36
+ version_requirements: *id001
37
+ description: "\xD0\x92\xD1\x8B\xD0\xB2\xD0\xBE\xD0\xB4\xD0\xB8\xD1\x82 \xD1\x81\xD1\x83\xD0\xBC\xD0\xBC\xD1\x83 \xD0\xBF\xD1\x80\xD0\xBE\xD0\xBF\xD0\xB8\xD1\x81\xD1\x8C\xD1\x8E \xD0\xB8 \xD1\x81\xD1\x83\xD0\xBC\xD0\xBC\xD1\x8B \xD0\xBA\xD0\xBE\xD0\xBF\xD0\xB5\xD0\xB5\xD0\xBA, \xD1\x80\xD1\x83\xD0\xB1\xD0\xBB\xD0\xB5\xD0\xB9 \xD0\xB8 \xD0\xB3\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD0\xBD. \xD0\x9F\xD0\xBE\xD0\xBC\xD0\xBE\xD0\xB3\xD0\xB0\xD0\xB5\xD1\x82 \xD0\xB2 \xD0\xB2\xD1\x8B\xD0\xB1\xD0\xBE\xD1\x80\xD0\xB5 \xD0\xBF\xD1\x80\xD0\xB0\xD0\xB2\xD0\xB8\xD0\xBB\xD1\x8C\xD0\xBD\xD0\xBE\xD0\xB3\xD0\xBE \xD1\x87\xD0\xB8\xD1\x81\xD0\xBB\xD0\xB8\xD1\x82\xD0\xB5\xD0\xBB\xD1\x8C\xD0\xBD\xD0\xBE\xD0\xB3\xD0\xBE."
38
+ email:
39
+ - me@julik.nl
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files:
45
+ - History.txt
46
+ - Manifest.txt
47
+ - README.rdoc
48
+ files:
49
+ - History.txt
50
+ - Manifest.txt
51
+ - README.rdoc
52
+ - Rakefile
53
+ - lib/ru_propisju.rb
54
+ - test/test_ru_propisju.rb
55
+ - .gemtest
56
+ has_rdoc: true
57
+ homepage: http://github.com/julik/ru_propisju
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --main
63
+ - README.rdoc
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ hash: 3
81
+ segments:
82
+ - 0
83
+ version: "0"
84
+ requirements: []
85
+
86
+ rubyforge_project: ru_propisju
87
+ rubygems_version: 1.4.1
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: "\xD0\x92\xD1\x8B\xD0\xB2\xD0\xBE\xD0\xB4\xD0\xB8\xD1\x82 \xD1\x81\xD1\x83\xD0\xBC\xD0\xBC\xD1\x83 \xD0\xBF\xD1\x80\xD0\xBE\xD0\xBF\xD0\xB8\xD1\x81\xD1\x8C\xD1\x8E \xD0\xB8 \xD1\x81\xD1\x83\xD0\xBC\xD0\xBC\xD1\x8B \xD0\xBA\xD0\xBE\xD0\xBF\xD0\xB5\xD0\xB5\xD0\xBA, \xD1\x80\xD1\x83\xD0\xB1\xD0\xBB\xD0\xB5\xD0\xB9 \xD0\xB8 \xD0\xB3\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD0\xBD"
91
+ test_files:
92
+ - test/test_ru_propisju.rb