petrovich 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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