[#532] Implement more partial queries

[#532] Implement more partial queries

--- backend/src/akvo/lumen/lib/pivot_impl.clj
+++ backend/src/akvo/lumen/lib/pivot_impl.clj
@@ -76,16 +76,42 @@
      :rows count}))

 (defn apply-empty-category-query [conn dataset query filter-str]
-  {:rows []
-   :columns []})
+  (let [rows (rest (jdbc/query conn
+                               [(format "SELECT %s, count(rnum) FROM %s WHERE %s GROUP BY 1 ORDER BY 1"
+                                        (get (:row-column query) "columnName")
+                                        (:table-name dataset)
+                                        filter-str)]
+                               {:as-arrays? true}))]
+    {:columns [{"type" "text"
+                "title" (get (:row-column query) "title")}
+               {"type" "number"
+                "title" "Total"}]
+     :rows rows}))

 (defn apply-empty-row-query [conn dataset query filter-str]
-  {:rows []
-   :columns []})
+  (let [counts (map second
+                    (rest (jdbc/query conn
+                                      [(format "SELECT %s, count(rnum) FROM %s WHERE %s GROUP BY 1 ORDER BY 1"
+                                               (get (:category-column query) "columnName")
+                                               (:table-name dataset)
+                                               filter-str)]
+                                      {:as-arrays? true})))
+        categories (unique-values conn (:table-name dataset) (:category-column query) filter-str)]
+    {:columns (cons {"title" ""
+                     "type" "text"}
+                    (map (fn [category]
+                           {"title" category
+                            "type" "number"})
+                         categories))
+     :rows [(cons "Total" counts)]}))

 (defn apply-empty-value-query [conn dataset query filter-str]
-  {:rows []
-   :columns []})
+  (apply-pivot conn
+               dataset
+               (assoc query
+                      :value-column {"columnName" "rnum"}
+                      "aggregation" "count")
+               filter-str))

 (defn apply-query [conn dataset query filter-str]
   (cond
@@ -151,7 +177,40 @@
                 "aggregation" "count"
                 "filters" []})

-  (query tenant-conn dataset-id empty-q)
+  (def empty-category-q
+    {"categoryColumn" nil
+     "rowColumn" "c4"
+     "valueColumn" nil
+     "aggregation" "count"
+     "filters" [{"column" "c2"
+                 "columnType" "text"
+                 "operation" "keep"
+                 "strategy" "is"
+                 "value" "Ethiopia"}]})
+
+  (def empty-row-q
+    {"categoryColumn" "c16"
+     "rowColumn" nil
+     "valueColumn" nil
+     "aggregation" "count"
+     "filters" [{"column" "c2"
+                 "columnType" "text"
+                 "operation" "keep"
+                 "strategy" "is"
+                 "value" "Ethiopia"}]})
+
+  (def empty-value-q
+    {"categoryColumn" "c16"
+     "rowColumn" "c4"
+     "valueColumn" nil
+     "aggregation" "count"
+     "filters" [{"column" "c2"
+                 "columnType" "text"
+                 "operation" "keep"
+                 "strategy" "is"
+                 "value" "Ethiopia"}]})
+
+  (query tenant-conn dataset-id empty-value-q)

   (unique-categories tenant-conn dataset-id)


Add missing require

Add missing require

--- backend/src/circle/backend/action/tag.clj
+++ backend/src/circle/backend/action/tag.clj
@@ -1,5 +1,6 @@
 (ns circle.backend.action.tag
   (:use [circle.backend.action :only (defaction)])
+  (:use [circle.util.except :only (throw-if-not)])
   (:require [circle.backend.nodes :as nodes])
   (:require [circle.backend.ec2-tag :as tag]))


added template name to the exception

added template name to the exception

--- src/selmer/validator.clj
+++ src/selmer/validator.clj
@@ -65,9 +65,10 @@
    (loop [tags [], ch (read-char rdr), line 1]
      (if ch
        (if (open-tag? ch rdr)
-         (let [tag-info (try (read-tag-info rdr)
-                          (catch Exception ex
-                            (exception "Error parsing tag on line " line ": " (.getMessage ex))))]
+         (let [tag-info
+               (try (read-tag-info rdr)
+                 (catch Exception ex
+                   (exception "Error parsing tag on line " line ": " (.getMessage ex) " for template " template)))]
            (recur (valide-tag template line tags tag-info) (read-char rdr) line))
          (recur tags (read-char rdr) (if (= \newline ch) (inc line) line)))
        tags))))


Fix RDF file inference for resource-repo

--- src/rdf-repository/grafter/rdf/repository.clj
+++ src/rdf-repository/grafter/rdf/repository.clj
@@ -275,7 +275,7 @@
   ([repo-or-data & data]
    (let [repo (if (instance? Repository repo-or-data)
                 repo-or-data
-                (rdf/add (sail-repo) (rdf/statements (io/resource repo-or-data))))]
+                (rdf/add (sail-repo) (statements-with-inferred-format (io/resource repo-or-data))))]
      (apply fixture-repo repo (map io/resource data)))))

 (defn repo


added partition-test

added partition-test

--- test/datasplash/api_test.clj
+++ test/datasplash/api_test.clj
@@ -124,6 +124,18 @@
       (ds/run-pipeline p))
     (let [res (into #{} (read-file (first (glob-file pt-cond-test))))]
       (is (= res #{2 3 4 5 6})))))
+
+(deftest partition-test
+  (let [p (ds/make-pipeline [])
+        input (ds/generate-input [1 2 3 4 5 6 7 8 9] p)
+        pcolls (ds/partition-by (fn [e _] (if (odd? e) 1 0))
+                                2
+                                {:name :partition}
+                                input)
+        [even-coll odd-coll] (.getAll pcolls)]
+    (-> (PAssert/that even-coll) (.containsInAnyOrder '(2 4 6 8)))
+    (-> (PAssert/that odd-coll) (.containsInAnyOrder '(1 3 5 7 9)))
+    (ds/run-pipeline p)))

 (deftest side-inputs-test
   (with-files [side-test]


Document render-component

Document render-component

--- test/demo.cljs
+++ test/demo.cljs
@@ -34,12 +34,13 @@
                  (map #(% defs) names))))

 (def builtins ["def" "defn" "ns" "atom" "let" "if" "when"
-               "cond" "merge"])
+               "cond" "merge" "assoc" "swap!" "reset!"])

 (defn syntaxify [src]
-  (let [str-p "\"[^\"]*\""
-        keyw-p ":[^\\][(){} \\t\\n]+"
-        res-p (string/join "\\b|" builtins)
+  (let [sep "\\][(){} \\t\\n"
+        str-p "\"[^\"]*\""
+        keyw-p (str ":[^" sep "]+")
+        res-p (string/join "|" (map #(str % "(?=[" sep "])") builtins))
         any-p ".|\\n"
         patt (re-pattern (str "("
                               (string/join ")|(" [str-p keyw-p res-p any-p])
@@ -56,11 +57,14 @@
   [:pre (syntaxify (src-for-names defs))])

 (defn demo-component [props]
-  [:div.example
-   [:h3 "Example"]
-   [(:comp props)]
-   [:h3 "Source"]
-   [src-for props]])
+  [:div
+   (when (:comp props)
+     [:div.demo-example
+      [:h3.demo-heading "Example"]
+      [(:comp props)]])
+   [:div.demo-source
+    [:h3.demo-heading "Source"]
+    [src-for props]]])

 (defn simple-component []
   [:div
@@ -88,7 +92,8 @@

 (defn counting-component []
   [:div
-   "The atom " [:code "click-count"] " has value: " @click-count ". "
+   "The atom " [:code "click-count"] " has value: "
+   @click-count ". "
    [:input {:type "button"
             :value "Click me!"
             :on-click #(swap! click-count inc)}]])
@@ -99,9 +104,13 @@
       [:div
        [:p "The value of " [:code "val"] " is now: " @val]
        [:p "Change it: "
-        [:input {:type "text"
-                 :value @val
-                 :on-change #(reset! val (-> % .-target .-value))}]]])))
+        [:input
+         {:type "text" :value @val
+          :on-change #(reset! val (-> % .-target .-value))}]]])))
+
+(defn render-simple []
+  (cloact/render-component [simple-component]
+                           (.-body js/document)))

 (defn calc-bmi [{:keys [height weight bmi] :as params}]
   (let [h (/ height 100)]
@@ -114,11 +123,11 @@
 (defn set-bmi [key val clear]
   (swap! bmi-data #(calc-bmi (merge % {key val, clear nil}))))

-(defn slider [{:keys [value key clear min max]}]
+(defn slider [{:keys [value min max param clear]}]
   [:div
    [:input {:type "range" :min min :max max :value value
             :style {:width "100%"}
-            :on-change #(set-bmi key (-> % .-target .-value)
+            :on-change #(set-bmi param (-> % .-target .-value)
                                  (or clear :bmi))}]])

 (defn bmi-component []
@@ -129,16 +138,18 @@
                           (< bmi 30) ["orange" "overweight"]
                           :else ["red" "obese"])]
     [:div
+     [:h3 "BMI calculator"]
      [:div
       "Height: " (int height) "cm"
-      [slider {:value height :min 100 :max 220 :key :height}]]
+      [slider {:value height :min 100 :max 220 :param :height}]]
      [:div
       "Weight: " (int weight) "kg"
-      [slider {:value weight :min 50 :max 200 :key :weight}]]
+      [slider {:value weight :min 30 :max 150 :param :weight}]]
      [:div
       "BMI: " (int bmi) " "
       [:span {:style {:color color}} diagnose]
-      [slider {:value bmi :min 10 :max 50 :key :bmi :clear :weight}]]]))
+      [slider {:value bmi :min 10 :max 50 :param :bmi
+               :clear :weight}]]]))

 (defn intro []
   [:div
@@ -172,15 +183,15 @@
    [:p "The easiest way to manage state in Cloact is to use Cloact's
    own version of " [:code "atom"] ". It works exactly like the one in
    clojure.core, except that it keeps track of every time it is
-   deref'ed. Any component that uses the atom is automagically
-   re-rendered."]
+   deref'ed. Any component that uses an " [:code "atom"]" is automagically
+   re-rendered when its value changes."]

    [:p "Let's demonstrate that with a simple example:"]
    [demo-component {:comp counting-component
                     :defs [:ns :click-count :counting-component]}]

    [:p "Sometimes you may want to maintain state locally in a
-   component. That is very easy to do with an " [:code "atom"] " as well."]
+   component. That is easy to do with an " [:code "atom"] " as well."]

    [:p "Here is an example of that:"]
    [demo-component {:comp local-state
@@ -193,18 +204,39 @@
    created components, without resorting to React's lifecycle
    events."]])

+(defn essential-api []
+  [:div
+   [:h2 "Essential API"]
+
+   [:p "Cloact supports (almost) the entire React API, but there is
+   really only one entry-point that is necessary for most
+   applications: " [:code "cloact.core/render-component"] "."]
+
+   [:p "It takes too arguments: a component, and a DOM node. For
+   example, splashing the very first example all over the page would
+   look like this:"]
+
+   [demo-component {:defs [:ns :simple-component :render-simple]}]])

 (defn bmi-demo []
   [:div
-   [:h2 "Simple BMI calculator"]
+   [:h2 "Putting it all together"]
+
+   [:p "Here is a slightly less contrived example: a simple BMI
+   calculator."]
+
+   [:p "Data is kept in a single " [:code "cloact.core/atom"] ": a map
+   with height, weight and BMI as keys."]
+
    [demo-component {:comp bmi-component
                     :defs [:ns :calc-bmi :bmi-data :set-bmi :slider
                            :bmi-component]}]])

 (defn demo []
-  [:div
+  [:div.cloact-demo
    [:h1 "This will become a demo"]
    [intro]
    [managing-state]
+   [essential-api]
    [bmi-demo]
    [:p "WIP"]])


Working on getting rid of midje.

Working on getting rid of midje.

--- test/com/lemondronor/turboshrimp/navdata_test.clj
+++ test/com/lemondronor/turboshrimp/navdata_test.clj
@@ -5,10 +5,8 @@
             [com.lemonodor.xio :as xio]
             [criterium.core :as criterium]
             [gloss.io]
-            [midje.sweet :refer :all]
-            [midje.util :refer :all]
-            [com.lemondronor.turboshrimp.navdata :refer :all]
-            [com.lemondronor.turboshrimp :refer :all])
+            [com.lemondronor.turboshrimp.navdata :as navdata]
+            [com.lemondronor.turboshrimp :as ardrone])
   (:import (java.net InetAddress DatagramSocket)
            (java.nio ByteOrder)))

@@ -84,22 +82,22 @@
 (def host (InetAddress/getByName "192.168.1.1"))
 (def port 5554)
 (def socket (DatagramSocket. ))
-(def packet (new-datagram-packet (byte-array 2048) host port))
+(def packet (navdata/new-datagram-packet (byte-array 2048) host port))

 (deftest navdata-unit-tests
-  (facts "about new-datagram-packet"
-    (fact "getPort/getAddress/getData"
+  (testing "about new-datagram-packet"
+    (testing "getPort/getAddress/getData"
       (let [data (byte-array (map byte [1 0 0 0]))
-            ndp (new-datagram-packet data host port)]
-        (.getPort ndp) => port
-        (.getAddress ndp) => host
-        (.getData ndp) => data)))
-
-  (facts "about parse-nav-state"
-    (fact "parse-nav-state"
+            ndp (navdata/new-datagram-packet data host port)]
+        (is (= (.getPort ndp) port))
+        (is (= (.getAddress ndp) host))
+        (is (= (.getData ndp) data)))))
+
+  (testing "about parse-nav-state"
+    (testing "parse-nav-state"
       (let [state 260048080
-            result (parse-nav-state state)
+            result (navdata/parse-nav-state state)
             {:keys [flying video vision control altitude-control
                     user-feedback command-ack camera travelling
                     usb demo bootstrap motors communication
@@ -108,514 +106,516 @@
                     pic-version atcodec-thread navdata-thread
                     video-thread acquisition-thread ctrl-watchdog
                     adc-watchdog com-watchdog emergency]} result]
-        flying => :landed
-        video => :off
-        vision => :off
-        control => :euler-angles
-        altitude-control => :on
-        user-feedback => :off
-        command-ack => :received
-        camera => :ready
-        travelling => :off
-        usb => :not-ready
-        demo => :on
-        bootstrap => :off
-        motors => :ok
-        communication => :ok
-        software => :ok
-        battery => :ok
-        emergency-landing => :off
-        timer => :not-elapsed
-        magneto => :ok
-        angles => :ok
-        wind => :ok
-        ultrasound => :ok
-        cutout => :ok
-        pic-version => :ok
-        atcodec-thread => :on
-        navdata-thread => :on
-        video-thread => :on
-        acquisition-thread => :on
-        ctrl-watchdog => :ok
-        adc-watchdog => :ok
-        com-watchdog => :ok
-        emergency => :ok)))
-
-  (fact "which-option-type"
-    (which-option-type 0) => :demo
-    (which-option-type 16) => :vision-detect
-    (which-option-type 2342342) => nil)
-
-  (facts "about parse-control-state"
-    (fact "parse-control-state"
+        (is (= flying :landed))
+        (is (= video :off))
+        (is (= vision :off))
+        (is (= control :euler-angles))
+        (is (= altitude-control :on))
+        (is (= user-feedback :off))
+        (is (= command-ack :received))
+        (is (= camera :ready))
+        (is (= travelling :off))
+        (is (= usb :not-ready))
+        (is (= demo :on))
+        (is (= bootstrap :off))
+        (is (= motors :ok))
+        (is (= communication :ok))
+        (is (= software :ok))
+        (is (= battery :ok))
+        (is (= emergency-landing :off))
+        (is (= timer :not-elapsed))
+        (is (= magneto :ok))
+        (is (= angles :ok))
+        (is (= wind :ok))
+        (is (= ultrasound :ok))
+        (is (= cutout :ok))
+        (is (= pic-version :ok))
+        (is (= atcodec-thread :on))
+        (is (= navdata-thread :on))
+        (is (= video-thread :on))
+        (is (= acquisition-thread :on))
+        (is (= ctrl-watchdog :ok))
+        (is (= adc-watchdog :ok))
+        (is (= com-watchdog :ok))
+        (is (= emergency :ok)))))
+
+  (testing "which-option-type"
+    (is (= (navdata/which-option-type 0) :demo))
+    (is (= (navdata/which-option-type 16) :vision-detect))
+    (is (= (navdata/which-option-type 2342342)) nil))
+
+  (testing "about parse-control-state"
+    (testing "parse-control-state"
       (let [bb (doto (gloss.io/to-byte-buffer b-demo-control-state)
                             (.order ByteOrder/LITTLE_ENDIAN))
             control-state (.getInt bb)]
-        (parse-control-state control-state) => :landed)))
-
-  (facts "about parse-demo-option"
-    (fact "parse-demo-option"
+        (is (= (navdata/parse-control-state control-state) :landed)))))
+
+  (testing "about parse-demo-option"
+    (testing "parse-demo-option"
       (let [bb (doto (gloss.io/to-byte-buffer
                       ;; Skip past the option ID and option size.
                       (drop 4 b-demo-option))
                  (.order ByteOrder/LITTLE_ENDIAN))
-            option (parse-demo-option bb)]
-        (:control-state option) => :landed
-        (:battery-percentage option) => 100
-        option => (contains {:theta (float -1.075) })
-        option => (contains {:phi (float -2.904) })
-        option => (contains {:psi (float -0.215) })
-        option => (contains {:altitude (float 0.0) })
-        option => (contains {:velocity {:x (float 0.0)
-                                        :y (float 0.0)
-                                        :z (float 0.0)}})
-        option => (contains {:detect-camera-type :roundel-under-drone }))))
-
-  (facts "about parse-vision-detect-option"
+            option (navdata/parse-demo-option bb)]
+        (is (= (:control-state option) :landed))
+        (is (= (:battery-percentage option) 100))
+        (is (= (:theta option) (float -1.075)))
+        (is (= (:phi option) (float -2.904)))
+        (is (= (:psi option) (float -0.215)))
+        (is (= (:altitude option) 0.0))
+        (is (= (:velocity option) {:x 0.0 :y 0.0 :z 0.0}))
+        (is (= (:detect-camera-type option) :roundel-under-drone)))))
+
+  (testing "about parse-vision-detect-option"
     (let [detections
-          (parse-vision-detect-option
+          (navdata/parse-vision-detect-option
            (doto (gloss.io/to-byte-buffer
                   ;; Skip past the option ID and option size.
                   (drop 4
                         b-vision-detect-option))
              (.order ByteOrder/LITTLE_ENDIAN)))]
-      (count detections) => 2
-      (fact "first detection"
+      (is (= (count detections) 2))
+      (testing "first detection"
         (let [det (nth detections 0)]
-          (:type det) => :vertical-deprecated
-          (:xc det) => 1
-          (:yc det) => 1
-          (:width det) => 1
-          (:height det) => 1
-          (:dist det) => 1
-          (:orientation-angle det) => -1075.0
-          (:camera-source det) => :vertical
-          (:translation det) => {:x 0.0 :y 0.0 :z 0.0}
-          (:rotation det) => {:m11 0.0, :m12 0.0, :m13 0.0,
-                              :m21 0.0, :m22 0.0, :m23 0.0,
-                              :m31 0.0, :m32 0.0, :m33 0.0}))
-      (fact "second detection"
+          (is (= (:type det) :vertical-deprecated))
+          (is (= (:xc det) 1))
+          (is (= (:yc det) 1))
+          (is (= (:width det)) 1)
+          (is (= (:height det) 1))
+          (is (= (:dist det) 1))
+          (is (= (:orientation-angle det) -1075.0))
+          (is (= (:camera-source det) :vertical))
+          (is (= (:translation det) {:x 0.0 :y 0.0 :z 0.0}))
+          (is (= (:rotation det)
+                 {:m11 0.0, :m12 0.0, :m13 0.0,
+                  :m21 0.0, :m22 0.0, :m23 0.0,
+                  :m31 0.0, :m32 0.0, :m33 0.0}))))
+      (testing "second detection"
         (let [det (nth detections 1)]
-          (:type det) => :horizontal-drone-shell
-          (:xc det) => 2
-          (:yc det) => 2
-          (:width det) => 2
-          (:height det) => 2
-          (:dist det) => 2
-          (:orientation-angle det) => -1075.0
-          (:camera-source det) => :vertical-hsync
-          (:translation det) => {:x 0.0 :y 0.0 :z 0.0}
-          (:rotation det) => {:m11 0.0, :m12 0.0, :m13 0.0,
-                              :m21 0.0, :m22 0.0, :m23 0.0,
-                              :m31 0.0, :m32 0.0, :m33 0.0}))))
-
-  (facts "about parse-navdata"
-    (fact "parse-navdata"
-      (fact "hand-crafted input"
-        (let [navdata (parse-navdata nav-input)]
-          navdata => (contains {:header 0x55667788})
-          navdata => (contains {:seq-num 870})
-          navdata => (contains {:vision-flag false})
-          (fact "state"
+          (is (= (:type det) :horizontal-drone-shell))
+          (is (= (:xc det) 2))
+          (is (= (:yc det) 2))
+          (is (= (:width det) 2))
+          (is (= (:height det) 2))
+          (is (= (:dist det) 2))
+          (is (= (:orientation-angle det) -1075.0))
+          (is (= (:camera-source det) :vertical-hsync))
+          (is (= (:translation det) {:x 0.0 :y 0.0 :z 0.0}))
+          (is (= (:rotation det) {:m11 0.0, :m12 0.0, :m13 0.0,
+                                  :m21 0.0, :m22 0.0, :m23 0.0,
+                                  :m31 0.0, :m32 0.0, :m33 0.0}))))))
+
+  (testing "about parse-navdata"
+    (testing "parse-navdata"
+      (testing "hand-crafted input"
+        (let [navdata (navdata/parse-navdata nav-input)]
+          (is (= (:header navdata) 0x55667788))
+          (is (= (:seq-num navdata) 870))
+          (is (= (:vision-flag navdata) false))
+          (testing "state"
             (let [state (:state navdata)]
-              state => (contains {:battery :ok})
-              state => (contains {:flying :landed})))
-          (fact "demo"
+              (is (= (:battery state) :ok))
+              (is (= (:flying state) :landed))))
+          (testing "demo"
             (let [demo (:demo navdata)]
-              (:control-state demo) => :landed
-              (:battery-percentage demo) => 100
-              demo => (contains {:theta (float -1.075) })
-              demo => (contains {:phi (float -2.904) })
-              demo => (contains {:psi (float -0.215) })
-              demo => (contains {:altitude (float 0.0) })
-              demo => (contains {:velocity
-                                 {:x (float 0.0)
-                                  :y (float 0.0)
-                                  :z (float 0.0)}}))))))))
+              (is (= (:control-state demo) :landed))
+              (is (= (:battery-percentage demo) 100))
+              (is (= (:theta demo) (float -1.075)))
+              (is (= (:phi demo) (float -2.904)))
+              (is (= (:psi demo) (float -0.215)))
+              (is (= (:altitude demo) 0.0))
+              (is (= (:velocity demo) {:x 0.0 :y 0.0 :z 0.0})))))))))

 (defn test-adc-data-frame-option [navdata]
-  (fact "adc-data-frame option"
+  (testing "adc-data-frame option"
     (let [adc (:adc-data-frame navdata)]
-      (:version adc) => 0
-      (:data-frame adc) => (repeat 32 0))))
+      (is (= (:version adc) 0))
+      (is (= (:data-frame adc) (repeat 32 0))))))

 (defn test-gps-option [navdata]
-  (fact "gps option"
+  (testing "gps option"
     (let [gps (:gps navdata)]
-      (:latitude gps) => 34.0905016
-      (:longitude gps) => -118.2766877
-      (:elevation gps) => 122.64
-      (:hdop gps) => 1.0
-      (:data-available gps) => 7
-      (:zero-validated gps) => 1
-      (:wpt-validated gps) => 0
-      (:lat0 gps) => 34.0905016
-      (:lon0 gps) => -118.2766877
-      (:lat-fuse gps) => 34.0904833
-      (:lon-fuse gps) => -118.2766982
-      (:gps-state gps) => 1
-      (:x-traj gps) => 0.0
-      (:x-ref gps) => 0.0
-      (:y-traj gps) => 0.0
-      (:y-ref gps) => 0.0
-      (:theta-p gps) => 0.0
-      (:phi-p gps) => 0.0
-      (:theta-i gps) => 0.0
-      (:phi-i gps) => 0.0
-      (:theta-d gps) => 0.0
-      (:phi-d gps) => 0.0
-      (:vdop gps) => 0.0
-      (:pdop gps) => 0.0
-      (:speed gps) => (roughly 0.1)
-      (:last-frame-timestamp gps) => 2.409591
-      (:degree gps) => (roughly 141.01)
-      (:degree-mag gps) => 0.0
-      (:ehpe gps) => (roughly 8.26)
-      (:ehve gps) => (roughly 0.42999998)
-      (:c-n0 gps) => 28.0
-      (:num-satellites gps) => 9
-      (:channels gps) => [{:cn0 26, :sat 10}
-                          {:cn0 21, :sat 5}
-                          {:cn0 27, :sat 8}
-                          {:cn0 17, :sat 3}
-                          {:cn0 18, :sat 13}
-                          {:cn0 32, :sat 7}
-                          {:cn0 23, :sat 9}
-                          {:cn0 9, :sat 27}
-                          {:cn0 19, :sat 19}
-                          {:cn0 29, :sat 28}
-                          {:cn0 26, :sat 30}
-                          {:cn0 0, :sat 138}]
-      (:gps-plugged gps) => 1
-      (:ephemeris-status gps) => 73
-      (:vx-traj gps) => 0.0
-      (:vy-traj gps) => 0.0
-      (:firmware-status gps) => 1)))
+      (are [x y] (= x y)
+           (:latitude gps) 34.0905016
+           (:longitude gps) -118.2766877
+           (:elevation gps) 122.64
+           (:hdop gps) 1.0
+           (:data-available gps) 7
+           (:zero-validated gps) 1
+           (:wpt-validated gps) 0
+           (:lat0 gps) 34.0905016
+           (:lon0 gps) -118.2766877
+           (:lat-fuse gps) 34.0904833
+           (:lon-fuse gps) -118.2766982
+           (:gps-state gps) 1
+           (:x-traj gps) 0.0
+           (:x-ref gps) 0.0
+           (:y-traj gps) 0.0
+           (:y-ref gps) 0.0
+           (:theta-p gps) 0.0
+           (:phi-p gps) 0.0
+           (:theta-i gps) 0.0
+           (:phi-i gps) 0.0
+           (:theta-d gps) 0.0
+           (:phi-d gps) 0.0
+           (:vdop gps) 0.0
+           (:pdop gps) 0.0
+           (:speed gps) (float 0.1)
+           (:last-frame-timestamp gps) 2.409591
+           (:degree gps) (float 141.01)
+           (:degree-mag gps) 0.0
+           (:ehpe gps) (float 8.26)
+           (:ehve gps) (float 0.42999998)
+           (:c-n0 gps) 28.0
+           (:num-satellites gps) 9
+           (:channels gps) [{:cn0 26, :sat 10}
+                            {:cn0 21, :sat 5}
+                            {:cn0 27, :sat 8}
+                            {:cn0 17, :sat 3}
+                            {:cn0 18, :sat 13}
+                            {:cn0 32, :sat 7}
+                            {:cn0 23, :sat 9}
+                            {:cn0 9, :sat 27}
+                            {:cn0 19, :sat 19}
+                            {:cn0 29, :sat 28}
+                            {:cn0 26, :sat 30}
+                            {:cn0 0, :sat 138}]
+           (:gps-plugged gps) 1
+           (:ephemeris-status gps) 73
+           (:vx-traj gps) 0.0
+           (:vy-traj gps) 0.0
+           (:firmware-status gps) 1))))

 (defn test-trackers-send-option [navdata]
-  (fact "trackers-send option"
+  (testing "trackers-send option"
     (let [ts (:trackers-send navdata)]
-      (:locked ts) => (repeat 30 0)
-      (:point ts) => (repeat 30 {:x 0 :y 0}))))
+      (is (= (:locked ts) (repeat 30 0)))
+      (is (= (:point ts) (repeat 30 {:x 0 :y 0}))))))

 (defn test-vision-option [navdata]
-  (fact "vision option"
+  (testing "vision option"
     (let [v (:vision navdata)]
-      (:state v) => 2
-      (:misc v) => 0
-      (:phi v) => {:trim 0.0 :ref-prop 0.0}
-      (:theta v) => {:trim 0.0 :ref-prop 0.0}
-      (:new-raw-picture v) => 0
-      (:capture v) => {:theta (float 0.05190306529402733)
-                       :phi (float 0.009620788507163525)
-                       :psi (float 0.033727407455444336)
-                       :altitude 243
-                       :time 0.362969}
-      (:body-v v) => {:x (float 0.05845191329717636)
-                      :y (float -0.8817280530929565)
-                      :z (float 0.011505687609314919)}
-      (:delta v) => {:phi 0.0
-                     :theta 0.0
-                     :psi 0.0}
-      (:gold v) => {:defined 0
-                    :reset 0
-                    :x 0.0
-                    :y 0.0})))
+      (are [x y] (= x y)
+           (:state v) 2
+           (:misc v) 0
+           (:phi v) {:trim 0.0 :ref-prop 0.0}
+           (:theta v) {:trim 0.0 :ref-prop 0.0}
+           (:new-raw-picture v) 0
+           (:capture v) {:theta (float 0.05190306529402733)
+                         :phi (float 0.009620788507163525)
+                         :psi (float 0.033727407455444336)
+                         :altitude 243
+                         :time 0.362969}
+           (:body-v v) {:x (float 0.05845191329717636)
+                        :y (float -0.8817280530929565)
+                        :z (float 0.011505687609314919)}
+           (:delta v) {:phi 0.0
+                       :theta 0.0
+                       :psi 0.0}
+           (:gold v) {:defined 0
+                      :reset 0
+                      :x 0.0
+                      :y 0.0}))))

 (defn test-vision-perf-option [navdata]
-  (fact "vision-perf option"
+  (testing "vision-perf option"
     (let [v (:vision-perf navdata)]
-      (:szo v) => 0.0
-      (:corners v) => 0.0
-      (:compute v) => 0.0
-      (:tracking v) => 0.0
-      (:trans v) => 0.0
-      (:update v) => 0.0
-      (:custom v) => [0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
-                      0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0])))
+      (are [x y] (= x y)
+           (:szo v) 0.0
+           (:corners v) 0.0
+           (:compute v) 0.0
+           (:tracking v) 0.0
+           (:trans v) 0.0
+           (:update v) 0.0
+           (:custom v) [0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
+                        0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0]))))

 (defn test-watchdog-option [navdata]
-  (fact "watchdog option"
+  (testing "watchdog option"
     (let [w (:watchdog navdata)]
-      w => 4822)))
+      (is (= w 4822)))))

 ;; (deftest whatever
-;;   (facts "yeah"
+;;   (testing "yeah"
 ;;     (let [navdata-bytes (xio/binary-slurp (io/resource "navdata.bin"))]
 ;;       (pprint/pprint (navdata-bytes-seq navdata-bytes)))))

 (deftest navdata-specimen-tests
-  (facts "parse-navdata on specimen"
+  (testing "parse-navdata on specimen"
     (let [navdata-bytes (xio/binary-slurp (io/resource "navdata.bin"))]
       ;;(println "Benchmarking parse-navdata")
       ;;(criterium/bench (parse-navdata navdata-bytes))
       ;;(criterium/bench (:gps (parse-navdata navdata-bytes)))
-      (let [navdata (parse-navdata navdata-bytes)]
-
-        (fact "navdata"
-          (:header navdata) => 0x55667788
-          (:seq-num navdata) => 300711
-          (:vision-flag navdata) => true)
-
-        (fact "state"
+      (let [navdata (navdata/parse-navdata navdata-bytes)]
+
+        (testing "navdata"
+          (are [x y] (= x y)
+               (:header navdata) 0x55667788
+               (:seq-num navdata) 300711
+               (:vision-flag navdata) true))
+
+        (testing "state"
           (let [state (:state navdata)]
-            state => (contains {:flying :landed})
-            state => (contains {:video :off})
-            state => (contains {:vision :off})
-            state => (contains {:altitude-control :on})
-            state => (contains {:command-ack :received})
-            state => (contains {:camera :ready})
-            state => (contains {:travelling :off})
-            state => (contains {:usb :not-ready})
-            state => (contains {:demo :off})
-            state => (contains {:bootstrap :off})
-            state => (contains {:motors :ok})
-            state => (contains {:communication :ok})
-            state => (contains {:software :ok})
-            state => (contains {:bootstrap :off})
-            state => (contains {:battery :ok})
-            state => (contains {:emergency-landing :off})
-            state => (contains {:timer :not-elapsed})
-            state => (contains {:magneto :ok})
-            state => (contains {:angles :ok})
-            state => (contains {:wind :ok})
-            state => (contains {:ultrasound :ok})
-            state => (contains {:cutout :ok})
-            state => (contains {:pic-version :ok})
-            state => (contains {:atcodec-thread :on})
-            state => (contains {:navdata-thread :on})
-            state => (contains {:video-thread :on})
-            state => (contains {:acquisition-thread :on})
-            state => (contains {:ctrl-watchdog :ok})
-            state => (contains {:adc-watchdog :ok})
-            state => (contains {:com-watchdog :problem})
-            state => (contains {:emergency-landing :off})))
+            (are [x y] (every? (fn [[k v]] (= (x k) v)) y)
+                 state {:flying :landed}
+                 state {:video :off}
+                 state {:vision :off}
+                 state {:altitude-control :on}
+                 state {:command-ack :received}
+                 state {:camera :ready}
+                 state {:travelling :off}
+                 state {:usb :not-ready}
+                 state {:demo :off}
+                 state {:bootstrap :off}
+                 state {:motors :ok}
+                 state {:communication :ok}
+                 state {:software :ok}
+                 state {:bootstrap :off}
+                 state {:battery :ok}
+                 state {:emergency-landing :off}
+                 state {:timer :not-elapsed}
+                 state {:magneto :ok}
+                 state {:angles :ok}
+                 state {:wind :ok}
+                 state {:ultrasound :ok}
+                 state {:cutout :ok}
+                 state {:pic-version :ok}
+                 state {:atcodec-thread :on}
+                 state {:navdata-thread :on}
+                 state {:video-thread :on}
+                 state {:acquisition-thread :on}
+                 state {:ctrl-watchdog :ok}
+                 state {:adc-watchdog :ok}
+                 state {:com-watchdog :problem}
+                 state {:emergency-landing :off})))

         (test-adc-data-frame-option navdata)

-        (fact "time option"
-          (:time navdata) => 362.979125)
-
-        (fact "raw-measures option"
+        (testing "time option"
+          (is (= (:time navdata) 362.979125)))
+
+        (testing "raw-measures option"
           (let [raw-meas (:raw-measures navdata)]
-            (:accelerometers raw-meas) => {:x 2040
-                                           :y 2036
-                                           :z 2528}
-            (:gyroscopes raw-meas) => {:x -23
-                                       :y 15
-                                       :z 0}
-            (:gyroscopes-110 raw-meas) => {:x 0
-                                           :y 0}
-            (:battery-millivolts raw-meas) => 11686
-            (:us-echo raw-meas) => {:start 0
-                                    :end 0
-                                    :association 3758
-                                    :distance 0}
-            (:us-curve raw-meas) => {:time 21423
-                                     :value 0
-                                     :ref 120}
-            (:echo raw-meas) => {:flag-ini 1
-                                 :num 1
-                                 :sum 3539193}
-            (:alt-temp-raw raw-meas) => 243
-            (:gradient raw-meas) => 41))
-
-        (fact "phys-measures option"
+            (is (= (:accelerometers raw-meas)
+                   {:x 2040 :y 2036 :z 2528}))
+            (is (= (:gyroscopes raw-meas)
+                   {:x -23 :y 15 :z 0}))
+            (is (= (:gyroscopes-110 raw-meas)
+                   {:x 0 :y 0}))
+            (is (= (:battery-millivolts raw-meas) 11686))
+            (is (= (:us-echo raw-meas)
+                   {:start 0 :end 0 :association 3758 :distance 0}))
+            (is (= (:us-curve raw-meas)
+                   {:time 21423 :value 0 :ref 120}))
+            (is (= (:echo raw-meas) {:flag-ini 1 :num 1 :sum 3539193}))
+            (is (= (:alt-temp-raw raw-meas) 243))
+            (is (= (:gradient raw-meas) 41))))
+
+        (testing "phys-measures option"
           (let [phys-meas (:phys-measures navdata)]
-            (:temperature phys-meas) => {:accelerometer 45.309303283691406
-                                         :gyroscope 55738}
-            (:accelerometers phys-meas) => {:x 80.2970962524414
-                                            :y -33.318603515625
-                                            :z -942.5283203125}
-            (:gyroscopes phys-meas) => {:x -0.11236488074064255
-                                        :y 0.06872134655714035
-                                        :z 0.06200997903943062}
-            (:alim3v3 phys-meas) => 0
-            (:vref-epson phys-meas) => 0
-            (:vref-idg phys-meas) => 0))
-
-        (fact "wifi option"
+            (is (= (:temperature phys-meas)
+                   {:accelerometer 45.309303283691406 :gyroscope 55738}))
+            (is (= (:accelerometers phys-meas)
+                   {:x 80.2970962524414
+                    :y -33.318603515625
+                    :z -942.5283203125}))
+            (is (= (:gyroscopes phys-meas)
+                   {:x -0.11236488074064255
+                    :y 0.06872134655714035
+                    :z 0.06200997903943062}))
+            (is (= (:alim3v3 phys-meas) 0))
+            (is (= (:vref-epson phys-meas) 0))
+            (is (= (:vref-idg phys-meas) 0))))
+
+        (testing "wifi option"
           (let [wifi (:wifi navdata)]
-            (:link-quality wifi) => 1.0))
-
-        (fact "altitude option"
+            (is (= (:link-quality wifi) 1.0))))
+
+        (testing "altitude option"
           (let [alt (:altitude navdata)]
-            (:vision alt) => 243
-            (:velocity alt) => 0.0
-            (:ref alt) => 0
-            (:raw alt) => 243
-            (:observer alt) => {:acceleration 0.0
-                                :altitude 0.0
-                                :x {:x 0.0
-                                    :y 0.0
+            (are [x y] (= x y)
+                 (:vision alt) 243
+                 (:velocity alt) 0.0
+                 (:ref alt) 0
+                 (:raw alt) 243
+                 (:observer alt) {:acceleration 0.0
+                                  :altitude 0.0
+                                  :x {:x 0.0
+                                      :y 0.0
+                                      :z 0.0}
+                                  :state 0}
+                 (:estimated alt) {:vb {:x 0.0
+                                        :y 0.0}
+                                   :state 0})))
+        (testing "demo option"
+          (let [demo (:demo navdata)]
+            (are [x y] (= x y)
+                 (:control-state demo) :landed
+                 (:battery-percentage demo) 50
+                 (:theta demo) (float 2.974)
+                 (:phi demo) (float 0.55)
+                 (:psi demo) (float 1.933)
+                 (:altitude demo) 0.0
+                 (:velocity demo) {:x 0.0585307739675045
+                                   :y -0.8817979097366333
+                                   :z 0.0})))
+
+        (testing "euler angles option"
+          (let [euler (:euler-angles navdata)]
+            (is (= (:theta euler) 4866.0))
+            (is (= (:phi euler) 2024.0))))
+
+        (test-gps-option navdata)
+
+        (testing "gryos offsets option"
+          (let [gyros (:gyros-offsets navdata)]
+            (is (= gyros {:x -0.5329172611236572
+                          :y 0.1788240224123001,
+                          :z 0.0}))))
+
+        (testing "magneto option"
+          (let [magneto (:magneto navdata)]
+            (are [x y] (= x y)
+                 (:mx magneto) 30
+                 (:my magneto) -56
+                 (:mz magneto) 80
+                 (:raw magneto) {:x 189.0 :y -100.8984375 :z -278.4375}
+                 (:rectified magneto) {:x 145.08058166503906
+                                       :y -84.93736267089844
+                                       :z -287.18157958984375}
+                 (:offset magneto) {:x 29.21237564086914
+                                    :y -13.282999038696289
                                     :z 0.0}
-                                :state 0}
-            (:estimated alt) => {:vb {:x 0.0
-                                      :y 0.0}
-                                 :state 0}))
-        (fact "demo option"
-          (let [demo (:demo navdata)]
-            (:control-state demo) => :landed
-            (:battery-percentage demo) => 50
-            (:theta demo) => (float 2.974)
-            (:phi demo) => (float 0.55)
-            (:psi demo) => (float 1.933)
-            (:altitude demo) => 0.0
-            (:velocity demo) => {:x 0.0585307739675045
-                                 :y -0.8817979097366333
-                                 :z 0.0}))
-
-        (fact "euler angles option"
-          (let [euler (:euler-angles navdata)]
-            (:theta euler) => 4866.0
-            (:phi euler) => 2024.0))
-
-        (test-gps-option navdata)
-
-        (fact "gryos offsets option"
-          (let [gyros (:gyros-offsets navdata)]
-            gyros => {:x -0.5329172611236572
-                      :y 0.1788240224123001,
-                      :z 0.0}))
-
-        (fact "magneto option"
-          (let [magneto (:magneto navdata)]
-            (:mx magneto) => 30
-            (:my magneto) => -56
-            (:mz magneto) => 80
-            (:raw magneto) => {:x 189.0 :y -100.8984375 :z -278.4375}
-            (:rectified magneto) => {:x 145.08058166503906
-                                     :y -84.93736267089844
-                                     :z -287.18157958984375}
-            (:offset magneto) => {:x 29.21237564086914
-                                  :y -13.282999038696289
-                                  :z 0.0}
-            (:heading magneto) =>  {:unwrapped (float 0.0)
-                                    :gyro-unwrapped (float 4.132266E-4)
-                                    :fusion-unwrapped (float 1.9333557)}
-            (:calibration-ok magneto) => 1
-            (:state magneto) => 2
-            (:radius magneto) => (float 387.31146)
-            (:error magneto) => {:mean (float -211.51361)
-                                 :variance (float 79.36719)}))
-
-        (fact "pwm option"
+                 (:heading magneto)  {:unwrapped (float 0.0)
+                                      :gyro-unwrapped (float 4.132266E-4)
+                                      :fusion-unwrapped (float 1.9333557)}
+                 (:calibration-ok magneto) 1
+                 (:state magneto) 2
+                 (:radius magneto) (float 387.31146)
+                 (:error magneto) {:mean (float -211.51361)
+                                   :variance (float 79.36719)})))
+
+        (testing "pwm option"
           (let [pwm (:pwm navdata)]
-            (:motors pwm) => [0 0 0 0]
-            (:sat-motors pwm) => [255 255 255 255]
-            (:gaz-feed-forward pwm) => 0.0
-            (:gaz-altitude pwm) => 0.0
-            (:altitude-integral pwm) => 0.0
-            (:vz-ref pwm) => 0.0
-            (:u-pitch pwm) => 0
-            (:u-roll pwm) => 0
-            (:u-yaw pwm) => 0
-            (:yaw-u-i pwm) => 0
-            (:u-pitch-planif pwm) => 0
-            (:u-roll-planif pwm) => 0
-            (:u-yaw-planif pwm) => 0
-            (:u-gaz-planif pwm) => 0
-            (:motor-currents pwm) => [0 0 0 0]
-            (:altitude-prop pwm) => 0.0
-            (:altitude-der pwm) => 0.0))
-
-        (fact "rc references option"
+            (are [x y] (= x y)
+                 (:motors pwm) [0 0 0 0]
+                 (:sat-motors pwm) [255 255 255 255]
+                 (:gaz-feed-forward pwm) 0.0
+                 (:gaz-altitude pwm) 0.0
+                 (:altitude-integral pwm) 0.0
+                 (:vz-ref pwm) 0.0
+                 (:u-pitch pwm) 0
+                 (:u-roll pwm) 0
+                 (:u-yaw pwm) 0
+                 (:yaw-u-i pwm) 0
+                 (:u-pitch-planif pwm) 0
+                 (:u-roll-planif pwm) 0
+                 (:u-yaw-planif pwm) 0
+                 (:u-gaz-planif pwm) 0
+                 (:motor-currents pwm) [0 0 0 0]
+                 (:altitude-prop pwm) 0.0
+                 (:altitude-der pwm) 0.0)))
+
+        (testing "rc references option"
           (let [rc-ref (:rc-references navdata)]
-            (:pitch rc-ref) => 0
-            (:roll rc-ref) => 0
-            (:yaw rc-ref) => 0
-            (:gaz rc-ref) => 0
-            (:az rc-ref) => 0))
-
-        (fact "references option"
+            (are [x y] (= x y)
+                 (:pitch rc-ref) 0
+                 (:roll rc-ref) 0
+                 (:yaw rc-ref) 0
+                 (:gaz rc-ref) 0
+                 (:az rc-ref) 0)))
+
+        (testing "references option"
           (let [ref (:references navdata)]
-            (:theta ref) => 0
-            (:phi ref) => 0
-            (:psi ref) => 0
-            (:theta-i ref) => 0
-            (:phi-i ref) => 0
-            (:pitch ref) => 0
-            (:roll ref) => 0
-            (:yaw ref) => 0
-            (:psi ref) => 0
-            (:vx ref) => 0.0
-            (:vy ref) => 0.0
-            (:theta-mod ref) => 0.0
-            (:phi-mod ref) => 0.0
-            (:k-v-x ref) => 0.0
-            (:k-v-y ref) => 0.0
-            (:k-mode ref) => 0.0
-            (:ui ref) => {:time 0.0
-                          :theta 0.0
-                          :phi 0.0
-                          :psi 0.0
-                          :psi-accuracy 0.0
-                          :seq 0}))
+            (are [x y] (= x y)
+                 (:theta ref) 0
+                 (:phi ref) 0
+                 (:psi ref) 0
+                 (:theta-i ref) 0
+                 (:phi-i ref) 0
+                 (:pitch ref) 0
+                 (:roll ref) 0
+                 (:yaw ref) 0
+                 (:psi ref) 0
+                 (:vx ref) 0.0
+                 (:vy ref) 0.0
+                 (:theta-mod ref) 0.0
+                 (:phi-mod ref) 0.0
+                 (:k-v-x ref) 0.0
+                 (:k-v-y ref) 0.0
+                 (:k-mode ref) 0.0
+                 (:ui ref) {:time 0.0
+                            :theta 0.0
+                            :phi 0.0
+                            :psi 0.0
+                            :psi-accuracy 0.0
+                            :seq 0})))

         (test-trackers-send-option navdata)

-        (fact "trims option"
+        (testing "trims option"
           (let [trims (:trims navdata)]
-            (:angular-rates trims) => {:r 0.0}
-            (:euler-angles trims) => {:theta (float 3028.916)
-                                      :phi (float 1544.3184)}))
+            (is (= (:angular-rates trims) {:r 0.0}))
+            (is (= (:euler-angles trims) {:theta (float 3028.916)
+                                          :phi (float 1544.3184)}))))

         (test-vision-option navdata)

-        (fact "vision-detect option"
+        (testing "vision-detect option"
           (let [detections (:vision-detect navdata)]
-            (count detections) => 0))
-
-        (fact "vision-of option"
+            (is (= (count detections) 0))))
+
+        (testing "vision-of option"
           (let [v (:vision-of navdata)]
-            (:dx v) => [0.0 0.0 0.0 0.0 0.0]
-            (:dy v) => [0.0 0.0 0.0 0.0 0.0]))
+            (is (= (:dx v) [0.0 0.0 0.0 0.0 0.0]))
+            (is (= (:dy v) [0.0 0.0 0.0 0.0 0.0]))))

         (test-vision-perf-option navdata)

-        (fact "vision-raw option"
+        (testing "vision-raw option"
           (let [v (:vision-raw navdata)]
-            (:tx v) => 1.3266397714614868
-            (:ty v) => -0.7230937480926514
-            (:tz v) => 0.0))
+            (is (= (:tx v) 1.3266397714614868))
+            (is (= (:ty v) -0.7230937480926514))
+            (is (= (:tz v) 0.0))))

         (test-watchdog-option navdata)))))

-(testable-privates stream-navdata)
+;;(testable-privates stream-navdata)

 ;; (deftest stream-navdata-tests
-;;   (facts "about stream-navdata"
+;;   (testing "about stream-navdata"
 ;;     (fact "stream-navdata"
-;;       (stream-navdata nil socket packet) => anything
+;;       (stream-navdata nil socket packet) anything
 ;;       (provided
-;;         (receive-navdata anything anything) => 1
-;;         (get-nav-data :default) => (:nav-data (:default @drones))
-;;         (get-navdata-bytes anything) => nav-input
-;;         (get-ip-from-packet anything) => "192.168.1.1")
+;;         (receive-navdata anything anything) 1
+;;         (get-nav-data :default) (:nav-data (:default @drones))
+;;         (get-navdata-bytes anything) nav-input
+;;         (get-ip-from-packet anything) "192.168.1.1")
 ;;       (against-background
-;;         (before :facts (do
+;;         (before :testing (do
 ;;                          (reset! drones {:default {:nav-data (atom {})
 ;;                                                    :host (InetAddress/getByName "192.168.1.1")}})
 ;;                          ;;(reset! stop-navstream true)
 ;;                          )))))
 ;;   )

-  ;; (facts "about parse-options"
+  ;; (testing "about parse-options"
   ;;   (fact "about parse-options with demo"
   ;;     (let [option (parse-options b-demo-option 0 {})]
-  ;;       option => (contains {:control-state :landed})))
+  ;;       option (contains {:control-state :landed})))
   ;;   (fact "about parse option with targets"
   ;;     (let [option (parse-options b-target-option 0 {})]
-  ;;       option => (contains {:targets-num 2})))
+  ;;       option (contains {:targets-num 2})))
   ;;   (fact "about parse-options with demo and targets"
   ;;     (let [options (parse-options nav-input 16 {})]
-  ;;       options => (contains {:control-state :landed})
-  ;;       options => (contains {:targets-num 2}))))
+  ;;       options (contains {:control-state :landed})
+  ;;       options (contains {:targets-num 2}))))


board is laid out dynamically

board is laid out dynamically

--- cartagena-web/src/cartagena_web/core.cljs
+++ cartagena-web/src/cartagena_web/core.cljs
@@ -18,33 +18,18 @@
    [:rect {:x 0 :y 0 :width (to-scale 50) :height (to-scale 90) :stroke "black" :fill "darkgray"}]
    [:text {:x 0 :y (to-scale 15) :style {:text-anchor "start" :stroke "none" :fill "black" :font-size "smaller"}} "jail"]
    ;; ship
-   [:rect {:x (to-scale 410) :y (to-scale 250) :width (to-scale 90) :height (to-scale 50) :stroke "black" :fill "sienna"}]
-   [:text {:x (to-scale 410) :y (to-scale 260) :style {:text-anchor "start" :stroke "none" :fill "black" :font-size "smaller"}} "ship"]
+   [:rect {:x (to-scale 400) :y (to-scale 240) :width (to-scale 90) :height (to-scale 50) :stroke "black" :fill "sienna"}]
+   [:text {:x (to-scale 400) :y (to-scale 255) :style {:text-anchor "start" :stroke "none" :fill "black" :font-size "smaller"}} "ship"]

-   [:circle {:cx (to-scale 455) :cy (to-scale 255) :r (to-scale 4) :fill "chartreuse"}]
-   [:circle {:cx (to-scale 455) :cy (to-scale 295) :r (to-scale 4) :fill "chartreuse"}]
-   [:circle {:cx (to-scale 465) :cy (to-scale 255) :r (to-scale 4) :fill "cyan"}]
-   [:circle {:cx (to-scale 475) :cy (to-scale 255) :r (to-scale 4) :fill "yellow"}]
-   [:circle {:cx (to-scale 485) :cy (to-scale 255) :r (to-scale 4) :fill "fuchsia"}]
-   [:circle {:cx (to-scale 495) :cy (to-scale 255) :r (to-scale 4) :fill "red"}]
+   ;[:circle {:cx (to-scale 445) :cy (to-scale 245) :r (to-scale 4) :fill "chartreuse"}]
+   ;[:circle {:cx (to-scale 445) :cy (to-scale 285) :r (to-scale 4) :fill "chartreuse"}]
+   ;[:circle {:cx (to-scale 445) :cy (to-scale 245) :r (to-scale 4) :fill "cyan"}]
+   ;[:circle {:cx (to-scale 465) :cy (to-scale 245) :r (to-scale 4) :fill "yellow"}]
+   ;[:circle {:cx (to-scale 475) :cy (to-scale 245) :r (to-scale 4) :fill "fuchsia"}]
+   ;[:circle {:cx (to-scale 485) :cy (to-scale 245) :r (to-scale 4) :fill "red"}]
    ])

-(def good-example (into [:svg {:w 10 :h 8}]
-                        [[:circle {:x 1 :y 2}] [:circle {:x 2 :y 4}]]))

-(defn jail []
-  (when-let [jail (get-in @app-state [:board 0])]
-    (apply concat
-           (let [pirate-frequencies (frequencies (:pirates jail))
-                 pirate-colors (vec (keys pirate-frequencies))]
-             (for [player-index (range (count pirate-frequencies))]
-               (let [pirate-color (get pirate-colors player-index)
-                     pirate-count (pirate-color pirate-frequencies)
-                     color-name (name pirate-color)
-                     x (to-scale (+ 5 (* 10 player-index)))]
-                 (for [pirate-index (range pirate-count)]
-                   (let [y (to-scale (+ 35 (* 10 pirate-index)))]
-                     [:circle {:cx x :cy y :r (to-scale 4) :fill color-name}]))))))))

 (def piece-positions
   [
@@ -76,7 +61,53 @@
    {:x 130 :y 120 :text-x 130 :text-y 135}
    {:x 90 :y 120 :text-x 90 :text-y 135}
    {:x 50 :y 120 :text-x 50 :text-y 135}
-   ])
+   ;; transition 2
+   {:x 50 :y 150 :text-x 50 :text-y 165}
+   ;; row 3, left to right
+   {:x 50 :y 180 :text-x 50 :text-y 195}
+   {:x 90 :y 180 :text-x 90 :text-y 195}
+   {:x 130 :y 180 :text-x 130 :text-y 195}
+   {:x 170 :y 180 :text-x 170 :text-y 195}
+   {:x 210 :y 180 :text-x 210 :text-y 195}
+   {:x 250 :y 180 :text-x 250 :text-y 195}
+   {:x 290 :y 180 :text-x 290 :text-y 195}
+   {:x 330 :y 180 :text-x 330 :text-y 195}
+   {:x 370 :y 180 :text-x 370 :text-y 195}
+   {:x 410 :y 180 :text-x 410 :text-y 195}
+   {:x 450 :y 180 :text-x 450 :text-y 195}
+   ;; transition 3
+   {:x 450 :y 210 :text-x 450 :text-y 225}
+   ;; ship
+   {:x 400 :y 240 :text-x 400 :text-y 415}
+ ])
+
+(defn jail []
+  (when-let [jail (get-in @app-state [:board 0])]
+    (apply concat
+           (let [pirate-frequencies (frequencies (:pirates jail))
+                 pirate-colors (vec (keys pirate-frequencies))]
+             (for [player-index (range (count pirate-frequencies))]
+               (let [pirate-color (get pirate-colors player-index)
+                     pirate-count (pirate-color pirate-frequencies)
+                     color-name (name pirate-color)
+                     x (to-scale (+ 5 (* 10 player-index)))]
+                 (for [pirate-index (range pirate-count)]
+                   (let [y (to-scale (+ 35 (* 10 pirate-index)))]
+                     [:circle {:cx x :cy y :r (to-scale 4) :fill color-name}]))))))))
+
+(defn ship []
+  (when-let [ship (get-in @app-state [:board 37])]
+    (apply concat
+           (let [pirate-frequencies (frequencies (:pirates ship))
+                 pirate-colors (vec (keys pirate-frequencies))]
+             (for [player-index (range (count pirate-frequencies))]
+               (let [pirate-color (get pirate-colors player-index)
+                     pirate-count (pirate-color pirate-frequencies)
+                     color-name (name pirate-color)
+                     x (to-scale (+ 445 (* 10 player-index)))]
+                 (for [pirate-index (range pirate-count)]
+                   (let [y (to-scale (+ 245 (* 10 pirate-index)))]
+                     [:circle {:cx x :cy y :r (to-scale 4) :fill color-name}]))))))))

 (defn normal-space [x y]
   [:rect {:x (to-scale x) :y (to-scale y) :width (to-scale 40) :height (to-scale 30) :stroke "black" :stroke-width "0.5" :fill "lightgray"}])
@@ -86,7 +117,7 @@

 (defn normal-spaces []
   (apply concat
-         (for [i (range 1 24)]
+         (for [i (range 1 37)]
            (when-let [space-data (get-in @app-state [:board i])]
              (let [position (get piece-positions i)
                    space (normal-space (:x position) (:y position))


linty fix

linty fix

--- src/metabase/driver/query_processor/expand.clj
+++ src/metabase/driver/query_processor/expand.clj
@@ -82,6 +82,7 @@
 (defn expand-filter
   "Expand a `filter` clause."
   [filter-clause]
+  (def _b filter-clause)
   (with-resolved-fields parse-filter filter-clause))

 ;; Do a breadth-first walk so we don't walk things that will be tossed anyway. Since
@@ -230,16 +231,16 @@
     ["INSIDE" (:field lat) (:field lon) (:max lat) (:min lon) (:min lat) (:max lon)]))

 (defrecord Filter:Between [^Keyword filter-type
-                           ^Field field
-                           ^Value min-val
-                           ^Value max-val]
+                           ^Field   field
+                           ^Value   min-val
+                           ^Value   max-val]
   ICollapse
   (collapse-one [_]
     ["BETWEEN" field min-val max-val]))

 (defrecord Filter:Field+Value [^Keyword filter-type
-                              ^Field field
-                              ^Value value]
+                               ^Field   field
+                               ^Value   value]
   ICollapse
   (collapse-one [_]
     [(s/upper-case (name filter-type)) field value]))
@@ -255,35 +256,35 @@

 (defparser parse-filter-subclause
   ["INSIDE" lat-field lon-field lat-max lon-min lat-min lon-max]
-  (map->Filter:Inside {:type :inside
-                       :lat  {:field (ph lat-field)
-                              :min   (ph lat-field lat-min)
-                              :max   (ph lat-field lat-max)}
-                       :lon  {:field (ph lon-field)
-                              :min   (ph lon-field lon-min)
-                              :max   (ph lon-field lon-max)}})
+  (map->Filter:Inside {:filter-type :inside
+                       :lat         {:field (ph lat-field)
+                                     :min   (ph lat-field lat-min)
+                                     :max   (ph lat-field lat-max)}
+                       :lon         {:field (ph lon-field)
+                                     :min   (ph lon-field lon-min)
+                                     :max   (ph lon-field lon-max)}})

   ["BETWEEN" field-id min max]
-  (map->Filter:Between {:type  :between
-                        :field (ph field-id)
-                        :min   (ph field-id min)
-                        :max   (ph field-id max)})
+  (map->Filter:Between {:filter-type :between
+                        :field       (ph field-id)
+                        :min-val     (ph field-id min)
+                        :max-val     (ph field-id max)})

   [filter-type field-id val]
-  (map->Filter:Field+Value {:type  (keyword filter-type)
-                            :field (ph field-id)
-                            :value (ph field-id val)})
+  (map->Filter:Field+Value {:filter-type (keyword filter-type)
+                            :field       (ph field-id)
+                            :value       (ph field-id val)})

   [filter-type field-id]
-  (map->Filter:Field {:type (case filter-type
-                              "NOT_NULL" :not-null
-                              "IS_NULL"  :is-null)
-                      :field (ph field-id)}))
+  (map->Filter:Field {:filter-type (case filter-type
+                                     "NOT_NULL" :not-null
+                                     "IS_NULL"  :is-null)
+                      :field       (ph field-id)}))

 (defparser parse-filter
-  ["AND" & subclauses] (map->Filter {:type :and
-                                     :subclauses (mapv parse-filter-subclause subclauses)})
-  ["OR" & subclauses]  (map->Filter {:type :or
-                                     :subclauses (mapv parse-filter-subclause subclauses)})
-  subclause            (map->Filter {:type :simple
-                                     :subclauses [(parse-filter-subclause subclause)]}))
+  ["AND" & subclauses] (map->Filter {:compound-type :and
+                                     :subclauses    (mapv parse-filter-subclause subclauses)})
+  ["OR" & subclauses]  (map->Filter {:compound-type :or
+                                     :subclauses    (mapv parse-filter-subclause subclauses)})
+  subclause            (map->Filter {:compound-type :simple
+                                     :subclauses    [(parse-filter-subclause subclause)]}))


Multiline textfield - fixed wrong cusror positioning on mouse click

--- flatguiwidgets/src/flatgui/widgets/textfield.clj
+++ flatguiwidgets/src/flatgui/widgets/textfield.clj
@@ -207,8 +207,8 @@
                              0)
             click-pos (if (> click-line 0)
                         (+
-                          (apply + (map #(.length %) (take (dec click-line) (:lines old-model)))) ; All previous lines
-                          (dec click-line) ; A linebreak symbol after each previous line
+                          (apply + (map #(.length %) (take click-line (:lines old-model)))) ; All previous lines
+                          click-line ; A linebreak symbol after each previous line
                           click-line-pos)
                         click-line-pos)]
         (merge old-model {:caret-pos click-pos
@@ -335,9 +335,10 @@

 (fg/defevolverfn :caret-visible
   (if (= :has-focus (:mode (get-property [:this] :focus-state)))
-    (if (timer/timer-event? component)
-      (not old-caret-visible)
-      old-caret-visible)
+    ;(if (timer/timer-event? component)
+    ;  (not old-caret-visible)
+    ;  old-caret-visible)
+    true
     false))

 (defn textfield-dflt-text-suplier [component]


Add filetypes from-name function in clojure

--- clojure/cljsearch/src/cljsearch/filetypes.clj
+++ clojure/cljsearch/src/cljsearch/filetypes.clj
@@ -1,6 +1,6 @@
 ;;; ############################################################################
 ;;;
-;;; fileutil.clj
+;;; filetypes.clj
 ;;;
 ;;; Utility functions for getting file extension and determining file type
 ;;;
@@ -12,7 +12,7 @@
   (:import (java.io File))
   (:require [clojure.java.io :as io])
   (:use [clojure.set :only (union)]
-        [clojure.string :only (split)]
+        [clojure.string :only (split upper-case)]
         [clojure.xml :only (parse)]
         [cljsearch.fileutil :only (expand-path get-ext)]))

@@ -55,3 +55,10 @@
     (binary-file? f) :binary
     (archive-file? f) :archive
     :else :unknown))
+
+(defn from-name [name]
+  (cond
+    (= "TEXT" (upper-case name)) :text
+    (= "BINARY" (upper-case name)) :binary
+    (= "ARCHIVE" (upper-case name)) :archive
+    :else :unknown))


Clean up imports

Clean up imports

--- src/spec_tools/convert.cljc
+++ src/spec_tools/convert.cljc
@@ -4,7 +4,7 @@
     #?@(:cljs [[goog.date.UtcDateTime]
                [goog.date.Date]]))
   #?(:clj
-     (:import (java.util Date)
+     (:import (java.util Date UUID)
               (java.time Instant))))

 (defn string->long [_ x]
@@ -19,7 +19,7 @@
 (defn string->double [_ x]
   (if (string? x)
     (try
-      #?(:clj  (java.lang.Double/parseDouble x)
+      #?(:clj  (Double/parseDouble x)
          :cljs (js/parseFloat x))
       (catch #?(:clj  Exception
                 :cljs js/Error) _
@@ -39,7 +39,7 @@
 (defn string->uuid [_ x]
   (if (string? x)
     (try
-      #?(:clj  (java.util.UUID/fromString x)
+      #?(:clj  (UUID/fromString x)
          :cljs (uuid x))
       (catch #?(:clj  Exception
                 :cljs js/Error) _


Allow :configurator to set a handler

Allow :configurator to set a handler

--- ring-jetty-adapter/src/ring/adapter/jetty.clj
+++ ring-jetty-adapter/src/ring/adapter/jetty.clj
@@ -63,7 +63,7 @@
     (when-let [configurator (:configurator options)]
       (configurator s))
     (doto s
-      (.setHandler (proxy-handler handler))
+      (.addHandler (proxy-handler handler))
       (.start))
     (when (:join? options true)
       (.join s))


Add type hint to eliminate reflection warning

--- ring-jetty-adapter/src/ring/adapter/jetty.clj
+++ ring-jetty-adapter/src/ring/adapter/jetty.clj
@@ -113,7 +113,7 @@
           (.addExcludeProtocols context-server protocols))))
     context-server))

-(defn- ^ServerConnector ssl-connector [server options]
+(defn- ^ServerConnector ssl-connector [^Server server options]
   (let [ssl-port     (options :ssl-port 443)
         http-factory (HttpConnectionFactory.
                       (doto (http-config options)


Moved keyword finding into (-main)

Moved keyword finding into (-main)

--- src/stream_crawler/core.clj
+++ src/stream_crawler/core.clj
@@ -37,19 +37,6 @@
 (defentity keyword-objects
   (table :keywords))

-(def keywords
-  (map :keyword
-    (select keyword-objects
-      (fields :keyword))))
-
-(def serialized-keywords
-  (str/join "," keywords))
-
-;; create the client with a twitter.api streaming method
-(def stream (twitter-client/create-twitter-stream twitter.api.streaming/statuses-filter
-                                          :oauth-creds twitter-creds
-                                          :params {:track serialized-keywords}))
-
 (defn create-tweet-entities [twitter-tweet]
   ; the entirety of this method should be wrapped in a database transaction
   (log/info (str "created tweet! (id: " (:id twitter-tweet) ")"))
@@ -71,7 +58,16 @@

 (defn -main []
-  ; (twitter-client/cancel-twitter-stream stream)
-  (log/info (str "Starting stream client at " t/now))
-  (twitter-client/start-twitter-stream stream)
-  (add-watch stream :queues do-on-queues-changed))
+  (let
+    [serialized-keywords
+      (str/join "," (map :keyword
+        (select keyword-objects
+          (fields :keyword))))
+      stream
+        (twitter-client/create-twitter-stream twitter.api.streaming/statuses-filter
+          :oauth-creds twitter-creds
+          :params {:track serialized-keywords})]
+
+    (log/info (str "Starting stream client at " t/now))
+    (twitter-client/start-twitter-stream stream)
+    (add-watch stream :queues do-on-queues-changed)))


Display a message for conflicts in generated dispatch values

--- clstreams/src/clstreams/kstreams/impl.clj
+++ clstreams/src/clstreams/kstreams/impl.clj
@@ -28,9 +28,14 @@
   (reduce
    (fn
      [mm-data {:keys [name parameter-types return-type] :as mmethod}]
-     (assoc-in mm-data [name (dispatch-value-fn class-name mmethod)]
-               {:parameter-types parameter-types
-                :return-type return-type}))
+     (update-in mm-data [name (dispatch-value-fn class-name mmethod)]
+                (fn [old]
+                  (if old
+                    (do
+                      (printf "Dispatch value conflict in %s.%s\n" class-name name)
+                      old)
+                    {:parameter-types parameter-types
+                     :return-type return-type}))))
    initial-mm-data
    members))


Revert "change label for name on credit card" (#1573)

This reverts commit b5adc7afe7206240fc9ee3a5172f2c31865d5df4.

--- src-cljs/frontend/components/org_settings.cljs
+++ src-cljs/frontend/components/org_settings.cljs
@@ -853,7 +853,7 @@
                 (om/build table/table
                           {:rows [card]
                            :key-fn (constantly "card")
-                           :columns [{:header "Name on Credit Card"
+                           :columns [{:header "Name"
                                       :cell-fn #(:name % "N/A")}
                                      {:header "Card type"
                                       :cell-fn #(:type % "N/A")}


s/track-update-plan-clicked/update-plan-clicked

we changed the function name but forgot to change it at all call
locations.

--- src-cljs/frontend/components/org_settings.cljs
+++ src-cljs/frontend/components/org_settings.cljs
@@ -387,11 +387,11 @@
                                                :disabled? (= (name plan-id) (pm/osx-plan-id plan))
                                                :on-click-fn #(do
                                                                (raise! owner [:update-osx-plan-clicked {:plan-type {:template (name plan-id)}}])
-                                                               (analytics-track/track-update-plan-clicked {:owner owner
-                                                                                :new-plan plan-id
-                                                                                :previous-plan (pm/osx-plan-id plan)
-                                                                                :plan-type pm/osx-plan-type
-                                                                                :upgrade? (> (:price plan-data) (pm/osx-cost plan))}))})
+                                                               (analytics-track/update-plan-clicked {:owner owner
+                                                                                :new-plan plan-id
+                                                                                :previous-plan (pm/osx-plan-id plan)
+                                                                                :plan-type pm/osx-plan-type
+                                                                                :upgrade? (> (:price plan-data) (pm/osx-cost plan))}))})
                 (om/build plan-payment-button {:text "Pay Now"
                                                :loading-text "Paying..."
                                                :on-click-fn #(do
@@ -528,11 +528,11 @@
                                   #(do
                                     (raise! owner [:update-containers-clicked
                                                    {:containers selected-paid-containers}])
-                                    (analytics-track/track-update-plan-clicked {:owner owner
-                                                                                :new-plan selected-paid-containers
-                                                                                :previous-plan (pm/paid-linux-containers plan)
-                                                                                :plan-type pm/linux-plan-type
-                                                                                :upgrade? (> selected-paid-containers (pm/paid-linux-containers plan))})))
+                                    (analytics-track/update-plan-clicked {:owner owner
+                                                                          :new-plan selected-paid-containers
+                                                                          :previous-plan (pm/paid-linux-containers plan)
+                                                                          :plan-type pm/linux-plan-type
+                                                                          :upgrade? (> selected-paid-containers (pm/paid-linux-containers plan))})))
                       :kind :primary}
                      (if (config/enterprise?)
                        enterprise-text


Method to generate argb color values

Method to generate argb color values

--- src/test_utils/sandbox.cljc
+++ src/test_utils/sandbox.cljc
@@ -14,3 +14,7 @@
   ([] (hex-uuid (random-uuid)))
   ([uuid] (clj-str/join (map #(Long/toHexString %) [(.getMostSignificantBits uuid) (.getLeastSignificantBits uuid)]))))

+(defn color []
+  (map clj-str/join
+       (map #(concat ["0x"] %)
+            (take 4 (map clj-str/join (partition 2 (hex-uuid)))))))