-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds lib/ folder ignored for some reason
- Loading branch information
Showing
10 changed files
with
262 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,4 @@ erl_crash.dump | |
*.beam | ||
|
||
#### custom #### | ||
doc/ | ||
/doc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
defmodule PetrovichElixir do | ||
@moduledoc """ | ||
Documentation for Petrovich. | ||
Elixir library to inflect Russian first, last, and middle names. | ||
""" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
defmodule PetrovichElixir.Applier do | ||
@moduledoc """ | ||
Applies rules on value. | ||
This module applies inflection rules on raw values. | ||
It is tightly coupled with `Parser`, which supplies the rules. | ||
""" | ||
|
||
@rules %{ | ||
genitive: 0, | ||
dative: 1, | ||
accusative: 2, | ||
instrumental: 3, | ||
prepositional: 4, | ||
} | ||
|
||
def apply(data, case_, %{"mods" => mods}) do | ||
mod = Enum.at(mods, @rules[case_]) | ||
apply_mod(mod, data) | ||
end | ||
|
||
defp apply_mod(".", data), do: data | ||
defp apply_mod(mod, data) do | ||
case count_replaces(mod) do | ||
0 -> data <> mod | ||
_ -> replace(mod, data) | ||
end | ||
end | ||
|
||
defp replace(mod, data) do | ||
replaces = count_replaces(mod) | ||
length = String.length(data) | ||
|
||
root = String.slice(data, 0, length - replaces) | ||
root <> String.replace(mod, "-", "") | ||
end | ||
|
||
defp count_replaces(mod) do | ||
mod | ||
|> String.graphemes | ||
|> Enum.reduce(%{}, fn(letter, acc) -> | ||
Map.update(acc, letter, 1, &(&1 + 1)) | ||
end) | ||
|> Map.get("-", 0) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
defmodule PetrovichElixir.Config do | ||
@moduledoc """ | ||
Provides application/system environment variable lookup at runtime | ||
""" | ||
|
||
@doc """ | ||
Returns the requested variable | ||
""" | ||
|
||
@spec get_env(atom, atom, atom | map) :: term | ||
def get_env(application, key, default \\ nil) do | ||
application | ||
|> Application.get_env(key, default) | ||
|> _get_env() | ||
end | ||
|
||
defp _get_env({:system, env_variable}), do: System.get_env(env_variable) | ||
defp _get_env(value), do: value | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
defmodule PetrovichElixir.Detector do | ||
@moduledoc """ | ||
Guesses the gender by person's name. | ||
""" | ||
|
||
@doc """ | ||
Returns gender from person's name | ||
""" | ||
def detect_gender(values, type) do | ||
|
||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
defmodule PetrovichElixir.Parser do | ||
@moduledoc """ | ||
Parser receives the name and case to infect it to. | ||
Then it parses the rules to find the appropriate modifications. | ||
It then calls `Applier` to modify the value. | ||
""" | ||
|
||
alias PetrovichElixir.{NameStore, Applier} | ||
|
||
def parse(data, _, :nomenative, _), do: data | ||
def parse(data, type, case_, gender) do | ||
apply_rule(data, to_string(type), case_, to_string(gender)) | ||
end | ||
|
||
defp apply_rule(values, type, case_, gender) do | ||
NameStore.start_link() | ||
|
||
values | ||
|> String.split("-") | ||
|> Enum.map(fn(item) -> prepare_value(item, type, case_, gender) end) | ||
|> Enum.join("-") | ||
end | ||
|
||
defp prepare_value(value, type, case_, gender) do | ||
%{"exceptions" => exceptions, | ||
"suffixes" => suffixes} = NameStore.get(type) | ||
|
||
value | ||
|> String.downcase | ||
|> maybe_exception(gender, exceptions) | ||
|> maybe_rule(gender, suffixes) | ||
|> case do | ||
{:error, _} -> value | ||
{:ok, res} -> Applier.apply(value, case_, res) | ||
end | ||
end | ||
|
||
defp maybe_exception(name, gender, exceptions) do | ||
exceptions | ||
|> Enum.filter(fn(item) -> fits?(:e, name, gender, item) end) | ||
|> pick_one(name) | ||
end | ||
|
||
defp maybe_rule({:ok, rule}, _, _), do: {:ok, rule} | ||
defp maybe_rule({:error, name}, gender, suffixes) do | ||
suffixes | ||
|> Enum.filter(fn(item) -> fits?(:r, name, gender, item) end) | ||
|> pick_one(name) | ||
end | ||
|
||
defp fits?(:e, name, gender, rule) do | ||
gender?(gender, rule) and name in rule["test"] | ||
end | ||
defp fits?(:r, name, gender, rule) do | ||
name_len = String.length(name) | ||
|
||
gender?(gender, rule) and Enum.any?(rule["test"], fn(test) -> | ||
test_len = String.length(test) | ||
test == String.slice(name, name_len - test_len, test_len) | ||
end) | ||
end | ||
|
||
defp gender?(gender, rule) do | ||
gender == rule["gender"] or rule["gender"] == "androgynous" | ||
end | ||
|
||
defp pick_one(items, name) do | ||
items | ||
|> Enum.at(0) | ||
|> case do | ||
nil -> {:error, name} | ||
rule -> {:ok, rule} | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
defmodule PetrovichElixir.Petrovich do | ||
@moduledoc """ | ||
Public interface to all the functions. | ||
It can inflect first, middle, and last names. | ||
It also can detect gender by name. | ||
""" | ||
|
||
alias PetrovichElixir.Parser | ||
|
||
@default_gender :androgynous | ||
|
||
def firstname(name, case_, gender \\ @default_gender) do | ||
Parser.parse(name, :firstname, case_, gender) | ||
end | ||
|
||
def middlename(name, case_, gender \\ @default_gender) do | ||
Parser.parse(name, :middlename, case_, gender) | ||
end | ||
|
||
def lastname(name, case_, gender \\ @default_gender) do | ||
Parser.parse(name, :lastname, case_, gender) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
defmodule PetrovichElixir.Store do | ||
@moduledoc """ | ||
This module implements basic functionality for different agents. | ||
This module provides a simple macro, when it is used | ||
it inserts all the required `Agent`'s methods inside the | ||
caller module. | ||
""" | ||
|
||
alias PetrovichElixir.Config | ||
|
||
defmacro __using__(options) do | ||
caller = __CALLER__.module | ||
|
||
quote location: :keep, bind_quoted: [options: options, caller: caller] do | ||
@setting Keyword.get(options, :setting) | ||
|
||
def start_link do | ||
Agent.start_link(fn -> | ||
load_values() end, name: unquote(caller)) | ||
end | ||
|
||
def stop do | ||
Agent.stop(unquote(caller)) | ||
end | ||
|
||
def get(key) do | ||
Agent.get(unquote(caller), fn(state) -> | ||
Map.get(state, key) | ||
end) | ||
end | ||
|
||
def all do | ||
Agent.get(unquote(caller), fn(state) -> | ||
state | ||
end) | ||
end | ||
|
||
defp load_values do | ||
:petrovich_elixir | ||
|> Config.get_env(@setting) | ||
|> File.read! | ||
|> Poison.decode! | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
defmodule PetrovichElixir.GenderStore do | ||
@moduledoc """ | ||
This module stores different genders. | ||
It is then used to guess the gender by name, | ||
last name or middle name. | ||
""" | ||
|
||
use PetrovichElixir.Store, setting: :gender_path | ||
|
||
@name __MODULE__ | ||
|
||
def get(key1, key2) do | ||
Agent.get(@name, fn(state) -> | ||
state | ||
|> Map.get(key1) | ||
|> Map.get(key2) | ||
end) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
defmodule PetrovichElixir.NameStore do | ||
@moduledoc """ | ||
This module stores different rules on how to inflect values. | ||
It stores rules for first, middle and last names. | ||
""" | ||
|
||
use PetrovichElixir.Store, setting: :rules_path | ||
end |