Skip to content

Commit

Permalink
Adds support for first names
Browse files Browse the repository at this point in the history
Changes:
1. Adds `Store` which is an `Agent` to store parsed json
2. Adds `Parser` to parse different rules
3. Adds `Applier` to apply these rule on names
4. Adds public interface to use it

TODO:
1. Add middlename tests
2. Add lastname support
3. Add gender detection
4. Make `:gender` parameter optional, try to guess it first
5. Add @doc and @SPEC to public functions
6. Write docs
7. Add travis and coveralls.io
8. Run diallyzer
  • Loading branch information
sobolevn committed Jun 11, 2017
1 parent 2e3d2df commit bf4ddb1
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 11 deletions.
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Check http://editorconfig.org for more information
# This is the main config file for this project:
root = true

[*]
charset = utf-8
indent_style = space
trim_trailing_whitespace = true
end_of_line = lf
insert_final_newline = true

[*.{ex,exs,exx}]
indent_style = space
indent_size = 2
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "rules"]
path = rules
url = https://github.com/petrovich/petrovich-rules.git
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# petrovic_elixir

[![petrovich](https://camo.githubusercontent.com/4555ec1b7aa15e0cd22f8ff619c965da0596399a/68747470733a2f2f7261772e6769746875622e636f6d2f726f637363692f706574726f766963682f6d61737465722f706574726f766963682e706e67)](https://github.com/petrovich/petrovich_elixir)

[![Hex Version](https://img.shields.io/hexpm/v/petrovich_elixir.svg)](https://hex.pm/packages/petrovich_elixir) [![License](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)

Elixir library to inflect Russian first, last, and middle names.
Expand All @@ -17,6 +19,32 @@ end
```


## Usage

### Do I need to know russian to use it?

Yes, you will need some basic russian knowledge to work with this library.
You need to understand how [grammatical cases](https://en.wikipedia.org/wiki/Grammatical_case) work in russian language.

### API

```elixir
PetrovichElixir.firstname("Александр", :accusative, :male)
# => Александра

PetrovichElixir.middlename("Сергеевич", :accusative, :male)
# => Сергеевича

PetrovichElixir.lastname("Пушкин", :accusative, :male)
# => Пушкина
```


## Rules

This package uses [`petrovich-rules`](https://github.com/petrovich/petrovich-rules) as the source for all transformations. If you ever experience wrong result or other issues with the data itself, please open an issue [here](https://github.com/petrovich/petrovich-rules/issues).


## License

MIT. See [LICENSE](/LICENSE) for details.
Expand Down
2 changes: 2 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ use Mix.Config
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env}.exs"

if Mix.env == :test, do: import_config "test.exs"
5 changes: 5 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use Mix.Config

# Configure Petrovich to use `rules` submodule:
config :petrovich_elixir,
rules_dir: "rules"
7 changes: 6 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ defmodule PetrovichElixir.Mixfile do
#
# Type "mix help deps" for more examples and options
defp deps do
[{:ex_doc, ">= 0.0.0", only: :dev}]
[{:poison, "~> 3.1"},

# Dev and test dependencies:
{:credo, "~> 0.8", only: [:dev, :test], runtime: false},
{:dialyxir, "~> 0.5", only: [:dev], runtime: false},
{:ex_doc, ">= 0.0.0", only: :dev}]
end

defp description do
Expand Down
10 changes: 8 additions & 2 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
%{"earmark": {:hex, :earmark, "1.2.2", "f718159d6b65068e8daeef709ccddae5f7fdc770707d82e7d126f584cd925b74", [:mix], []},
"ex_doc": {:hex, :ex_doc, "0.16.1", "b4b8a23602b4ce0e9a5a960a81260d1f7b29635b9652c67e95b0c2f7ccee5e81", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]}}
%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
"credo": {:hex, :credo, "0.8.1", "137efcc99b4bc507c958ba9b5dff70149e971250813cbe7d4537ec7e36997402", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"},
"dialyxir": {:hex, :dialyxir, "0.5.0", "5bc543f9c28ecd51b99cc1a685a3c2a1a93216990347f259406a910cf048d1d7", [:mix], [], "hexpm"},
"earmark": {:hex, :earmark, "1.2.2", "f718159d6b65068e8daeef709ccddae5f7fdc770707d82e7d126f584cd925b74", [:mix], [], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.16.1", "b4b8a23602b4ce0e9a5a960a81260d1f7b29635b9652c67e95b0c2f7ccee5e81", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"},
"meck": {:hex, :meck, "0.8.4", "59ca1cd971372aa223138efcf9b29475bde299e1953046a0c727184790ab1520", [:make, :rebar], [], "hexpm"},
"mock": {:hex, :mock, "0.2.1", "bfdba786903e77f9c18772dee472d020ceb8ef000783e737725a4c8f54ad28ec", [:mix], [{:meck, "~> 0.8.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}}
1 change: 1 addition & 0 deletions rules
Submodule rules added at e5e673
8 changes: 0 additions & 8 deletions test/petrovich_elixir_test.exs

This file was deleted.

154 changes: 154 additions & 0 deletions test/petrovich_elixir_test/parser_test/firstname_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
defmodule PetrovichElixirTest.ParserTest.FirstName.Normal do
use ExUnit.Case

alias PetrovichElixir.Parser

setup do
values = %{
nomenative: [
{:male, "Никита", "Никита"},
{:female, "Кира", "Кира"}
],

genitive: [
{:male, "Никита", "Никиты"},
{:female, "Кира", "Киры"}
],

dative: [
{:male, "Никита", "Никите"},
{:female, "Кира", "Кире"}
],

accusative: [
{:male, "Никита", "Никиту"},
{:female, "Кира", "Киру"}
],

instrumental: [
{:male, "Никита", "Никитой"},
{:female, "Кира", "Кирой"}
],

prepositional: [
{:male, "Никита", "Никите"},
{:female, "Кира", "Кире"}
]
}
{:ok, values: values}
end

test "parses nomenative name", %{values: values} do
for {gender, name, result} <- values.nomenative do
assert Parser.parse(name, :firstname, :nomenative, gender) == result
end
end

test "parses genitive name", %{values: values} do
for {gender, name, result} <- values.genitive do
assert Parser.parse(name, :firstname, :genitive, gender) == result
end
end

test "parses dative name", %{values: values} do
for {gender, name, result} <- values.dative do
assert Parser.parse(name, :firstname, :dative, gender) == result
end
end

test "parses accusative name", %{values: values} do
for {gender, name, result} <- values.accusative do
assert Parser.parse(name, :firstname, :accusative, gender) == result
end
end

test "parses instrumental name", %{values: values} do
for {gender, name, result} <- values.instrumental do
assert Parser.parse(name, :firstname, :instrumental, gender) == result
end
end

test "parses prepositional name", %{values: values} do
for {gender, name, result} <- values.prepositional do
assert Parser.parse(name, :firstname, :prepositional, gender) == result
end
end
end


defmodule PetrovichElixirTest.ParserTest.FirstName.Exception do
use ExUnit.Case

alias PetrovichElixir.Parser

setup do
values = %{
nomenative: [
{:male, "Яша", "Яша"},
{:female, "Жизель", "Жизель"}
],

genitive: [
{:male, "Яша", "Яши"},
{:female, "Жизель", "Жизели"}
],

dative: [
{:male, "Яша", "Яше"},
{:female, "Жизель", "Жизели"}
],

accusative: [
{:male, "Яша", "Яшу"},
{:female, "Жизель", "Жизель"}
],

instrumental: [
{:male, "Яша", "Яшей"},
{:female, "Жизель", "Жизелью"}
],

prepositional: [
{:male, "Яша", "Яше"},
{:female, "Жизель", "Жизели"}
]
}
{:ok, values: values}
end

test "parses nomenative name", %{values: values} do
for {gender, name, result} <- values.nomenative do
assert Parser.parse(name, :firstname, :nomenative, gender) == result
end
end

test "parses genitive name", %{values: values} do
for {gender, name, result} <- values.genitive do
assert Parser.parse(name, :firstname, :genitive, gender) == result
end
end

test "parses dative name", %{values: values} do
for {gender, name, result} <- values.dative do
assert Parser.parse(name, :firstname, :dative, gender) == result
end
end

test "parses accusative name", %{values: values} do
for {gender, name, result} <- values.accusative do
assert Parser.parse(name, :firstname, :accusative, gender) == result
end
end

test "parses instrumental name", %{values: values} do
for {gender, name, result} <- values.instrumental do
assert Parser.parse(name, :firstname, :instrumental, gender) == result
end
end

test "parses prepositional name", %{values: values} do
for {gender, name, result} <- values.prepositional do
assert Parser.parse(name, :firstname, :prepositional, gender) == result
end
end
end
45 changes: 45 additions & 0 deletions test/petrovich_elixir_test/store_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
defmodule PetrovichElixirTest.StoreTest do
use ExUnit.Case

alias PetrovichElixir.Store

setup do
{status, _pid} = Store.start_link()

status
end

test "agent has all end values" do
values = Store.all()
assert map_size(values) == 3

for i <- ["firstname", "lastname", "middlename"] do
assert i in Map.keys(values)
end
end

test "agent get value" do
value = Store.get("lastname")
assert map_size(value) == 2

for i <- ["exceptions", "suffixes"] do
assert i in Map.keys(value)
end
end

# test "finds value" do
# name = "Никита"
# len = String.length(name)

# first_names = Store.get("firstname")
# for rule <- first_names["suffixes"] do
# for test <- rule["test"] do
# l = String.length(test)
# fits = String.slice(name, len - l, l)
# IO.inspect([test, fits])
# end
# end

# assert false
# end
end

0 comments on commit bf4ddb1

Please sign in to comment.