pdfa worksheet: list of strings instead of strings + even model

--- examples/src/worksheets/pdfa.clj
+++ examples/src/worksheets/pdfa.clj
@@ -23,7 +23,7 @@
 (anglican.infcomp.core/reset-infcomp-addressing-scheme!)
 ;; @@
 ;; =>
-;;; {"type":"html","content":"#function[anglican.infcomp.core/reset-infcomp-addressing-scheme!$fn--26362$fn--26363]","value":"#function[anglican.infcomp.core/reset-infcomp-addressing-scheme!$fn--26362$fn--26363]"}
+;;; {"type":"html","content":"#function[anglican.infcomp.core/reset-infcomp-addressing-scheme!$fn--26348$fn--26349]","value":"#function[anglican.infcomp.core/reset-infcomp-addressing-scheme!$fn--26348$fn--26349]"}
 ;; <=

 ;; **
@@ -97,10 +97,13 @@

 ;; **
 ;;; ## Model
-;; **
-
-;; @@
-; Pfau, D., Bartlett, N., & Wood, F. (2011). Probabilistic Deterministic Infinite Automata. In Advances in Neural Information Processing Systems (pp. 1930–1938)
+;;;
+;;; From
+;;;
+;;; `Pfau, D., Bartlett, N., & Wood, F. (2011). Probabilistic Deterministic Infinite Automata. In Advances in Neural Information Processing Systems (pp. 1930–1938)`
+;; **
+
+;; @@
 (with-primitive-procedures [normalize]
   (defquery pdfa [observedsequence alphabet]
     (let [num-states (sample (categorical [[2 10] [3 6] [4 3] [5 1]]))
@@ -131,7 +134,7 @@
 ;; **

 ;; @@
-(def alphabet "ab")
+(def alphabet (map str "ab"))
 (def alphabet-len (count alphabet))
 (defn one-hot [len hot]
   (assoc (vec (replicate len 0)) hot 1))
@@ -160,14 +163,14 @@
 (sample-observes-from-prior pdfa [(repeat 10 nil) alphabet])
 ;; @@
 ;; =>
-;;; {"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"0","value":"0"}],"value":"[:time-index 0]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"0","value":"0"}],"value":"[:observe-instance 0]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 0, :observe-address O44, :observe-instance 0, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"1","value":"1"}],"value":"[:time-index 1]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"1","value":"1"}],"value":"[:observe-instance 1]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"0","value":"0"}],"value":"[:value 0]"}],"value":"{:time-index 1, :observe-address O44, :observe-instance 1, :value 0}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"2","value":"2"}],"value":"[:time-index 2]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"2","value":"2"}],"value":"[:observe-instance 2]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 2, :observe-address O44, :observe-instance 2, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"3","value":"3"}],"value":"[:time-index 3]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"3","value":"3"}],"value":"[:observe-instance 3]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 3, :observe-address O44, :observe-instance 3, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"4","value":"4"}],"value":"[:time-index 4]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"4","value":"4"}],"value":"[:observe-instance 4]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"0","value":"0"}],"value":"[:value 0]"}],"value":"{:time-index 4, :observe-address O44, :observe-instance 4, :value 0}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"5","value":"5"}],"value":"[:time-index 5]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"5","value":"5"}],"value":"[:observe-instance 5]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 5, :observe-address O44, :observe-instance 5, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"6","value":"6"}],"value":"[:time-index 6]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"6","value":"6"}],"value":"[:observe-instance 6]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 6, :observe-address O44, :observe-instance 6, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"7","value":"7"}],"value":"[:time-index 7]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"7","value":"7"}],"value":"[:observe-instance 7]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 7, :observe-address O44, :observe-instance 7, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"8","value":"8"}],"value":"[:time-index 8]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"8","value":"8"}],"value":"[:observe-instance 8]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 8, :observe-address O44, :observe-instance 8, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"9","value":"9"}],"value":"[:time-index 9]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"9","value":"9"}],"value":"[:observe-instance 9]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"0","value":"0"}],"value":"[:value 0]"}],"value":"{:time-index 9, :observe-address O44, :observe-instance 9, :value 0}"}],"value":"[{:time-index 0, :observe-address O44, :observe-instance 0, :value 1} {:time-index 1, :observe-address O44, :observe-instance 1, :value 0} {:time-index 2, :observe-address O44, :observe-instance 2, :value 1} {:time-index 3, :observe-address O44, :observe-instance 3, :value 1} {:time-index 4, :observe-address O44, :observe-instance 4, :value 0} {:time-index 5, :observe-address O44, :observe-instance 5, :value 1} {:time-index 6, :observe-address O44, :observe-instance 6, :value 1} {:time-index 7, :observe-address O44, :observe-instance 7, :value 1} {:time-index 8, :observe-address O44, :observe-instance 8, :value 1} {:time-index 9, :observe-address O44, :observe-instance 9, :value 0}]"}
+;;; {"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"0","value":"0"}],"value":"[:time-index 0]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"0","value":"0"}],"value":"[:observe-instance 0]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"0","value":"0"}],"value":"[:value 0]"}],"value":"{:time-index 0, :observe-address O44, :observe-instance 0, :value 0}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"1","value":"1"}],"value":"[:time-index 1]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"1","value":"1"}],"value":"[:observe-instance 1]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"0","value":"0"}],"value":"[:value 0]"}],"value":"{:time-index 1, :observe-address O44, :observe-instance 1, :value 0}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"2","value":"2"}],"value":"[:time-index 2]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"2","value":"2"}],"value":"[:observe-instance 2]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 2, :observe-address O44, :observe-instance 2, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"3","value":"3"}],"value":"[:time-index 3]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"3","value":"3"}],"value":"[:observe-instance 3]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 3, :observe-address O44, :observe-instance 3, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"4","value":"4"}],"value":"[:time-index 4]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"4","value":"4"}],"value":"[:observe-instance 4]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 4, :observe-address O44, :observe-instance 4, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"5","value":"5"}],"value":"[:time-index 5]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"5","value":"5"}],"value":"[:observe-instance 5]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"1","value":"1"}],"value":"[:value 1]"}],"value":"{:time-index 5, :observe-address O44, :observe-instance 5, :value 1}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"6","value":"6"}],"value":"[:time-index 6]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"6","value":"6"}],"value":"[:observe-instance 6]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"0","value":"0"}],"value":"[:value 0]"}],"value":"{:time-index 6, :observe-address O44, :observe-instance 6, :value 0}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"7","value":"7"}],"value":"[:time-index 7]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"7","value":"7"}],"value":"[:observe-instance 7]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"0","value":"0"}],"value":"[:value 0]"}],"value":"{:time-index 7, :observe-address O44, :observe-instance 7, :value 0}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"8","value":"8"}],"value":"[:time-index 8]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"8","value":"8"}],"value":"[:observe-instance 8]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"0","value":"0"}],"value":"[:value 0]"}],"value":"{:time-index 8, :observe-address O44, :observe-instance 8, :value 0}"},{"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":time-index","value":":time-index"},{"type":"html","content":"9","value":"9"}],"value":"[:time-index 9]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-address","value":":observe-address"},{"type":"html","content":"O44","value":"O44"}],"value":"[:observe-address O44]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":observe-instance","value":":observe-instance"},{"type":"html","content":"9","value":"9"}],"value":"[:observe-instance 9]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":value","value":":value"},{"type":"html","content":"0","value":"0"}],"value":"[:value 0]"}],"value":"{:time-index 9, :observe-address O44, :observe-instance 9, :value 0}"}],"value":"[{:time-index 0, :observe-address O44, :observe-instance 0, :value 0} {:time-index 1, :observe-address O44, :observe-instance 1, :value 0} {:time-index 2, :observe-address O44, :observe-instance 2, :value 1} {:time-index 3, :observe-address O44, :observe-instance 3, :value 1} {:time-index 4, :observe-address O44, :observe-instance 4, :value 1} {:time-index 5, :observe-address O44, :observe-instance 5, :value 1} {:time-index 6, :observe-address O44, :observe-instance 6, :value 0} {:time-index 7, :observe-address O44, :observe-instance 7, :value 0} {:time-index 8, :observe-address O44, :observe-instance 8, :value 0} {:time-index 9, :observe-address O44, :observe-instance 9, :value 0}]"}
 ;; <=

 ;; @@
 (combine-observes-fn (sample-observes-from-prior pdfa [(repeat 10 nil) alphabet]))
 ;; @@
 ;; =>
-;;; {"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"0","value":"0"},{"type":"html","content":"1","value":"1"}],"value":"[0 1]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"0","value":"0"},{"type":"html","content":"1","value":"1"}],"value":"[0 1]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"0","value":"0"},{"type":"html","content":"1","value":"1"}],"value":"[0 1]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"0","value":"0"},{"type":"html","content":"1","value":"1"}],"value":"[0 1]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"0","value":"0"},{"type":"html","content":"1","value":"1"}],"value":"[0 1]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"0","value":"0"},{"type":"html","content":"1","value":"1"}],"value":"[0 1]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"}],"value":"[[0 1] [1 0] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [0 1] [1 0]]"}
+;;; {"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"0","value":"0"},{"type":"html","content":"1","value":"1"}],"value":"[0 1]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"},{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"1","value":"1"},{"type":"html","content":"0","value":"0"}],"value":"[1 0]"}],"value":"[[0 1] [1 0] [1 0] [1 0] [1 0] [1 0] [1 0] [1 0] [1 0] [1 0]]"}
 ;; <=

 ;; **
@@ -254,13 +257,15 @@
 ;; <=

 ;; @@
-(def test-observations-str (apply str (take 100 "bbbbbbbbabbabbaaabbaaabbabbaaaaaabbaaabbabbaaabbbbbbabbaaabbbbbbbbbbabbbbbbbbbbabbaabbabbbbabbbbaaaaaaaaabbabbabbaaaabbabbaaaaabbaabbabbbbabbbbbbaabbabbabbbbabbabbbbbbaaabbabbbbaaabbbbaaabbbbbbabbaaaa")))
+(def test-observations-str (map str (apply str (take 100 "bbbbbbbbabbabbaaabbaaabbabbaaaaaabbaaabbabbaaabbbbbbabbaaabbbbbbbbbbabbbbbbbbbbabbaabbabbbbabbbbaaaaaaaaabbabbabbaaaabbabbaaaaabbaabbabbbbabbbbbbaabbabbabbbbabbabbbbbbaaabbabbbbaaabbbbaaabbbbbbabbaaaa"))))
 (def test-observations (encode-string test-observations-str))
 (println test-observations-str)
 (println test-observations)
 ;; @@
 ;; ->
-;;; bbbbbbbbabbabbaaabbaaabbabbaaaaaabbaaabbabbaaabbbbbbabbaaabbbbbbbbbbabbbbbbbbbbabbaabbabbbbabbbbaaaa[[0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [1 0] [1 0] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [1 0] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [1 0] [0 1] [0 1] [1 0] [0 1] [0 1] [0 1] [0 1] [1 0] [0 1] [0 1] [0 1] [0 1] [1 0] [1 0] [1 0] [1 0]]
+;;; (b b b b b b b b a b b a b b a a a b b a a a b b a b b a a a a a a b b a a a b b a b b a a a b b b b b b a b b a a a b b b b b b b b b b a b b b b b b b b b b a b b a a b b a b b b b a b b b b a a a a)
+;;; [[0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [1 0] [1 0] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [1 0] [1 0] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [1 0] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [0 1] [1 0] [0 1] [0 1] [1 0] [1 0] [0 1] [0 1] [1 0] [0 1] [0 1] [0 1] [0 1] [1 0] [0 1] [0 1] [0 1] [0 1] [1 0] [1 0] [1 0] [1 0]]
+;;;
 ;; <-
 ;; =>
 ;;; {"type":"html","content":"nil","value":"nil"}
@@ -322,5 +327,47 @@
 ;; <=

 ;; @@
-
-;; @@
+(with-primitive-procedures [normalize]
+  (defquery even [observedsequence alphabet]
+    (let [num-states 2
+
+          emissiondist (fn [state]
+                         (if (= state 0)
+                           (categorical [["a" 0.5] ["b" 0.5]])
+                           (categorical [["a" 0.0] ["b" 1.0]]))) ; \pi
+
+          transition (fn [state symbol]
+                       (case [state symbol]
+                         [0 "a"] 0
+                         [0 "b"] 1
+                         [1 "a"] 0
+                         [1 "b"] 0)) ; \delta
+          ]
+
+      (loop [obs observedsequence
+             state [0]]
+        (if (not (empty? obs))
+          (let [currentstate (peek state)
+                _ (observe (emissiondist currentstate) (first obs))
+                nextstate (transition currentstate (first obs))]
+            (recur (rest obs)
+                   (conj state nextstate)))
+          (new-pdfa alphabet num-states transition emissiondist))))))
+
+(def num-particles 1)
+(def is-states (take num-particles (infer :importance even [test-observations-str alphabet])))
+;; @@
+;; =>
+;;; {"type":"html","content":"#'pdfa/is-states","value":"#'pdfa/is-states"}
+;; <=
+
+;; @@
+(view-top-n-pdfas is-states 1)
+;; @@
+;; =>
+;;; {"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMUAAAC1CAYAAADvGjsxAAActElEQVR42u2dCdgN5fvH21eVdqVVURElRNpLtpIWIS3SIsqWLMlSos1WtihLRISIQlJkr6iQtFEpUrJEpVU9v+tz///P23HMOWfmvHPeM2fm/l7XXC7nnbPMM893nvu5l++9mzGmjx566PHfsZtRKBQ7QUmhUCgpFAolhUIRXlL8888/ZtWqVWbWrFlm1KhR5sknnzT33Xefufvuu82tt95qbrjhBnPNNdeY+vXrm9tuu800bdrUtG/f3jz99NNm/PjxZsGCBeb777/Xu67ITVL8+++/ZsWKFWbAgAGmYcOG5pxzzjH777+/2W233fKOQw891JQsWdJUqFDBXHTRRaZq1armyiuvNFWqVDHnn3++KVeunDn11FPNAQccsNP7Dj/8cHPxxRebZs2amTFjxpjvvvtOZ4IimKTYunWrrADXX3+9TFwm8D777GMqVqxo7rzzTnniv/XWW+bLL780v//+u+fP/uSTT8wrr7xiunfvLqvJ6aefnkcUyMPK8uabb5q///5bZ4aSInv466+/xLSpUaOGEGD33Xc3lSpVMg8//LCZPXu2+e233zL6/T/++KOZOHGiadGihTn55JOFIIcddpi54447zLvvvqszRElRcFi/fr158MEHTZEiRWQiXnDBBWbgwIFZN2WWLl1qOnfunEeQs88+2zz77LPmjz/+0NmipMgM2Oi2atXK7LfffqZw4cLyhF65cmUg9zQzZsww1157rdlzzz1N0aJFZX+j5FBS+AYmU9euXWWzzAb5kUceETs/F/DFF1+IdwtynHDCCWJuKZQU+cLMmTNlI8ueoUOHDubnn3/OycHCHVyrVi0xq9gDffXVVzqDlBTe8Oeff0ocgUmEm/Szzz4LxaC99tprsuc4+OCDzdixY3UWKSnc4ZtvvjHly5c3++67r7hSwwZWu5tuukkIf9ddd8kDQKGkSIiPPvrIHHvssfI0xZsTZowYMUKIf/nll+esWajIMClIpTjkkEMkmvzDDz9EYhDnzp0rzoOyZcuajRs36qxSUuy8QuBmveSSS8wvv/wSqYHErXzUUUeZc8891/z66686s5QUxnz77bdiMpGjFFUz4sMPP5TNN56pHTt26OyKMimYAESk8eGTNhFlkJtFPOPmm282nTp1kkAlG/Hb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\" width=\"197\" height=\"181\" alt=\"\" />","value":"#object[java.awt.image.BufferedImage 0x7a3b46f8 \"BufferedImage@7a3b46f8: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@5c5bc4fa transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 197 height = 181 #numDataElements 4 dataOff[0] = 3\"]"},{"type":"html","content":"-47.13400827807628","value":"-47.13400827807628"}],"value":"[#gorilla_repl.image.ImageView{:image #object[java.awt.image.BufferedImage 0x7a3b46f8 \"BufferedImage@7a3b46f8: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@5c5bc4fa transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 197 height = 181 #numDataElements 4 dataOff[0] = 3\"], :alt \"\", :type \"png\", :width 197, :height 181} -47.13400827807628]"}],"value":"[[#gorilla_repl.image.ImageView{:image #object[java.awt.image.BufferedImage 0x7a3b46f8 \"BufferedImage@7a3b46f8: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@5c5bc4fa transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 197 height = 181 #numDataElements 4 dataOff[0] = 3\"], :alt \"\", :type \"png\", :width 197, :height 181} -47.13400827807628]]"}
+;; <=
+
+;; @@
+
+;; @@


Adapt project services to schema changes.

--- src/uxbox/services/projects.clj
+++ src/uxbox/services/projects.clj
@@ -5,8 +5,7 @@
 ;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>

 (ns uxbox.services.projects
-  (:require [mount.core :as mount :refer (defstate)]
-            [suricatta.core :as sc]
+  (:require [suricatta.core :as sc]
             [buddy.hashers :as hashers]
             [buddy.sign.jwe :as jwe]
             [buddy.core.nonce :as nonce]
@@ -22,17 +21,19 @@
 ;; Schema
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(def ^:const +project-schema+
+(def +project-schema+
   {:id [us/required us/uuid]
    :user [us/required us/uuid]
+   :name [us/required us/string]})
+
+(def +page-schema+
+  {:id [us/required us/uuid]
+   :user [us/required us/uuid]
+   :project [us/required us/uuid]
    :name [us/required us/string]
    :width [us/required us/integer]
    :height [us/required us/integer]
    :layout [us/required us/string]})
-
-(def ^:const +page-schema+
-  (assoc +project-schema+
-         :project [us/required us/uuid]))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Repository
@@ -41,20 +42,20 @@
 ;; NOTE: maybe move sql into files?

 (defn create-project
-  [conn {:keys [id user name width height layout] :as data}]
+  [conn {:keys [id user name] :as data}]
   {:pre [(us/validate! data +project-schema+)]}
-  (let [sql (str "INSERT INTO projects (id, user, name, width, height, layout)"
-                 " VALUES (?, ?, ?, ?, ?) RETURNING *")
-        sqlv [sql id user name width height layout]]
+  (let [sql (str "INSERT INTO projects (id, \"user\", name)"
+                 " VALUES (?, ?, ?) RETURNING *")
+        sqlv [sql id user name]]
     (some-> (sc/fetch-one conn sqlv)
             (usc/normalize-attrs))))

 (defn create-page
   [conn {:keys [id user project name width height layout] :as data}]
   {:pre [(us/validate! data +page-schema+)]}
-  (let [sql (str "INSERT INTO pages (id, user, project, name, width, "
+  (let [sql (str "INSERT INTO pages (id, \"user\", project, name, width, "
                  "                   height, layout)"
-                 " VALUES (?, ?, ?, ?, ?, ?) RETURNING *")
+                 " VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING *")
         sqlv [sql id user project name width height layout]]
     (some-> (sc/fetch-one conn sqlv)
             (usc/normalize-attrs))))


Break out interceptor chain into var

Break out interceptor chain into var

--- src/yada/core.clj
+++ src/yada/core.clj
@@ -462,6 +462,27 @@
 (defn as-sequential [s]
   (if (sequential? s) s [s]))

+(def default-interceptor-chain
+  [available?
+   known-method?
+   uri-too-long?
+   TRACE
+   method-allowed?
+   malformed?
+   authentication
+   authorization
+   fetch
+   ;; TODO: Unknown or unsupported Content-* header
+   ;; TODO: Request entity too large - shouldn't we do this later,
+   ;; when we determine we actually need to read the request body?
+   select-representation
+   exists?
+   check-modification-time
+   if-match
+   invoke-method
+   compute-etag
+   create-response])
+
 (defn resource
   "Create a yada resource (Ring handler)"
   ([resource]                   ; Single-arity form with default options
@@ -497,34 +518,13 @@
                               (p/representations resource)))))

          vary (rep/vary representations)
-
-         interceptors
-         [
-          available?
-          known-method?
-          uri-too-long?
-          TRACE
-          method-allowed?
-          malformed?
-          authentication
-          authorization
-          fetch
-          ;; TODO: Unknown or unsupported Content-* header
-          ;; TODO: Request entity too large - shouldn't we do this later,
-          ;; when we determine we actually need to read the request body?
-          select-representation
-          exists?
-          check-modification-time
-          if-match
-          invoke-method
-          compute-etag
-          create-response]]
+         ]

      (map->HttpResource
       {:id (or (:id options) (java.util.UUID/randomUUID))
        :resource resource
        :base base
-       :interceptors interceptors
+       :interceptors default-interceptor-chain
        :options options
        :allowed-methods allowed-methods
        :known-methods known-methods


Meta-resources

Meta-resources

Not hugely useful, but enables the yada's signature tune :-

    (-> "Hello World!" yada yada yada)

--- src/yada/core.clj
+++ src/yada/core.clj
@@ -564,7 +564,25 @@
      journal]
   clojure.lang.IFn
   (invoke [this req]
-    (handle-request this req)))
+    (handle-request this req))
+  p/ResourceProperties
+  (resource-properties
+    [this]
+    {:allowed-methods #{:get}
+     :representations [{:media-type #{"text/html"
+                                      "application/edn"
+                                      "application/json"
+                                      "application/edn;pretty=true"
+                                      "application/json;pretty=true"}}]})
+
+  (resource-properties
+    [_ ctx]
+    {}
+    )
+  methods/Get
+  (GET [this ctx] (into {} this))
+
+  )

 (defrecord NoAuthorizationSpecified []
   service/Service


Updated exporting glossary to the text format

--- src/zg/server.clj
+++ src/zg/server.clj
@@ -309,7 +309,10 @@
 (defn words->text
     [words]
     (->> (for [word words :when (= (:deleted word) 0)]
-             (str (:word word) "\t" (:description word)))
+         (clojure.string/join "\t" [(:word word) (:description word) (:user word) (:datetime word)
+                                    (:class_name word) (:source_name word) (:product word)
+                                    (:use word) (:correct_forms word) (:incorrect_forms word)
+                                    (:see_also word) (:internal word) (:verified word) (:copyrighted word)]))
          (clojure.string/join "\n")))

 (defn words->xml


CMR-5500: Add back in accidently removed requires.

--- spatial-lib/test/cmr/spatial/test/ring_generators.clj
+++ spatial-lib/test/cmr/spatial/test/ring_generators.clj
@@ -6,7 +6,16 @@
    [clojure.test :refer :all]
    [clojure.test.check.generators :as gen]
    [clojure.test.check.properties :refer [for-all]]
-   [cmr.common.test.test-check-ext :as ext-gen :refer [defspec]]))
+   [cmr.common.test.test-check-ext :as ext-gen :refer [defspec]]
+   [cmr.spatial.arc :as a]
+   [cmr.spatial.derived :as d]
+   [cmr.spatial.geodetic-ring :as gr]
+   [cmr.spatial.math :refer :all]
+   [cmr.spatial.mbr :as mbr]
+   [cmr.spatial.point :as p]
+   [cmr.spatial.ring-relations :as rr]
+   [cmr.spatial.test.generators :as sgen]
+   [cmr.spatial.validation :as v]))

 ;; Ring tests. These are functions that return true if the ring is correct and false if invalid.


Addd cmd-only-items fn to history model

Addd cmd-only-items fn to history model

--- src/yetibot/core/models/history.clj
+++ src/yetibot/core/models/history.clj
@@ -34,17 +34,25 @@
   (filter #(= (-> % :user :id) (:id user)) (items-with-user chat-source)))

-;; non-cmd history
-(def ^:private history-ignore #"^\!")
+;; history filters
+(def ^:private cmd-history #"^\!")
+(def ^:private non-cmd-history #"^[^!]")
+
+(defn filter-history-by [re last-n]
+  (->> (history)
+       (take-last last-n)
+       reverse
+       (filter (fn [[_ body]] (re-find re body)))))

 (defn non-cmd-items
   "Return `chat-item` only if it doesn't match any regexes in `history-ignore`"
   [chat-source]
-  (->> (history)
-       (take-last 100)
-       reverse
-       (filter (fn [[_ body]] (not (re-find history-ignore body))))
-       first))
+  (filter-history-by non-cmd-history 100))
+
+(defn cmd-only-items
+  "Return `chat-item` only if it does match any regexes in `history-ignore`"
+  [chat-source]
+  (filter-history-by cmd-history 100))

 ;;;; write


Make buttons identifiable

Make buttons identifiable

--- desktop/src-common/nightmod/core.clj
+++ desktop/src-common/nightmod/core.clj
@@ -7,14 +7,17 @@
   (fn [screen entities]
     (update! screen :renderer (stage) :camera (orthographic))
     (let [ui-skin (skin "uiskin.json")
-          saved-games (map #(text-button % ui-skin) [])]
-      (-> [(label "New Game:" ui-skin)
-           (text-button "Arcade" ui-skin)
-           (text-button "Platformer" ui-skin)
-           (text-button "Orthogonal RPG" ui-skin)
-           (text-button "Isometric RPG" ui-skin)
-           (text-button "Barebones 2D" ui-skin)
-           (text-button "Barebones 3D" ui-skin)]
+          create-button (fn [[k v]]
+                          (text-button v ui-skin :set-name k))
+          templates [["arcade" "Arcade"]
+                     ["platformer" "Platformer"]
+                     ["orthogonal-rpg" "Orthogonal RPG"]
+                     ["isometric-rpg" "Isometric RPG"]
+                     ["barebones-2d" "Barebones 2D"]
+                     ["barebones-3d" "Barebones 3D"]]
+          new-games (map create-button templates)
+          saved-games (map create-button [])]
+      (-> (cons (label "New Game:" ui-skin) new-games)
           (concat (when (seq saved-games)
                     (cons (label "Load Game:" ui-skin) saved-games)))
           vertical


make inspect sort slightly smarter

make inspect sort slightly smarter

otherwise no sort for maps using more than one key type

--- src/main/shadow/remote/runtime/obj_support.cljc
+++ src/main/shadow/remote/runtime/obj_support.cljc
@@ -115,10 +115,38 @@
      :cljs true ;; (instance? js/Error x)
      ))

+(def rank-predicates
+  [nil?
+   boolean?
+   number?
+   string?
+   keyword?
+   symbol?
+   vector?
+   map?
+   list?])
+
+(defn rank-val [val]
+  (reduce-kv
+    (fn [res idx pred]
+      (if (pred val)
+        (reduced idx)
+        res))
+    -1
+    rank-predicates))
+
+(defn smart-comp [a b]
+  (try
+    (compare a b)
+    (catch #?(:clj Exception :cljs js/Error) e
+      (let [ar (rank-val a)
+            br (rank-val b)]
+        (compare ar br)))))
+
 (defn attempt-to-sort [desc coll]
   (try
     (-> desc
-        (assoc :view-order (vec (sort coll)))
+        (assoc :view-order (vec (sort smart-comp coll)))
         (assoc-in [:summary :sorted] true))
     (catch #?(:clj Exception :cljs :default) e
       (-> desc


correct point

correct point

--- server/project.clj
+++ server/project.clj
@@ -26,7 +26,7 @@
                  [org.clojure/data.json "0.2.2"]
                  [me.raynes/cegdown "0.1.0"]
                  [com.draines/postal "1.11.0"]
-                 [com.flyingmachine/penny-black-apache "0.1.0"]
+                 [com.flyingmachine/penny-black-apache-commons "0.1.0"]
                  [org.apache.commons/commons-email "1.2"]
                  [stencil "0.3.2"]
                  [clj-time "0.6.0"]]


Avoid double comparison

Avoid double comparison

--- src/aurora/btree.cljs
+++ src/aurora/btree.cljs
@@ -49,11 +49,11 @@
             lo
             (let [mid (+ lo (js/Math.floor (/ (- hi lo) 2)))
                   mid-key (aget keys mid)]
-              (if (gt mid-key key)
-                (recur lo (- mid 1))
-                (if (lt mid-key key)
-                  (recur (+ mid 1) hi)
-                  mid))))))
+              (if (lt mid-key key)
+                (recur (+ mid 1) hi)
+                (if (== mid-key key)
+                  mid
+                  (recur lo (- mid 1))))))))
   (assoc! [this key val max-keys]
           (set! lower (if (lt lower key) lower key))
           (set! upper (if (lt key upper) upper key))


Sketch on the new join

Sketch on the new join

--- src/aurora/btree.cljs
+++ src/aurora/btree.cljs
@@ -363,12 +363,13 @@
     tree))

 ;; ITERATORS
-;; .key / .val return key and val currently pointed at
+;; .key / .val return key and val currently pointed at. key may be aliased
 ;; On creation/reset, points to first key
 ;; On next, either point to next key or set .-end? true. Return (not .-end?)
 ;; On seek, point to first key greater than or equal to seek-key. Return (key= (.key this) seek-key)
 ;; NOTE iterators are not write-safe unless reset after writing

+;; TODO think we might need to be able to get last key on end
 (deftype Iterator [tree ^:mutable node ^:mutable ix ^:mutable end? key-len]
   Object
   (reset [this]
@@ -480,100 +481,32 @@

 (deftype Join [current-key iterators ^:mutable end?]
   Object
+  (maintain [this]
+            ;; if all equal, done
+            ;; if all blocked but max, .next on max
+            ;; if all blocked, set end? true
+            ;; otherwise seek smallest non-blocked to max, recur
+            )
   (reset [this]
          (debug)
          (debug :reset)
-         (set! end? false)
+         (dotimes [i (alength current-key)]
+           (aset current-key i least))
          (dotimes [i (alength iterators)]
            (.reset (aget iterators i)))
-         (dotimes [i (alength seek-key)]
-           (aset seek-key i least))
-         (.search this -1 0 0))
+         (set! end? false)
+         (.maintain this))
   (key [this]
        (when (false? end?)
-         (aclone seek-key)))
-  (search [this old-var new-var current]
-          (cond
-
-           (== old-var new-var)
-           ;; ACROSS: assumes prefixes all equal, keys not all equal, iterators sorted by ascending key, nothing at end
-           (let [var-iterators (aget var->iterators new-var)
-                 num-var-iterators (alength var-iterators)
-                 previous (mod (- current 1) num-var-iterators)
-                 max-key (.key-at (aget var-iterators previous) new-var)
-                 iterator (aget var-iterators current)
-                 min-key (.key-at iterator new-var)
-                 old-key (.outer-key iterator)]
-             (debug :across max-key current seek-key)
-             (aset seek-key new-var max-key)
-             (.seek iterator seek-key)
-             (if (true? (.end? iterator))
-               (do
-                 (.undo iterator)
-                 (recur new-var (- new-var 1) 0))
-               (let [new-key (.outer-key iterator)]
-                 (if (and (not (nil? old-key)) (prefix-not= old-key new-key new-var))
-                   (do
-                     (.undo iterator)
-                     (recur new-var (- new-var 1) 0))
-                   (if (== (.key-at iterator new-var) max-key)
-                     (do
-                       (aset seek-key new-var max-key)
-                       (recur new-var (+ new-var 1) 0))
-                     (recur new-var new-var (mod (+ current 1) num-var-iterators)))))))
-
-           (< new-var old-var)
-           ;; UP: assumes prefixes and keys all equal, nothing at end
-           (if (== old-var 0)
-             (set! end? true)
-             (let [new-var (- old-var 1)
-                   var-iterators (aget var->iterators new-var)
-                   iterator (aget var->nextable (- (alength var-iterators) 1))]
-               (debug :up old-var seek-key)
-               (when (< old-var (alength var->iterators))
-                 (aset seek-key old-var least)
-                 (let [iterator->push|pop? (aget var->iterator->push|pop? old-var)]
-                   (dotimes [i (alength iterators)]
-                     (when (true? (aget iterator->push|pop? i))
-                       (debug :popping i :at old-var)
-                       (.pop (aget iterators i))))))
-               (let [old-key (.inner-key iterator)]
-                 (.next iterator)
-                 (if (true? (.end? iterator))
-                   (do
-                     (.undo iterator)
-                     (recur new-var (- new-var 1) 0))
-                   (let [new-key (.inner-key iterator)]
-                     (if (prefix-not= old-key new-key new-var)
-                       (do
-                         (.undo iterator)
-                         (recur new-var (- new-var 1) 0))
-                       (recur new-var new-var 0)))))))
-
-           (> new-var old-var)
-           ;; DOWN: assumes prefixes all equal, nothing at end
-           (if (== old-var (- (alength var->iterators) 1))
-             (debug :done seek-key)
-             (let [new-var (+ old-var 1)
-                   var-iterators (aget var->iterators new-var)
-                   iterator->push|pop? (aget var->iterator->push|pop? new-var)]
-               (debug :down old-var old-key seek-key)
-               (dotimes [i (alength iterators)]
-                 (when (true? (aget iterator->push|pop? i))
-                   (debug :pushing i :at new-var)
-                   (.push (aget iterators i))))
-               (js/goog.array.sort var-iterators (fn [i0 i1] (compare (.key-at i0 new-var) (.key-at i1 new-var))))
-               (if (== (.key-at (aget var-iterators 0) new-var) (.key-at (aget var-iterators (- (alength var-iterators) 1)) new-var))
-                 (do
-                   (aset seek-key new-var (.key-at (aget var-iterators 0) new-var))
-                   (recur new-var (+ new-var 1) 0))
-                 (recur new-var new-var 0))))))
+         current-key))
   (next [this]
-        (debug)
-        (debug :next seek-key)
-        (when (false? end?)
-          (.search this (alength var->iterators) (- (alength var->iterators) 1) 0))
-        (false? end?)))
+        ;; .next on smallest non-blocked iter
+        ;; maintain
+        )
+  (seek [this key]
+        ;; .seek on all iters
+        ;; maintain
+        ))

 (defn join [iterators num-vars iterator->var->nextable? iterator->var->present?]
   (let [seek-key (least-key num-vars)
@@ -660,7 +593,7 @@
   ([n iterator]
    (let [results #js []]
      (while (and (false? (.-end? iterator)) (< (alength results) n))
-       (.push results (.key iterator))
+       (.push results (aclone (.key iterator)))
        (.next iterator))
      results)))


Add a meaningful message when no nimbus participant is found.

--- storm-core/src/clj/backtype/storm/zookeeper.clj
+++ storm-core/src/clj/backtype/storm/zookeeper.clj
@@ -218,7 +218,9 @@

 (defn- to-NimbusInfo [^Participant participant]
   (let
-    [id (.getId participant)
+    [id (if (clojure.string/blank? (.getId participant))
+          (throw (RuntimeException. "No nimbus leader participant host found, have you started your nimbus hosts?"))
+          (.getId participant))
      server (first (.split id ":"))
      port (Integer/parseInt (last (.split id ":")))
      is-leader (.isLeader participant)]


[STORM-2119] - bug in log message printing to stdout

--- storm-core/src/clj/org/apache/storm/ui/core.clj
+++ storm-core/src/clj/org/apache/storm/ui/core.clj
@@ -984,7 +984,7 @@
                                "dumplink" (worker-dump-link (:host profile-action) (str (:port profile-action)) topology-id)
                                "timestamp" (str (- (:timestamp profile-action) (System/currentTimeMillis)))})
                             latest-profile-actions)]
-    (log-message "Latest-active actions are: " (pr active-actions))
+    (log-message "Latest-active actions are: " (pr-str active-actions))
     active-actions))

 (defn component-page


Using local path for log

Using local path for log

--- src/celestial/api.clj
+++ src/celestial/api.clj
@@ -14,7 +14,7 @@
     [compojure.handler :as handler]
     [compojure.route :as route]))

-(set-config! [:shared-appender-config :spit-filename ] "/home/ronen/code/celestial/celestial.log")
+(set-config! [:shared-appender-config :spit-filename ] "celestial.log")
 (set-config! [:appenders :spit :enabled?] true)

 (defn generate-response [data & [status]]


Fix bug that left running logcat processes


* src/clj/cljs/core.clj: fix fast path protocols

--- src/clj/cljs/core.clj
+++ src/clj/cljs/core.clj
@@ -45,7 +45,7 @@

 (def fast-path-protocols
   "protocol fqn -> [partition number, bit]"
-  (zipmap (map #(symbol (core/str "cljs.core." %))
+  (zipmap (map #(symbol "cljs.core" (core/str %))
                '[IFn ICounted IEmptyableCollection ICollection IIndexed ASeq ISeq INext
                  ILookup IAssociative IMap IMapEntry ISet IStack IVector IDeref
                  IDerefWithTimeout IMeta IWithMeta IReduce IKVReduce IEquiv IHash


add comments on virus counter tracking

add comments on virus counter tracking

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -468,6 +468,7 @@
   ([state side card key n] (add-prop state side card key n nil))
   ([state side card key n {:keys [placed] :as args}]
     (update! state side (update-in card [key] #(+ (or % 0) n)))
+   ;If the counter is for a virus, flag the virus as having added a counter this turn.
    (if (= (:counter-type card) "Virus") (update! state side (assoc card :added-virus-counter true)))
     (if (= key :advance-counter)
       (do (when (and (#{"ICE"} (:type card)) (:rezzed card)) (update-ice-strength state side card))
@@ -1368,6 +1369,7 @@
             hosted-cards (filter :installed (mapcat :hosted rig-cards))
             hosted-on-ice (->> (get-in @state [:corp :servers]) seq flatten (mapcat :ices) (mapcat :hosted))]
         (doseq [card (concat rig-cards hosted-cards hosted-on-ice)]
+          ;Clear the added-virus-counter flag for each virus in play.
           (when (or (has? card :subtype "Virus") (= (:counter-type card) "Virus"))
             (set-prop state :runner card :added-virus-counter false))))
       (swap! state assoc :end-turn true)
@@ -1497,6 +1499,7 @@
                    (system-msg state side (str (build-spend-msg cost-str "install") title
                                             (when host-card (str " on " (:title host-card)))
                                             (when no-cost " at no cost")))))
+                 ;Apply added-virus-counter flag for this turn if the card enters play with a counter
                  (if (and (= (:counter-type installed-card) "Virus") (> (:counter installed-card) 0))
                    (update! state side (assoc installed-card :added-virus-counter true))
                    )


Don't auto pay run credits for credit costs

There's just too many possible interactions with other mechanics
(e.g. recurring credits) to be able to automate when to use
run credits or not. Just leave it to the user to exchange the
run credits for real credits when credits are spent.

See github issue #454.

--- src/clj/game/core.clj
+++ src/clj/game/core.clj
@@ -29,29 +29,14 @@
         scored (get-in @state [side :scored])]
     (if (and (every?
                (fn [[attr cost]]
-                 (if (and (= side :runner) (= attr :cost))
-                   (>= (- (+ (get-in @state [:runner :credit]) (get-in @state [:runner :run-credit])) cost) 0)
-                   (>= (- (get-in @state [side attr]) cost) 0)))
+                 (>= (- (get-in @state [side attr]) cost) 0))
                costs)
              (or (not forfeit-cost) (not (empty? scored))))
       {:costs costs, :forfeit-cost forfeit-cost, :scored scored}
     )))

-(defn lose-credit [state side cost]
-  (if (= side :runner)
-    (swap! state
-      (fn [old-state]
-        (let [run-credit-to-use (min (get-in old-state [:runner :run-credit]) cost)
-              cost-remaining (- cost run-credit-to-use)]
-          (-> old-state
-            (update-in [:runner :run-credit] - run-credit-to-use)
-            (update-in [:runner :credit] - cost-remaining)))))
-    (swap! state update-in [:corp :credit] #(- % cost))))
-
 (defn apply-loss [state side [attr value]]
-  (if (= attr :credit)
-    (lose-credit state side value)
-    (swap! state update-in [side attr] #(- (or % 0) value))))
+  (swap! state update-in [side attr] #(- (or % 0) value)))

 (defn pay [state side card & args]
   (when-let [{:keys [costs forfeit-cost scored]} (apply can-pay? state side args)]


Add namespace.tools refresh.

Add namespace.tools refresh.

--- src/clj/pfrt/main.clj
+++ src/clj/pfrt/main.clj
@@ -3,6 +3,7 @@
             [pfrt.web :refer [web-server]]
             [pfrt.core.app :as app]
             [pfrt.settings :as settings])
+  (:use clojure.tools.namespace.repl)
   (:gen-class))

 ;; Global var, only used for store
@@ -13,20 +14,20 @@
 ;; System private constructor with
 ;; clear and explicit dependency injection
 ;; on each app components.
-(defn- make-app []
+(defn- make-app
+  []
   (let [config    (settings/cfg)
         pf        (packet-filter config)
         webserver (web-server config pf)]
     (-> (app/->App [pf webserver])
-        (assoc :config config)
         (app/init))))

 ;; Start function that should
 ;; only be used from REPL.
-(defn start []
-  (alter-var-root #'main-app
-    (constantly (make-app)))
-  (start main-app))
+(defn start
+  []
+  (alter-var-root #'main-app (constantly (make-app)))
+  (app/start main-app))

 ;; Stop function that should
 ;; only be used from REPL.
@@ -36,8 +37,8 @@
 ;; Helper function that executes
 ;; stop and start.
 (defn restart []
-  (start)
-  (stop))
+  (stop)
+  (refresh :after 'pfrt.main/start))

 ;; Main entry point
 (defn -main


removed nonsense declares

removed nonsense declares

--- src/crawler/crawl.clj
+++ src/crawler/crawl.clj
@@ -19,10 +19,6 @@
       (cons v acc)))
   []
   coll))
-
-(declare extractor) ; the extraction module must be assigned before
-                                        ; crawl is called
-(declare )

 (defn crawl-richest
   "Main crawl routine


Erase non-existent dep

Erase non-existent dep


Update server.clj

Update server.clj

--- src/falkor/server.clj
+++ src/falkor/server.clj
@@ -22,10 +22,8 @@
         (json-handler 500
           {:body "Request failed"}))))))

-(defn root-handler
-  []
-  (json-handler 200
-    {:body "OK"}))
+(defn root-handler []
+  (json-handler 200 {:body "OK"}))

 (defroutes api-routes
   (GET "/api/query" {params :query-params}


Need to javaize extensions list

Need to javaize extensions list

--- src/clojure/puppetlabs/certificate_authority/core.clj
+++ src/clojure/puppetlabs/certificate_authority/core.clj
@@ -325,7 +325,7 @@
            (extension-list? extensions)]
     :post [(certificate-request? %)]}
    (CertificateAuthority/generateCertificateRequest
-     keypair subject-dn extensions)))
+     keypair subject-dn (javaize extensions))))

 (defn sign-certificate
   "Given a subject, certificate authority information and other certificate info,


Fixed RSS feed

Fixed RSS feed

--- src/sdos_site/article.clj
+++ src/sdos_site/article.clj
@@ -30,7 +30,7 @@
 (defn find-all-articles
   [db]
   (-> (base-query db)
-      (k/select)))
+      (k/select (k/order :id :DESC))))

 (defn find-article
   [db id]


add milliseconds, clean up code

add milliseconds, clean up code

--- src/edge/clock.cljs
+++ src/edge/clock.cljs
@@ -3,79 +3,76 @@

  (enable-console-print!)

+(def clock-state (r/atom {:current-time (js/Date.)}))
+
+(def stopwatch-state (atom 0)) ;;0 represents pause, 1 start
+
+(def clock-atom (atom 0))
+
+(def start-time (atom 0))
+
+(def time-fn (atom inc)) ;; inc for stopwatch, dec for countdown
+
+(defonce interval (atom 0))

-(def clock-state (r/atom {:current-time (js/Date.)}))

-(def stopwatch-state (atom 0)) ;0 represents pause, 1 start
+(defn stopwatch-started? []
+  (if (= @stopwatch-state 0)
+    false
+    true))

 (defn tick [] dosync
   (swap! clock-state assoc :current-time (js/Date.)))

-(defn seconds-to-time
-  [secs]
-  (let [d (js/Date. (* secs 1000))]
+(defn seconds-to-time [secs]
+  (let [d (js/Date. (* 10 secs))]
     {:hours   (.getUTCHours d)
      :minutes (.getUTCMinutes d)
-     :seconds (.getUTCSeconds d)}))
+     :seconds (.getUTCSeconds d)
+     :milliseconds (.getUTCMilliseconds d)}))

-(defn display-time
-  "Pretty-prints minutes:seconds, given time map of the form {:hours x :seconds y}."
-  [tm]
+(defn display-time [tm]
   (let [pad (fn [n]
               (if (< n 10)
                 (str "0" n)
                 n))
         mm (pad (:minutes tm))
-        ss (pad (:seconds tm))]
-    (str mm ":" ss)))
-
-(def clock-atom (atom 0))
-(def start-time (atom 0))
-
-(def time-fn (atom inc)) ;; included so we can swap it out for countdowns
+        ss (pad (:seconds tm))
+        ms (pad (/ (:milliseconds tm) 10))]
+    (str mm ":" ss ":" ms)))

 (defn keep-time [func]
   (display-time (seconds-to-time @clock-atom))
   (swap! clock-atom func))

-(defonce interval (atom 0))
-
 (defn pause []
-  (if (= @stopwatch-state 1)
-    (do
-      (swap! stopwatch-state dec)
-      (js/clearInterval @interval))))
+  (when (stopwatch-started?)
+    (swap! stopwatch-state dec)
+    (js/clearInterval @interval)))

 (defn start []
-  (if (= @stopwatch-state 0)
-    (do
-      (swap! stopwatch-state inc)
-      (reset! interval (js/setInterval #(keep-time @time-fn) 1000)))))
+  (when-not (stopwatch-started?)
+    (swap! stopwatch-state inc)
+    (reset! interval (js/setInterval #(keep-time @time-fn) 10))))

 (defn reset []
   (reset! stopwatch-state 0)
   (js/clearInterval @interval)
   (reset! clock-atom @start-time))

-
-
-
-
-
  (defn clock []
-   (let [time-now (:current-time @clock-state)
-         val (r/atom 5)]
+   (let [time-now (:current-time @clock-state)]
      [:div.clock
-      [:h1 "time = " (str time-now)]
+      [:h1 "Date = " (str time-now)]
       [:h1  "stopwatch = " (display-time (seconds-to-time @clock-atom))]
-      [:h3 "Stopwatch state = " (str @stopwatch-state)]
       [:button {:on-click (fn [ev] (start))} "Start!"]
       [:button {:on-click (fn [ev] (pause))} "Pause!"]
       [:button {:on-click (fn [ev] (reset))} "Reset!"]]))

-(.setInterval js/window tick 500)
+

 (defn init [section]
- (r/render-component [clock] section))
+  (.setInterval js/window tick 100)
+  (r/render-component [clock] section))


Write documents of some functions in jungerer.algo

--- src/jungerer/algo.clj
+++ src/jungerer/algo.clj
@@ -31,28 +31,46 @@
 ;; ------

 (defn barycenter-scorer
+  "Returns an edu.uci.ics.jung.algorithms.scoring.BarycenterScorer for graph. It
+  can be used for calculating scores for each node according to the sum of its
+  distances to all other nodes."
   [graph]
   (BarycenterScorer. graph))

 (defn degree-scorer
+  "Returns an edu.uci.ics.jung.algorithms.scoring.DegreeScorer for graph. It can
+  be used for calculating scores for each node equal to its degree."
   [graph]
   (DegreeScorer. graph))

 (defn betweenness-centrality
+  "Returns an edu.uci.ics.jung.algorithms.scoring.BetweennessCentrality for
+  graph. It can be used for calculating betweenness centrality for each node and
+  edge in the graph."
   [graph]
   (BetweennessCentrality. graph))

 (defn closeness-centrality
+  "Returns an edu.uci.ics.jung.algorithms.scoring.ClosenessCentrality for graph.
+  It can be used for calculating scores for each node based on the mean distance
+  to each other node."
   ([graph]
    (ClosenessCentrality. graph))
   ([^Hypergraph graph ^Distance distance]
    (ClosenessCentrality. graph distance)))

 (defn eigenvector-centrality
+  "Returns an edu.uci.ics.jung.algorithms.scoring.EigenvectorCentrality for
+  graph. It can be used for calculating eigenvector centrality for each node in
+  the graph. The 'eigenvector centrality' for a node is defined as the fraction
+  of time that a random walk(er) will spend at that node over an infinite time
+  horizon. Assumes that the graph is strongly connected."
   [graph]
   (EigenvectorCentrality. graph))

 (defn page-rank
+  "Returns an edu.uci.ics.jung.algorithms.scoring.PageRank for graph. It can be
+  used for calculating scores for each node according to the PageRank algorithm."
   ([graph]
    (page-rank graph 0.15))
   ([graph alpha]
@@ -60,6 +78,9 @@
      (.evaluate))))

 (defn hits
+  "Returns an edu.uci.ics.jung.algorithms.scoring.HITS for graph. It can be used
+  for calculating hub and authority scores to each node depending on the
+  topology of the network."
   [graph]
   (doto (HITS. graph)
     (.evaluate)))
@@ -67,5 +88,7 @@
 ;;

 (defn score
+  "Returns a score of node calculated with scorer algorithm. Note that type of
+  the returned score is different depending on the scorer."
   [^VertexScorer scorer node]
   (.getVertexScore scorer node))


SER-2225 | use status code

SER-2225 | use status code

--- src/vignette/storage/s3.clj
+++ src/vignette/storage/s3.clj
@@ -121,7 +121,7 @@
       (not (empty? (s3/list-objects creds bucket {:prefix path :max-keys 1})))
       (catch AmazonS3Exception e
         ; list-objects will throw access denied error on missing paths
-        (if (or (= (.getErrorCode e) "AccessDenied") (= (.getErrorCode e) "NoSuchBucket")) false (throw e)))))
+        (if (or (= (.getErrorCode e) "AccessDenied") (= (.getStatusCode e) 404)) false (throw e)))))
   (list-buckets [this])
   (list-objects [this bucket path]
     (perf/timing :s3-list-objects (s3/list-objects creds bucket {:prefix path}))))


Improved formatting

Improved formatting

--- src/leiningen/new/onyx_app/src/onyx_app/lifecycles/sample_lifecycle.clj
+++ src/leiningen/new/onyx_app/src/onyx_app/lifecycles/sample_lifecycle.clj
@@ -64,10 +64,8 @@
    Detects input/output automatically. Supports one input and one output."
   [{:keys [catalog lifecycles uuid] :as job}]
   (assert (and (sequential? catalog) (sequential? lifecycles)) "must supply a map of the form {:catalog [...] :lifecycles [...]")
-  (let [inputs  (u/find-task-by-key catalog :onyx/plugin
-                                    :onyx.plugin.core-async/input)
-        outputs (u/find-task-by-key catalog :onyx/plugin
-                                    :onyx.plugin.core-async/output)]
+  (let [inputs  (u/find-task-by-key catalog :onyx/plugin :onyx.plugin.core-async/input)
+        outputs (u/find-task-by-key catalog :onyx/plugin :onyx.plugin.core-async/output)]
     (u/add-to-job job
                   {:lifecycles
                    (mapcat #(remove nil? %)


core.async: Comments.

core.async: Comments.

--- test/com/nomistech/clojure_the_language/core_async_mapping_etc_test.clj
+++ test/com/nomistech/clojure_the_language/core_async_mapping_etc_test.clj
@@ -117,7 +117,7 @@
 ;;;; Motivation
 ;;;; ==========
 ;;;;
-;;;; You can do this...
+;;;; 1. For removing nils, you can do this...

 (comment
   (let [c (a/chan)]
@@ -126,6 +126,9 @@
     c))

 ;;;; ...but that doesn't play nicely in a mappy/filtery context.
+
+;;;; 2. Might want to pass nils through.
+;;;;    - Although Googling suggests this is wrong-headed.

 ;;;; What to do about it


applying validations for add and update from

--- src_cljs/rrms/corecljs.cljs
+++ src_cljs/rrms/corecljs.cljs
@@ -56,11 +56,14 @@
   (xhr/send url callback "DELETE"  (structs/Map. (clj->js {:Content-Type "application/json"}))))

-;; login functions
-(defn validator [data-set]
+;; =====================================================================================================
+;; login-form with validations
+;; =====================================================================================================
+
+(defn login-validator [data-set]
   (first (b/validate data-set
-                     :username-email [[v/required :message "Filed is required"]
-                                      [v/email :message "Enter valid email-id"]]
+                     :email [[v/required :message "Filed is required"]
+                             [v/email :message "Enter valid email-id"]]
                      :password [[v/required :message "Filed is required"]
                                 [v/string  :message "Enter valid password"]])))

@@ -74,7 +77,7 @@
                         }])

-(defn input-validate [id label span-class ttype data-set placeholder focus]
+(defn login-input-element [id label span-class ttype data-set placeholder focus]
   (let [input-focus (r/atom nil)]
     (fn []
       [:div.form-group
@@ -84,29 +87,27 @@
          [:span {:class span-class}]
          [input-element id ttype data-set placeholder input-focus]]
         (if (or @input-focus @focus)
-          (if (= nil (validator @data-set))
+          (if (= nil (login-validator @data-set))
             [:div]
-            [:div {:style  {:color "red"}}
-             [:b
-              (str (first ((validator @data-set) id)))]]  )
+            [:div {:style  {:color "red"}} [:b (str (first ((login-validator @data-set) id)))]])
           [:div])]])))

 (defn submit-login [data-set focus]
-  (if (= nil (validator @data-set))
-    (let [onresp (fn [json] (if (= (get-status json) 200) ((set-key-value :user (getdata json))
-                                                          (secretary/dispatch! "/documents"))))]
+  (if (= nil (login-validator @data-set))
+    (let [onresp (fn [json]
+                   (if (= (get-status json) 200)
+                     ((set-key-value :user (getdata json))
+                      (secretary/dispatch! "/documents"))))]
       (http-post "http://localhost:8193/user/authenticate"
-                 onresp (.serialize (Serializer.)
-                                    (clj->js {:email (getinputvalue "username-email")
-                                              :password (getinputvalue "password")} ))))
+                 onresp (.serialize (Serializer.) (clj->js @data-set ))))
     (reset! focus "yes")))

-(defn button [value ttype data-set focus]
+(defn sign-in-button [data-set focus]
   [:div.form-group
    [:div.col-md-6
-    [:button.btn.btn-primary {:type ttype
-                              :on-click #(submit-login data-set focus)} value]]])
+    [:button.btn.btn-primary {:type "button"
+                              :on-click #(submit-login data-set focus)} "Sign-in"]]])

 (defn login []
   (let [my-data (r/atom  {})
@@ -117,9 +118,13 @@
         [:div.panel-heading
          [:h2 "Log-in"]]
         [:div.panel-body
-         [input-validate :username-email "Email"  "input-group-addon glyphicon glyphicon-user" "email" my-data "Email" focus]
-         [input-validate :password "Password"  "input-group-addon glyphicon glyphicon-lock" "password" my-data "password" focus]
-         [button "Sign-in" "button" my-data focus ]]]])))
+         [login-input-element :email "Email"  "input-group-addon glyphicon glyphicon-user" "email" my-data "Email" focus]
+         [login-input-element :password "Password"  "input-group-addon glyphicon glyphicon-lock" "password" my-data "password" focus]
+         [sign-in-button my-data focus ]]]])))
+
+;; ====================================================================================================
+;; end of login-form
+;; ====================================================================================================

 (defn is-authenticated? []
   (not (nil? (get-value! :user))))
@@ -235,39 +240,93 @@
                         (get-new-page-data (get-value! :documents)
                                            (get-value! :current-page))]))))

-
-(defn row [label input]
-  [:div.row
-   [:div.col-md-2 [:label label]]
-   [:div.col-md-5 input]])
-
-(defn radio [label name value]
-  [:div.radio
-   [:label
-    [:input {:field :radio :name name :value value}]
-    label]])
-
-(defn input
-  ([label type id value]
-   (row label [:input.form-control {:type type :id id :defaultValue value}]))
-  ([label type id]
-   (input label type id "")))
-
-(defn get-documents-formdata []
-  {:documentname (getinputvalue "documentname")
-   :title (getinputvalue "title")
-   :employeename (getinputvalue "employeename")
-   :date (getinputvalue "date")
-   :location (getinputvalue "location") })
-
-(defn save [event]
-  (let [onres (fn[json] (do
-                         (set-key-value :documents (getdata json))
-                         (set-key-value :page-location
-                                        [render-documents (get-new-page-data (get-value! :documents)
-                                                                             (get-value! :current-page))])))]
-    (http-post "http://localhost:8193/documents/add"
-               onres  (.serialize (Serializer.) (clj->js (get-documents-formdata))))))
+;; ========================================================================================
+;; Add and Update form creation validation
+;; ========================================================================================
+
+(defn form-validator [data-set]
+  (first (b/validate data-set
+                     :documentname [[v/required :message "Filed is required"]
+                                    [v/string :message "Enter valid Document Name"]]
+                     :title [[v/required :message "Filed is required"]
+                             [v/string :message "Enter valid Title"]]
+                     :employeename [[v/required :message "Filed is required"]
+                                    [v/string  :message "Enter valid Employee name"]]
+                     :date [[v/required :message "Filed is required"]
+                            [v/datetime  :message "Enter valid Date"]]
+                     :location [[v/required :message "Filed is required"]
+                                [v/string  :message "Enter valid Location"]])))
+
+(defn form-input-element [id label ttype data-set focus]
+  (let [input-focus (r/atom nil)]
+    (fn []
+      [:div.form-group
+       [:div.col-md-12
+        [:div.row
+         [:div.col-md-2 [:label label]]
+         [:div.col-md-6 [input-element id ttype data-set label input-focus]]
+         [:div.col-md-4 (if (or @input-focus @focus)
+                          (if (= nil (form-validator @data-set))
+                            [:div]
+                            [:div {:style  {:color "red"}}
+                             [:b (str (first ((form-validator @data-set) id)))]])
+                          [:div])]]]] )))
+
+
+(defn button [data-set focus fun value]
+  [:button.btn.btn-primary {:type "button"
+                            :on-click fun} value] )
+
+(defn form-save [data-set focus]
+  (if (= nil (form-validator @data-set))
+    (let [onres (fn[json]
+                  (do
+                    (set-key-value :documents (getdata json))
+                    (set-key-value :page-location
+                                   [render-documents (get-new-page-data (get-value! :documents)
+                                                                        (get-value! :current-page))])))]
+      (http-post "http://localhost:8193/documents/add"
+                 onres  (.serialize (Serializer.) (clj->js @data-set))))
+    (reset! focus "on")))
+
+(defn form-cancel [event]
+  (secretary/dispatch! "/documents"))
+
+(defn document-template-form [doc-name data-set focus]
+  [:div#add.container
+   [:div.panel.panel-primary.model-dialog
+    [:div.panel-heading
+     [:h2 doc-name]]
+    [:div.panel-boby
+     [:div.container
+      [:div.form-group
+       [form-input-element :documentname "Document Name" "text" data-set focus]
+       [form-input-element :title "Title" "text" data-set focus ]
+       [form-input-element :employeename "Employee name" "text" data-set focus]
+       [form-input-element :date "Date" "date" data-set focus]
+       [form-input-element :location "Location" "text" data-set focus]
+       [button data-set focus #(form-save data-set focus) "Save"]
+       [button data-set focus form-cancel "cancel"]]]]]])
+
+(defn document-update-template1 [id dmt]
+  (let [add-data (r/atom {:documentname (.-documentname dmt)
+                          :title (.-title dmt)
+                          :employeename (.-employeename dmt)
+                          :date (f/unparse (f/formatter "yyyy-MM-dd")(f/parse (.-date dmt)))
+                          :location (.-location dmt)})
+        focus (r/atom nil)]
+    (fn [] [document-template-form "Update Document" add-data focus])))
+
+(defn document-template1 []
+  (let [add-data (r/atom {})
+        focus (r/atom nil)]
+    (fn [] [document-template-form "New Document" add-data focus])))
+
+;; ===============================================================================================
+;; end of add-update form coding
+;; ===============================================================================================
+
+

 (defn get-all-click [event]
   (let [onres (fn [json]
@@ -280,48 +339,14 @@
                                                                       (get-value! :current-page))])))]
     (http-get "http://localhost:8193/documents/all" onres)))

-(defn document-template []
-  [:div {:id "add" :class "form-group"}
-   [:div#dn (input "Documentname" :text :documentname )]
-   [:div#tl (input "Title" :text :title)]
-   [:div#empn (input "EmployeeName" :text :employeename)]
-   [:div#dt (input "Date":Date :date)]
-   [:div#loc (input "Location":text :location)]
-   [:input {:type "button" :value "Save"
-            :class "btn btn-primary" :on-click save}]
-   [:input {:type "button" :value "Cancel"
-            :class "btn btn-primary" :on-click cancel}]])
-
-(defn get-update-documents-formdata []
-  {
-   :id (getinputvalue "id")
-   :documentname (getinputvalue "upd_documentname")
-   :title (getinputvalue "upd_title")
-   :employeename (getinputvalue "upd_employeename")
-   :date (getinputvalue "upd_date")
-   :location (getinputvalue "upd_location")})
-
 (defn click-update[id]
   (secretary/dispatch! (str "#/documents/update/" id)))

-(defn docupdate [event]
-  (let [onres (fn[data]
-                (secretary/dispatch! "/documents"))]
-    (http-post "http://localhost:8193/documents/update"
-               onres (.serialize (Serializer.) (clj->js (get-update-documents-formdata))))))
-
-(defn document-update-template [id dmt]
-  [:div.form-group {:id "update" :class "form-group"}
-   [:div [:input {:type "hidden" :value id :id "id"}]]
-   [:div (input "Documentname" :text :upd_documentname (.-documentname dmt))]
-   [:div (input "Title" :text :upd_title (.-title dmt))]
-   [:div (input "EmployeeName" :text :upd_employeename (.-employeename dmt))]
-   [:div (input "Date":Date :upd_date  (f/unparse (f/formatter "yyyy-MM-dd")(f/parse (.-date dmt))))]
-   [:div (input "Location":text :upd_location (.-location dmt))]
-   [:input {:type "button" :value "Save"
-            :class "btn btn-primary" :on-click docupdate}]
-   [:input {:type "button" :value "Cancel"
-            :class "btn btn-primary" :on-click cancel}]])
+;; (defn docupdate [event]
+;;   (let [onres (fn[data]
+;;                 (secretary/dispatch! "/documents"))]
+;;     (http-post "http://localhost:8193/documents/update"
+;;                onres (.serialize (Serializer.) (clj->js (get-update-documents-formdata))))))

 (defn delete[id]
   (let [onres (fn [json]
@@ -419,10 +444,10 @@

 (defroute documents-path "/documents/add" []
-  (set-page! [document-template]))
+  (set-page! [document-template1]))

 (defroute documents-path1 "/documents/update/:id" [id]
- (set-page! [document-update-template id
+  (set-page! [document-update-template1 id
               (first (filter (fn[obj]
                                (=(.-id obj) (.parseInt js/window id))) (get-value! :documents)))]))


Removed unused fn.

Removed unused fn.

--- src/luhnybin/core.clj
+++ src/luhnybin/core.clj
@@ -43,11 +43,6 @@
     (#(if (zero? %) chars nil))))

 ;; ### Searching for Potential CCNs
-
-;; A potential credit card must have 14 to 16 digits (inclusive).
-(defn- correct-len? [chars]
-  (let [n (count (filter digits chars))]
-    (and (>= n 14) (<= n 16))))

 (defn- num-digits [chars]
   (reduce #(if (digits %2) (inc %1) %1) 0 chars))


Make the test pass

Make the test pass

--- src/icecap/rest.clj
+++ src/icecap/rest.clj
@@ -1,6 +1,7 @@
 (ns icecap.rest
   "The REST API for icecap."
   (:require [compojure.core :refer [DELETE GET POST context defroutes]]
+            [compojure.route :refer [not-found]]
             [icecap.api :refer :all]
             [icecap.codec :refer [safebase64-decode safebase64-encode]]
             [ring.middleware.defaults :refer [api-defaults
@@ -27,7 +28,8 @@
           (spy @(execute-cap cap components))))
       (DELETE "/" request
         (let [cap (safebase64-decode encoded-cap)]
-          (spy @(revoke-cap cap components)))))))
+          (spy @(revoke-cap cap components))))))
+  (not-found nil))

 (defn ^:private wrap-components
   "Adds some components to each request map."


[up|ref] Use everywhere cond-> instead macros.

--- src/ombs/validate.clj
+++ src/ombs/validate.clj
@@ -74,46 +74,29 @@
      (not (vld/errors? ~tag)))
   )

-(defn rule [[validator msg]]
-   (if-not validator
-     msg
-     nil))
-
-
-(cond-> {}
-  false (msg-insert :e "First")
-  false (msg-insert :e "Second")
-  true (msg-insert :f "Third")
-  false (msg-insert :d "ERoror")
-  true (msg-insert :f (message [:event :empty-name]))
-  )
-
-
-
 (defn msg-insert [coll tag msg]
-  (update coll tag #(vec (conj % msg)))
-  )
+  (update coll tag #(vec (conj % msg))))

 (defn new-event? [eventname price date]
   (cond-> {}
-    (vld/has-value? eventname)              (msg-insert :event (message [:event :empty-name]))
-    (vld/greater-than? price 0)             (msg-insert :event (message [:event :zero-price]))
-    (vld/has-value? date)                   (msg-insert :event (message [:event :empty-date]))
-    (empty? (db/get-event eventname date))  (msg-insert :event (message [:event :duplicate-event]))))
+    (vld/has-value? eventname)                         (msg-insert :event (message [:event :empty-name]))
+    (vld/greater-than? price 0)                        (msg-insert :event (message [:event :zero-price]))
+    (vld/has-value? date)                              (msg-insert :event (message [:event :empty-date]))
+    (empty? (db/get-event eventname date))             (msg-insert :event (message [:event :duplicate-event]))))

 (defn new-user? [username pass1 pass2]
   (cond-> {}
-    (vld/has-value? username)       (msg-insert :login (message [:user :empty-name]))
-    (>= (count pass1) 8)            (msg-insert :login (message [:register :short-pass]))
-    (= pass1 pass2)                 (msg-insert :login (message [:register :notmatch-pass]))
-    (empty? (db/get-user username)) (msg-insert :login (message [:user :unexist]))
+    (vld/has-value? username)                          (msg-insert :login (message [:user :empty-name]))
+    (>= (count pass1) 8)                               (msg-insert :login (message [:register :short-pass]))
+    (= pass1 pass2)                                    (msg-insert :login (message [:register :notmatch-pass]))
+    (empty? (db/get-user username))                    (msg-insert :login (message [:user :unexist]))
     ))

 (defn login? [username password]
   (cond-> {}
-    (vld/has-value? username)                       (msg-insert :login (message [:user :empty-name]))
-    (vld/has-value? (db/get-user username))         (msg-insert :login (message [:user :invalid]))
-    (= password (:password (db/get-user username))) (msg-insert :login (message [:login :invalid]))
+    (vld/has-value? username)                          (msg-insert :login (message [:user :empty-name]))
+    (vld/has-value? (db/get-user username))            (msg-insert :login (message [:user :invalid]))
+    (= password (:password (db/get-user username)))    (msg-insert :login (message [:login :invalid]))
     ))

 (defn participation? [eid]
@@ -123,41 +106,30 @@
                      ))

 (defn payment? [eid uid parts]
-  "Check, if id's is correct. Used with (db/get-*id)"
-  (create-validator :pay
-                    [
-                     [(not= nil uid)
-                      (message [:user :empty-name])]
-                     [(not= nil eid)
-                      (message [:event :unexist])]
-                     [(<= parts (+ (dbp/free-parts eid) parts))
-                      (message [:pay :wrong-parts])]
-                     ]))
+  "Check, if id's is correct. Used with (db/get-*id). Also check if actual parts is less than availiable  "
+  (cond-> {}
+    (not= nil uid)                                     (msg-insert :payment (message :user :empty-name))
+    (not= nil eid)                                     (msg-insert :payment (message :event :unexist))
+    (<= parts (+ (dbp/free-parts eid) parts))          (msg-insert :payment (message :pay :wrong-parts))
+    ))
+
 (defn fee? [id]
- (create-validator :pay
-                   [
-                    [(not= nil id)
-                     (message [:fee :unexist])]
-                    [(not (nil? (db/event-from-fee id)))
-                     (message [:event :unexist])]
-                    [(vld/has-value? (sess/get :username))
-                     (message [:user :unexist])]
-                    ]))
+  (cond-> {}
+    (not= nil id)                                       (msg-insert :payment (message :fee :unexist))
+    (not (nil? (db/event-from-fee id)))                 (msg-insert :payment (message :event :unexist))
+    (vld/has-value? (sess/get :username))               (msg-insert :payment (message :user :unexist))
+    ))

 (defn parts? [ename date parts]
-  (create-validator :pay
-                    [ ; FIXME: free-parts include parts from currect fee
-                     [(<= parts (+ (dbp/free-parts ename date) parts))
-                      (message [:event :parts-count])]
-                     ]))
+  (cond-> {}
+    ; FIXME: free-parts include parts from currect fee
+    (<= parts (+ (dbp/free-parts ename date) parts))   (msg-insert :payment (message :event :parts-count))
+    ))

 (defn moneyout? [username money]
-  (create-validator :admin
-                    [
-                     [(nil? (db/get-user username)) (message [:user :unexist])]
-                     [(< 0 money) (message [:pay :wrong-money])]
-                     [(<= money (:balance (db/get-user username))) (message [:user :low-balance] username)]
-                     ]
-                    )
-  )
+  (cond-> {}
+    (nil? (db/get-user username))                      (msg-insert :payment (message :user :unexist))
+    (< 0 money)                                        (msg-insert :payment (message :pay :wrong-money))
+    (<= money (:balance (db/get-user username)))       (msg-insert :payment (message :user :low-balance username))
+    ))


Taking out of live for development.

Taking out of live for development.

--- src/overtone/live.clj
+++ src/overtone/live.clj
@@ -48,7 +48,7 @@
  'overtone.libs.freesound
  'overtone.version
  'overtone.viz.scope
- 'overtone.gui.control
+ ;'overtone.gui.control
  )

 (defonce _auto-boot_ (boot-rig))


send status code as status-code instead of status

--- src/pc/http/sente.clj
+++ src/pc/http/sente.clj
@@ -280,7 +280,7 @@
        (log/error t)
        ;; TODO: should this use the send-fn? We can do that too, I guess, inside of the defmethod.
        ;; TODO: rip out sente and write a sensible library
-       (send-fn (str (client-uuid->uuid (:client-uuid req))) [:frontend/error {:status (:status t)
+       (send-fn (str (client-uuid->uuid (:client-uuid req))) [:frontend/error {:status-code (:status t)
                                                               :error-msg (:error-msg t)
                                                               :event (:event req)
                                                               :event-data (:?data req)}])))))


Add todo to poll.clj.

Add todo to poll.clj.

--- src/pepa/web/poll.clj
+++ src/pepa/web/poll.clj
@@ -60,6 +60,7 @@
             (when (async-web/open? ch)
               (async-web/close ch))))))))

+;;; TODO(mu): Logging: We need to pass the :web component into this
 (defn ^:private poll-handler* [req]
   (let [method (:request-method req)
         allowed-methods #{:get :post}