Compare commits

...

3 commits

21 changed files with 505 additions and 202 deletions

View file

@ -8,18 +8,21 @@
"build-signature-timestamp" "unset" "build-signature-timestamp" "unset"
"Implementation-Version" "unset" "Implementation-Version" "unset"
} }
:dependencies [[org.clojure/clojure "1.6.0"] :dependencies [[org.clojure/clojure "1.8.0"]
[mw-engine "0.1.5-SNAPSHOT"] [mw-engine "3.0.0-SNAPSHOT"]
[mw-parser "0.1.5-SNAPSHOT"] [mw-parser "3.0.0-SNAPSHOT"]
[lib-noir "0.8.4"] [lib-noir "0.9.9"]
[ring-server "0.3.1"] [ring-server "0.4.0"]
[selmer "0.6.8"] [selmer "1.0.9"]
[com.taoensso/timbre "3.2.1"] [com.taoensso/timbre "3.2.1"]
[com.taoensso/tower "2.0.2"] [com.taoensso/tower "3.0.2"]
[markdown-clj "0.9.44"] [markdown-clj "0.9.89"]
[environ "0.5.0"] [environ "1.1.0"]
[noir-exception "0.2.2"]] [noir-exception "0.2.5"]]
:source-paths ["src/clj" "src/cljc"]
:license {:name "GNU General Public License v2"
:url "http://www.gnu.org/licenses/gpl-2.0.html"}
:repl-options {:init-ns mw-ui.repl} :repl-options {:init-ns mw-ui.repl}
:plugins [[lein-ring "0.8.11"] :plugins [[lein-ring "0.8.11"]
[lein-environ "0.5.0"] [lein-environ "0.5.0"]
@ -37,8 +40,8 @@
:stacktraces? false :stacktraces? false
:auto-reload? false}} :auto-reload? false}}
:dev {:dependencies [[ring-mock "0.1.5"] :dev {:dependencies [[ring-mock "0.1.5"]
[ring/ring-devel "1.3.0"] [ring/ring-devel "1.5.0"]
[pjstadig/humane-test-output "0.6.0"]] [pjstadig/humane-test-output "0.8.1"]]
:injections [(require 'pjstadig.humane-test-output) :injections [(require 'pjstadig.humane-test-output)
(pjstadig.humane-test-output/activate!)] (pjstadig.humane-test-output/activate!)]
:env {:dev true}}} :env {:dev true}}}

View file

@ -6,7 +6,7 @@ body {
/* Overall container div, holds all content of page. Yes, I know it shouldn't have fixed width */ /* Overall container div, holds all content of page. Yes, I know it shouldn't have fixed width */
#main-container{ #main-container{
clear: both; clear: both;
/* width:100%; */ width:100%;
} }
/* footer of the document */ /* footer of the document */
@ -145,4 +145,3 @@ th, td {
text-align: left; text-align: left;
padding: 0 0.25em; padding: 0 0.25em;
} }

View file

@ -3,11 +3,7 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>{{title}}</title> <title>{{title}}</title>
<link href="{{servlet-context}}/css/phone.css" media="only screen and (max-device-width: 480px)" rel="stylesheet" type="text/css" />
<link href="{{servlet-context}}/css/tablet.css" media="only screen and (min-device-width: 481px) and (max-device-width: 1024px)" rel="stylesheet" type="text/css" />
<link href="{{servlet-context}}/css/standard.css" media="screen and (min-device-width: 1025px)" rel="stylesheet" type="text/css" /> <link href="{{servlet-context}}/css/standard.css" media="screen and (min-device-width: 1025px)" rel="stylesheet" type="text/css" />
<link href="{{servlet-context}}/css/print.css" media="print" rel="stylesheet" type="text/css" />
<link href="{{servlet-context}}/css/states.css" rel="stylesheet" type="text/css" />
{% script "/lib/jquery-1.9.0.js" %} {% script "/lib/jquery-1.9.0.js" %}
{% script "/lib/jquery.validate.min.js" %} {% script "/lib/jquery.validate.min.js" %}
{% script "/lib/script.js" %} {% script "/lib/script.js" %}
@ -45,7 +41,9 @@
{% endif %} {% endif %}
{% if error %} {% if error %}
<div id="error"> <div id="error">
<p class="error">{{error}}</p> <pre class="error">
{{error}}
</pre>
</div> </div>
{% endif %} {% endif %}
@ -57,7 +55,8 @@
Built with <a href="http://www.luminusweb.net/">LuminusWeb</a> || Built with <a href="http://www.luminusweb.net/">LuminusWeb</a> ||
<img height="16" width="16" align="top" src="img/clojure-icon.gif" alt="&lambda;"> Powered by <a href="http://clojure.org">Clojure</a> || <img height="16" width="16" align="top" src="img/clojure-icon.gif" alt="&lambda;"> Powered by <a href="http://clojure.org">Clojure</a> ||
Engineering and hosting by <a href="http://www.journeyman.cc">Journeyman</a> || Engineering and hosting by <a href="http://www.journeyman.cc">Journeyman</a> ||
World generated using <a href="http://git.journeyman.cc/?p=mw-engine;a=summary">MicroWorld Engine</a> World generated using <a href="http://git.journeyman.cc/?p=mw-engine;a=summary">MicroWorld Engine</a> ||
Version {{version}}
</div> </div>
</div> </div>
</body> </body>

View file

@ -4,6 +4,7 @@
{{content|safe}} {{content|safe}}
</div> </div>
<form action="inspect" method="post"> <form action="inspect" method="post">
{% csrf-field %}
<input type="hidden" name="x" value="{{x}}"/> <input type="hidden" name="x" value="{{x}}"/>
<input type="hidden" name="y" value="{{y}}"/> <input type="hidden" name="y" value="{{y}}"/>
<p class="widget"> <p class="widget">

View file

@ -1,6 +1,7 @@
{% extends "templates/base.html" %} {% extends "templates/base.html" %}
{% block content %} {% block content %}
<form action="{{servlet-context}}/params" method="POST"> <form action="{{servlet-context}}/params" method="POST">
{% csrf-field %}
<p class="widget"> <p class="widget">
<label for="ruleset">The rule set to use</label> <label for="ruleset">The rule set to use</label>
<select name="ruleset"> <select name="ruleset">

View file

@ -1,4 +1,6 @@
(ns mw-ui.handler (ns ^{:doc "Set up and tear down the request handler."
:author "Simon Brooke"}
mw-ui.handler
(:require [compojure.core :refer [defroutes]] (:require [compojure.core :refer [defroutes]]
[mw-ui.routes.home :refer [home-routes]] [mw-ui.routes.home :refer [home-routes]]
[mw-ui.middleware :refer [load-middleware]] [mw-ui.middleware :refer [load-middleware]]
@ -10,10 +12,34 @@
[selmer.parser :as parser] [selmer.parser :as parser]
[environ.core :refer [env]])) [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 (defroutes app-routes
(route/resources "/") (route/resources "/")
(route/not-found "Not Found")) (route/not-found "Not Found"))
(defn init (defn init
"init will be called once when "init will be called once when
app is deployed as a servlet on app is deployed as a servlet on
@ -27,14 +53,15 @@
:async? false ; should be always false for rotor :async? false ; should be always false for rotor
:max-message-per-msecs nil :max-message-per-msecs nil
:fn rotor/appender-fn}) :fn rotor/appender-fn})
(timbre/set-config! (timbre/set-config!
[:shared-appender-config :rotor] [:shared-appender-config :rotor]
{:path "mw_ui.log" :max-size (* 512 1024) :backlog 10}) {:path "mw_ui.log" :max-size (* 512 1024) :backlog 10})
(if (env :dev) (parser/cache-off!)) (if (env :dev) (parser/cache-off!))
(timbre/info "mw-ui started successfully")) (timbre/info "mw-ui started successfully"))
(defn destroy (defn destroy
"destroy will be called when your application "destroy will be called when your application
shuts down, put any clean up code here" shuts down, put any clean up code here"
@ -42,7 +69,6 @@
(timbre/info "mw-ui is shutting down...")) (timbre/info "mw-ui is shutting down..."))
(def app (app-handler (def app (app-handler
;; add your application routes here ;; add your application routes here
[home-routes app-routes] [home-routes app-routes]

54
src/clj/mw_ui/layout.clj Normal file
View file

@ -0,0 +1,54 @@
(ns ^{:doc "Layout content as HTML."
:author "Simon Brooke"}
mw-ui.layout
(:require [selmer.parser :as parser]
[clojure.string :as s]
[ring.util.response :refer [content-type response]]
[ring.util.anti-forgery :refer [anti-forgery-field]]
[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/")
(parser/add-tag! :csrf-field (fn [_ _] (anti-forgery-field)))
(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))

View file

@ -0,0 +1,53 @@
(ns ^{:doc "In truth, boilerplate from Luminus."
: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))

View file

@ -1,28 +1,56 @@
(ns mw-ui.render-world (ns ^{:doc "Render the state of the world as an HTML table."
:author "Simon Brooke"}
mw-ui.render-world
(:require [clojure.java.io :as jio] (:require [clojure.java.io :as jio]
[mw-engine.core :as engine] [microworld.engine.core :as engine]
[mw-engine.world :as world] [microworld.engine.world :as world]
[mw-engine.heightmap :as heightmap] [microworld.engine.heightmap :as heightmap]
[mw-parser.bulk :as compiler] [microworld.parser.bulk :as compiler]
[hiccup.core :refer [html]] [hiccup.core :refer [html]]
[noir.io :as io] [noir.io :as io]
[noir.session :as session])) [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] (defn format-css-class [statekey]
"Format this statekey, assumed to be a keyword indicating a state in the "Format this statekey, assumed to be a keyword indicating a state in the
world, into a CSS class" world, into a CSS class"
(subs (str statekey) 1)) (subs (str statekey) 1))
(defn format-image-path (defn format-image-path
"Render this statekey, assumed to be a keyword indicating a state in the "Render this statekey, assumed to be a keyword indicating a state in the
world, into a path which should recover the corresponding image file." world, into a path which should recover the corresponding image file."
[statekey] [statekey]
(format "img/tiles/%s.png" (format-css-class statekey))) (format "img/tiles/%s.png" (format-css-class statekey)))
(defn format-mouseover [cell] (defn format-mouseover [cell]
(str cell)) (str cell))
(defn render-cell (defn render-cell
"Render this world cell as a Hiccup table cell." "Render this world cell as a Hiccup table cell."
[cell] [cell]
@ -31,21 +59,22 @@
[:a {:href (format "inspect?x=%d&y=%d" (:x cell) (:y cell))} [:a {:href (format "inspect?x=%d&y=%d" (:x cell) (:y cell))}
[:img {:alt (:state cell) :src (format-image-path state)}]]])) [:img {:alt (:state cell) :src (format-image-path state)}]]]))
(defn render-world-row (defn render-world-row
"Render this world row as a Hiccup table row." "Render this world row as a Hiccup table row."
[row] [row]
(apply vector (cons :tr (map render-cell row)))) (apply vector (cons :tr (map render-cell row))))
(defn render-world-table (defn render-world-table
"Render the world implied by the current session as a complete HTML table in a DIV." "Render the world implied by the current session as a complete HTML table in a DIV."
[] []
(let [world (or (session/get :world) (let [world (or (session/get :world)
(heightmap/apply-heightmap (heightmap/apply-heightmap "public/img/heightmaps/small_hill.png"))
(io/get-resource "/img/heightmaps/small_hill.png")))
rules (or (session/get :rules) rules (or (session/get :rules)
(do (session/put! :rules (do (session/put! :rules
(compiler/compile-file (compiler/compile-file
(io/get-resource "/rulesets/basic.txt"))) (jio/resource "public/rulesets/basic.txt")))
(session/get :rules))) (session/get :rules)))
generation (inc (or (session/get :generation) 0)) generation (inc (or (session/get :generation) 0))
w2 (engine/transform-world world rules) w2 (engine/transform-world world rules)
@ -59,6 +88,7 @@
[:p [:p
(str "Generation " generation)]])) (str "Generation " generation)]]))
(defn render-inspector (defn render-inspector
"Render in Hiccup format the HTML content of an inspector on this cell." "Render in Hiccup format the HTML content of an inspector on this cell."
[cell table] [cell table]

View file

@ -1,9 +1,34 @@
(ns mw-ui.repl (ns ^{:doc "In truth, boilerplate from Luminus."
:author "Simon Brooke"}
mw-ui.repl
(:use mw-ui.handler (:use mw-ui.handler
ring.server.standalone ring.server.standalone
[ring.middleware file-info file]) [ring.middleware file-info file])
(:gen-class) (: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)) (defonce server (atom nil))

View file

@ -1,9 +1,12 @@
(ns mw-ui.routes.home (ns ^{:doc "Routes which serve the main pages of the application."
:author "Simon Brooke"}
mw-ui.routes.home
(:use clojure.walk (:use clojure.walk
compojure.core) compojure.core)
(:require [clojure.pprint :only [pprint]] (:require [clojure.java.io :refer [file resource]]
[clojure.pprint :only [pprint]]
[hiccup.core :refer [html]] [hiccup.core :refer [html]]
[mw-engine.utils :as engine-utils] [microworld.engine.utils :as engine-utils]
[mw-ui.layout :as layout] [mw-ui.layout :as layout]
[mw-ui.render-world :as world] [mw-ui.render-world :as world]
[mw-ui.routes.load :as load] [mw-ui.routes.load :as load]
@ -15,31 +18,57 @@
[noir.session :as session] [noir.session :as session]
[ring.util.response :as response])) [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 [] (defn list-states []
(sort (sort
(filter #(not (nil? %)) (filter #(not (nil? %))
(map #(first (rest (re-matches #"([0-9a-z-]+).png" (.getName %)))) (map #(first (rest (re-matches #"([0-9a-z-]+).png" (.getName %))))
(file-seq (clojure.java.io/file "resources/public/img/tiles")))))) (file-seq (resource "public/img/tiles"))))))
(defn about-page [] (defn about-page []
(layout/render "trusted-content.html" (layout/render "trusted-content.html"
{:title "About MicroWorld" {:title "About MicroWorld"
:about-selected "active" :about-selected "active"
:content (util/md->html "/md/about.md")})) :content (util/md->html "public/md/about.md")
:version (System/getProperty "mw-ui.version")}))
(defn docs-page [] (defn docs-page []
(layout/render "docs.html" {:title "Documentation" (layout/render "docs.html" {:title "Documentation"
:parser (util/md->html "/md/mw-parser.md" ) :parser (util/md->html "public/md/microworld.parser.md" )
:states (util/list-resources "/img/tiles" #"([0-9a-z-_]+).png") :states (util/list-resources "public/img/tiles" #"([0-9a-z-_]+).png")
:lessons (util/list-resources "/md/lesson-plans" #"([0-9a-z-_]+).md") :lessons (util/list-resources "public/md/lesson-plans" #"([0-9a-z-_]+).md")
:components ["mw-engine" "mw-parser" "mw-ui"]})) :components ["microworld.engine" "microworld.parser" "mw-ui"]
:version (System/getProperty "mw-ui.version")}))
(defn home-page [] (defn home-page []
"Render the home page." "Render the home page."
(layout/render "trusted-content.html" {:title "Welcome to MicroWorld" (layout/render "trusted-content.html" {:title "Welcome to MicroWorld"
:content (util/md->html "/md/mw-ui.md")})) :content (util/md->html "public/md/mw-ui.md")
:version (System/getProperty "mw-ui.version")}))
(defn inspect-page [request] (defn inspect-page [request]
"Open an inspector on the cell at the co-ordinates specified in this request" "Open an inspector on the cell at the co-ordinates specified in this request"
@ -63,7 +92,7 @@
:x (:x cell) :x (:x cell)
:y (:y cell) :y (:y cell)
:states (util/list-resources :states (util/list-resources
"/img/tiles" #"([0-9a-z-_]+).png")})))) "public/img/tiles" #"([0-9a-z-_]+).png")}))))
(defn md-page (defn md-page
"Render the markdown page specified in this request, if any. Probably undesirable, "Render the markdown page specified in this request, if any. Probably undesirable,

View file

@ -1,4 +1,6 @@
(ns mw-ui.routes.load (ns ^{:doc "Route which handles the upload of worlds/rules from the client."
:author "Simon Brooke"}
mw-ui.routes.load
(:use clojure.walk (:use clojure.walk
compojure.core) compojure.core)
(:require [hiccup.core :refer [html]] (:require [hiccup.core :refer [html]]
@ -8,6 +10,29 @@
[mw-ui.layout :as layout] [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] (defn- upload [file]
(io/upload-file "/tmp/" file) (io/upload-file "/tmp/" file)
@ -16,6 +41,7 @@
(with-open [eddi (java.io.FileReader. (:tempfile file))] (read))) (with-open [eddi (java.io.FileReader. (:tempfile file))] (read)))
(str "Successfully loaded your world from " (:filename file)))) (str "Successfully loaded your world from " (:filename file))))
(defn load-page (defn load-page
"If no args, show the load form; with args, load a world file from the client. "If no args, show the load form; with args, load a world file from the client.

View file

@ -0,0 +1,85 @@
(ns ^{:doc "Route which serves and handles the parameters page."
:author "Simon Brooke"}
mw-ui.routes.params
(:use clojure.walk
clojure.java.io
compojure.core)
(:require [clojure.java.io :refer [resource]]
[hiccup.core :refer [html]]
[microworld.engine.heightmap :as heightmap]
[microworld.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 "public/img/heightmaps" #"([0-9a-z-_]+).png")
:pause (or (session/get :pause) 5)
:rulesets (util/list-resources "public/rulesets" #"([0-9a-z-_]+).txt")
})
(defn params-page
"Handler for params request. If no `request` passed, show empty params form.
If `request` is passed, put parameters from request into session and show
the world 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 "public/rulesets/" rulefile ".txt")]
(if (not= map "")
(session/put! :world
(heightmap/apply-heightmap
(resource (str "public/img/heightmaps/" map ".png")))))
(when (not= rulefile "")
(session/put! :rule-text (io/slurp-resource rulepath))
(session/put! :rules (compiler/compile-file (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)}
)))))))

View file

@ -1,8 +1,10 @@
(ns mw-ui.routes.rules (ns ^{:doc "Route which serves and handles the rules page."
:author "Simon Brooke"}
mw-ui.routes.rules
(:use clojure.walk (:use clojure.walk
compojure.core) compojure.core)
(:require [hiccup.core :refer [html]] (:require [hiccup.core :refer [html]]
[mw-parser.bulk :as compiler] [microworld.parser.bulk :as compiler]
[mw-ui.layout :as layout] [mw-ui.layout :as layout]
[mw-ui.util :as util] [mw-ui.util :as util]
[mw-ui.render-world :as world] [mw-ui.render-world :as world]
@ -10,6 +12,30 @@
[noir.session :as session] [noir.session :as session]
[ring.util.response :as response])) [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 (defn process-rules-request
[request] [request]
(let [src (:src (keywordize-keys (:form-params request)))] (let [src (:src (keywordize-keys (:form-params request)))]
@ -30,6 +56,7 @@
:message "An error occurred during compilation" :message "An error occurred during compilation"
:error (str (.getName (.getClass e)) ": " (.getMessage e))})))) :error (str (.getName (.getClass e)) ": " (.getMessage e))}))))
(defn rules-page (defn rules-page
"Request handler for the `rules` request. If the `request` contains a value "Request handler for the `rules` request. If the `request` contains a value
for `:src`, treat that as rule source and try to compile it. If compilation for `:src`, treat that as rule source and try to compile it. If compilation

View file

@ -0,0 +1,41 @@
(ns ^{:doc "Route which handles the saving of world state the client."
:author "Simon Brooke"}
mw-ui.routes.save
(:require [clojure.pprint :refer [pprint]]
[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 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/header
(response/response
(with-out-str (pprint (session/get :world))))
"Content-Type" "application/journeyman-mwm; charset=utf-8"))

45
src/clj/mw_ui/util.clj Normal file
View file

@ -0,0 +1,45 @@
(ns ^{:doc "Utility functions used by other namespaces in this package."
:author "Simon Brooke"}
mw-ui.util
(:require [clojure.java.io :refer [resource file]]
[noir.session :as session]
[markdown.core :refer [md-to-html-string]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
;;;; 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 md->html
"reads a markdown file from public/md and returns an HTML string"
[filename]
(->>
(slurp (resource filename))
(md-to-html-string)))
(defn list-resources [directory pattern]
"List resource files matching `pattern` in `directory`."
(sort
(remove nil?
(map #(first (rest (re-matches pattern (.getName %))))
(file-seq (file (resource directory)))))))

View file

@ -1,24 +0,0 @@
(ns mw-ui.layout
(:require [selmer.parser :as parser]
[clojure.string :as s]
[ring.util.response :refer [content-type response]]
[compojure.response :refer [Renderable]]))
(def template-path "templates/")
(deftype RenderableTemplate [template params]
Renderable
(render [this request]
(content-type
(->> (assoc params
(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))

View file

@ -1,24 +0,0 @@
(ns 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]]))
(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))

View file

@ -1,57 +0,0 @@
(ns 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]))
(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")
})
(defn params-page
"Handler for params request. If no `request` passed, show empty params form.
If `request` is passed, put parameters from request into session and show
the world 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)}
)))))))

View file

@ -1,15 +0,0 @@
(ns mw-ui.routes.save
(:require [clojure.pprint :as pretty :only [pprint]]
[noir.session :as session]
[ring.util.response :as response]))
(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/header
(response/response
(with-out-str (pretty/pprint (session/get :world))))
"Content-Type" "application/journeyman-mwm; charset=utf-8"))

View file

@ -1,21 +0,0 @@
(ns mw-ui.util
(:require [noir.io :as io]
[noir.session :as session]
[markdown.core :as md]))
(defn md->html
"reads a markdown file from public/md and returns an HTML string"
[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)))))))