diff --git a/src/vending/routes/home.clj b/src/vending/routes/home.clj index adc562d..4313460 100644 --- a/src/vending/routes/home.clj +++ b/src/vending/routes/home.clj @@ -1,15 +1,53 @@ (ns vending.routes.home (:use compojure.core) (:require [vending.views.layout :as layout] + [noir.session :as session] + [vending.core :as machine] [vending.util :as util])) -(defn home-page [] + +(def button-actions + {"Coin return" machine/coin-return + "Add Merk" machine/add-merk + "Add Bawbee" machine/add-bawbee + "Add Plack" machine/add-plack + "Add Bodle" machine/add-bodle + "Request Caramel Wafer" machine/get-caramel-wafer + "Request Teacake" machine/get-teacake + "Request Snowball" machine/get-snowball + }) + + +(defn- perform-action! + "Apply this function to the machine in the session, if there is one, or else to a new default + machine; cache the result in the session; and return a rendered page representation of the + state of the machine." + [function] + (let [machine (apply function (list (or (session/get :machine) (machine/make-default-machine))))] + (session/put! :machine machine) + (layout/render + "home.html" {:content (util/md->html "/md/docs.md") + :machine machine + :buttons (keys button-actions)}))) + + +(defn home-page + "Render the home page with the default machine; in so doing, reset the machine in the session." + [] + (let [machine (machine/make-default-machine)] + (session/put! :machine machine) (layout/render - "home.html" {:content (util/md->html "/md/docs.md")})) + "home.html" {:content (util/md->html "/md/docs.md") + :machine machine + :buttons (keys button-actions)}))) + (defn about-page [] (layout/render "about.html")) + (defroutes home-routes (GET "/" [] (home-page)) - (GET "/about" [] (about-page))) + (GET "/about" [] (about-page)) + (POST "/update" [action] (perform-action! (button-actions action))) + ) diff --git a/src/vending/routes/json.clj b/src/vending/routes/json.clj index ffbd4de..21d8b87 100644 --- a/src/vending/routes/json.clj +++ b/src/vending/routes/json.clj @@ -8,75 +8,23 @@ [vending.util :as util])) -(defn- perform-action +(defn- perform-action! "Apply this function to the machine in the session, if there is one, or else to a new default - machine; cache the result in the session; and return a JSON formatted representation of the result." + machine; cache the result in the session; and return a JSON formatted representation of the state + of the machine." [function] (let [machine (apply function (list (or (session/get :machine) (machine/make-default-machine))))] (session/put! :machine machine) (json/write-str machine))) -;;; Each of these action functions perform an action on the machine in the session, if there is one, -;;; or on a new default machine if there is no machine in the session. They return (and cache in the -;;; session) the new state of the machine after the action; the machine returned is returned as a -;;; JSON string. - -(defn coin-return-action - "Return all the coins that have been tendered since the last sale." - [] - (perform-action machine/coin-return)) - - -(defn add-merk-action - "Insert one merk into the coin slot of the machine in the session." - [] - (perform-action machine/add-merk)) - - -(defn add-bawbee-action - "Insert one bawbee into the coin slot of the machine in the session." - [] - (perform-action machine/add-bawbee)) - - -(defn add-plack-action - "Insert one plack into the coin slot of the machine in the session." - [] - (perform-action machine/add-plack)) - - -(defn add-bodle-action - "Insert one bodle into the coin slot of the machine in the session." - [] - (perform-action machine/add-bodle)) - - -(defn select-caramel-wafer-action - "Request one caramel wafer from the machine in the session." - [] - (perform-action machine/get-caramel-wafer)) - - -(defn select-teacake-action - "Request one teacake from the machine in the session." - [] - (perform-action machine/get-teacake)) - - -(defn select-snowball-action - "Request one snowball from the machine in the session." - [] - (perform-action machine/get-snowball)) - - (defroutes json-routes - (GET "/coin-return" [] (coin-return-action)) - (GET "/add-merk" [] (add-merk-action)) - (GET "/add-bawbee" [] (add-bawbee-action)) - (GET "/add-plack" [] (add-plack-action)) - (GET "/add-bodle" [] (add-bodle-action)) - (GET "/select-caramel-wafer" [] (select-caramel-wafer-action)) - (GET "/select-teacake" [] (select-teacake-action)) - (GET "/select-snowball" [] (select-snowball-action)) + (GET "/json/coin-return" [] (perform-action! machine/coin-return)) + (GET "/json/add-merk" [] (perform-action! machine/add-merk)) + (GET "/json/add-bawbee" [] (perform-action! machine/add-bawbee)) + (GET "/json/add-plack" [] (perform-action! machine/add-plack)) + (GET "/json/add-bodle" [] (perform-action! machine/add-bodle)) + (GET "/json/select-caramel-wafer" [] (perform-action! machine/get-caramel-wafer)) + (GET "/json/select-teacake" [] (perform-action! machine/get-teacake)) + (GET "/json/select-snowball" [] (perform-action! machine/get-snowball)) ) diff --git a/src/vending/views/templates/home.html b/src/vending/views/templates/home.html index 66d452b..aaa9f02 100644 --- a/src/vending/views/templates/home.html +++ b/src/vending/views/templates/home.html @@ -1,56 +1,86 @@ {% extends "vending/views/templates/base.html" %} {% block content %} - <div class="jumbotron"> - <h1>Welcome to vending</h1> - <p>Time to start building your site!</p> - <p><a class="btn btn-primary btn-lg" href="http://luminusweb.net">Learn more »</a></p> - </div> +<div class="jumbotron"> + <h1>Welcome to vending</h1> +</div> - <div class="row-fluid"> - <div class="span8"> - {{content|safe}} - </div> - </div> -<div class="content"> - <h2>OK, the Vending machine plan</h2> +<div class="row-fluid"> + <div class="content span8"> <p>What this project is about is the - <a href="http://code.joejag.com/coding-dojo-vending-machine/">Vending Machine code kata</a>. - Just at this point, I've added the whole of a <a href="http://www.luminusweb.net/">luminusweb</a> - default template to it, but I haven't done much with it. In due course this page will be replaced - with a graphical representation of a <a href="http://en.wikipedia.org/wiki/W._Heath_Robinson">heath-robinson</a> - vending machine, with buttons allowing coins to be inserted, and items to be selected.<p> + <a href="http://code.joejag.com/coding-dojo-vending-machine/">Vending Machine code kata</a>. + Just at this point, I've added the whole of a <a href="http://www.luminusweb.net/">luminusweb</a> + default template to it, but I haven't done much with it. In due course this page will be replaced + with a graphical representation of a <a href="http://en.wikipedia.org/wiki/W._Heath_Robinson">heath-robinson</a> + vending machine, with buttons allowing coins to be inserted, and items to be selected.<p> <p>I intend that the page should be interactive, with the vending machine responding graphically to - what the user does on the buttons. The logic will almost certainly be server-side at first, - but possibly later I'll move it client-side using ClojureScript.</p> + what the user does on the buttons. The logic will almost certainly be server-side at first, + but possibly later I'll move it client-side using ClojureScript.</p> <p>At this stage in the project this page uses the <a href="https://github.com/yogthos/Selmer">Selmer</a> - templating system; later I intend that it should use <a href="https://github.com/cgrand/enlive">Enlive</a>.</p> - <table class="machine"> + templating system; later I intend that it should use <a href="https://github.com/cgrand/enlive">Enlive</a>.</p> + <form action="/update" method="post"> + <table class="machine"> <tr> - <td colspan="8" id="tendered-coins">Tendered coins</td> + <th colspan="2" id="tendered-coins-header">Tendered coins</th> + <td colspan="6" id="tendered-coins">{{machine.tendered}}</td> </tr> <tr> - <td id="teacake" class="items">Teacakes</td> - <td id="caramel-wafer" class="items">Caramel wafers</td> - <td id="snowballs" class="items">Snowballs</td> - <td id="merk" class="coins">Merks</td> - <td id="plack" class="coins">Placks</td> - <td id="bawbee" class="coins">Bawbees</td> - <td id="bodle" class="coins">Bodles</td> - <td id="change-chute" rowspan="2"></td> + <th colspan="3" id="stock-header">Stock</th> + <th colspan="4" id="coin-stack-header">Coin stacks</th> + <th id="change-chute" rowspan="2"></th> </tr> <tr> - <td id="message">Last Message</td> + <th id="teacake" class="item-header">Teacakes</th> + <th id="caramel-wafer" class="item-header">Caramel wafers</th> + <th id="snowballs" class="item-header">Snowballs</th> + <th id="merk" class="coin-header">Merks</th> + <th id="bawbee" class="coin-header">Bawbees</th> + <th id="plack" class="coin-header">Placks</th> + <th id="bodle" class="coin-header">Bodles</th> </tr> <tr> - <td colspan="3" id="output" class="hoppers">Output</td> - <td colspan="5" id="change" class="hoppers">Change</td> + <td id="caramel-wafers" class="item-stock"> + {{machine.stock.caramel-wafer}} + </td> + <td id="teacakes" class="item-stock"> + {{machine.stock.teacake}} + </td> + <td id="snowballs" class="item-stock"> + {{machine.stock.snowball}} + </td> + <td id="merks" class="coin-stacks">{{machine.coins.merk}}</td> + <td id="bawbee" class="coin-stacks">{{machine.coins.bawbee}}</td> + <td id="plack" class="coin-stacks">{{machine.coins.plack}}</td> + <td id="bodle" class="coin-stacks">{{machine.coins.bodle}}</td> </tr> <tr> - {% for button in buttons %} - <td class="button" id="{{ button }}-cell"> - <submit name="action" value="{{ button }}" id="{{ button }}-button"/> - </td> + <th id="message-header">Last Message</th> + </tr> + <tr> + <td id="message">{{machine.message}}</td> + </tr> + <tr> + <th colspan="3" id="output-header" class="hopper-headers">Output</th> + <th colspan="4" id="change-header" class="hopper-headers">Change</th> + </tr> + <tr> + <td colspan="3" id="output-hopper" class="hoppers"> + {{machine.output}} + </td> + <td colspan="4" id="change-hopper" class="hoppers"> + {% for coin in machine.change %} + {{coin}} {% endfor %} + </td> </tr> - </table> + <tr> + {% for button in buttons %} + <td class="button" id="{{ button }}-cell"> + <input type="submit" name="action" value="{{ button }}" id="{{ button }}-button"/> + </td> + {% endfor %} + </tr> + </table> + </form> + </div> +</div> {% endblock %}