Skip to content

Commit

Permalink
Add gender to cardinal numerals
Browse files Browse the repository at this point in the history
  • Loading branch information
wapmorgan committed Feb 3, 2017
1 parent b2ccef2 commit e0572bd
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 28 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,10 @@ echo $count.' '.Plurality::pluralize($word, $count, false);

All number creation classes are similar and have two common methods:

- `string getForm($number, $case)` - Get one form of a number.
- `array getForms($number)` - Get all forms of a number.
- `string getForm($number, $case, $gender = NumeralCreation::MALE)` - Get one form of a number.
- `array getForms($number, $gender = NumeralCreation::MALE)` - Get all forms of a number.

`$gender` is one of `morphos\NumeralCreation` constants: `MALE` or `FEMALE` or `NEUTER`.

### Cardinal numbers (`CardinalNumeral`)

Expand All @@ -359,6 +361,7 @@ _Creation of cardinal numerals in russian language._
Create declension class object:

```php
use morphos\NumeralCreation;
use morphos\Russian\CardinalNumeral;
use morphos\Russian\Cases;

Expand All @@ -371,6 +374,7 @@ Get text representation of a number:
$number = 4351;

$numeral = $cardinal->getForm($number, Cases::IMENIT); // четыре тысячи триста пятьдесят один
$numeral = $cardinal->getForm($number, Cases::IMENIT, NumeralCreation::FEMALE); // четыре тысячи триста пятьдесят одна
```

If you need all forms, you can get all forms of a name:
Expand Down
4 changes: 4 additions & 0 deletions src/NumeralCreation.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
namespace morphos;

class NumeralCreation implements Cases {
const MALE = 'm';
const FEMALE = 'f';
const NEUTER = 'n';

public function getForms($number) {}
public function getForm($number, $case) {}
}
76 changes: 58 additions & 18 deletions src/Russian/CardinalNumeral.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,56 @@ class CardinalNumeral extends NumeralCreation implements Cases {

protected $precalculated = array(
'один' => array(
self::IMENIT => 'один',
self::RODIT => 'одного',
self::DAT => 'одному',
self::VINIT => 'один',
self::TVORIT => 'одним',
self::PREDLOJ => 'об одном',
self::MALE => array(
self::IMENIT => 'один',
self::RODIT => 'одного',
self::DAT => 'одному',
self::VINIT => 'один',
self::TVORIT => 'одним',
self::PREDLOJ => 'об одном',
),
self::FEMALE => array(
self::IMENIT => 'одна',
self::RODIT => 'одной',
self::DAT => 'одной',
self::VINIT => 'одну',
self::TVORIT => 'одной',
self::PREDLOJ => 'об одной',
),
self::NEUTER => array(
self::IMENIT => 'одно',
self::RODIT => 'одного',
self::DAT => 'одному',
self::VINIT => 'одно',
self::TVORIT => 'одним',
self::PREDLOJ => 'об одном',
),
),
'два' => array(
self::IMENIT => 'два',
self::RODIT => 'двух',
self::DAT => 'двум',
self::VINIT => 'два',
self::TVORIT => 'двумя',
self::PREDLOJ => 'о двух',
self::MALE => array(
self::IMENIT => 'два',
self::RODIT => 'двух',
self::DAT => 'двум',
self::VINIT => 'два',
self::TVORIT => 'двумя',
self::PREDLOJ => 'о двух',
),
self::FEMALE => array(
self::IMENIT => 'две',
self::RODIT => 'двух',
self::DAT => 'двум',
self::VINIT => 'два',
self::TVORIT => 'двумя',
self::PREDLOJ => 'о двух',
),
self::NEUTER => array(
self::IMENIT => 'два',
self::RODIT => 'двух',
self::DAT => 'двум',
self::VINIT => 'два',
self::TVORIT => 'двумя',
self::PREDLOJ => 'о двух',
),
),
'три' => array(
self::IMENIT => 'три',
Expand Down Expand Up @@ -116,12 +152,16 @@ class CardinalNumeral extends NumeralCreation implements Cases {
),
);

public function getForms($number) {
public function getForms($number, $gender = self::MALE) {
// simple numeral
if (isset($this->words[$number]) || isset($this->exponents[$number])) {
$word = isset($this->words[$number]) ? $this->words[$number] : $this->exponents[$number];
if (isset($this->precalculated[$word])) {
return $this->precalculated[$word];
if (isset($this->precalculated[$word][self::MALE])) {
return $this->precalculated[$word][$gender];
} else {
return $this->precalculated[$word];
}
} else if (($number >= 5 && $number <= 20) || $number == 30) {
$prefix = slice($word, 0, -1);
return array(
Expand Down Expand Up @@ -182,7 +222,7 @@ public function getForms($number) {
foreach (array_reverse($this->exponents, true) as $word_number => $word) {
if ($number >= $word_number) {
$count = floor($number / $word_number);
$parts[] = $this->getForms($count);
$parts[] = $this->getForms($count, ($word_number == 1000 ? self::FEMALE : self::MALE));

// get forms of word
if (empty($this->declension)) $this->declension = new GeneralDeclension();
Expand Down Expand Up @@ -211,7 +251,7 @@ public function getForms($number) {

foreach (array_reverse($this->words, true) as $word_number => $word) {
if ($number >= $word_number) {
$parts[] = $this->getForms($word_number);
$parts[] = $this->getForms($word_number, $gender);
$number %= $word_number;
}
}
Expand All @@ -229,8 +269,8 @@ public function getForms($number) {
}
}

public function getForm($number, $form) {
$forms = $this->getForms($number);
public function getForm($number, $form, $gender = self::MALE) {
$forms = $this->getForms($number, $gender);
return $forms[$form];
}
}
19 changes: 11 additions & 8 deletions tests/Russian/CardinalNumeralTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace morphos\test\Russian;
require __DIR__.'/../../vendor/autoload.php';

use morphos\NumeralCreation;
use morphos\Russian\Cases;
use morphos\Russian\CardinalNumeral;

Expand All @@ -15,25 +16,27 @@ public function setUp() {
/**
* @dataProvider numbersProvider
*/
public function testGetForms($number, $case, $case2, $case3, $case4, $case5, $case6) {
public function testGetForms($number, $gender, $case, $case2, $case3, $case4, $case5, $case6) {
$this->assertEquals(array(
Cases::IMENIT => $case,
Cases::RODIT => $case2,
Cases::DAT => $case3,
Cases::VINIT => $case4,
Cases::TVORIT => $case5,
Cases::PREDLOJ => $case6,
), $this->cardinal->getForms($number));
), $this->cardinal->getForms($number, $gender));
}

public function numbersProvider() {
return array(
array(1, 'один', 'одного', 'одному', 'один', 'одним', 'об одном'),
array(201, 'двести один', 'двухсот одного', 'двумстам одному', 'двести один', 'двумястами одним', 'о двухстах одном'),
array(344, 'триста сорок четыре', 'трехсот сорока четырех', 'тремстам сорока четырем', 'триста сорок четыре', 'тремястами сорока четырьмя', 'о трехстах сорока четырех'),
array(3651, 'три тысячи шестьсот пятьдесят один', 'трех тысяч шестисот пятидесяти одного', 'трем тысячам шестистам пятидесяти одному', 'три тысячи шестьсот пятьдесят один', 'тремя тысячами шестьюстами пятьюдесятью одним', 'о трех тысячах шестистах пятидесяти одном'),
array(9999, 'девять тысяч девятьсот девяносто девять', 'девяти тысяч девятисот девяноста девяти', 'девяти тысячам девятистам девяноста девяти', 'девять тысяч девятьсот девяносто девять', 'девятью тысячами девятьюстами девяноста девятью', 'о девяти тысячах девятистах девяноста девяти'),
array(1234567890,
array(1, NumeralCreation::MALE, 'один', 'одного', 'одному', 'один', 'одним', 'об одном'),
array(1, NumeralCreation::FEMALE, 'одна', 'одной', 'одной', 'одну', 'одной', 'об одной'),
array(201, NumeralCreation::MALE, 'двести один', 'двухсот одного', 'двумстам одному', 'двести один', 'двумястами одним', 'о двухстах одном'),
array(344, NumeralCreation::MALE, 'триста сорок четыре', 'трехсот сорока четырех', 'тремстам сорока четырем', 'триста сорок четыре', 'тремястами сорока четырьмя', 'о трехстах сорока четырех'),
array(1007, NumeralCreation::MALE, 'одна тысяча семь', 'одной тысячи семи', 'одной тысяче семи', 'одну тысячу семь', 'одной тысячей семью', 'об одной тысяче семи'),
array(3651, NumeralCreation::MALE, 'три тысячи шестьсот пятьдесят один', 'трех тысяч шестисот пятидесяти одного', 'трем тысячам шестистам пятидесяти одному', 'три тысячи шестьсот пятьдесят один', 'тремя тысячами шестьюстами пятьюдесятью одним', 'о трех тысячах шестистах пятидесяти одном'),
array(9999, NumeralCreation::MALE, 'девять тысяч девятьсот девяносто девять', 'девяти тысяч девятисот девяноста девяти', 'девяти тысячам девятистам девяноста девяти', 'девять тысяч девятьсот девяносто девять', 'девятью тысячами девятьюстами девяноста девятью', 'о девяти тысячах девятистах девяноста девяти'),
array(1234567890, NumeralCreation::MALE,
'один миллиард двести тридцать четыре миллиона пятьсот шестьдесят семь тысяч восемьсот девяносто',
'одного миллиарда двухсот тридцати четырех миллионов пятисот шестидесяти семи тысяч восьмисот девяноста',
'одному миллиарду двумстам тридцати четырем миллионам пятистам шестидесяти семи тысячам восьмистам девяноста',
Expand Down

0 comments on commit e0572bd

Please sign in to comment.