diff --git a/docs/cloverage/the_great_game/merchants/merchant_utils.clj.html b/docs/cloverage/the_great_game/merchants/merchant_utils.clj.html index 70cd0f3..8774b44 100644 --- a/docs/cloverage/the_great_game/merchants/merchant_utils.clj.html +++ b/docs/cloverage/the_great_game/merchants/merchant_utils.clj.html @@ -64,13 +64,13 @@ <span class="not-tracked" title="0 out of 0 forms covered"> 020 [merchant world] </span><br/> -<span class="partial" title="3 out of 4 forms covered"> +<span class="covered" title="4 out of 4 forms covered"> 021 (let [m (cond </span><br/> <span class="covered" title="3 out of 3 forms covered"> 022 (keyword? merchant) </span><br/> -<span class="not-covered" title="0 out of 5 forms covered"> +<span class="covered" title="5 out of 5 forms covered"> 023 (-> world :merchants merchant) </span><br/> <span class="covered" title="3 out of 3 forms covered"> @@ -79,8 +79,8 @@ <span class="covered" title="1 out of 1 forms covered"> 025 merchant) </span><br/> -<span class="covered" title="3 out of 3 forms covered"> - 026 cargo (:stock m)] +<span class="covered" title="8 out of 8 forms covered"> + 026 cargo (or (:stock m) {})] </span><br/> <span class="covered" title="3 out of 3 forms covered"> 027 (reduce @@ -94,7 +94,7 @@ <span class="covered" title="3 out of 3 forms covered"> 030 (map </span><br/> -<span class="not-covered" title="0 out of 12 forms covered"> +<span class="covered" title="12 out of 12 forms covered"> 031 #(* (cargo %) (-> world :commodities % :weight)) </span><br/> <span class="covered" title="3 out of 3 forms covered"> @@ -124,7 +124,7 @@ <span class="covered" title="3 out of 3 forms covered"> 040 (keyword? merchant) </span><br/> -<span class="not-covered" title="0 out of 5 forms covered"> +<span class="covered" title="5 out of 5 forms covered"> 041 (-> world :merchants merchant) </span><br/> <span class="covered" title="3 out of 3 forms covered"> @@ -133,152 +133,194 @@ <span class="covered" title="1 out of 1 forms covered"> 043 merchant)] </span><br/> -<span class="covered" title="2 out of 2 forms covered"> - 044 (quot +<span class="covered" title="3 out of 3 forms covered"> + 044 (max </span><br/> -<span class="covered" title="9 out of 9 forms covered"> - 045 (- (:capacity m) (burden m world)) +<span class="not-tracked" title="0 out of 0 forms covered"> + 045 0 + </span><br/> +<span class="covered" title="2 out of 2 forms covered"> + 046 (quot + </span><br/> +<span class="partial" title="13 out of 14 forms covered"> + 047 (- (or (:capacity m) 0) (burden m world)) </span><br/> <span class="covered" title="7 out of 7 forms covered"> - 046 (-> world :commodities commodity :weight)))) + 048 (-> world :commodities commodity :weight))))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> - 047 + 049 </span><br/> <span class="covered" title="1 out of 1 forms covered"> - 048 (defn can-afford + 050 (defn can-afford </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> - 049 "Return the number of units of this `commodity` which this `merchant` + 051 "Return the number of units of this `commodity` which this `merchant` </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> - 050 can afford to buy in this `world`." + 052 can afford to buy in this `world`." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> - 051 [merchant world commodity] + 053 [merchant world commodity] </span><br/> <span class="partial" title="3 out of 4 forms covered"> - 052 (let [m (cond + 054 (let [m (cond </span><br/> <span class="covered" title="3 out of 3 forms covered"> - 053 (keyword? merchant) + 055 (keyword? merchant) </span><br/> -<span class="not-covered" title="0 out of 5 forms covered"> - 054 (-> world :merchants merchant) +<span class="covered" title="5 out of 5 forms covered"> + 056 (-> world :merchants merchant) </span><br/> <span class="covered" title="3 out of 3 forms covered"> - 055 (map? merchant) + 057 (map? merchant) </span><br/> <span class="covered" title="1 out of 1 forms covered"> - 056 merchant) + 058 merchant) </span><br/> <span class="covered" title="3 out of 3 forms covered"> - 057 l (:location m)] + 059 l (:location m)] + </span><br/> +<span class="covered" title="3 out of 3 forms covered"> + 060 (cond + </span><br/> +<span class="covered" title="3 out of 3 forms covered"> + 061 (nil? m) + </span><br/> +<span class="covered" title="3 out of 3 forms covered"> + 062 (throw (Exception. "No merchant?")) + </span><br/> +<span class="covered" title="14 out of 14 forms covered"> + 063 (or (nil? l) (nil? (-> world :cities l))) + </span><br/> +<span class="covered" title="6 out of 6 forms covered"> + 064 (throw (Exception. (str "No known location for merchant " m))) + </span><br/> +<span class="not-tracked" title="0 out of 0 forms covered"> + 065 :else </span><br/> <span class="covered" title="2 out of 2 forms covered"> - 058 (quot + 066 (quot </span><br/> <span class="covered" title="3 out of 3 forms covered"> - 059 (:cash m) + 067 (:cash m) </span><br/> <span class="covered" title="9 out of 9 forms covered"> - 060 (-> world :cities l :prices commodity)))) + 068 (-> world :cities l :prices commodity))))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> - 061 + 069 </span><br/> <span class="covered" title="1 out of 1 forms covered"> - 062 (defn add-stock + 070 (defn add-stock </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> - 063 "Where `a` and `b` are both maps all of whose values are numbers, return + 071 "Where `a` and `b` are both maps all of whose values are numbers, return </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> - 064 a map whose keys are a union of the keys of `a` and `b` and whose values + 072 a map whose keys are a union of the keys of `a` and `b` and whose values </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> - 065 are the sums of their respective values." + 073 are the sums of their respective values." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> - 066 [a b] + 074 [a b] </span><br/> -<span class="not-covered" title="0 out of 2 forms covered"> - 067 (reduce +<span class="covered" title="2 out of 2 forms covered"> + 075 (reduce </span><br/> -<span class="not-covered" title="0 out of 1 forms covered"> - 068 merge +<span class="covered" title="1 out of 1 forms covered"> + 076 merge </span><br/> -<span class="not-covered" title="0 out of 1 forms covered"> - 069 a +<span class="covered" title="1 out of 1 forms covered"> + 077 a </span><br/> -<span class="not-covered" title="0 out of 3 forms covered"> - 070 (map +<span class="covered" title="3 out of 3 forms covered"> + 078 (map </span><br/> -<span class="not-covered" title="0 out of 21 forms covered"> - 071 #(hash-map % (+ (or (a %) 0) (or (b %) 0))) +<span class="partial" title="20 out of 21 forms covered"> + 079 #(hash-map % (+ (or (a %) 0) (or (b %) 0))) </span><br/> -<span class="not-covered" title="0 out of 3 forms covered"> - 072 (keys b)))) +<span class="covered" title="3 out of 3 forms covered"> + 080 (keys b)))) </span><br/> <span class="blank" title="0 out of 0 forms covered"> - 073 + 081 </span><br/> <span class="covered" title="1 out of 1 forms covered"> - 074 (defn add-known-prices + 082 (defn add-known-prices </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> - 075 "Add the current prices at this `merchant`'s location in the `world` + 083 "Add the current prices at this `merchant`'s location in the `world` </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> - 076 to a new cacke of known prices, and return it." + 084 to a new cache of known prices, and return it." </span><br/> <span class="not-tracked" title="0 out of 0 forms covered"> - 077 [merchant world] + 085 [merchant world] </span><br/> <span class="not-covered" title="0 out of 4 forms covered"> - 078 (let [m (cond + 086 (let [m (cond </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> - 079 (keyword? merchant) + 087 (keyword? merchant) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> - 080 (-> world :merchants merchant) + 088 (-> world :merchants merchant) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> - 081 (map? merchant) + 089 (map? merchant) </span><br/> <span class="not-covered" title="0 out of 1 forms covered"> - 082 merchant) + 090 merchant) + </span><br/> +<span class="not-covered" title="0 out of 8 forms covered"> + 091 k (or (:known-prices m) {}) </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> - 083 k (:known-prices m) + 092 l (:location m) </span><br/> -<span class="not-covered" title="0 out of 3 forms covered"> - 084 l (:location m) - </span><br/> -<span class="not-covered" title="0 out of 3 forms covered"> - 085 d (:date world) +<span class="not-covered" title="0 out of 8 forms covered"> + 093 d (or (:date world) 0) </span><br/> <span class="not-covered" title="0 out of 7 forms covered"> - 086 p (-> world :cities l :prices)] - </span><br/> -<span class="not-covered" title="0 out of 2 forms covered"> - 087 (reduce - </span><br/> -<span class="not-covered" title="0 out of 1 forms covered"> - 088 merge - </span><br/> -<span class="not-covered" title="0 out of 1 forms covered"> - 089 k + 094 p (-> world :cities l :prices)] </span><br/> <span class="not-covered" title="0 out of 3 forms covered"> - 090 (map + 095 (cond + </span><br/> +<span class="not-covered" title="0 out of 3 forms covered"> + 096 (nil? m) + </span><br/> +<span class="not-covered" title="0 out of 3 forms covered"> + 097 (throw (Exception. "No merchant?")) + </span><br/> +<span class="not-covered" title="0 out of 14 forms covered"> + 098 (or (nil? l) (nil? (-> world :cities l))) + </span><br/> +<span class="not-covered" title="0 out of 6 forms covered"> + 099 (throw (Exception. (str "No known location for merchant " m))) + </span><br/> +<span class="not-tracked" title="0 out of 0 forms covered"> + 100 :else + </span><br/> +<span class="not-covered" title="0 out of 2 forms covered"> + 101 (reduce + </span><br/> +<span class="not-covered" title="0 out of 1 forms covered"> + 102 merge + </span><br/> +<span class="not-covered" title="0 out of 1 forms covered"> + 103 k + </span><br/> +<span class="not-covered" title="0 out of 3 forms covered"> + 104 (map </span><br/> <span class="not-covered" title="0 out of 17 forms covered"> - 091 #(hash-map % (apply vector cons {:price (p %) :date d} (k %))) + 105 #(hash-map % (apply vector cons {:price (p %) :date d} (k %))) </span><br/> <span class="not-covered" title="0 out of 5 forms covered"> - 092 (-> world :commodities keys))))) + 106 (-> world :commodities keys)))))) </span><br/> </body> </html> diff --git a/docs/index.html b/docs/index.html index 35656b5..044b871 100644 --- a/docs/index.html +++ b/docs/index.html @@ -6,8 +6,8 @@ <body> <h1>The Great Game: Dcocumentation</h1> <ul> - <li><a href="cloverage">Test coverage</a></li> - <li><a href="codox">Primary documentaion</a></li> + <li><a href="cloverage/index.html">Test coverage</a></li> + <li><a href="codox/index.html">Primary documentaion</a></li> </ul> </body> </html> diff --git a/project.clj b/project.clj index ff35841..67a2163 100644 --- a/project.clj +++ b/project.clj @@ -4,6 +4,7 @@ :doc/format :markdown} :output-path "docs/codox" :source-uri "https://github.com/simon-brooke/the-great-game/blob/master/{filepath}#L{line}"} + :cucumber-feature-paths ["test/features/"] :dependencies [[org.clojure/clojure "1.8.0"] [environ "1.1.0"] [com.taoensso/timbre "4.10.0"]] @@ -11,7 +12,9 @@ :license {:name "GNU General Public License,version 2.0 or (at your option) any later version" :url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"} :plugins [[lein-cloverage "1.1.1"] - [lein-codox "0.10.7"]] + [lein-codox "0.10.7"] + [lein-cucumber "1.0.2"] + [lein-gorilla "0.4.0"]] :release-tasks [["vcs" "assert-committed"] ["change" "version" "leiningen.release/bump-version" "release"] diff --git a/src/the_great_game/core.clj b/src/the_great_game/core.clj deleted file mode 100644 index 7a102ed..0000000 --- a/src/the_great_game/core.clj +++ /dev/null @@ -1,6 +0,0 @@ -(ns the-great-game.core) - -(defn foo - "I don't do a whole lot." - [x] - (println x "Hello, World!")) diff --git a/src/the_great_game/merchants/merchant_utils.clj b/src/the_great_game/merchants/merchant_utils.clj index b8cd969..9cfb5b4 100644 --- a/src/the_great_game/merchants/merchant_utils.clj +++ b/src/the_great_game/merchants/merchant_utils.clj @@ -23,7 +23,7 @@ (-> world :merchants merchant) (map? merchant) merchant) - cargo (:stock m)] + cargo (or (:stock m) {})] (reduce + 0 @@ -41,9 +41,11 @@ (-> world :merchants merchant) (map? merchant) merchant)] - (quot - (- (:capacity m) (burden m world)) - (-> world :commodities commodity :weight)))) + (max + 0 + (quot + (- (or (:capacity m) 0) (burden m world)) + (-> world :commodities commodity :weight))))) (defn can-afford "Return the number of units of this `commodity` which this `merchant` @@ -55,9 +57,15 @@ (map? merchant) merchant) l (:location m)] - (quot - (:cash m) - (-> world :cities l :prices commodity)))) + (cond + (nil? m) + (throw (Exception. "No merchant?")) + (or (nil? l) (nil? (-> world :cities l))) + (throw (Exception. (str "No known location for merchant " m))) + :else + (quot + (:cash m) + (-> world :cities l :prices commodity))))) (defn add-stock "Where `a` and `b` are both maps all of whose values are numbers, return @@ -73,20 +81,26 @@ (defn add-known-prices "Add the current prices at this `merchant`'s location in the `world` - to a new cacke of known prices, and return it." + to a new cache of known prices, and return it." [merchant world] (let [m (cond (keyword? merchant) (-> world :merchants merchant) (map? merchant) merchant) - k (:known-prices m) + k (or (:known-prices m) {}) l (:location m) - d (:date world) + d (or (:date world) 0) p (-> world :cities l :prices)] - (reduce - merge - k - (map - #(hash-map % (apply vector cons {:price (p %) :date d} (k %))) - (-> world :commodities keys))))) + (cond + (nil? m) + (throw (Exception. "No merchant?")) + (or (nil? l) (nil? (-> world :cities l))) + (throw (Exception. (str "No known location for merchant " m))) + :else + (reduce + merge + k + (map + #(hash-map % (apply vector cons {:price (p %) :date d} (k %))) + (-> world :commodities keys)))))) diff --git a/test/the_great_game/merchants/markets_test.clj b/test/the_great_game/merchants/markets_test.clj index bc3f515..7cacd30 100644 --- a/test/the_great_game/merchants/markets_test.clj +++ b/test/the_great_game/merchants/markets_test.clj @@ -79,8 +79,31 @@ (-> actual :cities :falkirk :stock :iron) 17) "Stock should be topped up by the difference between the supply and - the demand amount.")) + the demand amount.")))) - ) - - ) +(deftest run-test + (let [world (deep-merge + default-world + {:cities + {:aberdeen + {:stock {:fish 5} + :supplies {:fish 12} + :prices {:fish 1.1}} + :falkirk + {:stock {:iron 10} + :demands {:iron 5} + :supplies {:iron 12} + :prices {:iron 1.1}}}}) + actual (run world)] + (is + (= + (-> actual :cities :aberdeen :stock :fish) + (+ (-> world :cities :aberdeen :supplies :fish) + (-> world :cities :aberdeen :stock :fish))) + "If stock is not empty and price is above cost, stock should be topped up by supply amount.") + (is + (= + (-> actual :cities :falkirk :stock :iron) + 17) + "Stock should be topped up by the difference between the supply and + the demand amount."))) diff --git a/test/the_great_game/merchants/merchant_utils_test.clj b/test/the_great_game/merchants/merchant_utils_test.clj index 2f9071e..086c691 100644 --- a/test/the_great_game/merchants/merchant_utils_test.clj +++ b/test/the_great_game/merchants/merchant_utils_test.clj @@ -22,3 +22,106 @@ expected 1.7] ;; (is (= actual expected) "if information select the most recent"))))) +(deftest burden-test + (testing "Burden of merchant" + (let [world (deep-merge + default-world + {:merchants + {:archie + {:stock + {:iron 1}} + :belinda + {:stock + {:fish 2}} + :callum + {:stock + {:iron 1 + :fish 1}}}})] + (let [actual (burden :archie world) + expected (-> world :commodities :iron :weight)] + (is (= actual expected))) + (let [actual (burden :belinda world) + expected (* 2 (-> world :commodities :fish :weight))] + (is (= actual expected))) + (let [actual (burden :callum world) + expected (+ + (-> world :commodities :iron :weight) + (-> world :commodities :fish :weight))] + (is (= actual expected))) + (let [actual (burden {} world) + expected 0] + (is (= actual expected))) + (let [actual (burden (-> world :merchants :deidre) world) + expected 0] + (is (= actual expected)))))) + +(deftest can-carry-test + (testing "What merchants can carry" + (let [world (deep-merge + default-world + {:merchants + {:archie + {:cash 5 + :stock + {:iron 1}} + :belinda + {:stock + {:fish 2}} + :callum + {:stock + {:iron 1 + :fish 1}}}})] + (let [actual (can-carry :archie world :fish) + expected 0] + (is (= actual expected))) + (let [actual (can-carry :belinda world :fish) + expected 8] + (is (= actual expected))) + (let [actual (can-carry (-> world :merchants :archie) world :fish) + expected 0] + (is (= actual expected))) + (let [actual (can-carry {:stock {:fish 7} :capacity 10} world :fish) + expected 3] + (is (= actual expected)))))) + + +(deftest affordability-test + (testing "What merchants can afford to purchase" + (let [world (deep-merge + default-world + {:merchants + {:archie + {:cash 5 + :stock + {:iron 1}} + :belinda + {:stock + {:fish 2}} + :callum + {:stock + {:iron 1 + :fish 1}}}})] + (let [actual (can-afford :archie world :fish) + expected 5] + (is (= actual expected))) + (let [actual (can-afford :belinda world :fish) + expected 100] + (is (= actual expected))) + (let [actual (can-afford (-> world :merchants :archie) world :fish) + expected 5] + (is (= actual expected))) + (let [actual (can-afford {:cash 3 :location :buckie} world :fish) + expected 3] + (is (= actual expected))) + (is (thrown-with-msg? + Exception + #"No merchant?" + (can-afford :no-one world :fish))) + (is (thrown-with-msg? + Exception + #"No known location for merchant.*" + (can-afford {:cash 3} world :fish)))))) + +(deftest add-stock-test + (let [actual (add-stock {:iron 2 :fish 5} {:fish 3 :whisky 7}) + expected {:iron 2 :fish 8 :whisky 7}]))