some more plots

some more plots

--- gorilla/analysis-ws.clj
+++ gorilla/analysis-ws.clj
@@ -9,7 +9,7 @@
   (:refer-clojure :exclude [find sort])
   (:require [gorilla-plot.core :refer :all]
             [ceres.collector :refer :all]
-            [ceres.curator :refer [start-date end-date random-tree build-tree-from-source]]
+            [ceres.curator :refer [start-date end-date random-tree build-tree-from-source compute-summary]]
             [monger.collection :as mc]
             [clj-time.core :as t]
             [clj-time.periodic :as p]
@@ -176,6 +176,13 @@
 ;; **

 ;; @@
+(:title some-tree)
+;; @@
+;; =>
+;;; {"type":"html","content":""Ferguson : Der Tag, an dem die US-Polizei mein Feind wurde - Nachrichten Politik - Ausland - DIE WELT"","value":"\"Ferguson : Der Tag, an dem die US-Polizei mein Feind wurde - Nachrichten Politik - Ausland - DIE WELT\""}
+;; <=
+
+;; @@
 (-> some-tree :analysis keys)
 ;; @@
 ;; =>
@@ -190,14 +197,7 @@
 (-> some-tree :analysis (dissoc :pub-times :hashtags :delays :users))
 ;; @@
 ;; =>
-;;; {"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":size","value":":size"},{"type":"html","content":"43","value":"43"}],"value":"[:size 43]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":height","value":":height"},{"type":"html","content":"3","value":"3"}],"value":"[:height 3]"}],"value":"{:size 43, :height 3}"}
-;; <=
-
-;; @@
-(-> some-tree :analysis keys)
-;; @@
-;; =>
-;;; {"type":"html","content":"(:size :height :users :pub-times :hashtags :delays)","value":"(:size :height :users :pub-times :hashtags :delays)"}
+;;; {"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":size","value":":size"},{"type":"html","content":"479","value":"479"}],"value":"[:size 479]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":height","value":":height"},{"type":"html","content":"5","value":"5"}],"value":"[:height 5]"}],"value":"{:size 479, :height 5}"}
 ;; <=

 ;; **
@@ -214,7 +214,7 @@
    (bar-chart (keys h-freq) (vals h-freq) :plot-size 800)])))
 ;; @@
 ;; =>
-;;; {"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"list-like","open":"#{","close":"}","separator":" ","items":[{"type":"html","content":""burbach"","value":"\"burbach\""},{"type":"html","content":""m05h96"","value":"\"m05h96\""},{"type":"html","content":""ts20"","value":"\"ts20\""},{"type":"html","content":""ltwbb"","value":"\"ltwbb\""},{"type":"html","content":""ltwth"","value":"\"ltwth\""},{"type":"html","content":""sltw14"","value":"\"sltw14\""},{"type":"html","content":""essen"","value":"\"essen\""},{"type":"html","content":""tagesschau"","value":"\"tagesschau\""},{"type":"html","content":""waffensspd"","value":"\"waffensspd\""}],"value":"#{\"burbach\" \"m05h96\" \"ts20\" \"ltwbb\" \"ltwth\" \"sltw14\" \"essen\" \"tagesschau\" \"waffensspd\"}"},{"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"ordinal","range":"width","domain":{"data":"1a80d830-b7d2-4bd1-960b-c4defaba9028","field":"data.x"}},{"name":"y","range":"height","nice":true,"domain":{"data":"1a80d830-b7d2-4bd1-960b-c4defaba9028","field":"data.y"}}],"marks":[{"type":"rect","from":{"data":"1a80d830-b7d2-4bd1-960b-c4defaba9028"},"properties":{"enter":{"y":{"scale":"y","field":"data.y"},"width":{"offset":-1,"scale":"x","band":true},"x":{"scale":"x","field":"data.x"},"y2":{"scale":"y","value":0}},"update":{"fill":{"value":"steelblue"},"opacity":{"value":1}},"hover":{"fill":{"value":"#FF29D2"}}}}],"data":[{"name":"1a80d830-b7d2-4bd1-960b-c4defaba9028","values":[{"x":"ltwbb","y":9},{"x":"ltwth","y":9},{"x":"burbach","y":8},{"x":"essen","y":8},{"x":"tagesschau","y":7},{"x":"m05h96","y":3},{"x":"sltw14","y":3},{"x":"ts20","y":1},{"x":"waffensspd","y":1}]}],"width":800,"height":494.4375915527344,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"ordinal\", :range \"width\", :domain {:data \"1a80d830-b7d2-4bd1-960b-c4defaba9028\", :field \"data.x\"}} {:name \"y\", :range \"height\", :nice true, :domain {:data \"1a80d830-b7d2-4bd1-960b-c4defaba9028\", :field \"data.y\"}}], :marks [{:type \"rect\", :from {:data \"1a80d830-b7d2-4bd1-960b-c4defaba9028\"}, :properties {:enter {:y {:scale \"y\", :field \"data.y\"}, :width {:offset -1, :scale \"x\", :band true}, :x {:scale \"x\", :field \"data.x\"}, :y2 {:scale \"y\", :value 0}}, :update {:fill {:value \"steelblue\"}, :opacity {:value 1}}, :hover {:fill {:value \"#FF29D2\"}}}}], :data [{:name \"1a80d830-b7d2-4bd1-960b-c4defaba9028\", :values ({:x \"ltwbb\", :y 9} {:x \"ltwth\", :y 9} {:x \"burbach\", :y 8} {:x \"essen\", :y 8} {:x \"tagesschau\", :y 7} {:x \"m05h96\", :y 3} {:x \"sltw14\", :y 3} {:x \"ts20\", :y 1} {:x \"waffensspd\", :y 1})}], :width 800, :height 494.4376, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}],"value":"[#{\"burbach\" \"m05h96\" \"ts20\" \"ltwbb\" \"ltwth\" \"sltw14\" \"essen\" \"tagesschau\" \"waffensspd\"} #gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"ordinal\", :range \"width\", :domain {:data \"1a80d830-b7d2-4bd1-960b-c4defaba9028\", :field \"data.x\"}} {:name \"y\", :range \"height\", :nice true, :domain {:data \"1a80d830-b7d2-4bd1-960b-c4defaba9028\", :field \"data.y\"}}], :marks [{:type \"rect\", :from {:data \"1a80d830-b7d2-4bd1-960b-c4defaba9028\"}, :properties {:enter {:y {:scale \"y\", :field \"data.y\"}, :width {:offset -1, :scale \"x\", :band true}, :x {:scale \"x\", :field \"data.x\"}, :y2 {:scale \"y\", :value 0}}, :update {:fill {:value \"steelblue\"}, :opacity {:value 1}}, :hover {:fill {:value \"#FF29D2\"}}}}], :data [{:name \"1a80d830-b7d2-4bd1-960b-c4defaba9028\", :values ({:x \"ltwbb\", :y 9} {:x \"ltwth\", :y 9} {:x \"burbach\", :y 8} {:x \"essen\", :y 8} {:x \"tagesschau\", :y 7} {:x \"m05h96\", :y 3} {:x \"sltw14\", :y 3} {:x \"ts20\", :y 1} {:x \"waffensspd\", :y 1})}], :width 800, :height 494.4376, :padding {:bottom 20, :top 10, :right 10, :left 50}}}]"}
+;;; {"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"list-like","open":"#{","close":"}","separator":" ","items":[{"type":"html","content":""pressefreiheit"","value":"\"pressefreiheit\""},{"type":"html","content":""us"","value":"\"us\""},{"type":"html","content":""imgeilstenlandderwelt"","value":"\"imgeilstenlandderwelt\""},{"type":"html","content":""polizei"","value":"\"polizei\""},{"type":"html","content":""springer"","value":"\"springer\""},{"type":"html","content":""furgeson"","value":"\"furgeson\""},{"type":"html","content":""usa"","value":"\"usa\""},{"type":"html","content":""s21"","value":"\"s21\""},{"type":"html","content":""graw"","value":"\"graw\""},{"type":"html","content":""medien"","value":"\"medien\""},{"type":"html","content":""missouri"","value":"\"missouri\""},{"type":"html","content":""schland"","value":"\"schland\""},{"type":"html","content":""policestate"","value":"\"policestate\""},{"type":"html","content":""arbeitsvertrag"","value":"\"arbeitsvertrag\""},{"type":"html","content":""firstamendment"","value":"\"firstamendment\""},{"type":"html","content":""ferguson"","value":"\"ferguson\""},{"type":"html","content":""afd"","value":"\"afd\""},{"type":"html","content":""atlantik"","value":"\"atlantik\""}],"value":"#{\"pressefreiheit\" \"us\" \"imgeilstenlandderwelt\" \"polizei\" \"springer\" \"furgeson\" \"usa\" \"s21\" \"graw\" \"medien\" \"missouri\" \"schland\" \"policestate\" \"arbeitsvertrag\" \"firstamendment\" \"ferguson\" \"afd\" \"atlantik\"}"},{"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"ordinal","range":"width","domain":{"data":"d4fcfef5-9b5b-4a86-b626-6f485449746f","field":"data.x"}},{"name":"y","range":"height","nice":true,"domain":{"data":"d4fcfef5-9b5b-4a86-b626-6f485449746f","field":"data.y"}}],"marks":[{"type":"rect","from":{"data":"d4fcfef5-9b5b-4a86-b626-6f485449746f"},"properties":{"enter":{"y":{"scale":"y","field":"data.y"},"width":{"offset":-1,"scale":"x","band":true},"x":{"scale":"x","field":"data.x"},"y2":{"scale":"y","value":0}},"update":{"fill":{"value":"steelblue"},"opacity":{"value":1}},"hover":{"fill":{"value":"#FF29D2"}}}}],"data":[{"name":"d4fcfef5-9b5b-4a86-b626-6f485449746f","values":[{"x":"ferguson","y":124},{"x":"usa","y":5},{"x":"pressefreiheit","y":2},{"x":"us","y":2},{"x":"springer","y":2},{"x":"furgeson","y":2},{"x":"s21","y":2},{"x":"graw","y":2},{"x":"policestate","y":2},{"x":"arbeitsvertrag","y":2}]}],"width":800,"height":494.4375915527344,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"ordinal\", :range \"width\", :domain {:data \"d4fcfef5-9b5b-4a86-b626-6f485449746f\", :field \"data.x\"}} {:name \"y\", :range \"height\", :nice true, :domain {:data \"d4fcfef5-9b5b-4a86-b626-6f485449746f\", :field \"data.y\"}}], :marks [{:type \"rect\", :from {:data \"d4fcfef5-9b5b-4a86-b626-6f485449746f\"}, :properties {:enter {:y {:scale \"y\", :field \"data.y\"}, :width {:offset -1, :scale \"x\", :band true}, :x {:scale \"x\", :field \"data.x\"}, :y2 {:scale \"y\", :value 0}}, :update {:fill {:value \"steelblue\"}, :opacity {:value 1}}, :hover {:fill {:value \"#FF29D2\"}}}}], :data [{:name \"d4fcfef5-9b5b-4a86-b626-6f485449746f\", :values ({:x \"ferguson\", :y 124} {:x \"usa\", :y 5} {:x \"pressefreiheit\", :y 2} {:x \"us\", :y 2} {:x \"springer\", :y 2} {:x \"furgeson\", :y 2} {:x \"s21\", :y 2} {:x \"graw\", :y 2} {:x \"policestate\", :y 2} {:x \"arbeitsvertrag\", :y 2})}], :width 800, :height 494.4376, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}],"value":"[#{\"pressefreiheit\" \"us\" \"imgeilstenlandderwelt\" \"polizei\" \"springer\" \"furgeson\" \"usa\" \"s21\" \"graw\" \"medien\" \"missouri\" \"schland\" \"policestate\" \"arbeitsvertrag\" \"firstamendment\" \"ferguson\" \"afd\" \"atlantik\"} #gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"ordinal\", :range \"width\", :domain {:data \"d4fcfef5-9b5b-4a86-b626-6f485449746f\", :field \"data.x\"}} {:name \"y\", :range \"height\", :nice true, :domain {:data \"d4fcfef5-9b5b-4a86-b626-6f485449746f\", :field \"data.y\"}}], :marks [{:type \"rect\", :from {:data \"d4fcfef5-9b5b-4a86-b626-6f485449746f\"}, :properties {:enter {:y {:scale \"y\", :field \"data.y\"}, :width {:offset -1, :scale \"x\", :band true}, :x {:scale \"x\", :field \"data.x\"}, :y2 {:scale \"y\", :value 0}}, :update {:fill {:value \"steelblue\"}, :opacity {:value 1}}, :hover {:fill {:value \"#FF29D2\"}}}}], :data [{:name \"d4fcfef5-9b5b-4a86-b626-6f485449746f\", :values ({:x \"ferguson\", :y 124} {:x \"usa\", :y 5} {:x \"pressefreiheit\", :y 2} {:x \"us\", :y 2} {:x \"springer\", :y 2} {:x \"furgeson\", :y 2} {:x \"s21\", :y 2} {:x \"graw\", :y 2} {:x \"policestate\", :y 2} {:x \"arbeitsvertrag\", :y 2})}], :width 800, :height 494.4376, :padding {:bottom 20, :top 10, :right 10, :left 50}}}]"}
 ;; <=

 ;; **
@@ -227,7 +227,7 @@
   (bar-chart (keys users) (vals users) :plot-size 800))
 ;; @@
 ;; =>
-;;; {"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"ordinal","range":"width","domain":{"data":"371497d0-02d0-42e8-9d24-56d3b8d7f44d","field":"data.x"}},{"name":"y","range":"height","nice":true,"domain":{"data":"371497d0-02d0-42e8-9d24-56d3b8d7f44d","field":"data.y"}}],"marks":[{"type":"rect","from":{"data":"371497d0-02d0-42e8-9d24-56d3b8d7f44d"},"properties":{"enter":{"y":{"scale":"y","field":"data.y"},"width":{"offset":-1,"scale":"x","band":true},"x":{"scale":"x","field":"data.x"},"y2":{"scale":"y","value":0}},"update":{"fill":{"value":"steelblue"},"opacity":{"value":1}},"hover":{"fill":{"value":"#FF29D2"}}}}],"data":[{"name":"371497d0-02d0-42e8-9d24-56d3b8d7f44d","values":[{"x":"tagesschau","y":10},{"x":"stmeyer2401","y":1},{"x":"CptLeto","y":1},{"x":"g_rantelhuber","y":1},{"x":"DerAnimenator","y":1},{"x":"mistakrass","y":1},{"x":"BukosWelt","y":1},{"x":"derMylius","y":1},{"x":"DL_schreibt","y":1},{"x":"ManorMFL","y":1}]}],"width":800,"height":494.4375915527344,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"ordinal\", :range \"width\", :domain {:data \"371497d0-02d0-42e8-9d24-56d3b8d7f44d\", :field \"data.x\"}} {:name \"y\", :range \"height\", :nice true, :domain {:data \"371497d0-02d0-42e8-9d24-56d3b8d7f44d\", :field \"data.y\"}}], :marks [{:type \"rect\", :from {:data \"371497d0-02d0-42e8-9d24-56d3b8d7f44d\"}, :properties {:enter {:y {:scale \"y\", :field \"data.y\"}, :width {:offset -1, :scale \"x\", :band true}, :x {:scale \"x\", :field \"data.x\"}, :y2 {:scale \"y\", :value 0}}, :update {:fill {:value \"steelblue\"}, :opacity {:value 1}}, :hover {:fill {:value \"#FF29D2\"}}}}], :data [{:name \"371497d0-02d0-42e8-9d24-56d3b8d7f44d\", :values ({:x \"tagesschau\", :y 10} {:x \"stmeyer2401\", :y 1} {:x \"CptLeto\", :y 1} {:x \"g_rantelhuber\", :y 1} {:x \"DerAnimenator\", :y 1} {:x \"mistakrass\", :y 1} {:x \"BukosWelt\", :y 1} {:x \"derMylius\", :y 1} {:x \"DL_schreibt\", :y 1} {:x \"ManorMFL\", :y 1})}], :width 800, :height 494.4376, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}
+;;; {"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"ordinal","range":"width","domain":{"data":"19d37e13-9022-4e65-a9f6-c4caf69d630c","field":"data.x"}},{"name":"y","range":"height","nice":true,"domain":{"data":"19d37e13-9022-4e65-a9f6-c4caf69d630c","field":"data.y"}}],"marks":[{"type":"rect","from":{"data":"19d37e13-9022-4e65-a9f6-c4caf69d630c"},"properties":{"enter":{"y":{"scale":"y","field":"data.y"},"width":{"offset":-1,"scale":"x","band":true},"x":{"scale":"x","field":"data.x"},"y2":{"scale":"y","value":0}},"update":{"fill":{"value":"steelblue"},"opacity":{"value":1}},"hover":{"fill":{"value":"#FF29D2"}}}}],"data":[{"name":"19d37e13-9022-4e65-a9f6-c4caf69d630c","values":[{"x":"welt","y":10},{"x":"AufstandS21","y":6},{"x":"olaf26","y":3},{"x":"Welatpiraz","y":3},{"x":"frisch_fish","y":3},{"x":"rapic2012","y":3},{"x":"jep_","y":3},{"x":"Ibicis","y":3},{"x":"thetruemoeckert","y":3},{"x":"LakehillSoccer","y":3}]}],"width":800,"height":494.4375915527344,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"ordinal\", :range \"width\", :domain {:data \"19d37e13-9022-4e65-a9f6-c4caf69d630c\", :field \"data.x\"}} {:name \"y\", :range \"height\", :nice true, :domain {:data \"19d37e13-9022-4e65-a9f6-c4caf69d630c\", :field \"data.y\"}}], :marks [{:type \"rect\", :from {:data \"19d37e13-9022-4e65-a9f6-c4caf69d630c\"}, :properties {:enter {:y {:scale \"y\", :field \"data.y\"}, :width {:offset -1, :scale \"x\", :band true}, :x {:scale \"x\", :field \"data.x\"}, :y2 {:scale \"y\", :value 0}}, :update {:fill {:value \"steelblue\"}, :opacity {:value 1}}, :hover {:fill {:value \"#FF29D2\"}}}}], :data [{:name \"19d37e13-9022-4e65-a9f6-c4caf69d630c\", :values ({:x \"welt\", :y 10} {:x \"AufstandS21\", :y 6} {:x \"olaf26\", :y 3} {:x \"Welatpiraz\", :y 3} {:x \"frisch_fish\", :y 3} {:x \"rapic2012\", :y 3} {:x \"jep_\", :y 3} {:x \"Ibicis\", :y 3} {:x \"thetruemoeckert\", :y 3} {:x \"LakehillSoccer\", :y 3})}], :width 800, :height 494.4376, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}
 ;; <=

 ;; **
@@ -240,9 +240,120 @@
   (histogram delays :plot-size 900))
 ;; @@
 ;; =>
-;;; {"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"linear","range":"width","zero":false,"domain":{"data":"4ab1a30a-7e5d-4d95-b06d-ecef26ecff6d","field":"data.x"}},{"name":"y","type":"linear","range":"height","nice":true,"zero":false,"domain":{"data":"4ab1a30a-7e5d-4d95-b06d-ecef26ecff6d","field":"data.y"}}],"marks":[{"type":"line","from":{"data":"4ab1a30a-7e5d-4d95-b06d-ecef26ecff6d"},"properties":{"enter":{"x":{"scale":"x","field":"data.x"},"y":{"scale":"y","field":"data.y"},"interpolate":{"value":"step-before"},"fill":{"value":"steelblue"},"fillOpacity":{"value":0.4},"stroke":{"value":"steelblue"},"strokeWidth":{"value":2},"strokeOpacity":{"value":1}}}}],"data":[{"name":"4ab1a30a-7e5d-4d95-b06d-ecef26ecff6d","values":[{"x":0.0,"y":0},{"x":7002.059709821429,"y":9.0},{"x":14004.119419642859,"y":7.0},{"x":21006.17912946429,"y":4.0},{"x":28008.238839285717,"y":10.0},{"x":35010.298549107145,"y":0.0},{"x":42012.35825892857,"y":0.0},{"x":49014.41796875,"y":12.0},{"x":56016.47767857143,"y":1.0},{"x":63018.537388392855,"y":0}]}],"width":900,"height":556.2422485351562,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"linear\", :range \"width\", :zero false, :domain {:data \"4ab1a30a-7e5d-4d95-b06d-ecef26ecff6d\", :field \"data.x\"}} {:name \"y\", :type \"linear\", :range \"height\", :nice true, :zero false, :domain {:data \"4ab1a30a-7e5d-4d95-b06d-ecef26ecff6d\", :field \"data.y\"}}], :marks [{:type \"line\", :from {:data \"4ab1a30a-7e5d-4d95-b06d-ecef26ecff6d\"}, :properties {:enter {:x {:scale \"x\", :field \"data.x\"}, :y {:scale \"y\", :field \"data.y\"}, :interpolate {:value \"step-before\"}, :fill {:value \"steelblue\"}, :fillOpacity {:value 0.4}, :stroke {:value \"steelblue\"}, :strokeWidth {:value 2}, :strokeOpacity {:value 1}}}}], :data [{:name \"4ab1a30a-7e5d-4d95-b06d-ecef26ecff6d\", :values ({:x 0.0, :y 0} {:x 7002.059709821429, :y 9.0} {:x 14004.119419642859, :y 7.0} {:x 21006.17912946429, :y 4.0} {:x 28008.238839285717, :y 10.0} {:x 35010.298549107145, :y 0.0} {:x 42012.35825892857, :y 0.0} {:x 49014.41796875, :y 12.0} {:x 56016.47767857143, :y 1.0} {:x 63018.537388392855, :y 0})}], :width 900, :height 556.24225, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}
-;; <=
-
-;; @@
-
-;; @@
+;;; {"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"linear","range":"width","zero":false,"domain":{"data":"e1ae6cef-e4bc-432c-8907-3ced3cadc127","field":"data.x"}},{"name":"y","type":"linear","range":"height","nice":true,"zero":false,"domain":{"data":"e1ae6cef-e4bc-432c-8907-3ced3cadc127","field":"data.y"}}],"marks":[{"type":"line","from":{"data":"e1ae6cef-e4bc-432c-8907-3ced3cadc127"},"properties":{"enter":{"x":{"scale":"x","field":"data.x"},"y":{"scale":"y","field":"data.y"},"interpolate":{"value":"step-before"},"fill":{"value":"steelblue"},"fillOpacity":{"value":0.4},"stroke":{"value":"steelblue"},"strokeWidth":{"value":2},"strokeOpacity":{"value":1}}}}],"data":[{"name":"e1ae6cef-e4bc-432c-8907-3ced3cadc127","values":[{"x":0.0,"y":0},{"x":1888.1066406250004,"y":461.0},{"x":3776.213281250001,"y":6.0},{"x":5664.3199218750015,"y":6.0},{"x":7552.426562500002,"y":3.0},{"x":9440.533203125002,"y":0.0},{"x":11328.639843750003,"y":0.0},{"x":13216.746484375004,"y":2.0},{"x":15104.853125000005,"y":0.0},{"x":16992.959765625004,"y":0.0},{"x":18881.066406250004,"y":1.0},{"x":20769.173046875003,"y":0}]}],"width":900,"height":556.2422485351562,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"linear\", :range \"width\", :zero false, :domain {:data \"e1ae6cef-e4bc-432c-8907-3ced3cadc127\", :field \"data.x\"}} {:name \"y\", :type \"linear\", :range \"height\", :nice true, :zero false, :domain {:data \"e1ae6cef-e4bc-432c-8907-3ced3cadc127\", :field \"data.y\"}}], :marks [{:type \"line\", :from {:data \"e1ae6cef-e4bc-432c-8907-3ced3cadc127\"}, :properties {:enter {:x {:scale \"x\", :field \"data.x\"}, :y {:scale \"y\", :field \"data.y\"}, :interpolate {:value \"step-before\"}, :fill {:value \"steelblue\"}, :fillOpacity {:value 0.4}, :stroke {:value \"steelblue\"}, :strokeWidth {:value 2}, :strokeOpacity {:value 1}}}}], :data [{:name \"e1ae6cef-e4bc-432c-8907-3ced3cadc127\", :values ({:x 0.0, :y 0} {:x 1888.1066406250004, :y 461.0} {:x 3776.213281250001, :y 6.0} {:x 5664.3199218750015, :y 6.0} {:x 7552.426562500002, :y 3.0} {:x 9440.533203125002, :y 0.0} {:x 11328.639843750003, :y 0.0} {:x 13216.746484375004, :y 2.0} {:x 15104.853125000005, :y 0.0} {:x 16992.959765625004, :y 0.0} {:x 18881.066406250004, :y 1.0} {:x 20769.173046875003, :y 0})}], :width 900, :height 556.24225, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}
+;; <=
+
+;; **
+;;; ### Example Summary
+;; **
+
+;; @@
+(def dpa-summary (compute-summary "dpa"))
+;; @@
+;; =>
+;;; {"type":"html","content":"#'unsightly-reserve/dpa-summary","value":"#'unsightly-reserve/dpa-summary"}
+;; <=
+
+;; @@
+(keys dpa-summary)
+;; @@
+;; =>
+;;; {"type":"html","content":"(:source :article-count :analytics :pub-times :total-impact :avg-impact :no-reactions :avg-height)","value":"(:source :article-count :analytics :pub-times :total-impact :avg-impact :no-reactions :avg-height)"}
+;; <=
+
+;; @@
+(dissoc dpa-summary :analytics :pub-times)
+;; @@
+;; =>
+;;; {"type":"list-like","open":"{","close":"}","separator":", ","items":[{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":source","value":":source"},{"type":"html","content":""dpa"","value":"\"dpa\""}],"value":"[:source \"dpa\"]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":article-count","value":":article-count"},{"type":"html","content":"965","value":"965"}],"value":"[:article-count 965]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":total-impact","value":":total-impact"},{"type":"html","content":"4811","value":"4811"}],"value":"[:total-impact 4811]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":avg-impact","value":":avg-impact"},{"type":"html","content":"4.985492","value":"4.985492"}],"value":"[:avg-impact 4.985492]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":no-reactions","value":":no-reactions"},{"type":"html","content":"0.19170985","value":"0.19170985"}],"value":"[:no-reactions 0.19170985]"},{"type":"list-like","open":"","close":"","separator":" ","items":[{"type":"html","content":":avg-height","value":":avg-height"},{"type":"html","content":"0.98031086","value":"0.98031086"}],"value":"[:avg-height 0.98031086]"}],"value":"{:source \"dpa\", :article-count 965, :total-impact 4811, :avg-impact 4.985492, :no-reactions 0.19170985, :avg-height 0.98031086}"}
+;; <=
+
+;; @@
+(-> dpa-summary :analytics first keys)
+;; @@
+;; =>
+;;; {"type":"html","content":"(:size :height :users :pub-times :hashtags :delays)","value":"(:size :height :users :pub-times :hashtags :delays)"}
+;; <=
+
+;; @@
+(let [sizes (->> dpa-summary :analytics (map :size))]
+  (histogram sizes :plot-size 900 :bins 100))
+;; @@
+;; =>
+;;; {"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"linear","range":"width","zero":false,"domain":{"data":"19440ce8-a377-4c0e-9c4b-6e0ffe9e784d","field":"data.x"}},{"name":"y","type":"linear","range":"height","nice":true,"zero":false,"domain":{"data":"19440ce8-a377-4c0e-9c4b-6e0ffe9e784d","field":"data.y"}}],"marks":[{"type":"line","from":{"data":"19440ce8-a377-4c0e-9c4b-6e0ffe9e784d"},"properties":{"enter":{"x":{"scale":"x","field":"data.x"},"y":{"scale":"y","field":"data.y"},"interpolate":{"value":"step-before"},"fill":{"value":"steelblue"},"fillOpacity":{"value":0.4},"stroke":{"value":"steelblue"},"strokeWidth":{"value":2},"strokeOpacity":{"value":1}}}}],"data":[{"name":"19440ce8-a377-4c0e-9c4b-6e0ffe9e784d","values":[{"x":1.0,"y":0},{"x":1.56,"y":185.0},{"x":2.12,"y":112.0},{"x":2.68,"y":0.0},{"x":3.24,"y":149.0},{"x":3.8000000000000003,"y":0.0},{"x":4.36,"y":112.0},{"x":4.92,"y":0.0},{"x":5.48,"y":101.0},{"x":6.040000000000001,"y":76.0},{"x":6.600000000000001,"y":0.0},{"x":7.160000000000002,"y":48.0},{"x":7.720000000000002,"y":0.0},{"x":8.280000000000003,"y":42.0},{"x":8.840000000000003,"y":0.0},{"x":9.400000000000004,"y":40.0},{"x":9.960000000000004,"y":0.0},{"x":10.520000000000005,"y":24.0},{"x":11.080000000000005,"y":20.0},{"x":11.640000000000006,"y":0.0},{"x":12.200000000000006,"y":7.0},{"x":12.760000000000007,"y":0.0},{"x":13.320000000000007,"y":3.0},{"x":13.880000000000008,"y":0.0},{"x":14.440000000000008,"y":9.0},{"x":15.000000000000009,"y":5.0},{"x":15.56000000000001,"y":0.0},{"x":16.120000000000008,"y":4.0},{"x":16.680000000000007,"y":0.0},{"x":17.240000000000006,"y":3.0},{"x":17.800000000000004,"y":0.0},{"x":18.360000000000003,"y":6.0},{"x":18.92,"y":0.0},{"x":19.48,"y":3.0},{"x":20.04,"y":1.0},{"x":20.599999999999998,"y":0.0},{"x":21.159999999999997,"y":2.0},{"x":21.719999999999995,"y":0.0},{"x":22.279999999999994,"y":2.0},{"x":22.839999999999993,"y":0.0},{"x":23.39999999999999,"y":6.0},{"x":23.95999999999999,"y":0.0},{"x":24.51999999999999,"y":0.0},{"x":25.079999999999988,"y":0.0},{"x":25.639999999999986,"y":0.0},{"x":26.199999999999985,"y":1.0},{"x":26.759999999999984,"y":0.0},{"x":27.319999999999983,"y":1.0},{"x":27.87999999999998,"y":0.0},{"x":28.43999999999998,"y":0.0},{"x":28.99999999999998,"y":0.0},{"x":29.559999999999977,"y":0.0},{"x":30.119999999999976,"y":0.0},{"x":30.679999999999975,"y":0.0},{"x":31.239999999999974,"y":0.0},{"x":31.799999999999972,"y":0.0},{"x":32.35999999999997,"y":0.0},{"x":32.91999999999997,"y":0.0},{"x":33.479999999999976,"y":0.0},{"x":34.03999999999998,"y":0.0},{"x":34.59999999999998,"y":0.0},{"x":35.15999999999998,"y":0.0},{"x":35.719999999999985,"y":0.0},{"x":36.27999999999999,"y":0.0},{"x":36.83999999999999,"y":0.0},{"x":37.39999999999999,"y":0.0},{"x":37.959999999999994,"y":0.0},{"x":38.519999999999996,"y":0.0},{"x":39.08,"y":0.0},{"x":39.64,"y":0.0},{"x":40.2,"y":1.0},{"x":40.760000000000005,"y":0.0},{"x":41.32000000000001,"y":0.0},{"x":41.88000000000001,"y":0.0},{"x":42.44000000000001,"y":0.0},{"x":43.000000000000014,"y":0.0},{"x":43.56000000000002,"y":0.0},{"x":44.12000000000002,"y":0.0},{"x":44.68000000000002,"y":0.0},{"x":45.24000000000002,"y":0.0},{"x":45.800000000000026,"y":0.0},{"x":46.36000000000003,"y":0.0},{"x":46.92000000000003,"y":0.0},{"x":47.48000000000003,"y":0.0},{"x":48.040000000000035,"y":0.0},{"x":48.60000000000004,"y":0.0},{"x":49.16000000000004,"y":0.0},{"x":49.72000000000004,"y":0.0},{"x":50.280000000000044,"y":0.0},{"x":50.840000000000046,"y":0.0},{"x":51.40000000000005,"y":0.0},{"x":51.96000000000005,"y":0.0},{"x":52.52000000000005,"y":0.0},{"x":53.080000000000055,"y":0.0},{"x":53.64000000000006,"y":0.0},{"x":54.20000000000006,"y":0.0},{"x":54.76000000000006,"y":0.0},{"x":55.320000000000064,"y":0.0},{"x":55.88000000000007,"y":0.0},{"x":56.44000000000007,"y":1.0},{"x":57.00000000000007,"y":1.0},{"x":57.56000000000007,"y":0}]}],"width":900,"height":556.2422485351562,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"linear\", :range \"width\", :zero false, :domain {:data \"19440ce8-a377-4c0e-9c4b-6e0ffe9e784d\", :field \"data.x\"}} {:name \"y\", :type \"linear\", :range \"height\", :nice true, :zero false, :domain {:data \"19440ce8-a377-4c0e-9c4b-6e0ffe9e784d\", :field \"data.y\"}}], :marks [{:type \"line\", :from {:data \"19440ce8-a377-4c0e-9c4b-6e0ffe9e784d\"}, :properties {:enter {:x {:scale \"x\", :field \"data.x\"}, :y {:scale \"y\", :field \"data.y\"}, :interpolate {:value \"step-before\"}, :fill {:value \"steelblue\"}, :fillOpacity {:value 0.4}, :stroke {:value \"steelblue\"}, :strokeWidth {:value 2}, :strokeOpacity {:value 1}}}}], :data [{:name \"19440ce8-a377-4c0e-9c4b-6e0ffe9e784d\", :values ({:x 1.0, :y 0} {:x 1.56, :y 185.0} {:x 2.12, :y 112.0} {:x 2.68, :y 0.0} {:x 3.24, :y 149.0} {:x 3.8000000000000003, :y 0.0} {:x 4.36, :y 112.0} {:x 4.92, :y 0.0} {:x 5.48, :y 101.0} {:x 6.040000000000001, :y 76.0} {:x 6.600000000000001, :y 0.0} {:x 7.160000000000002, :y 48.0} {:x 7.720000000000002, :y 0.0} {:x 8.280000000000003, :y 42.0} {:x 8.840000000000003, :y 0.0} {:x 9.400000000000004, :y 40.0} {:x 9.960000000000004, :y 0.0} {:x 10.520000000000005, :y 24.0} {:x 11.080000000000005, :y 20.0} {:x 11.640000000000006, :y 0.0} {:x 12.200000000000006, :y 7.0} {:x 12.760000000000007, :y 0.0} {:x 13.320000000000007, :y 3.0} {:x 13.880000000000008, :y 0.0} {:x 14.440000000000008, :y 9.0} {:x 15.000000000000009, :y 5.0} {:x 15.56000000000001, :y 0.0} {:x 16.120000000000008, :y 4.0} {:x 16.680000000000007, :y 0.0} {:x 17.240000000000006, :y 3.0} {:x 17.800000000000004, :y 0.0} {:x 18.360000000000003, :y 6.0} {:x 18.92, :y 0.0} {:x 19.48, :y 3.0} {:x 20.04, :y 1.0} {:x 20.599999999999998, :y 0.0} {:x 21.159999999999997, :y 2.0} {:x 21.719999999999995, :y 0.0} {:x 22.279999999999994, :y 2.0} {:x 22.839999999999993, :y 0.0} {:x 23.39999999999999, :y 6.0} {:x 23.95999999999999, :y 0.0} {:x 24.51999999999999, :y 0.0} {:x 25.079999999999988, :y 0.0} {:x 25.639999999999986, :y 0.0} {:x 26.199999999999985, :y 1.0} {:x 26.759999999999984, :y 0.0} {:x 27.319999999999983, :y 1.0} {:x 27.87999999999998, :y 0.0} {:x 28.43999999999998, :y 0.0} {:x 28.99999999999998, :y 0.0} {:x 29.559999999999977, :y 0.0} {:x 30.119999999999976, :y 0.0} {:x 30.679999999999975, :y 0.0} {:x 31.239999999999974, :y 0.0} {:x 31.799999999999972, :y 0.0} {:x 32.35999999999997, :y 0.0} {:x 32.91999999999997, :y 0.0} {:x 33.479999999999976, :y 0.0} {:x 34.03999999999998, :y 0.0} {:x 34.59999999999998, :y 0.0} {:x 35.15999999999998, :y 0.0} {:x 35.719999999999985, :y 0.0} {:x 36.27999999999999, :y 0.0} {:x 36.83999999999999, :y 0.0} {:x 37.39999999999999, :y 0.0} {:x 37.959999999999994, :y 0.0} {:x 38.519999999999996, :y 0.0} {:x 39.08, :y 0.0} {:x 39.64, :y 0.0} {:x 40.2, :y 1.0} {:x 40.760000000000005, :y 0.0} {:x 41.32000000000001, :y 0.0} {:x 41.88000000000001, :y 0.0} {:x 42.44000000000001, :y 0.0} {:x 43.000000000000014, :y 0.0} {:x 43.56000000000002, :y 0.0} {:x 44.12000000000002, :y 0.0} {:x 44.68000000000002, :y 0.0} {:x 45.24000000000002, :y 0.0} {:x 45.800000000000026, :y 0.0} {:x 46.36000000000003, :y 0.0} {:x 46.92000000000003, :y 0.0} {:x 47.48000000000003, :y 0.0} {:x 48.040000000000035, :y 0.0} {:x 48.60000000000004, :y 0.0} {:x 49.16000000000004, :y 0.0} {:x 49.72000000000004, :y 0.0} {:x 50.280000000000044, :y 0.0} {:x 50.840000000000046, :y 0.0} {:x 51.40000000000005, :y 0.0} {:x 51.96000000000005, :y 0.0} {:x 52.52000000000005, :y 0.0} {:x 53.080000000000055, :y 0.0} {:x 53.64000000000006, :y 0.0} {:x 54.20000000000006, :y 0.0} {:x 54.76000000000006, :y 0.0} {:x 55.320000000000064, :y 0.0} {:x 55.88000000000007, :y 0.0} {:x 56.44000000000007, :y 1.0} {:x 57.00000000000007, :y 1.0} {:x 57.56000000000007, :y 0})}], :width 900, :height 556.24225, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}
+;; <=
+
+;; @@
+(let [delays (->> dpa-summary
+                  :analytics
+                  (map :delays)
+                  (map (fn [ds] (/ (reduce + ds) (count ds) 60)))
+                  (remove #(> % 1440)))]
+  (histogram delays :plot-size 900 :bins 100))
+;; @@
+;; =>
+;;; {"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"linear","range":"width","zero":false,"domain":{"data":"12db4ced-ee32-4b85-8ae0-7ebe1c800da5","field":"data.x"}},{"name":"y","type":"linear","range":"height","nice":true,"zero":false,"domain":{"data":"12db4ced-ee32-4b85-8ae0-7ebe1c800da5","field":"data.y"}}],"marks":[{"type":"line","from":{"data":"12db4ced-ee32-4b85-8ae0-7ebe1c800da5"},"properties":{"enter":{"x":{"scale":"x","field":"data.x"},"y":{"scale":"y","field":"data.y"},"interpolate":{"value":"step-before"},"fill":{"value":"steelblue"},"fillOpacity":{"value":0.4},"stroke":{"value":"steelblue"},"strokeWidth":{"value":2},"strokeOpacity":{"value":1}}}}],"data":[{"name":"12db4ced-ee32-4b85-8ae0-7ebe1c800da5","values":[{"x":0.0,"y":0},{"x":13.507833333333332,"y":477.0},{"x":27.015666666666664,"y":119.0},{"x":40.5235,"y":80.0},{"x":54.03133333333333,"y":53.0},{"x":67.53916666666666,"y":35.0},{"x":81.047,"y":31.0},{"x":94.55483333333333,"y":25.0},{"x":108.06266666666667,"y":20.0},{"x":121.57050000000001,"y":15.0},{"x":135.07833333333335,"y":15.0},{"x":148.58616666666668,"y":7.0},{"x":162.09400000000002,"y":6.0},{"x":175.60183333333336,"y":7.0},{"x":189.1096666666667,"y":3.0},{"x":202.61750000000004,"y":8.0},{"x":216.12533333333337,"y":3.0},{"x":229.6331666666667,"y":4.0},{"x":243.14100000000005,"y":2.0},{"x":256.64883333333336,"y":3.0},{"x":270.1566666666667,"y":1.0},{"x":283.66450000000003,"y":2.0},{"x":297.17233333333337,"y":2.0},{"x":310.6801666666667,"y":2.0},{"x":324.18800000000005,"y":0.0},{"x":337.6958333333334,"y":1.0},{"x":351.2036666666667,"y":1.0},{"x":364.71150000000006,"y":0.0},{"x":378.2193333333334,"y":3.0},{"x":391.72716666666673,"y":0.0},{"x":405.23500000000007,"y":0.0},{"x":418.7428333333334,"y":4.0},{"x":432.25066666666675,"y":0.0},{"x":445.7585000000001,"y":0.0},{"x":459.2663333333334,"y":0.0},{"x":472.77416666666676,"y":1.0},{"x":486.2820000000001,"y":1.0},{"x":499.78983333333343,"y":1.0},{"x":513.2976666666667,"y":0.0},{"x":526.8055,"y":0.0},{"x":540.3133333333334,"y":2.0},{"x":553.8211666666667,"y":0.0},{"x":567.3290000000001,"y":1.0},{"x":580.8368333333334,"y":0.0},{"x":594.3446666666667,"y":0.0},{"x":607.8525000000001,"y":3.0},{"x":621.3603333333334,"y":0.0},{"x":634.8681666666668,"y":1.0},{"x":648.3760000000001,"y":0.0},{"x":661.8838333333334,"y":0.0},{"x":675.3916666666668,"y":1.0},{"x":688.8995000000001,"y":0.0},{"x":702.4073333333334,"y":1.0},{"x":715.9151666666668,"y":0.0},{"x":729.4230000000001,"y":0.0},{"x":742.9308333333335,"y":1.0},{"x":756.4386666666668,"y":0.0},{"x":769.9465000000001,"y":2.0},{"x":783.4543333333335,"y":0.0},{"x":796.9621666666668,"y":0.0},{"x":810.4700000000001,"y":0.0},{"x":823.9778333333335,"y":1.0},{"x":837.4856666666668,"y":0.0},{"x":850.9935000000002,"y":1.0},{"x":864.5013333333335,"y":0.0},{"x":878.0091666666668,"y":0.0},{"x":891.5170000000002,"y":0.0},{"x":905.0248333333335,"y":0.0},{"x":918.5326666666668,"y":0.0},{"x":932.0405000000002,"y":1.0},{"x":945.5483333333335,"y":0.0},{"x":959.0561666666669,"y":1.0},{"x":972.5640000000002,"y":0.0},{"x":986.0718333333335,"y":1.0},{"x":999.5796666666669,"y":1.0},{"x":1013.0875000000002,"y":0.0},{"x":1026.5953333333334,"y":2.0},{"x":1040.1031666666668,"y":0.0},{"x":1053.611,"y":0.0},{"x":1067.1188333333334,"y":0.0},{"x":1080.6266666666668,"y":0.0},{"x":1094.1345000000001,"y":0.0},{"x":1107.6423333333335,"y":0.0},{"x":1121.1501666666668,"y":0.0},{"x":1134.6580000000001,"y":0.0},{"x":1148.1658333333335,"y":0.0},{"x":1161.6736666666668,"y":1.0},{"x":1175.1815000000001,"y":0.0},{"x":1188.6893333333335,"y":1.0},{"x":1202.1971666666668,"y":0.0},{"x":1215.7050000000002,"y":1.0},{"x":1229.2128333333335,"y":0.0},{"x":1242.7206666666668,"y":0.0},{"x":1256.2285000000002,"y":0.0},{"x":1269.7363333333335,"y":0.0},{"x":1283.2441666666668,"y":0.0},{"x":1296.7520000000002,"y":0.0},{"x":1310.2598333333335,"y":0.0},{"x":1323.7676666666669,"y":0.0},{"x":1337.2755000000002,"y":0.0},{"x":1350.7833333333335,"y":1.0},{"x":1364.2911666666669,"y":0}]}],"width":900,"height":556.2422485351562,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"linear\", :range \"width\", :zero false, :domain {:data \"12db4ced-ee32-4b85-8ae0-7ebe1c800da5\", :field \"data.x\"}} {:name \"y\", :type \"linear\", :range \"height\", :nice true, :zero false, :domain {:data \"12db4ced-ee32-4b85-8ae0-7ebe1c800da5\", :field \"data.y\"}}], :marks [{:type \"line\", :from {:data \"12db4ced-ee32-4b85-8ae0-7ebe1c800da5\"}, :properties {:enter {:x {:scale \"x\", :field \"data.x\"}, :y {:scale \"y\", :field \"data.y\"}, :interpolate {:value \"step-before\"}, :fill {:value \"steelblue\"}, :fillOpacity {:value 0.4}, :stroke {:value \"steelblue\"}, :strokeWidth {:value 2}, :strokeOpacity {:value 1}}}}], :data [{:name \"12db4ced-ee32-4b85-8ae0-7ebe1c800da5\", :values ({:x 0.0, :y 0} {:x 13.507833333333332, :y 477.0} {:x 27.015666666666664, :y 119.0} {:x 40.5235, :y 80.0} {:x 54.03133333333333, :y 53.0} {:x 67.53916666666666, :y 35.0} {:x 81.047, :y 31.0} {:x 94.55483333333333, :y 25.0} {:x 108.06266666666667, :y 20.0} {:x 121.57050000000001, :y 15.0} {:x 135.07833333333335, :y 15.0} {:x 148.58616666666668, :y 7.0} {:x 162.09400000000002, :y 6.0} {:x 175.60183333333336, :y 7.0} {:x 189.1096666666667, :y 3.0} {:x 202.61750000000004, :y 8.0} {:x 216.12533333333337, :y 3.0} {:x 229.6331666666667, :y 4.0} {:x 243.14100000000005, :y 2.0} {:x 256.64883333333336, :y 3.0} {:x 270.1566666666667, :y 1.0} {:x 283.66450000000003, :y 2.0} {:x 297.17233333333337, :y 2.0} {:x 310.6801666666667, :y 2.0} {:x 324.18800000000005, :y 0.0} {:x 337.6958333333334, :y 1.0} {:x 351.2036666666667, :y 1.0} {:x 364.71150000000006, :y 0.0} {:x 378.2193333333334, :y 3.0} {:x 391.72716666666673, :y 0.0} {:x 405.23500000000007, :y 0.0} {:x 418.7428333333334, :y 4.0} {:x 432.25066666666675, :y 0.0} {:x 445.7585000000001, :y 0.0} {:x 459.2663333333334, :y 0.0} {:x 472.77416666666676, :y 1.0} {:x 486.2820000000001, :y 1.0} {:x 499.78983333333343, :y 1.0} {:x 513.2976666666667, :y 0.0} {:x 526.8055, :y 0.0} {:x 540.3133333333334, :y 2.0} {:x 553.8211666666667, :y 0.0} {:x 567.3290000000001, :y 1.0} {:x 580.8368333333334, :y 0.0} {:x 594.3446666666667, :y 0.0} {:x 607.8525000000001, :y 3.0} {:x 621.3603333333334, :y 0.0} {:x 634.8681666666668, :y 1.0} {:x 648.3760000000001, :y 0.0} {:x 661.8838333333334, :y 0.0} {:x 675.3916666666668, :y 1.0} {:x 688.8995000000001, :y 0.0} {:x 702.4073333333334, :y 1.0} {:x 715.9151666666668, :y 0.0} {:x 729.4230000000001, :y 0.0} {:x 742.9308333333335, :y 1.0} {:x 756.4386666666668, :y 0.0} {:x 769.9465000000001, :y 2.0} {:x 783.4543333333335, :y 0.0} {:x 796.9621666666668, :y 0.0} {:x 810.4700000000001, :y 0.0} {:x 823.9778333333335, :y 1.0} {:x 837.4856666666668, :y 0.0} {:x 850.9935000000002, :y 1.0} {:x 864.5013333333335, :y 0.0} {:x 878.0091666666668, :y 0.0} {:x 891.5170000000002, :y 0.0} {:x 905.0248333333335, :y 0.0} {:x 918.5326666666668, :y 0.0} {:x 932.0405000000002, :y 1.0} {:x 945.5483333333335, :y 0.0} {:x 959.0561666666669, :y 1.0} {:x 972.5640000000002, :y 0.0} {:x 986.0718333333335, :y 1.0} {:x 999.5796666666669, :y 1.0} {:x 1013.0875000000002, :y 0.0} {:x 1026.5953333333334, :y 2.0} {:x 1040.1031666666668, :y 0.0} {:x 1053.611, :y 0.0} {:x 1067.1188333333334, :y 0.0} {:x 1080.6266666666668, :y 0.0} {:x 1094.1345000000001, :y 0.0} {:x 1107.6423333333335, :y 0.0} {:x 1121.1501666666668, :y 0.0} {:x 1134.6580000000001, :y 0.0} {:x 1148.1658333333335, :y 0.0} {:x 1161.6736666666668, :y 1.0} {:x 1175.1815000000001, :y 0.0} {:x 1188.6893333333335, :y 1.0} {:x 1202.1971666666668, :y 0.0} {:x 1215.7050000000002, :y 1.0} {:x 1229.2128333333335, :y 0.0} {:x 1242.7206666666668, :y 0.0} {:x 1256.2285000000002, :y 0.0} {:x 1269.7363333333335, :y 0.0} {:x 1283.2441666666668, :y 0.0} {:x 1296.7520000000002, :y 0.0} {:x 1310.2598333333335, :y 0.0} {:x 1323.7676666666669, :y 0.0} {:x 1337.2755000000002, :y 0.0} {:x 1350.7833333333335, :y 1.0} {:x 1364.2911666666669, :y 0})}], :width 900, :height 556.24225, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}
+;; <=
+
+;; @@
+(let [heights (->> dpa-summary :analytics (map :height))]
+  (histogram heights :plot-size 900 :bins 10))
+;; @@
+;; =>
+;;; {"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"linear","range":"width","zero":false,"domain":{"data":"26d75bbd-1c8a-4322-8af8-d0cdeb515d2e","field":"data.x"}},{"name":"y","type":"linear","range":"height","nice":true,"zero":false,"domain":{"data":"26d75bbd-1c8a-4322-8af8-d0cdeb515d2e","field":"data.y"}}],"marks":[{"type":"line","from":{"data":"26d75bbd-1c8a-4322-8af8-d0cdeb515d2e"},"properties":{"enter":{"x":{"scale":"x","field":"data.x"},"y":{"scale":"y","field":"data.y"},"interpolate":{"value":"step-before"},"fill":{"value":"steelblue"},"fillOpacity":{"value":0.4},"stroke":{"value":"steelblue"},"strokeWidth":{"value":2},"strokeOpacity":{"value":1}}}}],"data":[{"name":"26d75bbd-1c8a-4322-8af8-d0cdeb515d2e","values":[{"x":0.0,"y":0},{"x":0.7000000000000001,"y":185.0},{"x":1.4000000000000001,"y":661.0},{"x":2.1,"y":92.0},{"x":2.8000000000000003,"y":0.0},{"x":3.5000000000000004,"y":15.0},{"x":4.2,"y":8.0},{"x":4.9,"y":0.0},{"x":5.6000000000000005,"y":1.0},{"x":6.300000000000001,"y":2.0},{"x":7.000000000000001,"y":1.0},{"x":7.700000000000001,"y":0}]}],"width":900,"height":556.2422485351562,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"linear\", :range \"width\", :zero false, :domain {:data \"26d75bbd-1c8a-4322-8af8-d0cdeb515d2e\", :field \"data.x\"}} {:name \"y\", :type \"linear\", :range \"height\", :nice true, :zero false, :domain {:data \"26d75bbd-1c8a-4322-8af8-d0cdeb515d2e\", :field \"data.y\"}}], :marks [{:type \"line\", :from {:data \"26d75bbd-1c8a-4322-8af8-d0cdeb515d2e\"}, :properties {:enter {:x {:scale \"x\", :field \"data.x\"}, :y {:scale \"y\", :field \"data.y\"}, :interpolate {:value \"step-before\"}, :fill {:value \"steelblue\"}, :fillOpacity {:value 0.4}, :stroke {:value \"steelblue\"}, :strokeWidth {:value 2}, :strokeOpacity {:value 1}}}}], :data [{:name \"26d75bbd-1c8a-4322-8af8-d0cdeb515d2e\", :values ({:x 0.0, :y 0} {:x 0.7000000000000001, :y 185.0} {:x 1.4000000000000001, :y 661.0} {:x 2.1, :y 92.0} {:x 2.8000000000000003, :y 0.0} {:x 3.5000000000000004, :y 15.0} {:x 4.2, :y 8.0} {:x 4.9, :y 0.0} {:x 5.6000000000000005, :y 1.0} {:x 6.300000000000001, :y 2.0} {:x 7.000000000000001, :y 1.0} {:x 7.700000000000001, :y 0})}], :width 900, :height 556.24225, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}
+;; <=
+
+;; @@
+(let [hashtags (->> dpa-summary
+                  :analytics
+                  (map :hashtags)
+                  (apply concat)
+                  (remove #{"dpa" "dpavolo"})
+                  frequencies
+                  (sort-by second >)
+                  (take 20))]
+  [(keys hashtags)
+  (bar-chart (keys hashtags) (vals hashtags) :plot-size 1000)])
+;; @@
+;; =>
+;;; {"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"("ebola" "is" "sltw14" "wowereit" "ferguson" "snowden" "hongkong" "nsu" "uber" "afd" "indyref" "mh17" "china" "icebucketchallenge" "apple" "nsa" "news" "n24" "piraten" "tohti")","value":"(\"ebola\" \"is\" \"sltw14\" \"wowereit\" \"ferguson\" \"snowden\" \"hongkong\" \"nsu\" \"uber\" \"afd\" \"indyref\" \"mh17\" \"china\" \"icebucketchallenge\" \"apple\" \"nsa\" \"news\" \"n24\" \"piraten\" \"tohti\")"},{"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"ordinal","range":"width","domain":{"data":"90c80f82-240c-4c0c-ab4c-a783e2a3b731","field":"data.x"}},{"name":"y","range":"height","nice":true,"domain":{"data":"90c80f82-240c-4c0c-ab4c-a783e2a3b731","field":"data.y"}}],"marks":[{"type":"rect","from":{"data":"90c80f82-240c-4c0c-ab4c-a783e2a3b731"},"properties":{"enter":{"y":{"scale":"y","field":"data.y"},"width":{"offset":-1,"scale":"x","band":true},"x":{"scale":"x","field":"data.x"},"y2":{"scale":"y","value":0}},"update":{"fill":{"value":"steelblue"},"opacity":{"value":1}},"hover":{"fill":{"value":"#FF29D2"}}}}],"data":[{"name":"90c80f82-240c-4c0c-ab4c-a783e2a3b731","values":[{"x":"ebola","y":47},{"x":"is","y":45},{"x":"sltw14","y":34},{"x":"wowereit","y":33},{"x":"ferguson","y":30},{"x":"snowden","y":27},{"x":"hongkong","y":25},{"x":"nsu","y":22},{"x":"uber","y":20},{"x":"afd","y":19},{"x":"indyref","y":18},{"x":"mh17","y":17},{"x":"china","y":17},{"x":"icebucketchallenge","y":16},{"x":"apple","y":15},{"x":"nsa","y":15},{"x":"news","y":14},{"x":"n24","y":14},{"x":"piraten","y":14},{"x":"tohti","y":13}]}],"width":1000,"height":618.0469970703125,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"ordinal\", :range \"width\", :domain {:data \"90c80f82-240c-4c0c-ab4c-a783e2a3b731\", :field \"data.x\"}} {:name \"y\", :range \"height\", :nice true, :domain {:data \"90c80f82-240c-4c0c-ab4c-a783e2a3b731\", :field \"data.y\"}}], :marks [{:type \"rect\", :from {:data \"90c80f82-240c-4c0c-ab4c-a783e2a3b731\"}, :properties {:enter {:y {:scale \"y\", :field \"data.y\"}, :width {:offset -1, :scale \"x\", :band true}, :x {:scale \"x\", :field \"data.x\"}, :y2 {:scale \"y\", :value 0}}, :update {:fill {:value \"steelblue\"}, :opacity {:value 1}}, :hover {:fill {:value \"#FF29D2\"}}}}], :data [{:name \"90c80f82-240c-4c0c-ab4c-a783e2a3b731\", :values ({:x \"ebola\", :y 47} {:x \"is\", :y 45} {:x \"sltw14\", :y 34} {:x \"wowereit\", :y 33} {:x \"ferguson\", :y 30} {:x \"snowden\", :y 27} {:x \"hongkong\", :y 25} {:x \"nsu\", :y 22} {:x \"uber\", :y 20} {:x \"afd\", :y 19} {:x \"indyref\", :y 18} {:x \"mh17\", :y 17} {:x \"china\", :y 17} {:x \"icebucketchallenge\", :y 16} {:x \"apple\", :y 15} {:x \"nsa\", :y 15} {:x \"news\", :y 14} {:x \"n24\", :y 14} {:x \"piraten\", :y 14} {:x \"tohti\", :y 13})}], :width 1000, :height 618.047, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}],"value":"[(\"ebola\" \"is\" \"sltw14\" \"wowereit\" \"ferguson\" \"snowden\" \"hongkong\" \"nsu\" \"uber\" \"afd\" \"indyref\" \"mh17\" \"china\" \"icebucketchallenge\" \"apple\" \"nsa\" \"news\" \"n24\" \"piraten\" \"tohti\") #gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"ordinal\", :range \"width\", :domain {:data \"90c80f82-240c-4c0c-ab4c-a783e2a3b731\", :field \"data.x\"}} {:name \"y\", :range \"height\", :nice true, :domain {:data \"90c80f82-240c-4c0c-ab4c-a783e2a3b731\", :field \"data.y\"}}], :marks [{:type \"rect\", :from {:data \"90c80f82-240c-4c0c-ab4c-a783e2a3b731\"}, :properties {:enter {:y {:scale \"y\", :field \"data.y\"}, :width {:offset -1, :scale \"x\", :band true}, :x {:scale \"x\", :field \"data.x\"}, :y2 {:scale \"y\", :value 0}}, :update {:fill {:value \"steelblue\"}, :opacity {:value 1}}, :hover {:fill {:value \"#FF29D2\"}}}}], :data [{:name \"90c80f82-240c-4c0c-ab4c-a783e2a3b731\", :values ({:x \"ebola\", :y 47} {:x \"is\", :y 45} {:x \"sltw14\", :y 34} {:x \"wowereit\", :y 33} {:x \"ferguson\", :y 30} {:x \"snowden\", :y 27} {:x \"hongkong\", :y 25} {:x \"nsu\", :y 22} {:x \"uber\", :y 20} {:x \"afd\", :y 19} {:x \"indyref\", :y 18} {:x \"mh17\", :y 17} {:x \"china\", :y 17} {:x \"icebucketchallenge\", :y 16} {:x \"apple\", :y 15} {:x \"nsa\", :y 15} {:x \"news\", :y 14} {:x \"n24\", :y 14} {:x \"piraten\", :y 14} {:x \"tohti\", :y 13})}], :width 1000, :height 618.047, :padding {:bottom 20, :top 10, :right 10, :left 50}}}]"}
+;; <=
+
+;; @@
+(def dpa-users (->> dpa-summary
+                  :analytics
+                  (map :users)))
+;; @@
+;; =>
+;;; {"type":"html","content":"#'unsightly-reserve/dpa-users","value":"#'unsightly-reserve/dpa-users"}
+;; <=
+
+;; @@
+(let [users (->> dpa-users
+                 (apply concat)
+                 (remove #{"dpa"})
+                 frequencies
+                 (sort-by second >)
+                 (take 15))]
+  [(keys users)
+  (bar-chart (keys users) (vals users) :plot-size 1000)])
+;; @@
+;; =>
+;;; {"type":"list-like","open":"[","close":"]","separator":" ","items":[{"type":"html","content":"("Dietmar_Bauer" "alanyanews_eu" "thesirenofangel" "grimneko" "2014FL" "BBattmer" "S_Tagblatt" "Klostifan1981" "ChrisBrey1" "DietrichOpal" "martinromanczyk" "Dennis_Snehotta" "Liane13" "andreaslandwehr" "WOLKEFN")","value":"(\"Dietmar_Bauer\" \"alanyanews_eu\" \"thesirenofangel\" \"grimneko\" \"2014FL\" \"BBattmer\" \"S_Tagblatt\" \"Klostifan1981\" \"ChrisBrey1\" \"DietrichOpal\" \"martinromanczyk\" \"Dennis_Snehotta\" \"Liane13\" \"andreaslandwehr\" \"WOLKEFN\")"},{"type":"vega","content":{"axes":[{"scale":"x","type":"x"},{"scale":"y","type":"y"}],"scales":[{"name":"x","type":"ordinal","range":"width","domain":{"data":"1a0f4889-685a-4e77-8947-83dcaa838d4b","field":"data.x"}},{"name":"y","range":"height","nice":true,"domain":{"data":"1a0f4889-685a-4e77-8947-83dcaa838d4b","field":"data.y"}}],"marks":[{"type":"rect","from":{"data":"1a0f4889-685a-4e77-8947-83dcaa838d4b"},"properties":{"enter":{"y":{"scale":"y","field":"data.y"},"width":{"offset":-1,"scale":"x","band":true},"x":{"scale":"x","field":"data.x"},"y2":{"scale":"y","value":0}},"update":{"fill":{"value":"steelblue"},"opacity":{"value":1}},"hover":{"fill":{"value":"#FF29D2"}}}}],"data":[{"name":"1a0f4889-685a-4e77-8947-83dcaa838d4b","values":[{"x":"Dietmar_Bauer","y":120},{"x":"alanyanews_eu","y":55},{"x":"thesirenofangel","y":47},{"x":"grimneko","y":32},{"x":"2014FL","y":30},{"x":"BBattmer","y":30},{"x":"S_Tagblatt","y":29},{"x":"Klostifan1981","y":26},{"x":"ChrisBrey1","y":24},{"x":"DietrichOpal","y":23},{"x":"martinromanczyk","y":22},{"x":"Dennis_Snehotta","y":21},{"x":"Liane13","y":20},{"x":"andreaslandwehr","y":19},{"x":"WOLKEFN","y":19}]}],"width":1000,"height":618.0469970703125,"padding":{"bottom":20,"top":10,"right":10,"left":50}},"value":"#gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"ordinal\", :range \"width\", :domain {:data \"1a0f4889-685a-4e77-8947-83dcaa838d4b\", :field \"data.x\"}} {:name \"y\", :range \"height\", :nice true, :domain {:data \"1a0f4889-685a-4e77-8947-83dcaa838d4b\", :field \"data.y\"}}], :marks [{:type \"rect\", :from {:data \"1a0f4889-685a-4e77-8947-83dcaa838d4b\"}, :properties {:enter {:y {:scale \"y\", :field \"data.y\"}, :width {:offset -1, :scale \"x\", :band true}, :x {:scale \"x\", :field \"data.x\"}, :y2 {:scale \"y\", :value 0}}, :update {:fill {:value \"steelblue\"}, :opacity {:value 1}}, :hover {:fill {:value \"#FF29D2\"}}}}], :data [{:name \"1a0f4889-685a-4e77-8947-83dcaa838d4b\", :values ({:x \"Dietmar_Bauer\", :y 120} {:x \"alanyanews_eu\", :y 55} {:x \"thesirenofangel\", :y 47} {:x \"grimneko\", :y 32} {:x \"2014FL\", :y 30} {:x \"BBattmer\", :y 30} {:x \"S_Tagblatt\", :y 29} {:x \"Klostifan1981\", :y 26} {:x \"ChrisBrey1\", :y 24} {:x \"DietrichOpal\", :y 23} {:x \"martinromanczyk\", :y 22} {:x \"Dennis_Snehotta\", :y 21} {:x \"Liane13\", :y 20} {:x \"andreaslandwehr\", :y 19} {:x \"WOLKEFN\", :y 19})}], :width 1000, :height 618.047, :padding {:bottom 20, :top 10, :right 10, :left 50}}}"}],"value":"[(\"Dietmar_Bauer\" \"alanyanews_eu\" \"thesirenofangel\" \"grimneko\" \"2014FL\" \"BBattmer\" \"S_Tagblatt\" \"Klostifan1981\" \"ChrisBrey1\" \"DietrichOpal\" \"martinromanczyk\" \"Dennis_Snehotta\" \"Liane13\" \"andreaslandwehr\" \"WOLKEFN\") #gorilla_repl.vega.VegaView{:content {:axes [{:scale \"x\", :type \"x\"} {:scale \"y\", :type \"y\"}], :scales [{:name \"x\", :type \"ordinal\", :range \"width\", :domain {:data \"1a0f4889-685a-4e77-8947-83dcaa838d4b\", :field \"data.x\"}} {:name \"y\", :range \"height\", :nice true, :domain {:data \"1a0f4889-685a-4e77-8947-83dcaa838d4b\", :field \"data.y\"}}], :marks [{:type \"rect\", :from {:data \"1a0f4889-685a-4e77-8947-83dcaa838d4b\"}, :properties {:enter {:y {:scale \"y\", :field \"data.y\"}, :width {:offset -1, :scale \"x\", :band true}, :x {:scale \"x\", :field \"data.x\"}, :y2 {:scale \"y\", :value 0}}, :update {:fill {:value \"steelblue\"}, :opacity {:value 1}}, :hover {:fill {:value \"#FF29D2\"}}}}], :data [{:name \"1a0f4889-685a-4e77-8947-83dcaa838d4b\", :values ({:x \"Dietmar_Bauer\", :y 120} {:x \"alanyanews_eu\", :y 55} {:x \"thesirenofangel\", :y 47} {:x \"grimneko\", :y 32} {:x \"2014FL\", :y 30} {:x \"BBattmer\", :y 30} {:x \"S_Tagblatt\", :y 29} {:x \"Klostifan1981\", :y 26} {:x \"ChrisBrey1\", :y 24} {:x \"DietrichOpal\", :y 23} {:x \"martinromanczyk\", :y 22} {:x \"Dennis_Snehotta\", :y 21} {:x \"Liane13\", :y 20} {:x \"andreaslandwehr\", :y 19} {:x \"WOLKEFN\", :y 19})}], :width 1000, :height 618.047, :padding {:bottom 20, :top 10, :right 10, :left 50}}}]"}
+;; <=
+
+;; **
+;;; ### Unique users
+;; **
+
+;; @@
+(float (/ (->> dpa-users (apply concat) frequencies vals (remove #(> % 1)) count)
+          (->> dpa-users (apply concat) (into #{}) count)))
+;; @@
+;; =>
+;;; {"type":"html","content":"0.6464471","value":"0.6464471"}
+;; <=
+
+;; @@
+
+;; @@


Add 'description' and 'describe' macros

Add 'description' and 'describe' macros

--- src/main/clojure/com/stuartsierra/lazytest.clj
+++ src/main/clojure/com/stuartsierra/lazytest.clj
@@ -1,4 +1,69 @@
-(ns com.stuartsierra.lazytest)
+(ns com.stuartsierra.lazytest
+  (:use [com.stuartsierra.lazytest.arguments
+         :only (get-arg get-options standard-metadata firsts seconds)]
+        [com.stuartsierra.lazytest.groups
+         :only (group group-examples)]
+        [com.stuartsierra.lazytest.contexts
+         :only (context)]
+        [com.stuartsierra.lazytest.attach
+         :only (add-group!)]))
+
+(declare describe description)
+
+(defn- description-form? [form]
+  (and (seq? form)
+       (= #'description (resolve (first form)))))
+
+(defn- split-examples-and-subgroups [args]
+  [(remove description-form? args)
+   (vec (filter description-form? args))])
+
+(defmacro description
+  "Returns an example group.  body begins with an optional doc string,
+  followed by key-value options, followed by example expressions
+  and/or nested groups.
+
+  Option :using is followed by a vector of symbol-context pairs.  All
+  examples in the group will run with the symbol bound to the state
+  returned by that context.
+
+  Option :given is followed by a vector of symbol-expression pairs.
+  All examples in the group will run with the symbol bound to the
+  state returned by that expression."
+  [& body]
+  (let [[docstring body] (get-arg string? body)
+        [opts body] (get-options body)
+        givens (interleave (firsts (:given opts))
+                           (map (fn [e] `(context [] ~e))
+                                (seconds (:given opts))))
+        bindings (vec (concat (:using opts) givens))
+        [examples subgroups] (split-examples-and-subgroups body)]
+    `(with-meta (group ~bindings (group-examples ~@examples) ~subgroups)
+       ~(standard-metadata &form docstring))))
+
+(defn- replace-nested-describe [form]
+  (if (and (seq? form)
+           (= #'describe (resolve (first form))))
+    (if (symbol? (second form))
+      (throw (IllegalArgumentException.
+              "Nested descriptions cannot be attached to Vars."))
+      `(description ~@(rest form)))
+    form))
+
+(defmacro describe
+  "Creates an example group and attaches it to a target.  If first
+  argument is a symbol, the group will be attached to that Var.  If
+  first argument is a string, the group will be attached to the
+  current namespace.  Remaining arguments are like 'description'."
+  [& body]
+  (let [[target body] (get-arg symbol? body)
+        [docstring body] (get-arg string? body)
+        body (map replace-nested-describe body)
+        target-ref (if target `(var ~target) `*ns*)]
+    `(add-group! ~target-ref
+                 (with-meta (description ~@body)
+                   (assoc ~(standard-metadata &form docstring)
+                     :target ~target-ref)))))

 (defmacro thrown?
   "Returns true if body throws an instance of class c."


add assertion-result? helper

add assertion-result? helper

--- src/main/clojure/com/stuartsierra/lazytest.clj
+++ src/main/clojure/com/stuartsierra/lazytest.clj
@@ -270,6 +270,12 @@

 ;;; TEST RESULT HANDLING

+(defn assertion-result?
+  "True if r is an assertion result (pass, fail, or throw)"
+  [r]
+  (#{::AssertionPassed ::AssertionFailed ::AssertionThrown}
+   (type r)))
+
 (defn result-seq
   "Given a single TestResult, returns a depth-first sequence of that
   TestResult and all its children."


RS + AB | #144 | Try changing twitter oauth authorize url

--- src/objective8/front_end/workflows/twitter.clj
+++ src/objective8/front_end/workflows/twitter.clj
@@ -14,7 +14,7 @@
                                     secret-token
                                     "https://api.twitter.com/oauth/request_token"
                                     "https://api.twitter.com/oauth/access_token"
-                                    "https://api.twitter.com/oauth/authenticate"
+                                    "https://api.twitter.com/oauth/authorize"
                                     :hmac-sha1)
      :callback-url (str utils/host-url "/twitter-callback")}
     :invalid-configuration))


adds log for async status with location header not starting with a slash (#1003)

--- waiter/src/waiter/async_request.clj
+++ waiter/src/waiter/async_request.clj
@@ -105,7 +105,9 @@
                         (let [location-header (get headers "location")
                               location (normalize-location-header status-endpoint location-header)]
                           (if (str/starts-with? (str location) "/")
-                            (recur (max 0 (- ttl check-interval-ms)))
+                            (do
+                              (log/info "continuing async request status checks as location is a relative path:" location)
+                              (recur (max 0 (- ttl check-interval-ms))))
                             (do
                               (log/info "completing async request as result location is not a relative path:" location)
                               (complete-async-request :success)


reduce stdout output while running unit tests (#27)

--- waiter/test/waiter/test_helpers.clj
+++ waiter/test/waiter/test_helpers.clj
@@ -64,8 +64,7 @@
   (defmethod clojure.test/report :end-test-var [m]
     (let [test-name (full-test-name m)]
       (with-test-out
-        (println \tab (blue "FINISH:") test-name)
-        (println \tab "COUNTS:" (assoc @*report-counters* :name test-name)))
+        (println \tab (blue "FINISH:") test-name @*report-counters*))
       (swap! running-tests #(dissoc % test-name))
       (log-running-tests))))


prevent all issue cards from reanimating on refresh

--- src-cljs/frontend/components/issues.cljs
+++ src-cljs/frontend/components/issues.cljs
@@ -537,7 +537,7 @@
          [:section.menu-view.issues-list
           [:div.content.make
            (om/build issue-form {})]
-          [:div.issue-cards.make
+          [:div.issue-cards.make {:key "issue-cards"}
            (let [deleted (set/difference rendered-issue-ids all-issue-ids)
                  added (set/difference all-issue-ids rendered-issue-ids)]
              (when (or (seq deleted) (seq added))


Change root view name.

Change root view name.

--- src/cljs/openslack/views.cljs
+++ src/cljs/openslack/views.cljs
@@ -12,7 +12,7 @@
 (defn app [state owner]
   (reify
     om/IDisplayName
-    (display-name [_] "Sloth")
+    (display-name [_] "sloth")

     om/IRender
     (render [_]


fix ClassCastException in test spout

fix ClassCastException in test spout

--- test/marceline/storm/testing/trident_wordcount_test.clj
+++ test/marceline/storm/testing/trident_wordcount_test.clj
@@ -10,10 +10,10 @@
         storm.trident.testing
         marceline.storm.testing.trident-wordcount))

-(def test-vals '("the cow jumped over the moon"
-                 "four score and seven years ago"
-                 "how many can you eat"
-                 "to be or not to be the person"))
+(def test-vals [["the cow jumped over the moon"]
+                ["four score and seven years ago"]
+                ["how many can you eat"]
+                ["to be or not to be the person"]])

 (deftest wordcount-drpc
   (t/with-local-cluster [cluster]
@@ -21,9 +21,9 @@
       (let [feeder (t/feeder-spout ["sentence"])
             topology (build-topology feeder drpc)]
         (with-topology [cluster topology]
-          (feed feeder (into-array test-vals))
+          (feed feeder test-vals)
           (is (= 4
                  (ffirst
-                   (exec-drpc drpc "words"
-                              "cat dog the man jumped"))))
-          )))))
+                  (exec-drpc drpc
+                             "words"
+                             "cat dog the man jumped")))))))))


Account for alternate configurations.

Account for alternate configurations.

--- test/onyx/log/percentage_grouping_generative_test.clj
+++ test/onyx/log/percentage_grouping_generative_test.clj
@@ -238,5 +238,7 @@
          :peer-choices []}))]
      (let [[t1 t2 t3] (:tasks (:args rets))]
        (is (= 1 (count (get (get (:allocations replica) job-4-id) t1))))
-       (is (= 3 (count (get (get (:allocations replica) job-4-id) t2))))
-       (is (= 6 (count (get (get (:allocations replica) job-4-id) t3))))))))
+       (is (<= 3 (count (get (get (:allocations replica) job-4-id) t2))))
+       (is (>= 6 (count (get (get (:allocations replica) job-4-id) t3))))
+       (is (= 9 (+ (count (get (get (:allocations replica) job-4-id) t2))
+                   (count (get (get (:allocations replica) job-4-id) t3)))))))))


Added test comment

Added test comment

--- test/puppetlabs/master/certificate_authority_test.clj
+++ test/puppetlabs/master/certificate_authority_test.clj
@@ -660,7 +660,7 @@
                            {:oid      "1.3.6.1.4.1.34380.1.1.1"
                             :critical false
                             :value    "UUUU-IIIII-DDD"}]]
-        (is (= exts exts-expected))))
+        (is (= exts exts-expected "The puppet trusted facts extenions were not added by create-agent-extensions"))))

     (testing "only puppet extensions are extracted from CSR and DNS alt names is ignored."
       (let [csr-exts           [(utils/subject-dns-alt-names


Dynamically create empty.ini file

Dynamically create empty.ini file

--- test/puppetlabs/trapperkeeper/testutils/bootstrap.clj
+++ test/puppetlabs/trapperkeeper/testutils/bootstrap.clj
@@ -1,12 +1,14 @@
 (ns puppetlabs.trapperkeeper.testutils.bootstrap
-  (:require [puppetlabs.trapperkeeper.core :as tk]
+  (:require [fs.core :as fs]
+            [puppetlabs.trapperkeeper.core :as tk]
             [puppetlabs.trapperkeeper.app :as tk-app]
             [puppetlabs.kitchensink.testutils :as ks-testutils]
             [puppetlabs.trapperkeeper.internal :refer [parse-cli-args!]]
             [puppetlabs.trapperkeeper.bootstrap :as bootstrap]
             [puppetlabs.trapperkeeper.config :as config]))

-(def empty-config "./test-resources/config/empty.ini")
+(def empty-config "./target/empty.ini")
+(fs/touch empty-config)

 (defmacro with-app-with-config
   [app services config & body]


Account subpage values need to be keywords

The subpage component lookup in frontend.components.account/account
depends on the subpage value being a keyword.

This is a targeted fix for a bug we're seeing in production, there may
be other cases.

--- src-cljs/frontend/routes.cljs
+++ src-cljs/frontend/routes.cljs
@@ -96,7 +96,7 @@
   (defroute v1-account "/account" []
     (open-to-inner! nav-ch :account {:subpage nil}))
   (defroute v1-account-subpage "/account/:subpage" [subpage]
-    (open-to-inner! nav-ch :account {:subpage subpage}))
+    (open-to-inner! nav-ch :account {:subpage (keyword subpage)}))
   (defroute v1-logout "/logout" []
     (logout! nav-ch))


update param name

update param name

--- src/clj/org/openforis/ceo/db/imagery.clj
+++ src/clj/org/openforis/ceo/db/imagery.clj
@@ -9,7 +9,7 @@
     (dissoc source-config [:geoserverParams :accessToken])
     source-config))

-(defn- prepare-imagery [imagery admin?]
+(defn- prepare-imagery [imagery inst-admin?]
   (mapv (fn [{:keys [imagery_id institution_id visibility title attribution extent source_config]}]
           (let [source-config (tc/jsonb->clj source_config)]
             {:id           imagery_id
@@ -18,7 +18,7 @@
              :title        title
              :attribution  attribution
              :extent       (tc/jsonb->clj extent)
-             :sourceConfig (if admin? source-config (clean-source source-config))}))
+             :sourceConfig (if inst-admin? source-config (clean-source source-config))}))
         imagery))

 (defn get-institution-imagery [{:keys [params]}]


Replace navbar-nav class with tailwind

Replace navbar-nav class with tailwind

--- src/cljs/my_money/components/navbar.cljs
+++ src/cljs/my_money/components/navbar.cljs
@@ -35,10 +35,10 @@
         [:span.navbar-toggler-icon]]
        [:div.collapse.navbar-collapse
         (when-not @collapsed? {:class "show"})
-        [:ul.navbar-nav
+        [:ul.flex.pl-0.mb-0.list-none
          [nav-link "#/" "Home" :home collapsed?]
          (when (session/get :identity)
-           [:ul.navbar-nav
+           [:<>
             [:button.btn.btn-outline-info.fa.fa-cog.fa-inverse.ml-1 {:on-click #(routes/navigate! :config)}]
             [:button.btn.btn-outline-info.ml-1 {:on-click #(routes/navigate! :upload)} "Upload"]])]
         [user-menu e!]]])))


adding query to CBL

adding query to CBL

--- src/clojure/my/company/superapp/main.clj
+++ src/clojure/my/company/superapp/main.clj
@@ -24,6 +24,7 @@
              java.util.UUID
              com.couchbase.lite.Manager
              com.couchbase.lite.Mapper
+             com.couchbase.lite.Query
              com.couchbase.lite.Document$DocumentUpdater
              com.couchbase.lite.android.AndroidContext
              com.couchbase.lite.util.Log
@@ -153,7 +154,7 @@
                       (log/i "calling setUserProperties")
                       (.setUserProperties new-revision
                                           (assoc (into {}  properties)
-                                                 "name" "loco" "phone" "03649556"))
+                                                 "type" "person" "name" "loco" "phone" "03649556"))
                       true
                           )))]
     updater
@@ -165,9 +166,8 @@
   (let [mapper (proxy [Mapper] []
                  (map
                    [document, emitter]
-                   (log/i "testing mapper view function")
-                   (log/i (str "mapper:" document))
-                   (.emit emitter (get document "phone") (get document "name"))
+                   (log/i (str "Mapper:" document))
+                   (.emit emitter ["stam" (get document "phone")] (get document "name"))
                    ))]
     mapper
     )
@@ -266,26 +266,26 @@
     (def manager (Manager. (AndroidContext. (*a)) (.get (.getField Manager "DEFAULT_OPTIONS") nil)))
     (.setStorageType manager "ForestDB")
     (log/i "creteing database")
-    (def db-name "phones")
+    (def db-name "persons")
     (def database (.getDatabase manager db-name))
     (log/i "creating document")
     (def document (.createDocument database))
     ;; Views and mappers
-    (def new-view (.getView database "test"))
-    (.setMap new-view (document-mapper) "1")
+    (def new-view (.getView database "persons"))
+    (.setMap new-view (document-mapper) "2")
     (log/i "getting doc-id")
     (def doc-id (.getId document))
-    (.putProperties document {"name" "bizo" "phone" "0505919161"})
+    (.putProperties document {"type" "person" "name" "bizo" "phone" "0505919161"})
     (def data (.getProperties document))
     (log/i (str "first data: " data))
     (log/i "updating data using putProperties")
-    (.putProperties document (assoc (into {}  data) "name" "itzik" "phone" "0528543649"))
+    (.putProperties document (assoc (into {}  data) "type" "person" "name" "itzik" "phone" "0528543649"))
     (log/i (str "new data after using putProperties: " (.getProperties document)))

     (log/i "updating data using update method hendler")
     (.update document (document-updater))
     (log/i (str "new data after using putProperties: " (.getProperties document)))
-
+
     (log/i (str "deleting document: " (.delete document)))
     ;; this is how you get conflicts and revision histories
     ;; (.getCurrentRevision document)
@@ -295,7 +295,28 @@
     ;; (.getRevisionHistory document)
     ;; (def mapper (.getMap new-view))
     ;; (.map mapper {} nil)
-
+
+    ;; load the database with more persons
+    (loop [name 100 phone 6000]
+      (if (= name 200) nil
+          (do
+            (let [document (.createDocument database)]
+              (.putProperties document {"type" "person"
+                                        "name" (str "AA" name)
+                                        "phone" phone})
+            (recur (inc name) (inc phone))))))
+
+    ;; quering the database
+    (def query (.createQuery (.getView database "persons")))
+    (.setLimit query 2)
+    ;; (.setStartKey query "sdfsdfas")
+    (def result (.run query))
+    (loop []
+      (if-not (.hasNext result)
+        (log/i "done with qruey...")
+        (do
+          (log/i (str "qruey: " (.next result)))
+          (recur))))
     ;; starting servers
     (toast "starting HTTPD-WSD servers" :long)
     (start-servers httpd-wsd)


whitespace

whitespace

--- src/clojure/zensols/dataset/elsearch.clj
+++ src/clojure/zensols/dataset/elsearch.clj
@@ -95,7 +95,7 @@
 (defn describe
   "Get the mapping (provide info) about the index."
   []
-  (let [{:keys [index-name]} (context)]
+  (let [{:keys [index-name]} (context)]
     (esi/get-mapping (connection) index-name)))

 (defn- assert-success [res]
@@ -150,7 +150,7 @@
   [query]
   (->> (merge query {:search_type "query_then_fetch"
                      :scroll "1m"})
-       search-literal
+       search-literal
        (esd/scroll-seq (connection))
        (map #(-> %
                  (select-keys [:_id :_source])


zen button

zen button

--- src/cmd/ui.cljs
+++ src/cmd/ui.cljs
@@ -136,11 +136,25 @@
         editor-toggler    ($ "editor-toggler")
         console-toggler   ($ "console-toggler")
         info-toggler      ($ "info-toggler")
+        zen-toggler       ($ "zen-toggler")
         toolbar           ($ "toolbar")
         console           ($ "console")
         preview           ($ "preview-container")
         editor            ($ "input")
         preview-toggler   ($ "preview-toggler")]
+
+
+    (.. js/Rx -Observable
+        (fromEvent zen-toggler "click")
+        (subscribe (fn [] (if (visible? editor)
+                            (do
+                              (hide editor)
+                              (hide console)
+                              (hide toolbar))
+                            (do
+                              (show editor)
+                              (show console)
+                              (show toolbar))))))

     (.. js/Rx -Observable
       (fromEvent toolbar-toggler "click")


Use open-ext instead of :data-external

Use open-ext instead of :data-external

--- src-cljs/frontend/components/project_settings.cljs
+++ src-cljs/frontend/components/project_settings.cljs
@@ -503,22 +503,22 @@
                                     "web UI and the API."]})
             (describe-flag {:flag :build-fork-prs
                             :title "Permissive building of fork pull requests"
-                            :blurb '([:p
-                                      "Run builds of fork pull request changes with this project's configuration. "
-                                      "CircleCI will automatically update the commit status shown on GitHub's "
-                                      "pull request page."]
-                                       [:p
-                                        "There are serious security concerns with this setting (see "
-                                        [:a {:data-external true :href "/docs/fork-pr-builds"} "the documentation"] " for details.) "
-                                        "If you have SSH keys, sensitive env vars or AWS credentials stored in your project settings and "
-                                        "untrusted forks can make pull requests against your repo, then this option "
-                                        "isn't for you!"])})
+                            :blurb (list
+                                    [:p
+                                     "Run builds of fork pull request changes with this project's configuration. "
+                                     "CircleCI will automatically update the commit status shown on GitHub's "
+                                     "pull request page."]
+                                    [:p
+                                     "There are serious security concerns with this setting (see "
+                                     [:a (open-ext {:href "/docs/fork-pr-builds"}) "the documentation"] " for details.) "
+                                     "If you have SSH keys, sensitive env vars or AWS credentials stored in your project settings and "
+                                     "untrusted forks can make pull requests against your repo, then this option "
+                                     "isn't for you!"])})
             (describe-flag {:flag :osx-code-signing-enabled
                             :title "Code Signing Support"
                             :blurb [:p
                                     "Enable automatic importing of code-signing identities and provisioning "
-                                    "profiles into the system keychain to simplify the code-signing process."]})
-            ]]])))))
+                                    "profiles into the system keychain to simplify the code-signing process."]})]]])))))

 (defn dependencies [project-data owner]
   (reify


Function to tell whether you're an admin on the plan.

See https://github.com/circleci/circle/pull/3833/files

--- src-cljs/frontend/models/plan.cljs
+++ src-cljs/frontend/models/plan.cljs
@@ -150,3 +150,8 @@
   (and (paid? plan)
        (< (stripe-cost plan)
           (cost plan (usable-containers plan)))))
+
+(defn admin?
+  "Whether the logged-in user is an admin for this plan."
+  [plan]
+  (boolean (:admin plan)))


Update version number to 0.2.2.

Update version number to 0.2.2.

--- project.clj
+++ project.clj
@@ -1,4 +1,4 @@
-(defproject guangyin/guangyin "0.2.1"
+(defproject guangyin/guangyin "0.2.2"
   :description "Clojure date and time library wrapping java.time"
   :url "https://github.com/juhovh/guangyin"
   :license {:name "MIT License"


Add a dependency exclusion to fix warnings.

--- project.clj
+++ project.clj
@@ -18,7 +18,7 @@
                  [org.bovinegenius/exploding-fish "0.3.4"]
                  [overtone/at-at "1.2.0"]
                  [prismatic/schema "0.3.0"]
-                 [camel-snake-kebab "0.2.5"]]
+                 [camel-snake-kebab "0.2.5" :exclusions [org.clojure/clojure]]]
   :scm {:name "git"
         :url "http://github.com/cardforcoin/shale"}
   :auto-clean false


PLD: standard snap

PLD: standard snap

--- project.clj
+++ project.clj
@@ -3,7 +3,7 @@
   [path]
   (str "resources/public/js/lib/" path))

-(defproject onaio/hatti "0.3.16-flexi-tabs-SNAPSHOT"
+(defproject onaio/hatti "0.3.16-SNAPSHOT"
   :description "A cljs dataview from your friends at Ona.io"
   :license "Apache 2, see LICENSE"
   :url "https://github.com/onaio/hatti"


Push up the Clojure version

Push up the Clojure version

--- project.clj
+++ project.clj
@@ -1,9 +1,9 @@
 (defproject shoreleave-baseline "0.3.0"
   :description "A baseline application to get started with a Compojure+Shoreleave"
-  :url "http://example.com/FIXME"
+  :url "https://github.com/shoreleave/shoreleave-baseline"
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
-  :dependencies [[org.clojure/clojure "1.5.0-RC1"]
+  :dependencies [[org.clojure/clojure "1.5.0-RC17"]
                  [org.clojure/tools.reader "0.7.0"]
                  [compojure "1.1.5" :exclusions [org.clojure/clojure]]
                  [lib-noir "0.4.7" :exclusions [[org.clojure/clojure]


(feat) update clojure

(feat) update clojure

Signed-off-by: Ning Sun <a92165a57b6171072bd20ae225e0a6a0a2860443@about.me>

--- project.clj
+++ project.clj
@@ -3,7 +3,7 @@
   :url "http://github.com/sunng87/papaline"
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
-  :dependencies [[org.clojure/clojure "1.6.0"]
+  :dependencies [[org.clojure/clojure "1.8.0"]
                  [org.clojure/core.async "0.1.346.0-17112a-alpha"]]
   :scm {:url "https://github.com/sunng87/papaline"
         :name "github"}


Special case local-buf ugen wrt error checking

--- src/overtone/sc/machinery/ugen/specs.clj
+++ src/overtone/sc/machinery/ugen/specs.clj
@@ -150,7 +150,12 @@
                       (= :ar (:rate-name bad-input)))
                  ;; Special case Pitch ugen which may have ar ugens plugged into it
                  (and (= "Pitch" (:name ugen))
-                      (= :ar (:rate-name bad-input))))
+                      (= :ar (:rate-name bad-input)))
+
+                 ;; Special case LocalBuf which may have kr ugens plugged in
+                 ;; but further modifications aren't honoured
+                 (and (= "LocalBuf" (:name ugen))
+                      (= :kr (:rate-name bad-input))))

         (let [ugen-name     (real-ugen-name ugen)
               in-name       (real-ugen-name bad-input)


Track current tasks

Track current tasks

--- src/cljs/onyx_dashboard/controllers/websocket.cljs
+++ src/cljs/onyx_dashboard/controllers/websocket.cljs
@@ -1,4 +1,5 @@
-(ns onyx-dashboard.controllers.websocket)
+(ns onyx-dashboard.controllers.websocket
+  (:require [clojure.set :refer [union]]))

 (defmulti msg-controller (fn [[type _] _] type))

@@ -13,14 +14,19 @@
   (= (:tracking-id msg)
      (get-in state [:deployment :tracking-id])))

-(defmethod msg-controller :job/completed-task [[_ msg] state]
-  (when (is-tracking? msg state)
-    (println "Task completed: " msg))
-  state)
-
 (defmethod msg-controller :job/submitted-job [[_ msg] state]
   (if (is-tracking? msg state)
     (assoc-in state [:deployment :jobs (:id msg)] msg)
+    state))
+
+(defmethod msg-controller :job/peer-assigned [[_ msg] state]
+  (if (is-tracking? msg state)
+    (update-in state [:deployment :jobs (:job msg) :tasks] union #{(:task msg)})
+    state))
+
+(defmethod msg-controller :job/completed-task [[_ msg] state]
+  (if (is-tracking? msg state)
+    (update-in state [:deployment :jobs (:job msg) :tasks] disj (:task msg))
     state))

 (defmethod msg-controller :job/entry [[_ msg] state]


Fix cljs to allow multiple cljs-builder components

--- modules/cljs/src/modular/cljs.clj
+++ modules/cljs/src/modular/cljs.clj
@@ -11,21 +11,19 @@
    [schema.core :as s]
    [com.stuartsierra.dependency :as dep]))

-(def cljs-compiler-state nil)
+(def cljs-compiler-state (ref {}))

-(def cljs-compiler-compile-count 0)
+(def cljs-compiler-compile-count (ref {}))

 (defn add-modules [state modules]
   (reduce (fn [state {:keys [name mains dependencies]}]
             (cljs/step-configure-module state name mains dependencies))
           state modules))

-(defn compile-cljs [modules {:keys [context source-path target-dir work-dir
-                                    optimizations pretty-print]}]
+(defn compile-cljs [builder modules {:keys [context source-path target-dir work-dir
+                                            optimizations pretty-print]}]

-  ;; TODO This use of cljs-compiler-state only allows one cljs builder
-  ;; per system - need to allow multiple cljs builders
-  (let [state (if-let [s cljs-compiler-state]
+  (let [state (if-let [s (get @cljs-compiler-state builder)]
                 (do
                   (println "cljs: Using existing state")
                   s)
@@ -46,16 +44,15 @@
                       (add-modules modules)
                       )))]

-    (alter-var-root #'cljs-compiler-state
-                    (fn [_]
-                      (-> state
-                          (cljs/step-reload-modified)
-                          (cljs/step-compile-modules)
-                          (cljs/flush-unoptimized))))
+    (let [new-state (-> state
+                        (cljs/step-reload-modified)
+                        (cljs/step-compile-modules)
+                        (cljs/flush-unoptimized))]
+      (dosync
+       (alter cljs-compiler-state (fn [m] (assoc-in m [builder] new-state)))
+       (alter cljs-compiler-compile-count (fn [m] (update-in m [builder] (fnil inc 0))))))

-    (alter-var-root #'cljs-compiler-compile-count inc)
-
-    (println (format "Compiled %d times since last full compile" cljs-compiler-compile-count)))
+    (println (format "Compiled %d times since last full compile" (get @cljs-compiler-compile-count builder))))

   :done)

@@ -77,7 +74,8 @@
   (get-javascript-paths [_]))

 (def new-cljs-builder-schema
-  {:context s/Str
+  {:id s/Keyword
+   :context s/Str
    :source-path s/Str
    :target-dir s/Str
    :work-dir s/Str
@@ -90,27 +88,26 @@
   (start [this]
     (let [modules (map get-definition (filter (partial satisfies? ClojureScriptModule) (vals this)))]
       (try
-        (compile-cljs modules (select-keys this (keys new-cljs-builder-schema)))
-        this
+        (compile-cljs (:id this)
+                      modules (select-keys this (keys new-cljs-builder-schema)))
+        (cond
+         (and (= (:optimizations this) :none)
+              (= (:pretty-print this) true))
+         ;; Only do this on optimizations: none and pretty-print: true - do
+         ;; something different for each optimization mode (TODO)
+         (assoc this
+           :javascripts
+           (for [n (dep/topo-sort
+                    ;; Build a dependency graph between all the modules so
+                    ;; they load in the correct order.
+                    (reduce (fn [g {:keys [name dependencies]}]
+                              (reduce (fn [g d] (dep/depend g name d)) g dependencies))
+                            (dep/graph) modules))]
+             (str (:context this) (name n) ".js")))
+         :otherwise this)
         (catch Exception e
           (println "ClojureScript build failed:" e)
-          (assoc this :error e)))
-
-      (cond
-       (and (= (:optimizations this) :none)
-            (= (:pretty-print this) true))
-       ;; Only do this on optimizations: none and pretty-print: true - do
-       ;; something different for each optimization mode (TODO)
-       (assoc this
-         :javascripts
-         (for [n (dep/topo-sort
-                  ;; Build a dependency graph between all the modules so
-                  ;; they load in the correct order.
-                  (reduce (fn [g {:keys [name dependencies]}]
-                            (reduce (fn [g d] (dep/depend g name d)) g dependencies))
-                          (dep/graph) modules))]
-           (str (:context this) (name n) ".js")))
-       :otherwise this)))
+          (assoc this :error e)))))
   (stop [this] this)

   WebService
@@ -127,7 +124,8 @@

 (defn new-cljs-builder [& {:as opts}]
   (->> opts
-        (merge {:context "/cljs/"
+        (merge {:id ::default
+                :context "/cljs/"
                 :source-path "src-cljs"
                 :target-dir "target/cljs"
                 :work-dir "target/cljs-work"


Add :starting-after qualifier

Add :starting-after qualifier

--- src/test_utils/fracture_diagnostics.cljc
+++ src/test_utils/fracture_diagnostics.cljc
@@ -198,8 +198,16 @@
        :starting-at (let [start-time reference-time
                           java-start-time java-reference-time
                           java-stop-time (.addTo java-completion-time java-start-time)
-                          stop-time (tuc/java-time->timestamp java-stop-time)]))
-     [start-time stop-time])))
+                          stop-time (tuc/java-time->timestamp java-stop-time)]
+                      [start-time stop-time])
+       :starting-after (let [previous-java-stop-time java-reference-time
+                             java-changeover
+                             (Duration/ofSeconds (Math/round (typical-stage-completion-changeover)))
+                             java-start-time (.addTo java-changeover previous-java-stop-time)
+                             java-stop-time (.addTo java-completion-time java-start-time)
+                             start-time (tuc/java-time->timestamp java-start-time)
+                             stop-time (tuc/java-time->timestamp java-stop-time)]
+                         [start-time stop-time])))))

 (defn rand-easting []
   (let [minimum-easting 167000


- Added type pattern matching (Type+)

- Added type pattern matching (Type+)

--- damp.ekeko.aspectj.plugin/src/damp/ekeko/aspectj/annotations.clj
+++ damp.ekeko.aspectj.plugin/src/damp/ekeko/aspectj/annotations.clj
@@ -82,3 +82,36 @@
     (pointcut-annotation-annotation|type|name ?pc ?ann "damp.ekeko.aspectj.annotations.Label")))

+;;Type pattern matching
+
+(defn- type-simple-name
+  [?type ?sn]
+  (l/all
+    (class ?type)
+    (equals ?sn (.getSimpleName ?type))))
+
+(defn- type-name|sub
+  [?sn ?subtype]
+  (l/fresh [?type]
+           (type-simple-name ?type ?sn)
+           (type-super+ ?subtype ?type)))
+
+(defn- type-name|sub+
+  [?sn ?subtype]
+  (l/conde
+    [(type-simple-name ?subtype ?sn)]
+    [(type-name|sub ?sn ?subtype)]))
+
+
+(defn- type-pattern|type
+  [?typePat ?match]
+  (l/fresh [?name ?nameplus]
+           (v+ ?typePat)
+           (equals ?name (clojure.string/replace ?typePat #"[+]" ""))
+           (equals ?nameplus (str ?name "+"))
+           (l/conda
+             [(l/==  ?nameplus ?typePat)
+              (type-name|sub+ ?name ?match)]
+             [(l/!= ?nameplus ?typePat)
+              (type-simple-name ?match ?typePat)])))
+


fixing condition

fixing condition

--- src/es/node.clj
+++ src/es/node.clj
@@ -51,9 +51,9 @@
   (es/connect-to-local-node! @ES))

 (defn start-n-connect
-   "Both starts the node and connects to it if not ready"
+   "Both starts the node and connects to it (only) if not ready"
    []
-  (when-not (and @ES (.isClosed @ES))
+  (when-not (and @ES (not (.isClosed @ES)))
     (start)
     (connect)))


Make chdir directory agnostic. Now keys off the presence of the Gemfile

--- backend/src/circle/init.clj
+++ backend/src/circle/init.clj
@@ -12,7 +12,7 @@
   more conceptual sense, there are lots of entrypoints to the clojure code (for example, tests,
   swank, etc) which are hard to get a hook on, but making sure there is a hook into the Rails code
   is easy. It makes more code to write this in JRuby, but it's written now, so why change it.cl" []
-  (when (= (-> (fs/cwd) fs/normpath fs/split last) "CircleCI")
+  (when (= (fs/exists? "Gemfile"))
     (circle.util.chdir/chdir "backend")
     (println "Changing current working directory to" (fs/abspath (fs/cwd)))))


Switch test project to not use missing Clojure snapshot.

--- test_projects/sample_failing/project.clj
+++ test_projects/sample_failing/project.clj
@@ -3,8 +3,6 @@
 ;; just want a basic project to work from, generate a new one with
 ;; "lein new".

-(def clj-version "1.1.0-master-SNAPSHOT")
-
 (defproject nomnomnom "0.5.0-SNAPSHOT"
-  :dependencies [[~(symbol "org.clojure" "clojure") ~clj-version]]
+  :dependencies [[~(symbol "org.clojure" "clojure") ~"1.1.0"]]
   :main nom.nom.nom)


changed tense names to english

changed tense names to english

--- babel/francais/grammar.clj
+++ babel/francais/grammar.clj
@@ -197,7 +197,7 @@
                             :synsem {:aux false
                                      :infl :futuro
                                      :cat :verb
-                                     :sem {:tense :futuro}}})
+                                     :sem {:tense :future}}})
                    (unifyc c10
                            root-is-head
                            {:rule "s-future-nonphrasal"
@@ -224,19 +224,19 @@
                                      :sem {:tense :conditional}}})
                    (unifyc c10
                            root-is-head-root
-                           {:rule "s-imperfetto-phrasal"
+                           {:rule "s-imperfect-phrasal"
                             :head {:phrasal true}
                             :synsem {:aux false
-                                     :infl :imperfetto
+                                     :infl :imperfect
                                      :cat :verb
                                      :sem {:aspect :progressive
                                            :tense :past}}})
                    (unifyc c10
                            root-is-head
-                           {:rule "s-imperfetto-nonphrasal"
-                            :head {:phrasal false}
-                            :synsem {:aux false
-                                     :infl :imperfetto
+                           {:rule "s-imperfect-nonphrasal"
+                            :head {:phrasal false}
+                            :synsem {:aux false
+                                     :infl :imperfect
                                      :cat :verb
                                      :sem {:aspect :progressive
                                            :tense :past}}})
@@ -297,12 +297,12 @@
                    (unifyc h21
                            {:rule "vp-future"
                             :synsem {:aux false
-                                     :infl :futuro
-                                     :cat :verb}})
-                   (unifyc h21
-                          {:rule "vp-imperfetto"
+                                     :infl :future
+                                     :cat :verb}})
+                   (unifyc h21
+                          {:rule "vp-imperfect"
                            :synsem {:aux false
-                                    :infl :imperfetto
+                                    :infl :imperfect
                                     :cat :verb}})
                    (unifyc h21
                            {:rule "vp-past"


add type hints

add type hints

--- src/bolth.clj
+++ src/bolth.clj
@@ -58,7 +58,7 @@

 (defmacro with-test-out [& body]
   `(let [x# (with-test-out-str ~@body)]
-     (.put *result-queue* x#)))
+     (.add ^AbstractQueue *result-queue* x#)))

 (defn gather-tests-from-ns [^AbstractQueue queue n]
   (let [once-fixture-fn (clojure.test/join-fixtures (::once-fixtures (meta n)))
@@ -108,7 +108,7 @@
           (finally
             (record-test-finished v (- (System/nanoTime) t0))))))))

-(defn run-worker [results tests-to-run worker-id finished]
+(defn run-worker [results ^AbstractQueue tests-to-run worker-id finished]
   (future
     (try
       (binding [*result-queue* results


hotfix next page bug. Need automated testing

--- src/aristotle/templates/search.clj
+++ src/aristotle/templates/search.clj
@@ -72,28 +72,40 @@
                  (if (and (not (nil? (query-result-struct :num-found)))
                              (> page 1))
                       [:h3 {:id "first-page-headline"}
-                       [:a {:href (str "/" (query-terms->url-str
-                                            (assoc (req :params)
-                                                   "page"
-                                                   (str 1))))}
+                       [:a {:href (str "/"
+                                       daemon-name
+                                       (query-terms->url-str
+                                        (-> (req :params)
+                                            (dissoc :daemon-name)
+                                            (assoc
+                                             "page"
+                                             (str 1)))))}
                         "First Page"]])]

                 [:div {:class "col"}
                  (if (and (not (nil? (query-result-struct :num-found)))
                           (> page 1))
                    [:h3 {:id "second-page-headline"}
-                    [:a {:href (str "/" (query-terms->url-str
-                                         (assoc (req :params)
-                                                "page"
-                                                (str (- page 1)))))}
+                    [:a {:href (str "/"
+                                    daemon-name
+                                    (query-terms->url-str
+                                     (-> (req :params)
+                                         (dissoc :daemon-name)
+                                         (assoc
+                                          "page"
+                                          (str (- page 1))))))}
                      "Prev Page/"]])

                  ;;Next Page
                  (if (and (not (nil? (query-result-struct :num-found)))
                           (< (* page 10) (query-result-struct :num-found)))
                    [:h3 {:id "third-page-headline"}
-                    [:a {:href (str "/" (query-terms->url-str
-                                         (assoc (req :params)
-                                                "page"
-                                                (str (+ 1 page)))) )}
+                    [:a {:href (str "/"
+                                    daemon-name
+                                    (query-terms->url-str
+                                     (-> (req :params)
+                                         (dissoc :daemon-name)
+                                         (assoc
+                                          "page"
+                                          (str (+ 1 page))))))}
                      " Next Page"]])]]]]])))


Document `call-cc`.

Document `call-cc`.

--- src/active/clojure/monad.cljc
+++ src/active/clojure/monad.cljc
@@ -20,7 +20,12 @@
   [monad free-bind-monad
    cont free-bind-cont])

-(define-record-type CallCC
+(define-record-type ^{:doc "Accepts a function `f` with one argument that
+  returns a monadic value.  `call-cc` packages the current continuation as a
+  function and passes it as an argument to `f`.  If the function is called
+  later, the continuation of that call will be discarded and instead reinstate
+  the continuation that was in effect when the function was created."}
+  CallCC
   (call-cc f)
   call-cc?
   [f call-cc-f])


Add whitespace

Add whitespace

--- src/braid/client/quests/views.cljs
+++ src/braid/client/quests/views.cljs
@@ -12,6 +12,7 @@
        [:div.icon {:class (if (< i (quest :progress))
                             "complete"
                             "incomplete")}])]
+
     [:p (or (quest :description) "A short description would be here. Lorem ispum dolor it amet.")]]

    (if (< (quest :progress) (quest :goal))


Fix type conversions for blake2b

Fix type conversions for blake2b

--- src/caesium/crypto/generichash.clj
+++ src/caesium/crypto/generichash.clj
@@ -78,6 +78,10 @@
   ([msg]
    (blake2b msg {}))
   ([msg {:keys [size] :or {size blake2b-bytes} :as opts}]
-   (let [buf (bb/alloc size)]
-     (blake2b-to-buf! buf (bb/->indirect-byte-buf msg) opts)
+   (let [buf (bb/alloc size)
+         opts (dissoc opts :size)]
+     (blake2b-to-buf!
+      buf
+      (bb/->indirect-byte-buf msg)
+      (m/map-vals bb/->indirect-byte-buf opts))
      (bb/->bytes buf))))


show month+day if date is not today, show year if year is not this year

--- src/chat/client/views/helpers.cljs
+++ src/chat/client/views/helpers.cljs
@@ -107,5 +107,17 @@

 (defn format-date
   "Turn a Date object into a nicely formatted string"
-  [date]
-  (f/unparse (f/formatter "h:mm A") (t/to-default-time-zone date)))
+  [datetime]
+  (let [datetime (t/to-default-time-zone datetime)
+        now (t/to-default-time-zone (t/now))
+        format (cond
+                 (= (f/unparse (f/formatter "yyyydM") now)
+                    (f/unparse (f/formatter "yyyydM") datetime))
+                 "h:mm A"
+
+                 (= (t/year now) (t/year datetime))
+                 "h:mm A MMM d"
+
+                 :else
+                 "h:mm A MMM d yyyy")]
+    (f/unparse (f/formatter format) datetime)))


make message observe sender, so nickname updates happen right away

--- src/chat/client/views/threads.cljs
+++ src/chat/client/views/threads.cljs
@@ -16,7 +16,7 @@
   (reify
     om/IRender
     (render [_]
-      (let [sender (get-in @store/app-state [:users (message :user-id)])]
+      (let [sender (om/observe owner (om/ref-cursor (get-in (om/root-cursor store/app-state) [:users (message :user-id)])))]
         (dom/div #js {:className (str "message " (when (:collapse? opts) "collapse"))}
           (dom/img #js {:className "avatar" :src (sender :avatar)})
           (dom/div #js {:className "info"}


Responsive design improvements

Responsive design improvements

--- src/clj/chili_dog_night/styles.clj
+++ src/clj/chili_dog_night/styles.clj
@@ -1,6 +1,11 @@
 (ns chili-dog-night.styles
   (:require [garden.def :refer [defstyles]]
-            [garden.selectors :as selectors]))
+            [garden.selectors :as selectors]
+            [garden.stylesheet :refer [at-media]]
+            [garden.units :refer [px px+]]))
+
+(def ^:dynamic *media-query-mobile-large* (px 425))
+(def ^:dynamic *media-query-tablet* (px 768))

 (defstyles normalize
   [:body
@@ -10,17 +15,25 @@
 (defstyles layout
   [:body
    {:margin "0 auto"
-    :max-width "780px"}])
+    :max-width *media-query-tablet*}
+   (at-media {:max-width (px+ *media-query-tablet* 30)}
+     [:& {:margin "0 30px"}])
+   (at-media {:max-width *media-query-mobile-large*}
+     [:& {:margin "0 20px"}])])

 (defstyles typography
   [:body
    {:font-family "Playfair Display"
-    :font-size "18px"
+    :font-size (px 18)
     :font-variant-ligatures "common-ligatures"
     :text-rendering "optimizeLegibility"
     :-webkit-font-feature-settings "kern"
     :font-feature-settings "kern"
-    :font-kerning "normal"}]
+    :font-kerning "normal"}
+   (at-media {:max-width *media-query-tablet*}
+     [:& {:font-size (px 16)}])
+   (at-media {:max-width *media-query-mobile-large*}
+     [:& {:font-size (px 12)}])]
   [:a
    {:font-style "italic"}]
   [:p