kabal 0.3.5 → 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.
- checksums.yaml +4 -4
- data/.gitignore +0 -2
- data/Gemfile +1 -0
- data/README.md +3 -1
- data/kabal.gemspec +1 -1
- data/lib/kabal.rb +24 -20
- data/lib/kabal/config.rb +1 -1
- data/lib/kabal/config/yaml_loader.rb +4 -2
- data/lib/kabal/errors.rb +7 -5
- data/lib/kabal/errors/error.rb +5 -5
- data/lib/kabal/errors/no_language_support_error.rb +1 -1
- data/lib/kabal/errors/no_support_for_fractional_numbers_on_current_language_error.rb +1 -1
- data/lib/kabal/errors/number_out_range_error.rb +1 -1
- data/lib/kabal/languages/deutsch.rb +4 -15
- data/lib/kabal/languages/deutsch/declinations.rb +4 -4
- data/lib/kabal/languages/deutsch/fractional_numbers.rb +1 -25
- data/lib/kabal/languages/deutsch/natural_numbers.rb +19 -17
- data/lib/kabal/languages/english.rb +4 -14
- data/lib/kabal/languages/english/fractional_numbers.rb +4 -28
- data/lib/kabal/languages/english/natural_numbers.rb +11 -25
- data/lib/kabal/languages/global/fractional_numbers.rb +40 -0
- data/lib/kabal/languages/global/natural_numbers.rb +20 -0
- data/lib/kabal/languages/language.rb +40 -15
- data/lib/kabal/languages/russian.rb +4 -17
- data/lib/kabal/languages/russian/declinations.rb +10 -12
- data/lib/kabal/languages/russian/fractional_numbers.rb +10 -21
- data/lib/kabal/languages/russian/natural_numbers.rb +23 -30
- data/lib/kabal/version.rb +1 -1
- data/test/lib/kabal_test.rb +14 -11
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de5e475e931da2b5e708213ce699c0e69cdcb1c5
|
4
|
+
data.tar.gz: 8f37d26b3228d9b9471fff1397de6a1ed3dee356
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a75d13edce6e537158b6ab2d9be8a5bbd46db205b9d693e851777fb4bb13fbcf0c6d9448ee4cf78425ad5e715666accf37e16025b373733d7650ce1b9847ec3c
|
7
|
+
data.tar.gz: 61291e01e663a5b7a05daa5117df56b3fe0976681d61037ace697056f63d9e90d0bcc97770d21bbd2338b3891661e0375f39e8b303f2722548d010c40d8ecd87
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -7,9 +7,10 @@
|
|
7
7
|
[](https://coderwall.com/kalashnikovisme)
|
8
8
|
[](https://gemnasium.com/kalashnikovisme/kabal)
|
9
9
|
[](http://stillmaintained.com/kalashnikovisme/kabal)
|
10
|
+
[](https://codeclimate.com/github/kalashnikovisme/kabal)
|
10
11
|
|
11
12
|
|
12
|
-
Kabal allows you to translate number into text.
|
13
|
+
Kabal allows you to translate number into text. See Demo on [http://kabal.herokuapp.com](http://kabal.herokuapp.com)
|
13
14
|
|
14
15
|
## Installation
|
15
16
|
|
@@ -51,6 +52,7 @@ Supported Languages:
|
|
51
52
|
* Negative Numbers
|
52
53
|
* Deutsch
|
53
54
|
* Natural Number { max 10 ** 24 }
|
55
|
+
* Fractional Numbers
|
54
56
|
* Negative Numbers
|
55
57
|
|
56
58
|
Interfaces:
|
data/kabal.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Pavel Kalashnikov"]
|
10
10
|
spec.email = ["kalashnikovisme@gmail.com"]
|
11
11
|
spec.summary = %q{Number To Text Helper}
|
12
|
-
spec.description = %q{Kabal allows you to translate numbers into text on languages: English, Russian, Deutsch}
|
12
|
+
spec.description = %q{Kabal allows you to translate numbers into text on languages: English, Russian, Deutsch. See demo on http://kabal.herokuapp.com}
|
13
13
|
spec.homepage = "https://github.com/kalashnikovisme/kabal"
|
14
14
|
spec.license = "MIT"
|
15
15
|
spec.required_ruby_version = '>= 2.0.0'
|
data/lib/kabal.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
autoload :Version,
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
autoload :Version, 'kabal/version'
|
2
|
+
require 'kabal/supported_languages'
|
3
|
+
require 'kabal/errors'
|
4
|
+
require 'kabal/config'
|
5
5
|
require 'yaml'
|
6
6
|
|
7
7
|
module Kabal
|
@@ -14,22 +14,22 @@ module Kabal
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def language=(language_to_set)
|
17
|
-
languages = Kabal::Config::YamlLoader.yaml_object
|
17
|
+
languages = Kabal::Config::YamlLoader.yaml_object 'languages'
|
18
18
|
if languages[language_to_set]
|
19
19
|
@language = language_to_set
|
20
20
|
else
|
21
|
-
|
21
|
+
fail NoLanguageSupportError.message
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
def to_text_in_language(number, language_at_once)
|
26
26
|
number = string_convert number
|
27
|
-
languages = Kabal::Config::YamlLoader.yaml_object
|
27
|
+
languages = Kabal::Config::YamlLoader.yaml_object 'languages'
|
28
28
|
if languages[language_at_once]
|
29
|
-
if number > maximum_for(language_at_once)
|
29
|
+
if number > maximum_for(language_at_once) || number < minimum_for(language_at_once)
|
30
30
|
NumberOutRangeError.message
|
31
31
|
else
|
32
|
-
obj = Object.const_get(
|
32
|
+
obj = Object.const_get(language_class_name(language_at_once)).new
|
33
33
|
obj.convert number
|
34
34
|
end
|
35
35
|
else
|
@@ -39,9 +39,9 @@ module Kabal
|
|
39
39
|
|
40
40
|
def to_text_in_language_by_index(number, language_at_once_index)
|
41
41
|
number = string_convert number
|
42
|
-
languages = Kabal::Config::YamlLoader.yaml_object(
|
42
|
+
languages = Kabal::Config::YamlLoader.yaml_object('languages').to_a
|
43
43
|
if languages[language_at_once_index]
|
44
|
-
obj = Object.const_get(
|
44
|
+
obj = Object.const_get(language_class_name(languages[language_at_once_index].first)).new
|
45
45
|
obj.convert number
|
46
46
|
else
|
47
47
|
NoLanguageSupportError.message
|
@@ -49,42 +49,42 @@ module Kabal
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def current_language
|
52
|
-
@language ||=
|
52
|
+
@language ||= 'English'
|
53
53
|
@language
|
54
54
|
end
|
55
55
|
|
56
56
|
def supported_languages
|
57
|
-
languages = Kabal::Config::YamlLoader.yaml_object
|
57
|
+
languages = Kabal::Config::YamlLoader.yaml_object 'languages'
|
58
58
|
languages.keys
|
59
59
|
end
|
60
60
|
|
61
61
|
def current_language_supports_natural?
|
62
|
-
obj = Object.const_get(
|
62
|
+
obj = Object.const_get(language_class_name(current_language)).new
|
63
63
|
obj.supports_natural?
|
64
64
|
end
|
65
65
|
|
66
66
|
def current_language_supports_fractional?
|
67
|
-
obj = Object.const_get(
|
67
|
+
obj = Object.const_get(language_class_name(current_language)).new
|
68
68
|
obj.supports_fractional?
|
69
69
|
end
|
70
70
|
|
71
71
|
def language_supports_negative?(language)
|
72
|
-
obj = Object.const_get(
|
72
|
+
obj = Object.const_get(language_class_name(language)).new
|
73
73
|
obj.supports_negative?
|
74
74
|
end
|
75
75
|
|
76
76
|
def language_supports_fractional?(language)
|
77
|
-
obj = Object.const_get(
|
77
|
+
obj = Object.const_get(language_class_name(language)).new
|
78
78
|
obj.supports_fractional?
|
79
79
|
end
|
80
80
|
|
81
81
|
def maximum_for(language)
|
82
|
-
obj = Object.const_get(
|
82
|
+
obj = Object.const_get(language_class_name(language)).new
|
83
83
|
obj.max_value
|
84
84
|
end
|
85
85
|
|
86
86
|
def minimum_for(language)
|
87
|
-
obj = Object.const_get(
|
87
|
+
obj = Object.const_get(language_class_name(language)).new
|
88
88
|
obj.min_value
|
89
89
|
end
|
90
90
|
|
@@ -103,6 +103,10 @@ module Kabal
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def string_is_float?(number)
|
106
|
-
number.include?
|
106
|
+
number.include? '.'
|
107
|
+
end
|
108
|
+
|
109
|
+
def language_class_name(language)
|
110
|
+
'Kabal::' + language
|
107
111
|
end
|
108
112
|
end
|
data/lib/kabal/config.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
require 'active_support/core_ext/hash'
|
2
|
+
|
1
3
|
module Kabal
|
2
4
|
module Config
|
3
5
|
class YamlLoader
|
4
6
|
def self.gem_root
|
5
|
-
Gem::Specification.find_by_name(
|
7
|
+
Gem::Specification.find_by_name('kabal').gem_dir
|
6
8
|
end
|
7
9
|
|
8
10
|
def self.yaml_object(filename)
|
9
|
-
|
11
|
+
YAML.load_file(gem_root + '/yaml/' + filename + '.yml').with_indifferent_access
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
data/lib/kabal/errors.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
module Kabal
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
module Kabal
|
2
|
+
module Errors
|
3
|
+
require 'kabal/errors/no_language_support_error'
|
4
|
+
require 'kabal/errors/number_out_range_error'
|
5
|
+
require 'kabal/errors/no_support_for_fractional_numbers_on_current_language_error'
|
6
|
+
require 'kabal/errors/error'
|
7
|
+
end
|
6
8
|
end
|
data/lib/kabal/errors/error.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
require
|
1
|
+
require 'kabal/config'
|
2
2
|
|
3
3
|
module Kabal
|
4
4
|
module Errors
|
5
5
|
class Error < StandardError
|
6
|
-
@message =
|
7
|
-
@code =
|
6
|
+
@message = 'There is some error'
|
7
|
+
@code = 'Unknown error code'
|
8
8
|
|
9
9
|
def self.message
|
10
|
-
errors = Kabal::Config::YamlLoader.yaml_object
|
11
|
-
errors[
|
10
|
+
errors = Kabal::Config::YamlLoader.yaml_object 'errors'
|
11
|
+
errors[:errors][:messages][@code]
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -3,20 +3,9 @@ require 'kabal/languages/deutsch/natural_numbers'
|
|
3
3
|
require 'kabal/languages/deutsch/declinations'
|
4
4
|
require 'kabal/languages/deutsch/fractional_numbers'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def convert(number)
|
11
|
-
if need_minus? number
|
12
|
-
minus + " " + number_words(-number)
|
13
|
-
else
|
14
|
-
number_words number
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def number_words(number)
|
19
|
-
return natural_number_name number.round if natural? number
|
20
|
-
fractional_number_name number if fractional? number
|
6
|
+
module Kabal
|
7
|
+
class Deutsch < Kabal::Language
|
8
|
+
include Kabal::DeutschRules::NaturalNumbers
|
9
|
+
include Kabal::DeutschRules::FractionalNumbers
|
21
10
|
end
|
22
11
|
end
|
@@ -3,10 +3,10 @@ module Kabal
|
|
3
3
|
module Declinations
|
4
4
|
def self.name_with_declination(number_name, count)
|
5
5
|
if count != 1
|
6
|
-
if number_name[-1, 1] ==
|
7
|
-
return number_name +
|
8
|
-
elsif number_name[-1, 1] ==
|
9
|
-
return number_name +
|
6
|
+
if number_name[-1, 1] == 'n'
|
7
|
+
return number_name + 'en'
|
8
|
+
elsif number_name[-1, 1] == 'e'
|
9
|
+
return number_name + 'n'
|
10
10
|
end
|
11
11
|
end
|
12
12
|
number_name
|
@@ -2,7 +2,7 @@ module Kabal
|
|
2
2
|
module DeutschRules
|
3
3
|
module FractionalNumbers
|
4
4
|
def fractional_number_name(number)
|
5
|
-
whole_part_name(number) +
|
5
|
+
whole_part_name(number) + ' ' + dot + ' ' + fractional_part_name(number)
|
6
6
|
end
|
7
7
|
|
8
8
|
def whole_part_name(number)
|
@@ -10,33 +10,9 @@ module Kabal
|
|
10
10
|
natural_number_name(count)
|
11
11
|
end
|
12
12
|
|
13
|
-
def fractional_part_name(number)
|
14
|
-
name = ""
|
15
|
-
count_string = fractional_part_string(number).split('.')[1]
|
16
|
-
count = count_string.to_i
|
17
|
-
if count_string.size != count.to_s.size
|
18
|
-
(count_string.size - count.to_s.size).times do
|
19
|
-
name += names["single"][0] + " "
|
20
|
-
end
|
21
|
-
name + natural_number_name(count)
|
22
|
-
else
|
23
|
-
natural_number_name(count)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
13
|
def fractional_part_string(number)
|
28
14
|
"%.#{fractional_part_order(number)}f" % number
|
29
15
|
end
|
30
|
-
|
31
|
-
def fractional_part_order(number)
|
32
|
-
#FIXME find better way with whole 0 numbers
|
33
|
-
number_string = number.to_s
|
34
|
-
if number_string.include? "-"
|
35
|
-
number_string.split('-')[1].to_i
|
36
|
-
else
|
37
|
-
number_string.split('.')[1].length
|
38
|
-
end
|
39
|
-
end
|
40
16
|
end
|
41
17
|
end
|
42
18
|
end
|
@@ -1,35 +1,29 @@
|
|
1
1
|
module Kabal
|
2
2
|
module DeutschRules
|
3
3
|
module NaturalNumbers
|
4
|
-
def natural_number_name(number)
|
5
|
-
return single number if number >= 0 and number <= 19
|
6
|
-
return two_words number if number >= 0 and number <= 99
|
7
|
-
return three_words number if number >= 100 and number <= 999
|
8
|
-
ten_powers number if number >= 100
|
9
|
-
end
|
10
4
|
def single(number)
|
11
|
-
|
12
|
-
names["single"][number]
|
13
|
-
else
|
5
|
+
if @ein
|
14
6
|
@ein = false
|
15
|
-
names[
|
7
|
+
names[:single][number].chop
|
8
|
+
else
|
9
|
+
names[:single][number]
|
16
10
|
end
|
17
11
|
end
|
18
12
|
|
19
13
|
def two_words(number)
|
20
14
|
return single number if number <= 19
|
21
|
-
number_name = names[
|
15
|
+
number_name = names[:two_words][number / 10]
|
22
16
|
@ein = (number % 10 == 1)
|
23
|
-
number_name = single(number % 10) + names[
|
17
|
+
number_name = single(number % 10) + names[:and] + number_name if (number % 10 != 0)
|
24
18
|
number_name
|
25
19
|
end
|
26
20
|
|
27
21
|
def three_words(number)
|
28
22
|
return two_words number if number <= 99
|
29
23
|
@ein = (number / 100 == 1)
|
30
|
-
number_name = single(number / 100) + names[
|
24
|
+
number_name = single(number / 100) + names[:ten_powers][2]
|
31
25
|
number_name += two_words(number % 100) if (number % 100 >= 10)
|
32
|
-
number_name += single(number % 100) if number % 100 < 10
|
26
|
+
number_name += single(number % 100) if number % 100 < 10 && number % 100 != 0
|
33
27
|
number_name
|
34
28
|
end
|
35
29
|
|
@@ -37,7 +31,7 @@ module Kabal
|
|
37
31
|
less_thousands number if number_is_thousands? number
|
38
32
|
return @number_name if number_is_thousands? number
|
39
33
|
create_number_name number
|
40
|
-
ten_powers number % (10
|
34
|
+
ten_powers number % (10**number_order(number))
|
41
35
|
end
|
42
36
|
|
43
37
|
def create_number_name(number)
|
@@ -63,11 +57,19 @@ module Kabal
|
|
63
57
|
|
64
58
|
def words_to_add(number)
|
65
59
|
if millions_or_greater?(number)
|
66
|
-
|
60
|
+
number_with_space number
|
67
61
|
else
|
68
|
-
|
62
|
+
number_without_space number
|
69
63
|
end
|
70
64
|
end
|
65
|
+
|
66
|
+
def number_with_space(number)
|
67
|
+
@number_name = count_name(number) + ' ' + Declinations.name_with_declination(names[:ten_powers][number_order(number)], count(number)) + ' '
|
68
|
+
end
|
69
|
+
|
70
|
+
def number_without_space(number)
|
71
|
+
@number_name = count_name(number) + Declinations.name_with_declination(names[:ten_powers][number_order(number)], count(number))
|
72
|
+
end
|
71
73
|
end
|
72
74
|
end
|
73
75
|
end
|
@@ -2,19 +2,9 @@ require 'kabal/languages/language'
|
|
2
2
|
require 'kabal/languages/english/natural_numbers'
|
3
3
|
require 'kabal/languages/english/fractional_numbers'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
if need_minus? number
|
10
|
-
minus + " " + number_words(-number)
|
11
|
-
else
|
12
|
-
number_words number
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def number_words(number)
|
17
|
-
return natural_number_name number.round if natural? number
|
18
|
-
fractional_number_name number if fractional? number
|
5
|
+
module Kabal
|
6
|
+
class English < Kabal::Language
|
7
|
+
include Kabal::EnglishRules::NaturalNumbers
|
8
|
+
include Kabal::EnglishRules::FractionalNumbers
|
19
9
|
end
|
20
10
|
end
|
@@ -2,45 +2,21 @@ module Kabal
|
|
2
2
|
module EnglishRules
|
3
3
|
module FractionalNumbers
|
4
4
|
def fractional_number_name(number)
|
5
|
-
if whole_part_name(number) !=
|
6
|
-
whole_part_name(number) +
|
5
|
+
if whole_part_name(number) != ''
|
6
|
+
whole_part_name(number) + ' ' + dot + ' ' + fractional_part_name(number)
|
7
7
|
else
|
8
|
-
dot +
|
8
|
+
dot + ' ' + fractional_part_name(number)
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
12
|
def whole_part_name(number)
|
13
13
|
count = number.floor
|
14
|
-
count != 0 ? natural_number_name(count) :
|
15
|
-
end
|
16
|
-
|
17
|
-
def fractional_part_name(number)
|
18
|
-
name = ""
|
19
|
-
count_string = fractional_part_string(number).to_s.split('.')[1]
|
20
|
-
count = count_string.to_i
|
21
|
-
if count_string.size != count.to_s.size
|
22
|
-
(count_string.size - count.to_s.size).times do
|
23
|
-
name += names["single"][0] + " "
|
24
|
-
end
|
25
|
-
name + natural_number_name(count)
|
26
|
-
else
|
27
|
-
natural_number_name(count)
|
28
|
-
end
|
14
|
+
count != 0 ? natural_number_name(count) : ''
|
29
15
|
end
|
30
16
|
|
31
17
|
def fractional_part_string(number)
|
32
18
|
"%.#{fractional_part_order(number)}f" % number
|
33
19
|
end
|
34
|
-
|
35
|
-
def fractional_part_order(number)
|
36
|
-
#FIXME find better way with whole 0 numbers
|
37
|
-
number_string = number.to_s
|
38
|
-
if number_string.include? "-"
|
39
|
-
number_string.split('-')[1].to_i
|
40
|
-
else
|
41
|
-
number_string.split('.')[1].length
|
42
|
-
end
|
43
|
-
end
|
44
20
|
end
|
45
21
|
end
|
46
22
|
end
|
@@ -1,28 +1,22 @@
|
|
1
1
|
module Kabal
|
2
2
|
module EnglishRules
|
3
3
|
module NaturalNumbers
|
4
|
-
def natural_number_name(number)
|
5
|
-
return single number if number >= 0 and number <= 19
|
6
|
-
return two_words number if number >= 0 and number <= 99
|
7
|
-
return three_words number if number >= 100 and number <= 999
|
8
|
-
ten_powers number if number >= 100
|
9
|
-
end
|
10
4
|
def single(number)
|
11
|
-
names[
|
5
|
+
names[:single][number]
|
12
6
|
end
|
13
7
|
|
14
8
|
def two_words(number)
|
15
9
|
return single number if number <= 19
|
16
|
-
number_name = names[
|
17
|
-
number_name +=
|
10
|
+
number_name = names[:two_words][number / 10]
|
11
|
+
number_name += ' ' + single(number % 10) if (number % 10 != 0)
|
18
12
|
number_name
|
19
13
|
end
|
20
14
|
|
21
15
|
def three_words(number)
|
22
16
|
return two_words number if number <= 99
|
23
|
-
number_name = single(number / 100) +
|
24
|
-
number_name +=
|
25
|
-
number_name +=
|
17
|
+
number_name = single(number / 100) + ' ' + names[:ten_powers][2]
|
18
|
+
number_name += ' ' + two_words(number % 100) if number % 100 >= 10
|
19
|
+
number_name += ' ' + names[:and] + ' ' + single(number % 100) if number % 100 < 10 && number % 100 != 0
|
26
20
|
number_name
|
27
21
|
end
|
28
22
|
|
@@ -30,25 +24,17 @@ module Kabal
|
|
30
24
|
less_thousands number if number_is_thousands? number
|
31
25
|
return @number_name if number_is_thousands? number
|
32
26
|
create_number_name number
|
33
|
-
ten_powers number % (10
|
34
|
-
end
|
35
|
-
|
36
|
-
def create_number_name(number)
|
37
|
-
if @number_name.nil?
|
38
|
-
@number_name = count_name(number) + " " + names["ten_powers"][number_order(number)]
|
39
|
-
elsif count(number) != 0
|
40
|
-
@number_name += " " + count_name(number) + " " + names["ten_powers"][number_order(number)]
|
41
|
-
end
|
27
|
+
ten_powers number % (10**number_order(number))
|
42
28
|
end
|
43
29
|
|
44
|
-
def
|
45
|
-
three_words
|
30
|
+
def count_name_with_order_name(number)
|
31
|
+
three_words(count(number)) + ' ' + names[:ten_powers][number_order(number)]
|
46
32
|
end
|
47
33
|
|
48
34
|
def less_thousands(number)
|
49
35
|
return if number == 0
|
50
|
-
@number_name +=
|
51
|
-
@number_name +=
|
36
|
+
@number_name += ' ' + names[:and] if number < 100
|
37
|
+
@number_name += ' ' + three_words(number % 1000) unless number == 0
|
52
38
|
end
|
53
39
|
end
|
54
40
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Kabal
|
2
|
+
module GlobalRules
|
3
|
+
module FractionalNumbers
|
4
|
+
def fractional_part_order(number)
|
5
|
+
number_string = number.to_s
|
6
|
+
if number_string.include? '-'
|
7
|
+
number_string.split('-')[1].to_i
|
8
|
+
else
|
9
|
+
number_string.split('.')[1].length
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def fractional_part_name(number)
|
14
|
+
@count_string = fractional_part_string(number).to_s.split('.')[1]
|
15
|
+
@count_int = @count_string.to_i
|
16
|
+
if there_zeros_before_fractional_part?
|
17
|
+
number_name_with_zeros + natural_number_name(@count_int)
|
18
|
+
else
|
19
|
+
natural_number_name @count_int
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def there_zeros_before_fractional_part?
|
24
|
+
@count_string.size != @count_int.to_s.size
|
25
|
+
end
|
26
|
+
|
27
|
+
def zeros_number
|
28
|
+
@count_string.size - @count_int.to_s.size
|
29
|
+
end
|
30
|
+
|
31
|
+
def number_name_with_zeros
|
32
|
+
name = ''
|
33
|
+
zeros_number.times do
|
34
|
+
name += names[:single][0] + ' '
|
35
|
+
end
|
36
|
+
name
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Kabal
|
2
|
+
module GlobalRules
|
3
|
+
module NaturalNumbers
|
4
|
+
def natural_number_name(number)
|
5
|
+
return single number if number >= 0 && number <= 19
|
6
|
+
return two_words number if number >= 0 && number <= 99
|
7
|
+
return three_words number if number >= 100 && number <= 999
|
8
|
+
ten_powers number if number >= 100
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_number_name(number)
|
12
|
+
if @number_name.nil?
|
13
|
+
@number_name = count_name_with_order_name number
|
14
|
+
elsif count(number) != 0
|
15
|
+
@number_name += ' ' + count_name_with_order_name(number)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,8 +1,15 @@
|
|
1
|
+
require 'kabal/languages/global/fractional_numbers'
|
2
|
+
require 'kabal/languages/global/natural_numbers'
|
3
|
+
|
1
4
|
module Kabal
|
2
5
|
class Language
|
6
|
+
include Kabal::GlobalRules::NaturalNumbers
|
7
|
+
include Kabal::GlobalRules::FractionalNumbers
|
8
|
+
|
3
9
|
def initialize
|
4
10
|
@names = Kabal::Config::YamlLoader.yaml_object "languages/#{lang}"
|
5
|
-
|
11
|
+
support_file = Kabal::Config::YamlLoader.yaml_object('support')
|
12
|
+
@supports = support_file[:support][lang]
|
6
13
|
end
|
7
14
|
|
8
15
|
def convert(number)
|
@@ -13,22 +20,36 @@ module Kabal
|
|
13
20
|
end
|
14
21
|
end
|
15
22
|
|
23
|
+
def convert_number(number)
|
24
|
+
@number_name = nil
|
25
|
+
if need_minus? number
|
26
|
+
minus + ' ' + number_words(-number)
|
27
|
+
else
|
28
|
+
number_words number
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def number_words(number)
|
33
|
+
return natural_number_name number.round if natural? number
|
34
|
+
fractional_number_name number if fractional? number
|
35
|
+
end
|
36
|
+
|
16
37
|
def error(number)
|
17
38
|
if number_is_out_of_the_range? number
|
18
39
|
return Kabal::Errors::NumberOutRangeError.message
|
19
40
|
end
|
20
|
-
if
|
41
|
+
if (!supports_fractional?) && (number % 1 != 0)
|
21
42
|
Kabal::Errors::NoSupportForFractionalNumberOnCurrentLanguages.message
|
22
43
|
end
|
23
44
|
end
|
24
45
|
|
25
46
|
def lang
|
26
|
-
languages = Kabal::Config::YamlLoader.yaml_object
|
27
|
-
@lang = languages[self.to_s.split(
|
47
|
+
languages = Kabal::Config::YamlLoader.yaml_object 'languages'
|
48
|
+
@lang = languages[self.to_s.split(':')[-2]]
|
28
49
|
end
|
29
50
|
|
30
51
|
def supports_natural?
|
31
|
-
@supports[
|
52
|
+
@supports[:natural]
|
32
53
|
end
|
33
54
|
|
34
55
|
def supports_negative?
|
@@ -36,11 +57,11 @@ module Kabal
|
|
36
57
|
end
|
37
58
|
|
38
59
|
def min_value
|
39
|
-
eval @supports[
|
60
|
+
eval @supports[:natural][:min]
|
40
61
|
end
|
41
62
|
|
42
63
|
def max_value
|
43
|
-
eval @supports[
|
64
|
+
eval @supports[:natural][:max]
|
44
65
|
end
|
45
66
|
|
46
67
|
def names
|
@@ -48,15 +69,15 @@ module Kabal
|
|
48
69
|
end
|
49
70
|
|
50
71
|
def minus
|
51
|
-
names[
|
72
|
+
names[:minus]
|
52
73
|
end
|
53
74
|
|
54
75
|
def whole
|
55
|
-
names[
|
76
|
+
names[:whole]
|
56
77
|
end
|
57
78
|
|
58
79
|
def dot
|
59
|
-
names[
|
80
|
+
names[:dot]
|
60
81
|
end
|
61
82
|
|
62
83
|
def fractional?(number)
|
@@ -72,7 +93,7 @@ module Kabal
|
|
72
93
|
end
|
73
94
|
|
74
95
|
def number_is_google?(number)
|
75
|
-
count(number) == 10
|
96
|
+
count(number) == 10 && number_order(number) == 99
|
76
97
|
end
|
77
98
|
|
78
99
|
def number_order(number)
|
@@ -80,19 +101,23 @@ module Kabal
|
|
80
101
|
end
|
81
102
|
|
82
103
|
def count(number)
|
83
|
-
number / (10
|
104
|
+
number / (10**number_order(number))
|
84
105
|
end
|
85
106
|
|
86
107
|
def supports_fractional?
|
87
|
-
@supports[
|
108
|
+
@supports[:fractional]
|
88
109
|
end
|
89
110
|
|
90
111
|
def number_is_out_of_the_range?(number)
|
91
|
-
number >= max_value
|
112
|
+
number >= max_value || number <= min_value
|
113
|
+
end
|
114
|
+
|
115
|
+
def fractional_but_no_support_fractional?(number)
|
116
|
+
number % 1 != 0 && !supports_fractional?
|
92
117
|
end
|
93
118
|
|
94
119
|
def no_supports?(number)
|
95
|
-
(number
|
120
|
+
fractional_but_no_support_fractional?(number) || number_is_out_of_the_range?(number)
|
96
121
|
end
|
97
122
|
|
98
123
|
def need_minus?(number)
|
@@ -3,22 +3,9 @@ require 'kabal/languages/russian/declinations'
|
|
3
3
|
require 'kabal/languages/russian/natural_numbers'
|
4
4
|
require 'kabal/languages/russian/fractional_numbers'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def convert_number(number)
|
11
|
-
#FIXME find better way
|
12
|
-
@number_name = nil
|
13
|
-
if need_minus? number
|
14
|
-
minus + " " + number_words(-number)
|
15
|
-
else
|
16
|
-
number_words number
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def number_words(number)
|
21
|
-
return natural_number_name number.round if natural? number
|
22
|
-
fractional_number_name number if fractional? number
|
6
|
+
module Kabal
|
7
|
+
class Russian < Kabal::Language
|
8
|
+
include Kabal::RussianRules::NaturalNumbers
|
9
|
+
include Kabal::RussianRules::FractionalNumbers
|
23
10
|
end
|
24
11
|
end
|
@@ -2,32 +2,30 @@ module Kabal
|
|
2
2
|
module RussianRules
|
3
3
|
module Declinations
|
4
4
|
def self.name_with_declination(number_name, count)
|
5
|
-
|
6
|
-
#FIXME find another way to convert number from exp form
|
7
|
-
if count.to_s.include? "e"
|
5
|
+
if count.to_s.include? 'e'
|
8
6
|
count = count.to_s.split('.')[0].to_i
|
9
7
|
end
|
10
|
-
#FIXME add gem russian
|
11
|
-
if number_name[-1, 1] ==
|
8
|
+
# FIXME add gem russian
|
9
|
+
if number_name[-1, 1] == 'а'
|
12
10
|
return number_name if ends_with_one? count
|
13
|
-
return number_name[0..4] +
|
11
|
+
return number_name[0..4] + 'и' if end_with_two_or_three_of_four? count
|
14
12
|
number_name[0..4]
|
15
|
-
elsif number_name[-1, 1] ==
|
13
|
+
elsif number_name[-1, 1] == 'я'
|
16
14
|
return number_name if ends_with_one? count
|
17
|
-
number_name[0..-3] +
|
15
|
+
number_name[0..-3] + 'ых'
|
18
16
|
else
|
19
17
|
return number_name if ends_with_one? count
|
20
|
-
return number_name +
|
21
|
-
number_name +
|
18
|
+
return number_name + 'а' if end_with_two_or_three_of_four? count
|
19
|
+
number_name + 'ов'
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
25
23
|
def self.ends_with_one?(count)
|
26
|
-
count.to_s[-1] ==
|
24
|
+
count.to_s[-1] == '1' && (count % 100) / 10 != 1
|
27
25
|
end
|
28
26
|
|
29
27
|
def self.end_with_two_or_three_of_four?(count)
|
30
|
-
count.to_s[-1] ==
|
28
|
+
count.to_s[-1] == '2' || count.to_s[-1] == '3' || count.to_s[-1] == '4'
|
31
29
|
end
|
32
30
|
end
|
33
31
|
end
|
@@ -2,49 +2,38 @@ module Kabal
|
|
2
2
|
module RussianRules
|
3
3
|
module FractionalNumbers
|
4
4
|
def fractional_number_name(number)
|
5
|
-
whole_part_name(number) +
|
5
|
+
whole_part_name(number) + ' ' + fractional_part_name(number)
|
6
6
|
end
|
7
7
|
|
8
8
|
def fractional_part_name(number)
|
9
|
-
fractional_part = (number % 1).round(
|
10
|
-
fractional_order = ((fractional_part) * (10
|
11
|
-
feminine_natural_number_name(fractional_order, true) +
|
9
|
+
fractional_part = (number % 1).round(fractional_part_order(number))
|
10
|
+
fractional_order = ((fractional_part) * (10**fractional_part_order(number))).to_s.split('.')[0].to_i
|
11
|
+
feminine_natural_number_name(fractional_order, true) + ' ' + Declinations.name_with_declination(fractional_ten_powers_name(number), fractional_part)
|
12
12
|
end
|
13
13
|
|
14
14
|
def whole_part_name(number)
|
15
15
|
count = number.floor
|
16
|
-
feminine_natural_number_name(count) +
|
16
|
+
feminine_natural_number_name(count) + ' ' + Declinations.name_with_declination(whole, count)
|
17
17
|
end
|
18
18
|
|
19
19
|
def fractional_ten_powers_name(number)
|
20
|
-
ten_powers_name = ""
|
21
20
|
if need_pre_word? number
|
22
|
-
|
21
|
+
fractional_pre_word(number) + fractional_order_word(number)
|
23
22
|
else
|
24
|
-
|
23
|
+
names[:fractional_ten_powers][fractional_part_order(number)]
|
25
24
|
end
|
26
25
|
end
|
27
26
|
|
28
27
|
def fractional_order_word(number)
|
29
|
-
names[
|
28
|
+
names[:fractional_ten_powers][fractional_part_order(number) - (fractional_part_order(number) % 3)]
|
30
29
|
end
|
31
30
|
|
32
31
|
def fractional_pre_word(number)
|
33
|
-
names[
|
32
|
+
names[:fractional_pre_words][fractional_part_order(number) % 3]
|
34
33
|
end
|
35
34
|
|
36
35
|
def need_pre_word?(number)
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
def fractional_number_order(number)
|
41
|
-
#FIXME find better way with whole 0 numbers
|
42
|
-
number_string = number.to_s
|
43
|
-
if number_string.include? "-"
|
44
|
-
number_string.split('-')[1].to_i
|
45
|
-
else
|
46
|
-
number_string.split('.')[1].length
|
47
|
-
end
|
36
|
+
fractional_part_order(number) > 3 && fractional_part_order(number) % 3 != 0
|
48
37
|
end
|
49
38
|
end
|
50
39
|
end
|
@@ -2,74 +2,67 @@ module Kabal
|
|
2
2
|
module RussianRules
|
3
3
|
module NaturalNumbers
|
4
4
|
def feminine_natural_number_name(number, fractional_part = false)
|
5
|
+
@number_name = nil
|
5
6
|
@number = number
|
6
7
|
@feminine_name = !fractional_part
|
7
8
|
@fractional_part = fractional_part
|
8
9
|
natural_number_name number
|
9
10
|
end
|
10
11
|
|
11
|
-
def
|
12
|
-
#FIXME switch case next lines
|
13
|
-
return single(number, true) if number >= 0 and number <= 19
|
14
|
-
return two_words(number, true) if number >= 20 and number <= 99
|
15
|
-
return three_words(number, true) if number >= 100 and number <= 999
|
16
|
-
ten_powers(number) if number >= 1000
|
17
|
-
end
|
18
|
-
|
19
|
-
def single(number, this_is_end = false)
|
12
|
+
def single(number, this_is_end = true)
|
20
13
|
if @feminine_name
|
21
14
|
@feminine_name = false
|
22
|
-
return names[
|
15
|
+
return names[:single_feminine][count(number) % 10] if count_can_be_feminine? number
|
23
16
|
end
|
24
|
-
if @fractional_part
|
17
|
+
if @fractional_part && this_is_end
|
25
18
|
@fractional_part = false
|
26
|
-
return names[
|
19
|
+
return names[:single_feminine][count(number) % 10] if count_can_be_feminine? number
|
27
20
|
end
|
28
|
-
names[
|
21
|
+
names[:single][number]
|
29
22
|
end
|
30
23
|
|
31
|
-
def two_words(number, this_is_end =
|
24
|
+
def two_words(number, this_is_end = true)
|
32
25
|
return single(number, this_is_end) if number <= 19
|
33
|
-
number_name = names[
|
34
|
-
number_name +=
|
26
|
+
number_name = names[:two_words][number / 10]
|
27
|
+
number_name += ' ' + single(number % 10, this_is_end) if (number % 10 != 0)
|
35
28
|
number_name
|
36
29
|
end
|
37
30
|
|
38
|
-
def three_words(number, this_is_end =
|
31
|
+
def three_words(number, this_is_end = true)
|
39
32
|
return two_words(number, this_is_end) if number / 100 == 0
|
40
|
-
number_name = names[
|
41
|
-
return number_name +=
|
42
|
-
return number_name +=
|
33
|
+
number_name = names[:three_words][number / 100]
|
34
|
+
return number_name += ' ' + two_words(number % 100, this_is_end) if (number % 100 >= 20)
|
35
|
+
return number_name += ' ' + single(number % 100, this_is_end) if (number % 100 != 0)
|
43
36
|
number_name
|
44
37
|
end
|
45
38
|
|
46
39
|
def ten_powers(number)
|
47
|
-
return names[
|
40
|
+
return names[:ten_powers][100] if number_is_google? number
|
48
41
|
less_thousands number if number_is_thousands? number
|
49
42
|
return @number_name if number_is_thousands? number
|
50
43
|
create_number_name number
|
51
44
|
ten_powers(number % (10 ** number_order(number)))
|
52
45
|
end
|
53
46
|
|
54
|
-
def
|
55
|
-
|
56
|
-
@number_name = count_name(number) + " " + Declinations.name_with_declination(names["ten_powers"][number_order(number)], count(number))
|
57
|
-
elsif count(number) != 0
|
58
|
-
@number_name += " " + count_name(number) + " " + Declinations.name_with_declination(names["ten_powers"][number_order(number)], count(number))
|
59
|
-
end
|
47
|
+
def count_can_be_feminine?(number)
|
48
|
+
count(number) % 10 == 1 || count(number) % 10 == 2
|
60
49
|
end
|
61
50
|
|
62
51
|
def less_thousands(number)
|
63
|
-
@number_name +=
|
52
|
+
@number_name += ' ' + three_words(number % 1000) unless number == 0
|
64
53
|
end
|
65
54
|
|
66
55
|
def count_name(number)
|
67
|
-
if (number.to_s[-4] ==
|
56
|
+
if (number.to_s[-4] == '1' || number.to_s[-4] == '2') && count(number) && (count(number) % 100) / 10 != 1 && number_order(number) == 3
|
68
57
|
@feminine_name = true
|
69
58
|
else
|
70
59
|
@feminine_name = false
|
71
60
|
end
|
72
|
-
three_words count(number)
|
61
|
+
three_words count(number), false
|
62
|
+
end
|
63
|
+
|
64
|
+
def count_name_with_order_name(number)
|
65
|
+
count_name(number) + ' ' + Declinations.name_with_declination(names[:ten_powers][number_order(number)], count(number))
|
73
66
|
end
|
74
67
|
end
|
75
68
|
end
|
data/lib/kabal/version.rb
CHANGED
data/test/lib/kabal_test.rb
CHANGED
@@ -5,10 +5,11 @@ include Kabal
|
|
5
5
|
class KabalTest < TestCase
|
6
6
|
def test_language_init
|
7
7
|
Kabal.language = "Russian"
|
8
|
-
assert_equal Kabal.current_language
|
8
|
+
assert_equal "Russian", Kabal.current_language
|
9
9
|
end
|
10
10
|
|
11
11
|
def test_to_text
|
12
|
+
Kabal.language = "Russian"
|
12
13
|
assert_equal "сто двадцать пять миллиардов сто двадцать пять миллионов сто двадцать пять тысяч сто двадцать пять", Kabal.to_text(125125125125)
|
13
14
|
assert_equal "сто двадцать пять миллиардов сто двадцать пять миллионов сто двадцать пять тысяч сто двадцать пять", Kabal.to_text("125125125125")
|
14
15
|
end
|
@@ -57,15 +58,15 @@ class KabalTest < TestCase
|
|
57
58
|
end
|
58
59
|
|
59
60
|
def test_maximum_for_language
|
60
|
-
assert_equal Kabal.maximum_for("Russian")
|
61
|
-
assert_equal
|
62
|
-
assert_equal
|
61
|
+
assert_equal 10 ** 102, Kabal.maximum_for("Russian")
|
62
|
+
assert_equal (10 ** 66) - 1, Kabal.maximum_for("English")
|
63
|
+
assert_equal (10 ** 24) - 1, Kabal.maximum_for("Deutsch")
|
63
64
|
end
|
64
65
|
|
65
66
|
def test_minimum_for_language
|
66
|
-
assert_equal Kabal.minimum_for("Russian")
|
67
|
-
assert_equal
|
68
|
-
assert_equal
|
67
|
+
assert_equal -(10 ** 102), Kabal.minimum_for("Russian")
|
68
|
+
assert_equal -(10 ** 66) + 1, Kabal.minimum_for("English")
|
69
|
+
assert_equal -(10 ** 24) + 1, Kabal.minimum_for("Deutsch")
|
69
70
|
end
|
70
71
|
|
71
72
|
def test_minimum_and_maximum_convert_for_language
|
@@ -88,9 +89,11 @@ class KabalTest < TestCase
|
|
88
89
|
end
|
89
90
|
|
90
91
|
def test_bad_number_test
|
91
|
-
|
92
|
-
assert_equal Kabal.to_text("
|
93
|
-
assert_equal Kabal.to_text("
|
94
|
-
assert_equal
|
92
|
+
Kabal.language = "Russian"
|
93
|
+
assert_equal "сто десять квинтиллионов одна тысяча одиннадцать", Kabal.to_text("110000000000000001011")
|
94
|
+
assert_equal "одиннадцать квадраллионов одиннадцать", Kabal.to_text("11000000000000011")
|
95
|
+
assert_equal "сто двенадцать квинтиллиона двести двадцать три квадраллиона триста тридцать четыре триллиона четыреста сорок пять миллиардов пятьсот пятьдесят шесть миллионов шестьсот шестьдесят одна тысяча одиннадцать", Kabal.to_text("112223334445556661011")
|
96
|
+
assert_equal "девятьсот девять миллионов девяносто тысяч девятьсот девять целых одна тысяча двести тридцать четыре десятитысячных", Kabal.to_text("909090909.1234")
|
97
|
+
assert_equal "девятьсот девять миллионов девяносто тысяч девятьсот девять целых одна тысяча двести тридцать четыре десятитысячных", Kabal.to_text(909090909.1234)
|
95
98
|
end
|
96
99
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kabal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pavel Kalashnikov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
description: 'Kabal allows you to translate numbers into text on languages: English,
|
42
|
-
Russian, Deutsch'
|
42
|
+
Russian, Deutsch. See demo on http://kabal.herokuapp.com'
|
43
43
|
email:
|
44
44
|
- kalashnikovisme@gmail.com
|
45
45
|
executables: []
|
@@ -70,6 +70,8 @@ files:
|
|
70
70
|
- lib/kabal/languages/english.rb
|
71
71
|
- lib/kabal/languages/english/fractional_numbers.rb
|
72
72
|
- lib/kabal/languages/english/natural_numbers.rb
|
73
|
+
- lib/kabal/languages/global/fractional_numbers.rb
|
74
|
+
- lib/kabal/languages/global/natural_numbers.rb
|
73
75
|
- lib/kabal/languages/language.rb
|
74
76
|
- lib/kabal/languages/russian.rb
|
75
77
|
- lib/kabal/languages/russian/declinations.rb
|