Fix import declaration

Fix import declaration

--- src/buildviz/go/sync_jobs.clj
+++ src/buildviz/go/sync_jobs.clj
@@ -13,7 +13,7 @@
             [clojure.string :as str]
             [clojure.tools.logging :as log]
             [uritemplate-clj.core :as templ])
-  (:import [javax.xml.stream.XMLStreamException]))
+  (:import [javax.xml.stream XMLStreamException]))

 (defn- build-for-job [go-url stage-instance {:keys [name id]}]
   (let [job-instance (assoc stage-instance :job-name name)]


Pass-through boolean expressions.

Pass-through boolean expressions.

--- src/cavm/query/expression.clj
+++ src/cavm/query/expression.clj
@@ -42,7 +42,7 @@
       (contains? specialfns func) (func node scope)
       :else (apply func (map #(eval % scope) (rest node))))))

-(def ^:private as-is #{keyword? string?})
+(def ^:private as-is #{keyword? string? #(contains? #{true false} %)})

 (defn- sqlcall-node [^honeysql.types.SqlCall node scope]
   (let [fname (.name node) args (.args node)]


Implement new exact bpm calculation

Implement new exact bpm calculation

--- src/clj/beat_detector/bpm.clj
+++ src/clj/beat_detector/bpm.clj
@@ -12,9 +12,8 @@
 (defn patterned-beats
   "Returns timestamps of patterned beats(those which yield 0 from
   autocorrelation)."
-  [times]
-  (let [interval (estimated-interval times)
-        best-corr (autocorrelate times interval)
+  [times interval]
+  (let [best-corr (autocorrelate times interval)
         index-zip (map vector best-corr (range))]
     (mapv times (reduce (fn [acc [x y]]
                           (if (zero? x) (conj acc y) acc))
@@ -36,7 +35,7 @@
   "Tries candidate-major-beats using times as pivots and finds a long enough
   major beats chain."
   [times interval]
-  (let [pivots (patterned-beats times)
+  (let [pivots (patterned-beats times interval)
         _ (println "All beats:" times)
         _ (println "Patterned beats:" pivots)
         _ (println "Interval: " interval)]
@@ -64,9 +63,21 @@
 (defn determine-bpm ; SLOW
   [times]
   (let [majors (find-major-beats times)
+        interval (estimated-interval times) ; FIXME double computation
+        intervals (map #(- (second %) (first %)) (partition 2 1 majors))]
+    (* 4 (/ (/ (* 60 44100.0) 1024.0)
+            (average
+              (reduce (fn [xs y]
+                        (if (> (- y interval) (* 0.25 interval)) ; New segment
+                          xs
+                          (conj xs y))) [] intervals)))))) ; exact interval
+
+(comment (defn determine-bpm ; SLOW
+  [times]
+  (let [majors (find-major-beats times)
         interval (estimated-interval times)
         ^double duration (- (last majors) (first majors))
         n-beats (Math/round (/ duration interval))
         exact-interval (/ duration n-beats)
         _ (println "Exact interval: " exact-interval)]
-    (* 4 (/ (/ (* 60 44100.0) 1024.0) exact-interval))))
+    (* 4 (/ (/ (* 60 44100.0) 1024.0) exact-interval)))))


fix Lakshmi SF agenda targeting

fix Lakshmi SF agenda targeting

--- src/clj/game/cards-assets.clj
+++ src/clj/game/cards-assets.clj
@@ -381,14 +381,14 @@
    "Lakshmi Smartfabrics"
    {:events {:rez {:effect (effect (add-prop card :counter 1))}}
     :abilities [{:req (req (seq (filter #(and (is-type? % "Agenda")
-                                              (= (get card :counter 0) (:agendapoints %))) (:hand corp))))
+                                              (>= (get card :counter 0) (:agendapoints %))) (:hand corp))))
                  :label "X power counters: Reveal an agenda worth X points from HQ"
                  :effect (req (let [c (:counter card)]
                                 (resolve-ability
                                   state side
-                                  {:prompt "Choose an agenda in HQ"
+                                  {:prompt "Choose an agenda in HQ to reveal"
                                    :choices {:req #(and (is-type? % "Agenda")
-                                                        (= c (:agendapoints %)))}
+                                                        (>= c (:agendapoints %)))}
                                    :msg (msg "reveal " (:title target) " from HQ")
                                    :effect (req (let [title (:title target)
                                                       pts (:agendapoints target)]


underlying library fixed the sync connect bug, so connect timeout doesn't imply async connect anymore

--- src/clj/http/async/client.clj
+++ src/clj/http/async/client.clj
@@ -62,9 +62,7 @@
       (when max-conns-per-host (.setMaximumConnectionsPerHost b max-conns-per-host))
       (when max-conns-total (.setMaximumConnectionsTotal b max-conns-total))
       (when max-redirects (.setMaximumNumberOfRedirects b max-redirects))
-      (when (or connection-timeout      ;; connection timeout is not enforced by the underlying library
-                ;; unless it's in the async connect mode, which is not the default
-                (not (nil? async-connect)))
+      (when async-connect
         (let [provider-config (doto (NettyAsyncHttpProviderConfig.)
                                 (.removeProperty NettyAsyncHttpProviderConfig/USE_BLOCKING_IO)
                                 (.addProperty NettyAsyncHttpProviderConfig/EXECUTE_ASYNC_CONNECT true))]


better print for forms

better print for forms

--- src/clj/introclojure/eval.clj
+++ src/clj/introclojure/eval.clj
@@ -1,7 +1,8 @@
 (ns introclojure.eval
   (:require [net.cgrand.sjacket :as sj]
             [net.cgrand.sjacket.parser :as p]
-            [clojure.string]))
+            [clojure.string]
+            [clojure.pprint]))

 (defn pos-to-idx [text line pos]
@@ -63,15 +64,23 @@

+(defn pprint-to-str [f]
+  (let [s (java.io.StringWriter.)]
+    (binding [*out* s]
+      (clojure.pprint/pprint f))
+    (let [r (.toString s)]
+      (.substring r 0 (dec (.length r))))))
+
+

 (defn eval-from-text [text line pos]

   (let [ffo (find-form-offsets text)
         idx (pos-to-idx text line pos)
-        [s e :as fo]  (last (filter #(>= idx (first %)) ffo))
+        [s e :as fo]  (or (last (filter #(>= idx (first %)) ffo)) (first ffo))
         f   (.substring text s e)
         ]
-    (assoc (fo-to-info  fo text) :eval (str (eval (read-string f))))
+    (assoc (fo-to-info  fo text) :eval (pprint-to-str (eval (read-string f))))

   ))

@@ -81,6 +90,6 @@

 (idx-to-pos "(+ 1 2)\n a" 13)

-(find-form-offsets "(+ 1 2)\n a")
+(find-form-offsets " (+ 1 2)\n a")

-(eval-from-text "(+ 1 2)\n a" 0 0)
+(eval-from-text " (+ 1 2)\n a" 0 0)


fix cache foobar

fix cache foobar

--- src/clj/shadow/cljs/build.clj
+++ src/clj/shadow/cljs/build.clj
@@ -845,7 +845,9 @@
   ;; only cache files that don't have warnings!
   (when-not (seq (:warnings rc))

-    (let [cache-file (get-cache-file-for-rc state rc)
+    (let [cache-file
+          (get-cache-file-for-rc state rc)
+
           cache-data
           (-> rc
               (dissoc :file :output :input :url)
@@ -873,7 +875,9 @@

       (log state {:type :cache-write
                   :ns ns
-                  :name name}))))
+                  :name name})
+
+      true)))

 (defn maybe-compile-cljs
   "take current state and cljs resource to compile
@@ -888,11 +892,14 @@
                              from-jar)))]
     (or (when cache?
           (load-cached-cljs-resource state src))
-        (-> (do-compile-cljs-resource state src)
-            (cond->
-              cache?
-              (write-cached-cljs-resource state))
-            (assoc :cached false)))))
+        (let [compiled-src
+              (do-compile-cljs-resource state src)]
+
+          (when cache?
+            (write-cached-cljs-resource compiled-src state))
+
+          ;; fresh compiled, not from cache
+          (assoc compiled-src :cached false)))))

 (defn merge-provides [state provided-by provides]
   (reduce


revised Team Sponsorship tests

revised Team Sponsorship tests

--- src/clj/test/cards-assets.clj
+++ src/clj/test/cards-assets.clj
@@ -47,13 +47,13 @@
       (core/advance state :corp {:card (refresh ag1)})
       (core/advance state :corp {:card (refresh ag1)})
       (core/score state :corp {:card (refresh ag1)})
-      ; TSP prompt should be active
-      (is (= (:cid tsp) (get-in @state [:corp :prompt 0 :card :cid])))
-      (prompt-choice :corp "HQ")
-      (prompt-card :corp (find-card "Adonis Campaign" (:hand (get-corp))))
+      (is (= (:ts-active (refresh tsp)) true) "Team Sponsorship ability enabled")
+      (card-ability state :corp tsp 0)
+      (prompt-select :corp (find-card "Adonis Campaign" (:hand (get-corp))))
       (prompt-choice :corp "New remote")
       (is (= "Adonis Campaign" (get-in @state [:corp :servers :remote3 :content 0 :title])) "Adonis installed by Team Sponsorship")
-      (is (nil? (find-card "Adonis Campaign" (:hand (get-corp)))) "No Adonis in hand"))))
+      (is (nil? (find-card "Adonis Campaign" (:hand (get-corp)))) "No Adonis in hand")
+      (is (nil? (:ts-active (refresh tsp))) "Team Sponsorship ability disabled"))))

 (deftest team-sponsorship-archives
   "Team Sponsorship - Install from Archives"
@@ -70,13 +70,13 @@
       (core/advance state :corp {:card (refresh ag1)})
       (core/advance state :corp {:card (refresh ag1)})
       (core/score state :corp {:card (refresh ag1)})
-      ; TSP prompt should be active
-      (is (= (:cid tsp) (get-in @state [:corp :prompt 0 :card :cid])))
-      (prompt-choice :corp "Archives")
-      (prompt-card :corp (find-card "Adonis Campaign" (:discard (get-corp))))
+      (is (= (:ts-active (refresh tsp)) true) "Team Sponsorship ability enabled")
+      (card-ability state :corp tsp 0)
+      (prompt-select :corp (find-card "Adonis Campaign" (:discard (get-corp))))
       (prompt-choice :corp "New remote")
       (is (= "Adonis Campaign" (get-in @state [:corp :servers :remote3 :content 0 :title])) "Adonis installed by Team Sponsorship")
-      (is (nil? (find-card "Adonis Campaign" (:discard (get-corp)))) "No Adonis in discard"))))
+      (is (nil? (find-card "Adonis Campaign" (:discard (get-corp)))) "No Adonis in discard")
+      (is (nil? (:ts-active (refresh tsp))) "Team Sponsorship ability disabled"))))

 (deftest team-sponsorship-multiple
   "Team Sponsorship - Multiple installed"
@@ -88,21 +88,23 @@
     (play-from-hand state :corp "Domestic Sleepers" "New remote")
     (core/move state :corp (find-card "Adonis Campaign" (:hand (get-corp))) :discard)
     (let [ag1 (get-in @state [:corp :servers :remote3 :content 0])
-          tsp1 (get-in @state [:corp :servers :remote2 :content 0])
-          tsp2 (get-in @state [:corp :servers :remote1 :content 0])]
+          tsp2 (get-in @state [:corp :servers :remote2 :content 0])
+          tsp1 (get-in @state [:corp :servers :remote1 :content 0])]
       (core/rez state :corp tsp1)
       (core/rez state :corp tsp2)
       (core/gain state :corp :click 6 :credit 6)
       (core/advance state :corp {:card (refresh ag1)})
       (core/advance state :corp {:card (refresh ag1)})
       (core/score state :corp {:card (refresh ag1)})
-      ; TSP prompt should be active
-      (prompt-choice :corp "Archives")
-      (prompt-card :corp (find-card "Adonis Campaign" (:discard (get-corp))))
+      (is (= (:ts-active (refresh tsp1)) true) "Team Sponsorship 1 ability enabled")
+      (is (= (:ts-active (refresh tsp2)) true) "Team Sponsorship 2 ability enabled")
+      (card-ability state :corp tsp1 0)
+      (prompt-select :corp (find-card "Adonis Campaign" (:discard (get-corp))))
       (prompt-choice :corp "New remote")
-      ; second prompt should be active
-      (prompt-choice :corp "HQ")
-      (prompt-card :corp (find-card "Adonis Campaign" (:hand (get-corp))))
+      (card-ability state :corp tsp2 0)
+      (prompt-select :corp (find-card "Adonis Campaign" (:hand (get-corp))))
       (prompt-choice :corp "New remote")
       (is (= "Adonis Campaign" (get-in @state [:corp :servers :remote4 :content 0 :title])) "Adonis installed by Team Sponsorship")
-      (is (= "Adonis Campaign" (get-in @state [:corp :servers :remote5 :content 0 :title])) "Adonis installed by Team Sponsorship"))))
+      (is (= "Adonis Campaign" (get-in @state [:corp :servers :remote5 :content 0 :title])) "Adonis installed by Team Sponsorship")
+      (is (nil? (:ts-active (refresh tsp1))) "Team Sponsorship 1 ability disabled")
+      (is (nil? (:ts-active (refresh tsp2))) "Team Sponsorship 2 ability disabled"))))


refactor key and value decoder to use the defaultdecoder

--- src/clj_kafka/consumer/zk.clj
+++ src/clj_kafka/consumer/zk.clj
@@ -1,6 +1,7 @@
 (ns clj-kafka.consumer.zk
   (:import [kafka.consumer ConsumerConfig Consumer KafkaStream]
-           [kafka.javaapi.consumer ConsumerConnector])
+           [kafka.javaapi.consumer ConsumerConnector]
+           [kafka.serializer DefaultDecoder])
   (:use [clj-kafka.core :only (as-properties to-clojure with-resource)])
   (:require [zookeeper :as zk]))

@@ -34,6 +35,11 @@
    (when (.hasNext it)
      (cons (.next it) (lazy-iterate it)))))

+(defn default-decoder
+  "Creates the default decoder that reads message keys and values as byte arrays."
+  []
+  (DefaultDecoder. nil))
+
 (defn create-message-streams
   "Creates message streams for consuming topics. "
   ([^ConsumerConnector consumer topic-count-map]
@@ -51,10 +57,10 @@
   "Provides an easy way to consume a sequence of KafkaMessage messages from the
   named topic. Consumes on a single thread and returns a lazy sequence."
   [^ConsumerConnector consumer topic & {:keys [key-decoder
-                                               value-decoder]}]
+                                               value-decoder]
+                                        :or   {key-decoder (default-decoder)
+                                               value-decoder (default-decoder)}}]
   (let [topic-count-map {topic (int 1)}
-        streams (if (or key-decoder value-decoder)
-                  (create-message-streams consumer topic-count-map key-decoder value-decoder)
-                  (create-message-streams consumer topic-count-map))
+        streams (create-message-streams consumer topic-count-map key-decoder value-decoder)
         [stream & _] (get streams topic)]
     (stream-seq stream)))


Avoid reflection in `lazy-iterate`

Avoid reflection in `lazy-iterate`

--- src/clj_kafka/consumer/zk.clj
+++ src/clj_kafka/consumer/zk.clj
@@ -29,7 +29,7 @@
   (.shutdown consumer))

 (defn- lazy-iterate
-  [it]
+  [^java.util.Iterator it]
   (lazy-seq
    (when (.hasNext it)
      (cons (.next it) (lazy-iterate it)))))


fixed up

fixed up

--- src/cljs/schutzen/assets.cljs
+++ src/cljs/schutzen/assets.cljs
@@ -6,12 +6,14 @@
   (:require [schutzen.utils :refer [log]]
             [cljs.core.async
              :as async
-             :refer [put! take! chan <! >! close!]]))
+             :refer [put! chan <! close!]]))

 (def asset-images
   (atom
    ;;Image Assets
-   {:dot {:url "dot.png"} ;;test
+   {:dot {:url "dot.png"}
+
+
     }))

 (defn get-image


Updating in memory settings for ingest.

Updating in memory settings for ingest.

--- src/cmr/dev_system/system.clj
+++ src/cmr/dev_system/system.clj
@@ -5,6 +5,7 @@
             [cmr.indexer.system :as indexer-system]
             [cmr.search.system :as search-system]
             [cmr.ingest.system :as ingest-system]
+            [cmr.ingest.data.provider-acl-hash :as ingest-data]
             [cmr.index-set.system :as index-set-system]
             [cmr.mock-echo.system :as mock-echo-system]
             [cmr.metadata-db.data.memory-db :as memory]
@@ -66,9 +67,8 @@

   ;; Sets a bit of global state for the application and system integration tests that will know how to talk to elastic
   (config/set-config-value! :elastic-port in-memory-elastic-port-for-connection)
-
+  ;; The same in memory db is used for metadata db by itself and in search so they contain the same data
   (let [in-memory-db (memory/create-db)]
-    ;; Memory DB configured to run in memory
     {:apps {:mock-echo (mock-echo-system/create-system)
             :metadata-db (-> (mdb-system/create-system)
                              (assoc :db in-memory-db)
@@ -76,7 +76,8 @@
             ;; Bootstrap is not enabled for in-memory dev system
             :indexer (indexer-system/create-system)
             :index-set (index-set-system/create-system)
-            :ingest (ingest-system/create-system)
+            :ingest (-> (ingest-system/create-system)
+                        (assoc :db (ingest-data/create-in-memory-acl-hash-store)))
             :search (assoc-in (search-system/create-system)
                               [:metadata-db :db]
                               in-memory-db)}


CMR-615: Added support for validating content type.

--- src/cmr/search/api/routes.clj
+++ src/cmr/search/api/routes.clj
@@ -27,6 +27,10 @@
 (def CURL_CLIENT_ID "curl")
 (def UNKNOWN_CLIENT_ID "unknown")

+(def supported-content-types
+  "The content types supported by search"
+  #{"application/x-www-form-urlencoded"})
+
 (def extension->mime-type
   "A map of URL file extensions to the mime type they represent."
   {"json" "application/json"
@@ -232,7 +236,7 @@
         {:status 200}))
     (route/not-found "Not Found")))

-;; Copies the body into a new attributed called :body-copy so that after a post of form content type
+;; Copies the body into a new attribute called :body-copy so that after a post of form content type
 ;; the original body can still be read. The default ring params reads the body and parses it and we
 ;; don't have access to it.
 (defn copy-of-body-handler
@@ -243,11 +247,23 @@
                 :body-copy body
                 :body (java.io.ByteArrayInputStream. (.getBytes body)))))))

+;; Validates the content type of the request.
+(defn content-type-handler
+  [f]
+  (fn [request]
+    (println request)
+    (let [content-type (get-in request [:headers "content-type"])]
+      (if (get supported-content-types content-type)
+        (f request)
+        (svc-errors/throw-service-error :bad-request
+                                        (str "Unsupported content type [" content-type "]"))))))
+
 (defn make-api [system]
   (-> (build-routes system)
       (http-trace/build-request-context-handler system)
-      errors/exception-handler
       handler/site
       copy-of-body-handler
+      content-type-handler
+      errors/exception-handler
       ring-json/wrap-json-body
       ring-json/wrap-json-response))


The add-src task is back, via the --add-source option to sift task (fixes #58)

--- boot/core/src/boot/task/built_in.clj
+++ boot/core/src/boot/task/built_in.clj
@@ -252,7 +252,7 @@
   The move option applies a find/replace transformation on all paths in the
   output fileset."

-  [a add-src            bool        "Add all input files to output fileset."
+  [a add-source         bool        "Add all input files to output fileset."
    m move MATCH:REPLACE {regex str} "The map of regex to replacement path strings."
    i include REGEX      #{regex}    "The set of regexes that paths must match."
    x exclude REGEX      #{regex}    "The set of regexes that paths must not match."]
@@ -266,7 +266,7 @@
                              to-path   (mvpath from-path move)]
                          (core/mv %1 from-path to-path)))
           remover #(if (keep? (io/file (core/tmppath %2))) %1 (core/rm %1 [%2]))
-          addsrcs #(if-not add-src % (core/mv-resource % (core/input-files %)))]
+          addsrcs #(if-not add-source % (core/mv-resource % (core/input-files %)))]
       (util/info "Sifting output files...\n")
       (-> (addsrcs fileset)
           (core/fileset-reduce core/output-files remover mover)


Suppress updates when running show --fake-classpath

--- boot/core/src/boot/task/built_in.clj
+++ boot/core/src/boot/task/built_in.clj
@@ -107,7 +107,7 @@
    c classpath        bool "Print the project's full classpath."
    C fake-classpath   bool "Print the project's fake classpath."]

-  (let [updates (or updates update-snapshots (not (or deps env fileset classpath)))]
+  (let [updates (or updates update-snapshots (not (or deps env fileset classpath fake-classpath)))]
     (core/with-pre-wrap fileset'
       (when deps    (print (pod/with-call-worker (boot.aether/dep-tree ~(core/get-env)))))
       (when env     (println (pr-str (core/get-env))))


Fix member domain check in lookup.

Fix member domain check in lookup.

--- src/member_domains/lookup.clj
+++ src/member_domains/lookup.clj
@@ -36,7 +36,7 @@
 (defn try-hostname
   "Try to get a hostname from a URL string."
   [text]
-  (try (.getHostname (new URL text)) (catch Exception _ nil)))
+  (try (.getHost (new URL text)) (catch Exception e (do (info "Failed to parse URL:" text) nil))))

 (defn doi-from-url
   "If a URL is a DOI, return the non-URL version of the DOI."
@@ -143,8 +143,9 @@
   "Take a URL and try to resolve it to find what DOI it corresponds to."
   [url limit-to-member-domains]
   (info "Try to resolve:" url)
+
   ; Check if we want to bother with this URL.
-  (when (or (-> url try-hostname (get @member-full-domains))
+  (when (or (->> url try-hostname (get @member-full-domains))
             (not limit-to-member-domains))
     (when-let [result (try-try-again {:sleep 500 :tries 2} #(http/get url
                                                            {:follow-redirects true


Add back the Authorization field to Swagger POST reqs (#799)

--- src/ctia/http/routes/crud.clj
+++ src/ctia/http/routes/crud.clj
@@ -57,6 +57,7 @@
        (POST "/" []
              :return entity-schema
              :body [new-entity new-schema {:description (format "a new %s" capitalized)}]
+             :header-params [{Authorization :- (s/maybe s/Str) nil}]
              :summary (format "Adds a new %s" capitalized)
              :capabilities post-capabilities
              :auth-identity identity


Adding note in UI about load failure

Adding note in UI about load failure

--- src/dat/sys/client/views.cljs
+++ src/dat/sys/client/views.cljs
@@ -69,6 +69,7 @@
      :margin "20px 5px 5px"
      :children [[:h2 "Todos"]
                 [:p "Below are forms and views for each todo item in the database:"]
+                [:p "(Unfortunately, these probably won't render properly right away. You have to save a file to get figwheel to force an update. Even then, the styles aren't applying properly. But we're on the trail and should have a fix soon.)"]
                 (for [todo todo-eids]
                   ^{:key todo}
                   [:div {:style {:margin "20px 5px"}}


Actually talk about an undo when undoing

--- src/exploud/messages/data.clj
+++ src/exploud/messages/data.clj
@@ -465,7 +465,7 @@
         (hubot/speak-about-deployment-start parameters)
         (log/write (format "Starting deployment of '%s' to '%s'." application environment)))
       (do
-        (hubot/speak-about-deployment-start parameters)
+        (hubot/speak-about-deployment-undo parameters)
         (log/write (format "Starting undo of '%s' in '%s'." application environment))))
     (success (-> parameters
                  (assoc :phase "deployment")


Idiomatic usage of import in ns macro.

Idiomatic usage of import in ns macro.

--- src/examples/clojure/rx/lang/clojure/examples/rx_examples.clj
+++ src/examples/clojure/rx/lang/clojure/examples/rx_examples.clj
@@ -1,5 +1,5 @@
 (ns rx.lang.clojure.examples.rx-examples
-  (import rx.Observable)
+  (:import rx.Observable)
   (:require [clj-http.client :as http]))

 ; NOTE on naming conventions. I'm using camelCase names (against clojure convention)


Add `valid?` predicate that prints debug info to stdout.

When the predicate fails. Very usefull when used with preconditions
that by default does not print nothing.

--- backend/src/uxbox/util/spec.clj
+++ backend/src/uxbox/util/spec.clj
@@ -30,6 +30,12 @@
                 :message (s/explain-str spec data)
                 :context (s/explain-data spec data))
       result)))
+
+(defn valid?
+  [spec data]
+  (if (s/valid? spec data)
+    true
+    (s/explain spec data)))

 ;; --- Predicates


Fixes #220 - avoid out-of-sync preference node issues when saving REPL command history + attempt to recover when a preference node is touched outside of eclipse

--- ccw.core/src/ccw/repl/cmdhistory.clj
+++ ccw.core/src/ccw/repl/cmdhistory.clj
@@ -1,8 +1,12 @@
 (ns ccw.repl.cmdhistory
   (:use (clojure.contrib def core))
   (:import
+    ccw.CCWPlugin
     org.eclipse.core.runtime.jobs.Job
-    org.eclipse.core.runtime.IProgressMonitor))
+    org.eclipse.core.resources.IResource
+    org.eclipse.core.runtime.IProgressMonitor
+    org.osgi.service.prefs.BackingStoreException
+    org.eclipse.core.runtime.preferences.IEclipsePreferences))

 (defvar- queued-commands (ref {})
   "Map between project names and vectors of REPL expressions that have yet to
@@ -16,12 +20,13 @@
 (defvar- persist-schedule-ms 30000
   "Queued commands are persisted to project preferences every _ milliseconds.")

-(defn- get-pref-node
+(defn- ^IEclipsePreferences get-pref-node
   [project-name]
   (-?> project-name
     ccw.launching.LaunchUtils/getProject
     org.eclipse.core.resources.ProjectScope.
-    (.getNode pref-node-id)))
+    (.getNode pref-node-id)
+    (doto .sync)))

 (defn- queue-expression
   [project-name expr]
@@ -53,31 +58,52 @@
        (partial queue-expression project-name)]
       [[] identity])))

-(defn- save-history
-  [project-name history]
-  (doto (get-pref-node project-name)
-    (.put history-key (pr-str history))
-    .flush))
+(defn- save-cmds
+  [^IProgressMonitor pm queued-commands]
+  (loop [[[project-name exprs] & rqs :as queued-commands] (seq queued-commands)
+         retrying? false]
+    (when project-name
+      (let [[history] (get-history project-name)
+            node (get-pref-node project-name)
+            retry? (atom false)]
+        (.subTask pm project-name)
+        (try (doto node
+               (.put history-key (->> (reverse exprs)
+                                   (concat history)
+                                   (take-last max-history)
+                                   ; prevent consecutive duplicate expressions
+                                   (partition-by identity)
+                                   (mapcat (partial take 1))
+                                   vec
+                                   pr-str))
+               .flush)
+          (catch BackingStoreException e
+            (if retrying?
+              (CCWPlugin/logError e)
+              (reset! retry? true))))
+        (if (not @retry?)
+          (recur rqs false)
+          (do
+            ; maybe someone touched our project prefs; refresh
+            (CCWPlugin/log (format "Refreshing settings dir for %s, re-attempting saving REPL command history" project-name))
+            (-?> project-name
+              ccw.launching.LaunchUtils/getProject
+              (.getFolder ".settings")
+              (.refreshLocal IResource/DEPTH_INFINITE nil))
+            (recur queued-commands true)))))))

 (defvar- save-cmds-job
   (doto (proxy [Job] ["ccw REPL command history persistence"]
-          (run [^IProgressMonitor pm]
-            (.beginTask pm "Persisting REPL histories" IProgressMonitor/UNKNOWN)
-            (doseq [[project-name exprs] (dosync (let [queued @queued-commands]
-                                                  (ref-set queued-commands {})
-                                                  queued))
-                    :let [[history] (get-history project-name)]]
-              (.subTask pm project-name)
-              (save-history project-name (->> (reverse exprs)
-                                           (concat history)
-                                           (take-last max-history)
-                                           ; prevent consecutive duplicate expressions
-                                           (partition-by identity)
-                                           (mapcat (partial take 1))
-                                           vec)))
-            (.done pm)
-            (.schedule this persist-schedule-ms)
-            org.eclipse.core.runtime.Status/OK_STATUS))
+          (run [pm]
+            (try
+              (.beginTask pm "Persisting REPL histories" IProgressMonitor/UNKNOWN)
+              (save-cmds pm (dosync (let [queued (ensure queued-commands)]
+                                      (ref-set queued-commands {})
+                                      queued)))
+              (.done pm)
+              org.eclipse.core.runtime.Status/OK_STATUS
+              (finally
+                (.schedule this persist-schedule-ms)))))
     (.setSystem true)))

 (defn- schedule-job


(PCP-357) Don't start heartbeat task before connecting

Adding the start-heartbeat-task to the Client interface; it will be up
to the client code to actually start the heartbeat task to keep the
WebSocket connection up.

Removing the call that starts the heartbeat task right before spawning
the make-connection thread (in the 'connect' function).

--- src/puppetlabs/pcp/client.clj
+++ src/puppetlabs/pcp/client.clj
@@ -40,7 +40,12 @@
     pcp-broker.")
   (close [client]
     "Close the connection.  Once the client is close you will need a
-    new one."))
+    new one.")
+  (start-heartbeat-thread [client]
+    "Starts a thread that will periodically send WebSocket pings to the pcp-broker.
+    Propagates any unhandled exception thrown while attempting to connect.
+    Will raise ::not-connected if the client is not currently connected with the
+    pcp-broker."))

 (def Handlers
   "schema for handler map.  String keys are data_schema handlers,
@@ -52,7 +57,8 @@
 ;; ClientInterface
 (declare -connecting? -connected?
          -associating? -associated?
-         -wait-for-connection -wait-for-association -send! -close)
+         -wait-for-connection -wait-for-association -send! -close
+         -start-heartbeat-thread)

 (s/defrecord Client
   [server :- s/Str
@@ -72,7 +78,8 @@
   (wait-for-connection [client timeout] (-wait-for-connection client timeout))
   (wait-for-association [client timeout] (-wait-for-association client timeout))
   (send! [client message] (-send! client message))
-  (close [client] (-close client)))
+  (close [client] (-close client))
+  (start-heartbeat-thread [client] (-start-heartbeat-thread client)))

 (s/defn ^:always-validate ^:private -connecting? :- s/Bool
   [client :- Client]
@@ -135,12 +142,11 @@
     identity))

 (s/defn ^:always-validate ^:private heartbeat
-  "Starts the WebSocket heartbeat task that sends pings over the
+  "Provides the WebSocket heartbeat task that sends pings over the
   current set of connections as long as the 'should-stop' promise has
   not been delivered.  Will keep a connection alive, or detect a
   stalled connection earlier."
   [client :- Client]
-  (log/debug "WebSocket heartbeat task is about to start" client)
   (let [{:keys [should-stop websocket-client]} client]
     (while (not (deref should-stop 15000 false))
       (let [sessions (.getOpenSessions websocket-client)]
@@ -148,6 +154,18 @@
         (doseq [session sessions]
           (.. session (getRemote) (sendPing (ByteBuffer/allocate 1))))))
     (log/debug "WebSocket heartbeat task is about to finish")))
+
+(s/defn ^:always-validate ^:private -start-heartbeat-thread
+  "Ensures that the WebSocket connection is established and starts the WebSocket
+  heartbeat task.  Propagates any unhandled exception thrown while attempting
+  to connect. Rasises ::not-connected in case the connection was not established."
+  [client :- Client]
+  (log/trace "Ensuring that the WebSocket is connected")
+  (when-not (-connected? client)
+    (throw+ {:type ::not-connected}))
+  (log/debug "WebSocket heartbeat task is about to start" client)
+  (.start (Thread. (partial heartbeat client))))
+

 (s/defn ^:always-validate ^:private make-connection :- Object
   "Returns a connected websocket connection"
@@ -277,6 +295,5 @@
                              :should-stop (promise)
                              :user-data user-data})
         {:keys [websocket-connection]} client]
-    (.start (Thread. (partial heartbeat client)))
     (reset! websocket-connection (future (make-connection client)))
     client))


Give names to anonymous functions

Give names to anonymous functions

--- src/re_frame/interceptor.cljc
+++ src/re_frame/interceptor.cljc
@@ -246,13 +246,13 @@
   So, you won't want this interceptor present in production code. See the todomvc
   example to see how to exclude interceptors from production code."
   (->interceptor
-    :name :debug
-
-    :before (fn [context]
+    :name   :debug
+    :before (fn debug-before
+              [context]
               #_(console :log "Handling re-frame event: " (-> context :coeffects :event))
               context)
-
-    :after  (fn [context]
+    :after  (fn debug-after
+              [context]
               (let [event          (get-coeffect context :event)
                     orig-db        (get-coeffect context :db)
                     new-db         (get-effect   context :db)]
@@ -280,9 +280,9 @@
         [db [x y z]]    ;; <-- instead of [_ x y z]
         ....)"
   (->interceptor
-    :name :trim-v
-
-    :before  (fn [context]
+    :name    :trim-v
+    :before  (fn trimv-before
+               [context]
                (->>  (get-coeffect context :event)
                      rest
                      vec
@@ -310,13 +310,11 @@
   [handler-fn]
   (->interceptor
     :name   :db-handler
-
-    :before (fn handler-wrapper
-              [context]
-              (let [{:keys [db event]} (:coeffects context)
-                    context' (->>  (handler-fn db event)
-                                   (assoc-effect context :db))]
-                context'))))
+    :before (fn db-handler-before
+              [context]
+              (let [{:keys [db event]} (:coeffects context)]
+                (->>  (handler-fn db event)
+                      (assoc-effect context :db))))))

 (defn fx-handler->interceptor
@@ -419,8 +417,8 @@
   [f]
   (->interceptor
     :name  :enrich
-
-    :after (fn [context]
+    :after (fn enrich-after
+             [context]
              (let [event (get-coeffect context :event)
                    db    (get-effect context :db)]
                (->> (f db event)
@@ -439,8 +437,8 @@
   [f]
   (->interceptor
     :name  :after
-
-    :after (fn [context]
+    :after (fn after-after
+             [context]
              (let [db    (get-effect context :db)
                    event (get-coeffect context :event)]
                (f db event)    ;; call f for side effects
@@ -470,8 +468,8 @@
   [f out-path & in-paths]
   (->interceptor
     :name  :enrich
-
-    :after (fn [context]
+    :after (fn on-change-after
+             [context]
              (let [new-db   (get-effect context :db)
                    old-db   (get-coeffect context :db)


Remove funs from flow nodes so that value equality works

--- src/aurora/language.cljs
+++ src/aurora/language.cljs
@@ -245,92 +245,6 @@

   )

-;; FLOWS
-
-(defrecord Union [nodes])
-(defrecord FilterMap [nodes fun])
-(defrecord Index [nodes key-ixes])
-(defrecord Lookup [nodes index-node key-ixes val-ixes])
-
-(defn flow->nodes [flow]
-  (:nodes flow))
-
-;; FLOW PLAN
-
-(defrecord FlowPlan [node->flow flow->node])
-
-(defn flow-plan->flow-state [{:keys [node->flow]}]
-  (let [node->state (into-array (for [_ node->flow] nil))
-        node->out-nodes (into-array (for [_ node->flow] #js []))
-        node->facts (into-array (for [_ node->flow] #js []))
-        node->update! (into-array (for [_ node->flow] nil))]
-    (dotimes [node (count node->flow)]
-      (let [flow (nth node->flow node)]
-        (aset node->state node
-              (condp = (type flow)
-                Union (transient #{})
-                FilterMap nil
-                Index (transient {})
-                Lookup nil))
-        (doseq [in-node (:nodes flow)]
-          (apush (aget node->out-nodes in-node) node))
-        (aset node->update! node
-              (condp = (type flow)
-                Union (union-update!)
-                FilterMap (filter-map-update! (:fun flow))
-                Index (index-update! (:key-ixes flow))
-                Lookup (lookup-update! (:index-node flow) (:key-ixes flow) (:val-ixes flow))))))
-    (FlowState. node->state node->out-nodes node->facts node->update!)))
-
-(defn memory->node [memory]
-  (case memory
-    :known 0
-    :pretended 1
-    :remembered 2
-    :forgotten 3))
-
-(defn memory->nodes [memory]
-  (case memory
-    :known [0]
-    :pretended [1]
-    :remembered [2]
-    :forgotten [3]
-    :known&pretended [0 1]))
-
-(def empty-flow-plan
-  (FlowPlan. [(Union. #{}) (Union. #{}) (Union. #{}) (Union. #{})] {}))
-
-(defn add-output [flow-plan node memory]
-  (update-in flow-plan [:node->flow (memory->node memory) :nodes] conj node))
-
-(defn add-flow [{:keys [node->flow flow->node] :as flow-plan} flow]
-  (if-let [node (flow->node flow)]
-    [flow-plan node]
-    (let [node (count node->flow)
-          node->flow (conj node->flow flow)
-          flow->node (assoc flow->node flow node)]
-      [(FlowPlan. node->flow flow->node) node])))
-
-(comment
-  (deffact edge "[x] has an edge to [y]")
-  (deffact connected "[x] is connected to [y]")
-
-  (def known&pretended [0 1])
-
-  (let [plan empty-flow-plan
-        [plan edges] (add-flow plan (FilterMap. known&pretended (fn [x] (when (= edge (.-shape x)) x))))
-        [plan connecteds] (add-flow plan (FilterMap. known&pretended (fn [x] (when (= connected (.-shape x)) x))))
-        [plan edges-index] (add-flow plan (Index. [edges] #js [1]))
-        [plan connecteds-index] (add-flow plan (Index. [connecteds] #js [0]))
-        [plan edges-lookup] (add-flow plan (Lookup. [edges-index] connecteds-index #js [1] #js [0 3]))
-        [plan connecteds-lookup] (add-flow plan (Lookup. [connecteds-index] edges-index #js [0] #js [2 1]))
-        [plan new-connecteds] (add-flow plan (FilterMap. [edges edges-lookup connecteds-lookup] (fn [x] (->connected (fact-ix x 0) (fact-ix x 1)))))
-        plan (add-output plan new-connecteds :pretended)
-        state (flow-plan->flow-state plan)]
-    (apush* (aget (:node->facts state) 0) #js [(->edge 0 1) (->edge 1 2) (->edge 2 3) (->edge 3 1)])
-    (-> (fixpoint! state) :node->state (aget 1) persistent!))
-  )
-
 ;; IXES

 (defn ix-of [vector value]
@@ -344,6 +258,11 @@

 (defn ixes-of [vector values]
   (into-array (map #(ix-of vector %) values)))
+
+;; EXPRS
+
+(defn expr->fun [vars expr]
+  (apply js/Function (conj (vec vars) (str "return " expr ";"))))

 ;; PATTERNS

@@ -424,10 +343,123 @@
   ((pattern->deconstructor (->eg 'a 'a 'a)) (->eg "a" "a" "a"))
   )

-;; EXPRS
-
-(defn expr->fun [vars expr]
-  (apply js/Function (conj (vec vars) (str "return " expr ";"))))
+;; FUNLIKE
+
+(defrecord ShapeFun [shape])
+(defrecord ConstructorFun [vars pattern])
+(defrecord DeconstructorFun [pattern])
+(defrecord WhenFun [vars expr])
+(defrecord LetFun [vars expr])
+
+(defn funlike->fun [funlike]
+  (condp = (type funlike)
+    ShapeFun (let [{:keys [shape]} funlike]
+               (fn [x]
+                 (when (= shape (.-shape x))
+                   x)))
+    ConstructorFun (let [{:keys [vars pattern]} funlike]
+                     (pattern->constructor pattern vars))
+    DeconstructorFun (let [{:keys [pattern]} funlike]
+                       (pattern->deconstructor pattern))
+    WhenFun (let [{:keys [vars expr]} funlike
+                  when-fun (expr->fun vars expr)]
+              (fn [fact]
+                (when (.apply when-fun nil (.-values fact))
+                  fact)))
+    LetFun (let [{:keys [vars expr]} funlike
+                 let-fun (expr->fun vars expr)]
+             (fn [fact]
+               (let [values (.-values fact)
+                     new-value (.apply let-fun nil values)
+                     new-values (aclone values)]
+                 (apush new-values new-value)
+                 (Fact. nil new-values nil))))))
+
+;; FLOWS
+
+(defrecord Union [nodes])
+(defrecord FilterMap [nodes funlike])
+(defrecord Index [nodes key-ixes])
+(defrecord Lookup [nodes index-node key-ixes val-ixes])
+
+(defn flow->nodes [flow]
+  (:nodes flow))
+
+;; FLOW PLAN
+
+(defrecord FlowPlan [node->flow flow->node])
+
+(defn flow-plan->flow-state [{:keys [node->flow]}]
+  (let [node->state (into-array (for [_ node->flow] nil))
+        node->out-nodes (into-array (for [_ node->flow] #js []))
+        node->facts (into-array (for [_ node->flow] #js []))
+        node->update! (into-array (for [_ node->flow] nil))]
+    (dotimes [node (count node->flow)]
+      (let [flow (nth node->flow node)]
+        (aset node->state node
+              (condp = (type flow)
+                Union (transient #{})
+                FilterMap nil
+                Index (transient {})
+                Lookup nil))
+        (doseq [in-node (:nodes flow)]
+          (apush (aget node->out-nodes in-node) node))
+        (aset node->update! node
+              (condp = (type flow)
+                Union (union-update!)
+                FilterMap (filter-map-update! (funlike->fun (:funlike flow)))
+                Index (index-update! (:key-ixes flow))
+                Lookup (lookup-update! (:index-node flow) (:key-ixes flow) (:val-ixes flow))))))
+    (FlowState. node->state node->out-nodes node->facts node->update!)))
+
+(defn memory->node [memory]
+  (case memory
+    :known 0
+    :pretended 1
+    :remembered 2
+    :forgotten 3))
+
+(defn memory->nodes [memory]
+  (case memory
+    :known [0]
+    :pretended [1]
+    :remembered [2]
+    :forgotten [3]
+    :known&pretended [0 1]))
+
+(def empty-flow-plan
+  (FlowPlan. [(Union. #{}) (Union. #{}) (Union. #{}) (Union. #{})] {}))
+
+(defn add-output [flow-plan node memory]
+  (update-in flow-plan [:node->flow (memory->node memory) :nodes] conj node))
+
+(defn add-flow [{:keys [node->flow flow->node] :as flow-plan} flow]
+  (if-let [node (flow->node flow)]
+    [flow-plan node]
+    (let [node (count node->flow)
+          node->flow (conj node->flow flow)
+          flow->node (assoc flow->node flow node)]
+      [(FlowPlan. node->flow flow->node) node])))
+
+(comment
+  (deffact edge "[x] has an edge to [y]")
+  (deffact connected "[x] is connected to [y]")
+
+  (def known&pretended [0 1])
+
+  (let [plan empty-flow-plan
+        [plan edges] (add-flow plan (FilterMap. known&pretended (ShapeFun. edge)))
+        [plan connecteds] (add-flow plan (FilterMap. known&pretended (ShapeFun. connected)))
+        [plan edges-index] (add-flow plan (Index. [edges] #js [1]))
+        [plan connecteds-index] (add-flow plan (Index. [connecteds] #js [0]))
+        [plan edges-lookup] (add-flow plan (Lookup. [edges-index] connecteds-index #js [1] #js [0 3]))
+        [plan connecteds-lookup] (add-flow plan (Lookup. [connecteds-index] edges-index #js [0] #js [2 1]))
+        [plan new-connecteds] (add-flow plan (FilterMap. [edges edges-lookup connecteds-lookup] (ConstructorFun. '[x z] (->connected 'x 'z))))
+        plan (add-output plan new-connecteds :pretended)
+        state (flow-plan->flow-state plan)]
+    (apush* (aget (:node->facts state) 0) #js [(->edge 0 1) (->edge 1 2) (->edge 2 3) (->edge 3 1)])
+    (-> (fixpoint! state) :node->state (aget 1) persistent!))
+  )

 ;; CLAUSES

@@ -444,37 +476,23 @@
 (defn add-clause [plan nodes vars clause]
   (condp = (type clause)
     Recall (let [{:keys [memory pattern]} clause
-                 [plan node] (add-flow plan (FilterMap. (memory->nodes memory) (pattern->deconstructor pattern)))]
-             [plan [node] (pattern->vars pattern)])
+                 [plan node-a] (add-flow plan (FilterMap. (memory->nodes memory) (ShapeFun. (.-shape pattern))))
+                 [plan node-b] (add-flow plan (FilterMap. [node-a] (DeconstructorFun. pattern)))]
+             [plan [node-b] (pattern->vars pattern)])
     Compute (let [{:keys [pattern]} clause]
               (condp = (.-shape pattern)
                 Let (when (every? (set vars) (:vars pattern))
-                      (let [let-fun (expr->fun vars (:expr pattern))
-                            filter-map-fun (if (contains? (set vars) (:name pattern))
-                                             ;; filter
-                                             (let [name-ix (ix-of vars (:name pattern))]
-                                               (fn [fact]
-                                                 (let [new-value (.apply let-fun nil (.-values fact))]
-                                                   (when (= new-value (aget (.-values fact) name-ix))
-                                                     fact))))
-                                             ;; define
-                                             (fn [fact]
-                                               (let [new-value (.apply let-fun nil (.-values fact))
-                                                     new-values (aclone (.-values fact))]
-                                                 (apush new-values new-value)
-                                                 (Fact. nil new-values nil))))
-                            [plan node] (add-flow plan (->FilterMap nodes filter-map-fun))]
+                      (let [funlike (if (contains? (set vars) (:name pattern))
+                                      (WhenFun. vars (str "cljs.core.equals(" (:name pattern) "," (:expr pattern) ")"))
+                                      (LetFun. vars (:expr pattern)))
+                            [plan node] (add-flow plan (->FilterMap nodes funlike))]
                         [plan [node] (conj vars (:name pattern))]))
                 When (when (every? (set vars) (:vars pattern))
-                       (let [when-fun (expr->fun vars (:expr pattern))
-                             filter-map-fun (fn [fact]
-                                              (when (.apply when-fun nil (.-values fact))
-                                                fact))
-                             [plan node] (add-flow plan (->FilterMap nodes filter-map-fun))]
+                       (let [[plan node] (add-flow plan (->FilterMap nodes (WhenFun. vars (:expr pattern))))]
                          [plan [node] vars]))))
     Output (let [{:keys [memory pattern]} clause
                  _ (assert (every? (set vars) (pattern->vars pattern)))
-                 [plan output-node] (add-flow plan (FilterMap. nodes (pattern->constructor pattern vars)))
+                 [plan output-node] (add-flow plan (FilterMap. nodes (ConstructorFun. vars pattern)))
                  plan (add-output plan output-node memory)]
              [plan nodes vars])))


use keywords, not strings for 'models' map to allow easier use of threading macros

--- src/babel/directory.cljc
+++ src/babel/directory.cljc
@@ -10,12 +10,13 @@
    [dag_unify.core :refer [get-in]]))

 (def models
-  {"en"
+  {:en
    (let [model (babel.english.grammar/small)]
      (conj model
            {:generate-fn (fn [spec]
                            (en/generate spec :model model))}))
-   "la" babel.latin/model})
+   :la babel.latin/model})
+


(MAINT) changed locale-negotiator parens

did not need parens around it

--- src/clj/puppetlabs/services/ca/certificate_authority_core.clj
+++ src/clj/puppetlabs/services/ca/certificate_authority_core.clj
@@ -320,5 +320,5 @@
           authorization-fn
           whitelist-path
           (get-in ca-settings [:access-control :certificate-status]))
-        (i18n/locale-negotiator)
+        i18n/locale-negotiator
         (wrap-middleware puppet-version))))


PLD: send event when loading tab

PLD: send event when loading tab

--- src/hatti/views/dataview.cljs
+++ src/hatti/views/dataview.cljs
@@ -1,6 +1,7 @@
 (ns hatti.views.dataview
   (:require-macros [cljs.core.async.macros :refer [go]])
   (:require [chimera.js-interop :refer [format]]
+            [chimera.metrics :refer [send-event]]
             [chimera.om.state :refer [transact! merge-into-app-state!]]
             [cljs.core.async :refer [put!]]
             [om.core :as om :include-macros true]
@@ -186,9 +187,11 @@
            (om/build dataview-infobar
                      {:dataset-info (-> app-state :dataset-info)
                       :status (-> app-state :status)})]
-          (for [{:keys [component view]} dataviews]
-            [:div {:class (str "tab-page " (name view) "-page")
+          (for [{:keys [component view]} dataviews
+                :let [view-name (name view)]]
+            [:div {:class (str "tab-page " view-name "-page")
                    :style {:display (view->display view)}}
              (when (= selected view)
-               [:div.tab-content {:id (str "tab-content" (name view))}
+               (send-event :Dataview (str view-name "-page-load"))
+               [:div.tab-content {:id (str "tab-content" view-name)}
                 (om/build component app-state {:opts opts})])])])))))


Consolidating service into a single file


formatting

formatting

--- src/chat/server/db.clj
+++ src/chat/server/db.clj
@@ -660,30 +660,28 @@
                       :group/user [:user/id user-id]]]))

 (defn user-leave-group! [user-id group-id]
-  (let [unsub-txn (->>
-                    (d/q '[:find [?t ...]
-                           :in $ ?user-id ?group-id
-                           :where
-                           [?u :user/id ?user-id]
-                           [?g :group/id ?group-id]
-                           [?t :thread/group ?g]
-                           [?u :user/subscribed-thread ?t]]
-                         (d/db conn) user-id group-id)
-                    (map (fn [t]
-                           [:db/retract [:user/id user-id]
-                            :user/subscribed-thread t])))
-        unmention-txn (->>
-                        (d/q '[:find [?t ...]
-                               :in $ ?user-id ?group-id
-                               :where
-                               [?u :user/id ?user-id]
-                               [?g :group/id ?group-id]
-                               [?t :thread/group ?g]
-                               [?t :thread/mentioned ?u]]
-                             (d/db conn) user-id group-id)
-                        (map (fn [t]
-                               [:db/retract t
-                                :thread/mentioned [:user/id user-id]])))]
+  (let [unsub-txn (->> (d/q '[:find [?t ...]
+                              :in $ ?user-id ?group-id
+                              :where
+                              [?u :user/id ?user-id]
+                              [?g :group/id ?group-id]
+                              [?t :thread/group ?g]
+                              [?u :user/subscribed-thread ?t]]
+                            (d/db conn) user-id group-id)
+                       (map (fn [t]
+                              [:db/retract [:user/id user-id]
+                               :user/subscribed-thread t])))
+        unmention-txn (->> (d/q '[:find [?t ...]
+                                  :in $ ?user-id ?group-id
+                                  :where
+                                  [?u :user/id ?user-id]
+                                  [?g :group/id ?group-id]
+                                  [?t :thread/group ?g]
+                                  [?t :thread/mentioned ?u]]
+                                (d/db conn) user-id group-id)
+                           (map (fn [t]
+                                  [:db/retract t
+                                   :thread/mentioned [:user/id user-id]])))]
     @(d/transact conn (concat
                         [[:db/retract [:group/id group-id]
                           :group/user [:user/id user-id]]]


search skeletons

search skeletons

--- src/lex/dictionary.clj
+++ src/lex/dictionary.clj
@@ -21,5 +21,10 @@

 ;;; how to go from ID to entry

+(defn re-search
+  "Searches wordnet for all entries matching the regex."
+  [pattern])

-
+(defn search
+  "Searches wordnet for all entries that contain one of the supplied words as either a synonym or within it's gloss."
+  [& words])


Removing inprocess kixi.comms references

--- src/kixi/datastore/system.clj
+++ src/kixi/datastore/system.clj
@@ -18,8 +18,7 @@
             [kixi.comms :as comms]
             [kixi.comms.components
              [kinesis :as kinesis]
-             [coreasync :as coreasync]
-             [inprocess :as inprocess]]
+             [coreasync :as coreasync]]
             [kixi.datastore.metadatastore
              [inmemory :as md-inmemory]
              [dynamodb :as md-dd]]
@@ -76,8 +75,7 @@
                    :inmemory (segementation-inmemory/map->InMemory {}))
    :communications (case (first (keys (:communications config)))
                      :kinesis (kinesis/map->Kinesis {})
-                     :coreasync (coreasync/map->CoreAsync {})
-                     :inprocess (inprocess/map->InProcess {}))
+                     :coreasync (coreasync/map->CoreAsync {}))
                                         ;  :schema-extracter (se/map->SchemaExtracter {})
    :structural-validator (sv/map->StructuralValidator {})))


Rename some functions.

Rename some functions.

--- src/cavm/h2.clj
+++ src/cavm/h2.clj
@@ -947,7 +947,7 @@
 ; order is row -> order in output buffer.
 ; bin is the bin for the given set of samples.
 ; rows is ({:I 12 :bin 1 :off 1}, ... ), where all :bin are the same
-(defn- pick-samples-fn [[bin rows]]
+(defn- pick-rows-fn [[bin rows]]
   [bin (partial ashuffle-float
                 (map bin-mapping rows))])

@@ -956,9 +956,9 @@
 ; for each score bin in the request.
 ;
 ; rows ({:I 12 :bin 1 :off 1}, ... )
-(defn- pick-samples-fns [rows]
+(defn- pick-rows-fns [rows]
   (let [by-bin (group-by :bin rows)]
-    (apply hash-map (mapcat pick-samples-fn by-bin))))
+    (apply hash-map (mapcat pick-rows-fn by-bin))))

 ; Take map of bin copy fns, list of scores rows, and a map of output arrays,
 ; copying the scores to the output arrays via the bin copy fns.
@@ -1036,7 +1036,7 @@
                           (mapv merge-bin-off))

         bins (map :bin rows-to-copy)            ; list of bins to pull.
-        bfns (pick-samples-fns rows-to-copy)]   ; make fns that map from input bin to
+        bfns (pick-rows-fns rows-to-copy)]   ; make fns that map from input bin to
                                                 ; output buffer, one fn per input bin.

     (-> (select-scores-full dataset-id columns (distinct bins))


Fixed unit test.

Fixed unit test.

--- test/cmr/indexer/test/services/index_service.clj
+++ test/cmr/indexer/test/services/index_service.clj
@@ -13,6 +13,12 @@
         concept-id "C1234-PROV1"
         concept {:concept-id concept-id
                  :provider-id provider-id}
+        platforms [{:short-name "PLATFORM ONE"
+                    :long-name "dummy"
+                    :type "Dummy"}
+                   {:short-name "PLATFORM TWO"
+                    :long-name "dummy"
+                    :type "Dummy"}]
         projects [{:short-name "ESI"
                    :long-name "dummy"}
                   {:short-name "EVI"
@@ -28,6 +34,7 @@
                      :revision-date  nil
                      :temporal {:range-date-times [{:beginning-date-time (t/date-time 1996 2 24 22 20 41)
                                                     :ending-date-time (t/date-time 1997 3 25 23 23 43 123)}]}
+                     :platforms platforms
                      :projects projects
                      :two-d-coordinate-systems [{:name "FOO"}
                                                 {:name "Bar"}]
@@ -46,6 +53,8 @@
                   :revision-date  nil
                   :start-date "1996-02-24T22:20:41.000Z"
                   :end-date "1997-03-25T23:23:43.123Z"
+                  :platform-sn ["PLATFORM ONE" "PLATFORM TWO"]
+                  :platform-sn.lowercase ["platform one" "platform two"]
                   :project-sn ["ESI" "EVI" "EPI"]
                   :project-sn.lowercase ["esi" "evi" "epi"]
                   :archive-center ["SEDAC AC"]


Adding transfer-listener on aether/deploy

--- boot/aether/src/boot/aether.clj
+++ boot/aether/src/boot/aether.clj
@@ -276,6 +276,7 @@
        :coordinates  [project version]
        :jar-file     (io/file jarpath)
        :pom-file     (io/file pomfile)
+       :transfer-listener :stdout
        :artifact-map artifact-map
        :repository   {repo-id repo-settings}
        :local-repo   (or (:local-repo env) @local-repo nil)))))


clojure: complete rewrite of the recursive classification function

--- clojure/org/gavrog/clojure/pgraph_morphisms.clj
+++ clojure/org/gavrog/clojure/pgraph_morphisms.clj
@@ -50,17 +50,18 @@
         pos* (fn [v] (.minus (cover-node-position pos v) shift))]
     (map (comp sort (partial map pos*)) (shells net (cover-node net node)))))

-(defn classify [items2seqs]
-  (loop [done []
-         todo [[[] (seq items2seqs)]]]
-    (if (empty? todo)
-      done
-      (let [finished (fn [key group] (or (nil? (last key)) (= 1 (count group))))
-            refined (group-by first (for [[key group] todo, [item s] group]
-                                      [(conj key (first s)) [item (rest s)]]))
-            done (into done (for [[key group] refined
-                                  :when (finished key group)]
-                              [key (map (comp first second) group)]))
-            todo (for [[key group] refined :when (not (finished key group))]
-                   [key (map second group)])]
-        (recur done todo)))))
+(defn classify-once [items2seqs]
+  (for [[k c] (group-by first (for [[item s] items2seqs]
+                                [(first s) [item (rest s)]]))]
+    [k (map second c)]))
+
+(defn classify-recursively [items2seqs]
+  (loop [classes (sorted-set [(- (count items2seqs)) [] items2seqs])]
+    (let [[n k c] (first classes)]
+      (if (or (nil? n) (>= n -1))
+        (zipmap (map second classes) (map #(map first (last %)) classes))
+        (recur (into (disj classes (first classes))
+                     (for [[key cl] (classify-once c)]
+                       (if (nil? key)
+                         [0 k cl]
+                         [(- (count cl)) (conj k key) cl]))))))))


call all app init fns whether or not the DB is new

--- src/galleon.clj
+++ src/galleon.clj
@@ -33,10 +33,9 @@
         db-conn (d/connect datomic-uri)
         system {:db-conn db-conn
                 :config config-map}]
-    (when db-create-rval
-      (doseq [app applications]
-        (when (fn? (:init-fn! app))
-          ((:init-fn! app) system))))
+    (doseq [app applications]
+      (when (fn? (:init-fn! app))
+        ((:init-fn! app) system)))
     system))

 (defn start-system!


queue working

queue working

--- src/galleon.clj
+++ src/galleon.clj
@@ -67,11 +67,11 @@
   (dorun (map (fn start-queues!- [q]
                 (let [q (gw-util/queues q)]
                   (spit "/tmp/db1.txt" (str "waka: starting queue" (:name q)))
-                  (msg/start "queue.showevidence-in" #_(:name q))
+                  (msg/start (:name q))
                   (if (:worker q)
                     ;;(msg/listen (:name q) (:worker q))
                     ;;(msg/listen "queue.showevidence-in" (fn start-queues!-2 [msg] (spit "/tmp/dun.txt" (str msg))))
-                    (msg/listen "queue.showevidence-in" gw-worker/do-work)
+                    (msg/listen (:name q) (:worker q))
                     ;;(msg/listen "queue.showevidence-in" gw-worker/do-work)
                     )))
               queues)))


lein-release plugin: preparing 0.1.1 release

--- re-frame-simple/project.clj
+++ re-frame-simple/project.clj
@@ -1,4 +1,4 @@
-(defproject re-view/re-frame-simple "0.1.1-SNAPSHOT"
+(defproject re-view/re-frame-simple "0.1.1"

   :description "re-view syntax for re-frame"


Extract has-key function

Extract has-key function

--- src/hodgepodge/core.cljs
+++ src/hodgepodge/core.cljs
@@ -13,6 +13,12 @@

 (defn clear! [storage] (.clear storage))

+(defn has-key?
+  [storage key]
+  (let [ks (.keys js/Object storage)
+        idx  (.indexOf ks (serialize key))]
+    (>= idx 0)))
+
 (extend-type js/Storage
   ICounted
   (-count [s]
@@ -20,26 +26,21 @@

   ITransientAssociative
   (-assoc! [s key val]
-    (.setItem s
-              (serialize key)
-              (serialize val)))
+    (.setItem s (serialize key) (serialize val)))
+  ; TODO: contains-key? for transient associatives

   ITransientMap
   (-dissoc! [s key]
-    (.removeItem s
-                 (serialize key)))
+    (.removeItem s (serialize key)))

   ILookup
   (-lookup
     ([s key]
-       (some->
-        (.getItem s (serialize key))
-        deserialize))
+       (-lookup s key nil))
     ([s key not-found]
-       (if-let [i (.getItem s (serialize key))]
-         (deserialize i)
+       (if (has-key? s key)
+         (deserialize (.getItem s (serialize key)))
          not-found)))
-
 )

  (comment


Make this test more robust.

Make this test more robust.

It was failing occasionally with 39 entries in results after done? was
realized, which will only be delivered when results has 40 entries in
the future. The only thing I can figure is data visibility oddness
across the threads. This version should be less prone to that.

--- web/test-integration/immutant/web/integ_test.clj
+++ web/test-integration/immutant/web/integ_test.clj
@@ -186,22 +186,23 @@
          :on-open (fn [ch]
                     (let [query-string (:query-string (async/originating-request ch))]
                       (async/send! ch (last (re-find #"x=(.*)$" query-string))))))))
-  (let [results (atom [])
+  (let [messages (atom [])
         clients (atom [])
-        done? (promise)
+        results (promise)
         client-count 40]
     (dotimes [n client-count]
       (future
         (let [client (ws/connect (str (cdef-url "ws") "?x=" n)
                        :on-receive (fn [m]
-                                     (swap! results conj m)
-                                     (when (= client-count (count @results))
-                                       (deliver done? true))))]
+                                     (swap! messages conj m)
+                                     (when (= client-count (count @messages))
+                                       (deliver results @messages))))]
           (swap! clients conj client))))
-    (is (deref done? 5000 nil))
-    (println "RESULTS" @results)
-    (is (= (->> client-count (range 0) (map str) set)
-          (set @results)))
+    (let [results' (deref results 5000 nil)]
+      (is results')
+      (println "RESULTS" results')
+      (is (= (->> client-count (range 0) (map str) set)
+            (set results'))))
     (doseq [client @clients]
       (.close client))))


Added instructions on how to remove a page item

--- src/ui/relevance/display.cljs
+++ src/ui/relevance/display.cljs
@@ -265,6 +265,11 @@
                                    (take per-page)))]
     (fn []
       [:div {:class "row"}
+       [:p "If you wish to delete an item, hover the mouse over the listing. You'll see a "
+        [:i {:class    "fa fa-remove"
+             :style    {:color "red"}}]
+        " appear besides the last visit time. Click it to remove the row."
+        ]
        [:p "Total: " @total " URLs."]
        (when (< per-page @total)
          [Pagination
@@ -373,19 +378,6 @@
      [:a {:href "https://startpage.com" :target "_blank"} "StartPage"]
      ". After you run a search, it'll look at the results on your current page and re-prioritize the links shown to bring to the front those you have spent the longest reading."]
     [:p "Every search engine behaves differently, so if there's enough interest, I could extend this integration to others as well."]]
-   #_[:div
-      [:div {:class "col-sm-6"}
-       [:div {:class "col-sm-12"}
-        [:strong "Before"]]
-       [:div {:class "col-sm-12"}
-        [:img {:src "http://numergent.com/images/relevance/relevance-0.3-clojure chrome before.png"}]]
-       ]
-      [:div {:class "col-sm-6"}
-       [:div {:class "col-sm-12"}
-        [:strong "After"]]
-       [:div {:class "col-sm-12"}
-        [:img {:src "http://numergent.com/images/relevance/relevance-0.3-clojure chrome after.png"}]]
-       ]]
    ]
   )


Update fixtures with last schema changes.

--- src/uxbox/fixtures.clj
+++ src/uxbox/fixtures.clj
@@ -7,6 +7,8 @@
 (ns uxbox.fixtures
   "A initial fixtures."
   (:require [buddy.hashers :as hashers]
+            [buddy.core.codecs :as codecs]
+            [catacumba.serializers :as sz]
             [mount.core :as mount]
             [clj-uuid :as uuid]
             [suricatta.core :as sc]
@@ -20,6 +22,11 @@
 (defn- mk-uuid
   [prefix i]
   (uuid/v5 uuid/+namespace-oid+ (str prefix i)))
+
+(defn- data-encode
+  [data]
+  (-> (sz/encode data :transit+msgpack)
+      (codecs/bytes->base64)))

 (defn- create-user
   [conn i]
@@ -45,6 +52,7 @@
                      {:id (mk-uuid "page" i)
                       :user (mk-uuid "user" ui)
                       :project (mk-uuid "project" pi)
+                      :data (data-encode nil)
                       :name (str "page " i)
                       :width 1024
                       :height 768


Events reorganization on workspace.

Events reorganization on workspace.

--- src/uxbox/data/workspace.cljs
+++ src/uxbox/data/workspace.cljs
@@ -39,8 +39,22 @@
    :y [v/integer]})

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Events
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Events (explicit)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defn initialize
+  "Initialize the workspace state."
+  [projectid pageid]
+  (reify
+    rs/UpdateEvent
+    (-apply-update [_ state]
+      (let [s {:project projectid
+               :toolboxes #{:layers}
+               :flags #{}
+               :drawing nil
+               :selected #{}
+               :page pageid}]
+        (assoc state :workspace s)))))

 (defn toggle-tool
   "Toggle the enabled flag of the specified tool."
@@ -120,14 +134,6 @@
                         (map :id))]
         (assoc-in state [:workspace :selected] (into #{} shapes))))))

-(defn deselect-all
-  "Mark a shape selected for drawing in the canvas."
-  []
-  (reify
-    rs/UpdateEvent
-    (-apply-update [_ state]
-      (assoc-in state [:workspace :selected] #{}))))
-
 (defn add-shape
   "Mark a shape selected for drawing in the canvas."
   [shape props]
@@ -158,6 +164,76 @@
           (assoc-in $ [:pages-by-id pageid :shapes] shapes)
           (update-in $ [:shapes-by-id] dissoc sid))))))

+(defn move-shape
+  "Mark a shape selected for drawing in the canvas."
+  [sid [dx dy :as delta]]
+  (reify
+    rs/UpdateEvent
+    (-apply-update [_ state]
+      (let [shape (get-in state [:shapes-by-id sid])]
+        (update-in state [:shapes-by-id sid] shapes/-move {:dx dx :dy dy})))))
+
+(defn update-shape-rotation
+  [sid rotation]
+  {:pre [(number? rotation)
+         (>= rotation 0)
+         (>= 360 rotation)]}
+  (reify
+    rs/UpdateEvent
+    (-apply-update [_ state]
+      (update-in state [:shapes-by-id sid]
+                 shapes/-rotate rotation))))
+
+;; TODO: implement locked resize
+
+(defn update-shape-size
+  [sid {:keys [width height lock] :as opts}]
+  (sc/validate! +shape-update-size-schema+ opts)
+  (reify
+    rs/UpdateEvent
+    (-apply-update [_ state]
+      (let [shape (get-in state [:shapes-by-id sid])
+            size (select-keys shape [:width :height])
+            size (merge size
+                        (when width {:width width})
+                        (when height {:height height}))]
+        (update-in state [:shapes-by-id sid]
+                   shapes/-resize size)))))
+
+(defn update-shape-position
+  [sid {:keys [x y] :as opts}]
+  (sc/validate! +shape-update-position-schema+ opts)
+  (reify
+    rs/UpdateEvent
+    (-apply-update [_ state]
+      (update-in state [:shapes-by-id sid]
+                 merge
+                 (when x {:x x})
+                 (when y {:y y})))))
+
+(defn update-shape-fill
+  [sid {:keys [fill opacity] :as opts}]
+  (sc/validate! +shape-update-fill-schema+ opts)
+  (reify
+    rs/UpdateEvent
+    (-apply-update [_ state]
+      (update-in state [:shapes-by-id sid]
+                 merge
+                 (when fill {:fill fill})
+                 (when opacity {:opacity opacity})))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Events (for selected)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defn deselect-all
+  "Mark a shape selected for drawing in the canvas."
+  []
+  (reify
+    rs/UpdateEvent
+    (-apply-update [_ state]
+      (assoc-in state [:workspace :selected] #{}))))
+
 (defn remove-selected
   "Deselect all and remove all selected shapes."
   []
@@ -167,29 +243,6 @@
       (let [selected (get-in state [:workspace :selected])]
         (rx/from-coll
          (into [(deselect-all)] (map #(delete-shape %) selected)))))))
-
-(defn initialize
-  "Initialize the workspace state."
-  [projectid pageid]
-  (reify
-    rs/UpdateEvent
-    (-apply-update [_ state]
-      (let [s {:project projectid
-               :toolboxes #{}
-               :flags #{}
-               :drawing nil
-               :selected #{}
-               :page pageid}]
-        (assoc state :workspace s)))))
-
-(defn move-shape
-  "Mark a shape selected for drawing in the canvas."
-  [sid [dx dy :as delta]]
-  (reify
-    rs/UpdateEvent
-    (-apply-update [_ state]
-      (let [shape (get-in state [:shapes-by-id sid])]
-        (update-in state [:shapes-by-id sid] shapes/-move {:dx dx :dy dy})))))

 (defn move-selected
   "Move a minimal position unit the selected shapes."
@@ -207,55 +260,6 @@
         (rx/from-coll
          (map #(move-shape % delta) selected))))))

-(defn update-shape-rotation
-  [sid rotation]
-  {:pre [(number? rotation)
-         (>= rotation 0)
-         (>= 360 rotation)]}
-  (reify
-    rs/UpdateEvent
-    (-apply-update [_ state]
-      (update-in state [:shapes-by-id sid]
-                 shapes/-rotate rotation))))
-
-;; TODO: implement locked resize
-
-(defn update-shape-size
-  [sid {:keys [width height lock] :as opts}]
-  (sc/validate! +shape-update-size-schema+ opts)
-  (reify
-    rs/UpdateEvent
-    (-apply-update [_ state]
-      (let [shape (get-in state [:shapes-by-id sid])
-            size (select-keys shape [:width :height])
-            size (merge size
-                        (when width {:width width})
-                        (when height {:height height}))]
-        (update-in state [:shapes-by-id sid]
-                   shapes/-resize size)))))
-
-(defn update-shape-position
-  [sid {:keys [x y] :as opts}]
-  (sc/validate! +shape-update-position-schema+ opts)
-  (reify
-    rs/UpdateEvent
-    (-apply-update [_ state]
-      (update-in state [:shapes-by-id sid]
-                 merge
-                 (when x {:x x})
-                 (when y {:y y})))))
-
-(defn update-shape-fill
-  [sid {:keys [fill opacity] :as opts}]
-  (sc/validate! +shape-update-fill-schema+ opts)
-  (reify
-    rs/UpdateEvent
-    (-apply-update [_ state]
-      (update-in state [:shapes-by-id sid]
-                 merge
-                 (when fill {:fill fill})
-                 (when opacity {:opacity opacity})))))
-
 (defn update-selected-shapes-fill
   "Update the fill related attributed on
   selected shapes."


Eliminate minor reflection warning.

Eliminate minor reflection warning.

--- src/blocks/data.clj
+++ src/blocks/data.clj
@@ -186,6 +186,7 @@
 (defn- collect-bytes
   "Collects bytes from a data source into a `PersistentBytes` object. If the
   source is already persistent, it will be reused directly."
+  ^PersistentBytes
   [source]
   (if (instance? PersistentBytes source)
     source


Change delete to vote

Change delete to vote

--- cljs-src/lunch_finder/core.cljs
+++ cljs-src/lunch_finder/core.cljs
@@ -9,35 +9,40 @@
 (def app-state (atom {:restaurants [{:name "Q-Shack" :votes 0}
                                     {:name "Thai Cafe" :votes 0}]}))

+(defn vote-for-restaurant [restaurants vote]
+  (vec (map #(if (= % vote)
+             (update-in % [:votes] inc)
+             %) restaurants)))
+
 (defn restaurant-view [restaurant owner]
   (reify
     om/IRenderState
-    (render-state [this {:keys [delete]}]
+    (render-state [this {:keys [vote]}]
       (dom/span nil
                (dom/dt nil (:name restaurant))
                (dom/dd nil (str "Votes: " (:votes restaurant)))
-               (dom/button #js {:onClick (fn [e] (put! delete @restaurant))} "Delete")))))
+               (dom/button #js {:onClick (fn [e] (put! vote @restaurant))} "Vote")))))

 (defn restaurants-view [app owner]
   (reify
     om/IInitState
     (init-state [_]
-      {:delete (chan)})
+      {:vote (chan)})
     om/IWillMount
     (will-mount [_]
-      (let [delete (om/get-state owner :delete)]
+      (let [vote (om/get-state owner :vote)]
         (go (loop []
-              (let [restaurant (<! delete)]
+              (let [restaurant (<! vote)]
                 (om/transact! app :restaurants
-                              (fn [xs] (vec (remove #(= restaurant %) xs))))
+                              (fn [xs] (vote-for-restaurant xs restaurant)))
                 (recur))))))
     om/IRenderState
-    (render-state [this {:keys [delete]}]
+    (render-state [this {:keys [vote]}]
       (dom/div nil
                (dom/h2 nil "Restaurants")
                (apply dom/dl #js{:className "restaurants"}
                       (om/build-all restaurant-view (:restaurants app)
-                                    {:init-state {:delete delete}}))))))
+                                    {:init-state {:vote vote}}))))))

 (om/root
  restaurants-view


Add pprint import for fix-json.

Add pprint import for fix-json.

--- src/cavm/cgdata.clj
+++ src/cavm/cgdata.clj
@@ -4,6 +4,7 @@
   (:require [clojure.java.io :as io])
   (:require [clojure-csv.core :as csv])
   (:require [me.raynes.fs :as fs])
+  (:require clojure.pprint)
   (:gen-class))

 ;


Update help to print a nicer version of alias definitions.

--- src/cli4clj/cli.clj
+++ src/cli4clj/cli.clj
@@ -98,17 +98,17 @@
 (defn create-cli-help-fn
   [options]
   (let [cmds (:cmds options)
+        cmd-aliases (get-cmd-aliases cmds)
         command-names (sort (keys cmds))
         cmd-entry-delimiter (:help-cmd-entry-delimiter options)]
     (fn []
       (doseq [c command-names]
-        (if (map? (cmds c))
-          (do
-            (println (str (name c) "\t" (get-in cmds [c :short-info])))
-            (when-let [li (get-in cmds [c :long-info])]
-              (println (str "\t" li)))
-            (print cmd-entry-delimiter))
-          (println (str (name c) "\tSee: " (name (cmds c)) cmd-entry-delimiter)))))))
+        (when (map? (cmds c))
+          (println (str (name c) "\t" (vec (map name (c cmd-aliases))) "\n"
+                        "\t" (get-in cmds [c :short-info])))
+          (when-let [li (get-in cmds [c :long-info])]
+            (println (str "\t" li)))
+          (print cmd-entry-delimiter))))))

 (def cli-mandatory-default-options
   {:cmds {:exit {:fn (fn [] (System/exit 0))


fix score counting issue

fix score counting issue

--- src/cljs/turns.cljs
+++ src/cljs/turns.cljs
@@ -78,7 +78,6 @@
   []
   (when @timer
     (js/clearInterval @timer))
-  (reset! points 0)
   (reset! timer (js/setInterval next-turn (/ 1000 @block-speed))))

 (defn key-pressed


add partial match assertions and tidy up old code

--- src/crison/core.clj
+++ src/crison/core.clj
@@ -46,10 +46,6 @@
          s-file (str *output-dir* "/" (date) "_" "-source" nm ".txt")]
       (when name (spit s-file (wc/page-source @driver)))))
   ([] (source nil)))
-
-(defn title [] (wc/title @driver))
-
-(defn title? [x] (is (= x (title)) x))

 (defn go [x] (wc/to @driver x))

@@ -110,7 +106,12 @@
   (render-pause (or pause def-pause))
   (screenshot (:screenshot x)))

-(defmethod decode :title [x] (title? (:title x)))
+(defmethod decode :match [{:keys [match text]}]
+  (let [el (if (string? match)
+             (-> @driver (wc/find-element {:id match}))
+             (-> @driver (wc/find-element match)))
+        textval (wc/text el)]
+    (is (= true (.contains textval text)) (str "Fail on match for element : " match ", substring : " text))))

 (defmethod decode :default [x] (? x))


build out plan b search for less well structured markup

--- src/crison/main.clj
+++ src/crison/main.clj
@@ -37,7 +37,15 @@
       (-> driver (wc/find-element e) wc/click))
     (Thread/sleep 2000)))

-(defmethod decode :search! [x] (wf/quick-fill-submit driver (:search! x)) (Thread/sleep 2000))
+(defmethod decode :bsearch! [x]
+  (let [input (first (:bsearch! x))
+        v (:text! input)
+        srch (dissoc input :text!)]
+        (-> driver (wc/find-element srch) (wc/input-text v))
+        (-> driver (wc/find-element (last (:bsearch! x))) wc/click)))
+
+(defmethod decode :search! [x]
+  (wf/quick-fill-submit driver (:search! x)) (Thread/sleep 2000))

 (defmethod decode :title [x] (title? (:title x)))


Use commons.utils/direct-buffer and slice-buffer.

--- src/clojure/uncomplicate/neanderthal/internal/host/buffer_block.clj
+++ src/clojure/uncomplicate/neanderthal/internal/host/buffer_block.clj
@@ -7,8 +7,9 @@
 ;;   You must not remove this notice, or any other, from this software.

 (ns uncomplicate.neanderthal.internal.host.buffer-block
-  (:require [uncomplicate.commons.core
-             :refer [Releaseable release let-release double-fn wrap-float wrap-double wrap-int wrap-long]]
+  (:require [uncomplicate.commons
+             [core :refer [Releaseable release let-release double-fn wrap-float wrap-double wrap-int wrap-long]]
+             [utils :refer [direct-buffer slice-buffer]]]
             [uncomplicate.fluokitten.protocols
              :refer [PseudoFunctor Functor Foldable Magma Monoid Applicative fold]]
             [uncomplicate.neanderthal
@@ -23,7 +24,7 @@
              [printing :refer [print-vector print-ge print-uplo print-banded print-diagonal]]
              [navigation :refer :all]]
             [uncomplicate.neanderthal.internal.host.fluokitten :refer :all])
-  (:import [java.nio ByteBuffer DirectByteBuffer ByteOrder]
+  (:import [java.nio ByteBuffer DirectByteBuffer]
            [clojure.lang Seqable IFn IFn$DD IFn$DDD IFn$DDDD IFn$DDDDD IFn$LD IFn$LLD IFn$L IFn$LL
             IFn$LDD IFn$LLDD IFn$LLL]
            [uncomplicate.neanderthal.internal.api BufferAccessor RealBufferAccessor IntegerBufferAccessor
@@ -37,21 +38,6 @@
   (double (clojure.lang.Util/hashCombine h (Double/hashCode x))))

 (def ^:private f* (double-fn *))
-
-(defn ^:private direct-buffer [^long size]
-  (let [buff (ByteBuffer/allocateDirect size)]
-    (.order ^ByteBuffer buff (ByteOrder/nativeOrder))
-    buff))
-
-(defn ^:private slice-buffer [^ByteBuffer buf ^long ofst ^long len]
-  (when buf
-    (let [ord (.order buf)
-          res (.duplicate buf)]
-      (.position res ofst)
-      (.limit res (+ ofst len))
-      (.slice res)
-      (.order res)
-      res)))

 ;; ================== Declarations ============================================


fix typo in last commit

fix typo in last commit


Worked towards fixing dsets.clj

Worked towards fixing dsets.clj

--- clojure/org/gavrog/clojure/dsets.clj
+++ clojure/org/gavrog/clojure/dsets.clj
@@ -6,14 +6,13 @@
 (defn dsets [dim max-size]
   (let [idcs (range (inc dim))
         still-good? (fn [ds i D]
-                      (empty? (for [j idcs
-                                    :when (or (< j (dec i)) (> j (inc i)))
-                                    :let [o (orbit ds [i j] D)]
-                                    :when (> (size o) (if (loopless? o) 4 2))]
-                                j)))]
+                      (not-any? #(> (size %) (if (loopless? %) 4 2))
+                        (for [j idcs :when (or (< j (dec i)) (> j (inc i)))]
+                          (orbit ds [i j] D))))]
     (make-backtracker
       {:root [(dsymbol (str "1 " dim))
               (into (sorted-set) (for [i idcs] [i 1]))]
+       ;; TODO our generation procedure is incompatible with (canonical?)
        :extract (fn [[ds free]] (when (and (empty? free) (canonical? ds)) ds))
        :children (fn [[ds free]]
                    (when (seq free)


152 add superpos

152 add superpos

--- stuf/src/sandbox/4clojure.clj
+++ stuf/src/sandbox/4clojure.clj
@@ -1315,3 +1315,8 @@
       (subv (concat [space] v)
             lenmax
             (conj res (concat v (take lenrest (repeat space))))))))
+
+(defn superpos [[fst & rst]]
+  (if-not (seq rst)
+    (map list fst)
+    (for [x fst y (superpos rst)] (conj y x))))


Update quil version in docsite tool.

Update quil version in docsite tool.

--- dev-resources/utils/docsite.clj
+++ dev-resources/utils/docsite.clj
@@ -193,7 +193,7 @@
           (column->html [column]
             [:div.column (map (comp category->html find-category) column)])]
     [:div.wrapper
-     [:h1#title "Quil 2.2.0 API"]
+     [:h1#title "Quil 2.2.1 API"]
      [:div#description
       [:p "Quil is a clojure animation library for creating interactive sketches. "]
       [:p


String of doc

String of doc

--- src/exploud/web.clj
+++ src/exploud/web.clj
@@ -86,17 +86,22 @@
     v))

 (def locked?
+  "Atom holding a boolean indicating whether Exploud is locked for actions with side-effects."
   (atom false))

 (defn- lock!
+  "Lock Exploud, preventing deployments etc."
   []
   (reset! locked? true))

 (defn- unlock!
+  "Unlock Exploud, allowing deployment etc."
   []
   (reset! locked? false))

-(defmacro guarded [& body]
+(defmacro guarded
+  "Replace the given body with a Conflict response if Exploud has been locked."
+  [& body]
   `(if @locked?
      (response "Exploud is currently closed for business." "text/plain" 409)
      (do ~@body)))


use the same utils require format as the other nses

--- frontend/controllers/ws.cljs
+++ frontend/controllers/ws.cljs
@@ -8,9 +8,8 @@
             [frontend.pusher :as pusher]
             [frontend.utils.seq :refer [find-index]]
             [frontend.state :as state]
-            [frontend.utils :as utils :refer [mlog]])
-  (:require-macros [frontend.utils :refer [inspect]]
-                   [frontend.controllers.ws :refer [with-swallow-ignored-build-channels]]))
+            [frontend.utils :as utils :include-macros true])
+  (:require-macros [frontend.controllers.ws :refer [with-swallow-ignored-build-channels]]))

 ;; To subscribe to a channel, put a subscribe message in the websocket channel
 ;; with the channel name and the messages you want to listen to. That will be
@@ -61,12 +60,12 @@

 (defmethod ws-event :default
   [pusher-imp message args state]
-  (mlog "Unknown ws event: " (pr-str message))
+  (utils/mlog "Unknown ws event: " (pr-str message))
   state)

 (defmethod post-ws-event! :default
   [pusher-imp message args previous-state current-state]
-  (mlog "No post-ws for: " message))
+  (utils/mlog "No post-ws for: " message))

 (defmethod ws-event :build/update
   [pusher-imp message {:keys [data channel-name]} state]
@@ -109,7 +108,7 @@
               (let [container-index (aget data "index")
                     action-index (aget data "step")]
                 (if (not= container-index (get-in state state/current-container-path 0))
-                  (do (mlog "Ignoring output for inactive container: " container-index)
+                  (do (utils/mlog "Ignoring output for inactive container: " container-index)
                       (-> state
                           (build-model/fill-containers container-index action-index)
                           (update-in (state/action-path container-index action-index) assoc :missing-pusher-output true :has_output true)))
@@ -137,7 +136,7 @@
 (defmethod post-ws-event! :subscribe
   [pusher-imp message {:keys [channel-name messages context]} previous-state current-state]
   (let [ws-ch (get-in current-state [:comms :ws])]
-    (mlog "subscribing to " channel-name)
+    (utils/mlog "subscribing to " channel-name)
     (pusher/subscribe pusher-imp channel-name ws-ch :messages messages :context context)))

@@ -149,7 +148,7 @@
   [pusher-imp message _ previous-state current-state]
   (doseq [channel-name (clojure.set/difference (pusher/subscribed-channels pusher-imp)
                                                (fresh-channels current-state))]
-    (mlog "unsubscribing from " channel-name)
+    (utils/mlog "unsubscribing from " channel-name)
     (pusher/unsubscribe pusher-imp channel-name)))

 (defmethod post-ws-event! :refresh


Track first taker actx per ch.

Track first taker actx per ch.

--- src/cbfg/core.cljs
+++ src/cbfg/core.cljs
@@ -43,7 +43,7 @@
 (defn vis-add-ch [vis ch]
   (update-in vis [:chs ch]
              (fn [v] (if (nil? v)
-                       {:id ((:gen-id vis)) :msgs {}}
+                       {:id ((:gen-id vis)) :msgs {} :first-taker-actx nil}
                        v))))

 (def vis-event-handlers
@@ -69,7 +69,10 @@
            (let [[ch] args]
              (swap! vis #(-> %
                              (assoc-in [:actxs actx :wait-chs ch] :take)
-                             (vis-add-ch ch)))))
+                             (vis-add-ch ch)
+                             (update-in [:chs ch :first-taker-actx]
+                                        (fn [fta]
+                                          (if fta fta actx)))))))
     :end (fn [vis actx args]
            (let [[ch msg] args]
              (swap! vis #(-> %
@@ -154,7 +157,8 @@
         vis (atom {:actxs {} ; {actx -> {:children {child-actx -> true},
                              ;           :wait-chs {ch -> (:take|:put)}}}.
                    :chs {}   ; {ch -> {:id (gen-id),
-                             ;         :msgs {msg -> true}}}.
+                             ;         :msgs {msg -> true}
+                             ;         :first-taker-actx actx-or-nil}}.
                    :gen-id gen-id})]
     (go-loop [num-events 0]
       (let [tdv @event-delay]


Started a top world for the sim.

Started a top world for the sim.

--- src/cbfg/core.cljs
+++ src/cbfg/core.cljs
@@ -2,7 +2,8 @@
 ;; generic stuff should go elsewhere.

 (ns cbfg.core
-  (:require-macros [cljs.core.async.macros :refer [go]])
+  (:require-macros [cljs.core.async.macros :refer [go]]
+                   [cbfg.ago :refer [ago]])
   (:require [clojure.string :as string]
             [cljs.core.async :refer [<! put! chan]]
             [goog.dom :as dom]
@@ -23,11 +24,12 @@
     out))

 (let [clicks (listen (dom/getElement "go") "click")]
-  (go (while true
-        (<! clicks)
-        (set! (.-innerHTML (dom/getElement "output"))
-              (user-input))
-        (println (string/join "\n" (<! (cbfg.fence/test)))))))
+  (ago world nil
+       (while true
+         (<! clicks)
+         (set! (.-innerHTML (dom/getElement "output"))
+               (user-input))
+         (println (string/join "\n" (atake world (cbfg.fence/test)))))))

 ;; ------------------------------------------------


More efficient sort.

More efficient sort.

--- src/cbfg/core.cljs
+++ src/cbfg/core.cljs
@@ -147,7 +147,7 @@
   (let [actx-id (last actx)
         actx-info (get-in vis [:actxs actx])]
     (assign-position positions actx-id override)
-    (doseq [[ch ch-info] (sort-by #(:id (second %)) (get actx-ch-ch-infos actx))]
+    (doseq [ch-info (sort-by :id (vals (get actx-ch-ch-infos actx)))]
       (assign-position positions (:id ch-info) override))
     (doseq [child-actx (sort #(compare (last %1) (last %2))
                              (keys (:children actx-info)))]
@@ -187,11 +187,10 @@
      actx-id
      "
" (vis-html-loop-state vis (:loop-state actx-info)) "
"
      "

"
-     (mapv (fn [ch-ch-info]
-             (let [ch-info (second ch-ch-info)
-                   ch-id (:id ch-info)]
+     (mapv (fn [ch-info]
+             (let [ch-id (:id ch-info)]
                ["
" ch-id ": " (:msgs ch-info) "
"]))
-           (sort-by #(:id (second %)) (get actx-ch-ch-infos actx)))
+           (sort-by :id (vals (get actx-ch-ch-infos actx))))
      "

"
      (when (not (:closed actx-info))
        ["
" (mapv (fn [child-actx]


Simplify arb->* methods

Simplify arb->* methods

--- src/datemo/arb.clj
+++ src/datemo/arb.clj
@@ -10,6 +10,28 @@

 (defn get-in-metadata [k metadata]
   (k (first (filter #(k %) metadata))))
+
+(defn walk-arb-fn [wrap-node process-node]
+  (fn walk [arb]
+    (let [[_ metadata & nodes] arb]
+      (wrap-node
+       metadata
+       (apply vector (for [node nodes]
+                       (if (or (string? node) (nil? node))
+                         (process-node node)
+                         (walk node))))))))
+
+(defn arb->tx [arb]
+  (let [process-node #(hash-map :content/text %)
+        wrap-node #(hash-map
+                    :arb/metadata [{:metadata/html-tag (:original-tag %1)}]
+                    :arb/value %2)
+        convert (walk-arb-fn wrap-node process-node)]
+    (convert arb)))
+
+(defn html->tx [html & metadata]
+  (let [tx (-> html (html->arb) (arb->tx))]
+    (assoc tx :arb/metadata (into (:arb/metadata tx) metadata))))

 (defn html->hiccup
   ([html] (as-hiccup (parse html)))
@@ -39,26 +61,11 @@
     (hiccup->arb (html->hiccup html)))
     (hiccup->arb (html->hiccup html as-fragment))))

-(defn arb->tx [arb]
-  (let [[arb-tag metadata & value] arb]
-    (if (and
-          (= 1 (count value))
-          (or (string? (first value)) (nil? (first value))))
-      {:arb/metadata [{:metadata/html-tag (metadata :original-tag)}]
-       :arb/value [{:content/text (first value)}]}
-      (loop [values []
-             items value]
-        (def new-val (if (string? (first items))
-                       {:content/text (first items)}
-                       (arb->tx (first items))))
-        (if (= 1 (count items))
-          {:arb/metadata [{:metadata/html-tag (metadata :original-tag)}]
-           :arb/value (conj values new-val)}
-          (recur (conj values new-val) (next items)))))))
-
-(defn html->tx [html & metadata]
-  (let [tx (-> html (html->arb) (arb->tx))]
-    (assoc tx :arb/metadata (into (:arb/metadata tx) metadata))))
+(defn arb->hiccup [arb]
+  (let [proccess-node #(identity %)
+        wrap-node #(vec (concat [(:original-tag %1) {}] %2))
+        convert (walk-arb-fn wrap-node proccess-node)]
+    (convert arb)))

 (defn tx->arb [tx]
   (let [{metadata :arb/metadata value :arb/value} tx]
@@ -76,18 +83,5 @@
                          (:content/text (first items)) ;; If it's not an arb it must be a :content/text
                          (tx->arb (first items)))) (next items)))))))

-(defn arb->hiccup [arb]
-  (let [[arb-tag metadata & value] arb]
-    (if (and (string? (first value)) (= 1 (count value)))
-      [(:original-tag metadata) {} (first value)]
-      (loop [hiccups [], items value]
-        (if (= 0 (count items))
-          (into [(:original-tag metadata) {}] hiccups)
-          (if (string? (first items))
-            (recur (conj hiccups (first items)) (next items))
-            (recur
-              (conj hiccups (arb->hiccup (first items)))
-              (next items))))))))
-
 (defn tx->html [tx]
   (-> tx (tx->arb) (arb->hiccup) (html)))


GUI: Help->About cleaned up

GUI: Help->About cleaned up

--- src/gui/frames.clj
+++ src/gui/frames.clj
@@ -90,16 +90,10 @@
 Licensed under Eclipse Public License 1.0

 (http://www.eclipse.org/legal/epl-v10.html)

-This program uses much code and many ideas of the

-MNI Propopsition Analyzer (MNI)

-(homepages.thm.de/~hg11260/mpa.html)

-

 Written in Clojure (clojure.org)

 Libraries used:

-Instaparse (github.com/Engelberg/instaparse)

 SAT4J (sat4j.org)

-Kern (github.com/blancas/kern)

 Seesaw (github.com/daveray/seesaw)
 "
 ))]


Add `Explorable` protocol to allow interrogation of `Story` obj.

--- src/isla/story.clj
+++ src/isla/story.clj
@@ -8,11 +8,28 @@

 (declare types name-into-objs extract-by-class get-story-ctx)

+(defprotocol Explorable
+  (get-current-room [this])
+  (get-all-items [this])
+  (get-item [this name]))
+
 (defprotocol Playable
   (move [this direction])
   (look [this & object]))

 (defrecord Story [player rooms]
+  Explorable
+  (get-current-room [this]
+    (first (filter (fn [x] (= (:order x) (:current-room player))) rooms)))
+  (get-all-items [this]
+    (concat (map (fn [x] (:items x)) rooms)))
+  (get-item [this name]
+    (if-let [item (first (filter (fn [y] (= name (:name y))) (get-all-items this)))]
+      item ;; item getter untested because didn't have items when wrote it
+      (if (> (.indexOf ["myself" "me"] name) -1)
+        player
+        nil)))
+
   Playable
   (move [this direction]
     (println "move!"))


or-assoc fix

or-assoc fix

--- src/latte/prop.clj
+++ src/latte/prop.clj
@@ -422,7 +422,7 @@
    (if (clojure.core/and (seq? t)
                          (= (count t) 3)
                          (= (first t) #'latte.prop/or))
-     [:ok (second t) (nth t 2)]
+     [(second t) (nth t 2)]
      (match t
        (['Π [C ✳] (['Π [_ (['Π [_ A] C1] :seq)] (['Π [_ (['Π [_ B] C2] :seq)] C3] :seq)] :seq)] :seq)
        (if (= C C1 C2 C3)
@@ -448,9 +448,8 @@

 This is (for now) the easiest rule to use for proof-by-cases."
   [def-env ctx [or-term or-type] [prop prop-type] [left-proof left-type] [right-proof right-type]]
-  ;; (let [[A B] (decompose-or-type def-env ctx ty)]
-  ;; [[[[(list #'or-elim A B) or-term] prop] left-proof] right-proof])))
-  [[[[(list #'or-elim% left-type right-type) or-term] prop] left-proof] right-proof])
+  (let [[A B] (decompose-or-type def-env ctx or-type)]
+    [[[[(list #'or-elim% A B) or-term] prop] left-proof] right-proof]))

 (defthm or-not-elim-left
   "An elimination rule for disjunction, simpler than [[or-elim]].
@@ -544,13 +543,11 @@
       (assume [H3 A]
         (have <a> (or A (or B C))
               :by (or-intro-left H3 (or B C))))
-      [:print-type '<a>]
       (assume [H4 B]
         (have <b1> (or B C)
               :by (or-intro-left H4 C))
         (have <b> (or A (or B C))
               :by (or-intro-right A <b1>)))
-      [:print-type '<b>]
       (have <c> _
             :by (or-elim H2 (or A (or B C))
                          <a> <b>)))
@@ -561,9 +558,7 @@
             :by (or-intro-right A <d1>)))
     (have <e> _ :by (or-elim H1 (or A (or B C))
                              <c> <d>)))
-
-  )
-  ;;(qed <e>))
+  (qed <e>))

 (defthm or-assoc-conv
   [[A :type] [B :type] [C :type]]


Reverse specificity-sort

Reverse specificity-sort

--- src/lt/object.cljs
+++ src/lt/object.cljs
@@ -45,9 +45,9 @@
 (defn specificity-sort [xs]
   (let [arr #js []]
     (doseq [x xs]
-      (.push arr #js [(count (string/split (name x) ".")) (name x) x]))
+      (.push arr #js [(count (string/split (str x) ".")) (str x) x]))
     (.sort arr)
-    (amap arr i _ (aget arr i 2))))
+    (amap arr i _ (aget arr (- (.-length arr) i 1) 2))))

 (defn tags->behaviors [ts]
   (let [duped (apply concat (map @tags (specificity-sort ts)))


don't rethrow

don't rethrow

Signed-off-by: Chris Granger <5654cde260ae99bc4d30054171b8bcd902efd19a@gmail.com>

--- src/lt/object.cljs
+++ src/lt/object.cljs
@@ -158,11 +158,11 @@
         (raise obj :object.behavior.time r time)))
       (catch js/Error e
         (.error js/console (str "Invalid behavior: " (-> (->behavior r) :name)))
-        (throw e)
+        (.error js/console (str e "\n" (.-stack e)))
         )
       (catch js/global.Error e
         (.error js/console (str "Invalid behavior: " (-> (->behavior r) :name)))
-        (throw e)
+        (.error js/console (str e "\n" (.-stack e)))
         ))))

 (defn raise [obj k & args]


Add dam number to archived production view

Fixes #40

--- src/mdr2/views.clj
+++ src/mdr2/views.clj
@@ -192,13 +192,14 @@
      identity
      [:h1 (format "Archived Productions %s" date-str)]
      [:table#productions.table.table-striped
-      [:thead [:tr [:th "Title"] [:th "Author"] [:th "Product Number"] [:th "Library Number"] [:th "Total time"] [:th "Number of CDs"] [:th "Depth"] [:th "Narrator"] [:th "Date of Production"] [:th "Libary signature"]]]
+      [:thead [:tr [:th "DAM"] [:th "Title"] [:th "Author"] [:th "Product Number"] [:th "Library Number"] [:th "Total time"] [:th "Number of CDs"] [:th "Depth"] [:th "Narrator"] [:th "Date of Production"] [:th "Libary signature"]]]
       [:tbody
        (for [{:keys [id title creator product_number
                      library_number library_signature
                      total_time volumes depth narrator produced_date]}
              productions]
          [:tr
+          [:td id]
           [:td (link-to (str "/production/" id) title)]
           [:td creator]
           [:td product_number]


Fixed namespace for clouseau.test-server

--- test/clouseau/test_server.clj
+++ test/clouseau/test_server.clj
@@ -36,7 +36,7 @@
 ;;; exception statement from your version.
 ;;;

-(ns clouseau.test-core
+(ns clouseau.test-server
   (:require [clojure.test :refer :all]
             [clouseau.server :refer :all]))


New tests: test-process-add-new-group-page-existence, test-process-edit-chapter-page-existence, test-process-edit-product-page-existence, and test-process-chapter-page-existence

--- test/hurvinek/server_test.clj
+++ test/hurvinek/server_test.clj
@@ -99,3 +99,27 @@
         (is (callable? 'hurvinek.server/process-add-new-chapter-page))))

+(deftest test-process-add-new-group-page-existence
+    "Check that the hurvinek.server/process-add-new-group-page definition exists."
+    (testing "if the hurvinek.server/process-add-new-group-page definition exists."
+        (is (callable? 'hurvinek.server/process-add-new-group-page))))
+
+
+(deftest test-process-edit-chapter-page-existence
+    "Check that the hurvinek.server/process-edit-chapter-page definition exists."
+    (testing "if the hurvinek.server/process-edit-chapter-page definition exists."
+        (is (callable? 'hurvinek.server/process-edit-chapter-page))))
+
+
+(deftest test-process-edit-product-page-existence
+    "Check that the hurvinek.server/process-edit-product-page definition exists."
+    (testing "if the hurvinek.server/process-edit-product-page definition exists."
+        (is (callable? 'hurvinek.server/process-edit-product-page))))
+
+
+(deftest test-process-chapter-page-existence
+    "Check that the hurvinek.server/process-chapter-page definition exists."
+    (testing "if the hurvinek.server/process-chapter-page definition exists."
+        (is (callable? 'hurvinek.server/process-chapter-page))))
+
+


Graaagh

Graaagh

--- src/korhal/core.clj
+++ src/korhal/core.clj
@@ -18,7 +18,7 @@

 (defn korhal-main [& args]
   (let [ai (korhal.core.)
-        api (jnibwapi.JNIBWAPI. this)]
+        api (jnibwapi.JNIBWAPI. ai)]
     (swap! (.state ai) swap-key :api api)
     (.start (:api @ai))))