Vacation counting example in api tests

Vacation counting example in api tests

--- test/tick/alpha/api_test.clj
+++ test/tick/alpha/api_test.clj
@@ -68,8 +68,8 @@
        (t/date "2017-04-16")
        (cal/easter-sunday 2017)))

-  (is (= java.time.DayOfWeek/TUESDAY (t/day (t/date "2017-04-11"))))
-  (is (= java.time.DayOfWeek/WEDNESDAY (t/day (t/date "2017-04-19"))))
+  (is (= t/tuesday (t/day (t/date "2017-04-11"))))
+  (is (= t/wednesday (t/day (t/date "2017-04-19"))))

   ;; Let's take a vacation
   (let [vacation (t/interval (t/date "2017-04-11") (t/date "2017-04-19"))]
@@ -77,14 +77,41 @@
     (is (= 9 (t/days (t/duration vacation))))

     (let [year (t/year 2017)
-          holidays (map (comp t/interval :date) (cal/holidays-in-england-and-wales year))
+          public-holidays (map (comp t/interval :date) (cal/holidays-in-england-and-wales year))
           weekends (map t/interval (filter cal/weekend? (t/dates-over (t/interval year))))
-          working-days-absent (t/days (apply t/+ (map t/duration (t/difference [vacation] (t/union holidays weekends)))))]
+          non-working-days (t/union public-holidays weekends)
+          vacation-set (t/difference [vacation] non-working-days)
+          working-days-absent (t/days (apply t/+ (map t/duration vacation-set)))]

       ;; But really it's just the Tues, Weds, Thurs of the first week (because Good Friday is a holiday in England, and Monday being a bank holiday, just the following Tuesday and Wednesday count. That totals 5.
-      (is (= 5 working-days-absent)))))
-
-#_(t/years-over (t/interval ["2017-12-31" "2018-01-01"]))
+      (is (= 5 working-days-absent))
+
+      ;; OK, now we want to display the vacation on a monthly calendar,
+      ;; and want to determine what to display for Thursday 13th April. Does our vacation include this Thursday?
+      (let [day (t/date "2017-04-13")]
+        (is (= t/thursday (t/day day)))
+        ;; Intersections are powerful. If we only booked off a
+        ;; half-day on this thursday, the intersection would return
+        ;; this half-day.
+        (is (not-empty (t/intersection [(t/interval day)] vacation-set))))
+
+      ;; Another use of intersections can be to determine the number of vacation days taken in 2017. But let's make things a little harder by booking time over the new year period.
+      (let [festive-break (t/interval (t/date "2017-12-20") (t/date "2018-01-07"))
+
+            vacation-set
+            (-> vacation-set ; start with our original vacation set
+                ;; Let's add this to our vacation set
+                (t/union vacation-set [festive-break])
+                ;; We'll subtract the actual public holidays and
+                ;; weekends, these shouldn't be deducted from the
+                ;; number of vacation days.
+                (t/difference non-working-days)
+                ;; We only want to know the total vacation day count for 2017
+                (t/intersection [(t/interval "2017")]))]
+
+        ;; The festive vacation days in 2017 are 20th, 21th, 22nd, 27th, 28th, 29th.
+        ;; Added to the 5 days we've already taken, that makes 11
+        (is (= (+ 5 6) (t/days (apply t/+ (map t/duration vacation-set)))))))))

 #_(t/partition-by-date)


[STORM-2093] Fix permissions in multi-tenant, secure mode

--- storm-core/src/clj/org/apache/storm/daemon/logviewer.clj
+++ storm-core/src/clj/org/apache/storm/daemon/logviewer.clj
@@ -21,6 +21,7 @@
   (:use [org.apache.storm config daemon-config util log])
   (:use [org.apache.storm.ui helpers])
   (:import [org.apache.storm StormTimer]
+           [org.apache.storm.daemon.supervisor ClientSupervisorUtils]
            [org.apache.storm.daemon.supervisor SupervisorUtils]
            [org.apache.storm.metric StormMetricsRegistry])
   (:import [org.apache.storm.utils Time VersionInfo ConfigUtils Utils ServerUtils ServerConfigUtils])
@@ -501,6 +502,19 @@
                           pager-data)))))
       (-> (resp/response "Page not found")
           (resp/status 404)))))
+
+(defnk set-log-file-permissions [fname root-dir]
+  (let [file (.getCanonicalFile (File. root-dir fname))
+        run-as-user (*STORM-CONF* SUPERVISOR-RUN-WORKER-AS-USER)
+        parent (.getParent (File. root-dir fname))
+        md-file (if (nil? parent) nil (get-metadata-file-for-wroker-logdir parent))
+        topo-owner (if (nil? md-file) nil (get-topo-owner-from-metadata-file (.getCanonicalPath md-file)))]
+    (when (and run-as-user
+          (not-nil? topo-owner)
+          (.exists file)
+          (not (Files/isReadable (.toPath file))))
+      (log-debug "Setting permissions on file " fname " with topo-owner " topo-owner)
+      (ClientSupervisorUtils/processLauncherAndWait *STORM-CONF* topo-owner ["blob" (.getCanonicalPath file)] nil (str "setup group read permissions for file: " fname)))))

 (defnk download-log-file [fname req resp user ^String root-dir :is-daemon false]
   (let [file (.getCanonicalFile (File. root-dir fname))]
@@ -1020,6 +1034,7 @@
             start (if (:start m) (parse-long-from-map m :start))
             length (if (:length m) (parse-long-from-map m :length))
             file (URLDecoder/decode (:file m))]
+        (set-log-file-permissions file log-root)
         (log-template (log-page file start length (:grep m) user log-root)
           file user))
       (catch InvalidRequestException ex
@@ -1098,6 +1113,7 @@
       (.mark logviewer:num-download-log-file-http-requests)
       (let [user (.getUserName http-creds-handler servlet-request)
             file (URLDecoder/decode (:file m))]
+        (set-log-file-permissions file log-root)
         (download-log-file file servlet-request servlet-response user log-root))
       (catch InvalidRequestException ex
         (log-error ex)


Add link to show space diagram.

Add link to show space diagram.

--- src/afterglow/transform.clj
+++ src/afterglow/transform.clj
@@ -8,9 +8,13 @@
   audience: Standing facing your show, the X axis passes through it
   increasing from left to right, the Y axis passes through it
   increasing away from the floor, and the Z axis passes through it
-  increasing towards the audience. Pick an origin when setting up your
-  show; in our case it is easiest to use the center of gravity of the
-  main truss in our lighting rig, something else may be better for
+  increasing towards the audience. (There is a diagram on the [Show
+  Space](https://github.com/brunchboy/afterglow/blob/master/doc/show_space.adoc#show-space)
+  documentation page.)
+
+  Pick an origin when setting up your show; in our case it is easiest
+  to use the spot on the floor directly under the center of gravity of
+  the main truss in our lighting rig. Something else may be better for
   you.

   When hanging your lights, measure how far the center of the light is


ensure compatibility with older versions of clj-http.

--- src/ancient_clj/io/http.clj
+++ src/ancient_clj/io/http.clj
@@ -43,8 +43,10 @@
       (try
         (let [uri (xml/metadata-uri repository-uri group id)
               {:keys [status headers body error]} (http/get uri opts)
-              {:keys [content-type]} headers
-              content-type (and content-type (first (.split content-type ";")))]
+              content-type (some-> headers
+                                   (some [:content-type "content-type"])
+                                   (.split ";")
+                                   (first))]
           (if-not error
             (if (= status 200)
               (if (contains? valid-content-types content-type)


s/:mangiare/:eat/

s/:mangiare/:eat/

--- src/babel/encyclopedia.cljc
+++ src/babel/encyclopedia.cljc
@@ -390,7 +390,7 @@
         {:pred :live
          :subj {:animate true}}

-        {:pred :mangiare
+        {:pred :eat
          :subj {:animate true}
          :obj {:edible true}}


handle case when _demo_ is an empty string

--- src/babel/english/demo.cljc
+++ src/babel/english/demo.cljc
@@ -85,7 +85,7 @@
                                                  (subs formatted 1 (count formatted))
                                                  "."))))
                                        expressions))))))
-                (if spec
+                (if (and spec (not (empty? (string/trim spec))))
                   (filter #(= (:demo-name %)
                               spec)
                           demo-specs)


more work on making generation more lazy

--- src/babel/italiano/lab.cljc
+++ src/babel/italiano/lab.cljc
@@ -44,6 +44,10 @@
             :sem {:subj {:pred :top}
                   :obj {:pred :top}}}})

+
+(def non-aux-spec
+  {:synsem {:aux false}})
+
 (defn transitive-sentence []
   (let [spec transitive-spec]
     (repeatedly #(-> spec generate morph time println))))
@@ -56,7 +60,7 @@
 (defn sentences-with-pronoun-objects-hints
   "supply a spec enhanced with syntactic info to speed-up generation."
   []
-  (let [spec (unify transitive-spec phrasal-spec)]
+  (let [spec (unify non-aux-spec transitive-spec phrasal-spec)]
     (repeatedly #(-> spec generate morph time println))))

 (defn sentences-with-pronoun-objects-small []
@@ -84,9 +88,16 @@
                            :noun)
                         (= (get-in lexeme [:synsem :pronoun])
                            true)))
-        spec (unify transitive-spec phrasal-spec)]
+        propernoun? (fn [lexeme]
+                   (and (= (get-in lexeme [:synsem :cat])
+                           :noun)
+                        (= (get-in lexeme [:synsem :propernoun])
+                           true)))
+
+        spec (unify transitive-spec phrasal-spec non-aux-spec
+                    {:head {:comp {:synsem {:pronoun true}}}})]
     (repeatedly (fn []
-                  (let [chosen-subset (set (take 10 (shuffle transitive-verbs)))
+                  (let [chosen-subset (set (take 1000 (shuffle transitive-verbs)))
                         model
                         (model-plus-lexicon
                          ;; filtered lexicon: all pronouns and a small subset of transitive verbs.
@@ -97,6 +108,7 @@
                                                  (or (and
                                                       (contains? chosen-subset k)
                                                       (transitive? lexeme))
+                                                     (propernoun? lexeme)
                                                      (pronoun? lexeme)))
                                                lexemes)]
                                    (if (not (empty? filtered-lexemes))
@@ -159,3 +171,11 @@
         first
         (get-in [:synsem :sem])
         clojure.pprint/pprint)))
+
+(def spec {:comp {:phrasal false},
+           :head {:comp {:phrasal false, :synsem {:pronoun true}},
+                  :head {:phrasal false}},
+           :synsem {:cat :verb, :subcat (),
+                    :aux false :sem {:subj {:pred :top},
+                                     :obj {:pred :top}}}})
+(def foo (first (babel.generate/lightning-bolts model spec 0 2)))


Remove unused code.

Remove unused code.

--- dev/bench/core.cljs
+++ dev/bench/core.cljs
@@ -5,16 +5,6 @@
             [cljs.nodejs :as node]))

 (enable-console-print!)
-
-;; --- Helpers
-
-(defn generate-points
-  ([n] (generate-points n 1))
-  ([n step]
-   (into-array
-    (for [x (range 0 n step)
-          y (range 0 n step)]
-      #js [x y]))))

 ;; --- Index Initialization Bechmark


Return an anomaly if production creation fails

--- src/clj/mdr2/production.clj
+++ src/clj/mdr2/production.clj
@@ -11,7 +11,8 @@
             [mdr2.production.path :as path]
             [mdr2.obi :as obi]
             [mdr2.pipeline1 :as pipeline]
-            [clojure.tools.logging :as log]))
+            [clojure.tools.logging :as log]
+            [de.otto.nom.core :as nom]))

 (defn library-signature?
   "Return true if `id` is a valid library signature"
@@ -144,16 +145,13 @@
   [production]
   ;; FIXME: make sure nothing is inserted in the db if we cannot create the dirs
   ;;  (transaction)
-  (let [p (-> production
-              (assoc :state "new")
-              add-default-meta-data
-              db/insert-production)]
-    (when (map? p)
-      (create-dirs p)
-      (when (:product_number p)
-        ;; notify the erp of the status change
-        (>!! queues/notify-abacus p)))
-    p))
+  (nom/let-nom> [p (-> production
+                      add-default-meta-data
+                      db/insert-production)]
+    (create-dirs p)
+    (when (:product_number p)
+      ;; notify the erp of the status change
+      (>!! queues/notify-abacus p))))

 (defn update! [production]
   (db/update-production production))


Normalize queries

Normalize queries

--- src/clj/sparqlab/sparql.clj
+++ src/clj/sparqlab/sparql.clj
@@ -112,10 +112,10 @@
         canonical-results (sparql-query endpoint canonical-query)
         ; If the queries are the same, retrieve only the canonical results.
         query-results (if equal-query-result canonical-results (sparql-query endpoint query))]
-    {:canonical-query {:query canonical-query-string
+    {:canonical-query {:query (:query-string canonical-query)
                        :results canonical-results
                        :results-type (get-results-type (:query-type canonical-query))}
-     :query {:query query-string
+     :query {:query (:query-string query)
              :results query-results
              :results-type (get-results-type (:query-type query))}
      :equal? (or equal-query-result (equal-query-results? (:query-type canonical-query)


add bootstrap and layout

add bootstrap and layout

--- src/clj_money/web/pages.clj
+++ src/clj_money/web/pages.clj
@@ -2,12 +2,73 @@
   (:require [hiccup.core :refer :all]
             [hiccup.page :refer :all]))

+(defn navigation
+  "Renders the site navigation"
+  [items]
+  [:nav.navbar
+   [:div.container
+    [:div.navbar-header
+     [:button.navbar-toggle.collapsed {:type "button"
+                                       :data-toggle "collapse"
+                                       :data-target "#navbar"
+                                       :aria-expanded "false"
+                                       :aria-controls "navbar"}
+      [:span.sr-only "Toggle navigation"]
+      [:span.icon-bar]
+      [:span.icon-bar]
+      [:span.icon-bar]]
+     [:a.navbar-brand {:href "/"} "clj-money"]]
+    [:div#navbar.collapse.navbar-collapse
+     [:ul.nav.navbar-nav
+      (map (fn [item]
+             [:li
+              [:a {:href (:url item)} (:caption item)]
+              ])
+           items)]]]])
+
+(defn primary-nav
+  "Renders the site primary navigation"
+  []
+  (navigation [{:url "/accounts"     :caption "Accounts"}
+               {:url "/transactions" :caption "Transactions"}
+               {:url "/commodities"  :caption "Commodities"}]))
+
+(defn layout
+  "Renders content in a standard page"
+  [site-title page-title & content]
+  (html5
+    [:html {:lang "en"}
+     [:head
+      [:meta  {:charset "utf-8"}]
+      [:meta  {:http-equiv "X-UA-Compatible" :content "IE=edge"}]
+      [:meta  {:name "viewport" :content "width=device-width, initial-scale=1"}]
+      "<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->"
+
+      [:meta  {:name "description" :content "Double-entry account system"}]
+      [:meta  {:name "author" :content "Doug Knight"}]
+      [:link  {:rel "icon" :href "../../favicon.ico"}]
+      [:title (str "clj-money - " site-title)]
+
+      "<!-- jQuery -->"
+      [:script {:src "http://code.jquery.com/jquery-2.1.4.min.js"}]
+
+      "<!-- Bootstrap core CSS -->"
+      [:link {:rel "stylesheet" :href "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"}]
+      [:link {:rel "stylesheet" :href "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css"}]
+      [:link {:rel "stylesheet" :href "/clj-money.css"}]
+      [:script  {:src "https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"}]]
+     [:body
+      (primary-nav)
+      [:div.container {:style "margin-top: 2em;"}
+       (html
+         [:h1#page-title page-title]
+         content)]]]))
+
 (defn home
   "Renders the home page"
   []
-  (html5
-    [:html
-     [:head
-      [:title "Money"]]
-     [:body
-      [:h1 "Money"]]]))
+  (layout "Home",
+          "Money"
+          (html
+            "Welcome to the accounting application"
+            )))


Fix refresh keys on get-data

Fix refresh keys on get-data

--- src/cljs/herder/getter.cljs
+++ src/cljs/herder/getter.cljs
@@ -17,49 +17,49 @@

 (defmulti get-data (fn [key] (first key)))

-(defmethod get-data :conventions [& {:keys [refresh] :or [refresh false]}]
+(defmethod get-data :conventions [[_] & {:keys [refresh] :or {refresh false}}]
   (get-raw-data :conventions "/api/convention" :refresh refresh))

 (defn convention-url [id]
   (str "/api/convention/" id))

-(defmethod get-data :convention [[_ id] & {:keys [refresh] :or [refresh false]}]
+(defmethod get-data :convention [[_ id] & {:keys [refresh] :or {refresh false}}]
   (get-raw-data [id :convention] (convention-url id) :refresh refresh))

 (defn slots-url [id]
   (str (convention-url id) "/slot"))

-(defmethod get-data :slots [[_ id] & {:keys [refresh] :or [refresh false]}]
+(defmethod get-data :slots [[_ id] & {:keys [refresh] :or {refresh false}}]
   (get-raw-data [id :slots] (slots-url id) :refresh refresh))

 (defn persons-url [id]
   (str (convention-url id) "/person"))

-(defmethod get-data :persons [[_ id] & {:keys [refresh] :or [refresh false]}]
+(defmethod get-data :persons [[_ id] & {:keys [refresh] :or {refresh false}}]
   (get-raw-data [id :persons] (persons-url id) :refresh refresh))

 (defn person-url [conv_id person_id]
   (str (persons-url conv_id) "/" person_id))

-(defmethod get-data :person [[_ conv_id person_id] & {:keys [refresh] :or [refresh false]}]
+(defmethod get-data :person [[_ conv_id person_id] & {:keys [refresh] :or {refresh false}}]
   (get-raw-data [conv_id :person person_id] (person-url conv_id person_id) :refresh refresh))

 (defn events-url [id]
   (str (convention-url id) "/event"))

-(defmethod get-data :events [[_ id] & {:keys [refresh] :or [refresh false]}]
+(defmethod get-data :events [[_ id] & {:keys [refresh] :or {refresh false}}]
   (get-raw-data [id :events] (events-url id) :refresh refresh))

 (defn event-url [conv_id event_id]
   (str (convention-url conv_id) "/event/" event_id))

-(defmethod get-data :event [[_ conv_id event_id] & {:keys [refresh] :or [refresh false]}]
+(defmethod get-data :event [[_ conv_id event_id] & {:keys [refresh] :or {refresh false}}]
   (get-raw-data [conv_id :event event_id] (event-url conv_id event_id) :refresh refresh))

 (defn schedule-url [id]
   (str (convention-url id) "/schedule"))

-(defmethod get-data :schedule [[_ id] & {:keys [refresh] :or [refresh false]}]
+(defmethod get-data :schedule [[_ id] & {:keys [refresh] :or {refresh false}}]
   (get-raw-data [id :schedule] (schedule-url id) :refresh refresh))

 (defmethod get-data :default [params]


Add space to lang

Add space to lang

--- src/cljs/subman/search.cljs
+++ src/cljs/subman/search.cljs
@@ -28,7 +28,7 @@
       [:span " " (when (is-filled? season) (str "S" season))
        (when (is-filled? episode) (str "E" episode))])]
    [:p.pull-right "Source: " (const/type-names source)]
-   [:p "Language:" lang]
+   [:p "Language: " lang]
    (when (is-filled? version)
      [:p "Version: " version])])


remove unnecessary db events

remove unnecessary db events

--- src/cljs/tictag/events.cljs
+++ src/cljs/tictag/events.cljs
@@ -4,21 +4,6 @@
             [taoensso.timbre :as timbre]
             [ajax.core :refer [transit-response-format transit-request-format]]
             [tictag.nav :as nav]))
-
-(reg-event-db
- :login/password-input
- (fn [db [_ password]]
-   (assoc-in db [:login :password] password)))
-
-(reg-event-db
- :login/username-input
- (fn [db [_ username]]
-   (assoc-in db [:login :username] username)))
-
-(reg-event-db
- :login/email-input
- (fn [db [_ email]]
-   (assoc-in db [:login :email] email)))

 (defn authenticated-xhrio [m token]
   (merge m {:headers {"Authorization" token}}))


Rewrite todo rules with macro, add comments for those with issues

--- src/cljs/todomvc/rules.cljs
+++ src/cljs/todomvc/rules.cljs
@@ -44,12 +44,25 @@
 ;  [:todo/title [[e a v]] (= ?e e)]
 ;  =>
 ;  (insert! [?e :todo/visible :tag]))
-
-(defrule todo-is-visible-when-filter-is-done-and-todo-done
-  [:ui/visibility-filter [[e a v]] (= v :done)]
-  [:todo/done [[e a v]] (= e ?e)]
+(def-tuple-rule todo-is-visile-when-filter-is-done-and-todo-done
+  [[_ :ui/visibility-filter :done]]
+  [[?e :todo/done]]
   =>
   (insert! [?e :todo/visible :tag]))
+
+;(defrule todo-is-visible-when-filter-is-done-and-todo-done
+;  [:ui/visibility-filter [[e a v]] (= v :done)]
+;  [:todo/done [[e a v]] (= e ?e)]
+;  =>
+;  (insert! [?e :todo/visible :tag]))
+
+;TODO. Currently returning full expr when detect op, need to parse rest as tuple
+;(def-tuple-rule todo-is-visible-when-filter-active-and-todo-not-done
+;  [[_ :ui/visibility-filter :active]]
+;  [[?e :todo/title]]
+;  [:not [?e :todo/done]]
+;  =>
+;  (insert! [?e :todo/visible :tag]))

 (defrule todo-is-visible-when-filter-active-and-todo-not-done
   [:ui/visibility-filter [[e a v]] (= v :active)]
@@ -68,6 +81,22 @@
   (println "Marked done via toggle complete:" ?e)
   (insert-unconditional! [?e :todo/done :done]))

+;TODO. check if :test is considered an op. Note that
+; clara's syntax allows ?binding <- :attribute with no brackets
+; so we need to support that as well
+; Accum *shouldn't* be a problem.
+; Debugging should be easier in CLJ at this point, should just need to compare expansions
+;(def-tuple-rule remove-toggle-complete-when-all-todos-done
+;  [?toggle <- :ui/toggle-complete]
+;  [?total <- (acc/count) :from [:todo/title]]
+;  [?total-done <- (acc/count) :from [:todo/done]]
+;  [:test (not (not (= ?total ?total-done)))]
+;  =>
+;  (println "Total todos: " ?total)
+;  (println "Total done: " ?total-done)
+;  (println "Retracting toggle-all-complete action: " ?toggle)
+;  (retract! ?toggle))
+
 (defrule remove-toggle-complete-when-all-todos-done
   [?toggle <- :ui/toggle-complete]
   [?total <- (acc/count) :from [:todo/title]]
@@ -78,6 +107,21 @@
   (println "Total done: " ?total-done)
   (println "Retracting toggle-all-complete action: " ?toggle)
   (retract! ?toggle))
+
+; Need to nail down our accum syntax. Current expansion violates
+; Clara's schema anyway:
+;Value does not match schema: {:from {:constraints [(not ("s-expression" :all))]}}
+;(def-tuple-rule no-done-todos-when-clear-completed-action
+  ;[:exists [:ui/clear-completed]]
+  ;[[?e :todo/title]]
+  ;[[?e :todo/done]]
+  ;[?entity <- (acc/all) :from [?e :all]]
+  ;=>
+  ; (retract {:todo/keys :all})
+  ; (retract {:todo/keys [title visible done]})
+  ; (retract-entity ?e))
+  ;(println "Retracting entity " ?entity)
+  ;(doseq [tuple ?entity] (retract! tuple)))

 (defrule no-done-todos-when-clear-completed-action
   ; when clear completed action exists
@@ -87,6 +131,8 @@
   [:todo/done [[e a v]] (= ?e e)]
   [?entity <- (acc/all) :from [:all [[e a v]] (= ?e e)]]
   =>
+  ; DSL notes on how we might handle retractions such as these.
+  ; Follows convention for namespaced keyword destructuring slated for CLJ 1.9
   ; (retract {:todo/keys :all})
   ; (retract {:todo/keys [title visible done]})
   ; (retract-entity ?e)
@@ -94,6 +140,17 @@
   (println "Retracting entity " ?entity)
   (doseq [tuple ?entity] (retract! tuple)))

+;TODO. This doesn't work and we would like the first condition to be expressed with
+; square brackets optional.
+; Also need to handle cases of nested ops as in condition 2. Should do this on
+; same pass as adding support for matching in the rightmost part of the condition
+;(def-tuple-rule clear-completed-action-is-done-when-no-done-todos
+;  [?action <- [:ui/clear-completed]]
+;  [:not [:exists [:todo/done]]]
+;  =>
+;  (println "Clear-completed action finished. Retracting " ?action)
+;  (retract! ?action))
+
 (defrule clear-completed-action-is-done-when-no-done-todos
   [?action <- :ui/clear-completed]
   [:not [:exists [:todo/done]]]


Change get-order-transaction-result (and future not return!)


Tweak hardocded resilience

Tweak hardocded resilience

--- src/clojush/meta_errors.clj
+++ src/clojush/meta_errors.clj
@@ -168,7 +168,7 @@
         0
         (if (> (/ (count (distinct hist))
                   (count hist))
-               1/2)
+               1/4)
           0
           1)))))


Changed concept id validation methods.

Changed concept id validation methods.

--- src/cmr/common/concepts.clj
+++ src/cmr/common/concepts.clj
@@ -16,11 +16,18 @@
   "Maps a concept type to the concept id prefix"
   (clojure.set/map-invert concept-prefix->concept-type))

-(defn validate-concept-id
+(defn concept-id-validation
+  "Validates the concept id and returns errors if it's invalid. Returns nil if valid."
   [concept-id]
   (let [regex #"[CG]\d+-[A-Za-z0-9_]+"]
     (when-not (re-matches regex concept-id)
-      (errors/throw-service-error :bad-request "Concept-id [%s] is not valid." concept-id))))
+      [(format "Concept-id [%s] is not valid." concept-id)])))
+
+(defn validate-concept-id
+  "Validates a concept-id and throws an error if invalid"
+  [concept-id]
+  (when-let [[error-msg] (concept-id-validation concept-id)]
+    (errors/throw-service-error :bad-request error-msg)))

 (defn parse-concept-id
   "Split a concept id into concept-type-prefix, sequence number, and provider id."


Fixed docstring of «sort-by-first»

Fixed docstring of «sort-by-first»

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/fca/contexts.clj
+++ src/conexp/fca/contexts.clj
@@ -60,7 +60,7 @@
     (compare-order x y)))

 (defn sort-by-first
-  "Convenience function for custom context printing."
+  "Ensures that pairs are ordered by first entry first."
   [x y]
   (cond
     (and (vector? x)


Fail / warn on invalid flags to the template generator

[46]

--- edge-app-template/src/clj/new/edge_app_template.clj
+++ edge-app-template/src/clj/new/edge_app_template.clj
@@ -17,14 +17,73 @@
       [(format "%d%d" dd-port dd-port)
        (format "%d00" dd-port)])))

+
+(def supported-frameworks ["sass" "cljs" "reframe"])
+
+(def framework-opts (set (map #(str "--" %) supported-frameworks)))
+
+(def supported-attributes #{"cljs"})
+
+(def attribute-opts (set (map #(str "--" %) supported-attributes)))
+
+(defn- next-row
+  [previous current other-seq]
+  (reduce
+    (fn [row [diagonal above other]]
+      (let [update-val (if (= other current)
+                          diagonal
+                          (inc (min diagonal above (peek row))))]
+        (conj row update-val)))
+    [(inc (first previous))]
+    (map vector previous (next previous) other-seq)))
+
+(defn- levenshtein
+  [sequence1 sequence2]
+  (peek
+    (reduce (fn [previous current] (next-row previous current sequence2))
+            (map #(identity %2) (cons nil sequence2) (range))
+            sequence1)))
+
+(defn- similar [ky ky2]
+  (let [dist (levenshtein (str ky) (str ky2))]
+    (when (<= dist 2) dist)))
+
+(defn similar-options [opt]
+  (second (first (sort-by first
+                  (filter first (map (juxt (partial similar opt) identity)
+                                     (concat framework-opts attribute-opts)))))))
+
+(defn parse-opts [opts]
+  (reduce (fn [accum opt]
+            (cond
+              (or
+               (framework-opts opt)
+               (attribute-opts opt)) (conj accum (keyword (subs opt 2)))
+              :else
+              (let [suggestion (similar-options opt)]
+                (try
+                  (throw
+                   (ex-info
+                    (format "Unknown option '%s' %s"
+                            opt
+                            (str
+                             (when suggestion
+                               (format "\n    --> Perhaps you intended to use the '%s' option?" suggestion))))
+                    {:opts opts}))
+                  (catch Exception e
+                    (println (.toString e)))
+                  (finally
+                    (System/exit 0))))))
+          #{} opts))
+
 (defn edge-app-template
   "FIXME: write documentation"
   [name & opts]
   (binding [*dir* (sanitize-ns name)]
-    (let [opts (set (map #(keyword (subs % 2)) opts))
-          cljs? (contains? opts :cljs)
-          sass? (contains? opts :sass)
-          reframe? (contains? opts :reframe)
+    (let [parsed-opts (parse-opts opts)
+          cljs? (contains? parsed-opts :cljs)
+          sass? (contains? parsed-opts :sass)
+          reframe? (contains? parsed-opts :reframe)
           data {:name (project-name name)
                 :sanitized (name-to-path name)
                 :root-ns (multi-segment (sanitize-ns name))


Primitive days are gone

Primitive days are gone

--- icepick-processor/src/clojure/icepick/processor.clj
+++ icepick-processor/src/clojure/icepick/processor.clj
@@ -57,7 +57,7 @@
   public void restore(T target, Bundle state) {
     if (state == null) return;
     {{#fields}}
-    target.{{name}} = H.get{{primitive}}{{method}}(state, \"{{name}}\");
+    target.{{name}} = H.get{{method}}(state, \"{{name}}\");
     {{/fields}}
     super.restore(target, state);
   }
@@ -65,7 +65,7 @@
   public void save(T target, Bundle state) {
     super.save(target, state);
     {{#fields}}
-    H.put{{primitive}}{{method}}(state, \"{{name}}\", target.{{name}});
+    H.put{{method}}(state, \"{{name}}\", target.{{name}});
     {{/fields}}
   }
   {{/view?}}
@@ -73,7 +73,7 @@
   public Parcelable restore(T target, Parcelable p) {
     Bundle state = (Bundle) p;
     {{#fields}}
-    target.{{name}} = H.get{{primitive}}{{method}}(state, \"{{name}}\");
+    target.{{name}} = H.get{{method}}(state, \"{{name}}\");
     {{/fields}}
     return super.restore(target, H.getParent(state));
   }
@@ -81,7 +81,7 @@
   public Parcelable save(T target, Parcelable p) {
     Bundle state = H.putParent(super.save(target, p));
     {{#fields}}
-    H.put{{primitive}}{{method}}(state, \"{{name}}\", target.{{name}});
+    H.put{{method}}(state, \"{{name}}\", target.{{name}});
     {{/fields}}
     return state;
   }
@@ -169,38 +169,40 @@
 ;; bundle-method

 (def ^:private exact-types
-  {"float"                                       "Float",
-   "boolean"                                     "Boolean",
+  {"boolean"                                     "Boolean",
+   "boolean[]"                                   "BooleanArray",
    "java.lang.Boolean"                           "BoxedBoolean",
+   "byte"                                        "Byte",
+   "byte[]"                                      "ByteArray",
+   "java.lang.Byte"                              "BoxedByte",
+   "char"                                        "Char",
+   "char[]"                                      "CharArray",
+   "java.lang.Char"                              "BoxedChar",
+   "double"                                      "Double",
+   "double[]"                                    "DoubleArray",
+   "java.lang.Double"                            "BoxedDouble",
+   "float"                                       "Float",
+   "float[]"                                     "FloatArray",
+   "java.lang.Float"                             "BoxedFloat",
    "int"                                         "Int",
+   "int[]"                                       "IntArray",
+   "java.lang.Integer"                           "BoxedInt"
+   "long"                                        "Long",
+   "long[]"                                      "LongArray",
+   "java.lang.Long"                              "BoxedLong",
+   "short"                                       "Short",
    "short[]"                                     "ShortArray",
-   "java.lang.Char"                              "BoxedChar",
-   "byte[]"                                      "ByteArray",
+   "java.lang.Short"                             "BoxedShort",
+
    "java.lang.CharSequence"                      "CharSequence",
-   "long[]"                                      "LongArray",
-   "long"                                        "Long",
+   "java.lang.CharSequence[]"                    "CharSequenceArray",
+   "java.lang.String"                            "String",
+   "java.lang.String[]"                          "StringArray",
    "java.util.ArrayList<java.lang.CharSequence>" "CharSequenceArrayList",
-   "java.lang.CharSequence[]"                    "CharSequenceArray",
+   "java.util.ArrayList<java.lang.Integer>"      "IntegerArrayList",
    "java.util.ArrayList<java.lang.String>"       "StringArrayList",
-   "short"                                       "Short",
+
    "android.os.Bundle"                           "Bundle",
-   "java.lang.String[]"                          "StringArray",
-   "char"                                        "Char",
-   "int[]"                                       "IntArray",
-   "boolean[]"                                   "BooleanArray",
-   "java.lang.String"                            "String",
-   "java.lang.Double"                            "BoxedDouble",
-   "char[]"                                      "CharArray",
-   "double"                                      "Double",
-   "java.lang.Short"                             "BoxedShort",
-   "float[]"                                     "FloatArray",
-   "java.lang.Byte"                              "BoxedByte",
-   "java.util.ArrayList<java.lang.Integer>"      "IntegerArrayList",
-   "double[]"                                    "DoubleArray",
-   "java.lang.Float"                             "BoxedFloat",
-   "byte"                                        "Byte",
-   "java.lang.Long"                              "BoxedLong",
-   "java.lang.Integer"                           "BoxedInt"
    "android.os.Parcelable[]"                     "ParcelableArray"})

 (defn- parcelable? [type]


Transactor is now defined with deftype instead of defrecord.

--- src/continuo/postgresql.clj
+++ src/continuo/postgresql.clj
@@ -24,7 +24,7 @@
 ;; Types
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(defrecord Transactor [context]
+(deftype Transactor [connection schema]
   impl/ITransactorInternal
   (-initialize [it]
     (bootstrap/initialize it))
@@ -37,5 +37,7 @@

 (defmethod impl/connect :postgresql
   [uri options]
-  (let [options (merge options (util/parse-params uri))]
-    (Transactor. (bootstrap/connect options))))
+  (let [options (merge options (util/parse-params uri))
+        connection (bootstrap/connec options)
+        schema {}]
+    (Transactor. connection schema)))


Add agree-or-disagree view

Add agree-or-disagree view

--- src/discuss/references.cljs
+++ src/discuss/references.cljs
@@ -6,7 +6,8 @@
             [discuss.communication :as com]
             [discuss.config :as config]
             [discuss.sidebar :as sidebar]
-            [discuss.utils.common :as lib]))
+            [discuss.utils.common :as lib]
+            [discuss.utils.views :as vlib]))

 (defn- get-reference-usages-from-app-state
   "Return list of reference usages, which were previously stored in the app-state.
@@ -64,8 +65,10 @@
             statement (:statement data)
             author (:author data)]
         (dom/div #js {:className "bs-callout bs-callout-info"}
-                 (dom/a #js {:href    "javascript:void(0)"
-                             :onClick #(com/ajax-get-and-change-view (:url statement) :default)}
+                 (dom/a #js {:href "javascript:void(0)"
+                             :onClick #(lib/change-view! :reference-agree-disagree)
+                             ;:onClick #(com/ajax-get-and-change-view (:url statement) :default)
+                             }
                         (dom/strong nil (:text statement)))
                  (dom/div nil "Issue: " (:title issue))
                  (dom/div nil "Author: " (:nickname author)))))))
@@ -78,4 +81,22 @@
       (let [usages (get-reference-usages-from-app-state)]
         (dom/div nil
                  (apply dom/div nil
-                        (map #(om/build usage-view (lib/merge-react-key %)) usages)))))))+                        (map #(om/build usage-view (lib/merge-react-key %)) usages)))))))
+
+(defn agree-disagree-view
+  "Agree or disagree with the selected reference."
+  []
+  (reify om/IRender
+    (render [_]
+      (dom/div nil
+               (dom/div #js {:className "text-center"}
+                        "Do you agree or disagree with this statement?")
+               (om/build usage-view {})
+               (dom/div #js {:className "text-center"}
+                        (dom/button #js {:className "btn btn-primary"}
+                                    (vlib/fa-icon "fa-thumbs-up")
+                                    " Agree")
+                        " "
+                        (dom/button #js {:className "btn btn-primary"}
+                                    (vlib/fa-icon "fa-thumbs-down")
+                                    " Disagree"))))))


switch :use to :require, and respect http://notaverb.com/setup

--- test/aspire/web_test_config.clj
+++ test/aspire/web_test_config.clj
@@ -1,14 +1,14 @@
 (ns aspire.web-test-config
-  (:use aspire.web
-        clojure.test
-        ring.mock.request))
+  (:require [aspire.web :as a-web]
+            [clojure.test :refer :all]
+            [ring.mock.request :as rmr]))

-(defn setup-test []
+(defn set-up-test []
   ;; this is where we would also initialize and populate test db

   ;; the following vars containing the various responses are available to the
   ;; tests defined in web_test.clj
-  (def app-response (resource-app (request :get "/"))))
+  (def onboarding-response (a-web/handle-onboarding (rmr/request :get "/"))))

 (defn teardown-test []
   (comment
@@ -17,7 +17,7 @@

 (defn web-test-config
   [web-tests]
-  (setup-test)
+  (set-up-test)
   (web-tests)
   (try
     (teardown-test)


Fix indentation of some test data

Fix indentation of some test data


Get basic server start/stop tests working again

Mostly.

The point here was to fix the pieces that I broke in a previous commit
when I eliminated the dependency on Components.

--- test/frereth_cp/server_test.clj
+++ test/frereth_cp/server_test.clj
@@ -1,70 +1,93 @@
 (ns frereth-cp.server-test
   (:require [clojure.test :refer (deftest is testing)]
             [frereth-cp.server :as server]
+            [frereth-cp.server.state :as state]
             [frereth-cp.shared :as shared]
             [frereth-cp.shared.constants :as K]
             ;; TODO: This also needs to go away
-            [com.stuartsierra.component :as cpt]
-            [component-dsl.system :as cpt-dsl]
+            #_[com.stuartsierra.component :as cpt]
+            #_[component-dsl.system :as cpt-dsl]
             [manifold.stream :as strm])
   (:import io.netty.buffer.Unpooled))

-(defrecord StreamOwner [chan]
-  ;; TODO: Make this just totally go away
-  cpt/Lifecycle
-  (start
-    [this]
-    (assoc this :chan (or chan (strm/stream))))
-  (stop
-    [this]
-    (println "Stopping StreamOwner")
-    (when chan
-      (strm/close! chan))
-    (assoc this :chan nil)))
-(defn chan-ctor
-  [_]
-  (->StreamOwner (strm/stream)))
+(comment
+  (defrecord StreamOwner [chan]
+    ;; TODO: Make this just totally go away
+    cpt/Lifecycle
+    (start
+      [this]
+      (assoc this :chan (or chan (strm/stream))))
+    (stop
+      [this]
+      (println "Stopping StreamOwner")
+      (when chan
+        (strm/close! chan))
+      (assoc this :chan nil)))
+  (defn chan-ctor
+    [_]
+    (->StreamOwner (strm/stream)))

-(def options {:cp-server {:security {:keydir "curve-test"
-                                     ;; Note that name really isn't legal.
-                                     ;; It needs to be something we can pass
-                                     ;; along to DNS, padded to 255 bytes.
-                                     ;; This bug really should show up in
-                                     ;; a test.
-                                     :name "local.test"}
-                          :extension (byte-array [0x01 0x02 0x03 0x04
-                                                  0x05 0x06 0x07 0x08
-                                                  0x09 0x0a 0x0b 0x0c
-                                                  0x0d 0x0e 0x0f 0x10])}})
-(def sys-struct {:cp-server 'com.frereth.common.curve.server/ctor
-                 :client-chan 'com.frereth.common.curve.server-test/chan-ctor})
+  (def sys-struct {:cp-server 'com.frereth.common.curve.server/ctor
+                   :client-chan 'com.frereth.common.curve.server-test/chan-ctor}))
+
+(defn system-options
+  []
+  (let [server-name (shared/encode-server-name "test.frereth.com")]
+    {:cp-server {::shared/extension (byte-array [0x01 0x02 0x03 0x04
+                                                 0x05 0x06 0x07 0x08
+                                                 0x09 0x0a 0x0b 0x0c
+                                                 0x0d 0x0e 0x0f 0x10])
+                 ::shared/my-keys #::shared{::K/server-name server-name
+                                           :keydir "curve-test"}}}))

 (defn build
   []
-  (cpt-dsl/build #:component-dsl.system {:structure sys-struct
-                                         :dependencies {:cp-server [:client-chan]}}
-                 options))
+  {:cp-server (server/ctor (:cp-server (system-options)))
+   :client-read-chan {:chan (strm/stream)}
+   :client-write-chan {:chan (strm/stream)}})
+
+(defn start
+  [inited]
+  (let [client-write-chan (:client-write-chan inited)
+        client-read-chan (:client-read-chan inited)]
+    {:cp-server (server/start! (assoc (:cp-server inited)
+                                      ::state/client-read-chan client-read-chan
+                                      ::state/client-write-chan client-write-chan))
+     :client-read-chan client-read-chan
+     :client-write-chan client-write-chan}))
+
+(defn stop
+  [started]
+  (let [ch (get-in started [:client-read-chan :chan])]
+    (strm/close! ch))
+  (let [ch (get-in started [:client-write-chan :chan])]
+    (strm/close! ch))
+  {:cp-server (server/stop! (:cp-server started))
+   :client-read-chan {:chan nil}
+   :client-write-chan {:chan nil}})

 (deftest start-stop
   (testing "That we can start and stop successfully"
-    (let [init (build)
-          started (cpt/start init)]
+    (let [inited (build)
+          started (start inited)]
       (is started)
-      (is (cpt/stop started)))))
+      (is (stop started)))))
 (comment
   (def test-sys (build))
-  (alter-var-root #'test-sys cpt/start)
+  (alter-var-root #'test-sys start)
   (-> test-sys :client-chan keys)
   (alter-var-root #'test-sys cpt/stop)
   )

 (deftest shake-hands
   (let [init (build)
-        started (cpt/start init)]
+        started (start init)]
     (println "Server should be started now")
     (try
       (println "Sending bogus HELLO")
-      (let [client (get-in started [:client-chan :chan])
+      (let [msg "Howdy!"
+            client (get-in started [:client-write-chan :chan])
+            recvd (strm/try-take! client ::drained 500 ::timed-out)
             ;; Currently, this fails silently (from our perspective).
             ;; Which, really, is a fine thing.
             ;; Although the log message should be improved (since this could
@@ -76,12 +99,16 @@
             ;; (The alternative is to either capture that exchange so
             ;; I can send it manually or reinvent the client's packet
             ;; buildig code)
-            success (deref (strm/try-put! client "Howdy!" 1000 ::timed-out))]
+            success (deref (strm/try-put! client msg 1000 ::timed-out))]
         (println "put! success:" success)
-        (is (not= ::timed-out success)))
+        ;; This is failing.
+        ;; Probably because I'm not really creating a Client.
+        ;; Q: Is that worth actually doing?
+        (is (not= ::timed-out success))
+        (is (= @recvd msg)))
       (finally
         (println "Triggering event loop exit")
-        (cpt/stop started)))))
+        (stop started)))))

 (deftest test-cookie-composition
   (let [client-extension (byte-array (take 16 (repeat 0)))
@@ -92,9 +119,9 @@
         to-encode {::K/header K/cookie-header
                    ::K/client-extension client-extension
                    ::K/server-extension server-extension
-                   ::K/nonce (Unpooled/wrappedBuffer working-nonce
-                                                     K/server-nonce-prefix-length
-                                                     K/server-nonce-suffix-length)
+                   ::K/client-nonce-suffix (Unpooled/wrappedBuffer working-nonce
+                                                                   K/server-nonce-prefix-length
+                                                                   K/server-nonce-suffix-length)
                    ;; This is also a great big FAIL:
                    ;; Have to drop the first 16 bytes
                    ;; Q: Have I fixed that yet?


Update test to reflect the moving of consumed capacity to the response metadata

--- test/hildebrand/dynamo_test.clj
+++ test/hildebrand/dynamo_test.clj
@@ -119,6 +119,7 @@
     (is (= table
            (->
             (del-item {:table table :key item :capacity :total})
+            meta
             :capacity
             :table)))))


make om reloadable for figwheel

make om reloadable for figwheel

--- src/metronome/core.cljs
+++ src/metronome/core.cljs
@@ -4,9 +4,11 @@
             [cljs.core.async :refer [put! chan <!]])
   (:require-macros [cljs.core.async.macros :refer [go]]))

-(enable-console-print!)
+(defonce app-setup
+  (do
+    (enable-console-print!)))

-(def app-state (atom {:bpm  {:bpm nil}}))
+(defonce app-state (atom {:bpm  {:bpm nil}}))

 (defn clock [bpm owner]
   (letfn [(start-interval [millis]


Block HQ consumer.

Block HQ consumer.

--- test/onyx/peer/hornetq_util.clj
+++ test/onyx/peer/hornetq_util.clj
@@ -52,7 +52,7 @@
       (doseq [k (range n)]
         (when (zero? (mod k echo))
           (info (format "[HQ Util] Read %s segments" k)))
-        (let [message (.receive consumer 60000)]
+        (let [message (.receive consumer)]
           (when message
             (.acknowledge message)
             (swap! results conj (fressian/read (.toByteBuffer (.getBodyBuffer message)))))))


Fix bad merge

Fix bad merge

--- frontend/components/add_projects.cljs
+++ frontend/components/add_projects.cljs
@@ -210,8 +210,8 @@
                                                                     :name
                                                                     (.toLowerCase)
                                                                     (.indexOf (.toLowerCase repo-filter-string))
-                                                                    (not= -1)))
-                                                               repos)))]
+                                                                    (not= -1))))
+                                                             repos))]
                    (map (fn [repo] (om/build repo-item {:repo repo
                                                         :settings settings}))
                         filtered-repos))]]))


Don't pass build-model/pretty-start-time a build when a build hasn't been run (otherwise get 'build start NaN years ago')

--- frontend/components/builds_table.cljs
+++ frontend/components/builds_table.cljs
@@ -45,7 +45,8 @@
               [:a
                {:title (datetime/full-datetime (js/Date.parse (:start_time build)))
                 :href url}
-               (build-model/pretty-start-time build)]]
+               (when (:start_time build)
+                 (build-model/pretty-start-time build))]]
              [:td.recent-time-duration
               [:a
                {:title (build-model/duration build)


Convert strings to values when reading a config.

--- src/fm/simrunner/config.clj
+++ src/fm/simrunner/config.clj
@@ -1,16 +1,23 @@
 (ns fm.simrunner.config
   (:require
-    [clojure.java.io :as jio]))
+    [clojure.java.io :as jio])
+  (:import
+    (java.io File)))

-(def ^{:private true} parameter-keys [:input-file
-                                      :eps
-                                      :log-num
-                                      :stuetz-count
-                                      :correction
-                                      :max-deviation
-                                      :calc-err
-                                      :acsr-size])
+(def ^{:private true} parameter-ids [:input-file
+                                     :eps
+                                     :log-num
+                                     :stuetz-count
+                                     :correction
+                                     :max-deviation
+                                     :calc-err
+                                     :acsr-size])

+(def ^{:private true} blank-config (-> parameter-ids
+                                       (zipmap (repeat nil))
+                                       (assoc :invalid-ids
+                                              (into #{} parameter-ids))))
+
 (defn- blank? [trimmed-line]
   (.isEmpty trimmed-line))

@@ -36,14 +43,63 @@
 (defn- trimmed [lines]
   (map #(-> % str .trim) lines))

+(defn- string->double [^String string]
+  (try
+    (Double/valueOf (str string))
+    (catch NumberFormatException x)))
+
+(defn- string->file [^String string]
+  (let [string (-> string str .trim)]
+    (when-not (.isEmpty string)
+      (File. string))))
+
+(defmulti string->value {:private true} (fn [param-id _] param-id))
+
+(defmethod string->value :input-file [_ string]
+  (string->file string))
+
+(defmethod string->value :eps [_ string]
+  (string->double string))
+
+(defmethod string->value :log-num [_ string]
+  (string->double string))
+
+(defmethod string->value :stuetz-count [_ string]
+  (string->double string))
+
+(defmethod string->value :correction [_ string]
+  (string->double string))
+
+(defmethod string->value :max-deviation [_ string]
+  (string->double string))
+
+(defmethod string->value :calc-err [_ string]
+  (string->double string))
+
+(defmethod string->value :acsr-size [_ string]
+  (string->double string))
+
+(defn strings->values [config]
+  (reduce (fn [config [param-id value-string]]
+            (if-let [value (string->value param-id value-string)]
+              (-> config
+                  (assoc param-id value)
+                  (update-in [:invalid-ids] disj param-id))
+              (assoc config param-id nil)))
+          {:invalid-ids (into #{} parameter-ids)}
+          config))
+
 (defn read-config-lines [lines]
   (let [values (-> lines
                    trimmed
                    skip-ignored
                    strip-comments)]
-    (zipmap parameter-keys values)))
+    (strings->values (zipmap parameter-ids values))))

 (defn read-config-file [file]
   (with-open [reader (jio/reader file)]
     (read-config-lines (line-seq reader))))

+(defn valid? [config]
+  (-> config :invalid-ids seq not))
+


make it say feature request instead of issue title

--- src-cljs/frontend/components/overlay.cljs
+++ src-cljs/frontend/components/overlay.cljs
@@ -778,7 +778,7 @@
               [:h4.menu-heading {:title (:title component) :react-key (:title component)}
                ;; TODO: better way to handle custom titles
                (cond (keyword-identical? :issues/single-issue overlay-key)
-                     (:issue/title (issue-model/find-by-frontend-id @(om/get-shared owner :issue-db) (:active-issue-uuid app)))
+                     "Feature Request"

                      (namespaced? overlay-key)
                      (str (:title component) " " (str/capitalize (name overlay-key)))


Tidy up of state access.

Tidy up of state access.

--- src-cljs/kixi/hecuba/tabs/programmes.cljs
+++ src-cljs/kixi/hecuba/tabs/programmes.cljs
@@ -533,15 +533,14 @@
       (go-loop []
         (let [{:keys [th-chan sort-spec]} (om/get-state owner)
               {:keys [sort-key sort-asc]} sort-spec
-              th-click (<! th-chan)]
-          (log "Header clicked: " th-click)
+              th-click                    (<! th-chan)]
           (if (= th-click sort-key)
-            (om/set-state! owner {:th-chan th-chan
-                                  :sort-spec {:sort-key th-click
-                                              :sort-asc (not sort-asc)}})
-            (om/set-state! owner {:th-chan th-chan
-                                  :sort-spec {:sort-key th-click
-                                              :sort-asc true}})))
+            (om/update-state! owner #(assoc %
+                                       :sort-spec {:sort-key th-click
+                                                   :sort-asc (not sort-asc)}))
+            (om/update-state! owner #(assoc %
+                                       :sort-spec {:sort-key th-click
+                                                   :sort-asc true}))))
         (recur)))
     om/IRenderState
     (render-state [_ state]
@@ -562,7 +561,6 @@
             (sorting-th owner "Device" :device_id)
             (sorting-th owner "Status" :status)]]
           [:tbody
-           ;; TODO: reverse sorting based on :sort-asc
            (for [row (if sort-asc
                        (sort-by sort-key flattened-sensors)
                        (reverse (sort-by sort-key flattened-sensors)))]


whoops

whoops

--- server/src/gratefulplace/email/sending/senders.clj
+++ server/src/gratefulplace/email/sending/senders.clj
@@ -1,5 +1,6 @@
 (ns gratefulplace.email.sending.senders
-  (:require [com.flyingmachine.penny-black.core.send :refer [defsenders]]
+  (:require com.flyingmachine.penny-black-apache-commons
+            [com.flyingmachine.penny-black.core.send :refer [defsenders]]
             [gratefulplace.utils :refer :all]
             [gratefulplace.config :refer [config]]))


interpret-line now does resources

interpret-line now does resources

--- src/hphelper/shared/sql.clj
+++ src/hphelper/shared/sql.clj
@@ -95,6 +95,13 @@
         token)
       (get-or-create-name (partial get-random-name (second tokenised)) token))))

+(defn- get-random-resource
+  "Gets a random resource from the database"
+  [resType]
+  (:resource_name
+   (rand-nth
+    (query "SELECT resource_name FROM resource WHERE resource_type LIKE ?;" resType))))
+
 (defn- interpret-token
   "Takes a string of format ABC-TAGS-AND-OTHERS and looks at the first part, choosing which
   function to call, then calls get-or-create-name. On an error logs and returns the token."
@@ -103,6 +110,8 @@
     (case firstPart
       "ZON" zoneName
       "CIT" (interpret-citizen-name token)
+      "LOC" (get-or-create-name (partial get-random-resource "LOC") token)
+      "RES" (get-or-create-name (partial get-random-resource "RES") token)
       (do
         (log/error "Incorrect token form:" token)
         token)


Move the build time card next to last build card

--- src-cljs/frontend/components/insights/project.cljs
+++ src-cljs/frontend/components/insights/project.cljs
@@ -109,12 +109,12 @@
                                   :formatter-use-start? true}})]]]
          [:div.card.insights-metadata
           [:dl
+           [:dt "median build time"]
+           [:dd (datetime/as-duration (insights/median (map :build_time_millis bar-chart-builds))) " min"]]]
+         [:div.card.insights-metadata
+          [:dl
            [:dt "median queue time"]
            [:dd (datetime/as-duration (insights/median (map :queued_time_millis bar-chart-builds))) " min"]]]
-         [:div.card.insights-metadata
-          [:dl
-           [:dt "median build time"]
-           [:dd (datetime/as-duration (insights/median (map :build_time_millis bar-chart-builds))) " min"]]]
          [:div.card.insights-metadata
           [:dl
            [:dt "current parallelism"]


fix updated pause macro

fix updated pause macro

--- src/cljs/org/broadinstitute/firecloud_ui/utils.clj
+++ src/cljs/org/broadinstitute/firecloud_ui/utils.clj
@@ -30,4 +30,5 @@

 (defmacro pause
   "JS debugger statement."
+  []
   `(js* "debugger;"))


fixed rounding of km/h

fixed rounding of km/h

--- src/ontrail/formats.clj
+++ src/ontrail/formats.clj
@@ -31,9 +31,8 @@
     (str (int pace) "." (format "%02d" secs) " min/500m")))

 (defn to-human-pace-kmh [duration distance]
-  (let [speed (/ (/ distance 1000.0) (/ duration 360000.0))
-        fraction (int (* 10 (- (+ 0.05 speed) (int speed))))]
-    (str (int speed) "," (format "%01d" fraction) " km/h")))
+  (let [speed (+ 0.05 (/ (/ distance 1000.0) (/ duration 360000.0)))]
+    (format "%1.1f km/h" speed)))

 (defn pace-conversion-fun [^String sport]
   (case sport


units

units

--- src/ontrail/formats.clj
+++ src/ontrail/formats.clj
@@ -42,8 +42,10 @@
     "Sisäsoutu" to-human-pace-500m
     "Soutu" to-human-pace-500m
     "Rullaluistelu" to-human-pace-kmh
+    "Rullahiihto" to-human-pace-kmh
     "Kickbike" to-human-pace-kmh
     "Cyclocross" to-human-pace-kmh
+    "Kuntopyöräily" to-human-pace-kmh
     "Maantiepyöräily" to-human-pace-kmh
     "CYCLO" to-human-pace-kmh
     "MAANTIE" to-human-pace-kmh


include existing workflow validation

include existing workflow validation

--- src/onyx/validation.clj
+++ src/onyx/validation.clj
@@ -16,8 +16,32 @@

 (defn validate-catalog
   [catalog]
-  (schema/validate [(schema/pred map? 'map?)] catalog)
-  (doseq [entry catalog]
+  (doseq [entry catalog]
     (schema/validate catalog-entry-validator entry)))

+(defn flatten-workflow [workflow]
+  (concat (keys workflow)
+          (mapcat (fn [v]
+                    (if (map? v)
+                      (flatten-workflow v)
+                      (list v)))
+            (vals workflow))))

+(defn validate-workflow-names [{:keys [workflow catalog]}]
+  (when-let [missing-names (->> workflow
+                                flatten-workflow
+                                (remove (set (map :onyx/name catalog)))
+                                seq)]
+    (throw (Exception. (str "Catalog is missing :onyx/name values "
+                            "for the following workflow keywords: "
+                            (apply str (interpose ", " missing-names)))))))
+
+(def job-validator
+  {:catalog [(schema/pred map? 'map?)]
+   :workflow (schema/pred map? 'map?)})
+
+(defn validate-job
+  [job]
+  (schema/validate job-validator job)
+  (validate-catalog (:catalog job))
+  (validate-workflow-names job))


Might be able to survive with less consistency.

--- src/kixi/hecuba/session.clj
+++ src/kixi/hecuba/session.clj
@@ -16,8 +16,7 @@
         (let [user-session (first (db/execute
                                    db-session
                                    (hayt/select :sessions
-                                                (hayt/where [[= :id key]]))
-                                   {:consistency :quorum}))]
+                                                (hayt/where [[= :id key]]))))]
           (log/debugf "Retrieved session %s" user-session)
           (clojure.edn/read-string (:data user-session))))
       {}))


Make notes' colour nicer.

Make notes' colour nicer.

--- src/klangmeister/views.cljs
+++ src/klangmeister/views.cljs
@@ -26,11 +26,14 @@
                                          (scale :time 550)
                                          (scale :pitch 260))]
                          (doseq [{:keys [time pitch played?]} scaled]
-                           (quil/ellipse
-                             (-> time (+ 25))
-                             (-> pitch (+ 20) - (+ 300))
-                             (if played? 40 30)
-                             30))))
+                           (let [colour (if played? 200 20)]
+                             (quil/stroke colour)
+                             (quil/fill colour)
+                             (quil/ellipse
+                               (-> time (+ 25))
+                               (-> pitch (+ 20) - (+ 300))
+                               40
+                               30)))))
                :host "graph"
                :no-start true
                :middleware [middleware/fun-mode]


count test runs

count test runs

--- src/pharrellel_test.clj
+++ src/pharrellel_test.clj
@@ -87,7 +87,8 @@
 (defn run-worker [results tests-to-run worker-id finished]
   (future
     (try
-      (binding [*result-queue* results]
+      (binding [*result-queue* results
+                t/*report-counters* (ref {})]
         (loop []
           (if-let [[tvar each-fixture once-fixture] (.poll tests-to-run)]
             (do
@@ -97,7 +98,7 @@
                     #(test-var results tvar))))
               (recur))
             (do
-              (deliver (nth finished worker-id) 1)))))
+              (deliver (nth finished worker-id) t/*report-counters*)))))
       (catch Throwable e
         (.printStackTrace e))
       (finally (deliver (nth finished worker-id) 1)))))
@@ -110,7 +111,8 @@
     (doseq [n finished]
       (deref n))
     (doseq [r (iterator-seq (.iterator results))]
-      (println r))))
+      (println r))
+    (apply merge-with + (map (comp deref deref) finished))))

 (defn gather-tests [ns-re]
   (let [queue (LinkedBlockingQueue.)]