diff --git a/src/vending/core.clj b/src/vending/core.clj index 7b85f87..ebaa2ba 100644 --- a/src/vending/core.clj +++ b/src/vending/core.clj @@ -9,13 +9,13 @@ :change nil :output nil} ) -(def coin-values {:merk 1 :plack 0.25 :bawbee 0.10 :bodle 0.05}) +(def coin-values {:merk 100 :plack 25 :bawbee 10 :bodle 5}) (keys coin-values) (.indexOf (keys coin-values) :bodle) -(def item-prices {:caramel-wafer 0.65 :teacake 1 :snowball 1.5}) +(def item-prices {:caramel-wafer 65 :teacake 100 :snowball 150}) (defn coin-value [coin] (coin-values coin)) @@ -65,6 +65,8 @@ (defn subtract-denomination [list position] + "given a list of four numbers and a position, return a similar list with one subtracted + from the number at this position in the list" (cond (= (count list) position)(cons (- (first list) 1) (rest list)) true (cons (first list) (subtract-denomination (rest list) position)))) @@ -103,26 +105,29 @@ (apply in-make-change (map #(or % 0) (list amount merk plack bawbee bodle))) )) -(defn subtract-change [machine item-price change] - "subtract this change from this machine and return the machine" - (let [coins (:coins machine) - merk (:merk coins) - plack (:plack coins) - bawbee (:bawbee coins) - bodle (:bodle coins) - chance (make-change item-price merk plack bawbee bodle)]) - (assoc (dissoc machine :change) :change change)) -(defn make-change-machine [machine item-price change] - (let [ - tend (sum-coins (:tendered machine)) - change (make-change item-price (:merk tend) (:plack tend) (:bawbee tend) (:bodle tend))] - (cond (nil? change) machine) - true (assoc (dissoc (subtract-change machine item-price change) :change ) :change change ))) +(defn subtract-change [coin-stacks change] + "Return a copy of these coin-stacks with this change removed" + {:merk (- (:merk coin-stacks) (nth change 0)) + :plack (- (:plack coin-stacks) (nth change 1)) + :bawbee (- (:bawbee coin-stacks) (nth change 2)) + :bodle (- (:bodle coin-stacks) (nth change 3))}) + +(defn subtract-change-machine [machine change] + "return a copy of this machine which has this amount of change removed from its coins" + (let [coins (:coins machine)] + (assoc (dissoc machine :coins) :coins (subtract-change coins change)))) + +(defn make-change-machine [machine change] + "given this machine and these numbers of coins to remove, return a copy of the machine + with the coins removed" + (let [tend (sum-coins (:tendered machine))] + (cond (= change '(0 0 0 0)) machine) + true (assoc (dissoc (subtract-change-machine machine change) :change ) :change change ))) (defn remove-from-stock [machine item] - "TODO: This requires clever use of update-in" - machine) + "return a copy of this machine with one fewer of this item in stock" + (update-in machine [:items item] dec)) (defn deliver-item [machine item change] (make-change-machine @@ -135,12 +140,14 @@ (defn get-item [machine item] (let [item-price (item item-prices) - tend (sum-coins (:tendered machine)) - change (make-change item-price (:merk tend) (:plack tend) (:bawbee tend) (:bodle tend))] - (cond (>= 0 (item (:stock machine))) (message-machine (coin-return machine) (str "Sorry, " item " not in stock")) - (<= (coins-value (:tendered machine)) item-price) (message-machine machine "Please insert more money") - (empty? change) (message-machine (coin-return machine) "Sorry, I don't have enough change.") - true (message-machine (deliver-item machine item change) (str "Enjoy your " item))))) + coins (:coins machine) + tendered (coins-value (:tendered machine)) + change (make-change (- tendered item-price) (:merk coins) (:plack coins) (:bawbee coins) (:bodle coins))] + (print change) + (cond (>= 0 (item (:stock machine))) (message-machine (coin-return machine) (str "Sorry, " item " not in stock")) + (<= tendered item-price) (message-machine machine "Please insert more money") + (= change '(0 0 0 0)) (message-machine (coin-return machine) "Sorry, I don't have enough change.") + true (message-machine (deliver-item machine item change) (str "Enjoy your " item))))) (defn get-caramel-wafer [machine] (get-item machine :caramel-wafer)) diff --git a/test/vending/test/core.clj b/test/vending/test/core.clj new file mode 100644 index 0000000..e0ba36b --- /dev/null +++ b/test/vending/test/core.clj @@ -0,0 +1,68 @@ +(ns vending.test.core + (:use clojure.test + ring.mock.request + vending.core)) + +(defn member? + "true if seq contains elm" + [seq elm] + (some #(= elm %) seq)) + + +(deftest test-add-coin + (testing + "Test adding coins to machine" + (let [machine (make-default-machine) + merk-machine (add-coin machine :merk) + plack-machine (add-coin machine :plack) + bawbee-machine (add-coin machine :bawbee) + bodle-machine (add-coin machine :bodle) + all-machine (add-coin (add-coin (add-coin (add-coin machine :merk) :plack) :bawbee) :bodle) ] + (is (member? (:tendered merk-machine) :merk) "after adding a merk, a merk should be present") + (is (member? (:tendered all-machine) :merk) "after adding a merk, a merk should be present") + (is (member? (:tendered plack-machine) :plack) "after adding a plack, a plack should be present") + (is (member? (:tendered all-machine) :plack) "after adding a plack, a plack should be present") + (is (member? (:tendered bawbee-machine) :bawbee) "after adding a bawbee, a bawbee should be present") + (is (member? (:tendered all-machine) :bawbee) "after adding a bawbee, a bawbee should be present") + (is (member? (:tendered bodle-machine) :bodle) "after adding a bodle, a bodle should be present") + (is (member? (:tendered all-machine) :bodle) "after adding a merk, a merk should be present") + (is (nil? (:tendered machine)) "No coins should leak through into the base machine"))) + + (testing + "coin-return should return all coins added" + (let [machine (make-default-machine) + all-machine (add-coin (add-coin (add-coin (add-coin machine :merk) :plack) :bawbee) :bodle) + return-machine (coin-return all-machine)] + (is (= (:message return-machine)) "Coins returned") + (is (= (:tendered all-machine) (:change return-machine)) "All coins should be returned") + )) + + (testing + "summing coins" + (let [coins1 (sum-coins (list :merk :plack :bawbee :bodle)) + coins2 (sum-coins (list :merk :plack :bawbee :bodle :merk :plack :bawbee :bodle))] + (= (:merk coins1 1) "after adding one merk, one merk should be present") + (= (:merk coins2 2) "after adding two merks, two merks should be present") + )) + + (testing + "making appropriate change" + (let [no-change (make-change 0 5 5 5 5) + ten-change (make-change 10 5 5 5 5) + all-change (make-change 140 5 5 5 5)] + (is (= no-change '(0 0 0 0)) "one hundred units of change should be satisfied with one merk") + (is (= all-change '(1 1 1 1)) "140 units of change should be satisfied with one coin of each denomination") + (is (or (= ten-change '(0 0 1 0)) (= ten-change '(0 0 0 2))) "ten change could be satisfied with one bawbee or two bodles"))) + + (testing + "removing change from machine" + (let [machine (make-default-machine) + changed (make-change-machine machine '(1 1 1 1)) + emptied (make-change-machine machine '(1 4 4 4))] + (is (= (vals (:coins changed)) '(0 3 3 3)) "each coin slot should be decremented by one") + (is (= (vals (:coins emptied)) '(0 0 0 0)) "each coin slot should be empty (contain zero)") + )) + ) + + (make-change-machine (make-default-machine) '( 1 1 1 1)) + diff --git a/test/vending/test/handler.clj b/test/vending/test/handler.clj index 69b3d09..6783b17 100644 --- a/test/vending/test/handler.clj +++ b/test/vending/test/handler.clj @@ -7,8 +7,7 @@ (testing "main route" (let [response (app (request :get "/"))] (is (= (:status response) 200)) - (is (= (:body response) - "\n
\n