From 3aa25065939ea3784a364d974c3f9ee2299223d4 Mon Sep 17 00:00:00 2001 From: RA Date: Thu, 23 Jul 2015 19:19:51 +0300 Subject: [PATCH 01/19] =?UTF-8?q?fix=20=D0=BE=D0=BF=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=84=D0=B0=D0=BC=D0=B8?= =?UTF-8?q?=D0=BB=D0=B8=D0=B8=20=D0=BD=D0=B0=20-=D1=83=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D1=81=D0=BA=D0=BB=D0=BE=D0=BD=D1=8F=D0=B5=D0=BC;=20?= =?UTF-8?q?=D0=BD=D0=B5=20=D1=81=D0=BA=D0=BB=D0=BE=D0=BD=D1=8F=D0=B5=D0=BC?= =?UTF-8?q?=20'=D0=B2=D0=B0=D0=BD',=20'=D0=B4=D0=B5';=20=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D1=81=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20'=D1=81=D1=82=D0=B0=D1=80=D1=88=D0=B8=D0=B9',=20?= =?UTF-8?q?'=D0=BC=D0=BB=D0=B0=D0=B4=D1=88=D0=B8=D0=B9';=20=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D1=81=D0=BA=D0=B8=D0=B5=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20-=D0=B2=D0=B8=D1=8F;=20=D0=B8=D1=81=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20'=D0=90=D0=BD?= =?UTF-8?q?=D1=80=D0=B8',=20'=D0=9F=D0=B8=D1=82=D0=B5=D1=80',=20'=D0=9F?= =?UTF-8?q?=D0=B0=D1=83=D0=BB=D1=8C',=20'=D0=9C=D0=B0=D0=BA=D1=81',=20'?= =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81',=20'=D0=A4=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D1=86'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index edcaa7e..4df7584 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -52,7 +52,7 @@ class NCLNameCaseRu extends NCLNameCaseCore * Окончания имен/фамилий, который не склоняются * @var array */ - private $ih = array('их', 'ых', 'ко'); + private $ih = array('их', 'ых', 'ко', 'уа');//Бенуа, Франсуа /** * Список окончаний характерных для фамилий * По шаблону {letter}* где * любой символ кроме тех, что в {exclude} @@ -140,10 +140,16 @@ class NCLNameCaseRu extends NCLNameCaseCore $this->Rule(202); return true; } + elseif ($this->inNames($this->workingWord, array("ван", 'де'))) + { + $this->Rule(203); + $this->makeResultTheSame(); + return true; + } else { $this->wordForms($this->workingWord, array('а', 'у', 'а', 'ом', 'е')); - $this->Rule(203); + $this->Rule(204); return true; } } @@ -473,6 +479,11 @@ class NCLNameCaseRu extends NCLNameCaseCore */ protected function manFirstName() { + if ($this->inNames($this->workingWord, array('Старший', 'Младший'))) + { + $this->wordForms($this->workingWord, array('его', 'ему', 'его', 'им', 'ем'), 2); + return true; + } return $this->RulesChain('man', array(1, 2, 3)); } @@ -592,7 +603,7 @@ class NCLNameCaseRu extends NCLNameCaseCore $woman+=0.15; } - if ($this->in($this->Last(3), array('лия', 'ния', 'сия', 'дра', 'лла', 'кла', 'опа'))) + if ($this->in($this->Last(3), array('лия', 'ния', 'сия', 'дра', 'лла', 'кла', 'опа', 'вия'))) //Ольвия { $woman+=0.5; } @@ -602,7 +613,7 @@ class NCLNameCaseRu extends NCLNameCaseCore $woman+=0.5; } - if ($this->inNames($this->workingWord, 'Вова')) + if ($this->inNames($this->workingWord, array('Вова', 'Анри', 'Питер', 'Пауль'))) { $man += 10; } @@ -714,7 +725,7 @@ class NCLNameCaseRu extends NCLNameCaseCore } /** - * Не бывает имет с такими предпоследними буквами + * Не бывает имен с такими предпоследними буквами */ if ($this->in($this->Last(2, 1), 'жчщъэю')) { @@ -771,7 +782,8 @@ class NCLNameCaseRu extends NCLNameCaseCore } //Исключения - if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин'))) + if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', + 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль'))) { $first+=10; } From 85e245b4dc569937c5fa5164608e455404c3e9dc Mon Sep 17 00:00:00 2001 From: RA Date: Fri, 24 Jul 2015 12:05:06 +0300 Subject: [PATCH 02/19] =?UTF-8?q?feature=20=D0=9E=D0=B1=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BA=D0=B0=20=D0=92=D0=B8=D0=BB=D1=8C=D1=8F=D0=BC?= =?UTF-8?q?=20=D0=A3=D0=B8=D0=BB=D1=8C=D1=8F=D0=BC=20=D0=90=D0=BB=D1=8C?= =?UTF-8?q?=D1=84=D0=BE=D0=BD=D1=81=20=D0=93=D0=B0=D0=BD=D1=81=20=D0=A4?= =?UTF-8?q?=D1=80=D0=B0=20=D0=9C=D0=B0=D1=80=D0=B8=D0=B0,=20=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BD=D0=B0=20-=D0=BF=D0=BE,=20-=D1=8D?= =?UTF-8?q?=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 40 ++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index 4df7584..476b937 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -52,7 +52,7 @@ class NCLNameCaseRu extends NCLNameCaseCore * Окончания имен/фамилий, который не склоняются * @var array */ - private $ih = array('их', 'ых', 'ко', 'уа');//Бенуа, Франсуа + private $ih = array('их', 'ых', 'ко', 'уа'/*Бенуа, Франсуа*/); /** * Список окончаний характерных для фамилий * По шаблону {letter}* где * любой символ кроме тех, что в {exclude} @@ -140,7 +140,7 @@ class NCLNameCaseRu extends NCLNameCaseCore $this->Rule(202); return true; } - elseif ($this->inNames($this->workingWord, array("ван", 'де'))) + elseif ($this->inNames($this->workingWord, 'ван')) { $this->Rule(203); $this->makeResultTheSame(); @@ -167,16 +167,22 @@ class NCLNameCaseRu extends NCLNameCaseCore { if ($this->Last(1) == "а") { - if (!$this->in($this->Last(2, 1), 'кшгх')) + if ($this->inNames($this->workingWord, 'фра')) + { + $this->Rule(301); + $this->makeResultTheSame(); + return true; + } + elseif (!$this->in($this->Last(2, 1), 'кшгх')) { $this->wordForms($this->workingWord, array('ы', 'е', 'у', 'ой', 'е'), 1); - $this->Rule(301); + $this->Rule(302); return true; } else { $this->wordForms($this->workingWord, array('и', 'е', 'у', 'ой', 'е'), 1); - $this->Rule(302); + $this->Rule(303); return true; } } @@ -484,6 +490,12 @@ class NCLNameCaseRu extends NCLNameCaseCore $this->wordForms($this->workingWord, array('его', 'ему', 'его', 'им', 'ем'), 2); return true; } + if ($this->inNames($this->workingWord, array('Мариа'))) + { + //Альфонс Мария Муха + $this->wordForms($this->workingWord, array('и', 'и', 'ю', 'ей', 'ии'), 1); + return true; + } return $this->RulesChain('man', array(1, 2, 3)); } @@ -515,7 +527,7 @@ class NCLNameCaseRu extends NCLNameCaseCore } /** - * Функция склоняет мужский отчества + * Функция склоняет мужские отчества * @return boolean true - если слово было успешно изменено, false - если не получилось этого сделать */ protected function manFatherName() @@ -565,7 +577,7 @@ class NCLNameCaseRu extends NCLNameCaseCore { $man+=0.9; } - if ($this->in($this->Last(2), array('он', 'ов', 'ав', 'ам', 'ол', 'ан', 'рд', 'мп'))) + if ($this->in($this->Last(2), array('он', 'ов', 'ав', 'ам', 'ол', 'ан', 'рд', 'мп', 'по'/*Филиппо*/))) { $man+=0.3; } @@ -593,7 +605,7 @@ class NCLNameCaseRu extends NCLNameCaseCore $man+=0.01; } - if ($this->in($this->Last(3), array('лья', 'вва', 'ока', 'ука', 'ита'))) + if ($this->in($this->Last(3), array('лья', 'вва', 'ока', 'ука', 'ита', 'эль'/*Рафаэль, Габриэль*/))) { $man+=0.2; } @@ -603,7 +615,7 @@ class NCLNameCaseRu extends NCLNameCaseCore $woman+=0.15; } - if ($this->in($this->Last(3), array('лия', 'ния', 'сия', 'дра', 'лла', 'кла', 'опа', 'вия'))) //Ольвия + if ($this->in($this->Last(3), array('лия', 'ния', 'сия', 'дра', 'лла', 'кла', 'опа', 'вия'))) { $woman+=0.5; } @@ -697,6 +709,11 @@ class NCLNameCaseRu extends NCLNameCaseCore $first+=0.5; } + if ($this->in($this->Last(3), array('эль'/*Рафаэль, Габриэль*/))) + { + $first+=0.5; + } + /** * буквы на которые никогда не закнчиваются имена */ @@ -717,7 +734,7 @@ class NCLNameCaseRu extends NCLNameCaseCore } /** - * Сохкращенные ласкательные имена типя Аня Галя и.т.д. + * Сокращенные ласкательные имена типя Аня Галя и.т.д. */ if ($this->Last(1) == 'я' and $this->in($this->Last(3, 1), $this->vowels)) { @@ -783,7 +800,8 @@ class NCLNameCaseRu extends NCLNameCaseCore //Исключения if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', - 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль'))) + 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль', 'Вильям', 'Уильям', + 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо'))) { $first+=10; } From a0b88bee84846f4615d549dcd067a692523ec03c Mon Sep 17 00:00:00 2001 From: RA Date: Mon, 27 Jul 2015 16:32:20 +0300 Subject: [PATCH 03/19] =?UTF-8?q?fix=20=D0=94=D0=B5=D0=B3=D0=B0;=20=D0=BD?= =?UTF-8?q?=D0=B5=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5=20=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D1=81=D0=BA=D0=B8=D0=B5=20=D0=B8=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=B8=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index 476b937..cd498dd 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -167,7 +167,7 @@ class NCLNameCaseRu extends NCLNameCaseCore { if ($this->Last(1) == "а") { - if ($this->inNames($this->workingWord, 'фра')) + if ($this->inNames($this->workingWord, array('фра', 'Дега'))) { $this->Rule(301); $this->makeResultTheSame(); @@ -630,6 +630,11 @@ class NCLNameCaseRu extends NCLNameCaseCore $man += 10; } + if ($this->inNames($this->workingWord, array('Бриджет', 'Элизабет', 'Маргарет', 'Джанет'))) + { + $woman += 10; + } + $word->setGender($man, $woman); } @@ -801,7 +806,8 @@ class NCLNameCaseRu extends NCLNameCaseCore //Исключения if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль', 'Вильям', 'Уильям', - 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо'))) + 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', + 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет'/*женские иностранные*/))) { $first+=10; } From 2a89e0416367cd0b72174bb641bfd917a83934d1 Mon Sep 17 00:00:00 2001 From: RA Date: Tue, 28 Jul 2015 16:22:31 +0300 Subject: [PATCH 04/19] =?UTF-8?q?fix=20=D0=B8=D1=81=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20"=D0=94=D0=B5=D0=BB=D1=8C"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index cd498dd..b331101 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -103,6 +103,13 @@ class NCLNameCaseRu extends NCLNameCaseCore { if ($this->in($this->Last(1), 'ьй')) { + if ($this->inNames($this->workingWord, array('Дель'))) + { + $this->Rule(101); + $this->makeResultTheSame(); + return true; + } + if ($this->Last(2, 1) != "и") { $this->wordForms($this->workingWord, array('я', 'ю', 'я', 'ем', 'е'), 1); From 08261c807d5d73b006f0a099d480ca608b64ebad Mon Sep 17 00:00:00 2001 From: RA Date: Tue, 28 Jul 2015 16:35:24 +0300 Subject: [PATCH 05/19] =?UTF-8?q?fix=20=D0=90=D0=BD=D0=B4=D1=80=D0=B5?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index b331101..2cf5b09 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -113,13 +113,13 @@ class NCLNameCaseRu extends NCLNameCaseCore if ($this->Last(2, 1) != "и") { $this->wordForms($this->workingWord, array('я', 'ю', 'я', 'ем', 'е'), 1); - $this->Rule(101); + $this->Rule(102); return true; } else { $this->wordForms($this->workingWord, array('я', 'ю', 'я', 'ем', 'и'), 1); - $this->Rule(102); + $this->Rule(103); return true; } } @@ -174,7 +174,7 @@ class NCLNameCaseRu extends NCLNameCaseCore { if ($this->Last(1) == "а") { - if ($this->inNames($this->workingWord, array('фра', 'Дега'))) + if ($this->inNames($this->workingWord, array('фра', 'Дега', 'Андреа'))) { $this->Rule(301); $this->makeResultTheSame(); @@ -612,7 +612,7 @@ class NCLNameCaseRu extends NCLNameCaseCore $man+=0.01; } - if ($this->in($this->Last(3), array('лья', 'вва', 'ока', 'ука', 'ита', 'эль'/*Рафаэль, Габриэль*/))) + if ($this->in($this->Last(3), array('лья', 'вва', 'ока', 'ука', 'ита', 'эль'/*Рафаэль, Габриэль*/, 'реа'/*Андреа*/))) { $man+=0.2; } @@ -813,7 +813,7 @@ class NCLNameCaseRu extends NCLNameCaseCore //Исключения if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль', 'Вильям', 'Уильям', - 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', + 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет'/*женские иностранные*/))) { $first+=10; From b95e99f86089c0f5f760a71baa397c8e08ba1df4 Mon Sep 17 00:00:00 2001 From: RA Date: Fri, 31 Jul 2015 22:19:21 +0300 Subject: [PATCH 06/19] =?UTF-8?q?feature=20namecase.=20=D0=A1=D0=BA=D0=BB?= =?UTF-8?q?=D0=BE=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=B2=D0=BD=D1=8B=D1=85=20=D1=84=D0=B0=D0=BC=D0=B8=D0=BB?= =?UTF-8?q?=D0=B8=D0=B9=20(=20=D0=A1=D0=B0=D0=BB=D1=82=D1=8B=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2-=D0=A9=D0=B5=D0=B4=D1=80=D0=B8=D0=BD=20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCL/NCLNameCaseCore.php | 2255 ++++++++++++++++--------------- Library/NCL/NCLNameCaseWord.php | 568 ++++---- 2 files changed, 1441 insertions(+), 1382 deletions(-) diff --git a/Library/NCL/NCLNameCaseCore.php b/Library/NCL/NCLNameCaseCore.php index 56666a1..3334305 100644 --- a/Library/NCL/NCLNameCaseCore.php +++ b/Library/NCL/NCLNameCaseCore.php @@ -5,11 +5,11 @@ * @package NameCaseLib */ /** - * + * */ if (!defined('NCL_DIR')) { - define('NCL_DIR', dirname(__FILE__)); + define('NCL_DIR', dirname(__FILE__)); } require_once NCL_DIR . '/NCL.php'; @@ -18,10 +18,10 @@ require_once NCL_DIR . '/NCLNameCaseWord.php'; /** * NCL NameCase Core - * + * * Набор основных функций, который позволяют сделать интерфейс слонения русского и украниского языка * абсолютно одинаковым. Содержит все функции для внешнего взаимодействия с библиотекой. - * + * * @author Андрей Чайка * @version 0.4.1 * @package NameCaseLib @@ -29,1108 +29,1151 @@ require_once NCL_DIR . '/NCLNameCaseWord.php'; class NCLNameCaseCore extends NCL { - /** - * Версия библиотеки - * @var string - */ - protected $version = '0.4.1'; - /** - * Версия языкового файла - * @var string - */ - protected $languageBuild = '0'; - /** - * Готовность системы: - * - Все слова идентифицированы (известо к какой части ФИО относится слово) - * - У всех слов определен пол - * Если все сделано стоит флаг true, при добавлении нового слова флаг сбрасывается на false - * @var bool - */ - private $ready = false; - /** - * Если все текущие слова было просклонены и в каждом слове уже есть результат склонения, - * тогда true. Если было добавлено новое слово флаг збрасывается на false - * @var bool - */ - private $finished = false; - /** - * Массив содержит елементы типа NCLNameCaseWord. Это все слова которые нужно обработать и просклонять - * @var array - */ - private $words = array(); - /** - * Переменная, в которую заносится слово с которым сейчас идет работа - * @var string - */ - protected $workingWord = ''; - /** - * Метод Last() вырезает подстроки разной длины. Посколько одинаковых вызовов бывает несколько, - * то все результаты выполнения кешируются в этом массиве. - * @var array - */ - protected $workindLastCache = array(); - /** - * Номер последнего использованого правила, устанавливается методом Rule() - * @var int - */ - private $lastRule = 0; - /** - * Массив содержит результат склонения слова - слово во всех падежах - * @var array - */ - protected $lastResult = array(); - /** - * Массив содержит информацию о том какие слова из массива $this->words относятся к - * фамилии, какие к отчеству а какие к имени. Массив нужен потому, что при добавлении слов мы не - * всегда знаем какая часть ФИО сейчас, поэтому после идентификации всех слов генерируется массив - * индексов для быстрого поиска в дальнейшем. - * @var array - */ - private $index = array(); - - /** - * Метод очищает результаты последнего склонения слова. Нужен при склонении нескольких слов. - */ - private function reset() - { - $this->lastRule = 0; - $this->lastResult = array(); - } - - /** - * Сбрасывает все информацию на начальную. Очищает все слова добавленые в систему. - * После выполнения система готова работать с начала. - * @return NCLNameCaseCore - */ - public function fullReset() - { - $this->words = array(); - $this->index = array('N' => array(), 'F' => array(), 'S' => array()); - $this->reset(); - $this->notReady(); - return $this; - } - - /** - * Устанавливает флаги о том, что система не готово и слова еще не были просклонены - */ - private function notReady() - { - $this->ready = false; - $this->finished = false; - } - - /** - * Устанавливает номер последнего правила - * @param int $index номер правила которое нужно установить - */ - protected function Rule($index) - { - $this->lastRule = $index; - } - - /** - * Устанавливает слово текущим для работы системы. Очищает кеш слова. - * @param string $word слово, которое нужно установить - */ - protected function setWorkingWord($word) - { - //Сбрасываем настройки - $this->reset(); - //Ставим слово - $this->workingWord = $word; - //Чистим кеш - $this->workindLastCache = array(); - } - - /** - * Если не нужно склонять слово, делает результат таким же как и именительный падеж - */ - protected function makeResultTheSame() - { - $this->lastResult = array_fill(0, $this->CaseCount, $this->workingWord); - } - - /** - * Если $stopAfter = 0, тогда вырезает $length последних букв с текущего слова ($this->workingWord) - * Если нет, тогда вырезает $stopAfter букв начиная от $length с конца - * @param int $length количество букв с конца - * @param int $stopAfter количество букв которые нужно вырезать (0 - все) - * @return string требуемая подстрока - */ - protected function Last($length=1, $stopAfter=0) - { - //Сколько букв нужно вырезать все или только часть - if (!$stopAfter) - { - $cut = $length; - } - else - { - $cut = $stopAfter; - } - - //Проверяем кеш - if (!isset($this->workindLastCache[$length][$stopAfter])) - { - $this->workindLastCache[$length][$stopAfter] = NCLStr::substr($this->workingWord, -$length, $cut); - } - return $this->workindLastCache[$length][$stopAfter]; - } - - /** - * Над текущим словом ($this->workingWord) выполняются правила в порядке указаном в $rulesArray. - * $gender служит для указания какие правила использовать мужские ('man') или женские ('woman') - * @param string $gender - префикс мужских/женских правил - * @param array $rulesArray - массив, порядок выполнения правил - * @return boolean если правило было задествовано, тогда true, если нет - тогда false - */ - protected function RulesChain($gender, $rulesArray) - { - foreach ($rulesArray as $ruleID) - { - $ruleMethod = $gender . 'Rule' . $ruleID; - if ($this->$ruleMethod()) - { - return true; - } - } - return false; - } - - /** - * Если $string строка, тогда проверяется входит ли буква $letter в строку $string - * Если $string массив, тогда проверяется входит ли строка $letter в массив $string - * @param string $letter буква или строка, которую нужно искать - * @param mixed $string строка или массив, в котором нужно искать - * @return bool true если искомое значение найдено - */ - protected function in($letter, $string) - { - //Если второй параметр массив - if (is_array($string)) - { - return in_array($letter, $string); - } - else - { - if (!$letter or NCLStr::strpos($string, $letter) === false) - { - return false; - } - else - { - return true; - } - } - } - - /** - * Функция проверяет, входит ли имя $nameNeedle в перечень имен $names. - * @param string $nameNeedle - имя которое нужно найти - * @param array $names - перечень имен в котором нужно найти имя - */ - protected function inNames($nameNeedle, $names) - { - if (!is_array($names)) - { - $names = array($names); - } - - foreach ($names as $name) - { - if (NCLStr::strtolower($nameNeedle) == NCLStr::strtolower($name)) - { - return true; - } - } - return false; - } - - /** - * Склоняет слово $word, удаляя из него $replaceLast последних букв - * и добавляя в каждый падеж окончание из массива $endings. - * @param string $word слово, к которому нужно добавить окончания - * @param array $endings массив окончаний - * @param int $replaceLast сколько последних букв нужно убрать с начального слова - */ - protected function wordForms($word, $endings, $replaceLast=0) - { - //Создаем массив с именительный падежом - $result = array($this->workingWord); - //Убираем в окончание лишние буквы - $word = NCLStr::substr($word, 0, NCLStr::strlen($word) - $replaceLast); - - //Добавляем окончания - for ($padegIndex = 1; $padegIndex < $this->CaseCount; $padegIndex++) - { - $result[$padegIndex] = $word . $endings[$padegIndex - 1]; - } - - $this->lastResult = $result; - } - - /** - * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord - * со словом $firstname и пометкой, что это имя - * @param string $firstname имя - * @return NCLNameCaseCore - */ - public function setFirstName($firstname="") - { - if ($firstname) - { - $index = count($this->words); - $this->words[$index] = new NCLNameCaseWord($firstname); - $this->words[$index]->setNamePart('N'); - $this->notReady(); - } - return $this; - } - - /** - * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord - * со словом $secondname и пометкой, что это фамилия - * @param string $secondname фамилия - * @return NCLNameCaseCore - */ - public function setSecondName($secondname="") - { - if ($secondname) - { - $index = count($this->words); - $this->words[$index] = new NCLNameCaseWord($secondname); - $this->words[$index]->setNamePart('S'); - $this->notReady(); - } - return $this; - } - - /** - * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord - * со словом $fathername и пометкой, что это отчество - * @param string $fathername отчество - * @return NCLNameCaseCore - */ - public function setFatherName($fathername="") - { - if ($fathername) - { - $index = count($this->words); - $this->words[$index] = new NCLNameCaseWord($fathername); - $this->words[$index]->setNamePart('F'); - $this->notReady(); - } - return $this; - } - - /** - * Всем словам устанавливается пол, который может иметь следующие значения - * - 0 - не определено - * - NCL::$MAN - мужчина - * - NCL::$WOMAN - женщина - * @param int $gender пол, который нужно установить - * @return NCLNameCaseCore - */ - public function setGender($gender=0) - { - foreach ($this->words as $word) - { - $word->setTrueGender($gender); - } - return $this; - } - - /** - * В система заносится сразу фамилия, имя, отчество - * @param string $secondName фамилия - * @param string $firstName имя - * @param string $fatherName отчество - * @return NCLNameCaseCore - */ - public function setFullName($secondName="", $firstName="", $fatherName="") - { - $this->setFirstName($firstName); - $this->setSecondName($secondName); - $this->setFatherName($fatherName); - return $this; - } - - /** - * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord - * со словом $firstname и пометкой, что это имя - * @param string $firstname имя - * @return NCLNameCaseCore - */ - public function setName($firstname="") - { - return $this->setFirstName($firstname); - } - - /** - * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord - * со словом $secondname и пометкой, что это фамилия - * @param string $secondname фамилия - * @return NCLNameCaseCore - */ - public function setLastName($secondname="") - { - return $this->setSecondName($secondname); - } - - /** - * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord - * со словом $secondname и пометкой, что это фамилия - * @param string $secondname фамилия - * @return NCLNameCaseCore - */ - public function setSirName($secondname="") - { - return $this->setSecondName($secondname); - } - - /** - * Если слово $word не идентифицировано, тогда определяется это имя, фамилия или отчество - * @param NCLNameCaseWord $word слово которое нужно идентифицировать - */ - private function prepareNamePart(NCLNameCaseWord $word) - { - if (!$word->getNamePart()) - { - $this->detectNamePart($word); - } - } - - /** - * Проверяет все ли слова идентифицированы, если нет тогда для каждого определяется это имя, фамилия или отчество - */ - private function prepareAllNameParts() - { - foreach ($this->words as $word) - { - $this->prepareNamePart($word); - } - } - - /** - * Определяет пол для слова $word - * @param NCLNameCaseWord $word слово для которого нужно определить пол - */ - private function prepareGender(NCLNameCaseWord $word) - { - if (!$word->isGenderSolved()) - { - $namePart = $word->getNamePart(); - switch ($namePart) - { - case 'N': $this->GenderByFirstName($word); - break; - case 'F': $this->GenderByFatherName($word); - break; - case 'S': $this->GenderBySecondName($word); - break; - } - } - } - - /** - * Для всех слов проверяет определен ли пол, если нет - определяет его - * После этого расчитывает пол для всех слов и устанавливает такой пол всем словам - * @return bool был ли определен пол - */ - private function solveGender() - { - //Ищем, может гдето пол уже установлен - foreach ($this->words as $word) - { - if ($word->isGenderSolved()) - { - $this->setGender($word->gender()); - return true; - } - } - - //Если нет тогда определяем у каждого слова и потом сумируем - $man = 0; - $woman = 0; - - foreach ($this->words as $word) - { - $this->prepareGender($word); - $gender = $word->getGender(); - $man+=$gender[NCL::$MAN]; - $woman+=$gender[NCL::$WOMAN]; - } - - if ($man > $woman) - { - $this->setGender(NCL::$MAN); - } - else - { - $this->setGender(NCL::$WOMAN); - } - - return true; - } - - /** - * Генерируется массив, который содержит информацию о том какие слова из массива $this->words относятся к - * фамилии, какие к отчеству а какие к имени. Массив нужен потому, что при добавлении слов мы не - * всегда знаем какая часть ФИО сейчас, поэтому после идентификации всех слов генерируется массив - * индексов для быстрого поиска в дальнейшем. - */ - private function generateIndex() - { - $this->index = array('N' => array(), 'S' => array(), 'F' => array()); - foreach ($this->words as $index => $word) - { - $namepart = $word->getNamePart(); - $this->index[$namepart][] = $index; - } - } - - /** - * Выполнет все необходимые подготовления для склонения. - * Все слова идентфицируются. Определяется пол. - * Обновляется индекс. - */ - private function prepareEverything() - { - if (!$this->ready) - { - $this->prepareAllNameParts(); - $this->solveGender(); - $this->generateIndex(); - $this->ready = true; - } - } - - /** - * По указаным словам определяется пол человека: - * - 0 - не определено - * - NCL::$MAN - мужчина - * - NCL::$WOMAN - женщина - * @return int текущий пол человека - */ - public function genderAutoDetect() - { - $this->prepareEverything(); - if (isset($this->words[0])) - { - return $this->words[0]->gender(); - } - return false; - } - - /** - * Разбивает строку $fullname на слова и возвращает формат в котором записано имя - * Формат: - * - S - Фамилия - * - N - Имя - * - F - Отчество - * @param string $fullname строка, для которой необходимо определить формат - * @return array формат в котором записано имя массив типа $this->words - */ - private function splitFullName($fullname) - { - - $fullname = trim($fullname); - $list = explode(' ', $fullname); - - foreach ($list as $word) - { - $this->words[] = new NCLNameCaseWord($word); - } - - $this->prepareEverything(); - $formatArr = array(); - - foreach ($this->words as $word) - { - $formatArr[] = $word->getNamePart(); - } - - return $this->words; - } - - /** - * Разбивает строку $fullname на слова и возвращает формат в котором записано имя - * Формат: - * - S - Фамилия - * - N - Имя - * - F - Отчество - * @param string $fullname строка, для которой необходимо определить формат - * @return string формат в котором записано имя - */ - public function getFullNameFormat($fullname) - { - $this->fullReset(); - $words = $this->splitFullName($fullname); - $format = ''; - foreach ($words as $word) - { - $format .= $word->getNamePart() . ' '; - } - return $format; - } - - /** - * Склоняет слово $word по нужным правилам в зависимости от пола и типа слова - * @param NCLNameCaseWord $word слово, которое нужно просклонять - */ - private function WordCase(NCLNameCaseWord $word) - { - $gender = ($word->gender() == NCL::$MAN ? 'man' : 'woman'); - - $namepart = ''; - - switch ($word->getNamePart()) - { - case 'F': $namepart = 'Father'; - break; - case 'N': $namepart = 'First'; - break; - case 'S': $namepart = 'Second'; - break; - } - - $method = $gender . $namepart . 'Name'; - - $this->setWorkingWord($word->getWord()); - - if ($this->$method()) - { - $word->setNameCases($this->lastResult); - $word->setRule($this->lastRule); - } - else - { - $word->setNameCases(array_fill(0, $this->CaseCount, $word->getWord())); - $word->setRule(-1); - } - } - - /** - * Производит склонение всех слов, который хранятся в массиве $this->words - */ - private function AllWordCases() - { - if (!$this->finished) - { - $this->prepareEverything(); - - foreach ($this->words as $word) - { - $this->WordCase($word); - } - - $this->finished = true; - } - } - - /** - * Если указан номер падежа $number, тогда возвращается строка с таким номером падежа, - * если нет, тогда возвращается массив со всеми падежами текущего слова. - * @param NCLNameCaseWord $word слово для котрого нужно вернуть падеж - * @param int $number номер падежа, который нужно вернуть - * @return mixed массив или строка с нужным падежом - */ - private function getWordCase(NCLNameCaseWord $word, $number=null) - { - $cases = $word->getNameCases(); - if (is_null($number) or $number < 0 or $number > ($this->CaseCount - 1)) - { - return $cases; - } - else - { - return $cases[$number]; - } - } - - /** - * Если нужно было просклонять несколько слов, то их необходимо собрать в одну строку. - * Эта функция собирает все слова указаные в $indexArray в одну строку. - * @param array $indexArray индексы слов, которые необходимо собрать вместе - * @param int $number номер падежа - * @return mixed либо массив со всеми падежами, либо строка с одним падежом - */ - private function getCasesConnected($indexArray, $number=null) - { - $readyArr = array(); - foreach ($indexArray as $index) - { - $readyArr[] = $this->getWordCase($this->words[$index], $number); - } - - $all = count($readyArr); - if ($all) - { - if (is_array($readyArr[0])) - { - //Масив нужно скелить каждый падеж - $resultArr = array(); - for ($case = 0; $case < $this->CaseCount; $case++) - { - $tmp = array(); - for ($i = 0; $i < $all; $i++) - { - $tmp[] = $readyArr[$i][$case]; - } - $resultArr[$case] = implode(' ', $tmp); - } - return $resultArr; - } - else - { - return implode(' ', $readyArr); - } - } - return ''; - } - - /** - * Функция ставит имя в нужный падеж. - * - * Если указан номер падежа $number, тогда возвращается строка с таким номером падежа, - * если нет, тогда возвращается массив со всеми падежами текущего слова. - * @param int $number номер падежа - * @return mixed массив или строка с нужным падежом - */ - public function getFirstNameCase($number=null) - { - $this->AllWordCases(); - - return $this->getCasesConnected($this->index['N'], $number); - } - - /** - * Функция ставит фамилию в нужный падеж. - * - * Если указан номер падежа $number, тогда возвращается строка с таким номером падежа, - * если нет, тогда возвращается массив со всеми падежами текущего слова. - * @param int $number номер падежа - * @return mixed массив или строка с нужным падежом - */ - public function getSecondNameCase($number=null) - { - $this->AllWordCases(); - - return $this->getCasesConnected($this->index['S'], $number); - } - - /** - * Функция ставит отчество в нужный падеж. - * - * Если указан номер падежа $number, тогда возвращается строка с таким номером падежа, - * если нет, тогда возвращается массив со всеми падежами текущего слова. - * @param int $number номер падежа - * @return mixed массив или строка с нужным падежом - */ - public function getFatherNameCase($number=null) - { - $this->AllWordCases(); - - return $this->getCasesConnected($this->index['F'], $number); - } - - /** - * Функция ставит имя $firstName в нужный падеж $CaseNumber по правилам пола $gender. - * - * Если указан номер падежа $CaseNumber, тогда возвращается строка с таким номером падежа, - * если нет, тогда возвращается массив со всеми падежами текущего слова. - * @param string $firstName имя, которое нужно просклонять - * @param int $CaseNumber номер падежа - * @param int $gender пол, который нужно использовать - * @return mixed массив или строка с нужным падежом - */ - public function qFirstName($firstName, $CaseNumber=null, $gender=0) - { - $this->fullReset(); - $this->setFirstName($firstName); - if ($gender) - { - $this->setGender($gender); - } - return $this->getFirstNameCase($CaseNumber); - } - - /** - * Функция ставит фамилию $secondName в нужный падеж $CaseNumber по правилам пола $gender. - * - * Если указан номер падежа $CaseNumber, тогда возвращается строка с таким номером падежа, - * если нет, тогда возвращается массив со всеми падежами текущего слова. - * @param string $secondName фамилия, которую нужно просклонять - * @param int $CaseNumber номер падежа - * @param int $gender пол, который нужно использовать - * @return mixed массив или строка с нужным падежом - */ - public function qSecondName($secondName, $CaseNumber=null, $gender=0) - { - $this->fullReset(); - $this->setSecondName($secondName); - if ($gender) - { - $this->setGender($gender); - } - - return $this->getSecondNameCase($CaseNumber); - } - - /** - * Функция ставит отчество $fatherName в нужный падеж $CaseNumber по правилам пола $gender. - * - * Если указан номер падежа $CaseNumber, тогда возвращается строка с таким номером падежа, - * если нет, тогда возвращается массив со всеми падежами текущего слова. - * @param string $fatherName отчество, которое нужно просклонять - * @param int $CaseNumber номер падежа - * @param int $gender пол, который нужно использовать - * @return mixed массив или строка с нужным падежом - */ - public function qFatherName($fatherName, $CaseNumber=null, $gender=0) - { - $this->fullReset(); - $this->setFatherName($fatherName); - if ($gender) - { - $this->setGender($gender); - } - return $this->getFatherNameCase($CaseNumber); - } - - /** - * Склоняет текущие слова во все падежи и форматирует слово по шаблону $format - * Формат: - * - S - Фамилия - * - N - Имя - * - F - Отчество - * @param string $format строка формат - * @return array массив со всеми падежами - */ - public function getFormattedArray($format) - { - if (is_array($format)) - { - return $this->getFormattedArrayHard($format); - } - - $length = NCLStr::strlen($format); - $result = array(); - $cases = array(); - $cases['S'] = $this->getCasesConnected($this->index['S']); - $cases['N'] = $this->getCasesConnected($this->index['N']); - $cases['F'] = $this->getCasesConnected($this->index['F']); - - for ($curCase = 0; $curCase < $this->CaseCount; $curCase++) - { - $line = ""; - for ($i = 0; $i < $length; $i++) - { - $symbol = NCLStr::substr($format, $i, 1); - if ($symbol == 'S') - { - $line.=$cases['S'][$curCase]; - } - elseif ($symbol == 'N') - { - $line.=$cases['N'][$curCase]; - } - elseif ($symbol == 'F') - { - $line.=$cases['F'][$curCase]; - } - else - { - $line.=$symbol; - } - } - $result[] = $line; - } - return $result; - } - - /** - * Склоняет текущие слова во все падежи и форматирует слово по шаблону $format - * Формат: - * - S - Фамилия - * - N - Имя - * - F - Отчество - * @param array $format массив с форматом - * @return array массив со всеми падежами - */ - public function getFormattedArrayHard($format) - { - - $result = array(); - $cases = array(); - foreach ($format as $word) - { - $cases[] = $word->getNameCases(); - } - - for ($curCase = 0; $curCase < $this->CaseCount; $curCase++) - { - $line = ""; - foreach ($cases as $value) - { - $line.=$value[$curCase] . ' '; - } - $result[] = trim($line); - } - return $result; - } - - /** - * Склоняет текущие слова в падеж $caseNum и форматирует слово по шаблону $format - * Формат: - * - S - Фамилия - * - N - Имя - * - F - Отчество - * @param array $format массив с форматом - * @return string строка в нужном падеже - */ - public function getFormattedHard($caseNum=0, $format=array()) - { - $result = ""; - foreach ($format as $word) - { - $cases = $word->getNameCases(); - $result.= $cases[$caseNum] . ' '; - } - return trim($result); - } - - /** - * Склоняет текущие слова в падеж $caseNum и форматирует слово по шаблону $format - * Формат: - * - S - Фамилия - * - N - Имя - * - F - Отчество - * @param string $format строка с форматом - * @return string строка в нужном падеже - */ - public function getFormatted($caseNum=0, $format="S N F") - { - $this->AllWordCases(); - //Если не указан падеж используем другую функцию - if (is_null($caseNum) or !$caseNum) - { - return $this->getFormattedArray($format); - } - //Если формат сложный - elseif (is_array($format)) - { - return $this->getFormattedHard($caseNum, $format); - } - else - { - $length = NCLStr::strlen($format); - $result = ""; - for ($i = 0; $i < $length; $i++) - { - $symbol = NCLStr::substr($format, $i, 1); - if ($symbol == 'S') - { - $result.=$this->getSecondNameCase($caseNum); - } - elseif ($symbol == 'N') - { - $result.=$this->getFirstNameCase($caseNum); - } - elseif ($symbol == 'F') - { - $result.=$this->getFatherNameCase($caseNum); - } - else - { - $result.=$symbol; - } - } - return $result; - } - } - - /** - * Склоняет фамилию $secondName, имя $firstName, отчество $fatherName - * в падеж $caseNum по правилам пола $gender и форматирует результат по шаблону $format - * Формат: - * - S - Фамилия - * - N - Имя - * - F - Отчество - * @param string $secondName фамилия - * @param string $firstName имя - * @param string $fatherName отчество - * @param int $gender пол - * @param int $caseNum номер падежа - * @param string $format формат - * @return mixed либо массив со всеми падежами, либо строка - */ - public function qFullName($secondName="", $firstName="", $fatherName="", $gender=0, $caseNum=0, $format="S N F") - { - $this->fullReset(); - $this->setFirstName($firstName); - $this->setSecondName($secondName); - $this->setFatherName($fatherName); - if ($gender) - { - $this->setGender($gender); - } - - return $this->getFormatted($caseNum, $format); - } - - /** - * Склоняет ФИО $fullname в падеж $caseNum по правилам пола $gender. - * Возвращает результат в таком же формате, как он и был. - * @param string $fullname ФИО - * @param int $caseNum номер падежа - * @param int $gender пол человека - * @return mixed либо массив со всеми падежами, либо строка - */ - public function q($fullname, $caseNum=null, $gender=null) - { - $this->fullReset(); - $format = $this->splitFullName($fullname); - if ($gender) - { - $this->setGender($gender); - } - - return $this->getFormatted($caseNum, $format); - } - - /** - * Определяет пол человека по ФИО - * @param string $fullname ФИО - * @return int пол человека - */ - public function genderDetect($fullname) - { - $this->fullReset(); - $this->splitFullName($fullname); - return $this->genderAutoDetect(); - } - - /** - * Возвращает внутренний массив $this->words каждая запись имеет тип NCLNameCaseWord - * @return array Массив всех слов в системе - */ - public function getWordsArray() - { - return $this->words; - } - - /** - * Функция пытается применить цепочку правил для мужских имен - * @return boolean true - если было использовано правило из списка, false - если правило не было найденым - */ - protected function manFirstName() - { - return false; - } - - /** - * Функция пытается применить цепочку правил для женских имен - * @return boolean true - если было использовано правило из списка, false - если правило не было найденым - */ - protected function womanFirstName() - { - return false; - } - - /** - * Функция пытается применить цепочку правил для мужских фамилий - * @return boolean true - если было использовано правило из списка, false - если правило не было найденым - */ - protected function manSecondName() - { - return false; - } - - /** - * Функция пытается применить цепочку правил для женских фамилий - * @return boolean true - если было использовано правило из списка, false - если правило не было найденым - */ - protected function womanSecondName() - { - return false; - } - - /** - * Функция склоняет мужский отчества - * @return boolean true - если слово было успешно изменено, false - если не получилось этого сделать - */ - protected function manFatherName() - { - return false; - } - - /** - * Функция склоняет женские отчества - * @return boolean true - если слово было успешно изменено, false - если не получилось этого сделать - */ - protected function womanFatherName() - { - return false; - } - - /** - * Определение пола по правилам имен - * @param NCLNameCaseWord $word обьект класса слов, для которого нужно определить пол - */ - protected function GenderByFirstName(NCLNameCaseWord $word) - { - - } - - /** - * Определение пола по правилам фамилий - * @param NCLNameCaseWord $word обьект класса слов, для которого нужно определить пол - */ - protected function GenderBySecondName(NCLNameCaseWord $word) - { - - } - - /** - * Определение пола по правилам отчеств - * @param NCLNameCaseWord $word обьект класса слов, для которого нужно определить пол - */ - protected function GenderByFatherName(NCLNameCaseWord $word) - { - - } - - /** - * Идетифицирует слово определяе имя это, или фамилия, или отчество - * - N - имя - * - S - фамилия - * - F - отчество - * @param NCLNameCaseWord $word обьект класса слов, который необходимо идентифицировать - */ - protected function detectNamePart(NCLNameCaseWord $word) - { - - } - - /** - * Возвращает версию библиотеки - * @return string версия библиотеки - */ - public function version() - { - return $this->version; - } - - /** - * Возвращает версию использованого языкового файла - * @return string версия языкового файла - */ - public function languageVersion() - { - return $this->languageBuild; - } + /** + * Версия библиотеки + * @var string + */ + protected $version = '0.4.1'; + /** + * Версия языкового файла + * @var string + */ + protected $languageBuild = '0'; + /** + * Готовность системы: + * - Все слова идентифицированы (известо к какой части ФИО относится слово) + * - У всех слов определен пол + * Если все сделано стоит флаг true, при добавлении нового слова флаг сбрасывается на false + * @var bool + */ + private $ready = false; + /** + * Если все текущие слова было просклонены и в каждом слове уже есть результат склонения, + * тогда true. Если было добавлено новое слово флаг збрасывается на false + * @var bool + */ + private $finished = false; + /** + * Массив содержит елементы типа NCLNameCaseWord. Это все слова которые нужно обработать и просклонять + * @var array + */ + private $words = array(); + /** + * Переменная, в которую заносится слово с которым сейчас идет работа + * @var string + */ + protected $workingWord = ''; + /** + * Метод Last() вырезает подстроки разной длины. Посколько одинаковых вызовов бывает несколько, + * то все результаты выполнения кешируются в этом массиве. + * @var array + */ + protected $workindLastCache = array(); + /** + * Номер последнего использованого правила, устанавливается методом Rule() + * @var int + */ + private $lastRule = 0; + /** + * Массив содержит результат склонения слова - слово во всех падежах + * @var array + */ + protected $lastResult = array(); + /** + * Массив содержит информацию о том какие слова из массива $this->words относятся к + * фамилии, какие к отчеству а какие к имени. Массив нужен потому, что при добавлении слов мы не + * всегда знаем какая часть ФИО сейчас, поэтому после идентификации всех слов генерируется массив + * индексов для быстрого поиска в дальнейшем. + * @var array + */ + private $index = array(); + + /** + * Метод очищает результаты последнего склонения слова. Нужен при склонении нескольких слов. + */ + private function reset() + { + $this->lastRule = 0; + $this->lastResult = array(); + } + + /** + * Сбрасывает все информацию на начальную. Очищает все слова добавленые в систему. + * После выполнения система готова работать с начала. + * @return NCLNameCaseCore + */ + public function fullReset() + { + $this->words = array(); + $this->index = array('N' => array(), 'F' => array(), 'S' => array()); + $this->reset(); + $this->notReady(); + return $this; + } + + /** + * Устанавливает флаги о том, что система не готово и слова еще не были просклонены + */ + private function notReady() + { + $this->ready = false; + $this->finished = false; + } + + /** + * Устанавливает номер последнего правила + * @param int $index номер правила которое нужно установить + */ + protected function Rule($index) + { + $this->lastRule = $index; + } + + /** + * Устанавливает слово текущим для работы системы. Очищает кеш слова. + * @param string $word слово, которое нужно установить + */ + protected function setWorkingWord($word) + { + //Сбрасываем настройки + $this->reset(); + //Ставим слово + $this->workingWord = $word; + //Чистим кеш + $this->workindLastCache = array(); + } + + /** + * Если не нужно склонять слово, делает результат таким же как и именительный падеж + */ + protected function makeResultTheSame() + { + $this->lastResult = array_fill(0, $this->CaseCount, $this->workingWord); + } + + /** + * Если $stopAfter = 0, тогда вырезает $length последних букв с текущего слова ($this->workingWord) + * Если нет, тогда вырезает $stopAfter букв начиная от $length с конца + * @param int $length количество букв с конца + * @param int $stopAfter количество букв которые нужно вырезать (0 - все) + * @return string требуемая подстрока + */ + protected function Last($length=1, $stopAfter=0) + { + //Сколько букв нужно вырезать все или только часть + if (!$stopAfter) + { + $cut = $length; + } + else + { + $cut = $stopAfter; + } + + //Проверяем кеш + if (!isset($this->workindLastCache[$length][$stopAfter])) + { + $this->workindLastCache[$length][$stopAfter] = NCLStr::substr($this->workingWord, -$length, $cut); + } + return $this->workindLastCache[$length][$stopAfter]; + } + + /** + * Над текущим словом ($this->workingWord) выполняются правила в порядке указаном в $rulesArray. + * $gender служит для указания какие правила использовать мужские ('man') или женские ('woman') + * @param string $gender - префикс мужских/женских правил + * @param array $rulesArray - массив, порядок выполнения правил + * @return boolean если правило было задествовано, тогда true, если нет - тогда false + */ + protected function RulesChain($gender, $rulesArray) + { + foreach ($rulesArray as $ruleID) + { + $ruleMethod = $gender . 'Rule' . $ruleID; + if ($this->$ruleMethod()) + { + return true; + } + } + return false; + } + + /** + * Если $string строка, тогда проверяется входит ли буква $letter в строку $string + * Если $string массив, тогда проверяется входит ли строка $letter в массив $string + * @param string $letter буква или строка, которую нужно искать + * @param mixed $string строка или массив, в котором нужно искать + * @return bool true если искомое значение найдено + */ + protected function in($letter, $string) + { + //Если второй параметр массив + if (is_array($string)) + { + return in_array($letter, $string); + } + else + { + if (!$letter or NCLStr::strpos($string, $letter) === false) + { + return false; + } + else + { + return true; + } + } + } + + /** + * Функция проверяет, входит ли имя $nameNeedle в перечень имен $names. + * @param string $nameNeedle - имя которое нужно найти + * @param array $names - перечень имен в котором нужно найти имя + */ + protected function inNames($nameNeedle, $names) + { + if (!is_array($names)) + { + $names = array($names); + } + + foreach ($names as $name) + { + if (NCLStr::strtolower($nameNeedle) == NCLStr::strtolower($name)) + { + return true; + } + } + return false; + } + + /** + * Склоняет слово $word, удаляя из него $replaceLast последних букв + * и добавляя в каждый падеж окончание из массива $endings. + * @param string $word слово, к которому нужно добавить окончания + * @param array $endings массив окончаний + * @param int $replaceLast сколько последних букв нужно убрать с начального слова + */ + protected function wordForms($word, $endings, $replaceLast=0) + { + //Создаем массив с именительный падежом + $result = array($this->workingWord); + //Убираем в окончание лишние буквы + $word = NCLStr::substr($word, 0, NCLStr::strlen($word) - $replaceLast); + + //Добавляем окончания + for ($padegIndex = 1; $padegIndex < $this->CaseCount; $padegIndex++) + { + $result[$padegIndex] = $word . $endings[$padegIndex - 1]; + } + + $this->lastResult = $result; + } + + /** + * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord + * со словом $firstname и пометкой, что это имя + * @param string $firstname имя + * @return NCLNameCaseCore + */ + public function setFirstName($firstname="") + { + if ($firstname) + { + $index = count($this->words); + $this->words[$index] = new NCLNameCaseWord($firstname); + $this->words[$index]->setNamePart('N'); + $this->notReady(); + } + return $this; + } + + /** + * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord + * со словом $secondname и пометкой, что это фамилия + * @param string $secondname фамилия + * @return NCLNameCaseCore + */ + public function setSecondName($secondname="") + { + if ($secondname) + { + $index = count($this->words); + $this->words[$index] = new NCLNameCaseWord($secondname); + $this->words[$index]->setNamePart('S'); + $this->notReady(); + } + return $this; + } + + /** + * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord + * со словом $fathername и пометкой, что это отчество + * @param string $fathername отчество + * @return NCLNameCaseCore + */ + public function setFatherName($fathername="") + { + if ($fathername) + { + $index = count($this->words); + $this->words[$index] = new NCLNameCaseWord($fathername); + $this->words[$index]->setNamePart('F'); + $this->notReady(); + } + return $this; + } + + /** + * Всем словам устанавливается пол, который может иметь следующие значения + * - 0 - не определено + * - NCL::$MAN - мужчина + * - NCL::$WOMAN - женщина + * @param int $gender пол, который нужно установить + * @return NCLNameCaseCore + */ + public function setGender($gender=0) + { + foreach ($this->words as $word) + { + $word->setTrueGender($gender); + } + return $this; + } + + /** + * В система заносится сразу фамилия, имя, отчество + * @param string $secondName фамилия + * @param string $firstName имя + * @param string $fatherName отчество + * @return NCLNameCaseCore + */ + public function setFullName($secondName="", $firstName="", $fatherName="") + { + $this->setFirstName($firstName); + $this->setSecondName($secondName); + $this->setFatherName($fatherName); + return $this; + } + + /** + * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord + * со словом $firstname и пометкой, что это имя + * @param string $firstname имя + * @return NCLNameCaseCore + */ + public function setName($firstname="") + { + return $this->setFirstName($firstname); + } + + /** + * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord + * со словом $secondname и пометкой, что это фамилия + * @param string $secondname фамилия + * @return NCLNameCaseCore + */ + public function setLastName($secondname="") + { + return $this->setSecondName($secondname); + } + + /** + * В массив $this->words добавляется новый об’єкт класса NCLNameCaseWord + * со словом $secondname и пометкой, что это фамилия + * @param string $secondname фамилия + * @return NCLNameCaseCore + */ + public function setSirName($secondname="") + { + return $this->setSecondName($secondname); + } + + /** + * Если слово $word не идентифицировано, тогда определяется это имя, фамилия или отчество + * @param NCLNameCaseWord $word слово которое нужно идентифицировать + */ + private function prepareNamePart(NCLNameCaseWord $word) + { + if (!$word->getNamePart()) + { + $this->detectNamePart($word); + } + } + + /** + * Проверяет все ли слова идентифицированы, если нет тогда для каждого определяется это имя, фамилия или отчество + */ + private function prepareAllNameParts() + { + foreach ($this->words as $word) + { + $this->prepareNamePart($word); + } + } + + /** + * Определяет пол для слова $word + * @param NCLNameCaseWord $word слово для которого нужно определить пол + */ + private function prepareGender(NCLNameCaseWord $word) + { + if (!$word->isGenderSolved()) + { + $namePart = $word->getNamePart(); + switch ($namePart) + { + case 'N': $this->GenderByFirstName($word); + break; + case 'F': $this->GenderByFatherName($word); + break; + case 'S': $this->GenderBySecondName($word); + break; + } + } + } + + /** + * Для всех слов проверяет определен ли пол, если нет - определяет его + * После этого расчитывает пол для всех слов и устанавливает такой пол всем словам + * @return bool был ли определен пол + */ + private function solveGender() + { + //Ищем, может гдето пол уже установлен + foreach ($this->words as $word) + { + if ($word->isGenderSolved()) + { + $this->setGender($word->gender()); + return true; + } + } + + //Если нет тогда определяем у каждого слова и потом сумируем + $man = 0; + $woman = 0; + + foreach ($this->words as $word) + { + $this->prepareGender($word); + $gender = $word->getGender(); + $man+=$gender[NCL::$MAN]; + $woman+=$gender[NCL::$WOMAN]; + } + + if ($man > $woman) + { + $this->setGender(NCL::$MAN); + } + else + { + $this->setGender(NCL::$WOMAN); + } + + return true; + } + + /** + * Генерируется массив, который содержит информацию о том какие слова из массива $this->words относятся к + * фамилии, какие к отчеству а какие к имени. Массив нужен потому, что при добавлении слов мы не + * всегда знаем какая часть ФИО сейчас, поэтому после идентификации всех слов генерируется массив + * индексов для быстрого поиска в дальнейшем. + */ + private function generateIndex() + { + $this->index = array('N' => array(), 'S' => array(), 'F' => array()); + foreach ($this->words as $index => $word) + { + $namepart = $word->getNamePart(); + $this->index[$namepart][] = $index; + } + } + + /** + * Выполнет все необходимые подготовления для склонения. + * Все слова идентфицируются. Определяется пол. + * Обновляется индекс. + */ + private function prepareEverything() + { + if (!$this->ready) + { + $this->prepareAllNameParts(); + $this->solveGender(); + $this->generateIndex(); + $this->ready = true; + } + } + + /** + * По указаным словам определяется пол человека: + * - 0 - не определено + * - NCL::$MAN - мужчина + * - NCL::$WOMAN - женщина + * @return int текущий пол человека + */ + public function genderAutoDetect() + { + $this->prepareEverything(); + if (isset($this->words[0])) + { + return $this->words[0]->gender(); + } + return false; + } + + /** + * Разбивает строку $fullname на слова и возвращает формат в котором записано имя + * Формат: + * - S - Фамилия + * - N - Имя + * - F - Отчество + * @param string $fullname строка, для которой необходимо определить формат + * @return array формат в котором записано имя массив типа $this->words + */ + private function splitFullName($fullname) + { + + $fullname = trim($fullname); + $list = explode(' ', $fullname); + + foreach ($list as $word) + { + $this->words[] = new NCLNameCaseWord($word); + } + + $this->prepareEverything(); + $formatArr = array(); + + foreach ($this->words as $word) + { + $formatArr[] = $word->getNamePart(); + } + + return $this->words; + } + + /** + * Разбивает строку $fullname на слова и возвращает формат в котором записано имя + * Формат: + * - S - Фамилия + * - N - Имя + * - F - Отчество + * @param string $fullname строка, для которой необходимо определить формат + * @return string формат в котором записано имя + */ + public function getFullNameFormat($fullname) + { + $this->fullReset(); + $words = $this->splitFullName($fullname); + $format = ''; + foreach ($words as $word) + { + $format .= $word->getNamePart() . ' '; + } + return $format; + } + + /** + * Склоняет слово $word по нужным правилам в зависимости от пола и типа слова + * @param NCLNameCaseWord $word слово, которое нужно просклонять + */ + private function WordCase(NCLNameCaseWord $word) + { + $gender = ($word->gender() == NCL::$MAN ? 'man' : 'woman'); + + $namepart = ''; + + $name_part_letter=$word->getNamePart(); + switch ($name_part_letter) + { + case 'F': $namepart = 'Father'; + break; + case 'N': $namepart = 'First'; + break; + case 'S': $namepart = 'Second'; + break; + } + + $method = $gender . $namepart . 'Name'; + + //если фамилия из 2х слов через дефис + //http://new.gramota.ru/spravka/buro/search-answer?s=273912 + + //рабоиваем слово с дефисами на части + $tmp=$word->getWordOrig(); + $cur_words=explode('-', $tmp); + $o_cur_words=array(); + + $result=array(); + $last_rule=-1; + + $cnt=count($cur_words); + foreach ($cur_words as $k=>$cur_word){ + $is_norm_rules=true; + $o_ncw=new NCLNameCaseWord($cur_word); + if ( $name_part_letter=='S' && $cnt>1 && $k<$cnt-1 ){ + //если первая часть фамилии тоже фамилия, то склоняем по общим правилам + //иначе не склоняется + $o_nc = new NCLNameCaseRu(); + $o_nc->detectNamePart( $o_ncw ); + $is_norm_rules=( $o_ncw->getNamePart()==$name_part_letter ); + } + + $this->setWorkingWord($cur_word); + + if ($is_norm_rules && $this->$method()) + { + //склоняется + $result_tmp=$this->lastResult; + $last_rule=$this->lastRule; + } + else + { + //не склоняется. Заполняем что есть + $result_tmp=array_fill(0, $this->CaseCount, $cur_word); + $last_rule=-1; + } + + $o_ncw->setNameCases($result_tmp); + $o_cur_words[]=$o_ncw; + } + + //объединение пачку частей слова в одно слово по каждому падежу + foreach ($o_cur_words as $o_ncw){ + $namecases=$o_ncw->getNameCases(); + foreach ($namecases as $k=>$namecase){ + if ( key_exists($k, $result) ) $result[$k]=$result[$k].'-'.$namecase; + else $result[$k]=$namecase; + } + } + + //устанавливаем падежи для целого слова + $word->setNameCases($result, false); + $word->setRule($last_rule); + } + + /** + * Производит склонение всех слов, который хранятся в массиве $this->words + */ + private function AllWordCases() + { + if (!$this->finished) + { + $this->prepareEverything(); + + foreach ($this->words as $word) + { + $this->WordCase($word); + } + + $this->finished = true; + } + } + + /** + * Если указан номер падежа $number, тогда возвращается строка с таким номером падежа, + * если нет, тогда возвращается массив со всеми падежами текущего слова. + * @param NCLNameCaseWord $word слово для котрого нужно вернуть падеж + * @param int $number номер падежа, который нужно вернуть + * @return mixed массив или строка с нужным падежом + */ + private function getWordCase(NCLNameCaseWord $word, $number=null) + { + $cases = $word->getNameCases(); + if (is_null($number) or $number < 0 or $number > ($this->CaseCount - 1)) + { + return $cases; + } + else + { + return $cases[$number]; + } + } + + /** + * Если нужно было просклонять несколько слов, то их необходимо собрать в одну строку. + * Эта функция собирает все слова указаные в $indexArray в одну строку. + * @param array $indexArray индексы слов, которые необходимо собрать вместе + * @param int $number номер падежа + * @return mixed либо массив со всеми падежами, либо строка с одним падежом + */ + private function getCasesConnected($indexArray, $number=null) + { + $readyArr = array(); + foreach ($indexArray as $index) + { + $readyArr[] = $this->getWordCase($this->words[$index], $number); + } + + $all = count($readyArr); + if ($all) + { + if (is_array($readyArr[0])) + { + //Масив нужно скелить каждый падеж + $resultArr = array(); + for ($case = 0; $case < $this->CaseCount; $case++) + { + $tmp = array(); + for ($i = 0; $i < $all; $i++) + { + $tmp[] = $readyArr[$i][$case]; + } + $resultArr[$case] = implode(' ', $tmp); + } + return $resultArr; + } + else + { + return implode(' ', $readyArr); + } + } + return ''; + } + + /** + * Функция ставит имя в нужный падеж. + * + * Если указан номер падежа $number, тогда возвращается строка с таким номером падежа, + * если нет, тогда возвращается массив со всеми падежами текущего слова. + * @param int $number номер падежа + * @return mixed массив или строка с нужным падежом + */ + public function getFirstNameCase($number=null) + { + $this->AllWordCases(); + + return $this->getCasesConnected($this->index['N'], $number); + } + + /** + * Функция ставит фамилию в нужный падеж. + * + * Если указан номер падежа $number, тогда возвращается строка с таким номером падежа, + * если нет, тогда возвращается массив со всеми падежами текущего слова. + * @param int $number номер падежа + * @return mixed массив или строка с нужным падежом + */ + public function getSecondNameCase($number=null) + { + $this->AllWordCases(); + + return $this->getCasesConnected($this->index['S'], $number); + } + + /** + * Функция ставит отчество в нужный падеж. + * + * Если указан номер падежа $number, тогда возвращается строка с таким номером падежа, + * если нет, тогда возвращается массив со всеми падежами текущего слова. + * @param int $number номер падежа + * @return mixed массив или строка с нужным падежом + */ + public function getFatherNameCase($number=null) + { + $this->AllWordCases(); + + return $this->getCasesConnected($this->index['F'], $number); + } + + /** + * Функция ставит имя $firstName в нужный падеж $CaseNumber по правилам пола $gender. + * + * Если указан номер падежа $CaseNumber, тогда возвращается строка с таким номером падежа, + * если нет, тогда возвращается массив со всеми падежами текущего слова. + * @param string $firstName имя, которое нужно просклонять + * @param int $CaseNumber номер падежа + * @param int $gender пол, который нужно использовать + * @return mixed массив или строка с нужным падежом + */ + public function qFirstName($firstName, $CaseNumber=null, $gender=0) + { + $this->fullReset(); + $this->setFirstName($firstName); + if ($gender) + { + $this->setGender($gender); + } + return $this->getFirstNameCase($CaseNumber); + } + + /** + * Функция ставит фамилию $secondName в нужный падеж $CaseNumber по правилам пола $gender. + * + * Если указан номер падежа $CaseNumber, тогда возвращается строка с таким номером падежа, + * если нет, тогда возвращается массив со всеми падежами текущего слова. + * @param string $secondName фамилия, которую нужно просклонять + * @param int $CaseNumber номер падежа + * @param int $gender пол, который нужно использовать + * @return mixed массив или строка с нужным падежом + */ + public function qSecondName($secondName, $CaseNumber=null, $gender=0) + { + $this->fullReset(); + $this->setSecondName($secondName); + if ($gender) + { + $this->setGender($gender); + } + + return $this->getSecondNameCase($CaseNumber); + } + + /** + * Функция ставит отчество $fatherName в нужный падеж $CaseNumber по правилам пола $gender. + * + * Если указан номер падежа $CaseNumber, тогда возвращается строка с таким номером падежа, + * если нет, тогда возвращается массив со всеми падежами текущего слова. + * @param string $fatherName отчество, которое нужно просклонять + * @param int $CaseNumber номер падежа + * @param int $gender пол, который нужно использовать + * @return mixed массив или строка с нужным падежом + */ + public function qFatherName($fatherName, $CaseNumber=null, $gender=0) + { + $this->fullReset(); + $this->setFatherName($fatherName); + if ($gender) + { + $this->setGender($gender); + } + return $this->getFatherNameCase($CaseNumber); + } + + /** + * Склоняет текущие слова во все падежи и форматирует слово по шаблону $format + * Формат: + * - S - Фамилия + * - N - Имя + * - F - Отчество + * @param string $format строка формат + * @return array массив со всеми падежами + */ + public function getFormattedArray($format) + { + if (is_array($format)) + { + return $this->getFormattedArrayHard($format); + } + + $length = NCLStr::strlen($format); + $result = array(); + $cases = array(); + $cases['S'] = $this->getCasesConnected($this->index['S']); + $cases['N'] = $this->getCasesConnected($this->index['N']); + $cases['F'] = $this->getCasesConnected($this->index['F']); + + for ($curCase = 0; $curCase < $this->CaseCount; $curCase++) + { + $line = ""; + for ($i = 0; $i < $length; $i++) + { + $symbol = NCLStr::substr($format, $i, 1); + if ($symbol == 'S') + { + $line.=$cases['S'][$curCase]; + } + elseif ($symbol == 'N') + { + $line.=$cases['N'][$curCase]; + } + elseif ($symbol == 'F') + { + $line.=$cases['F'][$curCase]; + } + else + { + $line.=$symbol; + } + } + $result[] = $line; + } + return $result; + } + + /** + * Склоняет текущие слова во все падежи и форматирует слово по шаблону $format + * Формат: + * - S - Фамилия + * - N - Имя + * - F - Отчество + * @param array $format массив с форматом + * @return array массив со всеми падежами + */ + public function getFormattedArrayHard($format) + { + + $result = array(); + $cases = array(); + foreach ($format as $word) + { + $cases[] = $word->getNameCases(); + } + + for ($curCase = 0; $curCase < $this->CaseCount; $curCase++) + { + $line = ""; + foreach ($cases as $value) + { + $line.=$value[$curCase] . ' '; + } + $result[] = trim($line); + } + return $result; + } + + /** + * Склоняет текущие слова в падеж $caseNum и форматирует слово по шаблону $format + * Формат: + * - S - Фамилия + * - N - Имя + * - F - Отчество + * @param array $format массив с форматом + * @return string строка в нужном падеже + */ + public function getFormattedHard($caseNum=0, $format=array()) + { + $result = ""; + foreach ($format as $word) + { + $cases = $word->getNameCases(); + $result.= $cases[$caseNum] . ' '; + } + return trim($result); + } + + /** + * Склоняет текущие слова в падеж $caseNum и форматирует слово по шаблону $format + * Формат: + * - S - Фамилия + * - N - Имя + * - F - Отчество + * @param string $format строка с форматом + * @return string строка в нужном падеже + */ + public function getFormatted($caseNum=0, $format="S N F") + { + $this->AllWordCases(); + //Если не указан падеж используем другую функцию + if (is_null($caseNum) or !$caseNum) + { + return $this->getFormattedArray($format); + } + //Если формат сложный + elseif (is_array($format)) + { + return $this->getFormattedHard($caseNum, $format); + } + else + { + $length = NCLStr::strlen($format); + $result = ""; + for ($i = 0; $i < $length; $i++) + { + $symbol = NCLStr::substr($format, $i, 1); + if ($symbol == 'S') + { + $result.=$this->getSecondNameCase($caseNum); + } + elseif ($symbol == 'N') + { + $result.=$this->getFirstNameCase($caseNum); + } + elseif ($symbol == 'F') + { + $result.=$this->getFatherNameCase($caseNum); + } + else + { + $result.=$symbol; + } + } + return $result; + } + } + + /** + * Склоняет фамилию $secondName, имя $firstName, отчество $fatherName + * в падеж $caseNum по правилам пола $gender и форматирует результат по шаблону $format + * Формат: + * - S - Фамилия + * - N - Имя + * - F - Отчество + * @param string $secondName фамилия + * @param string $firstName имя + * @param string $fatherName отчество + * @param int $gender пол + * @param int $caseNum номер падежа + * @param string $format формат + * @return mixed либо массив со всеми падежами, либо строка + */ + public function qFullName($secondName="", $firstName="", $fatherName="", $gender=0, $caseNum=0, $format="S N F") + { + $this->fullReset(); + $this->setFirstName($firstName); + $this->setSecondName($secondName); + $this->setFatherName($fatherName); + if ($gender) + { + $this->setGender($gender); + } + + return $this->getFormatted($caseNum, $format); + } + + /** + * Склоняет ФИО $fullname в падеж $caseNum по правилам пола $gender. + * Возвращает результат в таком же формате, как он и был. + * @param string $fullname ФИО + * @param int $caseNum номер падежа + * @param int $gender пол человека + * @return mixed либо массив со всеми падежами, либо строка + */ + public function q($fullname, $caseNum=null, $gender=null) + { + $this->fullReset(); + $format = $this->splitFullName($fullname); + if ($gender) + { + $this->setGender($gender); + } + + return $this->getFormatted($caseNum, $format); + } + + /** + * Определяет пол человека по ФИО + * @param string $fullname ФИО + * @return int пол человека + */ + public function genderDetect($fullname) + { + $this->fullReset(); + $this->splitFullName($fullname); + return $this->genderAutoDetect(); + } + + /** + * Возвращает внутренний массив $this->words каждая запись имеет тип NCLNameCaseWord + * @return array Массив всех слов в системе + */ + public function getWordsArray() + { + return $this->words; + } + + /** + * Функция пытается применить цепочку правил для мужских имен + * @return boolean true - если было использовано правило из списка, false - если правило не было найденым + */ + protected function manFirstName() + { + return false; + } + + /** + * Функция пытается применить цепочку правил для женских имен + * @return boolean true - если было использовано правило из списка, false - если правило не было найденым + */ + protected function womanFirstName() + { + return false; + } + + /** + * Функция пытается применить цепочку правил для мужских фамилий + * @return boolean true - если было использовано правило из списка, false - если правило не было найденым + */ + protected function manSecondName() + { + return false; + } + + /** + * Функция пытается применить цепочку правил для женских фамилий + * @return boolean true - если было использовано правило из списка, false - если правило не было найденым + */ + protected function womanSecondName() + { + return false; + } + + /** + * Функция склоняет мужский отчества + * @return boolean true - если слово было успешно изменено, false - если не получилось этого сделать + */ + protected function manFatherName() + { + return false; + } + + /** + * Функция склоняет женские отчества + * @return boolean true - если слово было успешно изменено, false - если не получилось этого сделать + */ + protected function womanFatherName() + { + return false; + } + + /** + * Определение пола по правилам имен + * @param NCLNameCaseWord $word обьект класса слов, для которого нужно определить пол + */ + protected function GenderByFirstName(NCLNameCaseWord $word) + { + + } + + /** + * Определение пола по правилам фамилий + * @param NCLNameCaseWord $word обьект класса слов, для которого нужно определить пол + */ + protected function GenderBySecondName(NCLNameCaseWord $word) + { + + } + + /** + * Определение пола по правилам отчеств + * @param NCLNameCaseWord $word обьект класса слов, для которого нужно определить пол + */ + protected function GenderByFatherName(NCLNameCaseWord $word) + { + + } + + /** + * Идетифицирует слово определяе имя это, или фамилия, или отчество + * - N - имя + * - S - фамилия + * - F - отчество + * @param NCLNameCaseWord $word обьект класса слов, который необходимо идентифицировать + */ + protected function detectNamePart(NCLNameCaseWord $word) + { + + } + + /** + * Возвращает версию библиотеки + * @return string версия библиотеки + */ + public function version() + { + return $this->version; + } + + /** + * Возвращает версию использованого языкового файла + * @return string версия языкового файла + */ + public function languageVersion() + { + return $this->languageBuild; + } } diff --git a/Library/NCL/NCLNameCaseWord.php b/Library/NCL/NCLNameCaseWord.php index e7c1019..c004a23 100644 --- a/Library/NCL/NCLNameCaseWord.php +++ b/Library/NCL/NCLNameCaseWord.php @@ -6,7 +6,7 @@ /** * NCLNameCaseWord - класс, который служит для хранения всей информации о каждом слове - * + * * @author Андрей Чайка * @version 0.4.1 * @package NameCaseLib @@ -14,282 +14,298 @@ class NCLNameCaseWord { - /** - * Слово в нижнем регистре, которое хранится в об’єкте класса - * @var string - */ - private $word = ''; - - /** - * Тип текущей записи (Фамилия/Имя/Отчество) - * - N - ім’я - * - S - прізвище - * - F - по-батькові - * @var string - */ - private $namePart = null; - - /** - * Вероятность того, что текущей слово относится к мужскому полу - * @var int - */ - private $genderMan = 0; - - /** - * Вероятность того, что текущей слово относится к женскому полу - * @var int - */ - private $genderWoman = 0; - - /** - * Окончательное решение, к какому полу относится слово - * - 0 - не определено - * - NCL::$MAN - мужской пол - * - NCL::$WOMAN - женский пол - * @var int - */ - private $genderSolved = 0; - - /** - * Маска больших букв в слове. - * - * Содержит информацию о том, какие буквы в слове были большими, а какие мальникими: - * - x - маленькая буква - * - X - больная буква - * @var array - */ - private $letterMask = array(); - - /** - * Содержит true, если все слово было в верхнем регистре и false, если не было - * @var bool - */ - private $isUpperCase = false; - - /** - * Массив содержит все падежи слова, полученые после склонения текущего слова - * @var array - */ - private $NameCases = array(); - - /** - * Номер правила, по которому было произведено склонение текущего слова - * @var int - */ - private $rule = 0; - - /** - * Создание нового обьекта со словом $word - * @param string $word слово - */ - public function __construct($word) - { - $this->generateMask($word); - $this->word = NCLStr::strtolower($word); - } - - /** - * Генерирует маску, которая содержит информацию о том, какие буквы в слове были большими, а какие маленькими: - * - x - маленькая буква - * - X - больная буква - * @param string $word слово, для которого генерировать маску - */ - private function generateMask($word) - { - $letters = NCLStr::splitLetters($word); - $mask = array(); - $this->isUpperCase = true; - foreach ($letters as $letter) - { - if (NCLStr::isLowerCase($letter)) - { - $mask[] = 'x'; - $this->isUpperCase = false; - } - else - { - $mask[] = 'X'; - } - } - $this->letterMask = $mask; - } - - /** - * Возвращает все падежи слова в начальную маску: - * - x - маленькая буква - * - X - больная буква - */ - private function returnMask() - { - if ($this->isUpperCase) - { - foreach ($this->NameCases as $index => $case) - { - $this->NameCases[$index] = NCLStr::strtoupper($this->NameCases[$index]); - } - } - else - { - $splitedMask = $this->letterMask; - $maskLength = count($splitedMask); - foreach ($this->NameCases as $index => $case) - { - $caseLength = NCLStr::strlen($case); + /** + * Слово в нижнем регистре, которое хранится в об’єкте класса + * @var string + */ + private $word = ''; - $max = min(array($caseLength, $maskLength)); - $this->NameCases[$index] = ''; - for ($letterIndex = 0; $letterIndex < $max; $letterIndex++) - { - $letter = NCLStr::substr($case, $letterIndex, 1); - if ($splitedMask[$letterIndex] == 'X') - { - $letter = NCLStr::strtoupper($letter); - } - $this->NameCases[$index] .= $letter; - } - $this->NameCases[$index] .= NCLStr::substr($case, $max, $caseLength-$maskLength); - } - } - } - - /** - * Сохраняет результат склонения текущего слова - * @param array $nameCases массив со всеми падежами - */ - public function setNameCases($nameCases) - { - $this->NameCases = $nameCases; - $this->returnMask(); - } - - /** - * Возвращает массив со всеми падежами текущего слова - * @return array массив со всеми падежами - */ - public function getNameCases() - { - return $this->NameCases; - } - - /** - * Возвращает строку с нужным падежом текущего слова - * @param int $number нужный падеж - * @return string строка с нужным падежом текущего слова - */ - public function getNameCase($number) - { - if(isset($this->NameCases[$number])) - { - return $this->NameCases[$number]; - } - return false; - } - - /** - * Расчитывает и возвращает пол текущего слова - * @return int пол текущего слова - */ - public function gender() - { - if (!$this->genderSolved) - { - if ($this->genderMan > $this->genderWoman) - { - $this->genderSolved = NCL::$MAN; - } - else - { - $this->genderSolved = NCL::$WOMAN; - } - } - return $this->genderSolved; - } - - /** - * Устанавливает вероятности того, что даное слово является мужчиной или женщиной - * @param int $man вероятность того, что слово мужчина - * @param int $woman верятность того, что слово женщина - */ - public function setGender($man, $woman) - { - $this->genderMan = $man; - $this->genderWoman = $woman; - } - - /** - * Окончательно устанавливает пол человека - * - 0 - не определено - * - NCL::$MAN - мужчина - * - NCL::$WOMAN - женщина - * @param int $gender пол человека - */ - public function setTrueGender($gender) - { - $this->genderSolved = $gender; - } - - /** - * Возвращает массив вероятности того, что даное слово является мужчиной или женщиной - * @return array массив вероятностей - */ - public function getGender() - { - return array(NCL::$MAN => $this->genderMan, NCL::$WOMAN => $this->genderWoman); - } - - /** - * Устанавливает тип текущего слова - * Тип слова: - * - S - Фамилия - * - N - Имя - * - F - Отчество - * @param string $namePart тип слова - */ - public function setNamePart($namePart) - { - $this->namePart = $namePart; - } - - /** - * Возвращает тип текущего слова - * Тип слова: - * - S - Фамилия - * - N - Имя - * - F - Отчество - * @return string $namePart тип слова - */ - public function getNamePart() - { - return $this->namePart; - } - - /** - * Возвращает текущее слово. - * @return string текущее слово - */ - public function getWord() - { - return $this->word; - } - - /** - * Если уже был расчитан пол для всех слов системы, тогда каждому слову предается окончательное - * решение. Эта функция определяет было ли принято окончательное решение. - * @return bool было ли принято окончательное решение по поводу пола текущего слова - */ - public function isGenderSolved() - { - return ($this->genderSolved ? true : false); - } - - /** - * Устанавливает номер правила по которому склонялось текущее слово. - * @param int $ruleID номер правила - */ - public function setRule($ruleID) - { - $this->rule = $ruleID; - } + /** + * Оригинальное слово + * @var string + */ + private $word_orig = ''; + + /** + * Тип текущей записи (Фамилия/Имя/Отчество) + * - N - ім’я + * - S - прізвище + * - F - по-батькові + * @var string + */ + private $namePart = null; + + /** + * Вероятность того, что текущей слово относится к мужскому полу + * @var int + */ + private $genderMan = 0; + + /** + * Вероятность того, что текущей слово относится к женскому полу + * @var int + */ + private $genderWoman = 0; + + /** + * Окончательное решение, к какому полу относится слово + * - 0 - не определено + * - NCL::$MAN - мужской пол + * - NCL::$WOMAN - женский пол + * @var int + */ + private $genderSolved = 0; + + /** + * Маска больших букв в слове. + * + * Содержит информацию о том, какие буквы в слове были большими, а какие мальникими: + * - x - маленькая буква + * - X - больная буква + * @var array + */ + private $letterMask = array(); + + /** + * Содержит true, если все слово было в верхнем регистре и false, если не было + * @var bool + */ + private $isUpperCase = false; + + /** + * Массив содержит все падежи слова, полученые после склонения текущего слова + * @var array + */ + private $NameCases = array(); + + /** + * Номер правила, по которому было произведено склонение текущего слова + * @var int + */ + private $rule = 0; + + /** + * Создание нового обьекта со словом $word + * @param string $word слово + */ + public function __construct($word) + { + $this->word_orig=$word; + $this->generateMask($word); + $this->word = NCLStr::strtolower($word); + } + + /** + * Генерирует маску, которая содержит информацию о том, какие буквы в слове были большими, а какие маленькими: + * - x - маленькая буква + * - X - больная буква + * @param string $word слово, для которого генерировать маску + */ + private function generateMask($word) + { + $letters = NCLStr::splitLetters($word); + $mask = array(); + $this->isUpperCase = true; + foreach ($letters as $letter) + { + if (NCLStr::isLowerCase($letter)) + { + $mask[] = 'x'; + $this->isUpperCase = false; + } + else + { + $mask[] = 'X'; + } + } + $this->letterMask = $mask; + } + + /** + * Возвращает все падежи слова в начальную маску: + * - x - маленькая буква + * - X - больная буква + */ + private function returnMask() + { + if ($this->isUpperCase) + { + foreach ($this->NameCases as $index => $case) + { + $this->NameCases[$index] = NCLStr::strtoupper($this->NameCases[$index]); + } + } + else + { + $splitedMask = $this->letterMask; + $maskLength = count($splitedMask); + foreach ($this->NameCases as $index => $case) + { + $caseLength = NCLStr::strlen($case); + + $max = min(array($caseLength, $maskLength)); + $this->NameCases[$index] = ''; + for ($letterIndex = 0; $letterIndex < $max; $letterIndex++) + { + $letter = NCLStr::substr($case, $letterIndex, 1); + if ($splitedMask[$letterIndex] == 'X') + { + $letter = NCLStr::strtoupper($letter); + } + $this->NameCases[$index] .= $letter; + } + $this->NameCases[$index] .= NCLStr::substr($case, $max, $caseLength-$maskLength); + } + } + } + + /** + * Сохраняет результат склонения текущего слова + * @param array $nameCases массив со всеми падежами + */ + public function setNameCases($nameCases, $is_return_mask=true) + { + $this->NameCases = $nameCases; + if ($is_return_mask) $this->returnMask(); + } + + /** + * Возвращает массив со всеми падежами текущего слова + * @return array массив со всеми падежами + */ + public function getNameCases() + { + return $this->NameCases; + } + + /** + * Возвращает строку с нужным падежом текущего слова + * @param int $number нужный падеж + * @return string строка с нужным падежом текущего слова + */ + public function getNameCase($number) + { + if(isset($this->NameCases[$number])) + { + return $this->NameCases[$number]; + } + return false; + } + + /** + * Расчитывает и возвращает пол текущего слова + * @return int пол текущего слова + */ + public function gender() + { + if (!$this->genderSolved) + { + if ($this->genderMan > $this->genderWoman) + { + $this->genderSolved = NCL::$MAN; + } + else + { + $this->genderSolved = NCL::$WOMAN; + } + } + return $this->genderSolved; + } + + /** + * Устанавливает вероятности того, что даное слово является мужчиной или женщиной + * @param int $man вероятность того, что слово мужчина + * @param int $woman верятность того, что слово женщина + */ + public function setGender($man, $woman) + { + $this->genderMan = $man; + $this->genderWoman = $woman; + } + + /** + * Окончательно устанавливает пол человека + * - 0 - не определено + * - NCL::$MAN - мужчина + * - NCL::$WOMAN - женщина + * @param int $gender пол человека + */ + public function setTrueGender($gender) + { + $this->genderSolved = $gender; + } + + /** + * Возвращает массив вероятности того, что даное слово является мужчиной или женщиной + * @return array массив вероятностей + */ + public function getGender() + { + return array(NCL::$MAN => $this->genderMan, NCL::$WOMAN => $this->genderWoman); + } + + /** + * Устанавливает тип текущего слова + * Тип слова: + * - S - Фамилия + * - N - Имя + * - F - Отчество + * @param string $namePart тип слова + */ + public function setNamePart($namePart) + { + $this->namePart = $namePart; + } + + /** + * Возвращает тип текущего слова + * Тип слова: + * - S - Фамилия + * - N - Имя + * - F - Отчество + * @return string $namePart тип слова + */ + public function getNamePart() + { + return $this->namePart; + } + + /** + * Возвращает текущее слово. + * @return string текущее слово + */ + public function getWord() + { + return $this->word; + } + + /** + * Возвращает текущее оригинальное слово. + * @return string текущее слово + */ + public function getWordOrig() + { + return $this->word_orig; + } + + /** + * Если уже был расчитан пол для всех слов системы, тогда каждому слову предается окончательное + * решение. Эта функция определяет было ли принято окончательное решение. + * @return bool было ли принято окончательное решение по поводу пола текущего слова + */ + public function isGenderSolved() + { + return ($this->genderSolved ? true : false); + } + + /** + * Устанавливает номер правила по которому склонялось текущее слово. + * @param int $ruleID номер правила + */ + public function setRule($ruleID) + { + $this->rule = $ruleID; + } } ?> From 1ec87d11b51a620a95228390a917effa007cfc15 Mon Sep 17 00:00:00 2001 From: RA Date: Mon, 3 Aug 2015 15:02:54 +0300 Subject: [PATCH 07/19] =?UTF-8?q?fix=20=D0=B8=D1=81=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20"=D0=94=D0=B8=D0=BD=D0=B0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index 2cf5b09..e12cd7d 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -881,7 +881,7 @@ class NCLNameCaseRu extends NCLNameCaseCore /** * Исключения */ - elseif ($this->inNames($namepart, array('Мальвина', 'Антонина', 'Альбина', 'Агриппина', 'Фаина', 'Карина', 'Марина', 'Валентина', 'Калина', 'Аделина', 'Алина', 'Ангелина', 'Галина', 'Каролина', 'Павлина', 'Полина', 'Элина', 'Мина', 'Нина'))) + elseif ($this->inNames($namepart, array('Мальвина', 'Антонина', 'Альбина', 'Агриппина', 'Фаина', 'Карина', 'Марина', 'Валентина', 'Калина', 'Аделина', 'Алина', 'Ангелина', 'Галина', 'Каролина', 'Павлина', 'Полина', 'Элина', 'Мина', 'Нина', 'Дина'))) { $first+=10; } From 6dea3ed9c7fbc9a38212455d5e98f06d48e6b4b2 Mon Sep 17 00:00:00 2001 From: RA Date: Fri, 7 Aug 2015 19:15:10 +0300 Subject: [PATCH 08/19] =?UTF-8?q?fix=20=D0=9C=D0=B0=D1=83=D1=80=D0=B8?= =?UTF-8?q?=D1=86,=20=D0=9A=D0=BE=D1=80=D0=BD=D0=B5=D0=BB=D0=B8=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index e12cd7d..7585a1d 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -727,10 +727,18 @@ class NCLNameCaseRu extends NCLNameCaseCore } /** - * буквы на которые никогда не закнчиваются имена + * буквы на которые никогда не заканчиваются имена */ if ($this->in($this->Last(1), 'еёжхцочшщъыэю')) { + /** + * Просто исключения + */ + if ($this->inNames($namepart, array('Мауриц'))) + { + $first += 10; + } + else { $second += 0.3; } @@ -813,7 +821,7 @@ class NCLNameCaseRu extends NCLNameCaseCore //Исключения if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль', 'Вильям', 'Уильям', - 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', + 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет'/*женские иностранные*/))) { $first+=10; From a7ea2f57e0f0bcb3695749b86674c2d946c05042 Mon Sep 17 00:00:00 2001 From: RA Date: Wed, 26 Aug 2015 14:38:28 +0300 Subject: [PATCH 09/19] =?UTF-8?q?fix=20name=5Fcase=20=D0=A2=D1=83=D0=BB?= =?UTF-8?q?=D1=83=D0=B7-=D0=9B=D0=BE=D1=82=D1=80=D0=B5=D0=BA=20fix=20?= =?UTF-8?q?=D0=A4=D1=80=D1=8D=D0=BD=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCL/NCLNameCaseCore.php | 15 ++++++++++++--- Library/NCLNameCaseRu.php | 4 ++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Library/NCL/NCLNameCaseCore.php b/Library/NCL/NCLNameCaseCore.php index 3334305..3580548 100644 --- a/Library/NCL/NCLNameCaseCore.php +++ b/Library/NCL/NCLNameCaseCore.php @@ -612,13 +612,22 @@ class NCLNameCaseCore extends NCL $cnt=count($cur_words); foreach ($cur_words as $k=>$cur_word){ $is_norm_rules=true; + $o_ncw=new NCLNameCaseWord($cur_word); if ( $name_part_letter=='S' && $cnt>1 && $k<$cnt-1 ){ //если первая часть фамилии тоже фамилия, то склоняем по общим правилам //иначе не склоняется - $o_nc = new NCLNameCaseRu(); - $o_nc->detectNamePart( $o_ncw ); - $is_norm_rules=( $o_ncw->getNamePart()==$name_part_letter ); + + $exclusion=array('тулуз');//исключения + $cur_word_=mb_strtolower($cur_word); + if ( !in_array($cur_word_, $exclusion ) ){ + $o_nc = new NCLNameCaseRu(); + $o_nc->detectNamePart( $o_ncw ); + $is_norm_rules=( $o_ncw->getNamePart()=='S' ); + } + else { + $is_norm_rules=false; + } } $this->setWorkingWord($cur_word); diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index 7585a1d..9e255a6 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -270,7 +270,7 @@ class NCLNameCaseRu extends NCLNameCaseCore $this->Rule(501); return true; } - if ($this->Last(2, 1) == 'е') + if ($this->Last(2, 1) == 'е' && !in_array($this->Last(3, 1), array('р')))//Лотрек { $this->wordForms($this->workingWord, array('ька', 'ьку', 'ька', 'ьком', 'ьке'), 2); $this->Rule(502); @@ -821,7 +821,7 @@ class NCLNameCaseRu extends NCLNameCaseCore //Исключения if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль', 'Вильям', 'Уильям', - 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', + 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', 'Фрэнк', 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет'/*женские иностранные*/))) { $first+=10; From 67946fbf95820f9a3d2291bcf689d3784d7a2af4 Mon Sep 17 00:00:00 2001 From: RA Date: Tue, 15 Sep 2015 14:51:55 +0300 Subject: [PATCH 10/19] =?UTF-8?q?fix=20=D1=84=D0=B0=D0=BC=D0=B8=D0=BB?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=BD=D0=B0=20-=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index 9e255a6..b741181 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -264,7 +264,7 @@ class NCLNameCaseRu extends NCLNameCaseCore if ($this->Last(1) == 'к') { //Если перед слово на ок, то нужно убрать о - if ($this->Last(2, 1) == 'о') + if ($this->Last(4)=='енок' || $this->Last(4)=='ёнок')//Поллок { $this->wordForms($this->workingWord, array('ка', 'ку', 'ка', 'ком', 'ке'), 2); $this->Rule(501); From f6f81155a9a06126c003fc12c81793811405b2d9 Mon Sep 17 00:00:00 2001 From: RA Date: Mon, 21 Sep 2015 13:00:37 +0300 Subject: [PATCH 11/19] =?UTF-8?q?fix=20namecase=20=D0=9B=D0=B5=D0=BE=D0=BD?= =?UTF-8?q?=D0=B0=D1=80=D0=B4=D0=BE=20=D0=B4=D0=B0=20=D0=92=D0=B8=D0=BD?= =?UTF-8?q?=D1=87=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index b741181..55acb45 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -328,30 +328,36 @@ class NCLNameCaseRu extends NCLNameCaseCore { if ($this->Last(1) == "а") { + if ($this->inNames($this->workingWord, array('да'))) + { + $this->Rule(701); + $this->makeResultTheSame(); + return true; + } //Если основа на ш, то нужно и, ей if ($this->Last(2, 1) == 'ш') { $this->wordForms($this->workingWord, array('и', 'е', 'у', 'ей', 'е'), 1); - $this->Rule(701); + $this->Rule(702); return true; } elseif ($this->in($this->Last(2, 1), 'хкг')) { $this->wordForms($this->workingWord, array('и', 'е', 'у', 'ой', 'е'), 1); - $this->Rule(702); + $this->Rule(703); return true; } else { $this->wordForms($this->workingWord, array('ы', 'е', 'у', 'ой', 'е'), 1); - $this->Rule(703); + $this->Rule(704); return true; } } elseif ($this->Last(1) == "я") { $this->wordForms($this->workingWord, array('ой', 'ой', 'ую', 'ой', 'ой'), 2); - $this->Rule(704); + $this->Rule(705); return true; } return false; @@ -584,7 +590,7 @@ class NCLNameCaseRu extends NCLNameCaseCore { $man+=0.9; } - if ($this->in($this->Last(2), array('он', 'ов', 'ав', 'ам', 'ол', 'ан', 'рд', 'мп', 'по'/*Филиппо*/))) + if ($this->in($this->Last(2), array('он', 'ов', 'ав', 'ам', 'ол', 'ан', 'рд', 'мп', 'по'/*Филиппо*/, 'до'/*Леонардо*/))) { $man+=0.3; } @@ -740,7 +746,8 @@ class NCLNameCaseRu extends NCLNameCaseCore } else { $second += 0.3; - } + } + } /** * Используем массив характерных окончаний @@ -821,7 +828,7 @@ class NCLNameCaseRu extends NCLNameCaseCore //Исключения if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль', 'Вильям', 'Уильям', - 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', 'Фрэнк', + 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', 'Фрэнк', 'Леонардо', 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет'/*женские иностранные*/))) { $first+=10; @@ -928,6 +935,10 @@ class NCLNameCaseRu extends NCLNameCaseCore $second+=0.4; } + if ($this->inNames($namepart, array('да'))){ + $second += 10; + } + $max = max(array($first, $second, $father)); From 295c025b1bfc850b2a88a7e3b5b853a2d35aeae5 Mon Sep 17 00:00:00 2001 From: RA Date: Mon, 21 Sep 2015 13:10:10 +0300 Subject: [PATCH 12/19] =?UTF-8?q?fix=20namecase=20=D0=98=D1=81=D0=BA=D0=BB?= =?UTF-8?q?=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=91=D0=B5=D1=80=D0=B8=D0=BB=20=D0=9A=D1=83=D0=BA,=20=D0=BA?= =?UTF-8?q?=D0=BE=D1=82=D0=BE=D1=80=D0=B0=D1=8F=20=D0=B6=D0=B5=D0=BD=D1=89?= =?UTF-8?q?=D0=B8=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index 55acb45..c06288b 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -544,7 +544,7 @@ class NCLNameCaseRu extends NCLNameCaseCore * @return boolean true - если слово было успешно изменено, false - если не получилось этого сделать */ protected function manFatherName() - { + { //Проверяем действительно ли отчество if ($this->inNames($this->workingWord, 'Ильич')) { @@ -648,6 +648,12 @@ class NCLNameCaseRu extends NCLNameCaseCore $woman += 10; } + //Исключение для Берил Кук, которая женщина + if ($this->inNames($this->workingWord, array('Берил'))) + { + $woman += 0.05; + } + $word->setGender($man, $woman); } From f11a2d60e41f1f59e9173c3c9cf6828704895bb9 Mon Sep 17 00:00:00 2001 From: RA Date: Wed, 23 Sep 2015 11:19:34 +0300 Subject: [PATCH 13/19] =?UTF-8?q?fix=20namecase.=20=D0=96=D0=B5=D0=BD?= =?UTF-8?q?=D1=81=D0=BA=D0=B8=D0=B5=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B0=20*?= =?UTF-8?q?=D0=BD=D0=B0.=20=D0=A4=D0=B0=D0=BC=D0=B8=D0=BB=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=B2=D0=B0=D0=BB=D0=B0=D0=B4=D0=BE=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index c06288b..f114ac2 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -603,7 +603,7 @@ class NCLNameCaseRu extends NCLNameCaseCore $man+=0.02; } - if ($this->in($this->Last(2), array('вь', 'фь', 'ль'))) + if ($this->in($this->Last(2), array('вь', 'фь', 'ль', 'на'))) { $woman+=0.1; } @@ -941,7 +941,8 @@ class NCLNameCaseRu extends NCLNameCaseCore $second+=0.4; } - if ($this->inNames($namepart, array('да'))){ + //исключения и частички + if ($this->inNames($namepart, array('да', 'валадон'))){ $second += 10; } From b4cf7c1e475bcd39b2b9070d8eb53be775f23d10 Mon Sep 17 00:00:00 2001 From: RA Date: Tue, 29 Sep 2015 12:33:31 +0300 Subject: [PATCH 14/19] =?UTF-8?q?fix=20namecase=20+=D0=94=D0=B6=D0=B5?= =?UTF-8?q?=D0=B9=D0=BC=D1=81=20-=20=D0=B8=D0=BC=D1=8F=20fix=20namecase=20?= =?UTF-8?q?+=D0=9E=D1=82=D1=82=D0=BE=20-=20=D0=B8=D0=BC=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index f114ac2..319419a 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -834,7 +834,7 @@ class NCLNameCaseRu extends NCLNameCaseCore //Исключения if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль', 'Вильям', 'Уильям', - 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', 'Фрэнк', 'Леонардо', + 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', 'Фрэнк', 'Леонардо', 'Джеймс', 'Отто', 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет'/*женские иностранные*/))) { $first+=10; From b48bf4d9d12a98a1b4eb18c49cf98482865728a2 Mon Sep 17 00:00:00 2001 From: RA Date: Tue, 20 Oct 2015 11:59:34 +0300 Subject: [PATCH 15/19] =?UTF-8?q?fix=20=D1=80=D0=B5=D1=80=D0=B8=D1=85,=20?= =?UTF-8?q?=D0=B6=D0=B0=D0=BD-=D0=BF=D1=8C=D0=B5=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index 319419a..371d7f8 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -369,8 +369,9 @@ class NCLNameCaseRu extends NCLNameCaseCore */ protected function manRule8() { - if ($this->in($this->Last(3), $this->ovo) or $this->in($this->Last(2), $this->ih)) + if ($this->in($this->Last(3), $this->ovo) || $this->in($this->Last(2), $this->ih)) { + if ( $this->inNames($this->workingWord, array('рерих')) ) return false; $this->Rule(8); $this->makeResultTheSame(); return true; @@ -834,7 +835,7 @@ class NCLNameCaseRu extends NCLNameCaseCore //Исключения if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль', 'Вильям', 'Уильям', - 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', 'Фрэнк', 'Леонардо', 'Джеймс', 'Отто', + 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', 'Фрэнк', 'Леонардо', 'Джеймс', 'Отто', 'жан-пьер', 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет'/*женские иностранные*/))) { $first+=10; From 91dd537b21700a2b2791c6d385a892caab56a3c5 Mon Sep 17 00:00:00 2001 From: RA Date: Wed, 28 Oct 2015 11:42:17 +0200 Subject: [PATCH 16/19] =?UTF-8?q?feature=20=D0=96=D0=B5=D0=BD=D1=81=D0=BA?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B0=20'=D0=96=D0=B0?= =?UTF-8?q?=D0=BA=D0=BB=D0=B8=D0=BD',=20'=D0=AD=D0=B2=D0=B5=D0=BB=D0=B8?= =?UTF-8?q?=D0=BD'.=20=D0=A4=D0=B0=D0=BC=D0=B8=D0=BB=D0=B8=D1=8F=20=D0=94?= =?UTF-8?q?=D0=B0=D0=BD=D0=B1=D0=B0=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index 371d7f8..7c3dd59 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -644,7 +644,7 @@ class NCLNameCaseRu extends NCLNameCaseCore $man += 10; } - if ($this->inNames($this->workingWord, array('Бриджет', 'Элизабет', 'Маргарет', 'Джанет'))) + if ($this->inNames($this->workingWord, array('Бриджет', 'Элизабет', 'Маргарет', 'Джанет', 'Жаклин', 'Эвелин'))) { $woman += 10; } @@ -836,7 +836,7 @@ class NCLNameCaseRu extends NCLNameCaseCore if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль', 'Вильям', 'Уильям', 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', 'Фрэнк', 'Леонардо', 'Джеймс', 'Отто', 'жан-пьер', - 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет'/*женские иностранные*/))) + 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет', 'Жаклин', 'Эвелин'/*женские иностранные*/))) { $first+=10; } @@ -943,7 +943,7 @@ class NCLNameCaseRu extends NCLNameCaseCore } //исключения и частички - if ($this->inNames($namepart, array('да', 'валадон'))){ + if ($this->inNames($namepart, array('да', 'валадон', 'Данбар'))){ $second += 10; } From 807b6cc095b69f92ed84d5af504157c5ad099a3b Mon Sep 17 00:00:00 2001 From: RA Date: Tue, 3 Nov 2015 10:18:09 +0200 Subject: [PATCH 17/19] fix genderAutoDetect --- Library/NCL/NCLNameCaseCore.php | 29 +++++++++++++++++++++++++++-- Library/NCL/NCLNameCaseWord.php | 2 +- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Library/NCL/NCLNameCaseCore.php b/Library/NCL/NCLNameCaseCore.php index 3580548..43af4f3 100644 --- a/Library/NCL/NCLNameCaseCore.php +++ b/Library/NCL/NCLNameCaseCore.php @@ -88,6 +88,8 @@ class NCLNameCaseCore extends NCL */ private $index = array(); + public $gender_koef=0;//вероятность автоопредления пола [0..10]. Достаточно точно при 0.1 + /** * Метод очищает результаты последнего склонения слова. Нужен при склонении нескольких слов. */ @@ -516,9 +518,32 @@ class NCLNameCaseCore extends NCL public function genderAutoDetect() { $this->prepareEverything(); - if (isset($this->words[0])) + + if (!empty($this->words)){ + $n=-1; + $max_koef=-1; + foreach ($this->words as $k=>$word){ + $genders=$word->getGender(); + $min=min( $genders ); + $max=max( $genders ); + $koef=$max-$min; + if ($koef>$max_koef) { + $max_koef=$koef; + $n=$k; + } + } + + if ($n>=0){ + if (isset($this->words[$n])) { - return $this->words[0]->gender(); + $genders=$this->words[$n]->getGender(); + $min=min( $genders ); + $max=max( $genders ); + $this->gender_koef=$max-$min; + + return $this->words[$n]->gender(); + } + } } return false; } diff --git a/Library/NCL/NCLNameCaseWord.php b/Library/NCL/NCLNameCaseWord.php index c004a23..ed81e95 100644 --- a/Library/NCL/NCLNameCaseWord.php +++ b/Library/NCL/NCLNameCaseWord.php @@ -200,7 +200,7 @@ class NCLNameCaseWord { if (!$this->genderSolved) { - if ($this->genderMan > $this->genderWoman) + if ($this->genderMan >= $this->genderWoman) { $this->genderSolved = NCL::$MAN; } From 24eddc300150a20f2c2a266c1b523dfec1796c26 Mon Sep 17 00:00:00 2001 From: RA Date: Tue, 3 Nov 2015 10:19:00 +0200 Subject: [PATCH 18/19] =?UTF-8?q?refactor=20=D0=B8=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=BC=D1=83=D0=B6=D1=81?= =?UTF-8?q?=D0=BA=D0=B8=D0=B5=20=D0=B8=D0=BC=D0=B5=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Library/NCLNameCaseRu.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index 7c3dd59..baf5c66 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -94,6 +94,14 @@ class NCLNameCaseRu extends NCLNameCaseCore 'я' => 'нс' ); + private $names_man=array('Вова', 'Анри', 'Питер', 'Пауль', 'Франц', 'Вильям', 'Уильям', + 'Альфонс', 'Ганс', 'Франс', 'Филиппо', 'Андреа', 'Корнелис', 'Фрэнк', 'Леонардо', + 'Джеймс', 'Отто', 'жан-пьер', 'Джованни', 'Джозеф', 'Педро', 'Адольф', 'Уолтер', + 'Антонио', 'Якоб', 'Эсташ', 'Адрианс', 'Франческо', 'Доменико', 'Ханс', 'Гун', + 'Шарль', 'Хендрик', 'Амброзиус', 'Таддео', 'Фердинанд', 'Джошуа', 'Изак', 'Иоганн', + 'Фридрих', 'Эмиль', 'Умберто', 'Франсуа', 'Ян', 'Эрнст', 'Георг', 'Карл' + ); + /** * Мужские имена, оканчивающиеся на любой ь и -й, * скло­няются так же, как обычные существительные мужского рода @@ -591,7 +599,7 @@ class NCLNameCaseRu extends NCLNameCaseCore { $man+=0.9; } - if ($this->in($this->Last(2), array('он', 'ов', 'ав', 'ам', 'ол', 'ан', 'рд', 'мп', 'по'/*Филиппо*/, 'до'/*Леонардо*/))) + if ($this->in($this->Last(2), array('он', 'ов', 'ав', 'ам', 'ол', 'ан', 'рд', 'мп', 'по'/*Филиппо*/, 'до'/*Леонардо*/, 'др', 'рт'))) { $man+=0.3; } @@ -639,7 +647,7 @@ class NCLNameCaseRu extends NCLNameCaseCore $woman+=0.5; } - if ($this->inNames($this->workingWord, array('Вова', 'Анри', 'Питер', 'Пауль'))) + if ($this->inNames($this->workingWord, $this->names_man)) { $man += 10; } @@ -834,9 +842,11 @@ class NCLNameCaseRu extends NCLNameCaseCore //Исключения if ($this->inNames($namepart, array('Лев', 'Яков', 'Вова', 'Маша', 'Ольга', 'Еремей', - 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', 'Франц', 'Питер', 'Пауль', 'Вильям', 'Уильям', - 'Альфонс', 'Ганс', 'Франс', 'Мариа'/*Альфонс Мариа Муха*/, 'Филиппо', 'Андреа', 'Корнелис', 'Фрэнк', 'Леонардо', 'Джеймс', 'Отто', 'жан-пьер', - 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет', 'Жаклин', 'Эвелин'/*женские иностранные*/))) + 'Исак', 'Исаак', 'Ева', 'Ирина', 'Элькин', 'Мерлин', 'Макс', 'Алекс', + 'Мариа'/*Альфонс Мариа Муха*/, + 'Бриджет', 'Элизабет', 'Маргарет', 'Джанет', 'Жаклин', 'Эвелин'/*женские иностранные*/)) + || $this->inNames($namepart, $this->names_man) + ) { $first+=10; } From 4bc2eaf29f1f7bf5a4f68ff38538a5a730ab6e37 Mon Sep 17 00:00:00 2001 From: RA Date: Tue, 8 Dec 2015 15:45:57 +0200 Subject: [PATCH 19/19] =?UTF-8?q?feature=20=D0=98=D1=81=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D1=81?= =?UTF-8?q?=D0=BA=D0=BB=D0=BE=D0=BD=D0=B5=D0=BD=D0=B8=D0=B9=20+=D0=A1?= =?UTF-8?q?=D1=91=D1=80=D0=B0=20=D0=BD=D0=B5=20=D1=81=D0=BA=D0=BB=D0=BE?= =?UTF-8?q?=D0=BD=D1=8F=D0=B5=D1=82=D1=81=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-Url: https://trello.com/c/GQsARxyE --- Library/NCLNameCaseRu.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/NCLNameCaseRu.php b/Library/NCLNameCaseRu.php index baf5c66..8d6611a 100644 --- a/Library/NCLNameCaseRu.php +++ b/Library/NCLNameCaseRu.php @@ -182,7 +182,7 @@ class NCLNameCaseRu extends NCLNameCaseCore { if ($this->Last(1) == "а") { - if ($this->inNames($this->workingWord, array('фра', 'Дега', 'Андреа'))) + if ($this->inNames($this->workingWord, array('фра', 'Дега', 'Андреа', 'Сёра', 'Сера'))) { $this->Rule(301); $this->makeResultTheSame();