petrovich 0.0.7 → 0.1.0

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