Rule-level aggregates

Rule-level aggregates

--- src/aurora/language.cljs
+++ src/aurora/language.cljs
@@ -1,6 +1,6 @@
 (ns aurora.language
   (:require [aurora.btree :as btree])
-  (:require-macros [aurora.macros :refer [apush set!!]]))
+  (:require-macros [aurora.macros :refer [apush aclear set!!]]))

 ;; KNOWLEDGE

@@ -105,19 +105,48 @@

 ;; FLOWS

-(deftype Flow [solver output-kinds output-names output-fields]
+(deftype Sink [kind name fields]
+  Object
+  (run [this kn rule->dirty? kind->name->rules facts&vals]
+       (when (true? (.update-facts kn kind name fields facts&vals))
+         (let [dirtied-rules (aget kind->name->rules kind name)]
+           (dotimes [j (alength dirtied-rules)]
+             (aset rule->dirty? (aget dirtied-rules j) true))))))
+
+(deftype SolverFlow [solver sinks]
   Object
   (run [this kn rule->dirty? kind->name->rules]
        (.reset solver)
        (let [facts&vals (.elems solver)]
-         (dotimes [i (alength output-kinds)]
-           (let [kind (aget output-kinds i)
-                 name (aget output-names i)
-                 fields (aget output-fields i)]
-             (when (true? (.update-facts kn kind name fields facts&vals))
-               (let [dirtied-rules (aget kind->name->rules kind name)]
-                 (dotimes [j (alength dirtied-rules)]
-                   (aset rule->dirty? (aget dirtied-rules j) true)))))))))
+         (dotimes [i (alength sinks)]
+           (.run (aget sinks i) kn rule->dirty? kind->name->rules facts&vals)))))
+
+(deftype AggregateFlow [index group-len agg-ixes agg-funs sinks]
+  Object
+  (run [this kn rule->dirty? kind->name->rules]
+       (let [current-key nil
+             inputs #js []
+             aggs (make-array (alength agg-ixes))
+             facts&vals #js []
+             push-input (fn [key]
+                          (when (nil? current-key)
+                            (set!! current-key key))
+                          (when (btree/prefix-not= key current-key group-len)
+                            (dotimes [i (alength aggs)]
+                              (aset aggs i ((aget agg-funs i) (aget agg-ixes i) inputs)))
+                            (dotimes [i (alength inputs)]
+                              (let [output (aclone (aget inputs i))]
+                                (dotimes [j (alength aggs)]
+                                  (apush output (aget aggs j)))
+                                (apush facts&vals output)
+                                (apush facts&vals 1)))
+                            (aclear inputs)
+                            (set!! current-key key))
+                          (apush inputs key))]
+         (.foreach index push-input)
+         (push-input (btree/greatest-key group-len))
+         (dotimes [i (alength sinks)]
+           (.run (aget sinks i) kn rule->dirty? kind->name->rules facts&vals)))))

 (deftype Flows [rules rule->flow rule->dirty? kind->name->rules name->transient?]
   Object
@@ -158,8 +187,20 @@
         name->transient? (atom {})
         clauses (.keys (.get-or-create-index kn "know" "clauses" #js ["rule-id" "when|know|remember|forget" "clause-id" "name"]))
         fields (.keys (.get-or-create-index kn "know" "clause-fields" #js ["clause-id" "constant|variable" "key" "val"]))
+        has-aggs (.keys (.get-or-create-index kn "know" "has-agg" #js ["rule-id"]))
+        group-bys (.keys (.get-or-create-index kn "know" "group-by" #js ["rule-id" "var"]))
+        agg-overs (.keys (.get-or-create-index kn "know" "agg-over" #js ["rule-id" "in-var" "agg-fun" "out-var"]))
         rule-id->clauses (atom (into {} (for [[k vs] (group-by #(nth % 0) clauses)] [k (set (map vec vs))])))
-        clause-id->fields (atom (into {} (for [[k vs] (group-by #(nth % 0) fields)] [k (set (map vec vs))])))]
+        clause-id->fields (atom (into {} (for [[k vs] (group-by #(nth % 0) fields)] [k (set (map vec vs))])))
+        rule-id->has-agg (atom (into {} (for [[k vs] (group-by #(nth % 0) has-aggs)] [k (set (map vec vs))])))
+        rule-id->group-by (atom (into {} (for [[k vs] (group-by #(nth % 0) group-bys)] [k (set (map vec vs))])))
+        rule-id->agg-over (atom (into {} (for [[k vs] (group-by #(nth % 0) agg-overs)] [k (set (map vec vs))])))
+        sink-of (fn [rule-id clause-type clause-id name var->ix]
+                  (let [fields (make-array (count var->ix))]
+                    (doseq [[_ field-type key val] (@clause-id->fields clause-id)]
+                      (assert (= field-type "variable") [rule-id clause-id key val])
+                      (aset fields (var->ix val) key))
+                    (Sink. clause-type name fields)))]

     ;; rewrite clauses
     (doseq [[rule-id clauses] @rule-id->clauses]
@@ -187,6 +228,52 @@
                                                                  [new-clause-id "variable-b" "variable" val]})
                   (swap! rule-id->clauses update-in [rule-id] conj [rule-id "when" new-clause-id "=variable"]))
                 (swap! var->key assoc val key)))))))
+
+    ;; rewrite aggregates
+    (doseq [[rule-id clauses] @rule-id->clauses]
+      (when (seq (@rule-id->has-agg rule-id))
+        (let [agg-rule-id (str rule-id "-agg-rule")
+              agg-clause-id (str rule-id "-agg-clause")
+              agg-index-id (str rule-id "-agg-index")]
+
+          ;; remove output clauses
+          (doseq [[_ clause-type clause-id name] clauses
+                  :when (not= clause-type "when")]
+            (swap! rule-id->clauses update-in [rule-id] disj [rule-id clause-type clause-id name]))
+
+          ;; add a clause to output used vars to agg-index-ix
+          (swap! rule-id->clauses update-in [rule-id] conj [rule-id "know" agg-clause-id agg-index-id])
+          (doseq [[_ var] (@rule-id->group-by rule-id)]
+            (swap! clause-id->fields update-in [agg-clause-id] conj [agg-clause-id "variable" var var]))
+          (doseq [[_ in-var agg-fun out-var] (@rule-id->agg-over rule-id)]
+            (swap! clause-id->fields update-in [agg-clause-id] conj [agg-clause-id "variable" in-var in-var]))
+
+          ;; create an aggregate flow to read from agg-index-id
+          (let [group-by-vars (for [[_ var] (@rule-id->group-by rule-id)]
+                                var)
+                agg-in-vars (for [[_ in-var agg-fun out-var] (@rule-id->agg-over rule-id)]
+                              in-var)
+                agg-out-vars (for [[_ in-var agg-fun out-var] (@rule-id->agg-over rule-id)]
+                               out-var)
+                in-vars (into-array (concat group-by-vars agg-in-vars))
+                out-vars (into-array (concat group-by-vars agg-in-vars agg-out-vars))
+                var->ix (into {}
+                              (for [i (range (alength out-vars))]
+                                [(aget out-vars i) i]))
+                index (.get-or-create-index kn "know" agg-index-id in-vars)
+                group-len (count group-by-vars)
+                agg-ixes (into-array
+                          (for [[_ in-var agg-fun out-var] (@rule-id->agg-over rule-id)]
+                            (var->ix in-var)))
+                agg-funs (into-array
+                          (for [[_ in-var agg-fun out-var] (@rule-id->agg-over rule-id)]
+                            (aget js/aurora.aggregates agg-fun)))
+                sinks (into-array
+                       (for [[_ clause-type clause-id name] clauses
+                             :when (not= clause-type "when")]
+                         (sink-of rule-id clause-type clause-id name var->ix)))]
+            (swap! rule->flow assoc agg-rule-id (AggregateFlow. index group-len agg-ixes agg-funs sinks))
+            (swap! kind->name->rules update-in ["know" agg-index-id] conj agg-rule-id)))))

     (doseq [[rule-id clauses] @rule-id->clauses]
       (let [var->when-count (atom {})]
@@ -281,42 +368,30 @@
               ;; make solver
               solver (btree/solver num-vars (into-array constraints))

-              ;; make output specs
-              output-kinds (into-array
-                            (for [[_ clause-type clause-id name] clauses
-                                  :when (not= clause-type "when")]
-                              clause-type))
-              output-names (into-array
-                            (for [[_ clause-type clause-id name] clauses
-                                  :when (not= clause-type "when")]
-                              name))
-              output-fields (into-array
-                             (for [[_ clause-type clause-id name] clauses
-                                   :when (not= clause-type "when")]
-                               (let [clause-fields (get @clause-id->fields clause-id)
-                                     output-fields (make-array num-vars)]
-                                 (doseq [[_ field-type key val] clause-fields]
-                                   (assert (= field-type "variable") [rule-id clause-id clause-fields])
-                                   (aset output-fields (var->ix val) key))
-                                 output-fields)))]
-
-          ;; set up state for outputs
-          (dotimes [i (alength output-kinds)]
-            (let [kind (aget output-kinds i)
-                  name (aget output-names i)
-                  fields (aget output-fields i)
-                  filtered-fields (into-array (filter #(not (nil? %)) fields))
-                  transient? (identical? kind "know")]
-              ;; TODO get transient? from schema instead
-              (assert (not= (not transient?) (get @name->transient? name)) name)
-              (swap! name->transient? assoc name transient?)
-              (swap! kind->name->rules update-in [kind name] #(or % #{}))
-              (.ensure-index kn "know" name filtered-fields)
-              (when (false? transient?)
-                (.ensure-index kn "forget" name filtered-fields)
-                (.ensure-index kn "remember" name filtered-fields))))
-
-          (swap! rule->flow assoc rule-id (Flow. solver output-kinds output-names output-fields)))))
+              ;; make sinks
+              sinks (into-array
+                     (for [[_ clause-type clause-id name] clauses
+                           :when (not= clause-type "when")]
+                       (sink-of rule-id clause-type clause-id name var->ix)))]
+
+          (swap! rule->flow assoc rule-id (SolverFlow. solver sinks)))))
+
+    ;; set up state for outputs
+    (doseq [[rule flow] @rule->flow
+            sink (.-sinks flow)]
+      (let [kind (.-kind sink)
+            name (.-name sink)
+            fields (.-fields sink)
+            filtered-fields (into-array (filter #(not (nil? %)) fields))
+            transient? (identical? kind "know")]
+        ;; TODO get transient? from schema instead
+        (assert (not= (not transient?) (get @name->transient? name)) name)
+        (swap! name->transient? assoc name transient?)
+        (swap! kind->name->rules update-in [kind name] #(or % #{}))
+        (.ensure-index kn "know" name filtered-fields)
+        (when (false? transient?)
+          (.ensure-index kn "forget" name filtered-fields)
+          (.ensure-index kn "remember" name filtered-fields))))

     ;; TODO stratify
     (Flows. (clj->js (map first @rule->flow)) (clj->js @rule->flow) #js {} (clj->js @kind->name->rules) (clj->js @name->transient?))))
@@ -328,15 +403,15 @@

 (def kn (knowledge))

+(.get-or-create-index kn "know" "clauses" #js ["rule-id" "when|know|remember|forget" "clause-id" "name"])
+(.get-or-create-index kn "know" "clause-fields" #js ["clause-id" "constant|variable" "key" "val"])
+(.get-or-create-index kn "know" "has-agg" #js ["rule-id"])
+(.get-or-create-index kn "know" "group-by" #js ["rule-id" "var"])
+(.get-or-create-index kn "know" "agg-over" #js ["rule-id" "in-var" "agg-fun" "out-var"])
+
 (.get-or-create-index kn "know" "edge" #js ["x" "y"])
-
 (.get-or-create-index kn "know" "connected" #js ["x" "y"])
-
 (.add-facts kn "know" "edge" #js ["x" "y"] #js [#js ["a" "b"] #js ["b" "c"] #js ["c" "d"] #js ["d" "b"]])
-
-(.get-or-create-index kn "know" "clauses" #js ["rule-id" "when|know|remember|forget" "clause-id" "name"])
-
-(.get-or-create-index kn "know" "clause-fields" #js ["clause-id" "constant|variable" "key" "val"])

 (.add-facts kn "know" "clauses" #js ["rule-id" "when|know|remember|forget" "clause-id" "name"] #js [#js ["single-edge" "when" "get-edges" "edge"]
                                                                                #js ["single-edge" "know" "output-connected" "connected"]])
@@ -380,9 +455,7 @@
                                                                                #js ["-know-str" "variable" "name" "zz"]])

 (.get-or-create-index kn "know" "foo" #js ["x" "y"])
-
 (.get-or-create-index kn "know" "bar" #js ["z"])
-
 (.add-facts kn "know" "foo" #js ["x" "y"] #js [#js [1 5] #js [10 10] #js [20 15]])

 (.add-facts kn "know" "clauses" #js ["rule-id" "when|know|remember|forget" "clause-id" "name"] #js [#js ["overlap" "when" "get-foos" "foo"]
@@ -396,18 +469,28 @@
                                                                                #js ["some-interval" "variable" "in" "zz"]
                                                                                #js ["rem-bar" "variable" "z" "zz"]])

+(.add-facts kn "know" "clauses" #js ["rule-id" "when|know|remember|forget" "clause-id" "name"] #js [#js ["count-overlap" "when" "count-get-foos" "foo"]
+                                                                                #js ["count-overlap" "when" "count-some-interval" "interval"]
+                                                                                #js ["count-overlap" "remember" "count-rem-frip" "frip"]])
+
+(.add-facts kn "know" "clause-fields" #js ["clause-id" "constant|variable" "key" "val"] #js [#js ["count-get-foos" "variable" "x" "xx"]
+                                                                                #js ["count-get-foos" "variable" "y" "yy"]
+                                                                                #js ["count-some-interval" "variable" "lo" "xx"]
+                                                                                #js ["count-some-interval" "variable" "hi" "yy"]
+                                                                                #js ["count-some-interval" "variable" "in" "zz"]
+                                                                                #js ["count-rem-frip" "variable" "x" "xx"]
+                                                                                #js ["count-rem-frip" "variable" "w" "ww"]])
+
+
+(.add-facts kn "know" "has-agg" #js ["rule-id"] #js [#js ["count-overlap"]])
+
+(.add-facts kn "know" "group-by" #js ["rule-id" "var"] #js [#js ["count-overlap" "xx"]])
+
+(.add-facts kn "know" "agg-over" #js ["rule-id" "in-var" "agg-fun" "out-var"] #js [#js ["count-overlap" "zz" "count" "ww"]])
+
 (def flows (compile kn))

-(set! (.-rules flows) #js ["single-edge" "transitive-edge" "function-edge" "-function-edge" "overlap"])
-
 (enable-console-print!)
-
-(.get-or-create-index kn "know" "connected" #js ["x" "y"])
-
-(.get-or-create-index kn "remember" "str-edge" #js ["name"])
-
-(.get-or-create-index kn "forget" "str-edge" #js ["name"])
-
 (prn :running)
 (.quiesce flows kn (fn [kn] (prn :ticked kn)))

@@ -420,4 +503,6 @@
 (.get-or-create-index kn "know" "foo" #js ["x" "y"])

 (.get-or-create-index kn "know" "bar" #js ["z"])
+
+(.get-or-create-index kn "know" "frip" #js ["x" "w"])
 )


A little cleanup

A little cleanup

--- demo/sitetools/core.cljs
+++ demo/sitetools/core.cljs
@@ -1,15 +1,13 @@
 (ns sitetools.core
   (:require [clojure.string :as string]
             [goog.events :as evt]
-            [goog.history.EventType :as hevt]
             [reagent.core :as r]
             [reagent.debug :refer-macros [dbg log dev?]]
             [reagent.interop :as i :refer-macros [.' .!]])
   (:import goog.History
-           goog.history.Html5History))
-
-(when (exists? js/console)
-  (enable-console-print!))
+           [goog.history Html5History EventType]))
+
+(enable-console-print!)

 (defn rswap! [a f & args]
   ;; Like swap!, except that recursive swaps on the same atom are ok,
@@ -50,14 +48,12 @@
   (case id
     :set-content (let [page x
                        title (:title page)
-                       _ (assert (vector? (:content page)))
                        title (if title
                                (str (:title-prefix state) title)
-                               (str (:default-title state)))
-                       page (assoc page :title title)]
+                               (str (:default-title state)))]
                    (when r/is-client
                      (set! js/document.title title))
-                   (assoc state :current-page page))
+                   (assoc state :current-page page :title title))
     :set-page (let [path x
                     _ (assert (string? path))
                     ps (:pages state)
@@ -98,12 +94,13 @@
                                            (re-pattern (str page "$")) "")
                                           (string/replace #"/*$" ""))))
                     (History.)))
-        (evt/listen hevt/NAVIGATE #(when (.-isNavigation %)
-                                    (dispatch [:set-page (.-token %)])))
+        (evt/listen EventType.NAVIGATE #(when (.-isNavigation %)
+                                          (dispatch [:set-page (.-token %)])))
         (.setEnabled true))
-      (let [p (if (and page (not html5) (-> history .getToken empty?))
+      (let [token (.getToken history)
+            p (if (and page (not html5) (empty? token))
                 page
-                (.getToken history))]
+                token)]
         (dispatch [:set-page p])))))

 (defn to-relative [f]
@@ -120,16 +117,14 @@
    child])

 (defn main-content []
-  (let [comp (get-in @config [:current-page :content])]
-    (assert (vector? comp))
-    comp))
+  (get-in @config [:current-page :content]))

 ;;; Static site generation

-(defn prefix [href page]
-  (let [depth (-> #"/" (re-seq (to-relative page)) count)]
-    (str (->> "../" (repeat depth) (apply str)) href)))
+(defn base [page]
+  (let [depth (->> page to-relative (re-seq #"/") count)]
+    (->> "../" (repeat depth) (apply str))))

 (defn danger [t s]
   [t {:dangerouslySetInnerHTML {:__html s}}])
@@ -143,25 +138,23 @@
        [:meta {:charset 'utf-8}]
        [:meta {:name 'viewport
                :content "width=device-width, initial-scale=1.0"}]
-       [:base {:href (prefix "" (:page-path page-conf))}]
+       [:base {:href (-> page-conf :page-path base)}]
        [:link {:href (str css-file timestamp) :rel 'stylesheet}]
        [:title title]]
       [:body
        [:div {:id main-div} (danger :div body-html)]
        (danger :script (str "var pageConfig = "
-                            (-> page-conf clj->js js/JSON.stringify) ";"))
+                            (-> page-conf clj->js js/JSON.stringify)))
        [:script {:src main :type "text/javascript"}]]])))

 (defn gen-page [page-path conf]
   (dispatch [:set-page page-path])
   (let [conf (merge conf @config)
         b (:body conf)
-        _ (assert (vector? b))
         bhtml (r/render-component-to-string b)]
     (str "<!doctype html>\n"
          (html-template (assoc conf
                                :page-conf {:page-path page-path}
-                               :title (-> conf :current-page :title)
                                :body-html bhtml)))))

 (defn fs [] (js/require "fs"))


Use default facts operator matching for "~"

Signed-off-by: Deepak Giridharagopal <d11186354d1ef01ca06ae37d7e23e827da13e85f@puppetlabs.com>

--- src/com/puppetlabs/puppetdb/query/facts.clj
+++ src/com/puppetlabs/puppetdb/query/facts.clj
@@ -65,7 +65,6 @@
     (let [operator (string/lower-case op)]
       (cond
         (#{">" "<" ">=" "<="} operator) :numeric-comparison
-        (#{"~"} operator) :regexp-comparison
         (#{"and" "or"} operator) :connective
         :else operator))))

@@ -188,7 +187,7 @@
     (throw (IllegalArgumentException.
             (format "Value %s must be a number for %s comparison." value op)))))

-(defmethod compile-term :regexp-comparison
+(defmethod compile-term "~"
   [[op path pattern :as term]]
   {:post [(map? %)
           (string? (:where %))]}


add meta image

add meta image

--- src/pc/views/blog/ideas_are_made_with_precursor.clj
+++ src/pc/views/blog/ideas_are_made_with_precursor.clj
@@ -45,7 +45,7 @@
   {:title "Ideas are made with Precursor."
    :blurb "I'm exceedingly curious to see how people use Precursor. Recently we've been using an internal playback tool to learn about this..."
    :author "Danny"
-   :image ""
+   :image (external-cdn-path "/blog/ideas-are-made-with-precursor/lobanovskiy.gif")
    :body
    (list
     [:article


CMR-1373: Removing call to recreate indexes when the indexer starts up.

--- indexer-app/src/cmr/indexer/data/elasticsearch.clj
+++ indexer-app/src/cmr/indexer/data/elasticsearch.clj
@@ -117,7 +117,6 @@
     [this system]
     (let [context {:system system}
           conn (es/try-connect (:config this))]
-      (create-indexes context)
       (assoc this :conn conn)))

   (stop [this system]


add CLI flag to bootstrap from dns server

-d server-url will request recommended peers
and use these to bootstrap the network

--- src/block_chain/core.clj
+++ src/block_chain/core.clj
@@ -17,17 +17,23 @@
     (repl/stop-server @repl-server))
   (reset! repl-server (repl/start-server :port port)))

-(defn start! [{port :port repl-port :repl-port peer :bootstrap-peer}]
+(defn bootstrap-from-peer! [peer our-port]
+  (q/add-peer! db/db peer)
+  (pc/send-peer peer our-port)
+  (log/info "Will bootstrap from peer node: " peer)
+  (bsync/sync-if-needed! db/db peer))
+
+(defn bootstrap-from-dns-server! [url our-port]
+  (doseq [p (pc/dns-request-peers url our-port)]
+    (bootstrap-from-peer! p our-port)))
+
+(defn start! [{port :port repl-port :repl-port peer :bootstrap-peer dns-server :dns-server}]
   (log/info "****** Starting Clarke Coin *******")
   (println "Will set up initial DB at path" db/db-path)
   (reset! db/db (db/make-initial-db db/db-path))
   (http/start! port)
-  (if peer
-    (do
-      (q/add-peer! db/db peer)
-      (pc/send-peer peer port)
-      (log/info "Will bootstrap from peer node: " peer)
-      (bsync/sync-if-needed! db/db peer)))
+  (when peer (bootstrap-from-peer! peer port))
+  (when dns-server (bootstrap-from-dns-server!))
   (miner/run-miner!)
   (when repl-port (start-repl! repl-port)))

@@ -48,6 +54,8 @@
     :default nil
     :parse-fn (fn [p] {:host (first (clojure.string/split p #":"))
                        :port (last (clojure.string/split p #":"))})]
+   ["-d" "--dns-server URL" "URL for a DNS server to use for discovering initial peers"
+    :default nil]
    ["-h" "--help"]])

 (defn -main [& args]


Organizing app ns + adding extra arities for start... and load...

--- src/clj/zetawar/app.cljs
+++ src/clj/zetawar/app.cljs
@@ -9,7 +9,10 @@
    [zetawar.db :refer [e find-by qe qes qess]]
    [zetawar.game :as game]
    [zetawar.players :as players]
-   [zetawar.util :refer [breakpoint inspect]]))
+   [zetawar.util :as util :refer [breakpoint inspect]]))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; DB Accessors

 (defn root [db]
   (qe '[:find ?a
@@ -23,31 +26,21 @@
         [_ :app/game ?g]]
       db))

-(defn create-players! [{:as app-ctx :keys [conn players]}]
-  (let [factions (qess '[:find ?f
-                         :where
-                         [_  :app/game ?g]
-                         [?g :game/factions ?f]]
-                       @conn)]
-    (doseq [{:keys [faction/ai faction/color]} factions]
-      (let [player-type (if ai ::players/reference-ai ::players/human)
-            player (players/new-player app-ctx player-type color)]
-        (players/start player)
-        (swap! players assoc color player)))))
+(defn current-game-id [db]
+  (:game/id (current-game db)))

-(defn start-new-game! [{:as app-ctx :keys [conn players]} scenario-id]
-  (let [game (current-game @conn)]
-    (when-not game
-      (game/load-specs! conn))
-    (let [scenario-def (data/scenario-definitions scenario-id)
-          game-id (game/load-scenario! conn data/map-definitions scenario-def)
-          app-eid (or (some-> (root @conn) e) -101)]
-      (d/transact! conn (cond-> [{:db/id app-eid
-                                  :app/game [:game/id game-id]}]
-                          game (conj [:db.fn/retractEntity (e game)])))
-      (if players
-        (create-players! app-ctx)
-        (log/warnf "Skipping player creation for tests")))))
+(defn selected-hex [db]
+  (let [{:keys [app/selected-q app/selected-r]} (root db)]
+    [selected-q selected-r]))
+
+(defn targeted-hex [db]
+  (let [{:keys [app/targeted-q app/targeted-r]} (root db)]
+    [targeted-q targeted-r]))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Game State Encoding
+
+;; TODO: move to encoding or serialization ns?

 (defn encode-game-state [game-state]
   (let [writer (transit/writer :json)]
@@ -66,19 +59,59 @@
                                js/lzwDecode)]
     (transit/read reader transit-game-state)))

-(defn load-encoded-game-state! [{:as app-ctx :keys [conn players]} encoded-game-state]
-  (game/load-specs! conn)
-  (let [game-state (decode-game-state encoded-game-state)
-        game-id (game/load-game-state! conn
-                                       data/map-definitions
-                                       data/scenario-definitions
-                                       game-state)]
-    (d/transact! conn [{:db/id -1
-                        :app/game [:game/id game-id]}])
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Player Setup

-    (if players
-      (create-players! app-ctx)
-      (log/warnf "Skipping player creation for tests"))))
+(defn create-players! [{:as app-ctx :keys [conn players]}]
+  (let [factions (qess '[:find ?f
+                         :where
+                         [_  :app/game ?g]
+                         [?g :game/factions ?f]]
+                       @conn)]
+    (doseq [{:keys [faction/ai faction/color]} factions]
+      (let [player-type (if ai ::players/reference-ai ::players/human)
+            player (players/new-player app-ctx player-type color)]
+        (players/start player)
+        (swap! players assoc color player)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Game Setup
+
+(defn start-new-game!
+  ([{:as app-ctx :keys [conn players]} scenario-id]
+   (start-new-game! app-ctx data/map-definitions data/scenario-definitions scenario-id))
+  ([{:as app-ctx :keys [conn players]} map-definitions scenario-definitions scenario-id]
+   (let [game (current-game @conn)]
+     (when-not game
+       (game/load-specs! conn))
+     (let [scenario-def (scenario-definitions scenario-id)
+           game-id (game/load-scenario! conn map-definitions scenario-def)
+           app-eid (or (some-> (root @conn) e) -101)]
+       (d/transact! conn (cond-> [{:db/id app-eid
+                                   :app/game [:game/id game-id]}]
+                           game (conj [:db.fn/retractEntity (e game)])))
+       ;; TODO: remove test specific code
+       (if players
+         (create-players! app-ctx)
+         (log/warnf "Skipping player creation for tests"))))))
+
+(defn load-encoded-game-state!
+  ([{:as app-ctx :keys [conn players]} encoded-game-state]
+   (load-encoded-game-state! app-ctx data/map-definitions data/scenario-definitions encoded-game-state))
+  ([{:as app-ctx :keys [conn players]} map-definitions scenario-definitions encoded-game-state]
+   (game/load-specs! conn)
+   (let [game-state (decode-game-state encoded-game-state)
+         game-id (game/load-game-state! conn
+                                        map-definitions
+                                        scenario-definitions
+                                        game-state)]
+     (d/transact! conn [{:db/id -1
+                         :app/game [:game/id game-id]}])
+
+     ;; TODO: remove test specific code
+     (if players
+       (create-players! app-ctx)
+       (log/warnf "Skipping player creation for tests")))))

 ;; TODO: put URL in paste buffer
 (defn set-url-game-state! [db]
@@ -86,20 +119,3 @@
                                 (game/get-game-state db)
                                 encode-game-state)]
     (set! js/window.location.hash encoded-game-state)))
-
-(defn current-game-id [db]
-  (:game/id (current-game db)))
-
-(defn selected-hex [db]
-  (first (d/q '[:find ?q ?r
-                :where
-                [?a :app/selected-q ?q]
-                [?a :app/selected-r ?r]]
-              db)))
-
-(defn targeted-hex [db]
-  (first (d/q '[:find ?q ?r
-                :where
-                [?a :app/targeted-q ?q]
-                [?a :app/targeted-r ?r]]
-              db)))


removed eq

removed eq

--- src/clj_shoutcast/ui.clj
+++ src/clj_shoutcast/ui.clj
@@ -67,7 +67,7 @@
         url (nth urls url-index)
         player (core/get-player)
         ]
-    (doto player (.open url) .play (.setGain 0.2) (core/boost-bass true))
+    (doto player (.open url) .play (.setGain 0.2) #_(core/boost-bass true))
     (println "playing...")
     (while true
       (print "=>")


fix bug: if . in file path then everything cannot work

--- src/codeitlater/core.clj
+++ src/codeitlater/core.clj
@@ -6,9 +6,9 @@

 (defn read-json
   ([]
-   (json/read-str (slurp "./src/codeitlater/comments.json")))
+   (json/read-str (slurp "/Users/cchen386/Desktop/codeitlater/src/codeitlater/comments.json")))
   ([path]
-   (json/read-str (slurp "path/comments.json"))))
+   (json/read-str (slurp (str path "/comments.json")))))

 ;; This regex expression get help from: https://stackoverflow.com/questions/45848999/clojure-regex-delete-whitespace-in-pattern
@@ -48,14 +48,14 @@
   ([commentDict]
    (doall (for [filepath (get-all-files)
                 :when (not (.isDirectory (io/file filepath)))
-                :let [mark (get commentDict (re-find #"(?<=\w)\..*$" filepath))]
+                :let [mark (get commentDict (re-find #"(?<=\w)\.\w+$" filepath))]
                 :when mark]
             (conj (read-comments-in-file filepath mark)
                   filepath))))
   ([commentDict root]
    (doall (for [filepath (get-all-files root)
                 :when (not (.isDirectory (io/file filepath)))
-                :let [mark (get commentDict (re-find #"(?<=\w)\..*$" filepath))]
+                :let [mark (get commentDict (re-find #"(?<=\w)\.\w+$" filepath))]
                 :when mark]
             (conj (read-comments-in-file filepath mark)
                   filepath))))
@@ -68,7 +68,7 @@
                   :when (not (.isDirectory (io/file filepath)))
                   typepattern typepatterns
                   :when (re-matches (first typepattern) filepath)
-                  :let [mark (get commentDict (re-find #"(?<=\w)\..*$" filepath))]
+                  :let [mark (get commentDict (re-find #"(?<=\w)\.\w+$" filepath))]
                   :when mark]
               (conj (read-comments-in-file filepath (get commentDict (last typepattern)))
                     filepath))))))
@@ -78,7 +78,11 @@
 (defn -main [& args]
   (let [commentDict (read-json)
         [root & filetypes] args]
+    ;(println commentDict)
     ;(println args)
+    ;(println root)
     ;(println filetypes)
-    (println (read-files commentDict root filetypes)))
+    (cond filetypes (println (read-files commentDict root filetypes))
+          root (println (read-files commentDict root))
+          :else (println (read-files commentDict))))
 )


Extracted roles into two namespaces.

Extracted roles into two namespaces.

--- spec/freefrog/governance_roles_spec.clj
+++ spec/freefrog/governance_roles_spec.clj
@@ -28,7 +28,7 @@
                       {role-name {:accountabilities sample-accountabilities}})
         (g/add-role sample-anchor role-name
                     nil nil sample-accountabilities)))
-Ex
+
     (it "can add a role to a circle with name, purpose, and domains"
       (should= (assoc sample-anchor :roles {role-name {:domains sample-domains}})
         (g/add-role sample-anchor role-name


Update external_config.clj

Update external_config.clj

--- integration/dda/pallet/dda_managed_vm/app/external_config.clj
+++ integration/dda/pallet/dda_managed_vm/app/external_config.clj
@@ -17,7 +17,7 @@
   (:require
     [schema.core :as s]
     [dda.config.commons.user-env :as user-env]
-    keypin.core :refer [defkey letval] :as k]))
+    [keypin.core :refer [defkey letval] :as k]))

 (def ExternalConfigSchema
   {:provisioning {:ip s/Str


Use boot-jetty instead of boot-http in example

--- example/build.boot
+++ example/build.boot
@@ -2,15 +2,16 @@
   :resource-paths #{"resources"}
   :dependencies '[[org.clojure/clojure "1.8.0"]
                   [afrey/boot-asset-fingerprint "1.0.0-SNAPSHOT"]
-                  [pandeiro/boot-http "0.7.3" :scope "test"]])
+                  [tailrecursion/boot-jetty "0.1.3" :scope "test"]])

 (require
-  '[afrey.boot-asset-fingerprint :refer [asset-fingerprint]]
-  '[pandeiro.boot-http :refer [serve]])
+  '[afrey.boot-asset-fingerprint :refer [asset-fingerprint] :as fing]
+  '[tailrecursion.boot-jetty :as jetty]
+  '[clojure.java.io :as io])

 (deftask dev []
   (comp
     (watch)
-    (serve :port 5000 :reload true)
     (asset-fingerprint)
+    (jetty/serve :port 5000)
     (target)))


Removed old references.

Removed old references.

--- dev-resources/src/user.clj
+++ dev-resources/src/user.clj
@@ -11,10 +11,6 @@
    [clojure.java.io :as io]
    [clojure.pprint :refer [pprint]]
    [clojure.tools.namespace.repl :as repl]
-   [clojurewerkz.neocons.rest.cypher :as ncy]
-   [clojurewerkz.neocons.rest.nodes :as nn]
-   [clojurewerkz.neocons.rest.paths :as np]
-   [clojurewerkz.neocons.rest.relationships :as nrl]
    [cmr.opendap.dev :as dev]))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Remove unneeded reference to core.async

Remove unneeded reference to core.async

--- spectacles/src/spectacles/scheduler.clj
+++ spectacles/src/spectacles/scheduler.clj
@@ -4,8 +4,7 @@
             [spectacles.bet-you-miss]
             [spectacles.cyberspeed]
             [spectacles.kaleidoscope-logo]
-            [spectacles.kaleidoscope]
-            [clojure.core.async :as async]))
+            [spectacles.kaleidoscope]))

 (def sketches {:logo-countdown {:setup  spectacles.present-logo/setup
                                 :update spectacles.present-logo/update


Change conditionals to use set (#1816)

Change conditionals to use set (#1816)

--- src-cljs/frontend/components/build.cljs
+++ src-cljs/frontend/components/build.cljs
@@ -228,8 +228,7 @@
                                        (or current-tab (build-utils/default-tab build scopes))
                                        container-id)
            :on-click #(when (not= container-id selected-container-id)
-                        (when (or (= status-class :status-class/running)
-                                  (= status-class :status-class/waiting))
+                        (when (#{:status-class/running :status-class/waiting} status-class)
                           (raise! owner [:container-selected {:container-id container-id}]))
                         ((om/get-shared owner :track-event) {:event-type :container-selected
                                                              :properties {:old-container-id selected-container-id


remove prints

remove prints

--- src-cljs/frontend/components/build.cljs
+++ src-cljs/frontend/components/build.cljs
@@ -78,8 +78,6 @@
             {:keys [containers current-container-id]} container-data
             hide-pills? (or (>= 1 (count containers))
                             (empty? (remove :filler-action (mapcat :actions containers))))]
-        (println "test")
-        (println data)
         (html
          [:div.containers
           [:div.container-list


WIP remove logging.

WIP remove logging.

--- src-cljs/kixi/hecuba/tabs/programmes.cljs
+++ src-cljs/kixi/hecuba/tabs/programmes.cljs
@@ -352,7 +352,6 @@

 (defn postal-address
   ([property_data separator]
-     (println "Separator: " separator " Property Data: " property_data)
      (str/join
       separator
       (keep identity [(:address_street_two property_data)


Netto kontantstraum

Netto kontantstraum

--- src/clj_simple_chart/ssb/nettokontantstraumprognose.clj
+++ src/clj_simple_chart/ssb/nettokontantstraumprognose.clj
@@ -1,7 +1,6 @@
 (ns clj-simple-chart.ssb.nettokontantstraumprognose)

-(def data {
-           "2000" [47.596 85.120] ; https://www.regjeringen.no/contentassets/d4c7e71774cd4e688a3093d2f5aebc3f/no/pdfa/stp199920000001guldddpdfa.pdf
+(def data {"2000" [47.596 85.120] ; https://www.regjeringen.no/contentassets/d4c7e71774cd4e688a3093d2f5aebc3f/no/pdfa/stp199920000001guldddpdfa.pdf
            "2001" [160.152 188.980] ; https://www.regjeringen.no/contentassets/2bf8764f7e1246e58ad7633b02ea5e6f/no/pdfa/stp200020010001guldddpdfa.pdf
            "2002" [244.852 205.470] ; https://www.statsbudsjettet.no/Upload/Statsbudsjett_2002/dokumenter/pdf/gulbok.pdf
            "2003" [169.587 172.755] ; https://www.statsbudsjettet.no/Upload/Statsbudsjett_2003/dokumenter/pdf/gulbok.pdf


add further examples from the sc book

add further examples from the sc book

--- docs/sc-book/sc-one.clj
+++ docs/sc-book/sc-one.clj
@@ -395,3 +395,141 @@
               src (play-buf 1 houston 1 trigger (* frames (line:kr 0 1 60)))
               env (env-gen:kr (lin-env 0.01 0.96 0.01) trigger)]
           (* src env rate)))
+
+;; note how the envelope is used to stop clicking between segments. Contrast with the following
+
+(demo 5 (let [frames (num-frames houston)
+              rate   [1 1.01]
+              trigger (impulse:kr rate)
+              src (play-buf 1 houston 1 trigger (* frames (line:kr 0 1 60)))]
+          (* src rate)))
+
+;;( // speed and direction change
+;;{
+;;        var speed, direction;
+;;        speed = LFNoise0.kr(12) * 0.2 + 1;
+;;        direction = ]LFClipNoise.kr(1/3);
+;;        PlayBuf.ar(1, ~houston, (speed * direction), loop: 1);
+;;}.play
+;;)
+
+(demo 5 (let [speed     (+ 1 (* 0.2 (lf-noise0:kr 12)))
+              direction (lf-clip-noise:kr 1/3)]
+          (play-buf 1 houston (* speed direction) :loop 1)))
+
+
+;; Page 27
+
+;;( // if these haven't been used they will hold 0
+;;~kbus1 = Bus.control; // a control bus
+;;~kbus2 = Bus.control; // a control bus
+;;{
+;;        var speed, direction;
+;;        speed = In.kr(~kbus1, 1) * 0.2 + 1;
+;;        direction = In.kr(~kbus2);
+;;        PlayBuf.ar(1, ~chooston, (speed * direction), loop: 1);
+;;}.play
+;;)
+;;
+;;(
+;;// now start the controls
+;;{Out.kr(~kbus1, LFNoise0.kr(12))}.play;
+;;{Out.kr(~kbus2, LFClipNoise.kr(1/4))}.play;
+;;)
+;;// Now start the second buffer with the same control input buses,
+;;// but send it to the right channel using Out.ar(1 etc.
+;;
+;;(
+;;{
+;;        var speed, direction;
+;;        speed = In.kr(~kbus1, 1) * 0.2 + 1;
+;;        direction = In.kr(~kbus2);
+;;        Out.ar(1, PlayBuf.ar(1, ~houston, (speed * direction), loop: 1));
+;;}.play;
+;;)
+
+(def kbus1 (control-bus))
+(def kbus2 (control-bus))
+
+(defsynth src []
+  (let [speed (+ 1 (* 0.2 (in:kr kbus1 1)))
+        direction (in:kr kbus2)]
+    (out 0 (play-buf 1 chooston (* speed direction) :loop 1))))
+
+(defsynth control1 []
+  (out:kr kbus1 (lf-noise0:kr 12)))
+
+(defsynth control2 []
+  (out:kr kbus2 (lf-clip-noise:kr 1/4)))
+
+(defsynth player []
+  (let [speed (+ 1 (* 0.2 (in:kr kbus1 1)))
+        direction (in:kr kbus2)]
+    (out 1 (play-buf 1 houston (* speed direction) :loop 1))))
+
+(do
+  (src)
+  (control1)
+  (control2)
+  (player))
+
+(stop)
+
+
+;; Page 28
+
+;;~kbus3 = Bus.control;
+;;~kbus4 = Bus.control;
+;;{Out.kr(~kbus3, SinOsc.kr(3).range(340, 540))}.play;
+;;{Out.kr(~kbus4, LFPulse.kr(6).range(240, 640))}.play;
+;;SynthDef("Switch", {arg freq = 440; Out.ar(0, SinOsc.ar(freq, 0, 0.3))}).add
+;;x = Synth("Switch");
+;;x.map(\freq, ~kbus3)
+;;x.map(\freq, ~kbus4)
+
+(def kbus3 (control-bus))
+(def kbus4 (control-bus))
+
+(defsynth wave-ctl [] (out:kr kbus3 (lin-lin (sin-osc:kr 1) -1 1 140 740)))
+(defsynth pulse-ctl [] (out:kr kbus4 (lin-lin (sin-osc:kr 1) -1 1 240 640)))
+
+(defsynth switch [freq 440]
+  (out 0 (sin-osc freq 0 0.3)))
+
+(definst foo [] (sin-osc 440))
+
+(keys foo)
+(type kbus4)
+
+(:type foo)
+(keys switch)
+
+(:type switch)
+
+(:ugens :group :args :player :name :sdef :out-bus :fx-chain :type :doc)
+
+(defn node-id [node]
+  (let [id (if (inst? node) (:group node) node)]
+    (if-not (integer? id)
+      (throw (Exception. (str "The following node id is not an integer:" id))))))
+
+(defn make-foo [s]
+  (reify clojure.lang.IFn
+    (invoke [this] (str "Hello, " s))))
+
+(def s (switch))
+(def w (wave-ctl))
+(def p (pulse-ctl))
+
+(defn map-ctl [node control control-bus]
+  (let [n-id ]))
+
+(snd "/n_map" s "freq" (:id kbus4))
+(parents {})
+
+(def foo [a]
+  (if-let [b ()]))
+
+
+
+(stop)


CMR-4418: Clean up all variable associations as part of resetting providers function.

--- metadata-db-app/src/cmr/metadata_db/data/oracle/providers.clj
+++ metadata-db-app/src/cmr/metadata_db/data/oracle/providers.clj
@@ -87,7 +87,10 @@
   (reset-providers
     [db]
     (doseq [provider (p/get-providers db)]
-      (p/delete-provider db provider))))
+      (p/delete-provider db provider))
+    ;; delete the variables and vairable associations
+    (j/db-do-commands db "DELETE FROM cmr_variables")
+    (j/db-do-commands db "DELETE FROM cmr_variable_associations")))

 (comment


A little bit more clojure tabs work

A little bit more clojure tabs work

--- nightweb-android/src/clojure/net/nightweb/tabs.clj
+++ nightweb-android/src/clojure/net/nightweb/tabs.clj
@@ -26,7 +26,8 @@
               ["setSelectedTab" [android.view.View] void]
               ["getSelectedTab" [] int]
               ["animateScroll" [int] void]]
-    :exposes-methods {onLayout superOnLayout})
+    :exposes-methods {onLayout superOnLayout
+                      onScrollChanged superOnScrollChanged})
   (gen-class
     :name "net.nightweb.tabs.TabLayout"
     :extends net.nightweb.LinearLayout
@@ -107,6 +108,13 @@
           (.animateScroll this childl)
           (if (> childr viewr)
             (.animateScroll this (+ (- childr viewr) viewl)))))))
+  (defn tab-scroll-view-onScrollChanged
+    [this l t oldl oldt]
+    (.superOnScrollChanged this l t oldl oldt)
+    (let [content-view (get-state this :content-view)]
+      (if (.isHardwareAccelerated this)
+        (for [i (range 0 (.getChildCount content-view))]
+          (.invalidate (.getChildAt content-view i))))))
   (defn tab-scroll-view-addTab
     [this]
     (let [content-view (get-state this :content-view)
@@ -114,7 +122,7 @@
       (.setTitle tab-view "New Tab")
       (.setOnClickListener tab-view (on-click (.setSelectedTab this view)))
       (.addView content-view tab-view)
-      (.setActivated tab-view true)))
+      (.setActivated tab-view false)))
   (defn tab-scroll-view-setSelectedTab
     [this view]
     (let [content-view (get-state this :content-view)
@@ -156,8 +164,8 @@
   (defn tab-layout-onMeasure
     [this hspec vspec]
     (.superOnMeasure this hspec vspec)
-    (let [child-count (- (.getChildCount this) 1)
-          max (java.lang.Math/max 0 child-count)
+    (let [child-count (.getChildCount this)
+          max (java.lang.Math/max 0 (- child-count 1))
           tab-overlap (get-state this :tab-overlap)]
       (.superSetMeasuredDimension this
                                   (- (.getMeasuredWidth this) (* max tab-overlap))
@@ -166,14 +174,15 @@
     [this changed l t r b]
     (.superOnLayout this changed l t r b)
     (if (> (.getChildCount this) 1)
-      (for [i (range 1 (.getChildCount this))
-            :let [first-child (.getChildAt this 0)
-                  tab-overlap (get-state this :tab-overlap)
-                  left (- (.getRight first-child) tab-overlap)
-                  total-left (* left i)
-                  tab (.getChildAt this i)
-                  w (- (.getRight tab) (.getLeft tab))]]
-        (.layout tab total-left (.getTop tab) (+ total-left w) (.getBottom tab)))))
+      (let [tab-overlap (get-state this :tab-overlap)
+            first-child (.getChildAt this 0)
+            next-left (atom (- (.getRight first-child) tab-overlap))]
+        (for [i (range 1 (.getChildCount this))
+              :let [tab (.getChildAt this i)
+                    w (- (.getRight tab) (.getLeft tab))]]
+          (do
+            (.layout @next-left (.getTop tab) (+ @next-left w) (.getBottom tab))
+            (swap! next-left (fn [old-value] (+ old-value (- w tab-overlap)))))))))
   (defn tab-layout-getChildDrawingOrder
     [this cnt i]
     (let [selected (.getSelectedTab (get-state this :tabs))


Replace (reduce concat ,,,) with (mapcat ,,,)

The (reduce concat ,,,) pattern was causing the stack to overflow, this
was a bit tricky to debug, the symptom was that CIDER would just block
forever.

Also factored out a use of `proxy` so the class generation only needs to
happen once. All in all this version seems to perform significantly
better than the previous one.

--- src/refactor_nrepl/ns/slam/hound/search.clj
+++ src/refactor_nrepl/ns/slam/hound/search.clj
@@ -34,15 +34,17 @@

 ;; could probably be simplified

+(def jar-filter
+  (proxy [FilenameFilter] []
+    (accept [d n] (jar? (file n)))))
+
 (defn expand-wildcard
   "Expands a wildcard path entry to its matching .jar files (JDK 1.6+).
   If not expanding, returns the path entry as a single-element vector."
   [#^String path]
   (let [f (File. path)]
     (if (= (.getName f) "*")
-      (-> f .getParentFile
-          (.list (proxy [FilenameFilter] []
-                   (accept [d n] (jar? (file n))))))
+      (.. f getParentFile (list jar-filter))
       [f])))

 (defn class-or-ns-name
@@ -106,18 +108,15 @@
        (let [entries (enumeration-seq
                       (StringTokenizer. cp File/pathSeparator))
              locs (mapcat expand-wildcard entries)]
-         (reduce concat (for [loc locs]
-                          (path-class-files loc loc))))
-       ()))
-  ([cp & more]
-     (reduce #(concat %1 (scan-paths %2)) (scan-paths cp) more)))
+         (mapcat #(path-class-files % %) locs))
+       ())))

 (defn- get-available-classes
   []
-  (->> (apply scan-paths (System/getProperty "sun.boot.class.path")
-              (System/getProperty "java.ext.dirs")
-              (System/getProperty "java.class.path")
-              (map #(.getName %) (cp/classpath-jarfiles)))
+  (->> (mapcat scan-paths (concat (map #(System/getProperty %) ["sun.boot.class.path"
+                                                                "java.ext.dirs"
+                                                                "java.class.path"])
+                                  (map #(.getName %) (cp/classpath-jarfiles))))
        (remove clojure-fn-file?)
        (map symbol)))


Draw-circle. Not used anywhere ... yet.

Draw-circle. Not used anywhere ... yet.

--- src/asteroids/core.clj
+++ src/asteroids/core.clj
@@ -133,7 +133,7 @@
     (map f pol))
   )

-(declare fill-polygon draw-polygon)
+(declare fill-polygon draw-polygon fill-circle draw-circle)

 (defn create-ship []
   {:type                   :ship
@@ -163,6 +163,26 @@
    :life-colors            [(Color. 255 0 0) (Color. 255 80 75) (Color. 250 160 75) (Color. 160 160 150)]
    :collidable?            false                            ; is set to true at first movement / shooting
    })
+
+(defn create-circle
+  ([pos speed]
+   {:type           :shot
+
+    :size           (* 0.5 ship-size)
+    :shape          [[-1 -1] [1 1]]
+
+    :color          (Color. 10 200 220)
+    :paint-method   fill-circle
+
+    :position       pos
+    :speed          speed
+    :acceleration   0
+
+    :direction      0
+    :rotation-speed 0
+
+    :collidable?    true
+    }))

 (defn create-shot
   ([pos dir speed]
@@ -431,6 +451,18 @@
     (doto graphics
       (.setColor color)
       (.fillPolygon jpolygon)))
+  nil)
+
+(defn draw-circle [graphics [[x y] [x1 y1]] color]
+  (doto graphics
+    (.setColor color)
+    (.drawOval x y (- x1 x) (- y1 y)))
+  nil)
+
+(defn fill-circle [graphics [[x y] [x1 y1]] color]
+  (doto graphics
+    (.setColor color)
+    (.fillOval x y (- x1 x) (- y1 y)))
   nil)

 (defmulti paint (fn [_ {type :type}]


preserve newlines when converting clobs

preserve newlines when converting clobs

--- src/clj_oracle_namedparameters/core.clj
+++ src/clj_oracle_namedparameters/core.clj
@@ -22,7 +22,7 @@
   "Converts an Oracle CLOB to string."
   [^oracle.sql.CLOB clob]
   (with-open [rdr (java.io.BufferedReader. (.getCharacterStream clob))]
-    (apply str (line-seq rdr))))
+   (clojure.string/join "\n" (line-seq rdr))))

 (defn declob
   "If parameter is an Oracle Clob, converts it to a string."


functionality

functionality

--- src/clojure/zensols/nlparse/feature.clj
+++ src/clojure/zensols/nlparse/feature.clj
@@ -101,6 +101,7 @@
    :sent-count (count (:sents panon))
    :token-count (count tokens)
    :token-average-length (token-average-length tokens)
+   :stopword-count (->> tokens (map #(if (:stopword %) 1 0)) (reduce +))
    :is-question (= "?" (-> tokens last :text))})

 (defn token-feature-keys []
@@ -109,6 +110,7 @@
    [:sent-count 'numeric]
    [:token-count 'numeric]
    [:token-average-length 'numeric]
+   [:stopword-count 'numeric]
    [:is-question 'boolean]])


Use statement batching when inserting edges

Inserting edges one-at-a-time is quite wasteful compared to a batch insert of
all of them in one-shot.

Signed-off-by: Deepak Giridharagopal <d11186354d1ef01ca06ae37d7e23e827da13e85f@puppetlabs.com>

--- src/com/puppetlabs/cmdb/scf/storage.clj
+++ src/com/puppetlabs/cmdb/scf/storage.clj
@@ -280,12 +280,13 @@
   {:pre [(string? catalog-hash)
          (coll? edges)
          (map? resources)]}
-  (let [rows  (for [{:keys [source target relationship]} edges
-                    :let [source-hash (resource-identity-hash (resources source))
-                          target-hash (resource-identity-hash (resources target))
-                          type        (name relationship)]]
-                {:catalog catalog-hash :source source-hash :target target-hash :type type})]
-    (apply sql/insert-records :edges rows)))
+  (let [the-sql "INSERT INTO edges (catalog,source,target,type) VALUES (?,?,?,?)"
+        rows    (for [{:keys [source target relationship]} edges
+                      :let [source-hash (resource-identity-hash (resources source))
+                            target-hash (resource-identity-hash (resources target))
+                            type        (name relationship)]]
+                  [catalog-hash source-hash target-hash type])]
+    (apply sql/do-prepared the-sql rows)))

 (defn catalog-similarity-hash
   "Compute a hash for the given catalog's content


use clojure.core/update instead of clojure.core/update-in - leverage baseline Clojure 1.7

--- src/calfpath/route.clj
+++ src/calfpath/route.clj
@@ -207,7 +207,7 @@
   (as-> routes $
     (mapv (fn [spec]
             (if (contains? spec :nested)
-              (apply update-in spec [:nested] update-routes f args)
+              (apply update spec :nested update-routes f args)
               spec))
       $)
     (apply f $ args)))
@@ -246,7 +246,7 @@
       (i/expected "route spec to be a map" spec)))
   (mapv (fn [spec]
           (let [spec (if (contains? spec :nested)
-                       (apply update-in spec [:nested] update-each-route f args)
+                       (apply update spec :nested update-each-route f args)
                        spec)]
             (apply f spec args)))
     routes))
@@ -280,7 +280,7 @@
   "Given a bunch of routes, update every route (recursively) containing specified attribute with the given wrapper. The
   wrapper fn f is invoked with the old attribute value, and the returned value is updated into the route."
   [specs reference-key f]
-  (->> #(update-in % [reference-key] f)
+  (->> #(update % reference-key f)
     (make-updater reference-key)
     (update-each-route specs)))


remove clutter

remove clutter

--- src/checkmate/core.clj
+++ src/checkmate/core.clj
@@ -27,7 +27,6 @@
   (nil? (mc/find-one "lists" {:name n})))

 (defn store-new-list [l]
-  (println l)
   (let [{list-name :name items :items} l]
     (if (and
          (not-empty? list-name)


Remove helper file

Remove helper file

--- src/chenex/helpers.clj
+++ src/chenex/helpers.clj
@@ -1,6 +0,0 @@
-(ns chenex.helpers)
-
-(defmacro export
-  "Little helper fn for clojurescirpt exports"
-  [arg]
-  `(with-meta arg {:export true}))


Remove pgback dependency

Remove pgback dependency

--- src/clj/apoya/core.clj
+++ src/clj/apoya/core.clj
@@ -15,7 +15,6 @@
             [fortress.ring.server :as fortress]
             [fortress.ssl.context :as ssl-ctx]
             [fortress.util :as util]
-            [cemerick.piggieback :as pback]
             [nomad :refer [defconfig]])
   (:import [apoya.classloader JCloudsClassLoader]
            [ch.qos.logback.classic.joran JoranConfigurator]
@@ -76,8 +75,7 @@
     (schedule/setup-scheduler (get (cfg/apoya-config) :db))
     (when nrepl-port
       (log/info "Starting nrepl server at port" nrepl-port)
-      (nrepl/start-server :port nrepl-port
-                          :handler (nrepl/default-handler #'pback/wrap-cljs-repl))
+      (nrepl/start-server :port nrepl-port)
       (.mkdirs (java.io.File. "target/repl"))
       (spit "target/repl/repl-port" nrepl-port))))


Breaker Bay Grid.

Breaker Bay Grid.

--- src/clj/game/cards.clj
+++ src/clj/game/cards.clj
@@ -191,6 +191,10 @@
    "Brain Cage"
    {:effect (effect (damage :brain 1) (gain :max-hand-size 3))
     :leave-play (effect (lose :max-hand-size 3))}
+
+   "Breaker Bay Grid"
+   {:events {:pre-rez {:req (req (= (:zone card) (:zone target)))
+                       :effect (effect (rez-cost-bonus 5))}}}

    "Breaking News"
    {:effect (effect (gain :runner :tag 2)) :msg "give the Runner 2 tags"


Street Peddler fix

Street Peddler fix

--- src/clj/game/cards.clj
+++ src/clj/game/cards.clj
@@ -2567,9 +2567,8 @@
                       card))}

    "Street Peddler"
-   {:effect (effect (host card (first (:deck runner)) {:facedown true})
-                    (host (get-card state card) (second (:deck runner)) {:facedown true})
-                    (host (get-card state card) (get (:deck runner) 2) {:facedown true}))
+   {:effect (req (doseq [c (take 3 (:deck runner))]
+                   (host state side (get-card state card) c {:facedown true})))
     :abilities [{:prompt "Choose a card on Street Peddler to install"
                  :choices (req (filter #(and (not= (:type %) "Event")
                                              (<= (:cost %) (inc (:credit runner))))


Restore function core/mount-root

Restore function core/mount-root

It is referenced in env/dev/cljs/flux_challenge_reagent/dev.cljs

--- src/cljs/flux_challenge_reagent/core.cljs
+++ src/cljs/flux_challenge_reagent/core.cljs
@@ -4,7 +4,10 @@
             [flux-challenge-reagent.current-planet :as current-planet]
             [flux-challenge-reagent.sith-lords :as sith-lords]))

+(defn mount-root []
+  (r/render-component [view/dashboard] (.getElementById js/document "app")))
+
 (defn init! []
-  (r/render-component [view/dashboard] (.getElementById js/document "app"))
+  (mount-root)
   (current-planet/init-websocket-connection!)
   (sith-lords/init!))


Industrial Genomics, Skulljack.

Industrial Genomics, Skulljack.

--- src/clj/game/cards.clj
+++ src/clj/game/cards.clj
@@ -956,6 +956,10 @@
                                :effect (req (doseq [c (take 5 (:deck corp))]
                                               (move state side c :play-area)))}} card))}

+   "Industrial Genomics: Growing Solutions"
+   {:events {:pre-trash {:effect (effect (trash-cost-bonus
+                                           (count (filter #(not (:seen %)) (:discard corp)))))}}}
+
    "Infiltration"
    {:prompt "Gain 2 [Credits] or expose a card?" :choices ["Gain 2 [Credits]" "Expose a card"]
     :effect (effect (resolve-ability (if (= target "Expose a card")
@@ -1920,7 +1924,8 @@
                                        (trash state side c)))}} card))}

    "Skulljack"
-   {:effect (effect (damage :brain 1))}
+   {:effect (effect (damage :brain 1))
+    :events {:pre-trash {:effect (effect (trash-cost-bonus -1))}}}

    "Snatch and Grab"
    {:trace {:base 3 :choices {:req #(has? % :subtype "Connection")}


ENH: add data structures

ENH: add data structures

--- src/clj_prj03/core.clj
+++ src/clj_prj03/core.clj
@@ -54,3 +54,114 @@
 ; String interpolation
 (def name "Chewbacca")
 (println (str "\"Rawwwwwwwwrrrrr\" - " name))
+
+; 2.5 Maps
+;; an empty map
+{}
+;; keywords denoted by :
+{:a 1
+ :b "boring example"
+ :c []}
+
+;; associate "string-key" with the plus function
+{"string-key" +}
+
+;; maps can be nested
+{:name {:first "John" :middle "Jacob" :last "Jingleheimerschmidt"}}
+
+(get {:a 0 :b 1} :b)
+(get {:a 0 :b {:c "ho hum"}} :b)
+
+;; returns nil if key not found
+(get {:a 0 :b 1} :c)
+
+;; but you can specify a default
+(get {:a 0 :b 1} :c "UNICORNS")
+
+;; get-in allows you to dive into maps
+(get-in {:a 0 :b {:c "ho hum"}} [:b :c])
+
+;; not used often
+({:name "The Human Coffee Pot"} :name)
+
+; Keywords
+;; Look up :a in map
+(:a {:a 1 :b 2 :c 3})
+;; which is the same as:
+(get {:a 1 :b 2 :c 3} :a)
+
+;; or provide a default value with keywords
+(:d {:a 1 :b 2 :c 3} "FAERIES")
+
+;; hash-maps
+(hash-map :a 1 :b 2)
+
+; 2.6 Vectors (can be mixed-type)
+[3 2 1]
+(get [3 2 1] 0)
+(get ["a" {:name "Pugsley Winterbottom"} "c"] 1)
+(vector "creepy" "full" "moon")
+
+;; add to the end of a vector
+(conj [1 2 3] 4)
+
+; 2.7 Lists
+;; use the single quote or 'list'
+'(1 2 3 4)
+(list 1 2 3 4)
+
+;; get doesn't work
+;; instead use nth
+(nth '(100 200 300 400) 3)
+
+(conj ('1 2 3) 4) ;; added to the beginning
+
+;; Lists can be extended dynamically in either direction,
+;; but have O(n) access (similar to Linked Lists)
+
+;; Vectors on the other hand, are more like arrays: O(1) access,
+;; but have to be preallocated
+
+; 2.8 Sets
+;; Literal Notation
+#{"hannah montana" "miley cirus" 20 45}
+(conj #{:a :b} :b) ; won't add duplciate element
+
+;; getting elements (returns either the element or nil)
+(get #{:a :b} :a)
+(:a #{:a :b})
+(get #{:a :b} "hannah montana")
+
+(set [3 3 3 4 4])
+;; test if element exists in list
+(def test-set [3 3 3 4 4])
+(get (set test-set) 3)
+(get (set test-set) 5)
+
+;; hashable or sorted versions available
+(hash-set 1 1 3 1 2)
+(sorted-set :b :a :c)
+
+; 2.9 Symbols and Naming
+(def failed-movie-titles
+     ["Gone With the Moving Air"
+      "Swellfellas"])
+
+(identity 'test)
+
+; 2.10 Quoting
+failed-protagonist-names
+(first failed-protagonist-names)
+
+;; using a quote means using the symbol itself as a structure
+;; rather than the object
+'failed-protagonist-names
+(eval 'failed-protagonist-names)
+(first 'failed-protagonist-names) ;; doesn't eval
+(first ['failed-protagonist-names 'failed-antagonist-names])
+
+;; items will remain unevaluated
+'(failed-protagonist-names 0 1)
+(first '(failed-protagonist-names 0 1))
+(second '(failed-protagonist-nanmes 0 1))
+


Add future enhancement docs.

Add future enhancement docs.

--- src/cljs/todo/lib.cljs
+++ src/cljs/todo/lib.cljs
@@ -4,6 +4,14 @@
             [todo.canvas :as canvas]
             [todo.paddle :as paddle])
   (:require-macros [enfocus.macros :as em]))
+
+;; FIXME: make functions know less about various components of app
+;; FIXME: make functions in namespaces not need to be passed in elements of
+;; its own namespace
+;; FIXME: reduce state.  Pass around data structures.  Recursion??
+;; FIXME: abstract interactions so elements only need to know about
+;; the position of the element in question and then take a callback for true or false
+;; TODO: Finish tutorial (Finishing Touches)

 ;; IntervalId of setInterval, initialized to 0
 (def intervalId (atom 0))


Applied indentation change.

Applied indentation change.

--- system-int-test/test/cmr/system_int_test/bootstrap/bulk_index_test.clj
+++ system-int-test/test/cmr/system_int_test/bootstrap/bulk_index_test.clj
@@ -183,8 +183,7 @@
           invalid-prov-id "NCD4580"
           invalid-coll-id "C12-PROV1"
           err-msg1 (format "Provider: [%s] does not exist in the system" invalid-prov-id)
-          err-msg2 (format "Collection [%s] does not exist."
-                           invalid-coll-id)
+          err-msg2 (format "Collection [%s] does not exist." invalid-coll-id)
           {:keys [status errors] :as succ-stat} (bootstrap/bulk-index-collection
                                                   valid-prov-id valid-coll-id)
           ;; invalid provider and collection


Refactor route matching into one middleware

--- src/compojure/core.clj
+++ src/compojure/core.clj
@@ -12,22 +12,27 @@
             [ring.util.codec :as codec]
             [medley.core :refer [map-vals]]))

-(defn- method-matches? [method request]
-  (let [request-method (request :request-method)
-        form-method    (or (get-in request [:form-params "_method"])
-                           (get-in request [:multipart-params "_method"]))]
-    (if (and form-method (= request-method :post))
-      (.equalsIgnoreCase (name method) form-method)
-      (= method request-method))))
-
-(defn- if-method [method handler]
-  (fn [request]
-    (cond
-      (or (nil? method) (method-matches? method request))
-        (handler request)
-      (and (= :get method) (= :head (:request-method request)))
-        (if-let [response (handler request)]
-          (assoc response :body nil)))))
+(defn- form-method [request]
+  (or (get-in request [:form-params "_method"])
+      (get-in request [:multipart-params "_method"])))
+
+(defn- method-matches? [request method]
+  (or (nil? method)
+      (let [request-method (:request-method request)]
+        (case request-method
+          :head
+          (or (= method :head) (= method :get))
+          :post
+          (if-let [fm (form-method request)]
+            (.equalsIgnoreCase (name method) fm)
+            (= method :post))
+          ;else
+          (= request-method method)))))
+
+(defn- head-response [response request method]
+  (if (and (= :get method) (= :head (:request-method request)))
+    (assoc response :body nil)
+    response))

 (defn- decode-route-params [params]
   (map-vals codec/url-decode params))
@@ -39,10 +44,9 @@
   (let [path (:compojure/path request)]
     (clout/route-matches route (cond-> request path (assoc :path-info path)))))

-(defn- if-route [route handler]
-  (fn [request]
-    (if-let [params (route-matches route request)]
-      (handler (assoc-route-params request (decode-route-params params))))))
+(defn- route-request [request route]
+  (if-let [params (route-matches route request)]
+    (assoc-route-params request (decode-route-params params))))

 (defn- literal? [x]
   (if (coll? x)
@@ -125,16 +129,21 @@
   (fn [request]
     (handler (assoc request :compojure/route route-info))))

+(defn- wrap-route-matches [handler method path]
+  (fn [request]
+    (if (method-matches? request method)
+      (if-let [request (route-request request path)]
+        (some-> (handler request)
+                (head-response request method))))))
+
 (defn make-route
   "Returns a function that will only call the handler if the method and path
   match the request."
   [method path handler]
-  (let [route-info [(or method :any) (str path)]]
-    (if-method method
-      (if-route path
-        (-> (fn [request] (response/render (handler request) request))
-            (wrap-route-middleware)
-            (wrap-route-info route-info))))))
+  (-> (fn [request] (response/render (handler request) request))
+      (wrap-route-middleware)
+      (wrap-route-info [(or method :any) (str path)])
+      (wrap-route-matches method path)))

 (defn compile-route
   "Compile a route in the form `(method path bindings & body)` into a function.


Routes now accept raw regexs

Routes now accept raw regexs

--- src/compojure/http.clj
+++ src/compojure/http.clj
@@ -36,6 +36,7 @@
            (java.net URL)
            (java.util Enumeration
                       Map$Entry)
+           (java.util.regex Pattern)
            (javax.servlet ServletContext)
            (javax.servlet.http Cookie
                                HttpServlet
@@ -55,39 +56,52 @@
 (defstruct url-route
   :regex
   :keywords)
-
-(defn compile-route
-  "Turn a route string into a regex and seq of symbols."
-  [route-str]
+
+(defmulti compile-route class)
+
+(defmethod compile-route String
+  [route]
   (let [splat #"\*"
         word  #":(\w+)"
         path  #"[^:*]+"]
     (struct url-route
       (re-pattern
         (apply str
-          (parse route-str
+          (parse route
             splat "(.*?)"
             word  "([^/.,;?]+)"
             path  #(re-escape (.group %)))))
       (filter (complement nil?)
-        (parse route-str
+        (parse route
           splat :*
           word  #(keyword (.group % 1))
           path  nil)))))
-
+
+(defmethod compile-route Pattern
+  [route]
+  route)
+
+(defn- match-group-map
+  "Create a hash-map from a series of regex match groups and a collection of
+  keywords."
+  [groups keywords]
+  (reduce
+    (partial merge-with
+      #(conj (ifn vector? vector %1) %2))
+    {}
+    (map hash-map keywords (rest groups))))
+
 (defn match-route
   "Match a path against a parsed route. Returns a map of keywords and their
   matching path values."
   [route path]
-  (let [matcher (re-matcher (route :regex) path)]
-    (if (.matches matcher)
-      (reduce
-        (partial merge-with
-          #(conj (ifn vector? vector %1) %2))
-        {}
-        (map hash-map
-          (route :keywords)
-          (rest (re-groups matcher)))))))
+  (if (instance? Pattern route)
+    (let [matcher (re-matcher route path)]
+      (if (.matches matcher)
+        (vec (rest (re-groups matcher)))))
+    (let [matcher (re-matcher (route :regex) path)]
+      (if (.matches matcher)
+        (match-group-map (re-groups matcher) (route :keywords))))))

 ;;;; Handler functions ;;;;

@@ -96,18 +110,11 @@
   :route
   :function)

-(defn- first-if-one
-  "Returns the first value of a collection if there is only one element,
-  otherwise returns the collection."
-  [coll]
-  (if (rest coll)
-    coll
-    (first coll)))
-
 (defn- parse-key-value
   "Parse a key and value to make them more Clojure-friendly."
   [key val]
-  [(keyword key) (first-if-one (vec val))])
+  [(keyword key)
+   (if (rest val) val [(first val)])])

 (defn get-params
   "Creates a name/value map of all the request parameters."
@@ -142,7 +149,6 @@
   (apply hash-map
     (mapcat #(list (keyword (.getName %)) (.getValue %))
              (.getCookies request))))
-

 (defmacro handler-fn
   "Macro that wraps the body of a handler up in a standalone function."


Removed cider.nrepl :require in core.clj

--- src/hackerati_interval_web_app/core.clj
+++ src/hackerati_interval_web_app/core.clj
@@ -1,7 +1,6 @@
 ; Run test server with `lein ring server-headless`
 (ns hackerati-interval-web-app.core
-  (:require  [cider.nrepl :refer (cider-nrepl-handler)]
-             [compojure.core :refer :all]
+  (:require  [compojure.core :refer :all]
              [compojure.handler :as handler]
              [compojure.route :as route]
              [hackerati-interval-web-app.views :as views]


have to click to select a tool

have to click to select a tool

--- src-cljs/frontend/controllers/controls.cljs
+++ src-cljs/frontend/controllers/controls.cljs
@@ -279,10 +279,16 @@
         was-drawing? (get-in previous-state [:drawing :in-progress?])
         layer        (get-in current-state [:drawing :layer])]
     (cond
-     (and (not= type "touchend") (get-in current-state [:menu :open?])) (cast! [:menu-closed])
+     (and (not= type "touchend")
+          (not= button 2)
+          (get-in current-state [:menu :open?]))
+     (cast! [:menu-closed])
+
      (= :layer.type/text (:layer/type layer)) nil
+
      was-drawing? (do (d/transact! db [layer])
                       (cast! [:mouse-moved [x y]]))
+
      :else nil)))

 (defmethod control-event :text-layer-finished


CLI appears to work, basically

CLI appears to work, basically

--- src/dependable/cli.clj
+++ src/dependable/cli.clj
@@ -1,24 +1,88 @@
 (ns dependable.cli
   (:require [dependable.util :refer :all]
-            [clojure.java.io :as io])
+            [clojure.tools.cli :refer [parse-opts]]
+            [clojure.java.io :as io]
+            [clojure.string :as string]
+            [clojure.edn :as edn])
   (:gen-class))

 (def cli-options
-  ;; An option with a required argument
-  [["-c" "--config-file FILE" "Configuration file"
+  [["-p" "--project-file FILE" "Project spec file"
     :default "./dependable.edn"
     :validate [
-               #(.exists (io/as-file))
-               "Must be a regular file (which hopefully contains project info."]]
-   ;; A boolean option defaulting to nil
-   ["-h" "--help"]])
+               #(.exists (io/as-file %))
+               "Must be a regular file (which hopefully contains project info."]]])
+
+(defn update-repo! [project-config options arguments]
+  (println "goodbye"))
+
+(def subcommand-cli
+  {"update-repo"
+   {:function update-repo!
+    :cli [
+
+          ]}})
+
+(defn command-list [commands]
+  (->> ["Commands are:"
+        ""
+        (string/join \newline (map #(str "  - " %) commands))
+        ]
+       (string/join \newline)))
+
+(defn usage [options-summary & {:keys [sub-command]}]
+  (let [display-command (if sub-command
+                          sub-command
+                          "<command>")]
+    (->> [(str "Usage: dependable <options> "
+               display-command
+               " <"
+               display-command
+               "-options>")
+          ""
+          "Options are:"
+          ""
+          options-summary
+          ]
+         (string/join \newline))))
+
+(defn error-msg [errors & {:keys [sub-command]}]
+  (str "The following errors occurred while parsing commandline options"
+       (if sub-command
+         (str " for subcommand `" sub-command "`")
+         "")
+       ":\n\n"
+       (string/join \newline (map #(str "  - " errors)))))
+
+(defn exit [status msg]
+  (.println *err* msg)
+  (System/exit status))

 (defn -main [& args]
-  (parse-opts args cli-options))
-
-(:require [clojure.tools.cli :refer [parse-opts]])
-
-
-
-(defn -main [& args]
-  (println "I am a robot."))
+  (let [{:keys [options arguments errors summary]}
+        (parse-opts args (concat
+                          cli-options
+                          [["-h" "--help"]])
+                    :in-order true)]
+    (cond
+      (:help options) (exit 0 (str (usage summary)
+                                   "\n\n"
+                                   (command-list (keys subcommand-cli))))
+      errors (exit 1 (usage summary
+                            "\n"
+                            (command-list (keys subcommand-cli)))))
+    (let [global-options options
+          subcommand (first arguments)
+          subcmd-cli (get subcommand-cli subcommand)]
+      (when (nil? subcmd-cli)
+        (exit 1 (error-msg (str "Unknown command: " subcommand))))
+      (let [{:keys [options arguments errors summary]}
+            (parse-opts args (concat
+                              (:cli subcmd-cli)
+                              [["-h" "--help"]]))]
+        (cond
+          (:help options) (exit 0 (usage summary :sub-command subcommand))
+          errors (exit 1 (usage summary :sub-command subcommand)))
+        ((:function subcmd-cli)
+         (edn/read-string (slurp (:project-file global-options)))
+         options arguments)))))


change let to defn

change let to defn

--- ohack/src/ohack/core.clj
+++ ohack/src/ohack/core.clj
@@ -240,62 +240,58 @@

 ;; first, filter out all lines that don't look like guitar lines
 ;; use map-index because we need to keep ordering information
-(let [
-      guitar-tab fast-car-tab
-
-      index-line-list (filter
-                       ;; a tab line must contain "-"
-                       (fn [[_ s]] (.contains s "-"))
-                       (into {} (map-indexed vector (s/split-lines guitar-tab))))
-      index-to-line (into {} index-line-list)
-
-      ;; collect-into-consecutive will return
-      ;; a seq containing sets of 6 consecutive indexes [i_{n+0} ... i_{n+5}]
-      ;; which we assume map to sets of 6 lines within the tab file.
-      ;; in other words we are ignoring all the intervening lines, be them
-      ;; comments or dynamics or major chord labels or whatnot
-      ;; NOTE keys() here acts the same as (map first index-line-list)
-      ;; since index-line-list is not a hash-map
-      index-group-list (collect-into-consecutive (keys index-line-list))
-
-      ;; from the 6-line groups, get lines from the original index-line maps
-      ;; and sorted by increasing line indexes.
-      ;; how this works:
-      ;; 1. each set of 6 indexes gets passed to the lambda function
-      ;; 2. using index-to-line, select the 6 matching lines as a hash-map
-      ;; 3. sort by keys to ensure increasing line index order
-      ;; 4. get the vals, i.e., the lines in correct order
-      ;; now, we have a seq containing sets of 6 lines
-      sorted-grouped-line-set-list (map #(vals (sort (select-keys index-to-line %)))
-                                        ;; these will be grouped into sets of 6 lines, with indexes
-                                        (sort index-group-list))
-
-      play! (partial guitar-pick-note-sequence 80)
-      ]
-
-  ;; now we apply to everything
-  (play!
-   (apply
-    concat
-    (map (fn [play-map]
-           (let [max-beat (apply max (keys play-map))]
-             (map play-map (range max-beat))))
-         (for [line-set sorted-grouped-line-set-list]
-           ;; map over each line in the line-set, with string index
-           (apply
-            merge-with concat
-            ;; note the reverse
-            (for [[string-index tab-line] (map-indexed vector (reverse line-set))]
-              ;; now we need to parse the tab-line...
-              ;; collect each string's results into into {}
-              (into {}
-                    ;; create index -> []
-                    ;; when no string is played, for rest
-                    (map (fn [[k v]] [k (if v
-                                         [string-index v]
-                                         [])])
-                         (parse-guitar-tab-line tab-line))))))))))
-
-;; ok, listening to the version on youtube, we realize that the song is
-;; in a different key. we're not accounting for the Capo in the tab.
-;; that... is left as an exercise
+(defn play-tab [guitar-tab]
+  (let [index-line-list (filter
+                         ;; a tab line must contain "-"
+                         (fn [[_ s]] (.contains s "-"))
+                         (into {} (map-indexed vector (s/split-lines guitar-tab))))
+        index-to-line (into {} index-line-list)
+
+        ;; collect-into-consecutive will return
+        ;; a seq containing sets of 6 consecutive indexes [i_{n+0} ... i_{n+5}]
+        ;; which we assume map to sets of 6 lines within the tab file.
+        ;; in other words we are ignoring all the intervening lines, be them
+        ;; comments or dynamics or major chord labels or whatnot
+        ;; NOTE keys() here acts the same as (map first index-line-list)
+        ;; since index-line-list is not a hash-map
+        index-group-list (collect-into-consecutive (keys index-line-list))
+
+        ;; from the 6-line groups, get lines from the original index-line maps
+        ;; and sorted by increasing line indexes.
+        ;; how this works:
+        ;; 1. each set of 6 indexes gets passed to the lambda function
+        ;; 2. using index-to-line, select the 6 matching lines as a hash-map
+        ;; 3. sort by keys to ensure increasing line index order
+        ;; 4. get the vals, i.e., the lines in correct order
+        ;; now, we have a seq containing sets of 6 lines
+        sorted-grouped-line-set-list (map #(vals (sort (select-keys index-to-line %)))
+                                          ;; these will be grouped into sets of 6 lines, with indexes
+                                          (sort index-group-list))
+
+        play! (partial guitar-pick-note-sequence 80)
+        ]
+
+    ;; now we apply to everything
+    (play!
+     (apply
+      concat
+      (map (fn [play-map]
+             (let [max-beat (apply max (keys play-map))]
+               (map play-map (range max-beat))))
+           (for [line-set sorted-grouped-line-set-list]
+             ;; map over each line in the line-set, with string index
+             (apply
+              merge-with concat
+              ;; note the reverse
+              (for [[string-index tab-line] (map-indexed vector (reverse line-set))]
+                ;; now we need to parse the tab-line...
+                ;; collect each string's results into into {}
+                (into {}
+                      ;; create index -> []
+                      ;; when no string is played, for rest
+                      (map (fn [[k v]] [k (if v
+                                           [string-index v]
+                                           [])])
+                           (parse-guitar-tab-line tab-line)))))))))))
+
+(play-tab fast-car-tab)


update commentary to reflect what we need to modify

--- ohack/src/ohack/core.clj
+++ ohack/src/ohack/core.clj
@@ -121,10 +121,17 @@
 ;; Mark found this guitar-pick function
 (guitar-pick (guitar) 0 0) ;; String 0 (Low E) Fret 0 (open)

-;; then made this function to play a sequence of notes
+;; we need a function that will play a sequence of notes; notes will
+;; contain an arbitrarily long sequence of pairs of numbers denoting
+;; `string-index` `fret-value`
 (defn guitar-pick-note-sequence
   "play a sequence of notes [string fret] on instrument instrument
-  spaced by interval milliseconds"
+  spaced by interval milliseconds
+
+  interval = milliseconds between each play
+  noteseq = [[string-index-1 fret-index-1
+              string-index-2 fret-index-2 ... ]]
+  "
   [interval noteseq]
   (let [playguitar (partial guitar-pick (guitar))
         timeseq (range (now) (+ (now) (* interval (count noteseq))) interval)]


demo working playguitar320

demo working playguitar320

--- ohack/src/ohack/core.clj
+++ ohack/src/ohack/core.clj
@@ -131,3 +131,11 @@
     (doseq [[[string fret] timeval] (map vector noteseq timeseq)]
       (playguitar string fret timeval))))

+(def playguitar320
+  (partial guitar-pick-note-sequence 320))  ;; 320ms delay between picked strings
+
+;; now we can play a sequence of notes defined by
+;; [string-index fret-value]
+(playguitar320 [[0 8] [0 10] [0 12] [0 13] [0 15]]) ;;C scale on low E
+(playguitar320 [[4 1] [4 3] [4 5] [4 6] [4 8]])     ;;C scale on b string
+


Upgrade simple example shadow-cljs to 2.8.59

--- examples/simple/project.clj
+++ examples/simple/project.clj
@@ -3,7 +3,7 @@
                  [org.clojure/clojurescript  "1.10.520"
                   :exclusions [com.google.javascript/closure-compiler-unshaded
                                org.clojure/google-closure-library]]
-                 [thheller/shadow-cljs "2.8.52"]
+                 [thheller/shadow-cljs "2.8.59"]
                  [reagent  "0.9.0-rc1"]
                  [re-frame "0.11.0-rc2-SNAPSHOT"]]


Update euler1.clj

Update euler1.clj

--- euler/1/euler1.clj
+++ euler/1/euler1.clj
@@ -2,4 +2,5 @@
   (or (= 0 (mod n 3))
       (= 0 (mod n 5))))

-(reduce + (filter divisable? (range 1001)))+(reduce + (filter divisable? (range 1001)))
+;; or (map inc (range 1000)) I guess...


compile init sequence

compile init sequence

--- src/clj/algorithms_clj/macro_initiation.clj
+++ src/clj/algorithms_clj/macro_initiation.clj
@@ -387,11 +387,14 @@
             :init-sequence [println "logger init"]
             :shut-sequence [println "logger shut"]}})

-(def module-dependencies
+(defn modules->dependency-graph
+  [modules]
   (reduce-kv
     (fn [deps k v] (assoc deps k (:prerequisites v)))
     {}
     modules))
+
+(def module-dependencies (modules->dependency-graph modules))

 (defn visit
   [{:keys [graph not-visited sorted] :as dfs} node]
@@ -420,15 +423,17 @@
   )

 (defmacro compile-init-sequence
-  [dependencies]
-  (let [ordered-seq (topological-sort (eval dependencies))
+  [uneval-modules]
+  (let [modules (eval uneval-modules)
+        dependencies (modules->dependency-graph modules)
+        ordered-seq (topological-sort dependencies)
         ordered-init (map #(get-in modules [% :init-sequence]) ordered-seq)
         ordered-calls (map (fn [[f & args]] `(~f ~@args)) ordered-init)]
     `(do ~@ordered-calls)))

 (defn run-init-sequence
   []
-  (compile-init-sequence module-dependencies))
+  (compile-init-sequence modules))

 ;; --------------------------------------------------------
 ;; Example 7: Generating some code based on data structure


remove stackfiles cleanup job (done on delete/deactivate) #267

--- src/clj/swarmpit/event/rules/processing.clj
+++ src/clj/swarmpit/event/rules/processing.clj
@@ -10,18 +10,6 @@
   (match? [this type message])
   (process [this message]))

-(def cleanup-stackfiles
-  (reify Rule
-    (match? [_ type message]
-      (and (event? type)
-           (service-remove-event? message)))
-    (process [_ message]
-      (doseq [{:keys [name]} (api/stackfiles)]
-        (when (nil? (api/stack name))
-          (try
-            (api/delete-stackfile name)
-            (catch Exception _)))))))
-
 (def update-stats
   (reify Rule
     (match? [_ type message]
@@ -30,5 +18,4 @@
       (stats/store-to-cache message)
       (stats/store-to-db message))))

-(def list [cleanup-stackfiles
-           update-stats])+(def list [update-stats])


Avoid calling karma run if there is no karma server

--- plugin/src/leiningen/doo.clj
+++ plugin/src/leiningen/doo.clj
@@ -231,8 +231,9 @@
                     (doseq [js-env# non-karma-envs#]
                       (doo.core/print-envs js-env#)
                       (doo.core/run-script js-env# compiler# ~opts))
-                    (apply doo.core/print-envs karma-envs#)
-                    (doo.core/karma-run! ~opts)))))
+                    (when @karma-on?#
+                      (apply doo.core/print-envs karma-envs#)
+                      (doo.core/karma-run! ~opts))))))
             (do
               (cljs.build.api/build
                 (apply cljs.build.api/inputs ~source-paths) compiler#)


cleanup login page

cleanup login page

--- src/cljs/swarmpit/component/page_login.cljs
+++ src/cljs/swarmpit/component/page_login.cljs
@@ -14,11 +14,6 @@
 (def login-button-style
   {:marginTop "30px"})

-(def errorMessages
-  {:wordsError   "Please only use letters"
-   :numericError "Please provide a number"
-   :urlError     "Please provide a valid URL"})
-
 (defn- update-item
   "Update form item configuration"
   [k v]
@@ -30,8 +25,6 @@
      :key               "username"
      :name              "username"
      :required          true
-     :validations       "isWords"
-     :validationError   (:wordsError errorMessages)
      :floatingLabelText "Username"
      :value             value
      :onChange          (fn [_ v] (update-item :username v))}))


4clojure: implementing the recursive version of binary-tree? validator

--- src/clojure_learning/4clojure-exercises.clj
+++ src/clojure_learning/4clojure-exercises.clj
@@ -1296,10 +1296,6 @@
 ;; Each node in the tree must have a value, a left child, and a right child.
 ;; in short: binary trees are the trees which have NO MORE than 3 nodes:
 ;; -> 1 value, 1 left-branch, 1 right-branch
-;; (= true (__ '(:a (:b nil nil) nil))
-;; (= false (__ '(:a (:b nil nil)))
-;; (= false (__ [1 [2 [3 [4 false nil] nil] nil] nil])
-
 (defn binary-tree?
   [xs]
     (let [valid-node? #(= 3 (count %))
@@ -1317,34 +1313,33 @@
 ;; demo:
 (binary-tree? '(:a (:b nil nil) nil))                  ; true
 (binary-tree? [1 [2 [3 [4 false nil] nil] nil] nil])   ; false
-(binary-tree? [1 [2 nil nil] [3 nil nil] [4 nil nil]]) ; false
 (binary-tree? '(:a nil ()))                            ; false

+;; api-learning:
 (doc seq?) ; -> returns true if x implements ISeq
+(map sequential? [[] '()])  ; (true true)
 (class ()) ; EmptyList
 (seq? ()) ; true
-(empty? ()); true
 (if-let [c (seq ())] c) ; nil

-;; the recursive version follows:
-(defn binary-tree?
-  ([xs] (binary-tree? []))
-  ([xs results]
-     (if (empty? xs)
-       results
-       (if (= 3 (count xs))
-          (if (sequential? (first xs))
-              (binary-tree? (first xs) results)
-              (binary-tree? (rest xs) results))
-          (conj results false)))))
+;; the recursive version follows...interesting approach dude :)
+(defn binary-tree? [xs]
+  (letfn [(bin-node? [node]
+           (and (sequential? node) (= 3 (count (remove false? node)))))
+          (nested-nodes? [node]
+           ((comp not empty?) (filter sequential? node)))]
+  (if (bin-node? xs)
+    (if (nested-nodes? xs)
+      (if (sequential? (second xs))
+        (binary-tree? (second xs))
+        (binary-tree? (last xs)))                      ; handle right branch as well
+      true)
+    false)))
+

 (binary-tree? '(:a (:b nil nil) nil))                  ; true
 (binary-tree? [1 [2 [3 [4 false nil] nil] nil] nil])   ; false
 (binary-tree? [1 [2 nil nil] [3 nil nil] [4 nil nil]]) ; false
+(binary-tree? [ 1 nil  [2 [3 nil nil] [4 nil nil]]  ]) ; true -> handle right-branch as well
 (binary-tree? '(:a nil ()))                            ; false

-
-
-(sequential? [])  ; true
-(sequential? '()) ; true
-(sequential? :3)  ; false


Fix woff font file mime-type

Fix woff font file mime-type

The mime type for WOFF fonts was standardized in RFC 8081. Per RFC
8081 § 4.4.5, the old application/font-woff should be replaced
with font/woff.

See https://tools.ietf.org/html/rfc8081#section-4.4.5

--- ring-core/src/ring/util/mime_type.clj
+++ ring-core/src/ring/util/mime_type.clj
@@ -88,7 +88,7 @@
    "txt"      "text/plain"
    "webm"     "video/webm"
    "wmv"      "video/x-ms-wmv"
-   "woff"     "application/font-woff"
+   "woff"     "font/woff"
    "xbm"      "image/x-xbitmap"
    "xls"      "application/vnd.ms-excel"
    "xml"      "text/xml"


make :output-wrapper for multi-module builds as well

safer default, can always be disabled via :output-wrapper false

fixes #573

--- src/main/shadow/build/targets/browser.clj
+++ src/main/shadow/build/targets/browser.clj
@@ -287,10 +287,8 @@
               (assoc :modules chunks)))

         output-wrapper?
-        (let [x (get-in state [:compiler-options :output-wrapper])]
-          (if (false? x)
-            false
-            (or x (and (= :release mode) (= 1 (count modules))))))]
+        (and (= :release mode)
+             (not (false? (get-in state [:compiler-options :output-wrapper]))))]

     (-> state
         (assoc ::build/config config) ;; so the merged defaults don't get lost


No need to send feedback

No need to send feedback

--- src/lights/my_show.clj
+++ src/lights/my_show.clj
@@ -289,7 +289,7 @@
 ; Map Quneo MIDI controller, when it is connected
 (defn map-quneo
   []
-  (cues/add-midi-control-to-cue-mapping "quneo" 0 :note 36 0 7)
+  (cues/add-midi-control-to-cue-mapping "quneo" 0 :note 36 0 7 :feedback-on false)
   (show/add-midi-control-to-var-mapping
     "quneo" 0 24 :sparkle-chance :min 0.01 :max 0.2)
   (show/add-midi-control-to-var-mapping


indicate that the flags val in the list isn't used.

--- src/overtone/sc/machinery/ugen/fn_gen.clj
+++ src/overtone/sc/machinery/ugen/fn_gen.clj
@@ -69,7 +69,7 @@
                           [gcount
                            (conj seqs (repeat arg))
                            (next flags)]))
-          [greatest-count seqs] (reduce gc-seqs [1 [] expand-flags] args)]
+          [greatest-count seqs _] (reduce gc-seqs [1 [] expand-flags] args)]
       (take greatest-count (parallel-seqs seqs)))))

 (defn mk-scugen


Fixes key function used in pod watch (#1311)

--- scheduler/src/cook/kubernetes/api.clj
+++ scheduler/src/cook/kubernetes/api.clj
@@ -81,11 +81,6 @@
           (catch Exception e
             (log/error e "Error while processing callback")))))))

-(defn get-pod-name
-  "Given a V1Pod, return its name"
-  [^V1Pod pod]
-  (-> pod .getMetadata .getName))
-
 (defn get-pod-namespaced-key
   [^V1Pod pod]
   {:namespace (-> pod
@@ -141,7 +136,7 @@
       (.submit kubernetes-executor ^Callable
       (fn []
         (try
-          (handle-watch-updates all-pods-atom watch get-pod-name
+          (handle-watch-updates all-pods-atom watch get-pod-namespaced-key
                                 callbacks)
           (catch Exception e
             (log/error e "Error during watch"))


Fast fail when we get a bad request response from k8s (#1423)

--- scheduler/src/cook/kubernetes/api.clj
+++ scheduler/src/cook/kubernetes/api.clj
@@ -755,7 +755,7 @@
         true
         (catch ApiException e
           (let [code (.getCode e)
-                bad-pod-spec? (contains? #{404 422} code)]
+                bad-pod-spec? (contains? #{400 404 422} code)]
             (log/info e "Error submitting pod with name" pod-name "in namespace" namespace
                       ", code:" code ", response body:" (.getResponseBody e))
             (not bad-pod-spec?)))))


Fix leave cluster.

Fix leave cluster.

--- src/onyx/log/commands/leave_cluster.clj
+++ src/onyx/log/commands/leave_cluster.clj
@@ -41,12 +41,13 @@

 (defmethod extensions/reactions :leave-cluster
   [{:keys [args]} old new diff state]
-  (if (or (= (:id state) (get (:prepared old) (:id args)))
-          (= (:id state) (get (:accepted old) (:id args))))
-    [{:fn :abort-join-cluster
-      :args {:id (:id state)}
-      :immediate? true}]
-    (common/volunteer-via-leave? old new diff state)))
+  (cond (or (= (:id state) (get (:prepared old) (:id args)))
+            (= (:id state) (get (:accepted old) (:id args))))
+        [{:fn :abort-join-cluster
+          :args {:id (:id state)}
+          :immediate? true}]
+        (common/volunteer-via-leave? old new diff state)
+        [{:fn :volunteer-for-task :args {:id (:id state)}}]))

 (defmethod extensions/fire-side-effects! :leave-cluster
   [{:keys [message-id args]} old new {:keys [updated-watch]} state]


Removing f arg from writeTx

Removing f arg from writeTx

--- src/org/libraryweasel/ligature/core.clj
+++ src/org/libraryweasel/ligature/core.clj
@@ -31,7 +31,7 @@
   (collection-name [this])
   (readTx [this]
     "Returns a ReadTx.")
-  (writeTx [this f]
+  (writeTx [this]
     "Returns a ReadTx/WriteTx."))

 (defprotocol ReadTx


Since a function wasn't returned, it wasn't really a handler.

--- src/cmr/opendap/rest/handler/collection.clj
+++ src/cmr/opendap/rest/handler/collection.clj
@@ -58,4 +58,5 @@
   [conn-mgr]
   ;; XXX how much can we minimize round-tripping here?
   ;;     this may require creating divergent logic/impls ...
-  {:error :not-implemented})
+  (fn [request]
+    {:error :not-implemented}))


fix: prevent multiple taps on Register button from opening several tx during ENS registration

Signed-off-by: Andrey Shovkoplyas <b713972e59b8e606e23253c4a13e948139fea4d1@gmail.com>

--- src/status_im/ui/screens/ens/views.cljs
+++ src/status_im/ui/screens/ens/views.cljs
@@ -295,7 +295,7 @@
        (i18n/label :t/ens-deposit)]]]
     [button {:disabled?    (not @checked?)
              :label-style  (when (not @checked?) {:color colors/gray})
-             :on-press     #(re-frame/dispatch [::ens/register-name-pressed])}
+             :on-press     #(debounce/dispatch-and-chill [::ens/register-name-pressed] 2000)}
      (i18n/label :t/ens-register)]]])

 (defn- registration


Fix wrong method call on novelty function.

--- src/postal/client.cljs
+++ src/postal/client.cljs
@@ -129,9 +129,9 @@
 (defn novelty
   "Sends a novelty message to a server."
   ([client dest]
-   (query client dest nil {}))
-  ([client dest data]
-   (query client dest data {}))
+   (novelty client dest nil {}))
+  ([client dest data]
+   (novelty client dest data {}))
   ([client dest data opts]
    (send! client (merge {:type :novelty
                          :dest dest


Whitespace

Whitespace

--- src/postal/message.clj
+++ src/postal/message.clj
@@ -46,13 +46,13 @@
   jmsg)

 (defn add-multipart! [jmsg parts]
-  (let [;multiparts can have a number of different types: mixed,
-        ;alternative, encrypted...
-        ;The caller can use the first two entries to specify a type.
-        ;If no type is given, we default to "mixed" (for attachments etc.)
-        [multiPartType, parts] (if (keyword? (first parts))
-                                   [(name (first parts)) (rest parts)]
-                                   ["mixed" parts])
+  (let [;; multiparts can have a number of different types: mixed,
+        ;; alternative, encrypted...
+        ;; The caller can use the first two entries to specify a type.
+        ;; If no type is given, we default to "mixed" (for attachments etc.)
+        [multiPartType, parts] (if (keyword? (first parts))
+                                 [(name (first parts)) (rest parts)]
+                                 ["mixed" parts])
         mp (javax.mail.internet.MimeMultipart. multiPartType)
         fileize (fn [x]
                   (if (instance? java.io.File x) x (java.io.File. x)))]


linkin vaihto etusivulla

linkin vaihto etusivulla

--- src/publisher/core.clj
+++ src/publisher/core.clj
@@ -263,7 +263,7 @@
                                               [:p "Tällä sivustolla voit ladata, kommentoida ja jakaa Vantaan kiinteistöjen kuntotietoja. Koska aineisto on laaja, olisi hienoa, että he jotka perehtyvät johonkin, jakaisivat tekemänsä huomionsa kommentteina tällä sivustolla."]
                                               [:p "Linkkejä:"]
                                               [:ul [:li [:a {:href "https://vanvary-fi.directo.fi/tiedotteet/?x173393=3224734"} "Vanvaryn eli (Vantaan vanhempien yhdistyksen) sisäilmatoimikunta"]]
-                                               [:li [:a {:href "http://homepakolaiset.fi/terveyshaitat.html"} "Mitä ovat sisäilmaoireet Homepakolaiset-sivustolla"]]
+                                               [:li [:a {:href "http://www.hengitysliitto.fi/fi/home-ja-kosteusvauriopotilaan-oireet"} "Sisäilmaoireet Hengitysliiton sivuilla"]]
                                                [:li [:a {:href "http://www.sirpakauppinen.fi/node/970"} "Mikrobien toksiinit eli solumyrkyt"]]
                                                [:li [:a {:href "http://www.sirpakauppinen.fi/node/914"} "Koulukapinan ABC"]]
                                                [:li [:a {:href "http://www.sisailmayhdistys.fi/Perustietoa-sisailmasta/Mista-apua-sisailmaongelmiin"} "Sisäilmayhdistys"]]