diff --git a/.gitignore b/.gitignore index cf11b31..7e819cf 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ resources/public/docs/mw-*/uberdoc.html # Artefacts: mw_ui.log pom.xml + +buildall.tmp.*/ diff --git a/docs/uberdoc.html b/docs/uberdoc.html new file mode 100644 index 0000000..4d7c64b --- /dev/null +++ b/docs/uberdoc.html @@ -0,0 +1,3690 @@ + +
mw-ui0.1.5Web-based user interface for MicroWorld +dependencies
| (this space intentionally left almost blank) | ||||||||||||||||||||||||||||||||||||
Set up and tear down the request handler. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.handler
+ (:require [compojure.core :refer [defroutes]]
+ [mw-ui.routes.home :refer [home-routes]]
+ [mw-ui.middleware :refer [load-middleware]]
+ [noir.response :refer [redirect]]
+ [noir.util.middleware :refer [app-handler]]
+ [compojure.route :as route]
+ [taoensso.timbre :as timbre]
+ [taoensso.timbre.appenders.rotor :as rotor]
+ [selmer.parser :as parser]
+ [environ.core :refer [env]])) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
| + | (defroutes app-routes + (route/resources "/") + (route/not-found "Not Found")) | ||||||||||||||||||||||||||||||||||||
init will be called once when + app is deployed as a servlet on + an app server such as Tomcat + put any initialization code here + | (defn init
+ []
+ (timbre/set-config!
+ [:appenders :rotor]
+ {:min-level :info
+ :enabled? true
+ :async? false ; should be always false for rotor
+ :max-message-per-msecs nil
+ :fn rotor/appender-fn})
+ (timbre/set-config!
+ [:shared-appender-config :rotor]
+ {:path "mw_ui.log" :max-size (* 512 1024) :backlog 10})
+ (if (env :dev) (parser/cache-off!))
+ (timbre/info "mw-ui started successfully")) | ||||||||||||||||||||||||||||||||||||
destroy will be called when your application + shuts down, put any clean up code here + | (defn destroy + [] + (timbre/info "mw-ui is shutting down...")) | ||||||||||||||||||||||||||||||||||||
| + | (def app (app-handler
+ ;; add your application routes here
+ [home-routes app-routes]
+ ;; add custom middleware here
+ :middleware (load-middleware)
+ ;; timeout sessions after 30 minutes
+ :session-options {:timeout (* 60 30)
+ :timeout-response (redirect "/")}
+ ;; add access rules here
+ :access-rules []
+ ;; serialize/deserialize the following data formats
+ ;; available formats:
+ ;; :json :json-kw :yaml :yaml-kw :edn :yaml-in-html
+ :formats [:json-kw :edn])) | ||||||||||||||||||||||||||||||||||||
Layout content as HTML. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.layout
+ (:require [selmer.parser :as parser]
+ [clojure.string :as s]
+ [ring.util.response :refer [content-type response]]
+ [compojure.response :refer [Renderable]])) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
| + | (def template-path "templates/") | ||||||||||||||||||||||||||||||||||||
| + | (deftype RenderableTemplate [template params]
+ Renderable
+ (render [this request]
+ (content-type
+ (->> (assoc (merge params {:version (System/getProperty "mw-ui.version")})
+ (keyword (s/replace template #".html" "-selected")) "active"
+ :servlet-context
+ (if-let [context (:servlet-context request)]
+ (.getContextPath context)))
+ (parser/render-file (str template-path template))
+ response)
+ "text/html; charset=utf-8"))) | ||||||||||||||||||||||||||||||||||||
| + | (defn render [template & [params]] + (RenderableTemplate. template params)) | ||||||||||||||||||||||||||||||||||||
In truth, boilerplate from Luminus. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.middleware
+ (:require [taoensso.timbre :as timbre]
+ [selmer.parser :as parser]
+ [environ.core :refer [env]]
+ [selmer.middleware :refer [wrap-error-page]]
+ [noir-exception.core
+ :refer [wrap-internal-error wrap-exceptions]])) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
| + | (defn log-request [handler] + (fn [req] + (timbre/debug req) + (handler req))) | ||||||||||||||||||||||||||||||||||||
| + | (def development-middleware + [log-request + wrap-error-page + wrap-exceptions]) | ||||||||||||||||||||||||||||||||||||
| + | (def production-middleware + [#(wrap-internal-error % :log (fn [e] (timbre/error e)))]) | ||||||||||||||||||||||||||||||||||||
| + | (defn load-middleware [] + (concat (when (env :dev) development-middleware) + production-middleware)) | ||||||||||||||||||||||||||||||||||||
Render the state of the world as an HTML table. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.render-world
+ (:require [clojure.java.io :as jio]
+ [mw-engine.core :as engine]
+ [mw-engine.world :as world]
+ [mw-engine.heightmap :as heightmap]
+ [mw-parser.bulk :as compiler]
+ [hiccup.core :refer [html]]
+ [noir.io :as io]
+ [noir.session :as session])) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
| + | (defn format-css-class [statekey] + "Format this statekey, assumed to be a keyword indicating a state in the + world, into a CSS class" + (subs (str statekey) 1)) | ||||||||||||||||||||||||||||||||||||
Render this statekey, assumed to be a keyword indicating a state in the + world, into a path which should recover the corresponding image file. + | (defn format-image-path + [statekey] + (format "img/tiles/%s.png" (format-css-class statekey))) | ||||||||||||||||||||||||||||||||||||
| + | (defn format-mouseover [cell] + (str cell)) | ||||||||||||||||||||||||||||||||||||
Render this world cell as a Hiccup table cell. + | (defn render-cell
+ [cell]
+ (let [state (:state cell)]
+ [:td {:class (format-css-class state) :title (format-mouseover cell)}
+ [:a {:href (format "inspect?x=%d&y=%d" (:x cell) (:y cell))}
+ [:img {:alt (:state cell) :src (format-image-path state)}]]])) | ||||||||||||||||||||||||||||||||||||
Render this world row as a Hiccup table row. + | (defn render-world-row + [row] + (apply vector (cons :tr (map render-cell row)))) | ||||||||||||||||||||||||||||||||||||
Render the world implied by the current session as a complete HTML table in a DIV. + | (defn render-world-table
+ []
+ (let [world (or (session/get :world)
+ (heightmap/apply-heightmap
+ (io/get-resource "/img/heightmaps/small_hill.png")))
+ rules (or (session/get :rules)
+ (do (session/put! :rules
+ (compiler/compile-file
+ (io/get-resource "/rulesets/basic.txt")))
+ (session/get :rules)))
+ generation (inc (or (session/get :generation) 0))
+ w2 (engine/transform-world world rules)
+ ]
+ (session/put! :world w2)
+ (session/put! :generation generation)
+ [:div {:class "world"}
+ (apply vector
+ (cons :table
+ (map render-world-row w2)))
+ [:p
+ (str "Generation " generation)]])) | ||||||||||||||||||||||||||||||||||||
Render in Hiccup format the HTML content of an inspector on this cell. + | (defn render-inspector
+ [cell table]
+ [:table {:class "music-ruled"}
+ [:tr
+ [:td {:colspan 2 :style "text-align: center;"}
+ [:img {:src (str "img/tiles/" (name (:state cell)) ".png")
+ :width 64
+ :height 64}]]]
+ [:tr [:th "Key"][:th "Value"]]
+ (map #(vector :tr (vector :th %)(vector :td (cell %))) (keys cell))]) | ||||||||||||||||||||||||||||||||||||
In truth, boilerplate from Luminus. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.repl
+ (:use mw-ui.handler
+ ring.server.standalone
+ [ring.middleware file-info file])
+ (:gen-class)) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
| + | (defonce server (atom nil)) | ||||||||||||||||||||||||||||||||||||
| + | (defn get-handler [] + ;; #'app expands to (var app) so that when we reload our code, + ;; the server is forced to re-resolve the symbol in the var + ;; rather than having its own copy. When the root binding + ;; changes, the server picks it up without having to restart. + (-> #'app + ; Makes static assets in $PROJECT_DIR/resources/public/ available. + (wrap-file "resources") + ; Content-Type, Content-Length, and Last Modified headers for files in body + (wrap-file-info))) | ||||||||||||||||||||||||||||||||||||
used for starting the server in development mode from REPL + | (defn start-server
+ [& [port]]
+ (let [port (if port (Integer/parseInt port) 3000)]
+ (reset! server
+ (serve (get-handler)
+ {:port port
+ :init init
+ :auto-reload? true
+ :destroy destroy
+ :join? false}))
+ (println (str "You can view the site at http://localhost:" port)))) | ||||||||||||||||||||||||||||||||||||
| + | (defn stop-server [] + (.stop @server) + (reset! server nil)) | ||||||||||||||||||||||||||||||||||||
| + | (defn -main [] + (start-server)) | ||||||||||||||||||||||||||||||||||||
Routes which serve the main pages of the application. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.routes.home
+ (:use clojure.walk
+ compojure.core)
+ (:require [clojure.pprint :only [pprint]]
+ [hiccup.core :refer [html]]
+ [mw-engine.utils :as engine-utils]
+ [mw-ui.layout :as layout]
+ [mw-ui.render-world :as world]
+ [mw-ui.routes.load :as load]
+ [mw-ui.routes.rules :as rules]
+ [mw-ui.routes.params :as params]
+ [mw-ui.routes.save :as save]
+ [mw-ui.util :as util]
+ [noir.io :as io]
+ [noir.session :as session]
+ [ring.util.response :as response])) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
| + | (defn list-states [] + (sort + (filter #(not (nil? %)) + (map #(first (rest (re-matches #"([0-9a-z-]+).png" (.getName %)))) + (file-seq (clojure.java.io/file "resources/public/img/tiles")))))) | ||||||||||||||||||||||||||||||||||||
| + | (defn about-page []
+ (layout/render "trusted-content.html"
+ {:title "About MicroWorld"
+ :about-selected "active"
+ :content (util/md->html "/md/about.md")
+ :version (System/getProperty "mw-ui.version")})) | ||||||||||||||||||||||||||||||||||||
| + | (defn docs-page []
+ (layout/render "docs.html" {:title "Documentation"
+ :parser (util/md->html "/md/mw-parser.md" )
+ :states (util/list-resources "/img/tiles" #"([0-9a-z-_]+).png")
+ :lessons (util/list-resources "/md/lesson-plans" #"([0-9a-z-_]+).md")
+ :components ["mw-engine" "mw-parser" "mw-ui"]
+ :version (System/getProperty "mw-ui.version")})) | ||||||||||||||||||||||||||||||||||||
| + | (defn home-page []
+ "Render the home page."
+ (layout/render "trusted-content.html" {:title "Welcome to MicroWorld"
+ :content (util/md->html "/md/mw-ui.md")
+ :version (System/getProperty "mw-ui.version")})) | ||||||||||||||||||||||||||||||||||||
| + | (defn inspect-page [request]
+ "Open an inspector on the cell at the co-ordinates specified in this request"
+ (let [params (keywordize-keys (:params request))
+ xs (:x params)
+ ys (:y params)
+ x (if (seq xs) (read-string xs) 0)
+ y (if (seq ys) (read-string ys) 0)
+ world (session/get :world)
+ cell (engine-utils/get-cell world x y)
+ state (:state params)]
+ (cond state
+ (do
+ (session/put! :world (engine-utils/set-property world cell :state (keyword state)))
+ (response/redirect "world"))
+ true
+ (layout/render "inspector.html"
+ {:title (format "Inspect cell at %d, %d" x y)
+ :content (html (world/render-inspector cell world))
+ :cell cell
+ :x (:x cell)
+ :y (:y cell)
+ :states (util/list-resources
+ "/img/tiles" #"([0-9a-z-_]+).png")})))) | ||||||||||||||||||||||||||||||||||||
Render the markdown page specified in this request, if any. Probably undesirable, + should be removed. + | (defn md-page
+ [request]
+ (let [params (keywordize-keys (:params request))
+ content (or (:content params) "missing.md")]
+ (layout/render "trusted-content.html"
+ {:title "Welcome to MicroWorld"
+ :content (util/md->html (str "/md/" content))}))) | ||||||||||||||||||||||||||||||||||||
| + | (defn world-page []
+ "Render the world in the current session (or a default one if none)."
+ (layout/render "trusted-content.html"
+ {:title "Watch your world grow"
+ :world-selected "active"
+ :content (html (world/render-world-table))
+ :pause (or (session/get :pause) 5)
+ :maybe-refresh "refresh"})) | ||||||||||||||||||||||||||||||||||||
| + | (defroutes home-routes + (GET "/" [] (home-page)) + (GET "/about" [] (about-page)) + (GET "/docs" [] (docs-page)) + (GET "/inspect" request (inspect-page request)) + (POST "/inspect" request (inspect-page request)) + (GET "/load" [] (load/load-page)) + (POST "/load" request (load/load-page request)) + (GET "/md" request (md-page request)) + (GET "/params" [] (params/params-page)) + (POST "/params" request (params/params-page request)) + (GET "/rules" request (rules/rules-page request)) + (POST "/rules" request (rules/rules-page request)) + (GET "/saved-map.mwm" [] (save/save-page)) + (GET "/world" [] (world-page))) | ||||||||||||||||||||||||||||||||||||
Route which handles the upload of worlds/rules from the client. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.routes.load
+ (:use clojure.walk
+ compojure.core)
+ (:require [hiccup.core :refer [html]]
+ [noir.io :as io]
+ [noir.session :as session]
+ [ring.util.response :as response]
+ [mw-ui.layout :as layout])) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
| + | (defn- upload [file] + (io/upload-file "/tmp/" file) + (cond + (session/put! :world + (with-open [eddi (java.io.FileReader. (:tempfile file))] (read))) + (str "Successfully loaded your world from " (:filename file)))) | ||||||||||||||||||||||||||||||||||||
If no args, show the load form; with args, load a world file from the client. + +NOTE that this reads a Clojure form from an untrusted client and should almost + certainly NOT be enabled on a public-facing site, especially not on the Internet. + +TODO doesn't work yet. + | (defn load-page
+ ([]
+ (load-page nil))
+ ([request]
+ (let [params (keywordize-keys (:params request))
+ file (:file request)]
+ (try
+ (layout/render "load.html"
+ {:title "Load World"
+ :message (upload file)})
+ (catch Exception any
+ (layout/render "load.html"
+ {:title "Load World"
+ :message "Failed to load your world"
+ :error (str (.getName (.getClass any)) ": " (.getMessage any))})))))) | ||||||||||||||||||||||||||||||||||||
Route which serves and handles the parameters page. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.routes.params
+ (:use clojure.walk
+ clojure.java.io
+ compojure.core)
+ (:require [hiccup.core :refer [html]]
+ [mw-engine.heightmap :as heightmap]
+ [mw-parser.bulk :as compiler]
+ [mw-ui.layout :as layout]
+ [mw-ui.util :as util]
+ [mw-ui.render-world :as world]
+ [noir.io :as io]
+ [noir.session :as session])) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
| + | (defn- send-params []
+ {:title "Choose your world"
+ :heightmaps (util/list-resources "/img/heightmaps" #"([0-9a-z-_]+).png")
+ :pause (or (session/get :pause) 5)
+ :rulesets (util/list-resources "/rulesets" #"([0-9a-z-_]+).txt")
+ }) | ||||||||||||||||||||||||||||||||||||
Handler for params request. If no | (defn params-page
+ ([]
+ (layout/render "params.html" (send-params)))
+ ([request]
+ (try
+ (let [params (keywordize-keys (:form-params request))
+ map (:heightmap params)
+ pause (:pause params)
+ rulefile (:ruleset params)
+ rulepath (str "/rulesets/" rulefile ".txt")]
+ (if (not= map "")
+ (session/put! :world
+ (heightmap/apply-heightmap
+ (io/get-resource (str "/img/heightmaps/" map ".png")))))
+ (when (not= rulefile "")
+ (session/put! :rule-text (io/slurp-resource rulepath))
+ (session/put! :rules (compiler/compile-file (io/get-resource rulepath))))
+ (if (not= pause "")
+ (session/put! :pause pause))
+ (layout/render "params.html"
+ (merge (send-params)
+ {:r rulefile
+ :h map
+ :message "Your parameters are saved, now look at your world"})))
+ (catch Exception e
+ (let [params (keywordize-keys (:form-params request))]
+ (layout/render "params.html"
+ (merge (send-params)
+ {:title "Choose your world"
+ :r (:ruleset params)
+ :h (:heightmap params)
+ :message "Your paramters are not saved"
+ :error (str (.getName (.getClass e)) ": " (.getMessage e) "; " params)}))))))) | ||||||||||||||||||||||||||||||||||||
Route which serves and handles the rules page. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.routes.rules
+ (:use clojure.walk
+ compojure.core)
+ (:require [hiccup.core :refer [html]]
+ [mw-parser.bulk :as compiler]
+ [mw-ui.layout :as layout]
+ [mw-ui.util :as util]
+ [mw-ui.render-world :as world]
+ [noir.io :as io]
+ [noir.session :as session]
+ [ring.util.response :as response])) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
| + | (defn process-rules-request
+ [request]
+ (let [src (:src (keywordize-keys (:form-params request)))]
+ (try
+ (cond src
+ (let [rules (compiler/compile-string src)]
+ {:rule-text src
+ :rules rules
+ :message (str "Successfully compiled "
+ (count rules)
+ " rules") })
+ true {:rule-text (or
+ (session/get :rule-text)
+ (io/slurp-resource "/rulesets/basic.txt"))
+ :message "No rules found in request; loading defaults"})
+ (catch Exception e
+ {:rule-text src
+ :message "An error occurred during compilation"
+ :error (str (.getName (.getClass e)) ": " (.getMessage e))})))) | ||||||||||||||||||||||||||||||||||||
Request handler for the If | (defn rules-page
+ ([request]
+ (let [processed (process-rules-request request)]
+ (if (:rules processed)
+ (session/put! :rules (:rules processed)))
+ (if (:rule-text processed)
+ (session/put! :rule-text (:rule-text processed)))
+ (layout/render "rules.html"
+ (merge {:title "Edit Rules"} processed))))
+ ([]
+ (rules-page nil))) | ||||||||||||||||||||||||||||||||||||
Route which handles the saving of world state the client. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.routes.save
+ (:require [clojure.pprint :as pretty :only [pprint]]
+ [noir.session :as session]
+ [noir.response :as response])) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
| + | (defn save-page [] + "Save the current world to the browser, using our own custom mime-type in + an attempt to prevent the browser trying to do anything clever with it. + Note that it is saved as a raw Clojure data structure, not as XML or + any proprietary format." + (response/content-type + "application/journeyman-mwm; charset=utf-8" + (with-out-str (pretty/pprint (session/get :world))))) | ||||||||||||||||||||||||||||||||||||
Utility functions used by other namespaces in this package. + | (ns ^{:doc
+ :author "Simon Brooke"}
+ mw-ui.util
+ (:require [noir.io :as io]
+ [noir.session :as session]
+ [markdown.core :as md])) | ||||||||||||||||||||||||||||||||||||
mw-ui: a servlet user/visualisation interface for MicroWorld. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +USA. + +Copyright (C) 2014 Simon Brooke + | |||||||||||||||||||||||||||||||||||||
reads a markdown file from public/md and returns an HTML string + | (defn md->html + [filename] + (->> + (io/slurp-resource filename) + (md/md-to-html-string))) | ||||||||||||||||||||||||||||||||||||
| + | (defn list-resources [directory pattern] + "List resource files matching `pattern` in `directory`." + (let + [path (str (io/resource-path) directory)] + (session/put! :list-resources-path path) + (sort + (remove nil? + (map #(first (rest (re-matches pattern (.getName %)))) + (file-seq (clojure.java.io/file path))))))) | ||||||||||||||||||||||||||||||||||||