runumerals 1.0.2

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.
Files changed (8) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +6 -0
  3. data/LICENSE +21 -0
  4. data/README.md +109 -0
  5. data/Rakefile +17 -0
  6. data/lib/ru_numerals.rb +929 -0
  7. data/lib/version.rb +4 -0
  8. metadata +92 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 50737e4e66677d78dffb87b75fde135d380ed37e
4
+ data.tar.gz: 6cfb02594f54885cee13bc1769dadf83f3b61d2b
5
+ SHA512:
6
+ metadata.gz: 452e30f74ae5357d46c5faa11de415b5e0c7627100b35334c84342d0683a935eb432da79b2a8e1f39212941fb12c37cae6bc52cdb338d81b27b86812a4c070ea
7
+ data.tar.gz: 8ce338635748f9910500993aec7525ee81dff3dd200d56e3574531dd66e176a3d58ccedcf3e33f7cc2e36fc7e83aa7dc8c12f5dc07887fe0f27230ff3388d01e
data/.yardopts ADDED
@@ -0,0 +1,6 @@
1
+ --protected
2
+ --title "RuNumerals"
3
+ --readme README.md
4
+ -
5
+
6
+ LICENSE
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Boris Fifelin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,109 @@
1
+ Runumerals: Convertation of numeric values to russian numerals
2
+ ========
3
+ **Authors**: Sergey Abel, Boris Fifelin
4
+
5
+ **Copyright**: 1996 - 2018
6
+
7
+ **License**: MIT License
8
+
9
+ **Latest Version**: 1.0.2
10
+
11
+ **Ruby Version**: >= 1.9.2
12
+
13
+ Synopsis
14
+ --------
15
+ Runumerals is a Ruby module providing methods that convert numeric values to russian numerals.
16
+
17
+ The rest of this file is in Russian as the use of this module implies the knowledge of the Russian language.
18
+
19
+ Модуль RuNumerals содержит функции для работы с русскими числительными.
20
+ Основное предназначение - преобразование числительных для финансовых документов (не забудьте про capitalize ;-).
21
+ Также иногда требуют нумерацию листов в виде "лист 2 из 35 листов", здесь будет полезна способность правильно давать склонение сущесвительного в зависимости от количества.
22
+ Если найдете ещё какие-либо применения, буду только рад.
23
+
24
+
25
+ Возможности
26
+ --------
27
+ 1. Преобразование в количественные числительные
28
+ 2. Преобразование в порядковые числительные
29
+ 3. Преобразование числовых предствалений дат, времени, денежных единиц, дробей
30
+ 4. Согласование по роду, падежу; возможность задать свою грамматику
31
+ 5. Возможность расширения классов Ruby методами модуля RuNumerals (Ruby way?)
32
+
33
+ Feci quod potui, faciant meliora potentes :-)
34
+
35
+ Установка
36
+ ---------
37
+
38
+ $ gem install runumerals
39
+
40
+ Примеры
41
+ ---------
42
+
43
+ ```
44
+
45
+ require 'ru_numerals'
46
+ RuNumerals::ru_numeral(154,'д') #=> "ста пятидесяти четырём"
47
+ RuNumerals::ru_numeral(101,'','с',1) #=> "ноль тысяч сто одно"
48
+ RuNumerals::ru_numeral(1,'',RuNumerals::RUBGRAM,-1) #=> "рубль"
49
+ RuNumerals::ru_numeral(2,'',RuNumerals::RUBGRAM,-1) #=> "рубля"
50
+ RuNumerals::ru_ordinal(1) #=> "первый"
51
+ RuNumerals::ru_ordinal(2) #=> "второй"
52
+ RuNumerals::ru_ordinal(250000000,'в','ж') #=> "двухсотпятидесятимиллионную"
53
+ RuNumerals::ru_ordinal(5,'т','ж',true) #=> "пятыми"
54
+ RuNumerals::ru_ordinal(-5,'в','о') #=> "минус пятого"
55
+ RuNumerals::ru_date(Time.now) #=> "девятое ноября две тысячи шестнадцатого года"
56
+ RuNumerals::ru_date(Time.now,"д",spellyy: false) #=> "девятому ноября 2016 года"
57
+ RuNumerals::ru_date(Time.now,spelldd: false, spellyy: false) #=> "9 ноября 2016 года"
58
+ RuNumerals::ru_time(Time.now) #=> "восемнадцать часов пятьдесят две минуты двадцать секунд"
59
+ RuNumerals::ru_time(Time.now,"д",spellhh: false , spellmm: false , spellss: false)
60
+ #=> "18 часам 52 минутам 20 секундам"
61
+ RuNumerals::ru_time(Time.now,'',spellhh: false , spellmm: false , noseconds: false)
62
+ #=> "18 часов 52 минуты"
63
+ RuNumerals::ru_money(123.029,"и",RuNumerals::RUBGRAM,RuNumerals::KOPGRAM) #=> "сто двадцать три рубля три копейки"
64
+ RuNumerals::ru_money(123.029,"р",RuNumerals::RUBGRAM,RuNumerals::KOPGRAM, spellkop: false) #=> "ста двадцати трёх рублей 03 копеек"
65
+ RuNumerals::ru_money(123.029,"т",nil,RuNumerals::KOPGRAM) #=> "двенадцатью тысячами тремястами тремя копейками"
66
+ RuNumerals::ru_fractional(Rational(8,7)) #=> "одна целая одна седьмая"
67
+ RuNumerals::ru_fractional(Rational(8,7),"",improper: true) #=> "восемь седьмых"
68
+ RuNumerals::ru_fractional(Rational(6,2),"т") #=> "тремя"
69
+ RuNumerals::ru_fractional(1001.02) #=> "одна тысяча одна целая две сотых"
70
+ RuNumerals::extend(Integer) #=> nil
71
+ 1.ru_numeral #=> "один"
72
+ 1.ru_ordinal("д") #=> "первому"
73
+ RuNumerals::extend(Float,:ru_rubleskopecks) #=> nil
74
+ 1.25.ru_rubleskopecks("и",spellkop: false) #=> "один рубль 25 копеек"
75
+ ```
76
+
77
+ Замечания
78
+ ---------
79
+ Общие параметры для ряда функций:
80
+
81
+ * gr_casus (<tt>String</tt>), значение по умолчанию: "и" - падеж числительного
82
+ Может принимать значения "и","р","д","в","т" или "п" (первая буква названия падежа)
83
+
84
+ * grammar (<tt>String</tt>), значение по умолчанию: "мн",
85
+ описывает грамматику (род, одушевлённость/неодушевлённость, склонение по падежам).
86
+
87
+ Имеет вид: <tt>"[мжс][но]|И1|Р1|Д1|В1|Т1|П1|И2|Р2|Д2|В2|Т2|П2"</tt> где
88
+
89
+ 1. \[мжс\] указывет род ("м" - мужской, "ж" - женский, "с" - средний)
90
+ 2. \[но\] указывет одушевлённость: "н" для неодушевлённых, "о" для одушевлённых
91
+ 3. склонение по падежам (знак | - разделитель между падежными формами):
92
+ "И1" - форма для именительного падежа ед. ч., ... , "П2" - форма предложного падежа мн. ч.
93
+
94
+ Если в грамматике не указаны падежные формы, то, соответсвенно, склоняемое с числительным слово не выводится.
95
+
96
+ Примеры грамматик:
97
+
98
+ ```
99
+
100
+ "мн|этаж|этажа|этажу|этаж|этажом|этаже|этажи|этажей|этажам|этажи|этажами|этажах"
101
+ "мо|человек|человека|человеку|человека|человеком|человеке|человеки|человек|человекам|человеков|человеками|человеках"
102
+ "жн" # только согласование числительного по роду
103
+ ```
104
+
105
+ * Будьте осторожны с грамматиками. Например, множественное число слова <i>человек</i> - <i>люди</i> (супплетивная форма).
106
+ Но с числительными употрбеляется именно <i>человеки</i> (не в именительном падеже, разумеется)
107
+
108
+ * Также могут возникнуть проблемы с предложным падежом - в некоторых случаях требуется его другая форма (местный падеж).
109
+ Например, "в 1965 <i>году</i>", а не "<i>годе</i>", "в третьем <i>ряду</i>", "в первом <i>часу</i>" и т.п.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/lib/version.rb')
2
+
3
+ task :build => :gendoc do
4
+ system "gem build runumerals.gemspec"
5
+ end
6
+
7
+
8
+ task :gendoc do
9
+ system "yardoc"
10
+ end
11
+
12
+
13
+ task :release => :build do
14
+ system "gem push axlsx-#{RuNumerals::VERSION}.gem"
15
+ end
16
+
17
+ task :default => :build
@@ -0,0 +1,929 @@
1
+ # encoding: UTF-8
2
+ # Russian nurerals
3
+ #
4
+ # Copyright (c) 1996 Sergey Abel, (c) 2016 Boris Fifelin
5
+ #
6
+ # Licensed under the same terms as Ruby. No warranty is provided.
7
+ #
8
+ # Feci quod potui, faciant meliora potentes :-)
9
+ #
10
+ # RuNumerals contains methods that convert numeric values to russian numerals.
11
+ # The description and comments are in Russian as the use of this module implies
12
+ # the knowledge of the Russian language.
13
+ #
14
+ # Модуль RuNumerals содержит функции для работы с русскими числительными.
15
+ # Основное предназначение - преобразование числительных для финансовых документов (не забудьте про capitalize ;-).
16
+ # Также иногда требуют нумерацию листов в виде "лист 2 из 35 листов", здесь будет полезна
17
+ # способность правильно давать склонение сущесвительного в зависимости от количества.
18
+ # Если найдете ещё какие-либо применения, буду только рад.
19
+ #
20
+ # Общие параметры для ряда функций:
21
+ #
22
+ # * grammatical_case (+String+), значение по умолчанию: "и" - падеж числительного
23
+ # Может принимать значения "и","р","д","в","т" или "п" (первая буква названия падежа)
24
+ # * grammar (+String+), значение по умолчанию: "мн",
25
+ # описывает грамматику (род, одушевлённость/неодушевлённость, склонение по падежам).
26
+ #
27
+ # Имеет вид: <tt>"[мжс][но]|И1|Р1|Д1|В1|Т1|П1|И2|Р2|Д2|В2|Т2|П2"</tt> где
28
+ # 1. \[мжс\] указывет род ("м" - мужской, "ж" - женский, "с" - средний)
29
+ # 2. \[но\] указывет одушевлённость: "н" для неодушевлённых, "о" для одушевлённых
30
+ # 3. склонение по падежам (знак | - разделитель между падежными формами):
31
+ # "И1" - форма для именительного падежа ед. ч., ... , "П2" - форма предложного падежа мн. ч.
32
+ # Если в грамматике не указаны падежные формы, то, соответсвенно, склоняемое с числительным слово не выводится.
33
+ #
34
+ # Примеры грамматик:
35
+ #
36
+ # "мн|этаж|этажа|этажу|этаж|этажом|этаже|этажи|этажей|этажам|этажи|этажами|этажах"
37
+ # "мо|человек|человека|человеку|человека|человеком|человеке|человеки|человек|человекам|человеков|человеками|человеках"
38
+ # "жн" # только согласование числительного по роду
39
+ #
40
+ # Замечания:
41
+ # - Будьте осторожны с грамматиками, например, множественное число слова <i>человек</i> - <i>люди</i> (супплетивная форма).
42
+ # Но с числительными употрбеляется именно <i>человеки</i> (не в именительном падеже, разумеется)
43
+ # - Также могут возникнуть проблемы с предложным падежом - в некоторых случаях требуется его другая форма (местный падеж).
44
+ # Например, "в 1961 <i>году</i>", а не <i>годе</i>, "в третьем <i>ряду</i>", "в первом <i>часу</i>" и т.п.
45
+
46
+ require 'version.rb'
47
+
48
+ module RuNumerals
49
+ # RuNumerals contains methods that convert numeric values to russian numerals.
50
+ # The description and comments are in Russian as the use of this module implies the knowledge of the Russian language.
51
+
52
+ EXTEND_MAP={Integer => [:ru_numeral, :ru_ordinal],
53
+ Float => [:ru_fractional, :ru_money, :ru_rubles, :ru_kopecks, :ru_rubleskopecks,
54
+ :ru_dollars, :ru_cents, :ru_dollarscents, :ru_euros, :ru_eurocents, :ru_euroseurocents],
55
+ Rational => [:ru_fractional],
56
+ Time => [:ru_date, :ru_time]}
57
+ private_constant :EXTEND_MAP
58
+ CASUS_STR="ирдвтп"
59
+ private_constant :CASUS_STR
60
+ ORDWORD=[nil,"тысяч","миллион","миллиард","триллион","квадриллион","квинтиллион","секстиллион","септиллион","октиллион","нониллион",
61
+ "дециллион","ундециллион","додециллион","тредециллион","кваттуордециллион",
62
+ "квиндециллион","седециллион","септдециллион","октодециллион","новемдециллион",
63
+ "вигинтиллион","анвигинтиллион","дуовигинтиллион","тревигинтиллион","кватторвигинтиллион",
64
+ "квинвигинтиллион","сексвигинтиллион","септемвигинтиллион","октовигинтиллион","новемвигинтиллион",
65
+ "тригинтиллион","антригинтиллион","дуотригинтиллион","третригинтиллион","кваттортригинтиллион",
66
+ "квинтригинтиллион","секстригинтиллион","септемтригинтиллион","октотригинтиллион","новемтригинтиллион",
67
+ "квадрагинтиллион","анквадрагинтиллион","дуоквадрагинтиллион","треквадрагинтиллион","кватторквадрагинтиллион",
68
+ "квинквадрагинтиллион","сексквадрагинтиллион","септемквадрагинтиллион","октоквадрагинтиллион","новемквадрагинтиллион",
69
+ "квинквагинтиллион","анквинквагинтиллион","дуоквинквагинтиллион","треквинквагинтиллион","кватторквинквагинтиллион",
70
+ "квинквинквагинтиллион","сексквинквагинтиллион","септемквинквагинтиллион","октоквинквагинтиллион","новемквинквагинтиллион",
71
+ "сексагинтиллион","ансексагинтиллион","дуосексагинтиллион","тресексагинтиллион","кватторсексагинтиллион",
72
+ "квинсексагинтиллион","секссексагинтиллион","септемсексагинтиллион","октосексагинтиллион","новемсексагинтиллион",
73
+ "септуагинтиллион","ансептуагинтиллион","дуосептуагинтиллион","тресептуагинтиллион","кватторсептуагинтиллион",
74
+ "квинсептуагинтиллион","секссептуагинтиллион","септемсептуагинтиллион","октосептуагинтиллион","новемсептуагинтиллион",
75
+ "октогинтиллион","аноктогинтиллион","дуооктогинтиллион","треоктогинтиллион","кваттороктогинтиллион",
76
+ "квиноктогинтиллион","сексоктогинтиллион","септемоктогинтиллион","октооктогинтиллион","новемоктогинтиллион",
77
+ "нонагинтиллион","аннонагинтиллион","дуононагинтиллион","тренонагинтиллион","кватторнонагинтиллион",
78
+ "квиннонагинтиллион","секснонагинтиллион","септемнонагинтиллион","октононагинтиллион","новемнонагинтиллион","центиллион"]
79
+ private_constant :ORDWORD
80
+ THOU_ENDING=[["а","и","е","у","ей","е"],["и","","ам","и","ами","ах"]]
81
+ private_constant :THOU_ENDING
82
+ MILLI_ENDING=[["","а","у","","ом","е"],["ы","ов","ам","ы","ами","ах"]]
83
+ private_constant :MILLI_ENDING
84
+ HUNDREDS=[nil,["сто","ста","ста","сто","ста","ста"],
85
+ ["двести","двухсот","двумстам","двести","двумястами","двухстах"],
86
+ ["триста","трёхсот","трёмстам","триста","тремястами","трёхстах"],
87
+ ["четыреста","четырёхсот","четырёмстам","четыреста","четырьмястами","четырёхстах"],
88
+ ["пятьсот","пятисот","пятистам","пятьсот","пятьюстами","пятистах"],
89
+ ["шестьсот","шестисот","шестистам","шестьсот","шестьюстами","шестистах"],
90
+ ["семьсот","семисот","семистам","семьсот","семьюстами","семистах"],
91
+ ["восемьсот","восьмисот","восьмистам","восемьсот","восьмьюстами","восьмистах"],
92
+ ["девятьсот","девятисот","девятистам","девятьсот","девятьюстами","девятистах"]]
93
+ private_constant :HUNDREDS
94
+ TWENTIES=[nil,nil,
95
+ ["двадцать","двадцати","двадцати","двадцать","двадцатью","двадцати"],
96
+ ["тридцать","тридцати","тридцати","тридцать","тридцатью","тридцати"],
97
+ ["сорок","сорока","сорока","сорок","сорока","сорока"],
98
+ ["пятьдесят","пятидесяти","пятидесяти","пятьдесят","пятьюдесятью","пятидесяти"],
99
+ ["шестьдесят","шестидесяти","шестидесяти","шестьдесят","шестьюдесятью","шестидесяти"],
100
+ ["семьдесят","семидесяти","семидесяти","семьдесят","семьюдесятью","семидесяти"],
101
+ ["восемьдесят","восьмидесяти","восьмидесяти","восемьдесят","восьмьюдесятью","восьмидесяти"],
102
+ ["девяносто","девяноста","девяноста","девяносто","девяноста","девяноста"]]
103
+ private_constant :TWENTIES
104
+ TEENCASES=["ь","и","и","ь","ью","и"]
105
+ private_constant :TEENCASES
106
+ ONES=[["ноль","нуля","нулю","ноль","нулём","нуле"],
107
+ ["один","одного","одному","один","одним","одном"],
108
+ ["два","двух","двум","два","двумя","двух"],
109
+ ["три","трёх","трём","три","тремя","трёх"],
110
+ ["четыре","четырёх","четырём","четыре","четырьмя","четырёх"],
111
+ ["пять","пяти","пяти","пять","пятью","пяти"],
112
+ ["шесть","шести","шести","шесть","шестью","шести"],
113
+ ["семь","семи","семи","семь","семью","семи"],
114
+ ["восемь","восьми","восьми","восемь","восемью","восьми"],
115
+ ["девять","девяти","девяти","девять","девятью","девяти"]]
116
+ private_constant :ONES
117
+ ONES1=[nil,["одна","одной","одной","одну","одной","одной"],
118
+ ["одно","одного","одному","одно","одним","одном"]]
119
+ private_constant :ONES1
120
+ ONES2=[nil,["две","двух","двум","две","двумя","двух"],
121
+ ["два","двух","двум","два","двумя","двух"]]
122
+ private_constant :ONES2
123
+ ENDING02678=[["ой","ого","ому","ой","ым","ом"],
124
+ ["ая","ой","ой","ую","ой","ой"],
125
+ ["ое","ого","ому","ое","ым","ом"],
126
+ ["ые","ых","ым","ые","ыми","ых"]]
127
+ private_constant :ENDING02678
128
+ ENDING1459=[["ый","ого","ому","ый","ым","ом"],
129
+ ["ая","ой","ой","ую","ой","ой"],
130
+ ["ое","ого","ому","ое","ым","ом"],
131
+ ["ые","ых","ым","ые","ыми","ых"]]
132
+ private_constant :ENDING1459
133
+ ENDING3=[["ий","ьего","ьему","ий","ьим","ьем"],
134
+ ["ья","ьей","ьей","ью","ьей","ьей"],
135
+ ["ье","ьего","ьему","ье","ьим","ьем"],
136
+ ["ьи","ьих","ьим","ьи","ьими","ьих"]]
137
+ private_constant :ENDING3
138
+ ACCUSATIVE=["ого","ую","ое","ых"]
139
+ private_constant :ACCUSATIVE
140
+ ACCUSATIVE3=["ьего","ью","ье","ьих"]
141
+ private_constant :ACCUSATIVE3
142
+ COMPOUNDS=["одно","двух","трёх","четырёх","пяти","шести","семи","восьми","девяти"]
143
+ private_constant :COMPOUNDS
144
+ TEENS=["десят","одиннадцат","двенадцат","тринадцат","четырнадцат","пятнадцат","шестнадцат","семнадцат","восемнадцат","девятнадцат"]
145
+ private_constant :TEENS
146
+ TIES=[nil,nil,"двадцат","тридцат","сороков","пятидесят","шестидесят","семидесят","восьмидесят","девяност"]
147
+ private_constant :TIES
148
+ ORDINALS=["нулев","перв","втор","трет","четвёрт","пят","шест","седьм","восьм","девят"]
149
+ private_constant :ORDINALS
150
+ MONTAB=["января","февраля","марта","апреля","мая","июня","июля","августа","сентября","октября","ноября","декабря"]
151
+ private_constant :MONTAB
152
+ YEARGRAM="мн|год|года|году|год|годом|годе|годы|годов|годам|годы|годами|годах"
153
+ private_constant :YEARGRAM
154
+ HOURGRAM="мн|час|часа|часу|час|часом|часе|часы|часов|часам|часы|часами|часах"
155
+ private_constant :HOURGRAM
156
+ MINGRAM="жн|минута|минуты|минуте|минуту|минутой|минуте|минуты|минут|минутам|минуты|минутами|минутах"
157
+ private_constant :MINGRAM
158
+ SECGRAM="жн|секунда|секунды|секунде|секунду|секундой|секунде|секунды|секунд|секундам|секунды|секундами|секундах"
159
+ private_constant :SECGRAM
160
+ WHOLEGRAM="жн|целая|целой|целой|целую|целой|целой|целые|целых|целым|целые|целыми|целых"
161
+ private_constant :WHOLEGRAM
162
+ # Грамматика слова "рубль"
163
+ RUBGRAM="мн|рубль|рубля|рублю|рубль|рублём|рубле|рубли|рублей|рублям|рубли|рублями|рублях"
164
+ # Грамматика слова "копейка"
165
+ KOPGRAM="жн|копейка|копейки|копейке|копейку|копейкой|копейке|копейки|копеек|копейкам|копейки|копейками|копейках"
166
+ # Грамматика слова "доллар"
167
+ DOLLARGRAM="мн|доллар|доллара|доллару|доллар|долларом|долларе|доллары|долларов|долларам|доллары|долларами|долларах"
168
+ # Грамматика слова "цент"
169
+ CENTGRAM="мн|цент|цента|центу|цент|центом|центе|центы|центов|центам|центы|центами|центах"
170
+ # Грамматика слова "евро"
171
+ EUROGRAM="мн|евро|евро|евро|евро|евро|евро|евро|евро|евро|евро|евро|евро"
172
+ # Грамматика слова "евроцент"
173
+ EUROCENTGRAM="мн|евроцент|евроцента|евроценту|евроцент|евроцентом|евроценте|евроценты|евроцентов|евроцентам|евроценты|евроцентами|центах"
174
+ class << self
175
+ private
176
+ def get_grammar(order, plural, casus)
177
+ if order == 0 then
178
+ @usergram[plural][casus]
179
+ elsif order == 1 then
180
+ ORDWORD[order] + THOU_ENDING[plural][casus]
181
+ else
182
+ ORDWORD[order] + MILLI_ENDING[plural][casus]
183
+ end
184
+ end
185
+
186
+ def get_order(n)
187
+ order=1
188
+ order+=1 until n < 10 ** (3*order)
189
+ order-1
190
+ end
191
+
192
+ def set_grammar(grammar)
193
+ @gender=0
194
+ @animate=false
195
+ @usergram = [["","","","","",""],["","","","","",""]]
196
+ t_ar=grammar.to_s.split("|")
197
+ return if t_ar.empty?
198
+ t_ar[0].downcase.each_char do |c|
199
+ case c
200
+ when "м" then
201
+ @gender=0
202
+ when "ж" then
203
+ @gender=1
204
+ when "с" then
205
+ @gender=2
206
+ when "н"
207
+ @animate=false
208
+ when "о"
209
+ @animate=true
210
+ else
211
+ raise ArgumentError, %Q/Invalid grammar specified "#{s}"/, caller
212
+ end
213
+ end
214
+ 0.upto(1) do |i|
215
+ 0.upto(5) do |j|
216
+ c_gr=t_ar[6*i + j + 1]
217
+ @usergram[i][j] = c_gr ? c_gr : ""
218
+ end
219
+ end
220
+ end
221
+
222
+ def get_tail(n, casus, animate, order)
223
+ return get_grammar(order,1,1) if n.zero?
224
+ t_n=n
225
+ tail=get_grammar(order,1, casus == 0 || casus == 3 ? 1 : casus )
226
+ t_n = t_n%100
227
+ t_n = t_n%10 if t_n >= 20
228
+ return tail if t_n == 0 || t_n >= 10
229
+ if t_n == 1 then
230
+ tail=get_grammar(order,0,casus)
231
+ elsif ( t_n >=2 && t_n <=4 ) && ( casus == 0 || casus == 3 ) then
232
+ tail = get_grammar(order, animate && casus == 3 ? 1 : 0 , 1 )
233
+ else
234
+ tail = get_grammar(order, 1, casus == 0 || casus == 3 ? 1 : casus)
235
+ end
236
+ tail
237
+ end
238
+
239
+ def milli(n, casus, gender, animate, order)
240
+ t_n=n
241
+ if order != 0 then
242
+ t_gender=(order == 1 ? 1 : 0)
243
+ t_animate=false
244
+ else
245
+ t_gender=gender
246
+ t_animate=animate
247
+ end
248
+ tail=get_tail(t_n,casus,t_animate,order)
249
+ return ONES[0][casus] + " " + tail if t_n.zero?
250
+ t_str=""
251
+ if t_n >= 100 then
252
+ t_str+=HUNDREDS[t_n/100][casus]
253
+ t_n=t_n%100
254
+ end
255
+ if t_n >=20 then
256
+ t_str << " " if not t_str.empty?
257
+ t_str << TWENTIES[t_n/10][casus]
258
+ t_n = t_n%10
259
+ end
260
+ if t_n >=10 then
261
+ t_str << " " if not t_str.empty?
262
+ t_str << TEENS[t_n%10] + TEENCASES[casus]
263
+ t_n = 0
264
+ end
265
+ return t_str + " " + tail if t_n == 0
266
+ t_str << " " if not t_str.empty?
267
+ if t_n == 1 then
268
+ if t_animate && casus == 3 then
269
+ t_str << (t_gender == 0 ? ONES[1][1] : ONES1[t_gender][3])
270
+ else
271
+ t_str << (t_gender == 0 ? ONES[1][casus] : ONES1[t_gender][casus])
272
+ end
273
+ elsif t_n == 2 then
274
+ if t_animate && casus == 3 then
275
+ t_str << (t_gender == 0 ? ONES[2][1] : ONES2[t_gender][1])
276
+ else
277
+ t_str << (t_gender == 0 ? ONES[2][casus] : ONES2[t_gender][casus])
278
+ end
279
+ elsif t_animate && t_n <=4 && casus == 3 then
280
+ t_str << ONES[t_n][1]
281
+ else
282
+ t_str << ONES[t_n][casus]
283
+ end
284
+ t_str << " " + tail
285
+ end
286
+
287
+ def get_ending(n, animate, gender, casus)
288
+ if ( animate || gender == 1 ) && casus == 3 then
289
+ return n == 3 ? ACCUSATIVE3[gender] : ACCUSATIVE[gender]
290
+ end
291
+ case n
292
+ when 0,2,6,7,8 then
293
+ return ENDING02678[gender][casus]
294
+ when 1,4,5,9 then
295
+ return ENDING1459[gender][casus]
296
+ when 3
297
+ return ENDING3[gender][casus]
298
+ end
299
+ end
300
+
301
+ def first_ordinal(n, animate, gender, casus )
302
+ return "" if n.zero?
303
+ t_str=""
304
+ digit=n/100
305
+ if digit.nonzero? then
306
+ if (n%100).zero? then
307
+ if digit > 1 then
308
+ t_str=ONES[digit][1]
309
+ end
310
+ return t_str + "сот" + get_ending(1,animate,gender,casus)
311
+ end
312
+ t_str=HUNDREDS[digit][0] + " "
313
+ end
314
+ digit=(n%100)/10
315
+ return t_str + TEENS[n%10] + get_ending(1,animate,gender,casus) if digit == 1
316
+ if digit !=0 then
317
+ if (n%10).zero? then
318
+ return t_str + TIES[digit] + (digit == 4 ? get_ending(0,animate,gender,casus) : get_ending(1,animate,gender,casus))
319
+ else
320
+ t_str << TWENTIES[digit][0] + " "
321
+ end
322
+ end
323
+ digit=n%10
324
+ t_str + ORDINALS[digit] + get_ending(digit,animate,gender,casus)
325
+ end
326
+
327
+ def second_ordinal(n,order,animate, gender, casus )
328
+ return "" if n.zero?
329
+ t_str=""
330
+ if n != 1 then
331
+ digit=n/100
332
+ if digit.nonzero? then
333
+ if digit == 1
334
+ t_str= (n%100).zero? ? "сто" : "ста"
335
+ else
336
+ t_str= ONES[digit][1] + "сот"
337
+ end
338
+ end
339
+ digit=(n%100)/10
340
+ if digit == 1 then
341
+ t_str << TEENS[n%10] + TEENCASES[1]
342
+ else
343
+ t_str << TWENTIES[digit][1] if digit != 0
344
+ digit=n%10
345
+ t_str << COMPOUNDS[digit] if digit != 0
346
+ end
347
+ end
348
+ t_str + ORDWORD[order] + "н" + get_ending(1,animate,gender,casus)
349
+ end
350
+
351
+ public
352
+ ###
353
+ # Преобразует число в количественное числительное
354
+ #
355
+ # @param [Integer] n число для преобразования
356
+ # @param gr_casus [String] падеж числительного
357
+ # @param grammar [String] грамматика
358
+ # @param minorder [Integer] минимальный порядок тысяч (см. примеры). Если минимальный порядок < 0, то собственно числительное не выводится
359
+ # @return [String]
360
+ # @raise [ArgumentError]
361
+ # @example
362
+ # RuNumerals::ru_numeral(154,'д') #=> "ста пятидесяти четырём"
363
+ # RuNumerals::ru_numeral(101,'','с',1) #=> "ноль тысяч сто одно"
364
+ # RuNumerals::ru_numeral(1,'',RuNumerals::RUBGRAM,-1) #=> "рубль"
365
+ # RuNumerals::ru_numeral(2,'',RuNumerals::RUBGRAM,-1) #=> "рубля"
366
+ #
367
+ def ru_numeral(n,gr_casus = "и", grammar = "мн", minorder = 0)
368
+ if not n.kind_of?(Integer) then
369
+ raise ArgumentError, %Q/The number must be Integer. Argument has class "#{n.class}", value "#{n}"/, caller
370
+ end
371
+ gr_casus="и" if gr_casus.nil? || gr_casus.empty?
372
+ minorder=minorder.to_i
373
+ set_grammar(grammar)
374
+ @animate=false if n > 10 and n%10 != 1
375
+ casus=CASUS_STR.index(gr_casus.downcase)
376
+ if not casus
377
+ raise ArgumentError, %Q/The grammatical case must be one of "ирдвтп". Current value of argument is "#{gr_casus}"/, caller
378
+ end
379
+ if n < 0 then
380
+ is_negative=true
381
+ n=-n
382
+ else
383
+ is_negative=false
384
+ end
385
+ order=get_order(n)
386
+ if order > ORDWORD.length then
387
+ raise ArgumentError, %Q/Too big number #{n}. Max number supported is #{10**((ORDWORD.length+1)*3) - 1}/, caller
388
+ end
389
+ triad=0
390
+ return get_tail(n%1000,casus,@animate,0) if minorder < 0
391
+ t_str= is_negative ? "минус " : ""
392
+ [[minorder,ORDWORD.length].min,order].max.downto(0) do |i|
393
+ triad=(n/(10**(3*i)))%1000
394
+ t_str << milli(triad,casus,@gender,@animate,i) + " " if triad.nonzero? || t_str.empty?
395
+ end
396
+ t_str << get_grammar(0,1,1) if triad.zero? && n.nonzero?
397
+ t_str.rstrip
398
+ end
399
+
400
+ ###
401
+ #Преобразует число в порядковое числительное
402
+ #
403
+ # @param [Integer] n число для преобразования
404
+ # @param gr_casus [String] падеж числительного
405
+ # @param grammar [String] грамматика
406
+ # @param plural [true,false] множественное число
407
+ # @return [String]
408
+ # @raise [ArgumentError]
409
+ # @example
410
+ #
411
+ # RuNumerals::ru_ordinal(1) #=> "первый"
412
+ # RuNumerals::ru_ordinal(2) #=> "второй"
413
+ # RuNumerals::ru_ordinal(250000000,'в','ж') #=> "двухсотпятидесятимиллионную"
414
+ # RuNumerals::ru_ordinal(5,'т','ж',true) #=> "пятыми"
415
+ # RuNumerals::ru_ordinal(-5,'в','о') #=> "минус пятого"
416
+ #
417
+ def ru_ordinal(n, gr_casus = "и", grammar = "мн", plural = false)
418
+ if not n.kind_of?(Integer) then
419
+ raise ArgumentError, %Q/The number must be Integer. Argument has class "#{n.class}", value "#{n}"/, caller
420
+ end
421
+ gr_casus="и" if gr_casus.nil? || gr_casus.empty?
422
+ set_grammar(grammar)
423
+ casus=CASUS_STR.index(gr_casus.downcase)
424
+ if not casus
425
+ raise ArgumentError, %Q/The grammatical case must be one of "ирдвтп". Current value of argument is "#{gr_casus}"/, caller
426
+ end
427
+ if n < 0 then
428
+ is_negative=true
429
+ n=-n
430
+ else
431
+ is_negative=false
432
+ end
433
+ order=get_order(n)
434
+ if order > ORDWORD.length then
435
+ raise ArgumentError, %Q/Too big number #{n}. Max number supported is #{10**((ORDWORD.length+1)*3) - 1}/, caller
436
+ end
437
+ @gender=3 if plural
438
+ if n.zero? then
439
+ return (ORDINALS[0] + get_ending(0,@animate, @gender, casus) + " " + get_grammar(0, plural ? 1 : 0 , casus)).rstrip
440
+ end
441
+ t_str = first_ordinal(n%1000,@animate,@gender,casus)
442
+ 1.upto(get_order(n)) do |i|
443
+ triad=(n/(10**(3*i)))%1000
444
+ if triad.nonzero? then
445
+ if not t_str.empty? then
446
+ t_str = (triad == 1 ? get_grammar(i,0,0) : milli(triad,0,0,false,i)) + " " + t_str
447
+ else
448
+ t_str = second_ordinal(triad, i, @animate, @gender, casus)
449
+ end
450
+ end
451
+ end
452
+ (( is_negative ? "минус " : "" ) + t_str + " " + get_grammar(0, plural ? 1 : 0, casus)).rstrip
453
+ end
454
+ ###
455
+ #Преобразует объект класса +Time+ в текстовое представление даты
456
+ #
457
+ # @param [Time] d объект для преобразования
458
+ # @param gr_casus [String] падеж числительного
459
+ # @param [Hash] options опции
460
+ # @option options [true,false] :spelldd (true) преобразовать в числительное число месяца
461
+ # @option options [true,false] :spellyy (true) преобразовать в числительное год
462
+ # @return [String]
463
+ # @raise [ArgumentError]
464
+ # @example
465
+ #
466
+ # RuNumerals::ru_date(Time.now) #=> "девятое ноября две тысячи шестнадцатого года"
467
+ # RuNumerals::ru_date(Time.now, "д",spellyy: false) #=> "девятому ноября 2016 года"
468
+ # RuNumerals::ru_date(Time.now, spelldd: false, spellyy: false) #=> "9 ноября 2016 года"
469
+ #
470
+ def ru_date(d, gr_casus="и", **options )
471
+ if not d.kind_of?(Time) then
472
+ raise ArgumentError, %Q/The argument must be Time class. Argument has class "#{d.class}", value "#{d}"/, caller
473
+ end
474
+ spelldd=true
475
+ spellyy=true
476
+ options.each do |k,v|
477
+ case k
478
+ when :spelldd then spelldd=v
479
+ when :spellyy then spellyy=v
480
+ else raise ArgumentError, %Q/Invalid option key #{k} value "#{v}"/, caller
481
+ end
482
+ end
483
+ if spelldd then
484
+ day_part=ru_ordinal(d.day,gr_casus,"с")
485
+ else
486
+ day_part=d.day.to_s
487
+ end
488
+ day_part + " " + MONTAB[d.mon-1] + " " + (spellyy ? ru_ordinal(d.year,"р",YEARGRAM) : (d.year.to_s + " года"))
489
+ end
490
+ ###
491
+ #Преобразует объект класса +Time+ в текстовое представление времени
492
+ #
493
+ # @param [Time] d объект для преобразования
494
+ # @param gr_casus [String] падеж числительного
495
+ # @param [Hash] options опции
496
+ # @option options [true,false] :spellhh (true) преобразовать в числительное часы
497
+ # @option options [true,false] :spellmm (true) преобразовать в числительное минуты
498
+ # @option options [true,false] :spellss (true) преобразовать в числительное секунды
499
+ # @option options [true,false] :seconds (true) показывать секунды
500
+ # @return [String]
501
+ # @raise [ArgumentError]
502
+ # @example
503
+ #
504
+ # RuNumerals::ru_time(Time.now)
505
+ # #=> "восемнадцать часов пятьдесят две минуты двадцать секунд"
506
+ # RuNumerals::ru_time(Time.now,"д",spellhh: false , spellmm: false , spellss: false)
507
+ # #=> "18 часам 52 минутам 20 секундам"
508
+ # RuNumerals::ru_time(Time.now,'',spellhh: false , spellmm: false , noseconds: false)
509
+ # #=> "18 часов 52 минуты"
510
+ #
511
+ def ru_time(d, gr_casus="и", **options)
512
+ if not d.kind_of?(Time) then
513
+ raise ArgumentError, %Q/The argument must be Time class. Argument has class "#{d.class}", value "#{d}"/, caller
514
+ end
515
+ spellhh=true
516
+ spellmm=true
517
+ spellss=true
518
+ seconds=true
519
+ options.each do |k,v|
520
+ case k
521
+ when :spellhh then spellhh=v
522
+ when :spellmm then spellmm=v
523
+ when :spellss then spellss=v
524
+ when :seconds then seconds=v
525
+ else raise ArgumentError, %Q/Invalid option key #{k} value "#{v}"/, caller
526
+ end
527
+ end
528
+ (spellhh ? ru_numeral(d.hour, gr_casus, HOURGRAM ) : (d.hour.to_s + " " + ru_numeral(d.hour, gr_casus, HOURGRAM, -1 ))) + " " +
529
+ (spellmm ? ru_numeral(d.min, gr_casus, MINGRAM ) : (d.min.to_s + " "+ ru_numeral(d.min, gr_casus, MINGRAM, -1 ))) +
530
+ (seconds ? ( " " + (spellss ? ru_numeral(d.sec, gr_casus, SECGRAM ) : (d.sec.to_s + " " + ru_numeral(d.sec, gr_casus, SECGRAM, -1 )))) : "")
531
+ end
532
+ ###
533
+ #Преобразует число в текстовое представление денежной суммы
534
+ #
535
+ # @param [Integer,Float] n объект для преобразования
536
+ # @param gr_casus [String] падеж числительного
537
+ # @param rub_gram [String] грамматика "рублей", если nil или "", то выводятся только "копейки" со значением n*100
538
+ # @param kop_gram [String] грамматика "копеек", если nil или "", то "копейки" не выводятся и их значение отбрасывается
539
+ # @param [Hash] options опции
540
+ # @option options [true,false] :spellrub (true) преобразовать в числительное число "рублей"
541
+ # @option options [true,false] :spellkop (true) преобразовать в числительное число "копеек", значение выводится в формате "%02d"
542
+ # @return [String]
543
+ # @raise [ArgumentError]
544
+ # @example
545
+ #
546
+ # RuNumerals::ru_money(123.029,"и",RuNumerals::RUBGRAM,RuNumerals::KOPGRAM)
547
+ # #=> "сто двадцать три рубля три копейки"
548
+ # RuNumerals::ru_money(123.029,"р",RuNumerals::RUBGRAM,RuNumerals::KOPGRAM, spellkop: false)
549
+ # #=> "ста двадцати трёх рублей 03 копеек"
550
+ # RuNumerals::ru_money(123.029,"т",nil,RuNumerals::KOPGRAM)
551
+ # #=> "двенадцатью тысячами тремястами тремя копейками"
552
+ #
553
+ def ru_money(n,gr_casus,rub_gram, kop_gram, **options)
554
+ if not (n.kind_of?(Integer) || n.kind_of?(Float)) then
555
+ raise ArgumentError, %Q/The number must be Integer or Float. Argument has class "#{n.class}", value "#{n}"/, caller
556
+ end
557
+ n=n.to_f
558
+ spellrub=true
559
+ spellkop=true
560
+ options.each do |k,v|
561
+ case k
562
+ when :spellrub then spellrub=v
563
+ when :spellkop then spellkop=v
564
+ else raise ArgumentError, %Q/Invalid option key #{k} value "#{v}"/, caller
565
+ end
566
+ end
567
+ if (rub_gram.nil? || rub_gram.empty?) && (kop_gram.nil? || kop_gram.empty? ) then
568
+ raise ArgumentError, %Q/Both grammars are nil/, caller
569
+ end
570
+ if rub_gram.nil? || rub_gram.empty? then
571
+ kops=(n*100).round
572
+ if spellkop then
573
+ return ru_numeral(kops,gr_casus,kop_gram)
574
+ else
575
+ return kops.to_s + " " + ru_numeral(kops,gr_casus,kop_gram,-1)
576
+ end
577
+ end
578
+ rubs=n.truncate
579
+ kops=((n*100)%100).round
580
+ if spellrub then
581
+ rub_s=ru_numeral(rubs,gr_casus,rub_gram)
582
+ else
583
+ rub_s=rubs.to_s + " " + ru_numeral(rubs,gr_casus,rub_gram,-1)
584
+ end
585
+ return rub_s if ( kop_gram.nil? || kop_gram.empty? )
586
+ if spellkop then
587
+ kop_s=ru_numeral(kops,gr_casus,kop_gram)
588
+ else
589
+ kop_s=("%02d" % kops.to_s) + " " + ru_numeral(kops,gr_casus,kop_gram,-1)
590
+ end
591
+ rub_s + " " + kop_s
592
+ end
593
+ ###
594
+ #Преобразует дробное число в его текстовое представление
595
+ #
596
+ # @param [Rational, Float, Integer] n объект для преобразования
597
+ # @param gr_casus [String] падеж числительного
598
+ # @param grammar [String] грамматика
599
+ # @param [Hash] options опции
600
+ # @option options [true,false] :improper (false) не преобразовать в правильную дробь
601
+ # @return [String]
602
+ # @raise [ArgumentError]
603
+ # Если знаменатель равен единице (аргумент типа +Integer+ как частный случай),
604
+ # то результатом будет количественное числительное (будет осуществлен вызов ru_numeral)
605
+ #
606
+ # @example
607
+ #
608
+ # RuNumerals::ru_fractional(Rational(8,7)) #=> "одна целая одна седьмая"
609
+ # RuNumerals::ru_fractional(Rational(8,7),"",improper: true) #=> "восемь седьмых"
610
+ # RuNumerals::ru_fractional(Rational(8,7),improper: true) #=> "восемь седьмых"
611
+ # RuNumerals::ru_fractional(Rational(6,2),"т") #=> "тремя"
612
+ # RuNumerals::ru_fractional(1001.02) #=> "одна тысяча одна целая две сотых"
613
+ #
614
+ def ru_fractional(n,gr_casus="и",grammar=nil, **options)
615
+ improper=false
616
+ options.each do |k,v|
617
+ case k
618
+ when :improper then improper=v
619
+ else raise ArgumentError, %Q/Invalid option key #{k} value "#{v}"/, caller
620
+ end
621
+ end
622
+ if n.kind_of?(Integer) then
623
+ numer=n
624
+ denom=1
625
+ elsif n.kind_of?(Float) then
626
+ m=n.to_s.match('([-+]?[0-9]+)\.([0-9]+)([eE]([-+][0-9]+))?')
627
+ numer=(m[1] + m[2]).to_i
628
+ denom_order=(m[2].length - (m[3].nil? ? 0 : m[4].to_i))
629
+ while denom_order < 0
630
+ numer*=10
631
+ denom_order+=1
632
+ end
633
+ while numer%10 == 0 && denom_order > 0
634
+ numer/=10
635
+ denom_order-=1
636
+ end
637
+ denom=10**denom_order
638
+ elsif n.kind_of?(Rational) then
639
+ numer=n.numerator
640
+ denom=n.denominator
641
+ else
642
+ raise ArgumentError, %Q/The number must be one of Rational, Float or Integer. Argument has class "#{n.class}", value "#{n}"/, caller
643
+ end
644
+ if denom == 1 then
645
+ return ru_numeral(numer, gr_casus, grammar)
646
+ end
647
+ if (not improper) && numer.abs >= denom then
648
+ t_str=ru_numeral((numer < 0 ? -(numer.abs/denom) : numer/denom),gr_casus,WHOLEGRAM)
649
+ numer=numer.abs%denom
650
+ else
651
+ t_str=""
652
+ end
653
+ if not numer.zero? then
654
+ t_str << " " if not t_str.empty?
655
+ t_str << ru_numeral(numer,gr_casus,"ж") + " "
656
+ if numer%10 == 1 then
657
+ t_str << ru_ordinal(denom,gr_casus,"ж")
658
+ elsif gr_casus == "и" then
659
+ t_str << ru_ordinal(denom,"р","ж",true)
660
+ else
661
+ t_str << ru_ordinal(denom,gr_casus,"ж",true)
662
+ end
663
+ end
664
+ t_str + (grammar.nil? ? "" : (" " + ru_numeral(1,"р",grammar,-1)))
665
+ end
666
+ ###
667
+ #Преобразует число в текстовое представление денежной суммы в рублях. Дробная часть отбрасываются.
668
+ # @param [Integer,Float] n объект для преобразования
669
+ # @param gr_casus [String] падеж числительного
670
+ # @param [Hash] options опции
671
+ # @option options [true,false] :spellrub (true) преобразовать в числительное число рублей
672
+ # @return [String]
673
+ # @raise [ArgumentError]
674
+ # @example
675
+ #
676
+ # RuNumerals::ru_rubles(2123.29) #=> "две тысячи сто двадцать три рубля"
677
+ # RuNumerals::ru_rubles(3,"т", spellrub: false) #=> "3 рублями"
678
+ #
679
+ def ru_rubles(n,gr_casus="и",**options)
680
+ ru_money(n,gr_casus,RUBGRAM,nil,options)
681
+ end
682
+ ###
683
+ #Преобразует число в текстовое представление денежной суммы в копейках (n*100)
684
+ # @param [Integer,Float] n объект для преобразования
685
+ # @param gr_casus [String] падеж числительного
686
+ # @param [Hash] options опции
687
+ # @option options [true,false] :spellkop (true) преобразовать в числительное число копеек, значение выводится в формате "%02d"
688
+ # @return [String]
689
+ # @raise [ArgumentError]
690
+ # @example
691
+ #
692
+ # RuNumerals::ru_kopecks(2123.29) #=> "двести двенадцать тысяч триста двадцать девять копеек"
693
+ # RuNumerals::ru_kopecks(3,"т",spellkop: false) #=> "300 копейками"
694
+ #
695
+ def ru_kopecks(n,gr_casus="и",**options)
696
+ ru_money(n,gr_casus,nil,KOPGRAM,options)
697
+ end
698
+ ###
699
+ #Преобразует число в текстовое представление денежной суммы в рублях и копейках
700
+ # @param [Integer,Float] n объект для преобразования
701
+ # @param gr_casus [String] падеж числительного
702
+ # @param [Hash] options опции
703
+ # @option options [true,false] :spellrub (true) преобразовать в числительное число рублей
704
+ # @option options [true,false] :spellkop (true) преобразовать в числительное число копеек, значение выводится в формате "%02d"
705
+ # @return [String]
706
+ # @raise [ArgumentError]
707
+ # @example
708
+ #
709
+ # RuNumerals::ru_rubleskopecks(2123.29) #=> "две тысячи сто двадцать три рубля двадцать девять копеек"
710
+ # RuNumerals::ru_rubleskopecks(3,"т",spellkop: false) #=> "тремя рублями 00 копеек"
711
+ #
712
+ def ru_rubleskopecks(n,gr_casus="и",**options)
713
+ ru_money(n,gr_casus,RUBGRAM,KOPGRAM,options)
714
+ end
715
+ ###
716
+ #Преобразует число в текстовое представление денежной суммы в долларах. Дробная часть отбрасываются.
717
+ # @param [Integer,Float] n объект для преобразования
718
+ # @param gr_casus [String] падеж числительного
719
+ # @param [Hash] options опции
720
+ # @option options [true,false] :spellrub (true) преобразовать в числительное число долларов
721
+ # @return [String]
722
+ # @raise [ArgumentError]
723
+ # @example
724
+ #
725
+ # RuNumerals::ru_dollars(2123.29) #=> "две тысячи сто двадцать три доллара"
726
+ # RuNumerals::ru_dollars(3,"т",spellrub: false) #=> "3 долларами"
727
+ #
728
+ def ru_dollars(n,gr_casus="и",**options)
729
+ ru_money(n,gr_casus,DOLLARGRAM,nil,options)
730
+ end
731
+ ###
732
+ #Преобразует число в текстовое представление денежной суммы в центах (n*100)
733
+ # @param [Integer,Float] n объект для преобразования
734
+ # @param gr_casus [String] падеж числительного
735
+ # @param [Hash] options опции
736
+ # @option options [true,false] :spellkop (true) преобразовать в числительное число центов, значение выводится в формате "%02d"
737
+ # @return [String]
738
+ # @raise [ArgumentError]
739
+ # @example
740
+ #
741
+ # RuNumerals::ru_cents(2123.29) #=> "двести двенадцать тысяч триста двадцать девять центов"
742
+ # RuNumerals::ru_cents(3,"т",spellkop: false) #=> "300 центами"
743
+ #
744
+ def ru_cents(n,gr_casus="и",**options)
745
+ ru_money(n,gr_casus,nil,CENTGRAM,options)
746
+ end
747
+ ###
748
+ #Преобразует число в текстовое представление денежной суммы в долларах и центах
749
+ # @param [Integer,Float] n объект для преобразования
750
+ # @param gr_casus [String] падеж числительного
751
+ # @param [Hash] options опции
752
+ # @option options [true,false] :spellrub (true) преобразовать в числительное число долларов
753
+ # @option options [true,false] :spellkop (true) преобразовать в числительное число центов, значение выводится в формате "%02d"
754
+ # @return [String]
755
+ # @raise [ArgumentError]
756
+ # @example
757
+ #
758
+ # RuNumerals::ru_dollarscents(2123.29) #=> "две тысячи сто двадцать три доллара двадцать девять центов"
759
+ # RuNumerals::ru_dollarscents(3,"т",spellkop: false) #=> "тремя долларами 00 центов"
760
+ #
761
+ def ru_dollarscents(n,gr_casus="и",**options)
762
+ ru_money(n,gr_casus,DOLLARGRAM,CENTGRAM,options)
763
+ end
764
+ ###
765
+ #Преобразует число в текстовое представление денежной суммы в евро. Дробная часть отбрасываются.
766
+ # @param [Integer,Float] n объект для преобразования
767
+ # @param gr_casus [String] падеж числительного
768
+ # @param [Hash] options опции
769
+ # @option options [true,false] :spellrub (true) преобразовать в числительное число евро
770
+ # @return [String]
771
+ # @raise [ArgumentError]
772
+ # @example
773
+ #
774
+ # RuNumerals::ru_euros(2123.29) #=> "две тысячи сто двадцать три евро"
775
+ # RuNumerals::ru_euros(3,"т",spellrub: false) #=> "3 евро"
776
+ #
777
+ def ru_euros(n,gr_casus="и",**options)
778
+ ru_money(n,gr_casus,EUROGRAM,nil,options)
779
+ end
780
+ ###
781
+ #Преобразует число в текстовое представление денежной суммы в евроцентах (n*100)
782
+ # @param [Integer,Float] n объект для преобразования
783
+ # @param gr_casus [String] падеж числительного
784
+ # @param [Hash] options опции
785
+ # @option options [true,false] :spellkop (true) преобразовать в числительное число евроцентов, значение выводится в формате "%02d"
786
+ # @return [String]
787
+ # @raise [ArgumentError]
788
+ # @example
789
+ #
790
+ # RuNumerals::ru_eurocents(2123.29) #=> "двести двенадцать тысяч триста двадцать девять евроцентов"
791
+ # RuNumerals::ru_eurocents(3,"т",spellkop: false) #=> "300 евроцентами"
792
+ #
793
+ def ru_eurocents(n,gr_casus="и",**options)
794
+ ru_money(n,gr_casus,nil,EUROCENTGRAM,options)
795
+ end
796
+ ###
797
+ #Преобразует число в текстовое представление денежной суммы в евро и евроцентах
798
+ # @param [Integer,Float] n объект для преобразования
799
+ # @param gr_casus [String] падеж числительного
800
+ # @param [Hash] options опции
801
+ # @option options [true,false] :spellrub (true) преобразовать в числительное число евро
802
+ # @option options [true,false] :spellkop (true) преобразовать в числительное число евроцентов, значение выводится в формате "%02d"
803
+ # @return [String]
804
+ # @raise [ArgumentError]
805
+ # @example
806
+ #
807
+ # RuNumerals::ru_euroseurocents(2123.29) #=> "две тысячи сто двадцать три евро двадцать девять евроцентов"
808
+ # RuNumerals::ru_euroseurocents(3,"т",spellkop: false) #=> "тремя долларами 00 евроцентов"
809
+ #
810
+ def ru_euroseurocents(n,gr_casus="и",**options)
811
+ ru_money(n,gr_casus,EUROGRAM,EUROCENTGRAM,options)
812
+ end
813
+ ###
814
+ #Добавляет метод или методы RuNumerals классу.
815
+ # @param [Class] cls объект для преобразования
816
+ # @param [Array] methods методы
817
+ # - :ru_numeral (+Symbol+) - добавить метод ru_numeral (только для +Integer+)
818
+ # - :ru_ordinal (+Symbol+) - добавить метод ru_ordinal (только для +Integer+)
819
+ # - :ru_date (+Symbol+) - добавить метод ru_date (только для +Time+)
820
+ # - :ru_time (+Symbol+) - добавить метод ru_time (только для +Time+)
821
+ # - :ru_fractional (+Symbol+) - добавить метод ru_fractional (только для +Float+ и +Rational+)
822
+ # - :ru_money (+Symbol+) - добавить метод ru_money (только для +Float+)
823
+ # - :ru_rubles (+Symbol+) - добавить метод ru_rubles (только для +Float+)
824
+ # - :ru_kopecks (+Symbol+) - добавить метод ru_kopecks (только для +Float+)
825
+ # - :ru_rubleskopecks (+Symbol+) - добавить метод ru_rubleskopecks (только для +Float+)
826
+ # - :ru_dollars (+Symbol+) - добавить метод ru_dollars (только для +Float+)
827
+ # - :ru_cents (+Symbol+) - добавить метод ru_cents (только для +Float+)
828
+ # - :ru_dollarscents (+Symbol+) - добавить метод ru_dollarscents (только для +Float+)
829
+ # - :ru_euros (+Symbol+) - добавить метод ru_euros (только для +Float+)
830
+ # - :ru_eurocents (+Symbol+) - добавить метод ru_eurocents (только для +Float+)
831
+ # - :ru_euroseurocents (+Symbol+) - добавить метод ru_euroseurocents (только для +Float+)
832
+ #
833
+ #Если опции не указаны, то классу добавляются все подходящие функции.
834
+ # @return [nil]
835
+ # @raise [ArgumentError]
836
+ # @example
837
+ #
838
+ # RuNumerals::extend(Integer) #=> nil
839
+ # 1.ru_numeral #=> "один"
840
+ # 1.ru_ordinal("д") #=> "первому"
841
+ # RuNumerals::extend(Float,:ru_rubleskopecks) #=> nil
842
+ # 1.25.ru_rubleskopecks("и",:nospellkop) #=> "один рубль 25 копеек"
843
+ #
844
+ def extend(cls,*methods)
845
+ if ( cls.class != Class ) then
846
+ raise ArgumentError, %Q/Argument must be Class, current argument class is "#{cls.Class}, "/, caller
847
+ end
848
+ if not EXTEND_MAP.keys.include?(cls) then
849
+ raise ArgumentError, %Q/Class "#{cls}" is not supported/, caller
850
+ end
851
+ if methods.nil? or methods.empty? then
852
+ all_methods=true
853
+ else
854
+ all_methods=false
855
+ methods.each do |i|
856
+ if not EXTEND_MAP[cls].include?(i) then
857
+ raise ArgumentError, %Q/Method "#{i}" is not supported for class "#{cls}"/, caller
858
+ end
859
+ end
860
+ end
861
+ methods_to_ext= (all_methods ? EXTEND_MAP[cls] : methods)
862
+ methods_to_ext.each do |i|
863
+ case i
864
+ when :ru_numeral then
865
+ cls.send(:define_method,i) do |gr_casus='и', grammar='мн', min_order=0|
866
+ RuNumerals::ru_numeral(self, gr_casus, grammar, min_order)
867
+ end
868
+ when :ru_ordinal then
869
+ cls.send(:define_method,i) do |gr_casus='и', grammar='мн', plural=false|
870
+ RuNumerals::ru_ordinal(self, gr_casus, grammar, plural)
871
+ end
872
+ when :ru_money then
873
+ cls.send(:define_method,i) do |gr_casus='и', r_gram=nil,k_gram=nil, **opts|
874
+ RuNumerals::ru_money(self, gr_casus,r_gram,k_gram,opts)
875
+ end
876
+ when :ru_date then
877
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
878
+ RuNumerals::ru_date(self, gr_casus, opts)
879
+ end
880
+ when :ru_time then
881
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
882
+ RuNumerals::ru_time(self, gr_casus, opts)
883
+ end
884
+ when :ru_rubles then
885
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
886
+ RuNumerals::ru_rubles(self, gr_casus, opts)
887
+ end
888
+ when :ru_kopecks then
889
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
890
+ RuNumerals::ru_kopecks(self, gr_casus, opts)
891
+ end
892
+ when :ru_rubleskopecks then
893
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
894
+ RuNumerals::ru_rubleskopecks(self, gr_casus, opts)
895
+ end
896
+ when :ru_dollars then
897
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
898
+ RuNumerals::ru_dollars(self, gr_casus, opts)
899
+ end
900
+ when :ru_cents
901
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
902
+ RuNumerals::ru_cents(self, gr_casus, opts)
903
+ end
904
+ when :ru_dollarscents then
905
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
906
+ RuNumerals::ru_dollarscents(self, gr_casus, opts)
907
+ end
908
+ when :ru_euros then
909
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
910
+ RuNumerals::ru_euros(self, gr_casus, opts)
911
+ end
912
+ when :ru_eurocents then
913
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
914
+ RuNumerals::ru_eurocents(self, gr_casus, opts)
915
+ end
916
+ when :ru_euroseurocents then
917
+ cls.send(:define_method,i) do |gr_casus='и', **opts|
918
+ RuNumerals::ru_euroseurocents(self, gr_casus, opts)
919
+ end
920
+ when :ru_fractional then
921
+ cls.send(:define_method,i) do |gr_casus='и', grammar=nil, **opts|
922
+ RuNumerals::ru_fractional(self, gr_casus, grammar, opts)
923
+ end
924
+ end
925
+ end
926
+ nil
927
+ end
928
+ end
929
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,4 @@
1
+ module RuNumerals
2
+ # RuNumerals version
3
+ VERSION='1.0.2'
4
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: runumerals
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Sergey Abel
8
+ - Boris Fifelin
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2018-05-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: yard
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: test-unit
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ description: Convertation of numeric values to russian numerals
57
+ email: bfifelin@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".yardopts"
63
+ - LICENSE
64
+ - README.md
65
+ - Rakefile
66
+ - lib/ru_numerals.rb
67
+ - lib/version.rb
68
+ homepage: https://github.com/bfifelin/runumerals
69
+ licenses:
70
+ - MIT
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 1.9.2
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.6.11
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: Russian numerals
92
+ test_files: []