petrovich 0.0.7 → 0.1.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.
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
- ![Petrovich Logo](https://raw.github.com/rocsci/petrovich/master/petrovich.png)
1
+ ![Petrovich Logo](petrovich.png)
2
2
 
3
- Склонение падежей русских имён, фамилий и отчеств. Вы задаёте начальное имя в именительном падеже, а получаете в нужном вам.
3
+ Склонение падежей русских имён, фамилий и отчеств. Вы задаёте начальное имя
4
+ в именительном падеже, а получаете в нужном вам.
4
5
 
5
6
  [![Build Status](https://secure.travis-ci.org/rocsci/petrovich.png)](http://travis-ci.org/rocsci/petrovich)
6
7
 
@@ -10,36 +11,47 @@
10
11
 
11
12
  gem 'petrovich'
12
13
 
13
- Установите гем:
14
+ Установите гем cредствами Bundler:
14
15
 
15
16
  $ bundle
16
17
 
17
- Или, установите отдельно:
18
+ Или установите его отдельно:
18
19
 
19
20
  $ gem install petrovich
20
21
 
21
- ## Зависимоси
22
+ ## Зависимости
22
23
 
23
- * Ruby >= 1.9.1
24
- * Не зависит от Rails
24
+ Для работы гема требуется Ruby не младше версии 1.9.1. Petrovich не
25
+ привязан к Ruby on Rails и может свободно использоваться практически
26
+ в любых приложениях и библиотеках на Ruby.
25
27
 
26
28
  ## Использование
27
29
 
28
- Вы задаёте начальные значения (фамилию, имя и отчество) в именительном падеже. Самое простое использование выглядит так:
30
+ Вы задаёте начальные значения (фамилию, имя и отчество) в именительном
31
+ падеже.
29
32
 
30
33
  ```ruby
31
- # Указание пола снижает количество отказов
32
34
  p = Petrovich.new(:male)
33
35
  p.lastname('Иванов', :dative) # => Иванову
34
36
  p.firstname('Пётр', :dative) # => Петру
35
37
  p.middlename('Сергеевич', :dative) # => Сергеевичу
36
38
  ```
37
39
 
38
- Конструктор класса `Petrovich` принимает пол в качестве единственного аргумента. Пол может иметь значения `:male`, `:female` или `:androgynous`. Последнее означает, что имя не склоняется по родам. Обычно, не склоняются украинские фамилии, как например фамилия Симоненко, а так же фамилии, пришедшие в русский язык из европейских языков, например - Нельсон. Но всегда лучше, если пол вам известен и вы указываете его - так увеличивается вероятность правильного распознавания.
40
+ Конструктор класса `Petrovich` принимает пол в качестве единственного
41
+ аргумента. Пол может принимать значения `:male`, `:female` или
42
+ `:androgynous`. Последнее означает, что слово не склоняется по родам.
43
+ По нормам языка, некоторые фамилии не склоняются. Например, такие
44
+ украинские фамилии, как Симоненко, а также заимствованные фамилии,
45
+ такие как Нельсон.
46
+
47
+ Важно понимать, что явное указание пола повышает точность обработки слов.
48
+ Если пол не известен, однако известно отчество, то гем постарается
49
+ определить по пол отчеству на основе простой эвристики.
39
50
 
40
51
  ### Продвинутое использование
41
52
 
42
- Вы можете подмешать модуль `Petrovich::Extension` в любой класс. Это особенно полезно при использовании `ActiveRecord` и подобных ORM:
53
+ Вы можете подмешать модуль `Petrovich::Extension` в любой класс. Это
54
+ особенно полезно при использовании ActiveRecord и подобных ORM.
43
55
 
44
56
  ```ruby
45
57
  class User < ActiveRecord::Base
@@ -71,7 +83,8 @@ class User < ActiveRecord::Base
71
83
  end
72
84
  ```
73
85
 
74
- Или, подмешиваем в обычный класс:
86
+ Ничего не мешает подмешать модуль `Petrovich::Extension` в самый обычный
87
+ класс.
75
88
 
76
89
  ```ruby
77
90
  class Person
@@ -96,7 +109,13 @@ class Person
96
109
  end
97
110
  ```
98
111
 
99
- В примерах выше, вы указываете при помощи метода `petrovich` соответствие фамилии, имени и отчества методам или атрибутам класса. После этого, вы легко можете склонять имена, используя следующий синтаксис вызовов:
112
+ При помощи метода `petrovich` указываются методы, представляющие фамилию,
113
+ имя и отчество. В данном примере указано, что метод `name` представляет
114
+ имя, метод `lastname` представляет фамилию, метод `patronymic` представляет
115
+ отчество.
116
+
117
+ После конфигурации Petrovich можно легко выполнять склонение необходимых
118
+ строк.
100
119
 
101
120
  ```ruby
102
121
  user = User.new
@@ -107,8 +126,6 @@ user.my_middlename_dative # => Петровичу
107
126
  user.my_lastname_dative # => Петренко
108
127
  ```
109
128
 
110
- и для второго примера:
111
-
112
129
  ```ruby
113
130
  person = Person.new
114
131
  person.name # => Иван
@@ -117,44 +134,91 @@ person.my_firstname_dative # => Ивану
117
134
  person.my_middlename_dative # => Олеговичу
118
135
  person.my_lastname_dative # => Сафронову
119
136
  ```
120
- Изначальное имя должно быть в именительнои падеже. Вы просто добавляете `_падеж` в конец имени оригинального метода и получаете нужное значение. Вот список суффиксов, которые вы можете добавить к имени оригинального метода, чтобы получить имя в нужном падаже:
121
137
 
122
- * genitive - родительный
123
- * dative - дательный
124
- * accusative - винительный
125
- * instrumentative - творительный
126
- * prepositional - предложный
138
+ Базовое имя должно быть в именительном падеже. Вы просто добавляете
139
+ `_падеж` в конец имени оригинального метода и получаете заданное имя
140
+ в требуемом падеже.
127
141
 
128
- ## Разработчики
142
+ Вот список суффиксов, которые вы можете добавить к имени метода, чтобы
143
+ получить имя в нужном падеже:
129
144
 
130
- * [Андрей Козлов](https://github.com/tanraya) - идея, реализация
131
- * [Дмитрий Усталов](http://eveel.ru) - неоценимая помощь
145
+ * genitive — родительный;
146
+ * dative — дательный;
147
+ * accusative — винительный;
148
+ * instrumental — творительный;
149
+ * prepositional — предложный.
132
150
 
133
- ## Дальнейшее развитие
151
+ ## Оценка точности
134
152
 
135
- Мы планируем и далее улучшать этот проект. Поэтому, нам важен отклик от других разработчиков, использующих этот гем. Вот наши планы:
153
+ Тестирование гема при склонении коллекции фамилий из морфологического
154
+ словаря [АОТ] показало точность около 99%. Оригинальный словарь
155
+ распространяется по лицензии LGPL версии 2.1, однако используется
156
+ только в задаче оценки точности данного гема.
136
157
 
137
- * Тесты на базу фамилий.
138
- * Добавить debug-mode, чтобы видеть, какое именно правило применилось
139
- * Cli-interface, чтобы работать с гемом из коммандной строки
140
- * Веб-интерфейс для проверки имён (ф.и.о) и их логгирования, для улучшения правил распознавания.
141
- * Проверка работы с mongoid и mongo-mapper
158
+ Для оценки точности достаточно выполнить команду `rake evaluate`. После
159
+ выполнения этой команды в поток стандартного вывода будут напечатаны
160
+ результаты оценки с данными в словаре АОТ.
142
161
 
143
- Если вы хотите помочь этому проекту, вы можете реализовать любой план из перечисленных выше. Но прежде свяжитесь с разработчиками, чтобы ваши и наши планы не пересекались.
162
+ ```
163
+ Pr(nominative|male) = 100.0000%
164
+ Pr(genitive|male) = 99.6763%
165
+ Pr(dative|male) = 99.7012%
166
+ Pr(accusative|male) = 99.7261%
167
+ Pr(instrumental|male) = 97.9485%
168
+ Pr(prepositional|male) = 99.6888%
169
+ ```
170
+ ```
171
+ Pr(nominative|female) = 100.0000%
172
+ Pr(genitive|female) = 99.8652%
173
+ Pr(dative|female) = 99.8952%
174
+ Pr(accusative|female) = 99.9251%
175
+ Pr(instrumental|female) = 99.4189%
176
+ Pr(prepositional|female) = 99.8952%
177
+ ```
144
178
 
145
- ## Тестирование
179
+ В настоящий момент наблюдается точность в 99.6275% на основе обработки
180
+ 88314 примеров.
146
181
 
147
- Чтобы запустить тесты, тестирующие фамилии, нужно установить `ENV` переменную:
182
+ [АОТ]: http://seman.svn.sourceforge.net/viewvc/seman/trunk/Docs/Morph_UNIX.txt?revision=HEAD&view=markup
148
183
 
149
- ```
184
+ ## Модульные тесты
185
+
186
+ Чтобы запустить тесты, тестирующие фамилии, нужно установить переменную
187
+ окружения `TEST_SURNAMES`:
188
+
189
+ ```shell
150
190
  TEST_SURNAMES=1 rspec
151
191
  ```
152
192
 
193
+ ## Разработчики
194
+
195
+ * [Андрей Козлов](https://github.com/tanraya) — идея, реализация.
196
+ * [Дмитрий Усталов](http://eveel.ru) — неоценимая помощь.
197
+
198
+ ## Дальнейшее развитие
199
+
200
+ Мы планируем и далее улучшать этот проект. Поэтому нам важен отклик от
201
+ пользователей данного гема. Вот наши планы:
202
+
203
+ * добавить отладочный режим, чтобы видеть, какое именно правило было
204
+ использовано при словообразовании;
205
+ * интерфейс командной строки, чтобы работать с гемом из командной строки;
206
+ * Web-интерфейс для обработки ФИО;
207
+ * проверка совместимости с различными ORM и сторонними библиотеками.
208
+
209
+ Если вы хотите помочь этому проекту, вы можете реализовать любую
210
+ вышеперечисленную идею. Перед этим желательно связаться с нами,
211
+ чтобы мы были в курсе.
212
+
153
213
  ## Содействие
154
214
 
155
- Если вы нашли баги, как программной части, так и в словаре, вы всегда можете форкнуть репозиторий и внести необходимые правки. Ваша помощь не останется незамеченной. Если вы заметили ошибки при склонении падежей имён, фамилий или отчеств, можете написать об этом в issues. Проблема будет сразу же исследована и решена.
215
+ Если вы нашли баги, как программной части, так и в базе правил, то вы всегда
216
+ можете форкнуть репозиторий и внести необходимые изменения. Ваша помощь не
217
+ останется незамеченной! Если вы заметили ошибки при склонении падежей имён,
218
+ фамилий или отчеств, можете написать об этом в Issues на GitHub.
219
+ Проблема будет сразу же исследована и, по возможности, решена.
156
220
 
157
- Не стесняйтесь добавлять улучшения. Как всегда, чтобы помочь, вам нужно:
221
+ Не стесняйтесь добавлять улучшения.
158
222
 
159
223
  1. Fork it
160
224
  2. Create your feature branch (`git checkout -b my-new-feature`)
data/Rakefile CHANGED
@@ -1,9 +1,8 @@
1
1
  #!/usr/bin/env rake
2
- begin
3
- require 'bundler/setup'
4
- rescue LoadError
5
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
- end
2
+ # encoding: utf-8
3
+
4
+ require 'bundler/gem_tasks'
5
+
7
6
  begin
8
7
  require 'rdoc/task'
9
8
  rescue LoadError
@@ -12,7 +11,14 @@ rescue LoadError
12
11
  RDoc::Task = Rake::RDocTask
13
12
  end
14
13
 
15
- # Run tests by default
16
- task :default => :spec
14
+ require 'rspec/core/rake_task'
15
+ RSpec::Core::RakeTask.new(:spec)
16
+
17
+ task :petrovich do
18
+ require 'petrovich'
19
+ end
20
+
21
+ # Run tests and perform evaluation by default
22
+ task :default => [:spec, :evaluate]
17
23
 
18
- Bundler::GemHelper.install_tasks
24
+ Dir.glob('lib/tasks/*.rake').each { |r| import r }
data/lib/petrovich.rb CHANGED
@@ -31,18 +31,18 @@ require 'petrovich/extension'
31
31
  # * +:genitive+ - родительный
32
32
  # * +:dative+ - дательный
33
33
  # * +:accusative+ - винительный
34
- # * +:instrumentative+ - творительный
34
+ # * +:instrumental+ - творительный
35
35
  # * +:prepositional+ - предложный
36
36
  #
37
37
  class Petrovich
38
- CASES = [:nominative, :genitive, :dative, :accusative, :instrumentative, :prepositional]
38
+ CASES = [:nominative, :genitive, :dative, :accusative, :instrumental, :prepositional]
39
39
 
40
- NOMINATIVE = :nominative # именительный
41
- GENITIVE = :genitive # родительный
42
- DATIVE = :dative # дательный
43
- ACCUSATIVE = :accusative # винительный
44
- INSTRUMENTATIVE = :instrumentative # творительный
45
- PREPOSITIONAL = :prepositional # предложный
40
+ NOMINATIVE = :nominative # именительный
41
+ GENITIVE = :genitive # родительный
42
+ DATIVE = :dative # дательный
43
+ ACCUSATIVE = :accusative # винительный
44
+ INSTRUMENTATIVE = :instrumental # творительный
45
+ PREPOSITIONAL = :prepositional # предложный
46
46
 
47
47
  def initialize(gender = nil)
48
48
  @gender = gender.to_s
@@ -0,0 +1,89 @@
1
+ # encoding: utf-8
2
+
3
+ require 'csv'
4
+
5
+ CASES = [
6
+ :nominative,
7
+ :genitive,
8
+ :dative,
9
+ :accusative,
10
+ :instrumental,
11
+ :prepositional
12
+ ]
13
+
14
+ def check!(errors, correct, total, lemma, gender, gcase, expected)
15
+ inflector = Petrovich.new(gender)
16
+ inflection = begin
17
+ UnicodeUtils.upcase(inflector.lastname(lemma, gcase))
18
+ rescue
19
+ ''
20
+ end
21
+
22
+ total[[gender, gcase]] += 1
23
+
24
+ if inflection == expected
25
+ correct[[gender, gcase]] += 1
26
+ true
27
+ else
28
+ errors << [lemma, expected, inflection, [gender, gcase]]
29
+ inflection
30
+ end
31
+ end
32
+
33
+ desc 'Evaluate the inflector on surnames'
34
+ task :evaluate => :petrovich do
35
+ filename = File.expand_path('../../../spec/data/surnames.tsv', __FILE__)
36
+ errors_filename = ENV['errors'] || 'errors.tsv'
37
+
38
+ correct, total = Hash.new(0), Hash.new(0)
39
+
40
+ puts 'I will evaluate the inflector on "%s" ' \
41
+ 'and store errors to "%s".' % [filename, errors_filename]
42
+
43
+ CSV.open(errors_filename, 'w', col_sep: "\t") do |errors|
44
+ errors << %w(lemma expected actual params)
45
+
46
+ CSV.open(filename, col_sep: "\t", headers: true).each do |row|
47
+ word = row['word'].force_encoding('UTF-8')
48
+ lemma = row['lemma'].force_encoding('UTF-8')
49
+
50
+ grammemes = if row['grammemes']
51
+ row['grammemes'].force_encoding('UTF-8').split(',')
52
+ else
53
+ []
54
+ end
55
+
56
+ gender = grammemes.include?('мр') ? :male : :female
57
+
58
+ if grammemes.include? '0'
59
+ # some words are aptotic so we have to ensure that
60
+ CASES.each do |gcase|
61
+ check! errors, correct, total, lemma, gender, gcase, word
62
+ end
63
+ elsif grammemes.include? 'им'
64
+ check! errors, correct, total, lemma, gender, :nominative, word
65
+ elsif grammemes.include? 'рд'
66
+ check! errors, correct, total, lemma, gender, :genitive, word
67
+ elsif grammemes.include? 'дт'
68
+ check! errors, correct, total, lemma, gender, :dative, word
69
+ elsif grammemes.include? 'вн'
70
+ check! errors, correct, total, lemma, gender, :accusative, word
71
+ elsif grammemes.include? 'тв'
72
+ # actually, it's called the instrumetal case
73
+ check! errors, correct, total, lemma, gender, :instrumental, word
74
+ elsif grammemes.include? 'пр'
75
+ check! errors, correct, total, lemma, gender, :prepositional, word
76
+ end
77
+ end
78
+ end
79
+
80
+ total.each do |(gender, gcase), correct_count|
81
+ precision = correct[[gender, gcase]] / correct_count.to_f * 100
82
+ puts "\tPr(%s|%s) = %.4f%%" % [gcase, gender, precision]
83
+ end
84
+
85
+ correct_size = correct.values.inject(&:+)
86
+ total_size = total.values.inject(&:+)
87
+ puts 'Well, the precision on %d examples is about %.4f%%.' %
88
+ [total_size, (correct_size / total_size.to_f * 100)]
89
+ end
metadata CHANGED
@@ -1,32 +1,33 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: petrovich
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Andrew Kozloff
9
+ - Dmitry Ustalov
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2013-04-29 00:00:00.000000000 Z
13
+ date: 2013-05-13 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: unicode_utils
16
17
  requirement: !ruby/object:Gem::Requirement
17
18
  none: false
18
19
  requirements:
19
- - - '='
20
+ - - ~>
20
21
  - !ruby/object:Gem::Version
21
- version: 1.4.0
22
+ version: '1.4'
22
23
  type: :runtime
23
24
  prerelease: false
24
25
  version_requirements: !ruby/object:Gem::Requirement
25
26
  none: false
26
27
  requirements:
27
- - - '='
28
+ - - ~>
28
29
  - !ruby/object:Gem::Version
29
- version: 1.4.0
30
+ version: '1.4'
30
31
  - !ruby/object:Gem::Dependency
31
32
  name: rspec
32
33
  requirement: !ruby/object:Gem::Requirement
@@ -63,6 +64,7 @@ description: Вы задаёте начальное имя в именитель
63
64
  вам
64
65
  email:
65
66
  - demerest@gmail.com
67
+ - dmitry@eveel.ru
66
68
  executables: []
67
69
  extensions: []
68
70
  extra_rdoc_files: []
@@ -71,6 +73,7 @@ files:
71
73
  - lib/petrovich/rules.rb
72
74
  - lib/petrovich/rules.yml
73
75
  - lib/petrovich.rb
76
+ - lib/tasks/evaluate.rake
74
77
  - MIT-LICENSE
75
78
  - Rakefile
76
79
  - README.md