Initial commit

This commit is contained in:
Correl Roush 2012-05-04 08:18:08 -04:00
commit a68168d651
9 changed files with 232 additions and 0 deletions

14
Makefile Normal file
View file

@ -0,0 +1,14 @@
.PHONY: all deps compile test clean
REBAR=./rebar
all: deps compile
deps:
@$(REBAR) get-deps
compile: deps
@$(REBAR) compile
test:
@$(REBAR) skip_deps=true eunit
clean:
@$(REBAR) clean

4
include/riichi.hrl Normal file
View file

@ -0,0 +1,4 @@
-record(tile, {
suit,
value
}).

BIN
rebar vendored Executable file

Binary file not shown.

1
rebar.config Normal file
View file

@ -0,0 +1 @@
{cover_enabled, true}.

12
src/riichi.app.src Normal file
View file

@ -0,0 +1,12 @@
{application, riichi,
[
{description, ""},
{vsn, "1"},
{registered, []},
{applications, [
kernel,
stdlib
]},
{mod, { riichi_app, []}},
{env, []}
]}.

73
src/riichi.erl Normal file
View file

@ -0,0 +1,73 @@
-module(riichi).
-include("riichi.hrl").
-export([
is_valid_tile/1,
dora/1,
nearest/2,
score/3
]).
is_valid_tile(#tile{suit=dragon, value=Value}) ->
lists:member(Value, [white, green, red]);
is_valid_tile(#tile{suit=wind, value=Value}) ->
lists:member(Value, [east, south, west, north]);
is_valid_tile(#tile{suit=Suit, value=Value}) ->
ValidSuit = lists:member(Suit, [pin, sou, man]),
ValidValue = is_integer(Value) and (Value > 0) and (Value < 10),
ValidSuit and ValidValue;
is_valid_tile(_) ->
false.
dora(#tile{suit=dragon, value=Value}=Indicator) ->
case Value of
white -> Indicator#tile{value=green};
green -> Indicator#tile{value=red};
red -> Indicator#tile{value=white}
end;
dora(#tile{suit=wind, value=Value}=Indicator) ->
case Value of
east -> Indicator#tile{value=south};
south -> Indicator#tile{value=west};
west -> Indicator#tile{value=north};
north -> Indicator#tile{value=east}
end;
dora(#tile{value=Value}=Indicator) ->
case is_valid_tile(Indicator) of
false ->
throw({error, invalid_tile});
_ ->
if
Value == 9 -> Indicator#tile{value=1};
true -> Indicator#tile{value=Value + 1}
end
end.
nearest(Num, To) when Num rem To == 0 ->
Num;
nearest(Num, To) ->
Num - (Num rem To) + To.
score(_Fu, Yaku, Limit) when (Yaku >= 5) and (Limit == true) ->
if
Yaku < 6 ->
2000;
Yaku < 8 ->
3000;
Yaku < 11 ->
4000;
Yaku < 14 ->
6000;
true ->
8000
end;
score(Fu, Yaku, Limit) ->
Score = nearest(Fu * round(math:pow(2, 2 + Yaku)), 100),
if
Limit and (Score > 2000) ->
2000;
true ->
Score
end.

16
src/riichi_app.erl Normal file
View file

@ -0,0 +1,16 @@
-module(riichi_app).
-behaviour(application).
%% Application callbacks
-export([start/2, stop/1]).
%% ===================================================================
%% Application callbacks
%% ===================================================================
start(_StartType, _StartArgs) ->
riichi_sup:start_link().
stop(_State) ->
ok.

28
src/riichi_sup.erl Normal file
View file

@ -0,0 +1,28 @@
-module(riichi_sup).
-behaviour(supervisor).
%% API
-export([start_link/0]).
%% Supervisor callbacks
-export([init/1]).
%% Helper macro for declaring children of supervisor
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
%% ===================================================================
%% API functions
%% ===================================================================
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%% ===================================================================
%% Supervisor callbacks
%% ===================================================================
init([]) ->
{ok, { {one_for_one, 5, 10}, []} }.

84
test/riichi_tests.erl Normal file
View file

@ -0,0 +1,84 @@
-module(riichi_tests).
-include("riichi.hrl").
-include_lib("eunit/include/eunit.hrl").
valid_tile_dragon_test_() ->
[?_assert(riichi:is_valid_tile(#tile{suit=dragon, value=Value})) || Value <- [white, green, red]].
valid_tile_wind_test_() ->
[?_assert(riichi:is_valid_tile(#tile{suit=wind, value=Value})) || Value <- [east, south, west, north]].
valid_tile_suit_test_() ->
[?_assert(riichi:is_valid_tile(#tile{suit=Suit, value=Value})) || Suit <- [pin, sou, man], Value <- lists:seq(1,9)].
invalid_tile_test_() ->
[?_assertNot(riichi:is_valid_tile(Tile))
|| Tile <-
[
#tile{suit=badsuit, value=1},
#tile{suit=dragon, value=hidden},
#tile{suit=wind, value=broken},
#tile{suit=pin, value=0},
#tile{suit=sou, value=-1},
#tile{suit=man, value=10},
not_a_tile
]
].
dora_dragon_test_() ->
[?_assertEqual(riichi:dora(#tile{suit=dragon, value=Indicator}), #tile{suit=dragon, value=Dora})
|| {Indicator, Dora} <-
[
{white, green},
{green, red},
{red, white}
]
].
dora_wind_test_() ->
[?_assertEqual(riichi:dora(#tile{suit=wind, value=Indicator}), #tile{suit=wind, value=Dora})
|| {Indicator, Dora} <-
[
{east, south},
{south, west},
{west, north},
{north, east}
]
].
dora_suit_test_() ->
[?_assertEqual(riichi:dora(#tile{suit=Suit, value=Indicator}), #tile{suit=Suit, value=Dora})
||
{Indicator, Dora} <-
[{1,2}, {2,3}, {3,4}, {4,5}, {5,6}, {6,7}, {7,8}, {8,9}, {9,1}],
Suit <- [pin, sou, man]
].
dora_invalid_test() ->
?assertException(throw, {error, invalid_tile}, riichi:dora(#tile{suit=pin, value=9001})).
nearest_test_() ->
[?_assertEqual(riichi:nearest(Val, 10), 80) || Val <- lists:seq(71,80)].
score_yaku_limit_test_() ->
[?_assertEqual(riichi:score(30, Yaku, true), Score)
|| {Yaku, Score} <-
[
{ 5, 2000},
{ 6, 3000},
{ 7, 3000},
{ 8, 4000},
{ 9, 4000},
{10, 4000},
{11, 6000},
{12, 6000},
{13, 6000},
{14, 8000},
{1000, 8000}
]
].
score_fu_limit_test() ->
?assertEqual(riichi:score(80, 4, true), 2000).
score_rounded_test() ->
?assertEqual(riichi:score(20, 1, true), 200). % 160 rounded up