GUI: tooltips for menus added

GUI: tooltips for menus added

--- src/gui/menus.clj
+++ src/gui/menus.clj
@@ -3,55 +3,85 @@
 (def tool-bar (toolbar
                 :floatable? false
                 :orientation :horizontal
-                :items [(button :icon (icon-path "new_project.gif"))
-                        (action
+                :items [(action
+                          :tip "Create a new project."
+                          :icon (icon-path "new_project.gif"))
+                        (action
+                          :tip "Open an exisiting project."
                           :icon (icon-path "open_project.gif")
                           :handler handler-open-file)
                         :separator
-                        (button :icon (icon-path "new_proposition.gif"))
-                        (button :icon (icon-path "rename_proposition.gif"))
-                        :separator
-                        (button :icon (icon-path "new_m4file.gif"))
-                        (button :icon (icon-path "open_m4file.gif"))
-                        :separator
-                        (button :icon (icon-path "save.gif"))
-                        (button :icon (icon-path "save_all.gif"))
-                        (button :icon (icon-path "close.gif"))
-                        (button :icon (icon-path "delete.gif"))
-                        :separator
-                        (action
+                        (action
+                          :tip "Add a new proposition (formula) to the current project."
+                          :icon (icon-path "new_proposition.gif"))
+                        (action
+                          :tip "Rename the selected proposition (formula)."
+                          :icon (icon-path "rename_proposition.gif"))
+                        :separator
+                        (action
+                          :tip "Create a new M4 file."
+                          :icon (icon-path "new_m4file.gif"))
+                        (action
+                          :tip "Open an existing M4 file."
+                          :icon (icon-path "open_m4file.gif"))
+                        :separator
+                        (action
+                          :tip "Save"
+                          :icon (icon-path "save.gif"))
+                        (action
+                          :tip "Save all"
+                          :icon (icon-path "save_all.gif"))
+                        (action
+                          :tip "Closes the selected project, proposition or M4 file."
+                          :icon (icon-path "close.gif"))
+                        (action
+                          :tip "Deletes the selected project, proposition or M4 file."
+                          :icon (icon-path "delete.gif"))
+                        :separator
+                        (action
+                          :tip "Transforms the current MPA proposition to clojure code."
                           :icon (icon-path "formula2clojure.gif")
                           :handler handler-parse)
                         (action
+                          :tip "Transforms the current clojure code to a MPA proposition."
                           :icon (icon-path "clojure2formula.gif")
                           :handler handler-reparse)
                         (action
+                          :tip "SAT solves the proposition."
                           :icon (icon-path "task_sat.gif")
                           :handler handler-sat)
                         (action
+                          :tip "Prints a truth table for the proposition."
                           :icon (icon-path "task_tt.gif")
                           :handler handler-tt)
                         (action
+                          :tip "Generates the CNF (Conjunctive Normal Form) of the proposition."
                           :icon (icon-path "task_cnf.gif")
                           :handler handler-cnf)
                         (action
+                          :tip "Performs the tseitin transformation on the proposition."
                           :icon (icon-path "task_tcnf.gif")
                           :handler handler-tseitin)
                         (action
+                          :tip "Generates the dimacs file for the proposition (must be CNF)."
                           :icon (icon-path "dimacs.gif")
                           :handler handler-dimacs)
                         (action
+                          :tip "Generates the CNF, then prints the dimacs file."
                           :icon (icon-path "dimacsCNF.gif")
                           :handler handler-dimacs-cnf)
                         (action
+                          :tip "Performs the tseitin transformation, then prints the dimacs file."
                           :icon (icon-path "dimacsTseitin.gif")
                           :handler handler-dimacs-tseitin)
-                        (action
+                        (action
+                          :tip "Runs the M4 macro processor on the proposition."
                           :handler handler-m4
                           :icon (icon-path "task_m4.gif"))
                         :separator
                         ;(button :icon (icon-path "select_font.gif"))
                         (action
+                          :tip "Opens a window to change global settings."
                           :icon (icon-path "settings.gif")
                           :handler (fn [_] (settings-frame!)))
                         #_(combobox
@@ -63,40 +93,48 @@
                     :mnemonic "P"
                     :items [(action
                               :name "New Project"
+                              :tip "Create a new project."
                               :key "ctrl shift N"
                               :icon (icon-path "new_project.gif"))
                             (action
                               :name "Open Project"
+                              :tip "Open an exisiting project."
                               :key "ctrl shift O"
                               :icon (icon-path "open_project.gif")
                               :handler handler-open-file)
                             (separator)
                             (action
                               :name "New Proposition"
+                              :tip "Add a new proposition (formula) to the current project."
                               :key "ctrl N"
                               :icon (icon-path "new_proposition.gif"))
                             (action
                               :name "Rename Proposition"
+                              :tip "Rename the selected proposition (formula)."
                               :key "ctrl R"
                               :icon (icon-path "rename_proposition.gif"))
                             (separator)
                             (action
                               :name "New M4 File"
+                              :tip "Create a new M4 file."
                               :key "alt N"
                               :icon (icon-path "new_m4file.gif"))
                             (action
                               :name "Open M4 File"
+                              :tip "Open an existing M4 file."
                               :key "alt O"
                               :icon (icon-path "open_m4file.gif"))
                             (separator)
                             (action
                               :name "Save"
+                              :tip "Save"
                               :key "ctrl S"
                               :mnemonic "S"
                               :icon (icon-path "save.gif")
                               :handler (fn [_] (println "Saving"))) ;TODO
                             (action
                               :name "Save All"
+                              :tip "Save all"
                               :key "ctrl shift S"
                               :mnemonic "A"
                               :icon (icon-path "save_all.gif")
@@ -104,13 +142,16 @@
                               )
                             (action
                               :name "Close"
+                              :tip "Closes the selected project, proposition or M4 file."
                               :icon (icon-path "close.gif"))
                             (action
                               :name "Delete"
+                              :tip "Deletes the selected project, proposition or M4 file."
                               :icon (icon-path "delete.gif"))
                             (separator)
                             (action
                               :name "Exit"
+                              :tip "Exit the whole application."
                               :key "ctrl Q"
                               :icon (icon-path "exit.gif"))]))

@@ -119,46 +160,56 @@
                   :mnemonic "T"
                   :items [(action
                             :name "Parse formula to clojure"
+                            :tip "Transforms the current MPA proposition to clojure code."
                             :key "ctrl P"
                             :icon (icon-path "formula2clojure.gif")
                             :handler handler-parse)
                           (action
                             :name "Parse clojure back to formula"
+                            :tip "Transforms the current clojure code to a MPA proposition."
                             :icon (icon-path "clojure2formula.gif")
                             :handler handler-reparse)
                           (action
                             :name "Check SAT"
+                            :tip "SAT solves the proposition."
                             ;:key "ctrl T+S"
                             :icon (icon-path "task_sat.gif")
                             :handler handler-sat)
                           (action
                             :name "Truth Table"
+                            :tip "Prints a truth table for the proposition."
                             ;:key "ctrl T T"
                             :icon (icon-path "task_tt.gif")
                             :handler handler-tt)
                           (action
                             :name "Transform to CNF"
+                            :tip "Generates the CNF (Conjunctive Normal Form) of the proposition."
                             ;:key "ctrl T C"
                             :icon (icon-path "task_cnf.gif")
                             :handler handler-cnf)
                           (action
                             :name "Tseitin Transformation"
+                            :tip "Performs the tseitin transformation on the proposition."
                             :icon (icon-path "task_tcnf.gif")
                             :handler handler-tseitin)
                           (action
                             :name "Generate DIMACS"
+                            :tip "Generates the dimacs file for the proposition (must be CNF)."
                             :icon (icon-path "dimacs.gif")
                             :handler handler-dimacs)
                           (action
                             :name "Make CNF, then generate DIMACS"
+                            :tip "Generates the CNF, then prints the dimacs file."
                             :icon (icon-path "dimacsCNF.gif")
                             :handler handler-dimacs-cnf)
                           (action
                             :name "Make Tseitin-CNF, then generate DIMACS"
+                            :tip "Performs the tseitin transformation, then prints the dimacs file."
                             :icon (icon-path "dimacsTseitin.gif")
                             :handler handler-dimacs-tseitin)
                           (action
                             :name "Preprocess with M4"
+                            :tip "Runs the M4 macro processor on the proposition."
                             ;:key "ctrl T M"
                             :handler handler-m4
                             :icon (icon-path "task_m4.gif"))
@@ -172,6 +223,7 @@
                                :icon (icon-path "select_font.gif"))
                             (action
                               :name "Settings"
+                              :tip "Opens a window to change global settings."
                               :key "alt S"
                               :icon (icon-path "settings.gif")
                               :handler (fn [_] (settings-frame!)))
@@ -182,6 +234,7 @@
                  :mnemonic "H"
                  :items [(action
                            :name "Help Contents"
+                           :tip "Opens the help files in the system standard web browser."
                            :mnemonic "H"
                            :handler (fn [_]
                                       (let [help-file (File. "resources/help/toc.html")]
@@ -192,4 +245,5 @@
                          (separator)
                          (action
                            :name "About"
+                           :tip "Show general information on the project, authors, licences, etc."
                            :handler (fn [_] (about-frame!)))]))


fix add of kv pair in empty namelist

fix add of kv pair in empty namelist

--- src/nml/core.clj
+++ src/nml/core.clj
@@ -34,20 +34,29 @@
   (nml-str (second x)))

 (defn nml-add [tree parent child match proxy]
+;; (println (str "--- nml-add tree: " tree))
+;; (println (str "--- nml-add parent=" parent " child=" child " match=" match " proxy=" proxy))
   (let [missing? (fn [children] (not-any? #(= (nml-name %) match) children))
         f (fn [& children]
+;;           (println (str "--- nml-add " match " missing? " (missing? children)))
             (if (missing? children)
               (into [parent (parse proxy :start child)] children)
               (into [parent] children)))]
-    (insta/transform {parent f} tree)))
+    (let [t2 (if (nil? tree) [parent (parse proxy :start child)] (insta/transform {parent f} tree))]
+;;     (println (str "--- nml-add returning " t2))
+      t2)))

 (defn nml-set [tree nml key val & sub]
+;; (println (str "### nml-set nml=" nml " key=" key " val=" val))
   (let [child  (if sub :nvsubseq :stmt)
         match  (if sub key nml)
         parent (if sub :nvseq :s)
         proxy  (if sub (str match "=0") (str "&" match " /"))
         vnew   (if sub (fn [tree] (parse val :start :values)) #(nml-set % nml key val true))
-        f      (fn ([k v] [child k (if (= (nml-str k) match) (vnew v) v)]))]
+        f      (fn
+                 ([k v] (if (= (nml-str k) match) [child k (vnew v  )] [child k v]))
+                 ([k  ] (if (= (nml-str k) match) [child k (vnew nil)] [child k  ])))]
+;;   (println (str "### tree " tree))
     (insta/transform {child f} (nml-add tree parent child match proxy))))

 (defn nml-sets [tree sets]


Update net.postgis/postgis-jdbc to "2.3.0"

--- backend/project.clj
+++ backend/project.clj
@@ -46,7 +46,7 @@
                  [ring/ring-defaults "0.3.2"]
                  [ring/ring-json "0.4.0"]
                  [selmer "1.12.12" :exclusions [com.fasterxml.jackson.dataformat/jackson-dataformat-smile com.fasterxml.jackson.dataformat/jackson-dataformat-cbor cheshire]]
-                 [net.postgis/postgis-jdbc "2.2.1" :exclusions [org.postgresql/postgresql]]
+                 [net.postgis/postgis-jdbc "2.3.0" :exclusions [org.postgresql/postgresql]]
                  [iapetos "0.1.8" :exclusions [io.prometheus/simpleclient]]
                  [io.prometheus/simpleclient_hotspot "0.6.0"]
                  [io.prometheus/simpleclient_dropwizard "0.6.0"]


Update honeysql to "0.9.4"

Update honeysql to "0.9.4"

--- backend/project.clj
+++ backend/project.clj
@@ -21,7 +21,7 @@
                  [duct/database.sql.hikaricp "0.4.0" :exclusions [org.clojure/spec.alpha org.slf4j/slf4j-nop org.clojure/clojure integrant org.clojure/core.specs.alpha]]
                  [environ "1.1.0"]
                  [funcool/cuerdas "2.2.0" :exclusions [org.clojure/spec.alpha com.google.protobuf/protobuf-java com.google.errorprone/error_prone_annotations org.clojure/clojure com.google.guava/guava org.clojure/core.specs.alpha com.google.code.findbugs/jsr305 org.clojure/tools.reader]]
-                 [honeysql "0.9.3"]
+                 [honeysql "0.9.4"]
                  [meta-merge "1.0.0"]
                  [metosin/reitit "0.3.6" :exclusions [com.cognitect/transit-java org.clojure/spec.alpha org.ow2.asm/asm ring/ring-core mvxcvi/puget org.clojure/clojure ring/ring-codec org.clojure/core.rrb-vector mvxcvi/arrangement fipp r org.clojure/core.specs.alpha com.fasterxml.jackson.core/jackson-databind com.fasterxml.jackson.core/jackson-core]]
                  [org.akvo/commons "0.4.5" :exclusions [org.postgresql/postgresql org.clojure/java.jdbc]]


fix boxed math warning

fix boxed math warning

--- src/insn/core.clj
+++ src/insn/core.clj
@@ -9,7 +9,8 @@
            [java.io File FileOutputStream]
            [java.lang.reflect Constructor]))

-(def ^:private jvm-version
+(def ^{:private true, :tag 'long}
+  jvm-version
   (-> (System/getProperty "java.specification.version")
       Double/valueOf))


comment debug s-exprs

comment debug s-exprs

--- src/fat_jar/core.clj
+++ src/fat_jar/core.clj
@@ -53,14 +53,14 @@
                      BufferedReader.
                      json/parsed-seq
                      first)]
-        (->> mappings
-          println)
-
-        (->> user-data
-          println)
-
-        (->> selections
-          println)
+;        (->> mappings
+;          println)
+;
+;        (->> user-data
+;          println)
+;
+;        (->> selections
+;          println)

        (->>  (map #(select- % user-data) mappings)


Rework arg parsing to deal with 0 or more args

--- src/grimoire/doc.clj
+++ src/grimoire/doc.clj
@@ -216,58 +216,57 @@
 projects such as clojure.core which may not exist as a covenient lein project
 but which do exist as artifacts."
   [p-groupid p-artifactid p-version p-source-paths ;; provided by lein via profile
-   mode-selector & args ;; user provided
+   & args ;; user provided
    ]
-  (case mode-selector
-    ("artifact" :artifact)
-    ,,(let [[platform
-             groupid
-             artifactid
-             version
-             dst]    args
-             _        (assert platform "Platform missing!")
-             platform (util/normalize-platform platform)
-             _        (assert platform "Unknown platform!")
-             _        (assert groupid "Groupid missing!")
-             _        (assert artifactid "Artifactid missing!")
-             _        (assert version "Version missing!")
-             _        (assert dst "Doc target dir missing!")
-             config   {:groupid    groupid
-                       :artifactid artifactid
-                       :version    version
-                       :platform   platform
-                       :datastore  {:docs dst
-                                    :mode :filesystem}}
-             pattern  (format ".*?/%s/%s/%s.*"
-                              (string/replace groupid "." "/")
-                              artifactid
-                              version)
-             pattern  (re-pattern pattern)]
-        (doseq [e (cp/classpath)]
-          (when (re-matches pattern (str e))
-            (doseq [ns (tns.f/find-namespaces [e])]
-              (when-not (= ns 'clojure.parallel) ;; FIXME: get out nobody likes you
-                (require ns)
-                (write-docs-for-ns config ns))))))
-
-    ("src" :src "source" :source)
-    ,,(let [[platform
-             doc]    args
-             _        (assert platform "Platform missing!")
-             platform (util/normalize-platform platform)
-             _        (assert platform "Unknown platform!")
-             _        (assert doc "Doc target dir missing!")
-             config   {:groupid    p-groupid
-                       :artifactid p-artifactid
-                       :version    p-version
-                       :platform   platform
-                       :datastore  {:docs (last args)
-                                    :mode :filesystem}}]
-        (doseq [ns (->> p-source-paths
-                        (map io/file)
-                        (tns.f/find-namespaces))]
-          (require ns)
-          (write-docs-for-ns config ns)))
-
-    ;; Implicit else
-    (println (:doc (meta #'-main)))))
+  (let [[mode-selector platform & args] args]
+    (case mode-selector
+      ("artifact" :artifact)
+      ,,(let [[groupid
+               artifactid
+               version
+               dst]    args
+               _        (assert platform "Platform missing!")
+               platform (util/normalize-platform platform)
+               _        (assert platform "Unknown platform!")
+               _        (assert groupid "Groupid missing!")
+               _        (assert artifactid "Artifactid missing!")
+               _        (assert version "Version missing!")
+               _        (assert dst "Doc target dir missing!")
+               config   {:groupid    groupid
+                         :artifactid artifactid
+                         :version    version
+                         :platform   platform
+                         :datastore  {:docs dst
+                                      :mode :filesystem}}
+               pattern  (format ".*?/%s/%s/%s.*"
+                                (string/replace groupid "." "/")
+                                artifactid
+                                version)
+               pattern  (re-pattern pattern)]
+          (doseq [e (cp/classpath)]
+            (when (re-matches pattern (str e))
+              (doseq [ns (tns.f/find-namespaces [e])]
+                (when-not (= ns 'clojure.parallel) ;; FIXME: get out nobody likes you
+                  (require ns)
+                  (write-docs-for-ns config ns))))))
+
+      ("src" :src "source" :source)
+      ,,(let [[doc]    args
+               _        (assert platform "Platform missing!")
+               platform (util/normalize-platform platform)
+               _        (assert platform "Unknown platform!")
+               _        (assert doc "Doc target dir missing!")
+               config   {:groupid    p-groupid
+                         :artifactid p-artifactid
+                         :version    p-version
+                         :platform   platform
+                         :datastore  {:docs (last args)
+                                      :mode :filesystem}}]
+          (doseq [ns (->> p-source-paths
+                          (map io/file)
+                          (tns.f/find-namespaces))]
+            (require ns)
+            (write-docs-for-ns config ns)))
+
+      ;; Implicit else
+      (println (:doc (meta #'-main))))))


Fixed early loop termination bug

Fixed early loop termination bug

--- src/hangman/core.clj
+++ src/hangman/core.clj
@@ -101,7 +101,7 @@

 (defn main
   ( []
-    (let [tgt-word      "toxics"
+    (let [tgt-word      "stereoisomers"
           game-words    all-words
           words-map     (group-by count game-words)  ; map keyed by word length
           word-list     (words-map (count tgt-word)) ; words of correct length


get some pieces working with real datomic (memdb)

--- src/navigator.clj
+++ src/navigator.clj
@@ -1,7 +1,21 @@
-(ns navigator.data.competency
+(ns navigator
   ^{:author "David Zaharee <dzaharee@vlacs.org>"
     :doc "This library knows how to work with competency data."}
-  (:require [datomic.api :as d]))
+  (:require [clojure.edn :as edn]
+            [datomic.api :as d]
+            [datomic-schematode.core :as schematode]
+            [navigator.schema :as schema]))
+
+(def updatable-fields
+  {:comp [:comp/description :comp/status :comp/tags]})
+
+(def valid-fields
+  {:comp [:comp/id-sk :comp/name :comp/description :comp/version :comp/status :comp/tags]})
+
+;; TODO: use https://github.com/rkneufeld/conformity ... in schematode. But noting it here. :-)
+(defn init! [system]
+  [(schematode/init-schematode-constraints! (:db-conn system))
+   (schematode/load-schema! (:db-conn system) schema/schema)])

 ;; Get functions

@@ -21,7 +35,7 @@
               id-sk))

 (defn get-competency-by-name-version
-  "Get competency by shared key"
+  "Get competency by name+verion"
   [conn name version]
   (get-entity conn '[:find ?e
                      :in $ ?name ?version
@@ -49,35 +63,29 @@
 ;; Creation/update functions

 ;; TODO: schematode may have a thing that does this?
-(defn with-constraints
+(defn tx
   "transact with schematode constraints"
-  [conn tx]
-  (d/transact conn [[:schematode-tx [tx]]]))
-
-(defn- transact-entity-fn
-  [fields]
-  (fn [conn eid & {:as updates}]
-    (with-constraints conn (merge {:db/id eid} (select-keys updates fields)))))
+  [conn txs]
+  (schematode/tx conn :enforce txs))
+
+#_(defn- transact-entity-fn
+  [valid-fields]
+  (fn [conn eid & {:as fields}]
+    (tx conn (merge {:db/id eid} (select-keys fields valid-fields)))))

 (defn- update-entity-fn
   [updatable-fields transact-fn]
-  (fn [conn & {:keys {eid} :as entity}]
+  (fn [conn & {:keys [eid] :as entity}]
     (apply transact-fn conn eid (select-keys entity updatable-fields))))

-(def transact-competency
-  ^{:private true}
-  (transact-entity-fn [:comp/id-sk :comp/name :comp/description :comp/version :comp/status :comp/tags]))
-
-;; TODO: can we update name-version?
-;; TODO: this?
-(def update-competency
-  (update-entity-fn [:comp/description :comp/status] transact-competency))
-
-;; TODO: or this?   -- this seems better from a readability standpoint
-(defn update-competency2
-  [conn & {:keys {eid} :as entity}]
-  (let [updatable-fields [:comp/description :comp/status]]
-    (apply transact-competency conn eid (select-keys entity updateable-fields))))
+(defn- transact-competency
+  [conn eid & {:as entity}]
+  (tx conn [(merge {:db/id eid} (select-keys entity (:comp valid-fields)))]))
+
+(defn update-competency
+  "Consider using :comp/id-sk instead of the entity ID here, IF every :comp has a :comp/id-sk."
+  [conn & {:keys [eid] :as entity}]
+  (apply transact-competency conn eid (select-keys entity (:comp updatable-fields))))

 (defn create-competency
   "Create a new competency"
@@ -86,10 +94,12 @@
   (apply transact-competency conn (d/tempid :db.part/user)
          :comp/name name
          :comp/version version
+         :comp/status status
          (flatten (seq optional-fields))))

 (def transact-comp-tag
-  ^{:private true}
+  1
+  #_
   (transact-entity-fn [:comp-tag/name
                        :comp-tag/description
                        :comp-tag/version
@@ -121,6 +131,7 @@
          (flatten (seq optional-fields))))

 (def update-comp-tag-disp-ctx
+  #_
   (transact-entity-fn [:comp-tag-disp-ctx/name]))

 (defn create-comp-tag-disp-ctx
@@ -129,6 +140,7 @@
   (apply update-comp-tag-disp-ctx (d/tempid :db.part/user) :comp-tag-disp-ctx/name name))

 (def transact-perf-asmt
+  #_
   (transact-entity-fn [:perf-asmt/id-sk
                        :perf-asmt/name
                        :perf-asmt/version
@@ -151,7 +163,8 @@
          (flatten (seq optional-fields))))

 (def transact-user2comp
-  ^{:private true}
+  1
+  #_
   (transact-entity-fn [:user2comp/sis-user-id
                        :user2comp/comp
                        :user2comp/start-date


Include (currently empty) caching lib in catch-all.

--- immutant/project.clj
+++ immutant/project.clj
@@ -18,6 +18,7 @@
             :url "http://www.apache.org/licenses/LICENSE-2.0"}
   :packaging "pom"

-  :dependencies [[org.immutant/messaging _]
+  :dependencies [[org.immutant/caching _]
+                 [org.immutant/messaging _]
                  [org.immutant/scheduling _]
                  [org.immutant/web _]])


Clean up subcommand-usage output

Clean up subcommand-usage output

Signed-off-by: Gregory Haskins <640d9fe47775e6723f0355b7315e38f7d98d3539@gmail.com>

--- src/obcc/core.clj
+++ src/obcc/core.clj
@@ -81,7 +81,7 @@
 (defn subcommand-usage [subcommand options-summary]
   (prep-usage [(version)
                ""
-               (str "Description: " (:name subcommand) ": " (:desc subcommand))
+               (str "Description: obcc " (:name subcommand) " - " (:desc subcommand))
                ""
                (str "Usage: obcc " (:name subcommand) " [options]")
                ""


can now generate a stream

can now generate a stream

--- src/kba_clj/core.clj
+++ src/kba_clj/core.clj
@@ -1,6 +1,30 @@
-(ns kba-clj.core)
+(ns kba-clj.core
+  (:require [clojure.java.io :as io]
+            [thrift-clj.core :as thrift])
+  (:import [java.io FileInputStream]
+           [org.apache.thrift.protocol TBinaryProtocol]
+           [org.apache.thrift.transport
+            TIOStreamTransport
+            TTransport
+            TTransportException]
+           [streamcorpus StreamItem]))

-(defn foo
-  "I don't do a whole lot."
-  [x]
-  (println x "Hello, World!"))
+(defn file-stream
+  [a-file]
+  (let [itransport (-> a-file
+                       (FileInputStream.)
+                       (TIOStreamTransport.))
+        iprotocol  (new TBinaryProtocol itransport)]
+    (do
+      (.open itransport)
+      (take-while
+       identity
+       (repeatedly
+        (fn []
+          (let [item (new StreamItem)]
+            (try (do (.read item iprotocol)
+                     item)
+                 (catch TTransportException e (do (.close itransport)
+                                                  nil))))))))))
+
+


Work in progress for asteroids in Clojure.

--- Clojure/asteroids.clj
+++ Clojure/asteroids.clj
@@ -1,43 +1,77 @@
 ; :mode=clojure:

 (import
-    '(java.awt Color)
-    '(java.awt Dimension)
-    '(javax.swing.JFrame)
-    '(javax.swing.JComponent)
-    '(javax.swing.JLabel)
-    '(java.awt.event.ActionListener)
+    '(java.awt Color Dimension Polygon RenderingHints)
+    '(javax.swing JComponent JFrame JLabel Timer)
+    '(java.awt.event ActionListener KeyAdapter)
 )

 (defn do-mod [coll func v]
     (dosync (alter coll (fn [x] (apply func [x v])))))

+(defn player-shape []
+    (doto
+        (new Polygon)
+        (.addPoint 10 0)
+        (.addPoint -3 5)
+        (.addPoint -3 -5)))
+
+(defn draw-player [player g]
+    (do
+        (.setColor g (Color/WHITE))
+        (let [old-transform (.getTransform g)]
+            (.translate g (:x player) (:y player))
+            (.fill g (player-shape))
+            (.setTransform g old-transform))))
+
+(defn game-render [state g]
+    (do
+        (.setRenderingHint g
+            RenderingHints/KEY_ANTIALIASING
+            RenderingHints/VALUE_ANTIALIAS_ON)
+        (.setRenderingHint g
+            RenderingHints/KEY_RENDERING
+            RenderingHints/VALUE_RENDER_QUALITY)
+        (.setColor g (Color/BLACK))
+        (let [rect (.getClipBounds g)]
+            (.fillRect g (.x rect) (.y rect) (.width rect) (.height rect)))
+        (draw-player (:player state) g)))
+
 (defn create-component [game-state]
     (doto
-        (proxy [javax.swing.JComponent] []
-            (paint [g] (dosync
-                (.setColor g (if (empty? (deref game-state)) (java.awt.Color/RED) (java.awt.Color/BLUE)))
-                (let [rect (.getClipBounds g)]
-                    (.fillRect g (.x rect) (.y rect) (.width rect) (.height rect))))))
-        (.setPreferredSize (new java.awt.Dimension 640 480))
+        (proxy [JComponent] []
+            (paint [g] (dosync (game-render (deref game-state) g))))
+        (.setPreferredSize (new Dimension 640 480))
         (.setDoubleBuffered true)
         (.setFocusable true)))

+(defn now [] (* 0.001 (System/currentTimeMillis)))
+
+(defn default-state [] {
+    :time (now)
+    :player { :x 100.0 :y 100.0 :xv 10.0 :yv 5.0 } } )
+
+(defn player-step [player time-step]
+    (assoc player
+        :x (+ (:x player) (* (:xv player) time-step))
+        :y (+ (:y player) (* (:yv player) time-step))))
+
 (defn game-step [state keys-pressed]
-    (if (empty? keys-pressed)
-        (assoc (hash-map) :a true)
-        (hash-map)))
+    (let [new-time (now) time-step (- new-time (:time state))]
+        (assoc state
+            :time new-time
+            :player (player-step (:player state) time-step))))

 (defn create-game []
     (let [
         keys-pressed (ref (hash-set))
-        game-state (ref (hash-map))
+        game-state (ref (default-state))
         result (create-component game-state)
         ]
         (do
             (doto
                 result
-                (.addKeyListener (proxy [java.awt.event.KeyAdapter] []
+                (.addKeyListener (proxy [KeyAdapter] []
                     (keyPressed [event] (if (not (.isConsumed event)) (do
                         (do-mod keys-pressed conj (.getKeyCode event))
                         (.consume event))))
@@ -46,8 +80,8 @@
                         (.consume event)))))))

             (doto
-                (new javax.swing.Timer (/ 1000 60)
-                    (reify java.awt.event.ActionListener
+                (new Timer (/ 1000 60)
+                    (reify ActionListener
                         (actionPerformed [this event] (.repaint result))))
                 (.start))

@@ -59,7 +93,7 @@

             result)))

-(let [frame (new javax.swing.JFrame)]
+(let [frame (new JFrame)]
     (do
         (.add (.getContentPane frame) (create-game))
         (.pack frame)


Add actions to the buttons and url field

--- nightweb-desktop/src/nightweb/browser.clj
+++ nightweb-desktop/src/nightweb/browser.clj
@@ -6,7 +6,8 @@
            javafx.scene.layout.Priority
            javafx.geometry.Insets
            javafx.scene.text.Font
-           javafx.geometry.Pos))
+           javafx.geometry.Pos
+           javafx.beans.value.ChangeListener))

 (defn create-tab
   "Creates a new tab."
@@ -14,11 +15,14 @@
   (let [new-tab (Tab. "Main Page")
         tab-view (VBox.)
         nav-bar (HBox.)
+        reload-icon "⟳"
+        stop-icon "x"
         back-btn (Button. "<")
         for-btn (Button. ">")
-        reload-btn (Button. "⟳")
+        reload-btn (Button. reload-icon)
         url-field (TextField.)
         web-view (WebView.)
+        web-engine (.getEngine web-view)
         index (- (.size (.getTabs tab-bar)) 1)]
     ; resize the controls
     (.setFont back-btn (Font. 16))
@@ -26,8 +30,31 @@
     (.setFont reload-btn (Font. 16))
     (.setMinHeight url-field 28)
     (HBox/setHgrow url-field Priority/ALWAYS)
+    (VBox/setVgrow web-view Priority/ALWAYS)
+    ; set actions for the controls
+    (defhandler :onAction back-btn
+                (if (> (.getCurrentIndex (.getHistory web-engine)) 0)
+                  (.go (.getHistory web-engine) -1)))
+    (defhandler :onAction for-btn
+                (if (< (+ (.getCurrentIndex (.getHistory web-engine)) 1)
+                       (.size (.getEntries (.getHistory web-engine))))
+                  (.go (.getHistory web-engine) 1)))
+    (defhandler :onAction reload-btn
+                (if (= (.getText reload-btn) reload-icon)
+                  (.reload web-engine)
+                  (.cancel (.getLoadWorker web-engine))))
+    (defhandler :onAction url-field
+                (.load web-engine (.getText url-field)))
+    (.addListener (.stateProperty (.getLoadWorker web-engine))
+                  (proxy [ChangeListener] []
+                    (changed [ov oldState newState]
+                             (if (= newState javafx.concurrent.Worker$State/RUNNING)
+                               (do
+                                 (.setText url-field (.getLocation web-engine))
+                                 (.setText reload-btn stop-icon))
+                               (.setText reload-btn reload-icon)))))
     ; load the main page
-    (.load (.getEngine web-view) "http://localhost:8080")
+    (.load web-engine "http://localhost:8080")
     ; set spacing for the nav bar
     (.setAlignment nav-bar javafx.geometry.Pos/CENTER)
     (.setPadding nav-bar (Insets. 4))


Fixed problem with url settings

Fixed problem with url settings

--- src/lobos/config.clj
+++ src/lobos/config.clj
@@ -2,12 +2,17 @@
   (:use [lobos.connectivity]
         [heroku-database-url-to-jdbc.core]))

+(def localDb
+  {:classname   "org.postgresql.Driver"
+   :subprotocol "postgresql"
+   :subname     "//localhost:5432/barmap"})
+
+
 (defn db []
-;; FIXME korma-connection-map throws NPE if DATABASE_URL is not set
-  (or (korma-connection-map (System/getenv "DATABASE_URL"))
-              {:classname   "org.postgresql.Driver"
-               :subprotocol "postgresql"
-               :subname     "//localhost:5432/barmap"}))
+  (if-let
+      [url (System/getenv "DATABASE_URL")]
+    (korma-connection-map url)
+    localDb))

 (defn init []
   (open-global (db)))


Tentative fix for #339.

Tentative fix for #339.

--- src/onyx/interop.clj
+++ src/onyx/interop.clj
@@ -2,16 +2,15 @@
   (:gen-class :name onyx.interop
               :methods [^:static [write_batch [clojure.lang.IPersistentMap] clojure.lang.IPersistentMap]
                         ^:static [read_batch [clojure.lang.IPersistentMap] clojure.lang.IPersistentMap]])
-  (:require [onyx.peer.function :refer [write-batch read-batch]]
-            [onyx.peer.pipeline-extensions :refer [PipelineInput Pipeline]]))
+  (:require [onyx.peer.pipeline-extensions :refer [PipelineInput Pipeline]]))

 (defn -write_batch
   [event]
-  (write-batch event))
+  ((resolve 'onyx.peer.function/write-batch) event))

 (defn -read_batch
   [event]
-  (read-batch event))
+  ((resolve 'onyx.peer.function/read-batch) event))

 (gen-interface
   :name onyx.IPipelineInput


docstrings for book review fns

docstrings for book review fns

--- src/myshelf/core.clj
+++ src/myshelf/core.clj
@@ -192,6 +192,7 @@
          (map (comp (juxt :title :id :author) :best_book :work)))))

 (defn add-book-review
+  "Add a book review. Automatically adds book to read shelf."
   [consumer access-token book-id rating & [review-text]]
   (let [review-url "https://www.goodreads.com/review"
         params (merge {:format "xml"
@@ -206,6 +207,8 @@
                             params)))

 (defn edit-book-review
+  "Edit a book review. Automatically sets book to finished
+  and adds it to the read shelf, if it wasn't already there."
   [consumer access-token review-id new-rating & [review-text]]
   (let [review-url (str "https://www.goodreads.com/review/"
                         review-id


Update data.cljs

Update data.cljs

--- src/prais2/data.cljs
+++ src/prais2/data.cljs
@@ -562,7 +562,7 @@
               "(0-16 years old). "
               "This data is updated annually and covers the most recent 3 year report period.")]
      [:p "Previous reporting periods can be selected at the bottom of the table.
-    Clicking on a hospital code will bring up specific information for that hospital along with an interpretation of its survival rate."]
+    Clicking on a hospital code will bring up specific information for that hospital along with an interpretation of its survival rate. It is only valid to compare a hospital's survival rate to its predicted range and not to other hospitals [link to Everything Else]."]
      [:p "You can use your mouse to hover over the chart to bring up more explanation."]
      ]
     (table1 app data event-bus)]])


unmount slider processing added. beginning to think about ragged left axis

--- src/prais2/data.cljs
+++ src/prais2/data.cljs
@@ -192,7 +192,7 @@

 (defn dot-size [slider]
-  (Math.round (- 12 (* 4 (- 1 slider)))))
+  (Math.round (- 12 (* 7 (- 1 slider)))))

 (def chart-states [#{} #{:dot} #{:inner :dot} #{:inner :outer :dot}
@@ -204,44 +204,45 @@
         bars (chart-states (:chart-state ap))
         dotty (:dot bars)
         dotless (disj bars :dot)]
-    [:td.chart-cell {:style {:padding-left (important (px axis-margin))
-                             :padding-right last-pad-right}}
-
-     [:div.bar-chart
-      (map-indexed key-with
-
-       (cond
-         (= dotless #{})
-         [(dot slider (dot-size slider) (:survival-rate row) dotty)]
-
-         (= dotless #{:inner})
-         [(bar slider (:outer-low row) (* min-outer-low slider) :low (:low colours))
-          (bar slider (:inner-low row) (:outer-low row) :outer-low (:low colours))
-          (bar slider (:inner-high row) (:inner-low row) :inner (:inner colours))
-          (bar slider (:outer-high row) (:inner-high row) :outer-high (:high colours))
-          (bar slider 100 (:outer-high row) :high (:high colours))
-          (dot slider (dot-size slider) (:survival-rate row) dotty)
-          ]
-
-
-         (= dotless #{:outer})
-         [(bar slider (:outer-low row) (* min-outer-low slider) :low (:low colours))
-          (bar slider (:inner-low row) (:outer-low row) :outer-low (:outer-low colours))
-          (bar slider (:inner-high row) (:inner-low row) :inner (:outer-low colours))
-          (bar slider (:outer-high row) (:inner-high row) :outer-high (:outer-high colours))
-          (bar slider 100 (:outer-high row) :high (:high colours))
-          (dot slider (dot-size slider) (:survival-rate row) dotty)
-          ]
-
-
-         (= dotless #{:inner :outer})
-         [(bar slider (:outer-low row) (* min-outer-low slider) :low (:low colours))
-          (bar slider (:inner-low row) (:outer-low row) :outer-low (:outer-low colours))
-          (bar slider (:inner-high row) (:inner-low row) :inner (:inner colours))
-          (bar slider (:outer-high row) (:inner-high row) :outer-high (:outer-high colours))
-          (bar slider 100 (:outer-high row) :high (:high colours))
-          (dot slider (dot-size slider) (:survival-rate row) dotty)
-          ]))]]))
+    [:td
+     [:.chart-cell {:style {:padding-left (important (px axis-margin))
+                            :padding-right last-pad-right}}
+
+      [:div.bar-chart
+       (map-indexed key-with
+
+                    (cond
+                      (= dotless #{})
+                      [(dot slider (dot-size slider) (:survival-rate row) dotty)]
+
+                      (= dotless #{:inner})
+                      [(bar slider (:outer-low row) (* min-outer-low slider) :low (:low colours))
+                       (bar slider (:inner-low row) (:outer-low row) :outer-low (:low colours))
+                       (bar slider (:inner-high row) (:inner-low row) :inner (:inner colours))
+                       (bar slider (:outer-high row) (:inner-high row) :outer-high (:high colours))
+                       (bar slider 100 (:outer-high row) :high (:high colours))
+                       (dot slider (dot-size slider) (:survival-rate row) dotty)
+                       ]
+
+
+                      (= dotless #{:outer})
+                      [(bar slider (:outer-low row) (* min-outer-low slider) :low (:low colours))
+                       (bar slider (:inner-low row) (:outer-low row) :outer-low (:outer-low colours))
+                       (bar slider (:inner-high row) (:inner-low row) :inner (:outer-low colours))
+                       (bar slider (:outer-high row) (:inner-high row) :outer-high (:outer-high colours))
+                       (bar slider 100 (:outer-high row) :high (:high colours))
+                       (dot slider (dot-size slider) (:survival-rate row) dotty)
+                       ]
+
+
+                      (= dotless #{:inner :outer})
+                      [(bar slider (:outer-low row) (* min-outer-low slider) :low (:low colours))
+                       (bar slider (:inner-low row) (:outer-low row) :outer-low (:outer-low colours))
+                       (bar slider (:inner-high row) (:inner-low row) :inner (:inner colours))
+                       (bar slider (:outer-high row) (:inner-high row) :outer-high (:outer-high colours))
+                       (bar slider 100 (:outer-high row) :high (:high colours))
+                       (dot slider (dot-size slider) (:survival-rate row) dotty)
+                       ]))]]]))

 (r/defc tick < r/static [baseline value]
@@ -290,18 +291,21 @@
                                                                  :step 0.01
                                                                  :value (:slider-axis-value @core/app)
                                                                  }))
-                      state' (assoc state :slider slider)]
-                  (.on slider
-                       "slide"
-                       #(put! event-bus [:slider-axis-value (.getValue slider)]))
+                      handler #(put! event-bus [:slider-axis-value (.getValue slider)])
+                      state' (assoc state :slider slider :handler handler)]
+                  (.on slider "slide" handler)
+                  (.on slider "change" handler)
                   (prn state')
                   state'))

    :will-unmount (fn [state]
-                   (let [slider (:slider state)]
+                   (let [slider (:slider state)
+                         handler (:handler state)]
                      (prn "unmounting slider")
-                     (when  slider (.destroy slider))
-                     (dissoc state :slider)))})
+                     (when  slider
+                       (when handler (.off slider "slide" handler))
+                       (.destroy slider))
+                     (dissoc state :slider :handler)))})

 (r/defcs slider-control < r/static bs-slider [state event-bus value min max step]
   (when (:slider state) (.setValue (:slider state) value))
@@ -442,62 +446,6 @@
            (r/with-key (chart-cell row slider-axis-value) :bars)])]]]]))

-
-(comment
-;; This is right for md and lg, but goes wrong in xs and sm sizes
-;; You need  .screenable position not to be fixed to enable it again.
-(r/defc table1 < r/reactive [app data event-bus]
-  (let [ap (r/react app)
-        sort-key (:sort-by ap)
-        sort-direction (:sort-ascending ap)
-        headers (dissoc (first data) :n-deaths)
-        rows  (if sort-key
-                (let [sorted (sort-by sort-key (rest data))]
-                  (if sort-direction sorted (reverse sorted)))
-                (rest data))
-        column-keys (keys headers)
-        slider-axis-value (:slider-axis-value ap)  ]
-    [:div
-     (when (core/query-media? "screen")
-       #_(prn column-keys)
-
-         [:div.container {:style {
-                                  :position "fixed"
-                                  :z-index 2}}
-          [:.row
-           [:.col-sm-12.col-md-12
-            [:div.screenable {:key :screen}
-             ;; fixed table with header only for @media screen, hidden in print
-             [:table.table.table-striped.table-bordered {:cell-spacing "0"}
-              (r/with-key (table-head app ap headers column-keys event-bus slider-axis-value) :thead)]]]]])
-
-     [:div.col-sm-12.col-md-12
-      [:div.printable {:key :print}
-       [:table.table.table-striped.table-bordered {:cell-spacing "0"}
-        #_(prn (str "printing true?" (core/query-media? "print")))
-        ;; full table with print header, hidden on screen
-        (r/with-key (table-head app ap headers column-keys event-bus slider-axis-value) :thead)
-
-        ;; body for both print and screen
-        [:tbody {:key :tbody}
-         (for [row rows]
-           [:tr {:key (:h-code row)
-                 :on-click #(put! event-bus [:row-clicked row])
-                 :data-toggle "modal"
-                 :data-target "#rowModal"
-                 :data-h-code (:h-code row)
-                 :class (if (= row (:selected-row ap)) "info" "")}
-            (for [column-key column-keys
-                  :let [column-header (column-key headers)]
-                  :when (:shown column-header)]
-              [:td {:key [column-key "r"]
-                    :style {:width (px (:width column-header))
-                            :height (px (:height column-header))}}
-               (str (column-key row) (if (= column-key :survival-rate) " %" ""))])
-            (r/with-key (chart-cell row slider-axis-value) :bars)])]]]]]))
-)
-
-
 (defn get-chart-state
   [index]
   (chart-states index)


agents to fetch read counts

agents to fetch read counts

--- src/ontrail/keen.clj
+++ src/ontrail/keen.clj
@@ -14,11 +14,14 @@
         [compojure.core :only (defroutes ANY POST GET PUT DELETE)]))

 (def conman
-  (make-reusable-conn-manager {:timeout 10 :threads 50 :default-per-route 50}))
+  (make-reusable-conn-manager
+   {:threads 10 :default-per-route 10}))

 (def connection
-  (merge {:accept :json}
-         {:throw-exceptions false}
+  (merge {:accept :json
+          :throw-exceptions false
+          :socket-timeout 5000  ;; in milliseconds
+          :conn-timeout 120000}
          {:connection-manager conman}))

 (def read-key (-> properties :keen :read-key))
@@ -38,11 +41,15 @@
       "&event_collection=pageviews&timezone=7200" filters-as-str group-by-str)))

 (defn count-by-id [id]
-  (let [filter-by [{:property_name :eid :operator :eq :property_value id}]]
-    (-> (http/get (keen-count-uri filter-by nil) connection)
-         :body
-         json/read-str
-         walk/keywordize-keys)))
+  (try
+    (let [filter-by [{:property_name :eid :operator :eq :property_value id}]]
+      (-> (http/get (keen-count-uri filter-by nil) connection)
+          :body
+          json/read-str
+          walk/keywordize-keys))
+    (catch Exception ex
+      (prn ex)
+      {:result 0})))

 (defn group-by-eid []
   (-> (http/get (keen-count-uri  nil "eid") connection)
@@ -50,8 +57,37 @@
       json/read-str
       walk/keywordize-keys))

-(def memo-count-by-id
-  (memo/ttl count-by-id :ttl/threshold (* 60 60 1000)))
+(def agents (ref {}))
+(def expires (ref {}))
+
+(import java.util.concurrent.Executors)
+(set-agent-send-off-executor! (Executors/newFixedThreadPool 8))
+
+(def expires-in (* 10 60 1000))
+
+(defn now []
+  (System/currentTimeMillis))
+
+(defn get-agent [id]
+  (dosync
+   (if-let [c (@agents id)]
+     c
+     (do
+       (alter expires assoc id 0)
+       ((alter agents assoc id (agent (count-by-id id))) id)))))
+
+(defn update [state blocking-fn]
+  (blocking-fn))
+
+(defn memo-count-by-id [id]
+  @(let [agent (get-agent id)]
+     (if (< (@expires id) (now))
+       (do
+         (dosync (alter expires assoc id (+ expires-in (now))))
+         (send-off
+          agent
+          update (fn [] (count-by-id id))))
+       agent)))

 (defn try-get-one [id]
   (try


fixed the log level to info

fixed the log level to info

--- src/ophion/aleph.clj
+++ src/ophion/aleph.clj
@@ -11,7 +11,11 @@
    [ophion.db :as db]
    [ophion.query :as query])
   (:import
-   [java.io InputStreamReader]))
+   [java.io InputStreamReader]
+   [ch.qos.logback.classic Logger Level]))
+
+(.setLevel
+   (org.slf4j.LoggerFactory/getLogger (Logger/ROOT_LOGGER_NAME)) Level/INFO)

 (defn append-newline
   [s]


view - basic book list

view - basic book list

--- src/osmium/index.clj
+++ src/osmium/index.clj
@@ -13,22 +13,55 @@
     [:body
      [:div {:class "container"} content ]]]))

+(def books
+  [{:title "I Am a Strange Loop"
+    :author "Douglas R. Hofstadter"
+    :rating 5}
+   {:title "I Am a Strange Loop"
+    :author "Douglas R. Hofstadter"
+    :rating 5}
+   {:title "I Am a Strange Loop"
+    :author "Douglas R. Hofstadter"
+    :rating 4}
+   {:title "I Am a Strange Loop"
+    :author "Douglas R. Hofstadter"
+    :rating 5}])
+
+(def title-row
+  [:tr
+   [:th.row-left "Title"]
+   [:th "Author"]
+   [:th.center.row-right "Rating"]])
+
+(defn rating-icons [r]
+  (html
+   [:span {}
+    (for [i (range r)]
+      [:i {:class "fa fa-star"}])]))
+
+(defn book-row [book]
+  (html
+   [:tr.session-row {}
+    [:td.row-left (:title book)]
+    [:td.row-left (:author book)]
+    [:td.row-right.center {} (rating-icons (:rating book))]]))
+
+(defn table []
+  (html
+   [:div.main {}
+    [:table.session-table.u-full-width {}
+     [:thead title-row]
+     [:tbody {}
+      (for [book books]
+        (book-row book))]]]))
+
 (defn index []
   (application
    "Osmium"
    (html
     [:div.container {}
      [:div.title-row {}
-      [:div {} [:h2.main-title {} "some title"]]
-      [:div {} [:span.right "Current: "]]]
-     [:div.session {}
-      [:h5.session-title {}  "id"
-       [:i {:class "fa fa-circle "}]
-       [:i.fa.fa-times.u-pull-right.close-session {}]]
-      [:button.playback [:a {:target "_blank"}
-                         "Playback"]]
-      [:button.playback [:a {:href "https://saucelabs.com/beta/manual"
-                             :target "_blank"}
-                         "Sauce Labs"]]
-      [:p {} "App Version: "]
-      [:br]]])))
+      [:div {}
+       [:h2.main-title {} "Osmium"]
+       [:h5 {} [:em {} "Dense books"]]]]
+     (table)])))


Initial moving and resizing and wall-making

--- src/player/core.cljs
+++ src/player/core.cljs
@@ -588,6 +588,78 @@
                    [:objects id])
                  (has-under wld x y)))))

+(def drag-threshold 2)
+
+(defn editor-start-new-thing [ed x y now-x now-y]
+  ;todo: HA _or_ wall
+  (let [new-id (inc (apply max (map first (:walls (:draft-desc ed)))))
+        _ (println "create new wall" new-id x y now-x now-y)
+        new-thing-handle [:walls new-id]
+        ax x
+        ay y
+        bx now-x
+        by now-y]
+    (assoc ed
+      :move-mode :resizing
+      :selection #{new-thing-handle}
+      :draft-desc (assoc-in
+                    (:draft-desc ed)
+                    new-thing-handle
+                    {:x (.min js/Math ax bx)
+                     :y (.min js/Math ay by)
+                     :w (.abs js/Math (- bx ax))
+                     :h (.abs js/Math (- by ay))}))))
+
+(defn editor-move-selection [ed dx dy]
+  (println "move selection by" dx dy)
+  (assoc ed
+    :move-mode :moving
+    :draft-desc
+    (reduce
+      (fn [desc sel-path]
+        (update-in desc sel-path (fn [{x :x y :y :as obj}]
+                                   (assoc obj :x (+ x dx)
+                                              :y (+ y dy)))))
+      (:draft-desc ed)
+      (:selection ed))))
+
+(defn editor-resize-selection [ed dx dy]
+  (println "resize selection"
+           (first (:selection ed))
+           (get-in (:draft-desc ed)
+                   (first (:selection ed)))
+           "by" dx dy)
+  (let [[sx sy] (:last-loc ed)
+        {x :x y :y w :w h :h} (get-in (:draft-desc ed) (first (:selection ed)))
+        ; if sx is rightish, adjust width only; else adjust width and x
+        [nx nw] (if (> sx (+ x (/ w 2)))
+                  [x (+ w dx)]
+                  [(+ x dx) (- w dx)])
+        ; if sy is toppish, adjust height only; else adjust height and y
+        [ny nh] (if (> sy (+ y (/ h 2)))
+                  [y (+ h dy)]
+                  [(+ y dy) (- h dy)])
+        [nx nw] (if (< nw 0)
+                  [(+ nx nw) (.abs js/Math nw)]
+                  [nx nw])
+        [ny nh] (if (< nh 0)
+                  [(+ ny nh) (.abs js/Math nh)]
+                  [ny nh])]
+    (assoc ed :draft-desc (update-in (:draft-desc ed)
+                                     (first (:selection ed))
+                                     assoc
+                                     :x nx :y ny
+                                     :w nw :h nh)
+              :move-mode :resizing)))
+
+(def resize-threshold 4)
+
+(defn wall-centerish-point? [wld wx wy]
+  (some (fn [{x :x y :y w :w h :h}]
+          (and (<= (+ x resize-threshold) wx (- (+ x w) resize-threshold))
+               (<= (+ y resize-threshold) wy (- (+ y h) resize-threshold))))
+        (:walls (:desc wld))))
+
 (def world-widget
   (let [props (fn [this] (aget (.-props this) "args"))
         ; world -> view: scale up and flip
@@ -637,9 +709,10 @@
                              (this-as this
                                (let [props (props this)
                                      world (get props :world)
-                                     _ (assert (instance? Atom world) "world should be atom?")
                                      wld @world
-                                     desc (:desc wld)
+                                     editor (get props :editor)
+                                     ed @editor
+                                     desc (or (:draft-desc ed) (:desc wld))
                                      container-w (:view-width wld)
                                      _ (assert (number? container-w))
                                      container-h (:view-height wld)
@@ -655,46 +728,111 @@
                                      ha-starts (:objects desc)
                                      polys (apply concat (vals (:seen-polys wld)))

-                                     editor (get props :editor)
-                                     ed @editor
                                      sel (:selection ed)]
-                                 (sab/html [:div {:style   {:backgroundColor "blue"
-                                                            :width           (+ container-w 20)
-                                                            :height          (+ container-h 20)
-                                                            :position        "relative"
-                                                            :overflow        "scroll"}
-                                                  :onClick (fn [evt]
-                                                             (let [t (.-currentTarget evt)
-                                                                   mx (+ (- (.-pageX evt) (.-offsetLeft t))
-                                                                         (.-scrollLeft t))
-                                                                   my (+ (- (.-pageY evt) (.-offsetTop t))
-                                                                         (.-scrollTop t))
-                                                                   [wx wy] (view->world props mx my)
-                                                                   found-things (things-under wld wx wy)]
-                                                               (println "click at" mx my "->" wx wy)
-                                                               (println "found under mouse:" found-things)
+                                 (sab/html [:div {:style {:backgroundColor "blue"
+                                                          :width           (+ container-w 20)
+                                                          :height          (+ container-h 20)
+                                                          :position        "relative"
+                                                          :overflow        "scroll"}
+                                                  :onMouseDown
+                                                         (fn [evt]
+                                                           (let [t (.-currentTarget evt)
+                                                                 mx (+ (- (.-pageX evt) (.-offsetLeft t))
+                                                                       (.-scrollLeft t))
+                                                                 my (+ (- (.-pageY evt) (.-offsetTop t))
+                                                                       (.-scrollTop t))
+                                                                 [wx wy] (view->world props mx my)
+                                                                 found-things (things-under wld wx wy)]
+                                                             (println "click at" mx my "->" wx wy)
+                                                             (println "found under mouse:" found-things)
+                                                             (swap! editor assoc
+                                                                    :draft-desc (:desc wld)
+                                                                    :mouse-down-loc [wx wy]
+                                                                    :last-loc [wx wy]
+                                                                    :move-mode :clicking
+                                                                    :selection
+                                                                    (if-let [new-sel (first found-things)]
+                                                                      (if (.-shiftKey evt)
+                                                                        (if (contains? sel new-sel)
+                                                                          (disj sel new-sel)
+                                                                          (conj sel new-sel))
+                                                                        #{new-sel})
+                                                                      (if (.-shiftKey evt)
+                                                                        sel
+                                                                        #{})))))
+                                                  :onMouseMove
+                                                         (fn [evt]
+                                                           (let [ed @editor
+                                                                 [down-x down-y] (or (:mouse-down-loc ed) [nil nil])]
+                                                             (when (some? down-x)
+                                                               ;drag/extend/etc, update desc in some placeholder spot?
+                                                               ; this way can draw overlay of new wall/object/position/size/whatever, while still drawing the old one where it lives.
+                                                               (let [t (.-currentTarget evt)
+                                                                     mx (+ (- (.-pageX evt) (.-offsetLeft t))
+                                                                           (.-scrollLeft t))
+                                                                     my (+ (- (.-pageY evt) (.-offsetTop t))
+                                                                           (.-scrollTop t))
+                                                                     [wx wy] (view->world props mx my)
+                                                                     dx (- wx down-x)
+                                                                     dy (- wy down-y)
+                                                                     [last-x last-y] (:last-loc ed)
+                                                                     ddx (- wx last-x)
+                                                                     ddy (- wy last-y)
+                                                                     sel (:selection ed)
+                                                                     mode (:move-mode ed)]
+                                                                 (let [new-ed
+                                                                       (assoc
+                                                                         (cond
+                                                                           (= mode :resizing)
+                                                                           ; resize selected object
+                                                                           (editor-resize-selection ed ddx ddy)
+                                                                           (= mode :moving)
+                                                                           ; move selected objects
+                                                                           (editor-move-selection ed ddx ddy)
+                                                                           (>= (.sqrt js/Math (+ (* dx dx) (* dy dy))) drag-threshold)
+                                                                           (do
+                                                                             (println "start dragging")
+                                                                             (cond
+                                                                               ; no selection
+                                                                               (empty? sel)
+                                                                               ;create new object and set sel to it and enter either moving state (for HAs) or resizing state (for walls)
+                                                                               ; multi-selection or HA selected or mouse in center
+                                                                               (editor-start-new-thing ed down-x down-y wx wy)
+                                                                               (or (> 1 (count sel))
+                                                                                (= :objects (ffirst sel))
+                                                                                (wall-centerish-point? (get-in (:draft-desc ed) (first sel)) wx wy))
+                                                                               ; move selected object(s)
+                                                                               (editor-move-selection ed dx dy)
+                                                                               ;(mouse started at edge of selected thing)
+                                                                               :else
+                                                                               ; resize selected object if wall
+                                                                               (editor-resize-selection ed dx dy)))
+                                                                           ; haven't moved enough to drag.
+                                                                           ; todo: show resize or move cursor appropriately
+                                                                           :else ed)
+                                                                         :last-loc [wx wy])]
+                                                                   (reset! editor new-ed)))))
+                                                           )
+                                                  :onMouseUp
+                                                         (fn [_evt]
+                                                           (let [ed @editor]
+                                                             (when (:mouse-down-loc ed)
+                                                               ;actually change world to match new desc
+                                                               (world-update-desc! world (:draft-desc ed))
                                                                (swap! editor assoc
-                                                                      :selection
-                                                                      (if-let [new-sel (first found-things)]
-                                                                        (if (.-shiftKey evt)
-                                                                          (if (contains? sel new-sel)
-                                                                            (disj sel new-sel)
-                                                                            (conj sel new-sel))
-                                                                          #{new-sel})
-                                                                        (if (.-shiftKey evt)
-                                                                          sel
-                                                                          #{})))))
+                                                                      :mouse-down-loc nil
+                                                                      :move-mode nil))))
                                                   :onScroll
-                                                           (fn [scroll-evt]
-                                                             (let [n (.-target scroll-evt)]
-                                                               (update-world! world
-                                                                              (fn [w]
-                                                                                (let [[sx sy] (view->world props (.-scrollLeft n) (+ (.-scrollTop n) container-h))]
-                                                                                #_(println "update from scroll:"
-                                                                                (.-scrollLeft n) (+ (.-scrollTop n) container-h)
-                                                                                "->" sx sy)
-                                                                                (assoc w :scroll-x sx
-                                                                                :scroll-y sy))))))}
+                                                         (fn [scroll-evt]
+                                                           (let [n (.-target scroll-evt)]
+                                                             (update-world! world
+                                                                            (fn [w]
+                                                                              (let [[sx sy] (view->world props (.-scrollLeft n) (+ (.-scrollTop n) container-h))]
+                                                                                #_(println "update from scroll:"
+                                                                                (.-scrollLeft n) (+ (.-scrollTop n) container-h)
+                                                                                "->" sx sy)
+                                                                                (assoc w :scroll-x sx
+                                                                                :scroll-y sy))))))}
                                             [:svg {:width               (* world-w x-scale)
                                                    :height              (* world-h y-scale)
                                                    :style               {:position "absolute"}


Return map from get*

Return map from get*

--- src/poky/kv/jdbc.clj
+++ src/poky/kv/jdbc.clj
@@ -38,13 +38,14 @@
 (defrecord JdbcKeyValue [conn]
   kv.core/KeyValueProtocol
   (get* [this b k params]
-    (jdbc-get conn b k))
+    (kv.core/get* this b k))
   (get* [this b k]
-    (jdbc-get conn b k))
+    (when-let [row (jdbc-get conn b k)]
+      {(:key row) (:data row)}))
   (mget* [this b ks params]
-    (jdbc-mget conn b ks))
+    (kv.core/mget* this b ks))
   (mget* [this b ks]
-    (jdbc-mget conn b ks))
+    (into {} (map (juxt :key :data) (jdbc-mget conn b ks))))
   (set* [this b k value]
     (jdbc-set conn b k value))
   (delete* [this b k]


add TODO

add TODO

--- src/revdiff/core.clj
+++ src/revdiff/core.clj
@@ -9,7 +9,8 @@
 ;; TODO is --stop-on-copy on log really a good idea?
 ;; TODO maybe print log message / committer info (could use awt/swing popup)?
 ;; TODO pass all '--' options (e.g. --username) to svn?
-;; TODO item, term used to be global: refactor to avoid passing them so much
+;; TODO item, term used to be global: refactor to avoid passing them so much!
+;; TODO add command-line switch for case insensitivity!

 (def shhh "--non-interactive")  ; suppress svn user prompts


Improve naming based on suggestions from Kyle

--- src/riemann/core.clj
+++ src/riemann/core.clj
@@ -180,15 +180,15 @@
               integration now."
               ((:index core) event)))

-; Provides an accessor for an inner index
+; Provides an accessor for a source index
 (defprotocol WrappedIndex
-  (inner [this]))
-
-(defn- get-inner-index
+  (source [this]))
+
+(defn- unwrap
   "Get the inner index of a wrapped index"
   [wrapped]
   (if (instance? riemann.core.WrappedIndex wrapped)
-    (inner wrapped)
+    (source wrapped)
     wrapped))

 (defn wrap-index
@@ -202,9 +202,9 @@
      (reify
        Object
        (equals [this other]
-         (= source (get-inner-index other)))
+         (= source (unwrap other)))
        WrappedIndex
-       (inner [this]
+       (source [this]
          source)
        Index
        (clear [this]
@@ -233,11 +233,11 @@

        ServiceEquiv
        (equiv? [this other]
-         (service/equiv? source (get-inner-index other)))
+         (service/equiv? source (unwrap other)))

        Service
        (conflict? [this other]
-         (service/conflict? source (get-inner-index other)))
+         (service/conflict? source (unwrap other)))
        (reload! [this new-core]
          (service/reload! source new-core))
        (start! [this]


Improved call signature on schema ns functions.

--- src/uxbox/schema.clj
+++ src/uxbox/schema.clj
@@ -74,16 +74,15 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (defn validate
-  ([schema] #(validate schema %))
-  ([schema data] (first (b/validate data schema))))
+  [data schema] (first (b/validate data schema)))

 (defn validate!
-  ([schema] #(validate! schema %))
-  ([schema data]
-   (when-let [errors (validate schema data)]
-     (let [data {:type :validation
-                 :payload errors}]
-       (throw (ex-info "Schema validations error." data))))))
+  [data schema]
+  (if-let [errors (validate data schema)]
+    (let [data {:type :validation
+                :payload errors}]
+      (throw (ex-info "Schema validations error." data)))
+    data))

 (defn valid?
   [validator data]
@@ -95,12 +94,12 @@
         (throw (ex-info message {}))))))

 (defn extract
-  [schema data]
+  [data schema]
   (let [keycoll (keys schema)]
     (select-keys data keycoll)))

 (defn extract!
   "Extract and validate."
-  [schema data]
-  (validate! schema data)
-  (extract schema data))
+  [data schema]
+  (validate! data schema)
+  (extract data schema))


Basic user API implemented.

Basic user API implemented.

--- src/wat/database.clj
+++ src/wat/database.clj
@@ -5,7 +5,38 @@
          '[clojure.java.io :as io])

 (defn define-attributes [c]
-  (d/transact c
+  (d/transact c ; User attributes
+              [{:db/id (d/tempid :db.part/db)
+                :db/ident :user/name
+                :db/valueType :db.type/string
+                :db/cardinality :db.cardinality/one
+                :db/doc "Username"
+                :db.install/_attribute :db.part/db}
+               {:db/id (d/tempid :db.part/db)
+                :db/ident :user/properties
+                :db/valueType :db.type/long
+                :db/cardinality :db.cardinality/one
+                :db/doc "Defines user rights (admin/user etc.)"
+                :db.install/_attribute :db.part/db}
+               {:db/id (d/tempid :db.part/db)
+                :db/ident :user/uid
+                :db/valueType :db.type/long
+                :db/cardinality :db.cardinality/one
+                :db/doc "UID"
+                :db.install/_attribute :db.part/db}
+               {:db/id (d/tempid :db.part/db)
+                :db/ident :user/rating
+                :db/valueType :db.type/double
+                :db/cardinality :db.cardinality/one
+                :db/doc "User work rating."
+                :db.install/_attribute :db.part/db}
+               {:db/id (d/tempid :db.part/db)
+                :db/ident :user/worklist
+                :db/valueType :db.type/ref
+                :db/cardinality :db.cardinality/many
+                :db/doc "List of lines user working on."
+                :db.install/_attribute :db.part/db}])
+  (d/transact c ; Line attributes
               [{:db/id (d/tempid :db.part/db)
                 :db/ident :line/pname
                 :db/valueType :db.type/string
@@ -20,9 +51,21 @@
                 :db.install/_attribute :db.part/db}
                {:db/id (d/tempid :db.part/db)
                 :db/ident :line/translator
-                :db/valueType :db.type/string
+                :db/valueType :db.type/long
                 :db/cardinality :db.cardinality/one
                 :db/doc "Text line translator."
+                :db.install/_attribute :db.part/db}
+               {:db/id (d/tempid :db.part/db)
+                :db/ident :line/redactor
+                :db/valueType :db.type/long
+                :db/cardinality :db.cardinality/one
+                :db/doc "Text line translator."
+                :db.install/_attribute :db.part/db}
+               {:db/id (d/tempid :db.part/db)
+                :db/ident :line/reserved
+                :db/valueType :db.type/long
+                :db/cardinality :db.cardinality/one
+                :db/doc "UID of person that is currently working on this line."
                 :db.install/_attribute :db.part/db}
                {:db/id (d/tempid :db.part/db)
                 :db/ident :line/original
@@ -54,36 +97,42 @@
       (println "Database" db-name "already exist, its fine."))
     (println "Connection established!")))

-(defn create-line [& {:keys [pname id text male-text female-text translator],
-                      :or {male-text "" female-text "" translator ""}}]
+(defn create-line [& {:keys [pname id text male-text female-text translator redactor reserved],
+                      :or {pname "" id -1 text "" male-text "" female-text ""
+                           translator 0 redactor 0 reserved 0}}]
   {:db/id (d/tempid :db.part/user)
    :line/pname pname
    :line/num (java.lang.Long. id)
    :line/original text
    :line/male male-text
    :line/female female-text
-   :line/translator translator})
+   :line/translator (java.lang.Long. translator)
+   :line/redactor (java.lang.Long. redactor)
+   :line/reserved (java.lang.Long. reserved)
+   })

 (defn get-n-words [n coll]
   (let [sum (atom 0)
         db (d/db conn)]
-    (reduce (fn [x y]
-              (if (< @sum n)
-                (do
-                  (swap! sum + (count (clojure.string/split (:line/original (d/touch (d/entity db y))) #"\s")))
-                  (conj x y))
-                x))
-          []
-          coll)))
-
-(defn dump-project [project-name]
+    [(reduce (fn [x y]
+               (if (< @sum n)
+                  (do
+                    (swap! sum + (count (clojure.string/split (:line/original (d/touch (d/entity db y))) #"\s")))
+                    (conj x y))
+                  x))
+              []
+              coll) @sum]))
+
+(defn dump-project
+  "Dump project sorted by line number into file specified.
+   Header is not printed now."
+  [project-name fname]
   (let [db (d/db conn)
         content (d/q '[:find [?line ...]
                        :in $ ?pname
                        :where [?line :line/pname ?pname]]
                      db project-name)]
-    (println (str "dumped " content))
-    (with-open [out-file (io/writer (str "/tmp/" project-name ".csv"))]
+    (with-open [out-file (io/writer fname)]
       (csv/write-csv out-file
                      (sort #(compare (first %1) (first %2))
                              (map #(let [ent (d/touch (d/entity db %))]
@@ -94,43 +143,120 @@
                                       (:line/translator ent)])
                                   content))))))

-(defn load-project [pname source]
+(defn load-project
+  "Load project from specified file.
+   Now it is considered that header does not exist."
+  [pname source]
   (let [data (with-open [in-file (io/reader source)]
                (doall
                 (csv/read-csv in-file)))]
-    (println "loaded")
     (doseq [[n o m f t] data]
-      @(d/transact conn [(create-line :pname pname :id n :text o)]))))
-
-(defn cleanup-project [pname]
+      (d/transact conn [(create-line :pname pname :id n :text o)]))))
+
+(defn cleanup-project
+  "Delete all entries related to specified project.
+   Good to wait for ~3 seconds after it to let indexing event occur."
+  [pname]
   (let [data (d/q '[:find [?line ...]
                     :in $ ?pname
                     :where [?line :line/pname ?pname]]
                   (d/db conn) pname)]
-    (println "cleaned " data)
     (doseq [e data]
-      @(d/transact
-        conn
-        [{:db/id #db/id[db.part/user], :db/excise e}]))))
-
-(defn get-project-chunk [pname size]
-  (println (str (d/q '[:find (wat.database/get-n-words 8 ?e) .;; find all untranslated entries and collect till have n words
-                       :where [?e :line/pname "tududu"]]
-                     (d/db conn)))))
+      (d/transact
+       conn
+       [{:db/id #db/id[db.part/user], :db/excise e}]))))
+
+(defn get-project-chunk-to-translate [pname size uid]
+  (let [[chunk actual-size] (get-n-words size
+                                         (d/q '[:find [?e ...]
+                                                :in $ ?pname
+                                                :where [?e :line/pname ?pname]
+                                                       [?e :line/translator 0]
+                                                       [?e :line/reserved 0]]
+                                              (d/db conn) pname))]
+    (doseq [e chunk]
+      (d/transact conn
+                  [{:db/id e
+                    :line/reserved uid}]))
+    [chunk actual-size]))
+
+(defn get-project-chunk-to-redact [pname size uid]
+  (let [[chunk actual-size] (get-n-words size
+                                         (d/q '[:find [?e ...]
+                                                :in $ ?pname
+                                                :where [?e :line/pname ?pname]
+                                                       (not [?e :line/translator 0])
+                                                       [?e :line/reserved 0]]
+                                              (d/db conn) pname))]
+    (doseq [e chunk]
+      (d/transact conn
+                  [{:db/id e
+                    :line/reserved uid}]))
+    [chunk actual-size]))
+
+(defn return-translated-chunk [chunk uid]
+  (doseq [e chunk]
+    (d/transact conn
+                  [{:db/id e
+                    :line/reserved 0}
+                    :line/translator uid])))
+
+(defn return-redacted-chunk [chunk uid]
+  (doseq [e chunk]
+    (d/transact conn
+                  [{:db/id e
+                    :line/reserved 0}
+                    :line/redactor uid])))
+
+(defn update-chunk [data]
+  (doseq [e data]
+    (when-not (= e (d/touch (d/entity (d/db conn) (:db/id e))))
+      (d/transact conn [e]))))

 (defn get-dummy-info []
   (println "====================")
   ;(define-attributes conn)
-  #_@(d/transact ; add entry
-    conn
-    [(create-line :pname "default" :id 2 :text "qwerty sdfg")])
+  #_(println (str (d/transact ; add entry
+                 conn
+                 [(create-line :pname "default" :id 1 :text "qwerty sdfg")])))
+  (println (d/q '[:find [?ident ...]
+                  :where
+                  [?e :db/ident ?ident]
+                  [_ :db.install/attribute ?e]
+                  [(.toString ?ident) ?val]
+                  [(.startsWith ?val ":line")]] (d/db conn)))
   (println ">")
-  ;(dump-project "default")
   ;(load-project "tududu" "/tmp/default")
-  (future
-    (cleanup-project "tududu")
-    (Thread/sleep 3000)
-    (dump-project "tududu"))
+  ;(dump-project "tududu" "/tmp/atatta.csv")
+  ;; (future
+  ;;   (cleanup-project "tududu")
+  ;;   (Thread/sleep 3000)
+  ;;   (dump-project "tududu" "/tmp/atatta.csv"))
+                                        ;(println (get-project-chunk "tududu" 12))
+  #_(d/transact conn ; User attributes
+                [{:db/id (d/tempid :db.part/db)
+                  :db/ident :user/name
+                  :db/valueType :db.type/string
+                  :db/cardinality :db.cardinality/one
+                  :db/doc "Username"
+                  :db.install/_attribute :db.part/db}
+                 {:db/id (d/tempid :db.part/db)
+                  :db/ident :user/uid
+                  :db/valueType :db.type/ref
+                  :db/cardinality :db.cardinality/many
+                  :db/doc "UID"
+                  :db.install/_attribute :db.part/db}])
+  #_(d/transact
+     conn
+     [{:db/id 17592186045973
+       :user/name "dummy"
+       :user/uid [17592186045969]}])
+
+  ;(get-project-chunk-to-translate "tududu" 11 1)
+
+  #_(println (d/touch (d/entity (d/db conn) (d/q '[:find ?e .
+                                                 :where [?e :user/name "dummy"]]
+                                               (d/db conn)))))
   (println "<")
   (str "Hello there, big brother greets you!"))


cleanup

cleanup

--- src/splash/core.cljs
+++ src/splash/core.cljs
@@ -48,23 +48,13 @@
          :fade-in 0.2
          :fade-out 0.5))

-
-
     (macros/with-sprite canvas :stars
       [spr (sprite/make-sprite
             (resources/get-texture :stars :nearest)
             :scale [8 8]
             :alpha 0.1)]

-      (<! (events/wait-time 2000)))
-
-    #_ (macros/on-layer (-> canvas :layer :stars)
-                        [spr (sprite/make-sprite
-                              (resources/get-texture :stars :nearest)
-                              :scale [8 8])]
-                        (<! (events/wait-time 2000)))
-
-    ))
+      (<! (events/wait-time 2000)))))

 (main)


An attempt to use h2 database for storing messages.

--- src/takehome/web.clj
+++ src/takehome/web.clj
@@ -14,6 +14,23 @@
              [format-params :refer [wrap-json-kw-params]]
              [format-response :refer [wrap-json-response]]
              [params :refer [wrap-params]]]))
+
+(require '[clojure.java.jdbc.deprecated :as sql])
+
+(def db-config
+    {:classname "org.h2.Driver"
+     :subprotocol "h2"
+     :subname "/tmp/takehome"})
+
+
+(sql/with-connection db-config
+  (try (sql/drop-table :message)
+       (catch org.h2.jdbc.JdbcBatchUpdateException ex nil))
+
+  (sql/create-table :message
+    [:user "varchar(256) primary key"]
+    [:topic "varchar(256)"]
+    [:message "varchar(256)"]))

 (def version
   (setup/version "takehome"))
@@ -37,7 +54,12 @@
 (defn subscribe
   "Subscribe username to topic"
   [topic username]
-  {:status 200 :body (format "SUBSCRIBED\n")})
+  (sql/with-connection db-config
+    (sql/insert-records
+     :message
+     {:topic topic :user username :message "SUBSCRIBED"})
+
+  {:status 200 :body (format "SUBSCRIBED\n")}))

 (defn unsubscribe


Fixed lint errors

Fixed lint errors

--- src/tango/export.clj
+++ src/tango/export.clj
@@ -42,7 +42,7 @@
 ;; DancePerfect/CompData
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defn- make-comp-data-node [query-result]
-  (let [result (first (first query-result))
+  (let [result (ffirst query-result)
         options (:competition/options result)]
     (xml/element
       :CompData
@@ -130,7 +130,7 @@
         adjudicator-infos))))

 (defn- make-panel-list-node [qr]
-  (let [adjudicator-panels (into [] (map first qr))
+  (let [adjudicator-panels (vec (map first qr))
         n (- 30 (count adjudicator-panels))
         padded-panels (repeat n {:adjudicator-panel/adjudicators []})
         all-panels (into adjudicator-panels padded-panels)]
@@ -177,7 +177,7 @@
       )))

 (defn- make-class-list-node [query-result]
-  (let [classes (into [] (map first query-result))]
+  (let [classes (vec (map first query-result))]
     (xml/element :ClassList
                  {}
                  (reduce


Added id retrieval.

Added id retrieval.

--- src/vertigo/core.clj
+++ src/vertigo/core.clj
@@ -40,15 +40,18 @@
             [clj-time.format]
             [clj-time.core :only (now)]))

-(defrecord Show [title
+(defrecord Show [id
+                 title
                  theatre
                  genres
                  image])
+
 (def shows-db (atom {}))

 (defn parse-shows-and-group-by-genre [xz]
   (let [shows (for [show (xml-> xz :Shows :Show)]
           (Show.
+            (xml1-> show :EventId text)
             (xml1-> show :OriginalTitle text)
             (xml1-> show :TheatreAndAuditorium text)
             (into #{} (split (xml1-> show :Genres text) #", "))


(TK-18) Remove duplicate precondition

(TK-18) Remove duplicate precondition

--- src/puppetlabs/trapperkeeper/services_internal.clj
+++ src/puppetlabs/trapperkeeper/services_internal.clj
@@ -100,7 +100,6 @@
    :post [(map? %)
           (= #{:fns :dependencies :service-protocol-sym :service-sym}
              (set (keys %)))
-          ((some-fn nil? symbol?) (:service-sym %))
           ((some-fn nil? symbol?) (:service-sym %))
           ((some-fn nil? symbol?) (:service-protocol-sym %))
           (vector? (:dependencies %))


Last modified default on nil

Last modified default on nil

--- src/yada/service.clj
+++ src/yada/service.clj
@@ -166,6 +166,7 @@
   (service-available? [_ _] true)
   (request-uri-too-long? [_ uri]
     (request-uri-too-long? 4096 uri))
+  (last-modified [_ ctx] nil)
   (body [_ _] nil)
   (post [_ _] nil)
   (produces [_] nil)


Clarify copy on Join/Leave topbar (#2126)

--- src-cljs/frontend/components/pieces/page_header.cljs
+++ src-cljs/frontend/components/pieces/page_header.cljs
@@ -237,8 +237,8 @@
         has-topbar? (feature/enabled? "top-bar-ui-v-1")
         toggle-topbar (when-not has-topbar? "top-bar-ui-v-1")
         toggle-topbar-text (if has-topbar?
-                             "Leave Beta UI"
-                             "Join Beta UI")
+                             "Go Back to Our Old Look"
+                             "Check Out Our New Look")
         om-next-page? (-> topbar-beta :nav-point routes/om-next-nav-point?)]
     (reify
       om/IDisplayName (display-name [_] "User Header")
@@ -265,7 +265,7 @@
                                   :on-click #((om/get-shared owner :track-event) {:event-type :feedback-clicked
                                                                                :properties {:component "topbar"
                                                                                :treatment "top-bar-beta"}})}
-                      "Provide Beta UI Feedback")])])
+                      "Give Topbar UI Feedback")])])

               (when (and (false? om-next-page?)
                          (false? show-nux-experience?))


Require cljs.reader explicitly, advanced optimization fails otherwise

--- src/app/ctl.cljs
+++ src/app/ctl.cljs
@@ -2,6 +2,7 @@
   (:require [cljs.core.async :refer [put! chan <! mult tap]]
             [dragonmark.web.core :as dw :refer [xf xform]]
             [app.datasource :as data]
+            [cljs.reader]
             [reagent.core :as reagent :refer [atom]])
   (:require-macros [app.templates :refer [deftmpl]]
                    [cljs.core.async.macros :refer [go]]))


Revert "moving reloaded.repl to dev dependencies"

This reverts commit 078b806d0e157088413ad3f9099e58d4dfaf291a.

--- ingestion-api/project.clj
+++ ingestion-api/project.clj
@@ -18,13 +18,13 @@
                  [org.clojure/tools.cli "0.3.1"]
                  [samsara/trackit "0.2.0"]
                  [org.clojure/math.numeric-tower "0.0.4"]
-                 [com.stuartsierra/component "0.3.0"]]
+                 [com.stuartsierra/component "0.3.0"]
+                 [reloaded.repl "0.2.1"]]
   :main ingestion-api.core
   :profiles {:uberjar {:aot :all}
              :dev {:dependencies [[midje "1.6.3"]
                                   [clojurewerkz/machine_head "1.0.0-beta9"]
-                                  [clj-mqtt "0.4.1-alpha"]
-                                  [reloaded.repl "0.2.1"]]
+                                  [clj-mqtt "0.4.1-alpha"]]
                    :plugins [[lein-midje "3.1.3"]
                              [lein-bin "0.3.5"]]}}
   :jvm-opts ["-server" "-Dfile.encoding=utf-8"]


Get port from env var GBU_HTTP_PORT.

Get port from env var GBU_HTTP_PORT.

--- src/gbu/core.clj
+++ src/gbu/core.clj
@@ -4,6 +4,10 @@
             [compojure.route :as route]
             [ring.adapter.jetty :as jetty]
             [gbu.web :as web]))
+
+(defn http-port
+  []
+  (or (System/getenv "GBU_HTTP_PORT") 5000))

 (defroutes app
   (GET "/" [] (web/home))
@@ -13,5 +17,4 @@
   (route/not-found "Oops 404"))

 (defn -main [& [port]]
-  (let [port (int 5000)]
-    (jetty/run-jetty (site #'app) {:port port :join? false})))+  (jetty/run-jetty (site #'app) {:port (http-port) :join? false}))


fix filename calculation

fix filename calculation

--- src/io/perun.clj
+++ src/io/perun.clj
@@ -35,9 +35,13 @@
     fileset))

 (defn add-filedata [f]
-  {:filename  (.getName (boot/tmp-file f))
-   :path      (boot/tmp-path f)
-   :full-path (.getPath (boot/tmp-file f))})
+  (let [tmpfile (boot/tmp-file f)]
+    {:filename  (some-> tmpfile
+                        .getName
+                        ; remove extension from the filename
+                        (clojure.string/replace #"[.][^.]+$" ""))
+     :path      (boot/tmp-path f)
+     :full-path (.getPath tmpfile)}))

 (deftask base
   "Adds some basic information to the perun metadata and


stringify uuid before sending it to 3rd parties

--- src-cljs/frontend/analytics.cljs
+++ src-cljs/frontend/analytics.cljs
@@ -6,9 +6,9 @@

 (defn init-user [cust]
   (utils/swallow-errors
-   (rollbar/init (:cust/uuid cust) (:cust/email cust)))
+   (rollbar/init (str (:cust/uuid cust)) (:cust/email cust)))
   (utils/swallow-errors
-   (mixpanel/identify (:cust/uuid cust))
+   (mixpanel/identify (str (:cust/uuid cust)))
    (mixpanel/name-tag (:cust/email cust))
    (mixpanel/set-people-props {:$email (:cust/email cust)
                                :$last_login (js/Date.)})))


Add compare-bytes

Add compare-bytes

--- src/useful/io.clj
+++ src/useful/io.clj
@@ -45,3 +45,15 @@
   (-> (ByteArrayOutputStream. 8)
       (doto (-> (DataOutputStream.) (.writeLong long)))
       (.toByteArray)))
+
+(defn compare-bytes [^"[B" a ^"[B" b]
+  (let [alen (alength a)
+        blen (alength b)
+        len (int (min alen blen))]
+    (loop [idx 0]
+      (if (= idx len)
+        (compare alen blen)
+        (let [diff (unchecked-subtract (aget a idx) (aget b idx))]
+          (if (zero? diff)
+            (recur (unchecked-inc-int idx))
+            diff))))))


Pass anim phase to :animate command

Pass anim phase to :animate command

for debug display

--- frontend/src/faceboard/animator.cljs
+++ frontend/src/faceboard/animator.cljs
@@ -50,7 +50,7 @@
             (let [next-phase (inc current-phase)]
               (if (< next-phase (count timing))
                 (do
-                  (perform! :animate path)
+                  (perform! :animate path current-phase)
                   (recur next-phase))
                 (perform! :stop-anim path)))))))))


Working on beat grid.

Working on beat grid.

--- src/afterglow/controllers/ableton_push_2.clj
+++ src/afterglow/controllers/ableton_push_2.clj
@@ -1117,16 +1117,18 @@

         (let [beat-width (/ button-cell-width (:bpb snapshot))
               beat-position (- button-cell-width (* beat-width (:beat-phase snapshot)))
-              metro (:metronome (:show controller))]
+              metro (:metronome (:show controller))
+              beat-background (colors/adjust-alpha white-color -0.25)]
           (.setClip graphics  0 (- Wayang/DISPLAY_HEIGHT 60) (* 2 button-cell-width) 40)
-          (set-graphics-color graphics (if (rhythm/snapshot-down-beat? snapshot) red-color white-color))
-          (.draw graphics (java.awt.geom.Line2D$Double. beat-position (- Wayang/DISPLAY_HEIGHT 40)
+          (set-graphics-color graphics (beat-mark-color snapshot))
+          (draw-beat-grid-triangle graphics beat-position beat-width 40 beat-background)
+          (.draw graphics (java.awt.geom.Line2D$Double. beat-position (beat-mark-top-y snapshot)
                                                         beat-position (- Wayang/DISPLAY_HEIGHT 20)))
           (loop [position (+ beat-position beat-width)
                  snap (rhythm/metro-snapshot metro (+ (:instant snapshot) (rhythm/metro-tick metro)))]
             (when (< position (* 2 button-cell-width))
               (set-graphics-color graphics (if (rhythm/snapshot-down-beat? snap) red-color white-color))
-              (.draw graphics (java.awt.geom.Line2D$Double. position (- Wayang/DISPLAY_HEIGHT 40)
+              (.draw graphics (java.awt.geom.Line2D$Double. position (beat-mark-top-y snap)
                                                             position (- Wayang/DISPLAY_HEIGHT 20)))
               (recur (+ position beat-width)
                      (rhythm/metro-snapshot metro (+ (:instant snap) (rhythm/metro-tick metro))))))
@@ -1134,7 +1136,7 @@
                  snap (rhythm/metro-snapshot metro (- (:instant snapshot) (rhythm/metro-tick metro)))]
             (when (>= position 0)
               (set-graphics-color graphics (if (rhythm/snapshot-down-beat? snap) red-color white-color))
-              (.draw graphics (java.awt.geom.Line2D$Double. position (- Wayang/DISPLAY_HEIGHT 40)
+              (.draw graphics (java.awt.geom.Line2D$Double. position (beat-mark-top-y snap)
                                                             position (- Wayang/DISPLAY_HEIGHT 20)))
               (recur (- position beat-width)
                      (rhythm/metro-snapshot metro (- (:instant snap) (rhythm/metro-tick metro)))))))


Refactor to use util/display utility

Refactor to use util/display utility

--- src/cljs/koeeoadi/components/faceeditor.cljs
+++ src/cljs/koeeoadi/components/faceeditor.cljs
@@ -54,9 +54,9 @@
                 face/bold
                 face/italic
                 face/underline]} (om/props comp)
-        {:keys [active-face]}    (om/get-computed comp)
-        active?                  (= name active-face)]
-    (dom/ul #js {:className (str (if active? "" "hide") "face-styles")}
+        {:keys [active-face]}    (om/get-computed comp)]
+    (dom/ul #js {:className "face-styles"
+                 :style (util/display (= name active-face))}
       (face-style comp :face/bold)
       (face-style comp :face/italic)
       (face-style comp :face/underline))))