diff --git a/erlang/.gitignore b/erlang/.gitignore new file mode 100644 index 00000000..088157b2 --- /dev/null +++ b/erlang/.gitignore @@ -0,0 +1,2 @@ +/_build +/*.txt \ No newline at end of file diff --git a/erlang/README.md b/erlang/README.md new file mode 100644 index 00000000..2f8af532 --- /dev/null +++ b/erlang/README.md @@ -0,0 +1,11 @@ +# Erlang + +## Prerequisites + +- Erlang/OTP 20 or later + +## Running Tests + +``` +./rebar3 eunit +``` diff --git a/erlang/include/gilded_rose.hrl b/erlang/include/gilded_rose.hrl new file mode 100644 index 00000000..4b74d598 --- /dev/null +++ b/erlang/include/gilded_rose.hrl @@ -0,0 +1,5 @@ +-record(item, { + name :: binary(), + sell_in = 0 :: integer(), + quality = 0 :: integer() +}). diff --git a/erlang/rebar.config b/erlang/rebar.config new file mode 100644 index 00000000..60a00f5d --- /dev/null +++ b/erlang/rebar.config @@ -0,0 +1,2 @@ +{erl_opts, [warnings_as_errors]}. +{eunit_opts, [verbose]}. diff --git a/erlang/rebar3 b/erlang/rebar3 new file mode 100755 index 00000000..f0b1ba78 Binary files /dev/null and b/erlang/rebar3 differ diff --git a/erlang/src/gilded_rose.app.src b/erlang/src/gilded_rose.app.src new file mode 100644 index 00000000..4c47019a --- /dev/null +++ b/erlang/src/gilded_rose.app.src @@ -0,0 +1 @@ +{application, gilded_rose, [{vsn, "0.1"}]}. diff --git a/erlang/src/gilded_rose.erl b/erlang/src/gilded_rose.erl new file mode 100644 index 00000000..98b08e95 --- /dev/null +++ b/erlang/src/gilded_rose.erl @@ -0,0 +1,87 @@ +-module(gilded_rose). + +-include("gilded_rose.hrl"). + +-export([ + update_quality/1 +]). + +-spec update_quality([#item{}]) -> [#item{}]. +update_quality(Items) -> + lists:map(fun update_item/1, Items). + +-spec update_item(#item{}) -> #item{}. +update_item(Item = #item{name = Name}) -> + Item1 = if + Name /= "Aged Brie" andalso Name /= "Backstage passes to a TAFKAL80ETC concert" -> + if + Item#item.quality > 0 -> + if + Name /= "Sulfuras, Hand of Ragnaros" -> + Item#item{quality = Item#item.quality - 1}; + true -> + Item + end; + true -> + Item + end; + true -> + if + Item#item.quality < 50 -> + Item2 = Item#item{quality = Item#item.quality + 1}, + if + Name == "Backstage passes to a TAFKAL80ETC concert" -> + Item3 = if + Item2#item.sell_in < 11 -> + if + Item2#item.quality < 50 -> + Item2#item{quality = Item2#item.quality + 1}; + true -> Item2 + end; + true -> Item2 + end, + if + Item3#item.sell_in < 6 -> + if + Item3#item.quality < 50 -> + Item3#item{quality = Item3#item.quality + 1}; + true -> Item3 + end; + true -> Item3 + end; + true -> Item2 + end; + true -> Item + end + end, + Item4 = if + Name /= "Sulfuras, Hand of Ragnaros" -> + Item1#item{sell_in = Item1#item.sell_in - 1}; + true -> Item1 + end, + if + Item4#item.sell_in < 0 -> + if + Name /= "Aged Brie" -> + if + Name /= "Backstage passes to a TAFKAL80ETC concert" -> + if + Item4#item.quality > 0 -> + if + Name /= "Sulfuras, Hand of Ragnaros" -> + Item4#item{quality = Item4#item.quality - 1}; + true -> Item4 + end; + true -> Item4 + end; + true -> Item4#item{quality = Item4#item.quality - Item4#item.quality} + end; + true -> + if + Item4#item.quality < 50 -> + Item4#item{quality = Item4#item.quality + 1}; + true -> Item4 + end + end; + true -> Item4 + end. diff --git a/erlang/test/gilded_rose_tests.erl b/erlang/test/gilded_rose_tests.erl new file mode 100644 index 00000000..a05c7f52 --- /dev/null +++ b/erlang/test/gilded_rose_tests.erl @@ -0,0 +1,44 @@ +-module(gilded_rose_tests). + +-include("gilded_rose.hrl"). +-include_lib("eunit/include/eunit.hrl"). + +-define(ITEMS, [ + #item{name = "+5 Dexterity Vest", sell_in = 10, quality = 20}, + #item{name = "Aged Brie", sell_in = 2, quality = 0}, + #item{name = "Elixir of the Mongoose", sell_in = 5, quality = 7}, + #item{name = "Sulfuras, Hand of Ragnaros", sell_in = 0, quality = 80}, + #item{name = "Sulfuras, Hand of Ragnaros", sell_in = -1, quality = 80}, + #item{name = "Backstage passes to a TAFKAL80ETC concert", sell_in = 15, quality = 20}, + #item{name = "Backstage passes to a TAFKAL80ETC concert", sell_in = 10, quality = 49}, + #item{name = "Backstage passes to a TAFKAL80ETC concert", sell_in = 5, quality = 49}, + #item{name = "Conjured Mana Cake", sell_in = 3, quality = 6} +]). + +golden_master_test() -> + Days = 30, + {ok, IoDevice} = file:open("actual_output.txt", [write]), + try + lists:foldl(fun(Day, Items) -> + io:format(IoDevice, "-------- day ~p --------~n", [Day]), + io:format(IoDevice, "name, sellIn, quality~n", []), + lists:foreach(fun(#item{name = Name, sell_in = SellIn, quality = Quality}) -> + io:format(IoDevice, "~s, ~p, ~p~n", [Name, SellIn, Quality]) + end, Items), + io:nl(IoDevice), + gilded_rose:update_quality(Items) + end, ?ITEMS, lists:seq(0, Days - 1)) + after + file:close(IoDevice) + end, + case file:read_file("expected_output.txt") of + {ok, ExpectedFile} -> + {ok, ActualFile} = file:read_file("actual_output.txt"), + ?assertEqual(ExpectedFile, ActualFile); + {error, Reason} -> + ?debugFmt("Could not read file 'expected_output.txt': ~p", [Reason]) + end. + +update_quality_test_() -> [ + {"first test", ?_assertMatch([#item{}], gilded_rose:update_quality([#item{}]))} +].