petrovich 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +14 -13
- data/lib/petrovich/extension.rb +19 -10
- data/lib/petrovich/rules.rb +42 -10
- data/lib/petrovich/rules.yml +22 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
|
6
6
|
[](http://travis-ci.org/rocsci/petrovich)
|
7
7
|
|
8
|
+
#### Посмотреть в действии: http://petrovich.rocketscience.it
|
9
|
+
|
8
10
|
## Установка
|
9
11
|
|
10
12
|
Добавьте в Gemfile:
|
@@ -47,7 +49,7 @@ p.middlename('Сергеевич', :dative) # => Сергеевичу
|
|
47
49
|
такие как Нельсон.
|
48
50
|
|
49
51
|
Важно понимать, что явное указание пола повышает точность обработки слов.
|
50
|
-
Если пол
|
52
|
+
Если пол неизвестен, однако известно отчество, то гем постарается
|
51
53
|
определить по пол отчеству на основе простой эвристики.
|
52
54
|
|
53
55
|
### Продвинутое использование
|
@@ -166,22 +168,22 @@ person.my_lastname_dative # => Сафронову
|
|
166
168
|
|
167
169
|
```
|
168
170
|
Pr(nominative|male) = 100.0000%
|
169
|
-
Pr(genitive|male) = 99.
|
170
|
-
Pr(dative|male) = 99.
|
171
|
-
Pr(accusative|male) = 99.
|
172
|
-
Pr(instrumental|male) = 97.
|
173
|
-
Pr(prepositional|male) = 99.
|
171
|
+
Pr(genitive|male) = 99.7137%
|
172
|
+
Pr(dative|male) = 99.7386%
|
173
|
+
Pr(accusative|male) = 99.7635%
|
174
|
+
Pr(instrumental|male) = 97.9858%
|
175
|
+
Pr(prepositional|male) = 99.7261%
|
174
176
|
```
|
175
177
|
```
|
176
178
|
Pr(nominative|female) = 100.0000%
|
177
|
-
Pr(genitive|female) = 99.
|
178
|
-
Pr(dative|female) = 99.
|
179
|
-
Pr(accusative|female) = 99.
|
180
|
-
Pr(instrumental|female) = 99.
|
181
|
-
Pr(prepositional|female) = 99.
|
179
|
+
Pr(genitive|female) = 99.9102%
|
180
|
+
Pr(dative|female) = 99.9401%
|
181
|
+
Pr(accusative|female) = 99.9701%
|
182
|
+
Pr(instrumental|female) = 99.4636%
|
183
|
+
Pr(prepositional|female) = 99.9401%
|
182
184
|
```
|
183
185
|
|
184
|
-
В настоящий момент наблюдается точность в 99.
|
186
|
+
В настоящий момент наблюдается точность в 99.6614% на основе обработки
|
185
187
|
88314 примеров.
|
186
188
|
|
187
189
|
[АОТ]: http://seman.svn.sourceforge.net/viewvc/seman/trunk/Docs/Morph_UNIX.txt?revision=HEAD&view=markup
|
@@ -203,7 +205,6 @@ Pr(prepositional|female) = 99.8952%
|
|
203
205
|
* добавить отладочный режим, чтобы видеть, какое именно правило было
|
204
206
|
использовано при словообразовании;
|
205
207
|
* интерфейс командной строки, чтобы работать с гемом из командной строки;
|
206
|
-
* Web-интерфейс для обработки ФИО;
|
207
208
|
* проверка совместимости с различными ORM и сторонними библиотеками.
|
208
209
|
|
209
210
|
Если вы хотите помочь этому проекту, вы можете реализовать любую
|
data/lib/petrovich/extension.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
class Petrovich
|
4
4
|
# Этот модуль разработан для возможности его подмешивания в класс Ruby.
|
5
5
|
# Его можно подмешать в любой класс, например, в модель ActiveRecord.
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# При помощи вызова метода +petrovich+ вы указываете, какие аттрибуты или методы класса
|
8
8
|
# будут возвращать фамилию, имя и отчество.
|
9
9
|
#
|
@@ -24,23 +24,23 @@ class Petrovich
|
|
24
24
|
# на основе файла правил.
|
25
25
|
#
|
26
26
|
# Пример использования
|
27
|
-
#
|
27
|
+
#
|
28
28
|
# class User
|
29
29
|
# include Petrovich::Extension
|
30
|
-
#
|
30
|
+
#
|
31
31
|
# petrovich :firstname => :my_firstname,
|
32
32
|
# :middlename => :my_middlename,
|
33
33
|
# :lastname => :my_lastname,
|
34
34
|
# :gender => :my_gender
|
35
|
-
#
|
35
|
+
#
|
36
36
|
# def my_firstname
|
37
37
|
# 'Пётр'
|
38
38
|
# end
|
39
|
-
#
|
39
|
+
#
|
40
40
|
# def my_middlename
|
41
41
|
# 'Александрович'
|
42
42
|
# end
|
43
|
-
#
|
43
|
+
#
|
44
44
|
# def my_lastname
|
45
45
|
# 'Ларин'
|
46
46
|
# end
|
@@ -74,7 +74,7 @@ class Petrovich
|
|
74
74
|
end
|
75
75
|
|
76
76
|
self.petrovich_configuration = {
|
77
|
-
:
|
77
|
+
:lastname => nil,
|
78
78
|
:firstname => nil,
|
79
79
|
:middlename => nil,
|
80
80
|
:gender => nil
|
@@ -84,11 +84,20 @@ class Petrovich
|
|
84
84
|
|
85
85
|
def petrovich_create_getter(method_name, attribute, gcase)
|
86
86
|
options = self.class.petrovich_configuration
|
87
|
-
reflection = options.key(attribute.to_sym) or
|
87
|
+
reflection = options.key(attribute.to_sym) or
|
88
|
+
raise "No reflection for attribute '#{attribute}'!"
|
88
89
|
|
89
90
|
self.class.send(:define_method, method_name) do
|
90
|
-
|
91
|
-
|
91
|
+
# detect by gender attr if defined
|
92
|
+
gender = options[:gender] && send(options[:gender])
|
93
|
+
# detect by middlename attr if defined
|
94
|
+
gender ||= begin
|
95
|
+
middlename = options[:middlename] && send(options[:middlename])
|
96
|
+
middlename && Petrovich.detect_gender(middlename)
|
97
|
+
end
|
98
|
+
|
99
|
+
rn = Petrovich.new gender
|
100
|
+
rn.send reflection, send(attribute), gcase
|
92
101
|
end
|
93
102
|
end
|
94
103
|
|
data/lib/petrovich/rules.rb
CHANGED
@@ -26,13 +26,18 @@ class Petrovich
|
|
26
26
|
#
|
27
27
|
[:lastname, :firstname, :middlename].each do |method_name|
|
28
28
|
define_method(method_name) do |name, gcase|
|
29
|
-
|
29
|
+
inflect(name, gcase, Petrovich::RULES[method_name.to_s])
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
protected
|
34
|
-
|
35
|
-
|
34
|
+
# Известно несколько типов признаков, которые влияют на процесс поиска.
|
35
|
+
#
|
36
|
+
# Признак +first_word+ указывает, что данное слово является первым словом
|
37
|
+
# в составном слове. Например, в двойной русской фамилии Иванов-Сидоров.
|
38
|
+
#
|
39
|
+
def match?(name, rule, match_whole_word, tags)
|
40
|
+
return false unless tags_allow? tags, rule['tags']
|
36
41
|
return false if rule['gender'] == 'male' && female? || rule['gender'] == 'female' && !female?
|
37
42
|
|
38
43
|
name = UnicodeUtils.downcase(name)
|
@@ -52,6 +57,19 @@ class Petrovich
|
|
52
57
|
@gender == 'female'
|
53
58
|
end
|
54
59
|
|
60
|
+
def inflect(name, gcase, rules)
|
61
|
+
i = 0
|
62
|
+
|
63
|
+
parts = name.split('-')
|
64
|
+
|
65
|
+
parts.map! do |part|
|
66
|
+
first_word = (i += 1) == 1 && parts.size > 1
|
67
|
+
find_and_apply(part, gcase, rules, first_word: first_word)
|
68
|
+
end
|
69
|
+
|
70
|
+
parts.join('-')
|
71
|
+
end
|
72
|
+
|
55
73
|
# Применить правило
|
56
74
|
def apply(name, gcase, rule)
|
57
75
|
modificator_for(gcase, rule).each_char do |char|
|
@@ -68,8 +86,8 @@ class Petrovich
|
|
68
86
|
end
|
69
87
|
|
70
88
|
# Найти правило и применить к имени с учетом склонения
|
71
|
-
def find_and_apply(name, gcase, rules)
|
72
|
-
rule = find_for(name, rules)
|
89
|
+
def find_and_apply(name, gcase, rules, features = {})
|
90
|
+
rule = find_for(name, rules, features)
|
73
91
|
apply(name, gcase, rule)
|
74
92
|
rescue UnknownRuleException
|
75
93
|
# Если не найдено правило для имени, возвращаем неизмененное имя.
|
@@ -77,21 +95,23 @@ class Petrovich
|
|
77
95
|
end
|
78
96
|
|
79
97
|
# Найти подходящее правило в исключениях или суффиксах
|
80
|
-
def find_for(name, rules)
|
98
|
+
def find_for(name, rules, features = {})
|
99
|
+
tags = extract_tags(features)
|
100
|
+
|
81
101
|
# Сначала пытаемся найти исключения
|
82
102
|
if rules.has_key?('exceptions')
|
83
|
-
p = find(name, rules['exceptions'], true)
|
103
|
+
p = find(name, rules['exceptions'], true, tags)
|
84
104
|
return p if p
|
85
105
|
end
|
86
106
|
|
87
107
|
# Не получилось, ищем в суффиксах. Если не получилось найти и в них,
|
88
108
|
# возвращаем неизмененное имя.
|
89
|
-
find(name, rules['suffixes'], false) or raise UnknownRuleException, "Cannot find rule for #{name}"
|
109
|
+
find(name, rules['suffixes'], false, tags) or raise UnknownRuleException, "Cannot find rule for #{name}"
|
90
110
|
end
|
91
111
|
|
92
112
|
# Найти подходящее правило в конкретном списке правил
|
93
|
-
def find(name, rules, match_whole_word)
|
94
|
-
rules.find { |rule| match?(name, rule, match_whole_word) }
|
113
|
+
def find(name, rules, match_whole_word, tags)
|
114
|
+
rules.find { |rule| match?(name, rule, match_whole_word, tags) }
|
95
115
|
end
|
96
116
|
|
97
117
|
# Получить модификатор из указанного правиля для указанного склонения
|
@@ -114,5 +134,17 @@ class Petrovich
|
|
114
134
|
end
|
115
135
|
end
|
116
136
|
|
137
|
+
# Преобразование +{a: true, b: false, c: true}+ в +%w(a c)+.
|
138
|
+
def extract_tags(features = {})
|
139
|
+
features.keys.select { |k| features[k] == true }.map(&:to_s)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Правило не подходит только в том случае, если оно содержит больше
|
143
|
+
# тегов, чем требуется для данного слова.
|
144
|
+
#
|
145
|
+
def tags_allow?(tags, rule_tags)
|
146
|
+
rule_tags ||= []
|
147
|
+
(rule_tags - tags).empty?
|
148
|
+
end
|
117
149
|
end
|
118
150
|
end
|
data/lib/petrovich/rules.yml
CHANGED
@@ -29,8 +29,29 @@
|
|
29
29
|
#
|
30
30
|
lastname:
|
31
31
|
exceptions:
|
32
|
+
# Неизменяемые первые части двойных русских фамилий.
|
33
|
+
#
|
34
|
+
- gender: androgynous
|
35
|
+
test:
|
36
|
+
- бонч
|
37
|
+
- абдул
|
38
|
+
- белиц
|
39
|
+
- гасан
|
40
|
+
- дюссар
|
41
|
+
- дюмон
|
42
|
+
- книппер
|
43
|
+
- корвин
|
44
|
+
- ван
|
45
|
+
- шолом
|
46
|
+
- тер
|
47
|
+
- призван
|
48
|
+
- мелик
|
49
|
+
- вар
|
50
|
+
mods: [., ., ., ., .]
|
51
|
+
tags: [first_word]
|
52
|
+
|
32
53
|
- gender: androgynous
|
33
|
-
test: [дюма, тома, дега, люка, ферма, гамарра, петипа,
|
54
|
+
test: [дюма, тома, дега, люка, ферма, гамарра, петипа, шандра, скаля]
|
34
55
|
mods: [., ., ., ., .]
|
35
56
|
|
36
57
|
- gender: androgynous
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: petrovich
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-09-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: unicode_utils
|