diff --git a/lfe/README.md b/lfe/README.md new file mode 100644 index 00000000..872a6b7a --- /dev/null +++ b/lfe/README.md @@ -0,0 +1,10 @@ +GildedRose +===== + +It is assumed you have installed Erlang and rebar3. + +To run the tests do: `rebar3 as test lfe ltest`. + +Checkout the [LFEUnit Emacs plugin](https://github.com/mdbergmann/emacs-lfeunit) when you're on Emacs. + +Otherwise the usual rebar3 things apply. diff --git a/lfe/include/gilded-rose-item.lfe b/lfe/include/gilded-rose-item.lfe new file mode 100644 index 00000000..f9ab5191 --- /dev/null +++ b/lfe/include/gilded-rose-item.lfe @@ -0,0 +1,4 @@ +;;; Item + +(defrecord item + name sellin quality) diff --git a/lfe/rebar.config b/lfe/rebar.config new file mode 100644 index 00000000..5a7ed9a4 --- /dev/null +++ b/lfe/rebar.config @@ -0,0 +1,49 @@ +{erl_opts, [debug_info]}. + +{deps, [ + {lfe, "2.0.1"} +]}. + +{plugins, [ + {rebar3_lfe, "0.4.0"} +]}. + +{lfe, [ + {main, "scripts/main.lfe"} +]}. + +{provider_hooks, [ + {pre, [{compile, {lfe, compile}}]} +]}. + +{xref_checks,[ + undefined_function_calls,undefined_functions,locals_not_used, + deprecated_function_calls,deprecated_functions +]}. + +{profiles, [ + {test, [ + {deps, [ + {proper, "1.3.0"} + ]}, + {plugins, [ + {rebar3_proper, "0.12.0"} + ]}, + {eunit_opts, [verbose]}, + {erl_opts, [{src_dirs, ["src", "test"]}]} + ]} +]}. + +{alias, [ + {coverage, [ + {proper, "-c"}, + {cover, "-v --min_coverage=0"} + ]}, + {check, [ + compile, + xref, + %%dialyzer, + eunit, + coverage + ]} +]}. diff --git a/lfe/scripts/main.lfe b/lfe/scripts/main.lfe new file mode 100644 index 00000000..b9c4c96e --- /dev/null +++ b/lfe/scripts/main.lfe @@ -0,0 +1,10 @@ +#! /usr/bin/env lfescript + +;;; -------------------- +;;; entry point function +;;; -------------------- + +(defun main (args) + (let ((script-name (escript:script_name))) + (io:format "Running script '~s' with args ~p ...~n" `(,script-name ,args)) + (io:format "~p~n" `(,(gilded-rose:my-fun))))) diff --git a/lfe/src/gilded-rose.app.src b/lfe/src/gilded-rose.app.src new file mode 100644 index 00000000..04d9b067 --- /dev/null +++ b/lfe/src/gilded-rose.app.src @@ -0,0 +1,14 @@ +{application, 'gilded-rose', [ + {description, "A run-ready LFE script"}, + {vsn, "0.1"}, + {registered, []}, + {applications, [ + kernel, + stdlib + ]}, + {env,[]}, + {modules, []}, + + {licenses, ["Apache 2.0"]}, + {links, []} + ]}. diff --git a/lfe/src/gilded-rose.lfe b/lfe/src/gilded-rose.lfe new file mode 100644 index 00000000..a135ecc7 --- /dev/null +++ b/lfe/src/gilded-rose.lfe @@ -0,0 +1,133 @@ +;; Hi and welcome to team Gilded Rose. As you know, we are a small inn +;; with a prime location in a prominent city ran by a friendly +;; innkeeper named Allison. We also buy and sell only the finest goods. +;; Unfortunately, our goods are constantly degrading in (item-quality item) as they +;; approach their sell by date. We have a system in place that updates +;; our inventory for us. It was developed by a no-nonsense type named +;; Leeroy, who has moved on to new adventures. Your task is to add the +;; new feature to our system so that we can begin selling a new +;; category of items. + +;; First an introduction to our system: +;; All items have a SellIn value which denotes the number of days we have to sell the item +;; All items have a Quality value which denotes how valuable the item is +;; At the end of each day our system lowers both values for every item +;; Pretty simple, right? Well this is where it gets interesting: +;; Once the sell by date has passed, Quality degrades twice as fast +;; The Quality of an item is never negative +;; "Aged Brie" actually increases in Quality the older it gets +;; The Quality of an item is never more than 50 +;; "Sulfuras", being a legendary item, never has to be sold or decreases in Quality +;; "Backstage passes", like aged brie, increases in Quality as it's +;; SellIn value approaches; Quality increases by 2 when there are 10 +;; days or less and by 3 when there are 5 days or less but Quality +;; drops to 0 after the concert + +;; We have recently signed a supplier of conjured items. This requires an update to our system: +;; "Conjured" items degrade in Quality twice as fast as normal items +;; Feel free to make any changes to the UpdateQuality method and add +;; any new code as long as everything still works correctly. However, +;; do not alter the Item class or Items property as those belong to the +;; goblin in the corner who will insta-rage and one-shot you as he +;; doesn't believe in shared code ownership (you can make the +;; UpdateQuality method and Items property static if you like, we'll +;; cover for you). +;; Just for clarification, an item can never have its Quality increase +;; above 50, however "Sulfuras" is a legendary item and as such its +;; Quality is 80 and it never alters. + +;; https://github.com/emilybache/GildedRose-Refactoring-Kata + +;; LFE version by Manfred Bergmann, 2022 + +;;; ================================================================ +;;; Code + +(defmodule gilded-rose + (export all)) + +(include-lib "include/gilded-rose-item.lfe") + +;; update-quality + +(defun update-quality (items) + (lists:map #'update-item/1 items)) + +(defun update-item (item) + (let* ((item (if (and (not (string:equal (item-name item) + "Aged Brie")) + (not (string:equal (item-name item) + "Backstage passes to a TAFKAL80ETC concert"))) + (if (> (item-quality item) 0) + (if (not (string:equal (item-name item) + "Sulfuras, Hand of Ragnaros")) + (set-item-quality item (- (item-quality item) 1)) + item) + item) + (if (< (item-quality item) 50) + (set-item-quality item (+ (item-quality item) 1)) + (if (string:equal (item-name item) + "Backstage passes to a TAFKAL80ETC concert") + (if (< (item-sellin item) 11) + (if (< (item-quality item) 50) + (set-item-quality item (+ (item-quality item) 1)) + item) + item) + (if (< (item-sellin item) 6) + (if (< (item-quality item) 50) + (set-item-quality item (+ (item-quality item) 1)) + item) + item))))) + (item (if (not (string:equal (item-name item) + "Sulfuras, Hand of Ragnaros")) + (set-item-sellin item (- (item-sellin item) 1)) + item))) + (if (< (item-sellin item) 0) + (if (not (string:equal (item-name item) + "Aged Brie")) + (if (not (string:equal (item-name item) + "Backstage passes to a TAFKAL80ETC concert")) + (if (> (item-quality item) 0) + (if (not (string:equal (item-name item) + "Sulfuras, Hand of Ragnaros")) + (set-item-quality item (- (item-quality item) 1)) + item) + item) + (set-item-quality item (- (item-quality item) (item-quality item)))) + (if (< (item-quality item) 50) + (set-item-quality item (+ (item-quality item) 1)) + item)) + item))) + +;;; Example + +(defun print-item (item) + (io:format "~s ~b ~b~n" (list (item-name item) (item-sellin item) (item-quality item)))) + +(defun print-day (day items) + (io:format "-------- day ~b --------~n" (list day)) + (io:format "name, sellin, quality~n") + (lists:foreach #'print-item/1 items) + (io:format "~n")) + +(defrecord gilded-rose items) + +(defun run-gilded-rose (days) + (io:format "OMGHAI!~n") + (let ((items (list (make-item name "+5 Dexterity Vest" sellin 10 quality 20) + (make-item name "Aged Brie" sellin 2 quality 0) + (make-item name "Elixir of the Mongoose" sellin 5 quality 7) + (make-item name "Sulfuras, Hand of Ragnaros" sellin 0 quality 80) + (make-item name "Sulfuras, Hand of Ragnaros" sellin -1 quality 80) + (make-item name "Backstage passes to a TAFKAL80ETC concert" sellin 15 quality 20) + (make-item name "Backstage passes to a TAFKAL80ETC concert" sellin 10 quality 49) + (make-item name "Backstage passes to a TAFKAL80ETC concert" sellin 5 quality 49) + ;; this conjured item does not work properly yet + (make-item name "Conjured Mana Cake" sellin 3 quality 6)))) + + (lists:foldl (lambda (day gr) + (print-day day (gilded-rose-items gr)) + (make-gilded-rose items (update-quality (gilded-rose-items gr)))) + (make-gilded-rose items items) + (lists:seq 0 days)))) + diff --git a/lfe/test/gilded-rose-test.lfe b/lfe/test/gilded-rose-test.lfe new file mode 100644 index 00000000..2e17714a --- /dev/null +++ b/lfe/test/gilded-rose-test.lfe @@ -0,0 +1,13 @@ +(defmodule gilded-rose-test + (behaviour ltest-unit) + (export all) + (import (from gilded-rose + (update-quality 1)))) + +(include-lib "ltest/include/ltest-macros.lfe") + +(include-lib "include/gilded-rose-item.lfe") + +(deftest update-quality-test + (is-equal "fixme" (item-name (car (update-quality + (list (make-item name "foo" sellin 0 quality 0)))))))