Feature complete for version 1; some refactoring still needed.

This commit is contained in:
Simon Brooke 2014-07-24 18:44:04 +01:00
parent a0f59ac2dd
commit 98e43dbe8f
10 changed files with 190 additions and 84 deletions

View file

@ -1,5 +1,6 @@
## What this is about
<img alt="Screenshot" id="screenshot" style="float: left; padding-right: 2em;" src="img/screenshot_med.png"/>
MicroWorld is a rule driven cellular automaton. What does that mean? Well, it's
a two dimensional world made up of squares called **cells**. The world develops
in steps, and at each step, each cell is modified by applying the rules.

View file

@ -72,9 +72,10 @@ li.nav-item a:active { background: gray; color: white; }
}
.widget {
margin: 0;
padding: 0.25em 1em;
background-color: silver;
border: thin solid white;
margin-top: 0;
margin-bottom: 0;
}
.world {
@ -86,8 +87,6 @@ div.error {
}
form {
width: 100%;
background-color: silver;
border: thin solid silver;
}
@ -100,7 +99,7 @@ h1, h2, h3, h4, h5 {
color: white;
}
p, pre, ul, ol, dl, menu, h1, h2, h3, h4, h5 {
div.content, form, p, pre, ul, ol, dl, menu, h1, h2, h3, h4, h5 {
padding: 0.25em 10%;
}
@ -118,15 +117,8 @@ input.required:after {
}
label {
min-width: 35%;
}
label, input {
padding: 0.25em 1em;
margin: 0 0.5em;
}
label {
width: 30em;
min-width: 20em;
border-right: thin solid gray;
}
@ -138,9 +130,19 @@ menu li::before {
content: "|| ";
}
div.world table, div.world tr td {
div.world table, div.world table tr td {
padding: 0;
margin: 0;
border-collapse: collapse;
border: none;
}
table.music-ruled tr:nth-child(odd) {
background-color: silver;
}
th, td {
text-align: left;
padding: 0 0.25em;
}

View file

@ -3441,7 +3441,30 @@ important.</p>
([world cell depth state]
(get-neighbours-with-state world (:x cell) (:y cell) depth state))
([world cell state]
(get-neighbours-with-state world cell 1 state)))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-engine.world" name="mw-engine.world"><h1 class="project-name">mw-engine.world</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"><p>Functions to create and to print two dimensional cellular automata. Nothing in this
(get-neighbours-with-state world cell 1 state)))</pre></td></tr><tr><td class="docs"><p>If this <code>cell</code>s x and y properties are equal to these <code>x</code> and <code>y</code> values,
return a cell like this cell but with the value of this <code>property</code> set to
this <code>value</code>. Otherwise, just return this <code>cell</code>.</p>
</td><td class="codes"><pre class="brush: clojure">(defn- set-cell-property
[cell x y property value]
(cond
(and (= x (:x cell)) (= y (:y cell)))
(merge cell {property value})
true
cell))</pre></td></tr><tr><td class="docs"><p>Return a world like this <code>world</code> but with the value of exactly one <code>property</code>
of one <code>cell</code> changed to this <code>value</code></p>
</td><td class="codes"><pre class="brush: clojure">(defn set-property
([world cell property value]
(set-property world (:x cell) (:y cell) property value))
([world x y property value]
(apply
vector ;; we want a vector of vectors, not a list of lists, for efficiency
(map
(fn [row]
(apply
vector
(map #(set-cell-property % x y property value)
row)))
world))))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-engine.world" name="mw-engine.world"><h1 class="project-name">mw-engine.world</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"><p>Functions to create and to print two dimensional cellular automata. Nothing in this
file should determine what states are possible within the automaton, except for the
initial state, :new.</p>

View file

@ -3126,6 +3126,7 @@ net.brehaut.ClojureTools = (function (SH) {
[mw-engine.natural-rules :as rules]
[mw-parser.bulk :as compiler]
[hiccup.core :refer [html]]
[noir.io :as io]
[noir.session :as session]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn format-css-class [statekey]
&quot;Format this statekey, assumed to be a keyword indicating a state in the
@ -3141,7 +3142,7 @@ net.brehaut.ClojureTools = (function (SH) {
[cell]
(let [state (:state cell)]
[:td {:class (format-css-class state) :title (format-mouseover cell)}
[:a {:href (format &quot;inspect?x=%d&amp;amp;y=%d&quot; (:x cell) (:y cell))}
[:a {:href (format &quot;inspect?x=%d&amp;y=%d&quot; (:x cell) (:y cell))}
[:img {:alt (:state cell) :src (format-image-path state)}]]]))</pre></td></tr><tr><td class="docs"><p>Render this world row as a Hiccup table row.</p>
</td><td class="codes"><pre class="brush: clojure">(defn render-world-row
[row]
@ -3151,11 +3152,13 @@ net.brehaut.ClojureTools = (function (SH) {
(let [world (or (session/get :world)
(engine/transform-world
(heightmap/apply-heightmap
&quot;resources/public/img/heightmaps/small_hill.png&quot;
(io/get-resource &quot;/img/heightmaps/small_hill.png&quot;)
;; &quot;resources/public/img/heightmaps/great_britain_and_ireland_small.png&quot;)
rules/init-rules))
rules (or (session/get :rules)
(do (session/put! :rules (compiler/compile-file &quot;resources/rulesets/basic.txt&quot;))
(do (session/put! :rules
(compiler/compile-file
(io/get-resource &quot;/rulesets/basic.txt&quot;)))
(session/get :rules)))
generation (+ (or (session/get :generation) 0) 1)
w2 (engine/transform-world world rules)
@ -3166,22 +3169,17 @@ net.brehaut.ClojureTools = (function (SH) {
(apply vector
(cons :table
(map render-world-row w2)))
[:p (str &quot;Generation &quot; generation)]]))</pre></td></tr><tr><td class="docs"><p>Render the world implied by the session as a complete HTML page.</p>
</td><td class="codes"><pre class="brush: clojure">(defn render-world
[]
(html
[:html
[:head
[:title &quot;MicroWorld demo&quot;]
[:link {:media &quot;only screen and (max-device-width: 480px)&quot; :href &quot;css/phone.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}]
[:link {:media &quot;only screen and (min-device-width: 481px) and (max-device-width: 1024px)&quot; :href &quot;css/tablet.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}]
[:link {:media &quot;screen and (min-device-width: 1025px)&quot; :href &quot;css/standard.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}]
[:link {:media &quot;print&quot; :href &quot;css/print.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}]
[:link {:href &quot;css/states.css&quot; :type &quot;text/css&quot; :rel &quot;stylesheet&quot;}]
[:meta {:http-equiv &quot;refresh&quot; :content &quot;5&quot;}]]
[:body
(render-world-table)
]]))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.repl" name="mw-ui.repl"><h1 class="project-name">mw-ui.repl</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
[:p (str &quot;Generation &quot; generation)]]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn render-inspector
[cell table]
[:table {:class &quot;music-ruled&quot;}
[:tr
[:td {:colspan 2 :style &quot;text-align: center;&quot;}
[:img {:src (str &quot;img/tiles/&quot; (name (:state cell)) &quot;.png&quot;)
:width 64
:height 64}]]]
[:tr [:th &quot;Key&quot;][:th &quot;Value&quot;]]
(map #(vector :tr (vector :th %)(vector :td (cell %))) (keys cell))])</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.repl" name="mw-ui.repl"><h1 class="project-name">mw-ui.repl</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns mw-ui.repl
(:use mw-ui.handler
ring.server.standalone
@ -3214,16 +3212,40 @@ net.brehaut.ClojureTools = (function (SH) {
</td><td class="codes"><pre class="brush: clojure">(ns mw-ui.routes.home
(:use clojure.walk
compojure.core
[mw-engine.utils :as engine-utils]
[mw-ui.routes.rules :as rules]
[mw-ui.routes.params :as params])
(:require [hiccup.core :refer [html]]
[mw-ui.layout :as layout]
[mw-ui.util :as util]
[mw-ui.render-world :as world]
[noir.session :as session]))</pre></td></tr><tr><td class="docs">
[noir.session :as session]
[ring.util.response :as response]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn home-page []
(layout/render &quot;trusted-content.html&quot; {:title &quot;Welcome to MicroWorld&quot;
:content (util/md-&gt;html &quot;/md/mw-ui.md&quot;)}))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn inspect-page [request]
(let [params (keywordize-keys (:params request))
xs (:x params)
ys (:y params)
x (if (not (empty? xs)) (read-string xs) 0)
y (if (not (empty? 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 &quot;world&quot;))
true
(layout/render &quot;inspector.html&quot;
{:title (format &quot;Inspect cell at %d, %d&quot; x y)
:content (html (world/render-inspector cell world))
:cell cell
:x (:x cell)
:y (:y cell)
:states (util/list-resources
&quot;/img/tiles&quot; #&quot;([0-9a-z-_]+).png&quot;)}))))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn world-page []
(layout/render &quot;trusted-content.html&quot;
{:title &quot;Watch your world grow&quot;
@ -3250,8 +3272,8 @@ net.brehaut.ClojureTools = (function (SH) {
</td><td class="codes"><pre class="brush: clojure">(defn docs-page []
(layout/render &quot;docs.html&quot; {:title &quot;Documentation&quot;
:parser (util/md-&gt;html &quot;/md/mw-parser.md&quot; )
:states (util/list-resources &quot;resources/public/img/tiles&quot; #&quot;([0-9a-z-_]+).png&quot;)
:lessons (util/list-resources &quot;resources/public/md/lesson-plans&quot; #&quot;([0-9a-z-_]+).md&quot;)
:states (util/list-resources &quot;/img/tiles&quot; #&quot;([0-9a-z-_]+).png&quot;)
:lessons (util/list-resources &quot;/md/lesson-plans&quot; #&quot;([0-9a-z-_]+).md&quot;)
:components [&quot;mw-engine&quot; &quot;mw-parser&quot; &quot;mw-ui&quot;]}))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defroutes home-routes
(GET &quot;/&quot; [] (home-page))
@ -3262,9 +3284,12 @@ net.brehaut.ClojureTools = (function (SH) {
(GET &quot;/md&quot; request (md-page request))
(POST &quot;/params&quot; request (params/params-page request))
(GET &quot;/rules&quot; request (rules/rules-page request))
(POST &quot;/rules&quot; request (rules/rules-page request)))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.routes.params" name="mw-ui.routes.params"><h1 class="project-name">mw-ui.routes.params</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
(POST &quot;/rules&quot; request (rules/rules-page request))
(GET &quot;/inspect&quot; request (inspect-page request))
(POST &quot;/inspect&quot; request (inspect-page request)))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.routes.params" name="mw-ui.routes.params"><h1 class="project-name">mw-ui.routes.params</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns mw-ui.routes.params
(:use clojure.walk
clojure.java.io
compojure.core)
(:require [hiccup.core :refer [html]]
[mw-engine.heightmap :as heightmap]
@ -3272,12 +3297,13 @@ net.brehaut.ClojureTools = (function (SH) {
[mw-ui.layout :as layout]
[mw-ui.util :as util]
[mw-ui.render-world :as world]
[noir.io :as io]
[noir.session :as session]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn- send-params []
{:title &quot;Choose your world&quot;
:heightmaps (util/list-resources &quot;resources/public/img/heightmaps&quot; #&quot;([0-9a-z-_]+).png&quot;)
:heightmaps (util/list-resources &quot;/img/heightmaps&quot; #&quot;([0-9a-z-_]+).png&quot;)
:pause (or (session/get :pause) 5)
:rulesets (util/list-resources &quot;resources/rulesets&quot; #&quot;([0-9a-z-_]+).txt&quot;)
:rulesets (util/list-resources &quot;/rulesets&quot; #&quot;([0-9a-z-_]+).txt&quot;)
})</pre></td></tr><tr><td class="docs"><p>Handler for params request. If no <code>request</code> passed, show empty params form.
If <code>request</code> is passed, put parameters from request into session and show
the world page.</p>
@ -3290,15 +3316,15 @@ net.brehaut.ClojureTools = (function (SH) {
map (:heightmap params)
pause (:pause params)
rulefile (:ruleset params)
rulepath (str &quot;resources/rulesets/&quot; rulefile &quot;.txt&quot;)]
rulepath (str &quot;/rulesets/&quot; rulefile &quot;.txt&quot;)]
(if (not (= map &quot;&quot;))
(session/put! :world
(heightmap/apply-heightmap
(str &quot;resources/public/img/heightmaps/&quot; map &quot;.png&quot;))))
(io/get-resource (str &quot;/img/heightmaps/&quot; map &quot;.png&quot;)))))
(if (not (= rulefile &quot;&quot;))
(do
(session/put! :rule-text (slurp rulepath))
(session/put! :rules (compiler/compile-file rulepath))))
(session/put! :rule-text (io/slurp-resource rulepath))
(session/put! :rules (compiler/compile-file (io/get-resource rulepath)))))
(if (not (= pause &quot;&quot;))
(session/put! :pause pause))
(layout/render &quot;params.html&quot;
@ -3323,6 +3349,7 @@ net.brehaut.ClojureTools = (function (SH) {
[mw-ui.layout :as layout]
[mw-ui.util :as util]
[mw-ui.render-world :as world]
[noir.io :as io]
[noir.session :as session]))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn process-rules-request
[request]
@ -3337,7 +3364,7 @@ net.brehaut.ClojureTools = (function (SH) {
&quot; rules&quot;) })
true {:rule-text (or
(session/get :rule-text)
(slurp &quot;resources/rulesets/basic.txt&quot;))
(io/slurp-resource &quot;/rulesets/basic.txt&quot;))
:message &quot;No rules found in request; loading defaults&quot;})
(catch Exception e
{:rule-text src
@ -3362,6 +3389,7 @@ net.brehaut.ClojureTools = (function (SH) {
(rules-page nil)))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#mw-ui.util" name="mw-ui.util"><h1 class="project-name">mw-ui.util</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns mw-ui.util
(:require [noir.io :as io]
[noir.session :as session]
[markdown.core :as md]))</pre></td></tr><tr><td class="docs"><p>reads a markdown file from public/md and returns an HTML string</p>
</td><td class="codes"><pre class="brush: clojure">(defn md-&gt;html
[filename]
@ -3370,8 +3398,11 @@ net.brehaut.ClojureTools = (function (SH) {
(md/md-to-html-string)))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn list-resources [directory pattern]
&quot;List resource files matching `pattern` in `directory`.&quot;
(let
[path (str (io/resource-path) directory)]
(session/put! :list-resources-path path)
(sort
(filter #(not (nil? %))
(map #(first (rest (re-matches pattern (.getName %))))
(file-seq (clojure.java.io/file directory))))))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr></table><div class="footer">Generated by <a href="https://github.com/fogus/marginalia">Marginalia</a>.&nbsp;&nbsp;Syntax highlighting provided by Alex Gorbatchev's <a href="http://alexgorbatchev.com/SyntaxHighlighter/">SyntaxHighlighter</a></div><script type="text/javascript">SyntaxHighlighter.defaults['gutter'] = false;
(file-seq (clojure.java.io/file path)))))))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr></table><div class="footer">Generated by <a href="https://github.com/fogus/marginalia">Marginalia</a>.&nbsp;&nbsp;Syntax highlighting provided by Alex Gorbatchev's <a href="http://alexgorbatchev.com/SyntaxHighlighter/">SyntaxHighlighter</a></div><script type="text/javascript">SyntaxHighlighter.defaults['gutter'] = false;
SyntaxHighlighter.all()</script></body></html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

After

Width:  |  Height:  |  Size: 192 B

View file

@ -15,7 +15,10 @@ if state is in grassland or heath and more than 2 neighbours are pasture then st
if state is pasture and more than 3 neighbours are pasture and fewer than 1 neighbours are camp and fewer than 1 neighbours within 2 are house then state should be camp
;; the idea of agriculture spreads
if state is in grassland or heath and some neighbours are pasture and some neighbours within 3 are house then state should be pasture
if state is in grassland or heath and some neighbours within 3 are house then state should be pasture
;; nomads don't move on while the have crops growing. That would be silly!
if state is camp and some neighbours are ploughland then state should be camp
;; nomads move on
if state is camp then 1 chance in 5 state should be waste
@ -82,8 +85,8 @@ if state is forest and fertility is more than 5 and altitude is less than 70 the
if state is climax then 1 chance in 500 state should be fire
;; Climax forest neighbouring fires is likely to catch fire. So are buildings.
if state is in climax or camp or house or inn and some neighbours are fire then 1 chance in 3 state should be fire
;; Forest neighbouring fires is likely to catch fire. So are buildings.
if state is in forest or climax or camp or house or inn and some neighbours are fire then 1 chance in 3 state should be fire
;; Climax forest near to settlement may be cleared for timber
if state is in climax and more than 3 neighbours within 2 are house then state should be scrub
@ -123,4 +126,3 @@ if state is new and altitude is more than 200 then state should be snow
;; otherwise, we have grassland.
if state is new then state should be grassland

View file

@ -93,12 +93,15 @@
user interface is a web browser. It would be possible to arrange a
classroom with one copy of MicroWorld on a single server, and each child's
machine running MicroWorld from that single server.</p>
<p>However, performance isn't very good, and unless you have an unusually
powerful server you may find that when a full class of pupils are running
MicroWorld from a single server performance may be frustratingly poor.
Check your performance before introducing a class to it, and if in doubt,
<p>However, many users accessing the same server at the same time may
lead to poor performance.
Check performance on your system before introducing a class to it, and if in doubt,
running a separate copy on each machine used by children may well be more
satisfactory.</p>
<p>If many users are using the same shared machine, you should make sure
that they don't use the 'original' or 'med' versions of the Great Britain
and Ireland map - both of these are big, and performance will inevitably
be poor.</p>
<h3>Subject areas</h3>
<p>One of my main objectives in writing MicroWorld was to create a system
@ -148,15 +151,34 @@
class projects. Writing rules will enable discussion of why castles, or
mills, are positioned where they are, and what the social consequences of
these developments are.</p>
<p>You might also want to explore the conditions for the spread of epidemic
disease - such as the black death - I've provided a state for this,
but no rules.</p>
<h4>IT/Informatics</h4>
<p>Obviously, any of the rulesets but particularly the <em>gameoflife</em>
<p>Obviously, any of the rulesets but particularly the <em>life</em>
ruleset are good introduction points to informatics lessons. The rule
language is sufficiently simple that introducing children to writing
their own rules can begin almost as soon as basic literacy is
established.</p>
<p>In more advanced IT lessons, at the upper end of primary school or in
secondary schools, I would encourage you to explore modifying the engine
itself in your classes.</p>
itself in your classes. Also, it would be interesting to write an
export program which would export MicroWorld maps to Minecraft, or
render them as explorable three dimensional spaces using
<a href="http://jmonkeyengine.org/">JMonkeyEngine</a>
or <a href="https://nightmod.net/">NightMod</a>.</p>
<h4>Art and design</h4>
<p>A number of projects, progressively more ambitious, are possible in
art and design.</p>
<ol>
<li>The tiles I've drawn are pretty basic - again, that's
intentional, children can easily produce better ones. They don't have to
be 32x32, but they do all have to be the same size.</li>
<li>The stylesheets providing the overall look and feel of the system
could be modified</li>
<li>If you have an IT project to render a 3d world, you will need 3d
models of each of the states, instead of tiles. That might be a job for
<a href="http://blender.org">Blender</a>.</li></ol>
<h3>Lesson plans</h3>
<ul>

View file

@ -28,7 +28,7 @@
[cell]
(let [state (:state cell)]
[:td {:class (format-css-class state) :title (format-mouseover cell)}
[:a {:href (format "inspect?x=%d&amp;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)}]]]))
(defn render-world-row
@ -63,19 +63,16 @@
(map render-world-row w2)))
[:p (str "Generation " generation)]]))
(defn render-world
"Render the world implied by the session as a complete HTML page."
[]
(html
[:html
[:head
[:title "MicroWorld demo"]
[:link {:media "only screen and (max-device-width: 480px)" :href "css/phone.css" :type "text/css" :rel "stylesheet"}]
[:link {:media "only screen and (min-device-width: 481px) and (max-device-width: 1024px)" :href "css/tablet.css" :type "text/css" :rel "stylesheet"}]
[:link {:media "screen and (min-device-width: 1025px)" :href "css/standard.css" :type "text/css" :rel "stylesheet"}]
[:link {:media "print" :href "css/print.css" :type "text/css" :rel "stylesheet"}]
[:link {:href "css/states.css" :type "text/css" :rel "stylesheet"}]
[:meta {:http-equiv "refresh" :content "5"}]]
[:body
(render-world-table)
]]))
(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))])

View file

@ -1,18 +1,43 @@
(ns mw-ui.routes.home
(:use clojure.walk
compojure.core
[mw-engine.utils :as engine-utils]
[mw-ui.routes.rules :as rules]
[mw-ui.routes.params :as params])
(:require [hiccup.core :refer [html]]
[mw-ui.layout :as layout]
[mw-ui.util :as util]
[mw-ui.render-world :as world]
[noir.session :as session]))
[noir.session :as session]
[ring.util.response :as response]))
(defn home-page []
(layout/render "trusted-content.html" {:title "Welcome to MicroWorld"
:content (util/md->html "/md/mw-ui.md")}))
(defn inspect-page [request]
(let [params (keywordize-keys (:params request))
xs (:x params)
ys (:y params)
x (if (not (empty? xs)) (read-string xs) 0)
y (if (not (empty? 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")}))))
(defn world-page []
(layout/render "trusted-content.html"
{:title "Watch your world grow"
@ -43,8 +68,8 @@
(defn docs-page []
(layout/render "docs.html" {:title "Documentation"
:parser (util/md->html "/md/mw-parser.md" )
:states (util/list-resources "resources/public/img/tiles" #"([0-9a-z-_]+).png")
:lessons (util/list-resources "resources/public/md/lesson-plans" #"([0-9a-z-_]+).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"]}))
(defroutes home-routes
@ -56,4 +81,7 @@
(GET "/md" request (md-page request))
(POST "/params" request (params/params-page request))
(GET "/rules" request (rules/rules-page request))
(POST "/rules" request (rules/rules-page request)))
(POST "/rules" request (rules/rules-page request))
(GET "/inspect" request (inspect-page request))
(POST "/inspect" request (inspect-page request))
)

View file

@ -6,8 +6,8 @@
;; Test file specifically to test the helper function in rules handler
(deftest test-rules-processor
(testing "Rules processor"
(let [request {:src "if state is new and altitude is less than 10 then state should be water"}
(let [request {:form-params {:src "if state is new and altitude is less than 10 then state should be water"}}
response (process-rules-request request)]
(is (= (:message response) "Successfully compiled 1 rules"))
(is (= (count (:rules response)) 1))
(is (= (:rule-text response) (:src request))))))
(is (= (:rule-text response) (:src (:form-params request)))))))