petrovich 0.2.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 291b554af39a55c68a42696020da4267eead218c
4
- data.tar.gz: 8b1b99e5cb9e78d82e2ef87604888c917ab155bd
3
+ metadata.gz: 8e6066940e4b5258379235c3252ff522958d539b
4
+ data.tar.gz: 5ecd85e3a147030e003819d3866061a927eb1552
5
5
  SHA512:
6
- metadata.gz: d3ad699a3a7abb3dbccabc0ca5c3c7ede00c128bea6a509bd6a154ec441ed8be6b457a3388dfa725b9f9e2eec912e639ff37ce7c27cc5fc8693daf7633861396
7
- data.tar.gz: 84c671a9e76c5cc738f3ea3b62f1092d57353b51efe0f95421540c730c2e19509aa1992ea637808c6735659aac3c9b78746bbb943c676b9cfb204e9ae32611c0
6
+ metadata.gz: 95f3fd34b305b733f233df19c9bb31a71e712c7a8d298104f0a2764baa2f56deeb07876cd6f2fbb62915c8d64ff060229505cc0d484014044a5140728c55484f
7
+ data.tar.gz: da1eac52ca78014e3ecf10fcda4ecee604d35a7d05dff8a78d3d24a3ae39c0f4af150ae74b13d23f1951c331ccba9163956dc7ac2b51d4a910126e4b828ea6ec
data/README.md CHANGED
@@ -3,16 +3,16 @@
3
3
  Склонение падежей русских имён, фамилий и отчеств. Вы задаёте начальное имя
4
4
  в именительном падеже, а получаете в нужном вам.
5
5
 
6
- [![Build Status](https://secure.travis-ci.org/petrovich/petrovich-ruby.png)](http://travis-ci.org/petrovich/petrovich-ruby)
6
+ Petrovich также позволяет определять пол по имени, фамилии, отчеству.
7
7
 
8
- #### Посмотреть в действии: http://petrovich.rocketscience.it
8
+ [![Build Status](https://travis-ci.org/petrovich/petrovich-ruby.svg?branch=dev-1.0)](https://travis-ci.org/petrovich/petrovich-ruby)
9
9
 
10
10
  ## Установка
11
11
 
12
12
  Добавьте в Gemfile:
13
13
 
14
14
  ```ruby
15
- gem 'petrovich'
15
+ gem 'petrovich', '~> 1.0'
16
16
  ```
17
17
 
18
18
  Установите гем cредствами Bundler:
@@ -25,199 +25,100 @@ gem 'petrovich'
25
25
 
26
26
  ## Зависимости
27
27
 
28
- Для работы гема требуется Ruby не младше версии 1.9.1. Petrovich не
28
+ Для работы гема требуется Ruby не младше версии 1.9.3. Petrovich не
29
29
  привязан к Ruby on Rails и может свободно использоваться практически
30
30
  в любых приложениях и библиотеках на языке Ruby.
31
31
 
32
32
  ## Использование
33
33
 
34
34
  Вы задаёте начальные значения (фамилию, имя и отчество) в именительном
35
- падеже, а библиотека делает всё остальное.
35
+ падеже, а библиотека делает всё остальное. Если вам известен пол - укажите его, это повысит скорость работы и даст более точные результаты. Если пол не указан, то Petrovich попытается определить его автоматически. Примеры:
36
36
 
37
37
  ```ruby
38
- p = Petrovich.new(:male)
39
- p.lastname('Иванов', :dative) # => Иванову
40
- p.firstname('Пётр', :dative) # => Петру
41
- p.middlename('Сергеевич', :dative) # => Сергеевичу
38
+ # Склонение в дательный падеж при помощи метода `dative`. Существуют методы `genitive`,
39
+ # `dative`, `accusative`, `instrumental`, `prepositional`.
40
+ Petrovich(
41
+ lastname: 'Салтыков-Щедрин',
42
+ firstname: 'Михаил',
43
+ middlename: 'Евграфович',
44
+ ).dative.to_s # => Салтыкову-Щедрину Михаилу Евграфовичу
45
+
46
+ # Склонение в творительный падеж с использованием метода `to` и возвратом отчества.
47
+ # Аналогично можно вызвать метод `firstname`, чтобы получить имя.
48
+ Petrovich(
49
+ firstname: 'Иван',
50
+ middlename: 'Петрович',
51
+ ).to(:instrumental).middlename # => Петровича Ивана
52
+
53
+ # Склонение с указанием пола. В данном случае по имени и фамилии не возможно определить пол
54
+ # человека, поэтому, если вам известен пол, всегда передавайте его в аргументах,
55
+ # чтобы склонение было верным.
56
+ # Если пол неизвестен, то гем попытается определить его самостоятельно.
57
+ # Пол должен быть указан в виде строки или символа, возможные значения: male, female.
58
+ Petrovich(
59
+ lastname: 'Андрейчук',
60
+ firstname: 'Саша',
61
+ gender: :male
62
+ ).to(:instrumental).to_s # => Андрейчуку Саше
42
63
  ```
43
64
 
44
- Конструктор класса `Petrovich` принимает пол в качестве единственного
45
- аргумента. Пол может принимать значения `:male`, `:female` или
46
- `:androgynous`. Последнее означает, что слово не склоняется по родам.
47
- По нормам языка, некоторые фамилии не склоняются. Например, такие
48
- украинские фамилии, как Симоненко, а также заимствованные фамилии,
49
- такие как Нельсон.
50
-
51
- Важно понимать, что явное указание пола повышает аккуратность обработки слов.
52
- Если пол неизвестен, однако известно отчество, то гем постарается
53
- определить пол по отчеству на основе простой эвристики.
54
-
55
- ### Продвинутое использование
56
-
57
- Вы можете подмешать модуль `Petrovich::Extension` в любой класс. Это
58
- особенно полезно при использовании ActiveRecord и подобных ORM.
59
-
60
- ```ruby
61
- class User < ActiveRecord::Base
62
- include Petrovich::Extension
63
-
64
- petrovich :firstname => :my_firstname,
65
- :middlename => :my_middlename,
66
- :lastname => :my_lastname,
67
- :gender => :my_gender
68
-
69
- def my_firstname
70
- 'Пётр'
71
- end
72
-
73
- def my_middlename
74
- 'Петрович'
75
- end
76
-
77
- def my_lastname
78
- 'Петренко'
79
- end
80
-
81
- # Если пол не был указан, используется автоматическое определение
82
- # пола на основе отчества. Если отчество также не было указано,
83
- # пытаемся определить правильное склонение на основе файла правил.
84
- def my_gender
85
- :male # :male, :female или :androgynous
86
- end
87
- end
88
- ```
89
-
90
- Ничего не мешает подмешать модуль `Petrovich::Extension` в самый обычный
91
- класс.
92
-
93
- ```ruby
94
- class Person
95
- include Petrovich::Extension
96
-
97
- # А здесь мы не указали пол - он будет определяться на основе отчества
98
- petrovich :firstname => :name,
99
- :middlename => :patronymic,
100
- :lastname => :surname
101
-
102
- def name
103
- 'Иван'
104
- end
105
-
106
- def patronymic
107
- 'Олегович'
108
- end
109
-
110
- def surname
111
- 'Сафронов'
112
- end
113
- end
114
- ```
115
-
116
- При помощи метода `petrovich` указываются методы, представляющие фамилию,
117
- имя и отчество. В данном примере указано, что метод `name` представляет
118
- имя, метод `lastname` представляет фамилию, метод `patronymic` представляет
119
- отчество.
120
-
121
- После конфигурации Petrovich можно легко выполнять склонение необходимых
122
- строк.
123
-
124
- ```ruby
125
- user = User.new
126
- user.my_firstname # => Пётр
127
-
128
- user.my_firstname_dative # => Петру
129
- user.my_middlename_dative # => Петровичу
130
- user.my_lastname_dative # => Петренко
131
- ```
132
-
133
- ```ruby
134
- person = Person.new
135
- person.name # => Иван
136
-
137
- person.my_firstname_dative # => Ивану
138
- person.my_middlename_dative # => Олеговичу
139
- person.my_lastname_dative # => Сафронову
140
- ```
141
-
142
- Базовое имя должно быть в именительном падеже. Вы просто добавляете
143
- `_<суффикс>` в конец имени оригинального метода и получаете заданное имя
144
- в требуемом падеже.
145
-
146
- Названия суффиксов для методов образованы от английских названий
147
- соответствующих падежей. Полный список поддерживаемых падежей приведён
65
+ Полный список поддерживаемых методов склонения приведён
148
66
  в таблице ниже.
149
67
 
150
- | Суффикс метода | Падеж | Характеризующий вопрос |
68
+ | Метод | Падеж | Характеризующий вопрос |
151
69
  |----------------|--------------|------------------------|
152
- | genitive | родительный | Кого? Чего? |
153
- | dative | дательный | Кому? Чему? |
154
- | accusative | винительный | Кого? Что? |
155
- | instrumental | творительный | Кем? Чем? |
156
- | prepositional | предложный | О ком? О чём? |
157
-
158
- ## Лемматизация
159
-
160
- Petrovich умеет выполнять преобразовывание фамилии, имени и отчества
161
- в произвольном падеже к нормальной форме, а именно в именительный падеж.
162
- Такой процесс называется *лемматизацией*.
163
-
164
- Для выполнения лемматизации нужно передать в методы склонения третий
165
- аргумент, означающий текущий падеж слова, а во втором аргументе указать
166
- желаемый падеж — именительный.
70
+ | genitive | родительный | Кого? |
71
+ | dative | дательный | Кому? |
72
+ | accusative | винительный | Кого? |
73
+ | instrumental | творительный | Кем? |
74
+ | prepositional | предложный | О ком? |
167
75
 
168
- ```ruby
169
- p = Petrovich.new(:male )
170
- p.firstname('Савве', :nominative, :dative) # => Савва
171
- p.middlename('Палладиевичу', :nominative, :dative) # => Палладиевич
172
- p.lastname('Солунскому', :nominative, :dative) # => Солунский
173
- ```
76
+ ### Определение пола
174
77
 
175
- Также Petrovich позволяет преобразовывать слово сразу в любой падеж,
176
- отличный от именительного:
78
+ Примеры:
177
79
 
178
80
  ```ruby
179
- p = Petrovich.new(:female )
180
- p.firstname('Марфе', :accusative, :dative) # => Марфу
181
- p.middlename('Золовне', :accusative, :dative) # => Золовну
182
- p.lastname('Соловецкой', :accusative, :dative) # => Соловецкую
81
+ Petrovich(
82
+ lastname: 'Склифасовский'
83
+ ).gender # => :male
84
+
85
+ Petrovich(
86
+ firstname: 'Александра',
87
+ lastname: 'Склифасовская'
88
+ ).female? # => true
89
+
90
+ Petrovich(
91
+ lastname: 'Склифасовский'
92
+ ).male? # => true
93
+
94
+ Petrovich(
95
+ firstname: 'Саша',
96
+ lastname: 'Андрейчук'
97
+ ).androgynous? # => true
98
+
99
+ Petrovich(
100
+ firstname: 'Саша',
101
+ lastname: 'Андрейчук'
102
+ gender: :male,
103
+ ).male? # => true
183
104
  ```
184
105
 
185
- ## Оценка аккуратности
106
+ ## CLI
186
107
 
187
- Тестирование гема при склонении коллекции фамилий из морфологического
188
- словаря [АОТ] показало аккуратность около 99%. Оригинальный словарь
189
- распространяется по лицензии LGPL версии 2.1, однако используется
190
- только в задаче оценки аккуратности данного гема.
108
+ Примеры вызовов:
191
109
 
192
- Для оценки аккуратности достаточно выполнить команду `rake evaluate`. После
193
- выполнения этой команды в поток стандартного вывода будут напечатаны
194
- результаты оценки с данными в словаре АОТ.
195
-
196
- ```
197
- Ac(nominative|male) = 100.0000%
198
- Ac(genitive|male) = 99.7635%
199
- Ac(dative|male) = 99.7884%
200
- Ac(accusative|male) = 99.8008%
201
- Ac(instrumental|male) = 99.3037%
202
- Ac(prepositional|male) = 99.7759%
203
- ```
204
- ```
205
- Ac(nominative|female) = 100.0000%
206
- Ac(genitive|female) = 99.9102%
207
- Ac(dative|female) = 99.9401%
208
- Ac(accusative|female) = 99.9701%
209
- Ac(instrumental|female) = 99.4636%
210
- Ac(prepositional|female) = 99.9401%
110
+ ```bash
111
+ petrovich -l Иванов -f Иван -m Иванович -g male -t accusative
112
+ petrovich -l Иванов -f Иван -m Иванович -t accusative -d
113
+ petrovich -l Иванов -f Иван -m Иванович -t accusative -o
211
114
  ```
212
115
 
213
- В настоящий момент наблюдается аккуратность в 99.7984% на основе обработки
214
- 88314 примеров.
215
-
216
- [АОТ]: http://seman.svn.sourceforge.net/viewvc/seman/trunk/Docs/Morph_UNIX.txt?revision=HEAD&view=markup
116
+ Подробное руководство: `petrovich inflect --help`
217
117
 
218
118
  ## Модульные тесты
219
119
 
220
- Для запуска тестов достаточно выполнить `rake spec` или просто `rake`.
120
+ Для запуска тестов достаточно выполнить команду `rake`.
121
+ Чтобы запустить тесты "аккуратности" по словарю фамилий, выполните команду `rake evaluate`, после выполнения вы увидите подробный отчёт.
221
122
 
222
123
  ## Разработчики
223
124
 
@@ -237,20 +138,21 @@ Ac(prepositional|female) = 99.9401%
237
138
  ## Дальнейшее развитие
238
139
 
239
140
  Мы планируем и далее улучшать этот проект. Поэтому нам важен отклик от
240
- пользователей данного гема. Вот наши планы:
141
+ пользователей данного гема.
142
+
143
+ Наши приоритеты следующие:
241
144
 
242
- * добавить отладочный режим, чтобы видеть, какое именно правило было
243
- использовано при словообразовании;
244
- * интерфейс командной строки, чтобы работать с гемом из командной строки;
245
- * проверка совместимости с различными ORM и сторонними библиотеками.
145
+ * Повысить аккуратность склонения женских фамилий до 98%
146
+ * Обрабатывать ФИО в тексте. Например, чтобы выделить ФИО в виде гиперссылки. Не обязательно только ФИО, возможно просто фамилии, имена и так далее.
147
+ * Перевести реализацию на язык Rust. Это даст возможность использовать библиотеку в различных языках, подключая её через FFI и не потребует отдельной реализации в каждом языке. Это также увеличит скорость работы библиотеки.
246
148
 
247
149
  Если вы хотите помочь этому проекту, вы можете реализовать любую
248
150
  вышеперечисленную идею. Перед этим желательно связаться с нами,
249
- чтобы мы были в курсе.
151
+ чтобы мы были в курсе. Если у вас появилось такое желание, напишите в issues.
250
152
 
251
153
  ## Содействие
252
154
 
253
- Если вы нашли баги, как программной части, так и в базе правил, то вы всегда
155
+ Если вы нашли баги как программной части, так и в базе правил, то вы всегда
254
156
  можете форкнуть репозиторий и внести необходимые изменения. Ваша помощь не
255
157
  останется незамеченной! Если вы заметили ошибки при склонении падежей имён,
256
158
  фамилий или отчеств, можете написать об этом в Issues на GitHub.
data/Rakefile CHANGED
@@ -1,20 +1,18 @@
1
1
  #!/usr/bin/env rake
2
2
  # encoding: utf-8
3
3
 
4
- require 'bundler/gem_tasks'
5
- require 'rake/testtask'
4
+ require "bundler/gem_tasks"
5
+ require "rake/testtask"
6
6
 
7
- Rake::TestTask.new(:spec) do |test|
8
- test.libs << 'spec'
9
- test.test_files = Dir['spec/**/*_spec.rb']
10
- test.verbose = true
7
+ Rake::TestTask.new do |t|
8
+ t.test_files = FileList['test/*_test.rb']
11
9
  end
12
10
 
11
+ task default: :test
12
+
13
+ # We need this to avoid loading the library in tasks directly.
13
14
  task :petrovich do
14
15
  require 'petrovich'
15
16
  end
16
17
 
17
- # Run tests and perform evaluation by default
18
- task :default => [:spec, :evaluate]
19
-
20
18
  Dir.glob('lib/tasks/*.rake').each { |r| import r }
data/lib/petrovich.rb CHANGED
@@ -1,91 +1,92 @@
1
1
  # encoding: utf-8
2
- require 'yaml'
2
+ require 'forwardable'
3
+ require 'petrovich/value'
4
+ require 'petrovich/inflector'
5
+ require 'petrovich/inflected'
6
+ require 'petrovich/gender'
3
7
  require 'petrovich/unicode'
4
- require 'petrovich/rules'
5
- require 'petrovich/extension'
8
+ require 'petrovich/rule_set'
9
+ require 'petrovich/case/rule'
10
+ require 'petrovich/case/rule/modifier'
11
+ require 'petrovich/case/rule/test'
12
+ require 'petrovich/gender/rule'
6
13
 
7
- # Склонение падежей русских имён фамилий и отчеств. Вы задаёте начальное имя в именительном падеже,
8
- # а получаете в нужном вам.
9
- #
10
- # Использование
11
- #
12
- # # Склонение в дательном падеже
13
- # rn = Petrovich.new
14
- # puts rn.firstname('Иван', :dative) # => Ивану
15
- # puts rn.middlename('Сергеевич', :dative) # => Сергеевичу
16
- # puts rn.lastname('Воронов', :dative) # => Воронову
17
- #
18
- #
19
- # Если известен пол, то его можно передать в конструктор. Это повышает точность склонений
20
- #
21
- # rn = Petrovich.new('male')
22
- #
23
- # Если пол не известен, его можно определить по отчеству, при помощи метода +detect_gender+
24
- #
25
- # gender = Petrovich.detect_gender('Сергеевич')
26
- # rn = Petrovich.new(gender)
27
- #
28
- # Возможные падежи
29
- #
30
- # * +:nominative+ - именительный
31
- # * +:genitive+ - родительный
32
- # * +:dative+ - дательный
33
- # * +:accusative+ - винительный
34
- # * +:instrumental+ - творительный
35
- # * +:prepositional+ - предложный
36
- #
37
- class Petrovich
38
- CASES = [:nominative, :genitive, :dative, :accusative, :instrumental, :prepositional]
14
+ # A library to inflect Russian anthroponyms such as first names, last names, and middle names.
15
+ module Petrovich
16
+ # Possible cases
17
+ CASES = [
18
+ :nominative,
19
+ :genitive,
20
+ :dative,
21
+ :accusative,
22
+ :instrumental,
23
+ :prepositional
24
+ ]
39
25
 
40
- NOMINATIVE = :nominative # именительный
41
- GENITIVE = :genitive # родительный
42
- DATIVE = :dative # дательный
43
- ACCUSATIVE = :accusative # винительный
44
- INSTRUMENTAL = :instrumental # творительный
45
- PREPOSITIONAL = :prepositional # предложный
46
-
47
- def initialize(gender = nil)
48
- @gender = gender.to_s
49
- end
50
-
51
- def lastname(name, gcase, scase = :nominative)
52
- Rules.new(@gender).lastname(name, gcase, scase)
53
- end
54
-
55
- def firstname(name, gcase, scase = :nominative)
56
- Rules.new(@gender).firstname(name, gcase, scase)
57
- end
58
-
59
- def middlename(name, gcase, scase = :nominative)
60
- Rules.new(@gender).middlename(name, gcase, scase)
61
- end
62
-
63
- alias :patronymic :middlename
26
+ class << self
27
+ # A place that keeps inflection and gender rules loaded from yaml file.
28
+ #
29
+ # @return Petrovich::RuleSet
30
+ attr_accessor :rule_set
64
31
 
65
- def gender
66
- @gender
67
- end
32
+ # Checks name that should be value object, instance of {Petrovich::Value}
33
+ #
34
+ # Raises an ArgumentError if passed argument not of type Petrovich::Value or
35
+ # all values is empty in this object.
36
+ #
37
+ # @example
38
+ # Petrovich.assert_name!(name)
39
+ #
40
+ # @param [Foo] name Value to check
41
+ def assert_name!(name)
42
+ unless name.is_a?(Value)
43
+ fail ArgumentError, 'Passed argument should be Petrovich::Value instace'.freeze
44
+ end
68
45
 
69
- class << self
70
- include Petrovich::Unicode
46
+ if [name.lastname, name.firstname, name.middlename].compact.size == 0
47
+ fail ArgumentError, 'You should set at least one of :lastname, :firstname or :middlename'.freeze
48
+ end
49
+ end
71
50
 
72
- # Определение пола по отчеству
51
+ # Checks passed argument that should be member of {CASES}
73
52
  #
74
- # detect_gender('Алексеевич') # => male
53
+ # Raises an ArgumentError if passed argument not in {CASES}
75
54
  #
76
- # Если пол не был определён, метод возвращает значение +androgynous+
55
+ # @example
56
+ # Petrovich.assert_case!(name_case)
77
57
  #
78
- # detect_gender('блаблабла') # => androgynous
58
+ # @param [Foo] name_case Value to check
59
+ def assert_case!(name_case)
60
+ return if CASES.include?(name_case)
61
+ fail ArgumentError, "Unknown case #{name_case}"
62
+ end
63
+
64
+ # Converts hash to {Petrovich::Value} value object
79
65
  #
80
- def detect_gender(midname)
81
- case downcase(midname[-2, 2])
82
- when /ич|ыч/
83
- 'male'
84
- when 'на'
85
- 'female'
86
- else
87
- 'androgynous'
88
- end
66
+ # @example
67
+ # Petrovich.normalize_name(firstname: 'Иван', lastname: 'Иванов')
68
+ #
69
+ # @param [Hash] name Value hash with lastname, firstname, middlename
70
+ # @return [Petrovich::Value] Value object
71
+ def normalize_name(name)
72
+ name = Value.new(name) if name.is_a?(Hash)
73
+ name
74
+ end
75
+
76
+ # Loads YAML rules into {Petrovich::RuleSet} object
77
+ # @return [void]
78
+ def load_rules!
79
+ self.rule_set ||= RuleSet.new
80
+ self.rule_set.load!
89
81
  end
90
82
  end
83
+
84
+ load_rules!
85
+
86
+ require 'petrovich/name'
87
+ end
88
+
89
+ # Main entry point
90
+ def Petrovich(opts)
91
+ Petrovich::Name.new(opts)
91
92
  end