Show Subworkflow Detail (PR #1295)

Show Subworkflow Detail (PR #1295)

--- src/cljs/main/broadfcui/page/workspace/monitor/workflow_details.cljs
+++ src/cljs/main/broadfcui/page/workspace/monitor/workflow_details.cljs
@@ -177,92 +177,157 @@
                           :response (if success? (get-parsed-response false) status-text)
                           :raw-response raw-response}))}))})

+(defn- render-gcs-path [components]
+  (str moncommon/google-storage-context (string/join "/" components) "/"))
+
+;; recursive partner of render-subworkflow-detail
+(declare CallDetail)
+
+;; Subworkflows contain a lot of information that is redundant to what can be seen from the Calls
+;; Only show new information
+(defn- render-subworkflow-detail [workflow raw-data workflow-name submission-id workspace-id gcs-path-prefix]
+  (let [inputs (ffirst (workflow "calls"))
+        input-names (string/split inputs ".")
+        workflow-name-for-path (first input-names)
+        subworkflow-path-components (conj gcs-path-prefix workflow-name-for-path (workflow "id"))]
+    [:div {:style {:padding "1em" :border style/standard-line :borderRadius 4
+                   :backgroundColor (:background-light style/colors)}}
+     (create-field "Subworkflow ID" (links/create-external {:href (render-gcs-path subworkflow-path-components)} (workflow "id")))
+     (let [call-cache-status (-> (workflow "calls") vals first first (get "callCaching") (get "effectiveCallCachingMode"))]
+       (create-field "Call Caching" (moncommon/call-cache-result call-cache-status)))
+     (when (seq (workflow "calls"))
+       [WorkflowTiming {:label "Workflow Timing" :data raw-data :workflow-name workflow-name}])
+     (when-let [failures (workflow "failures")]
+       [Failures {:data failures}])
+     (when (seq (workflow "calls"))
+       [:div {:style {:marginTop "1em" :fontWeight 500}} "Calls:"])
+     (for [[call data] (workflow "calls")]
+       [CallDetail {:label call :data data :submission-id submission-id :workflowId (workflow "id")
+                    :workspace-id workspace-id :gcs-path-prefix subworkflow-path-components}])]))
+
+(react/defc- SubworkflowDetails
+  {:render
+   (fn [{:keys [state props]}]
+     [:div {}
+      (let [server-response (:server-response @state)]
+        (cond
+          (nil? server-response)
+          (spinner "Loading subworkflow details...")
+          (not (:success? server-response))
+          (style/create-server-error-message (:response server-response))
+          :else
+          (render-subworkflow-detail (:response server-response) (:raw-response server-response)
+                                     (:workflow-name props) (:submission-id props)
+                                     (:workspace-id props) (:gcs-path-prefix props))))])
+      :component-did-mount
+      (fn [{:keys [props state]}]
+        (endpoints/call-ajax-orch
+          {:endpoint
+           (endpoints/get-workflow-details
+             (:workspace-id props) (:submission-id props) (:workflow-id props))
+           :on-done (fn [{:keys [success? get-parsed-response status-text raw-response]}]
+                      (swap! state assoc :server-response
+                             {:success? success?
+                              :response (if success? (get-parsed-response false) status-text)
+                              :raw-response raw-response}))}))})
+
 (react/defc- CallDetail
   {:get-initial-state
    (fn []
-     {:expanded false})
+     {:expanded false
+      :subworkflow-expanded {}})
    :render
    (fn [{:keys [props state]}]
-     [:div {:style {:marginTop "1em"}}
-      (when (:show-operation-dialog? @state)
-        [OperationDialog (:operation-dialog-props @state)])
-      [:div {:style {:display "inline-block" :marginRight "1em"}}
-       (let [workflow-name (workflow-name (:label props))
-             call-name (call-name (:label props))]
-         (links/create-external {:href (str moncommon/google-storage-context (:bucketName props) "/" (:submission-id props)
-                                            "/" workflow-name "/" (:workflowId props) "/call-" call-name "/")}
-           (:label props)))]
-      (links/create-internal {:onClick #(swap! state update :expanded not)}
-        (if (:expanded @state) "Hide" "Show"))
-      (when (:expanded @state)
-        (map-indexed
-         (fn [index data]
-           [:div {:style {:padding "0.5em 0 0 0.5em"}}
-            [:div {:style {:paddingBottom "0.25em"}} (str "Call #" (inc index) ":")]
-            [:div {:style {:paddingLeft "0.5em"}}
-             (create-field "Operation"
-                           ;; Note: using [:a ...] instead of style/create-link to be consistent with GCSFilePreviewLink
-                           [:a {:href "javascript:;"
-                                :onClick (fn [_]
-                                           (swap! state assoc
-                                                  :show-operation-dialog? true
-                                                  :operation-dialog-props {:workspace-id (:workspace-id props)
-                                                                           :job-id (data "jobId")
-                                                                           :dismiss #(swap! state dissoc :show-operation-dialog?)}))}
-                            (data "jobId")])
-             (let [status (data "executionStatus")]
-               (create-field "Status" (moncommon/icon-for-call-status status) status))
-             (when (= (get-in data ["callCaching" "effectiveCallCachingMode"]) "ReadAndWriteCache")
-               (create-field "Cache Result" (moncommon/format-call-cache (get (data "callCaching") "hit"))))
-             (create-field "Started" (moncommon/render-date (data "start")))
-             ;(utils/cljslog data)
-             (create-field "Ended" (moncommon/render-date (data "end")))
-             [IODetail {:label "Inputs" :data (data "inputs") :call-detail? true}]
-             [IODetail {:label "Outputs" :data (data "outputs") :call-detail? true}]
-             (create-field "stdout" (display-value (data "stdout") (last (string/split (data "stdout") #"/"))))
-             (create-field "stderr" (display-value (data "stderr") (last (string/split (data "stderr") #"/"))))
-             (backend-logs data)
-             (when-let [failures (data "failures")]
-               [Failures {:data failures}])]])
-         (:data props)))])})
-
-
-(defn- render-workflow-detail [workflow raw-data workflow-name submission-id bucketName workspace-id]
-  [:div {:style {:padding "1em" :border style/standard-line :borderRadius 4
-                 :backgroundColor (:background-light style/colors)}}
-   [:div {}
-    (let [inputs (ffirst (workflow "calls"))
-          input-names (string/split inputs ".")
-          workflow-name (first input-names)]
-      (create-field "Workflow ID"
-                    (links/create-external {:href (str moncommon/google-storage-context
-                                                       bucketName "/" submission-id "/"
-                                                       workflow-name "/" (workflow "id") "/")}
-                      (workflow "id"))))
-    (let [status (workflow "status")]
-      (create-field "Status" (moncommon/icon-for-wf-status status)))
-    (let [call-cache-status (-> (workflow "calls") vals first first (get "callCaching") (get "effectiveCallCachingMode"))]
-      (create-field "Call Caching" (moncommon/call-cache-result call-cache-status)))
-    (when-let [submission (workflow "submission")]
-      (create-field "Submitted" (moncommon/render-date submission)))
-    (when-let [start (workflow "start")]
-      (create-field "Started" (moncommon/render-date start)))
-    (when-let [end (workflow "end")]
-      (create-field "Ended" (moncommon/render-date end)))
-    [IODetail {:label "Inputs" :data (utils/parse-json-string (get-in workflow ["submittedFiles", "inputs"]))}]
-    [IODetail {:label "Outputs" :data (workflow "outputs")}]
-    (when-let [workflowLog (workflow "workflowLog")]
-      (create-field "Workflow Log" (display-value workflowLog (str "workflow." (workflow "id") ".log"))))
-    (when (seq (workflow "calls"))
-      [WorkflowTiming {:label "Workflow Timing" :data raw-data :workflow-name workflow-name}])
-    (when-let [failures (workflow "failures")]
-      [Failures {:data failures}])]
-   (when (seq (workflow "calls"))
-     [:div {:style {:marginTop "1em" :fontWeight 500}} "Calls:"])
-   (for [[call data] (workflow "calls")]
-     [CallDetail {:label call :data data :submission-id submission-id :bucketName bucketName :workflowId (workflow "id")
-                  :workspace-id workspace-id}])])
-
+     (let [call-path-components (conj (:gcs-path-prefix props) (str "call-" (call-name (:label props))))]
+       [:div {:style {:marginTop "1em"}}
+        (when (:show-operation-dialog? @state)
+          [OperationDialog (:operation-dialog-props @state)])
+        [:div {:style {:display "inline-block" :marginRight "1em"}}
+         (links/create-external {:href (render-gcs-path call-path-components)} (:label props))]
+        (links/create-internal {:onClick #(swap! state update :expanded not)}
+                               (if (:expanded @state) "Hide" "Show"))
+        (when (:expanded @state)
+          (map-indexed
+            (fn [index data]
+              [:div {:style {:padding "0.5em 0 0 0.5em"}}
+               [:div {:style {:paddingBottom "0.25em"}}
+                (if-let [subWorkflowId (data "subWorkflowId")]
+                  [:span {}
+                   (str "Call #" (inc index) " (Subworkflow ID " subWorkflowId "): ")
+                   (if (contains? (:subworkflow-expanded @state) subWorkflowId)
+                     [:span {}
+                      ;; click to hide this SubworkflowDetails and remove from the :subworkflow-expanded map in @state
+                      (links/create-internal {:onClick #(swap! state update :subworkflow-expanded
+                                                               (fn [expanded-map]
+                                                                 (dissoc expanded-map subWorkflowId)))}
+                                             "Hide")
+                      (let [subworkflow-path-prefix (conj call-path-components (str "shard-" index))]
+                        [SubworkflowDetails (merge (select-keys props [:workspace-id :submission-id :workflow-name])
+                                                   {:workflow-id subWorkflowId
+                                                    :gcs-path-prefix subworkflow-path-prefix})])]
+                     ;; click to show subworkflow details and add it to the :subworkflow-expanded map in @state
+                     (links/create-internal {:onClick #(swap! state assoc-in
+                                                              [:subworkflow-expanded subWorkflowId] true)}
+                                            "Show"))]
+                  (str "Call #" (inc index) ":"))]
+               [:div {:style {:paddingLeft "0.5em"}}
+                (create-field "Operation"
+                              ;; Note: using [:a ...] instead of style/create-link to be consistent with GCSFilePreviewLink
+                              [:a {:href    "javascript:;"
+                                   :onClick (fn [_]
+                                              (swap! state assoc
+                                                     :show-operation-dialog? true
+                                                     :operation-dialog-props {:workspace-id (:workspace-id props)
+                                                                              :job-id       (data "jobId")
+                                                                              :dismiss      #(swap! state dissoc :show-operation-dialog?)}))}
+                               (data "jobId")])
+                (let [status (data "executionStatus")]
+                  (create-field "Status" (moncommon/icon-for-call-status status) status))
+                (when (= (get-in data ["callCaching" "effectiveCallCachingMode"]) "ReadAndWriteCache")
+                  (create-field "Cache Result" (moncommon/format-call-cache (get (data "callCaching") "hit"))))
+                (create-field "Started" (moncommon/render-date (data "start")))
+                ;(utils/cljslog data)
+                (create-field "Ended" (moncommon/render-date (data "end")))
+                [IODetail {:label "Inputs" :data (data "inputs") :call-detail? true}]
+                [IODetail {:label "Outputs" :data (data "outputs") :call-detail? true}]
+                (create-field "stdout" (display-value (data "stdout") (last (string/split (data "stdout") #"/"))))
+                (create-field "stderr" (display-value (data "stderr") (last (string/split (data "stderr") #"/"))))
+                (backend-logs data)
+                (when-let [failures (data "failures")]
+                  [Failures {:data failures}])]])
+            (:data props)))]))})
+
+(defn- render-workflow-detail [workflow raw-data workflow-name submission-id bucketName workspace-id gcs-path-prefix]
+  (let [inputs (ffirst (workflow "calls"))
+        input-names (string/split inputs ".")
+        workflow-name-for-path (first input-names)
+        workflow-path-components (conj gcs-path-prefix workflow-name-for-path (workflow "id"))]
+    [:div {:style {:padding "1em" :border style/standard-line :borderRadius 4
+                   :backgroundColor (:background-light style/colors)}}
+     (create-field "Workflow ID" (links/create-external {:href (render-gcs-path workflow-path-components)} (workflow "id")))
+     (let [status (workflow "status")]
+       (create-field "Status" (moncommon/icon-for-wf-status status)))
+     (let [call-cache-status (-> (workflow "calls") vals first first (get "callCaching") (get "effectiveCallCachingMode"))]
+       (create-field "Call Caching" (moncommon/call-cache-result call-cache-status)))
+     (when-let [submission (workflow "submission")]
+       (create-field "Submitted" (moncommon/render-date submission)))
+     (when-let [start (workflow "start")]
+       (create-field "Started" (moncommon/render-date start)))
+     (when-let [end (workflow "end")]
+       (create-field "Ended" (moncommon/render-date end)))
+     [IODetail {:label "Inputs" :data (utils/parse-json-string (get-in workflow ["submittedFiles", "inputs"]))}]
+     [IODetail {:label "Outputs" :data (workflow "outputs")}]
+     (when-let [workflowLog (workflow "workflowLog")]
+       (create-field "Workflow Log" (display-value workflowLog (str "workflow." (workflow "id") ".log"))))
+     (when (seq (workflow "calls"))
+       [WorkflowTiming {:label "Workflow Timing" :data raw-data :workflow-name workflow-name}])
+     (when-let [failures (workflow "failures")]
+       [Failures {:data failures}])
+     (when (seq (workflow "calls"))
+       [:div {:style {:marginTop "1em" :fontWeight 500}} "Calls:"])
+     (for [[call data] (workflow "calls")]
+       [CallDetail {:label call :data data :submission-id submission-id :workflowId (workflow "id")
+                    :workspace-id workspace-id :gcs-path-prefix workflow-path-components}])]))

 (react/defc- WorkflowDetails
   {:render
@@ -274,9 +339,13 @@
          (not (:success? server-response))
          (style/create-server-error-message (:response server-response))
          :else
-         (render-workflow-detail (:response server-response) (:raw-response server-response)
-                                 (:workflow-name props) (:submission-id props) (:bucketName props)
-                                 (:workspace-id props)))))
+         ;; generate this workflow's GCS path prefix
+         ;; subworkflows receive them as props from parent workflows
+         ;; top-level workflows use workspace-bucket-name/submission-id
+         (let [workflow-path-prefix [(:bucketName props) (:submission-id props)]]
+           (render-workflow-detail (:response server-response) (:raw-response server-response)
+                                   (:workflow-name props) (:submission-id props) (:bucketName props)
+                                   (:workspace-id props) workflow-path-prefix)))))
    :component-did-mount
    (fn [{:keys [props state]}]
      (endpoints/call-ajax-orch


Rename function to-schema-reference to ->swagger-schema

--- src/io/aviso/rook/swagger.clj
+++ src/io/aviso/rook/swagger.clj
@@ -138,7 +138,7 @@
                                         (-> schema meta :doc))})
       remove-nil-vals)))

-(defn to-schema-reference
+(defn ->swagger-schema
   "Converts a schema to a schema reference; the schema must be named.  Returns a tuple
   of the possibly updated swagger object and a Swagger schema definition (or a \"$ref\" map)."
   [swagger-options swagger-object schema]
@@ -147,7 +147,7 @@
     [swagger-object nil]

     (instance? APersistentVector schema)
-    (let [[object' item-reference] (to-schema-reference swagger-options swagger-object (first schema))]
+    (let [[object' item-reference] (->swagger-schema swagger-options swagger-object (first schema))]
       [object' {:type  :array
                 :items item-reference}])

@@ -182,7 +182,7 @@
     (if-let [schema (-> routing-entry :meta :body-schema)]

       ;; Assumption: it's a map and named
-      (let [[swagger-object' schema-reference] (to-schema-reference swagger-options swagger-object schema)]
+      (let [[swagger-object' schema-reference] (->swagger-schema swagger-options swagger-object schema)]
         (update-in swagger-object' paths-key
                    conj {:name     :request-body
                          :in       :body
@@ -203,7 +203,7 @@
                                           (:doc schema-meta)
                                           ;; description is required in the Response Object, so we need some default here.
                                           "Documentation not provided.")
-                          [so' schema-reference] (to-schema-reference swagger-options so schema)
+                          [so' schema-reference] (->swagger-schema swagger-options so schema)
                           response (remove-nil-vals {:description description
                                                      :schema      schema-reference})]
                       (assoc-in so' (concat paths-key [:responses status-code]) response))))]


Fix wrapper API for traps

Fix wrapper API for traps

--- src/monkey_music/wrapper.cljs
+++ src/monkey_music/wrapper.cljs
@@ -118,8 +118,8 @@
    "baseLayout" (layout->json base-layout)
    "teams" (teams->json teams)
    "inventorySize" inventory-size
-   "trapPositions" (map trap->json traps)
-   "armedTrapPositions" (map trap->json armed-traps)
+   "traps" (map trap->json traps)
+   "armedTraps" (map trap->json armed-traps)
    "remainingTurns" remaining-turns
    "isGameOver" (c/game-over? state)
    "renderingHints" (map hint->json rendering-hints)})


Minor coordinator cleanup.

Minor coordinator cleanup.

--- src/onyx/peer/coordinator.clj
+++ src/onyx/peer/coordinator.clj
@@ -116,8 +116,7 @@
                        :job-id job-id
                        :replica-version replica-version
                        :epoch epoch}
-          {:keys [write-version]} checkpoint
-          next-write-version (write-coordinate write-version log tenancy-id job-id coordinates)]
+          next-write-version (write-coordinate (:write-version checkpoint) log tenancy-id job-id coordinates)]
       (>!! group-ch [:send-to-outbox {:fn :complete-job :args {:job-id job-id}}])
       (-> state
           (update :job merge {:completed? true
@@ -133,7 +132,7 @@
 (defn periodic-barrier
   [{:keys [tenancy-id workflow-depth log curr-replica job-id messenger barrier checkpoint] :as state}]
   (if (:offering? barrier)
-    ;; No op because hasn't finished emitting last barrier, wait again
+    ;; No op because hasn't finished emitting last barrier, back-off
     state
     (let [start-checkpoint? (or (:sealing? (:job state))
                                 (not (:initiated? checkpoint)))


remove evil apostrophe

remove evil apostrophe

--- src/overtone/music/rhythm.clj
+++ src/overtone/music/rhythm.clj
@@ -24,7 +24,7 @@

 (defprotocol IMetronome
   (start [this] [this start-beat]
-    "Returns the start time of the metronome. Also restart's the metronome at
+    "Returns the start time of the metronome. Also restarts the metronome at
      'start-beat' if given.")
   (tick [this]
     "Returns the duration of one metronome 'tick' in milleseconds.")


added sleep content and status

added sleep content and status

sleep will get the adv 100 hp
content is to show at what location has what item(will be deleted, only
used for development)
status will show adv’s location name hp social and skill

--- src/adventure/core.clj
+++ src/adventure/core.clj
@@ -3,8 +3,7 @@
             [clojure.core.match :refer [match]]
                )
   (:gen-class))
-; [clojure.core.match :refer [match]]
-; [clojure.string :as str]
+
 (def the-map
   {
    :bedroom {:desc "There is a bed, and a warm warm warm blanket that is pretty effective in putting you to sleep"
@@ -75,8 +74,8 @@
     (when-not ((adv :before) location)
       (print (-> the-map location :desc) ) )
     (update-in adv [:before] #(conj % location))))
-
-
+(defn adv_status [adv]
+  (do (println (str (-> adv :location)" "(-> adv :name)" "(-> adv :hp) " " (-> adv :skill) " " (-> adv :social)))adv))
 (defn go [dir adv]
   (let [curr-room (get-in adv [:location])]
    (if-let [dest (get-in the-map [curr-room :dir dir])]
@@ -92,20 +91,26 @@
         (update-in adv [:inventory] #(conj % dest)))
      (do (println "There is no such item. ")
         adv) )))
+
 (defn dropItem [obj adv]
     (if-let [dest (get-in adv [:inventory obj])]
       (update-in adv [:inventory] #(dissoc % dest))
       (do (println "You don't have such item")
        adv)))
+
 (defn print_inventory [adv]
     (do (println (seq (adv :inventory)))
       adv))
+
 (defn print_content [adv]
     (let [location (adv :location)]
-    (do (print (str (-> the-map location :content)))adv)))
+    (do (println (str (-> the-map location :content)))adv)))

 (defn tp [location adv]
     )
+
+(defn sleep [adv]
+    (do (println "You are at full health")(assoc-in adv [:hp] 100)))

 (defn respond [inst adv]
   (if (contains? inst 1)
@@ -113,7 +118,7 @@
           [:pick] (pick (inst 1) adv)
           [:dropItem] (dropItem (inst 1) adv)
           [_](do
-              (println (str "I'm sorry Dave. I cannot allow you to do that."))
+              (println (str "I'm sorry "(-> adv :name)". I cannot allow you to do that."))
               adv)
           )
   (match inst
@@ -123,8 +128,10 @@
          [:east] (go :east adv)
          [:inventory] (print_inventory adv)
          [:content] (print_content adv)
+         [:status] (adv_status adv)
+         [:sleep] (sleep adv)
          _ (do
-             (println (str "I'm sorry Dave. I cannot allow you to do that."))
+             (println (str "I'm sorry "(-> adv :name)". I cannot allow you to do that."))
              adv) )
     ) )

@@ -133,13 +140,13 @@

 (defn -main
   [& args]
-  (println "What is your name")
+  (println "What is your name?")
   (let [n (read-line)
         adv-n (adventurer :name)
-        adv (assoc-in adventurer [:name] n)]
-  (println (str "Good morning, "(str(adv :name))"! How was your sleep? "))
+        adv' (assoc-in adventurer [:name] n)]
+  (println (str "Good morning, "(str (-> adv' :name))"! How was your sleep? "))
   (loop [the-m the-map
-         the-a adventurer]
+         the-a adv']
     (let [location (the-a :location)
           the-a' (status the-a)
           _      (println (str " What do you wanna do? You can go "  (str(-> the-m location :todo))))


added URL to 401 error message.

added URL to 401 error message.

--- src/ancient_clj/io.clj
+++ src/ancient_clj/io.clj
@@ -20,7 +20,7 @@
         (let [{:keys [status] :as data} (:object (ex-data ex))]
           (condp = status
             404 (throw (java.io.FileNotFoundException. url))
-            401 (throw (ex-info "Invalid or missing Credentials!" data))
+            401 (throw (ex-info (str "invalid or missing credentials: " url) data))
             (throw ex)))))))

 (defn- id->path


javaparser: fix broken when clause

javaparser: fix broken when clause

--- src/app/javaparser.clj
+++ src/app/javaparser.clj
@@ -188,8 +188,8 @@
     (.append sb "(")
     (let [firstParam (first (.getParameters constructor))
           otherParams (rest (.getParameters constructor) )]
-      (when-not (nil? firstParam))
-        (.append sb (toStringWithoutComments (.getType firstParam)))
+      (when-not (nil? firstParam)
+        (.append sb (toStringWithoutComments (.getType firstParam))))
       (doseq [param otherParams]
         (.append sb ", ")
         (.append sb (toStringWithoutComments (.getType param)))))


Bugfix

Bugfix

--- src/asteroids/core.clj
+++ src/asteroids/core.clj
@@ -276,7 +276,7 @@
       )))

 (defmulti handle-collision (fn [{type :type}]
-                             (if (some #{:ship :shot :asteroid} type)
+                             (if (#{:ship :shot :asteroid} type)
                                type
                                :other)))

@@ -462,8 +462,8 @@
 (defmulti paint (fn [_ {type :type}]
                   (cond
                     (= type :ship) :ship
-                    (some #{:shot} type) :fill
-                    (some #{:asteroid :debris} type) :draw)))
+                    (#{:shot} type) :fill
+                    (#{:asteroid :debris} type) :draw)))

 (defmethod paint :ship [g {:keys [shape life-colors life cockpit-shape cockpit-color shots] :as ship}]
   (doseq [shot shots]


extracted active-player, displaying cards for play-card

--- src/cartagena/core.clj
+++ src/cartagena/core.clj
@@ -175,28 +175,35 @@
        default
        (str/lower-case input)))))

+
+(defn active-player
+  "Gets the active player from the players collection by name"
+  [game-state]
+  (first (filter #(= (:current-player game-state) (:name %)) (:players game-state))))
+
 (defn prompt-play-card
   "Display card play options for current player, capture input, perform action"
-  []
-  (println "playing card!"))
+  [game-state]
+  (let [cards (:cards (active-player game-state))]
+    (println "Your cards are:" cards)
+    (println "Which card?")))

 (defn prompt-move-back
   "Display move options for current player, capture input, perform action"
-  []
+  [game-state]
   (println "moving!"))

 (defn prompt-action
   "Gets input for current player"
   [game-state]
-  (let [active-player (filter #(= (:current-player game-state) (:name %)) (:players game-state))]
-    (println "active player" active-player)
-    (println "You have" (:actions-left game-state) "actions left!  Choose! ([1] is default)")
-    (println "[1] Play card")
-    (println "[2] Move back")
-    (let [current-action (get-input "1")]
-      (if (= "1" current-action)
-        (prompt-play-card)
-        (prompt-move-back)))))
+  (println "active player" (active-player game-state))
+  (println "You have" (:actions-left game-state) "actions left!  Choose! ([1] is default)")
+  (println "[1] Play card")
+  (println "[2] Move back")
+  (let [current-action (get-input "1")]
+    (if (= "1" current-action)
+      (prompt-play-card game-state)
+      (prompt-move-back game-state))))

 (defn -main
   "Calls the function to get the number of players... goes on from there"


update check timeout

update check timeout

--- src/ci3/controller.clj
+++ src/ci3/controller.clj
@@ -47,7 +47,7 @@
   (if @stop
     (println "Stop watching " (name rt))
     (future (process (walk/keywordize-keys (k8s/list k8s/cfg rt)))
-            (Thread/sleep 10000)
+            (Thread/sleep 5000)
             (watch-resource rt process))))

 (defn process-repository [repositories]
@@ -55,10 +55,7 @@
     (doseq [r repos]
       (when-not (:staus r)
         (println "Add webhook " (:url r))
-        (spit "/tmp/repl" (str "add web hook" "\n\n\n") )
-        )
-      )
-    ))
+        (spit "/tmp/repl" (str "add web hook" "\n\n\n"))))))

 (defn restart []
   (do


randomize device emulation

randomize device emulation

--- src/cljs/app/core.cljs
+++ src/cljs/app/core.cljs
@@ -27,7 +27,7 @@
     (pubnub/bidir-send (pubnub/tunnel)
                        {:id (str "device-" (inc (rand-int n)))
                         :value (str (pubnub/generate-id))})
-    (<! (timeout (* 10 1000)))
+    (<! (timeout (* (rand-int 3) 1000)))
     (recur)))

 (defn monitor-devices [& {:keys [alarm]}]


docs are comming

docs are comming

--- src/clojure2d/core.clj
+++ src/clojure2d/core.clj
@@ -1,5 +1,16 @@
+;; ## Scope
+;;
+;; This namespace provides basic functions to manipulate with display windows with events, canvas, image files and session.
+;; What's here in brief:
+;;
+;; * Image file read and write, backed by Java ImageIO API. You can read and write BMP, JPG and PNG files. I didn't test WBMP and GIF. Image itself is Java BufferedImage in integer ARGB mode. Each pixel is represented as 32bit unsigned integer and 8 bits per channel. See clojure2d.pixels namespace for pixels operations.
+;; * Canvas with functions to draw on it, represented as atom of BufferedImage and Graphics2D objects.
+;; * Display (JFrame) with events handlers (multimethods), autorefreshing associated canvas and if you prefer Processing style, calling drawing function with context
+;; * Session management to: get unique identifier, save logs (different file per session) and get unique, sequenced filename.
+;; * Some general helper functions
+
 (ns clojure2d.core
-  ""
+  "JFrame, Java2D, file io and simple session management"
   (:require [clojure.java.io :refer :all]
             [clojure2d.math :as m])
   (:import [java.awt.image BufferedImage]


Replaced sorted-map with sort

Replaced sorted-map with sort

--- src/compojure/html.clj
+++ src/compojure/html.clj
@@ -50,8 +50,8 @@
   (str-map
     (fn [[key val]]
       (str " " key "=\"" (h val) "\""))
-    (apply sorted-map
-      (mapcat #(map str* %) attrs))))
+    (sort
+      (map (fn [[k v]] [(str* k) (str* v)]) attrs))))

 (defn- create-tag
   "Wrap some content in an XML tag."


Removed compojure.json - duplicates functionality of clojure.contrib.json.write

--- src/compojure/json.clj
+++ src/compojure/json.clj
@@ -1,39 +0,0 @@
-;; Copyright (c) James Reeves. All rights reserved.
-;; The use and distribution terms for this software are covered by the Eclipse
-;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which
-;; can be found in the file epl-v10.html at the root of this distribution. By
-;; using this software in any fashion, you are agreeing to be bound by the
-;; terms of this license. You must not remove this notice, or any other, from
-;; this software.
-
-;; compojure.json:
-;;
-;; A library for outputting basic Clojure types in JSON.
-
-(ns compojure.json
-  (:use clojure.contrib.str-utils))
-
-(declare json)
-
-(defn- json-array
-  [coll]
-  (str "[" (str-join ", " (map json coll)) "]"))
-
-(defn- json-object
-  [hash]
-  (let [pair (fn [[key val]]
-               (str (json key) ": " (json val)))]
-    (str "{" (str-join ", " (map pair hash)) "}")))
-
-(defn json
-  "Format a Clojure datatype into a portable JSON format."
-  [x]
-  (cond
-    (nil? x)     "null"
-    (seq? x)     (json-array x)
-    (vector? x)  (json-array x)
-    (map? x)     (json-object x)
-    (string? x)  (pr-str x)
-    (keyword? x) (pr-str (name x))
-    (number? x)  (pr-str x)
-    :else        (str x)))


Review comment: add comment about cljify.

--- src/node/datomish/cljify.cljs
+++ src/node/datomish/cljify.cljs
@@ -5,6 +5,9 @@
   but successfully passes Clojure Records through. This allows JS API
   callers to round-trip values they receive from ClojureScript APIs."
   [x]
+  ;; This implementation is almost identical to js->clj, but it allows
+  ;; us to hook into the recursion into sequences and objects, and it
+  ;; passes through records.
   (if (record? x)
     x
     (cond


title is required in most html5

title is required in most html5

--- src/nodecljs/server/core.cljs
+++ src/nodecljs/server/core.cljs
@@ -16,8 +16,10 @@
       (->> (<! jokes-chan)
            (map #(str "
" %))
            (string/join "\n")
-           (#(string/join "\n" ["<!DOCTYPE html>"
-                                % "


Fix typo.

Fix typo.

--- src/oc/storage/api/boards.clj
+++ src/oc/storage/api/boards.clj
@@ -303,8 +303,8 @@
                                org-uuid (:uuid org)
                                user (:user ctx)
                                board (or (:existing-board ctx)
-                                         (if (and (= slug (:slug board-res/default-drafts-board)
-                                                  (lib-schema/valid? lib-schema/User user)))
+                                         (if (and (= slug (:slug board-res/default-drafts-board))
+                                                  (lib-schema/valid? lib-schema/User user))
                                             ;; Draft board for the user
                                             (board-res/drafts-board org-uuid user)
                                             ;; Regular board by slug


Fix rates. Use it only on birthday events.

--- src/ombs/handler/addevent.clj
+++ src/ombs/handler/addevent.clj
@@ -31,6 +31,25 @@
   ;valudation
   (if (isvalid/new-event? event price date users)
     (let [user-rates (db/get-rates (core/as-vec users))
+          party-pay (/ (read-string price) (count users)) ]
+      (db/add-event event (read-string price) date)
+      ;use 'dorun' for execute lazy function 'db/credit-payment'
+      (dorun
+        (map
+          #(db/credit-payment (db/get-uid %) (db/get-eid event date) party-pay)
+          (core/as-vec users)))
+      (println (str "rates " user-rates " pp " party-pay " users " users))
+      (redirect "/user"))
+    (addevent-page)
+
+    )
+  )
+
+(defn add-birthday [ {event :name price :price date :date users :participants :as params} ]
+  "Add event in events table, with adding participants, and calculating debts."
+  ;valudation
+  (if (isvalid/new-event? event price date users)
+    (let [user-rates (db/get-rates (core/as-vec users))
           party-pay (/ (read-string price) (reduce + user-rates)) ]
       (db/add-event event (read-string price) date)
       ;use 'dorun' for execute lazy function 'db/credit-payment'


Remove deceptive log statement.

Remove deceptive log statement.

--- src/onyx/peer/coordinator.clj
+++ src/onyx/peer/coordinator.clj
@@ -282,8 +282,7 @@
     (>!! shutdown-ch scheduler-event)
     (close! shutdown-ch))
   (when allocation-ch
-    (close! allocation-ch))
-  (info "Coordinator stopped."))
+    (close! allocation-ch)))

 (defrecord PeerCoordinator
            [workflow resume-point log messenger-group peer-config peer-id job-id monitoring


Reformat/minor refactor coordinator.

Reformat/minor refactor coordinator.

--- src/onyx/peer/coordinator.clj
+++ src/onyx/peer/coordinator.clj
@@ -62,10 +62,9 @@
       (if (empty? new-remaining)
         (update state :barrier merge {:remaining nil
                                       :offering? false})
-        (do
-         ;; sleep for two milliseconds before retrying the offer
-          (LockSupport/parkNanos (* 2 1000000))
-          (assoc-in state [:barrier :remaining] new-remaining))))
+        (do ;; sleep for two milliseconds before retrying the offer
+            (LockSupport/parkNanos (* 2 1000000))
+            (update state :barrier merge {:remaining new-remaining}))))
     state))

 (defn write-coordinate [curr-version log tenancy-id job-id coordinate]
@@ -75,10 +74,6 @@
        (catch KeeperException$BadVersionException bve
          (throw (Exception. "Coordinator failed to write coordinates.
                              This is likely due to the coordinator being quarantined, and another coordinator taking over.")))))
-
-(defn complete-job! [state job-id]
-  (>!! (:group-ch state) [:send-to-outbox {:fn :complete-job :args {:job-id job-id}}])
-  state)

 (defn next-replica
   [{:keys [log job-id peer-id messenger curr-replica tenancy-id] :as state}
@@ -108,17 +103,20 @@
           (assoc state :curr-replica new-replica))))

 (defn complete-job
-  [{:keys [tenancy-id log job-id messenger checkpoint] :as state}]
+  [{:keys [tenancy-id log job-id messenger checkpoint group-ch] :as state}]
   (info (format "Job %s completed, and final checkpoint has finished. Writing checkpoint coordinates." job-id))
   (let [replica-version (m/replica-version messenger)
         epoch (m/epoch messenger)]
-    (let [coordinates {:tenancy-id tenancy-id :job-id job-id :replica-version replica-version :epoch epoch}
+    (let [coordinates {:tenancy-id tenancy-id
+                       :job-id job-id
+                       :replica-version replica-version
+                       :epoch epoch}
           next-write-version (write-coordinate (:write-version checkpoint) log tenancy-id job-id coordinates)]
+      (>!! group-ch [:send-to-outbox {:fn :complete-job :args {:job-id job-id}}])
       (-> state
-          (complete-job! job-id)
           (update :job merge {:completed? true
                               :sealing? false})
-          (assoc-in [:checkpoint :write-version] next-write-version)))))
+          (update :checkpoint merge {:write-version next-write-version})))))

 (defn merged-statuses [messenger]
   (->> (m/publishers messenger)
@@ -131,7 +129,8 @@
   (if (:offering? barrier)
     ;; No op because hasn't finished emitting last barrier, wait again
     state
-    (let [checkpoint? (first (shuffle [true #_false]))
+    (let [;; always checkpoints at the moment
+          checkpoint? (first (shuffle [true #_false]))
           messenger (m/set-epoch! messenger (inc (m/epoch messenger)))]
       (-> state
           (update :checkpoint merge {:initiated? true
@@ -154,12 +153,12 @@

 (defn checkpointing? [{:keys [initiated? epoch] :as checkpoint} status]
   (and ;; we've initiated a snapshot
-   initiated?
+       initiated?
        ;; none of the statuses are saying they're checkpointing
-   (or (:checkpointing? status)
+       (or (:checkpointing? status)
            ;; and they are all at least up to the checkpoint barrier
            ;; which means that we are not getting a stale status
-       (< (:min-epoch status) epoch))))
+           (< (:min-epoch status) epoch))))

 (defn completed-checkpoint [{:keys [checkpoint messenger job-id tenancy-id log] :as state}]
   (let [{:keys [epoch write-version]} checkpoint
@@ -175,7 +174,7 @@
     (-> state
         ;; TODO, move this into a barrier completed action
         ;; so we can make the checkpoints separate to the barriers
-        (update :barrier merge {:scheduled? false})
+        (update :barrier    merge {:scheduled? false})
         (update :checkpoint merge {:initiated? false
                                    :write-version next-write-version}))))

@@ -235,24 +234,24 @@
   [{:keys [allocation-ch shutdown-ch peer-config] :as state}]
   (thread
     (try
-      (let [;; FIXME: allow in job data
-          ;snapshot-every-n (arg-or-default :onyx.peer/coordinator-snapshot-every-n-barriers peer-config)
-            coordinator-max-sleep-ns (ms->ns (arg-or-default :onyx.peer/coordinator-max-sleep-ms peer-config))
-            barrier-period-ns (ms->ns (arg-or-default :onyx.peer/coordinator-barrier-period-ms peer-config))
-            heartbeat-ns (ms->ns (arg-or-default :onyx.peer/heartbeat-ms peer-config))
-            result (loop [state (initialise-state state)]
-                     (if-let [scheduler-event (poll! shutdown-ch)]
-                       (do (shutdown (assoc state :scheduler-event scheduler-event))
-                           :shutdown)
-                       (if-let [new-replica (poll! allocation-ch)]
-                       ;; Set up reallocation barriers. Will be sent on next recur through :offer-barriers
-                         (recur (next-replica state barrier-period-ns new-replica))
-                         (recur (coordinator-iteration state
-                                                       coordinator-max-sleep-ns
-                                                       barrier-period-ns
-                                                       heartbeat-ns)))))]
-        (when-not (= result :shutdown)
-          (throw (Exception. "Coordinator not properly shutdown"))))
+     (let [;; FIXME: allow in job data
+           ;snapshot-every-n (arg-or-default :onyx.peer/coordinator-snapshot-every-n-barriers peer-config)
+           coordinator-max-sleep-ns (ms->ns (arg-or-default :onyx.peer/coordinator-max-sleep-ms peer-config))
+           barrier-period-ns (ms->ns (arg-or-default :onyx.peer/coordinator-barrier-period-ms peer-config))
+           heartbeat-ns (ms->ns (arg-or-default :onyx.peer/heartbeat-ms peer-config))
+           result (loop [state (initialise-state state)]
+                    (if-let [scheduler-event (poll! shutdown-ch)]
+                      (do (shutdown (assoc state :scheduler-event scheduler-event))
+                          :shutdown)
+                      (if-let [new-replica (poll! allocation-ch)]
+                        ;; Set up reallocation barriers. Will be sent on next recur through :offer-barriers
+                        (recur (next-replica state barrier-period-ns new-replica))
+                        (recur (coordinator-iteration state
+                                                      coordinator-max-sleep-ns
+                                                      barrier-period-ns
+                                                      heartbeat-ns)))))]
+       (when-not (= result :shutdown)
+         (throw (Exception. "Coordinator not properly shutdown"))))
       (catch Throwable e
         (>!! (:group-ch state) [:restart-vpeer (:peer-id state)])
         (fatal e "Error in coordinator")))))


Add clear completed/all/active/completed feature

--- src/todomvc_reagent/core.cljs
+++ src/todomvc_reagent/core.cljs
@@ -32,6 +32,11 @@
   (swap! todos dissoc id))
 (defn save [title]
   (when (not-empty title) (add-todo title)))
+(defn clear-done []
+  (reset! todos (->> (vals @todos)
+                     (filter :done)
+                     (map :id)
+                     (reduce dissoc @todos))))

 ;; -------------------------
 ;; Views
@@ -61,49 +66,58 @@
         [:button.destroy {:on-click #(delete id)}]
         [:input.edit {:value ""}]]]))

-(defn todo-list [todos]
+(defn todo-list [showing todos]
   [:ul.todo-list
-   (for [todo todos]
+   (for [todo (filter (case @showing
+                        :all identity
+                        :active (complement :done)
+                        :completed :done)
+                      todos)]
      ^{:key (:id todo)} [todo-item todo])])

-(defn todo-footer [count]
-  (when (> count 0)
-    [:footer.footer
-     [:span.todo-count [:strong (str count)] " item left"]
-     [:ul.filters
-      [:li [:a.selected {:href "#/"} "All"]]
-      [:li [:a {:href "#/active"} "Active"]]
-      [:li [:a {:href "#/completed"} "Completed"]]]
-     [:button.clear-completed "Clear completed"]]))
+(defn todo-footer [showing count]
+  (let [a-fn (fn [kw url txt]
+               [:a {:class (when (= kw @showing) "selected")
+                    :href url
+                    :on-click #(reset! showing kw)}
+                txt])]
+   (when (> count 0)
+     [:footer.footer
+      [:span.todo-count [:strong (str count)] " item left"]
+      [:ul.filters
+       [:li (a-fn :all "#/" "All")]
+       [:li (a-fn :active "#/active" "Active")]
+       [:li (a-fn :completed "#/completed" "Completed")]]
+      [:button.clear-completed {:on-click #(clear-done)} "Clear completed"]])))

 (defn home-page []
-  (fn []
-    [:div
-     [:section.todoapp
-      [todo-header "reagent" "What needs to be done?"]
+  (let [showing (r/atom :all)]
+   (fn []
+     (let [items (vals @todos)]
+      [:div
+       [:section.todoapp
+        [todo-header "reagent" "What needs to be done?"]

-      [:section.main
-       [:input.toggle-all {:type "checkbox"}]
-       [:label {:for "toggle-all"} "Mark all as complte"]
+        [:section.main
+         [:input.toggle-all {:type "checkbox"}]
+         [:label {:for "toggle-all"} "Mark all as complte"]

-       [todo-list (vals @todos)]]
+         [todo-list showing items]]

-      [todo-footer (count @todos)]
-      ]
+        [todo-footer showing (count items)]
+        ]

-     [:footer.info
-      [:p "Double-click to edit a todo"]
-      [:p "Template by "
-       [:a {:href "http://sindresorhus.com"}]
-       "http://sindresorhus.com"]
-      [:p "Created by "
-       [:a {:href "http://todomvc.com"}]
-       "you"]
-      [:p "Part of  "
-       [:a {:href "http://todomvc.com"}]
-       "TodoMVC"]]
-     ])
-  )
+       [:footer.info
+        [:p "Double-click to edit a todo"]
+        [:p "Template by "
+         [:a {:href "http://sindresorhus.com"}]
+         "http://sindresorhus.com"]
+        [:p "Created by "
+         [:a {:href "http://todomvc.com"}]
+         "you"]
+        [:p "Part of  "
+         [:a {:href "http://todomvc.com"}]
+         "TodoMVC"]]]))))

 ;; -------------------------
 ;; Initialize app


Remove old test code from main module.

Remove old test code from main module.

--- src/uk/me/iwilcox/poltree.clj
+++ src/uk/me/iwilcox/poltree.clj
@@ -150,11 +150,3 @@
     (if (= sibling-side :left)
         (hcombine sibling-data ndata)
         (hcombine ndata sibling-data)))
-
-; A noddy test.
-(require '[uk.me.iwilcox.poltree :as poltree])
-(def accounts (map #(hash-map :uid % :balance % :nonce %) (range 6)))
-(def tree (poltree/accounts->tree accounts))
-(def index (poltree/index-leaves tree))
-(def vpath3 (poltree/verification-path tree (get index 3)))
-(poltree/included? 3 3 vpath3 "Nmu5CwNXrw2xiH2cKj4zyHbRWmoPAU3vZTt2RLVLS2g=")


BW-1251: Make owners check case insensitive (#1611)

--- src/cljs/main/broadfcui/page/method_repo/method/summary.cljs
+++ src/cljs/main/broadfcui/page/method_repo/method/summary.cljs
@@ -33,7 +33,7 @@
    (fn [{:keys [props state locals]}]
      (let [{:keys [selected-snapshot refresh-snapshot]} props
            {:keys [managers]} selected-snapshot
-           owner? (contains? (set managers) (user/get-email))
+           owner? (contains? (set (map string/lower-case managers)) (user/get-email))
            {:keys [body-id]} @locals
            on-method-created (fn [_ method-id]
                                (nav/go-to-path :method-summary method-id)


Re-enable "lein deps", and first attempt to fire up the main program of labrepl.clj, but it's not working yet.

--- ccw.support.examples/src/ccw/support/labrepl/wizards/LabreplCreationOperation.clj
+++ ccw.support.examples/src/ccw/support/labrepl/wizards/LabreplCreationOperation.clj
@@ -24,11 +24,12 @@
      [org.eclipse.jdt.core JavaCore]
      [org.eclipse.debug.core ILaunchManager]
      [java.io IOException]
-     [org.eclipse.core.resources ResourcesPlugin]
+     [org.eclipse.core.resources IResource ResourcesPlugin]
      [org.eclipse.jface.viewers StructuredSelection]
      [ccw ClojureCore]
      [ccw.support.labrepl Activator]
      [ccw.launching ClojureLaunchShortcut]
+     [ccw.editors.antlrbased EvaluateTextAction]
      [org.eclipse.ui.wizards.datatransfer ImportOperation
                                           ZipFileStructureProvider])
   (:use
@@ -88,8 +89,7 @@
   (try
     (let
       [dest-path (.getFullPath project)
-       ; additional-folders ["lib" "classes" "bin"] TODO re-add lib
-       additional-folders ["classes" "bin"]
+        additional-folders ["lib" "classes" "bin"]
         zip-file (get-zipfile-from-plugin-dir "examples/labrepl.zip")]
       (doall (map #(make-project-folder project % monitor) additional-folders))
       (import-files-from-zip zip-file dest-path (SubProgressMonitor. monitor 1) overwrite-query))
@@ -100,8 +100,10 @@
   [project]
   (let
     [java-project (.getJavaProject (ClojureCore/getClojureProject project))
+     lib-folder (.getFolder project "lib")
+     _ (.refreshLocal lib-folder (IResource/DEPTH_ONE) nil)
+     lib-members (.members lib-folder)
      old-lib-entries (vec (.getRawClasspath java-project))
-     lib-members (.members (.getFolder project "lib"))
      new-lib-entries
        (into-array
          (concat old-lib-entries (map #(JavaCore/newLibraryEntry (.getFullPath %) nil nil) lib-members)))]
@@ -122,18 +124,22 @@

     (do-imports project (SubProgressMonitor. monitor 1) overwrite-query)

-    ; TODO handle run-repl
     (if run-lein-deps
       (let
         [leiningen-pfile (.toOSString (.getLocation (.getFile project "project.clj")))
           labrepl-leiningen-project (read-project (str leiningen-pfile))
           run-repl (.getSelection (:run-repl-button page-state))]
-        #_(deps labrepl-leiningen-project) ; TODO enable
-        (println "lein deps is disabled")
+        (deps labrepl-leiningen-project)
         (fix-libraries project)
         (if run-repl
-          (let [startup-file-selection (StructuredSelection. (.getFile (.getFolder project "src") "labrepl.clj"))]
-            (.launch (ClojureLaunchShortcut.) startup-file-selection ILaunchManager/RUN_MODE)))))))
+          (let
+            [startup-file-selection (StructuredSelection. (.getFile (.getFolder project "src") "labrepl.clj"))
+              run-labrepl-action
+                (proxy [EvaluateTextAction] ["Start labrepl"]
+                  (run [] (.evaluateText "(labrepl/-main)")))]
+            (.launch (ClojureLaunchShortcut.) startup-file-selection ILaunchManager/RUN_MODE)
+            ; TODO the following does not work
+            #_(.run run-labrepl-action)))))))

 (defn -run
   [this monitor]


Fixing the es spatial plugin command to install it in the local elastic vm.

--- es-spatial-plugin/project.clj
+++ es-spatial-plugin/project.clj
@@ -63,7 +63,7 @@
             ;; Packages and installs the plugin into the local elastic search vm
             "install-local" ["do"
                              "package,"
-                             "shell" "../cmr-vms/elastic_local/install_plugin.sh" ~plugin-zip-name "spatialsearch-plugin,"
+                             "shell" "../../cmr-vms/elastic_local/install_plugin.sh" ~plugin-zip-name "spatialsearch-plugin,"
                              "clean"]

             "install-aws" ["do"


[scamp] Remove 'do-comms, add 'do-all-comms.

--- modules/scamp/src/scamp/core.clj
+++ modules/scamp/src/scamp/core.clj
@@ -400,16 +400,13 @@
           (assoc :message-envelopes (concatv message-envelopes new-message-envelopes))
           (assoc-in [:network destination-node-id] new-destination-node)))))

-(s/defn do-comms :- WorldSchema
-  "Take 'world and 'n. Process up to 'n messages. Return new 'world.
-   If 'world has no :message-envelopes before 'n messages have been
-   processed, 'world is returned immediately."
-  [world :- WorldSchema
-   n :- s/Int]
-  (if (or (zero? n)
-          (empty? (:message-envelopes world)))
+(s/defn do-all-comms :- WorldSchema
+  "Take 'world. Process communication until no unread messages remain.
+   Return world."
+  [world :- WorldSchema]
+  (if (-> world :message-envelopes empty?)
     world
-    (recur (do-comm world) (dec n))))
+    (recur (do-comm world))))

 (comment
   [1] "Peer-to-Peer Membership Management for Gossip-Based Protocols"


Rebind eval in load just to be sure

Rebind eval in load just to be sure

--- src/oxcart.clj
+++ src/oxcart.clj
@@ -154,7 +154,8 @@
        (binding [*ns*                 *ns*
                  *file*               p
                  *load-configuration* options
-                 clojure.core/load    oxcart/load]
+                 clojure.core/load    oxcart/load
+                 clojure.core/eval    oxcart/eval]
          (loop []
            (let [form (r/read reader false eof)]
              (when (not= eof form)


Account for very slow EventSource on CI

Account for very slow EventSource on CI

--- web/test/immutant/web/sse_test.clj
+++ web/test/immutant/web/sse_test.clj
@@ -38,7 +38,8 @@
           (event->str {:data (range 3)})))))

 (deftest sse
-  (let [closed (promise)
+  (let [complete (promise)
+        closed (promise)
         result (atom [])
         app (fn [req]
               (as-channel req
@@ -47,7 +48,7 @@
                              (send! ch x)
                              (Thread/sleep 10))
                            (send! ch {:event "close", :data "bye!"}
-                             {:on-complete (fn [_] (swap! result conj :done))}))))
+                             {:on-complete (fn [_] (deliver complete :success))}))))
         server (run app)
         client (event-source "http://localhost:8080")]
     (handle-events client (fn [e]
@@ -56,10 +57,10 @@
                               (.close client)
                               (deliver closed :success))))
     (.open client)
-    (is (= :success (deref closed 5000 :fail)))
+    (is (= :success (deref complete 2000 :fail)))
+    (is (= :success (deref closed 2000 :fail)))
     (is (not (.isOpen client)))
-    (is (= ["5" "4" "3" "2" "1"] (take 5 @result)))
-    (is (= #{:done "bye!"} (set (drop 5 @result))))
+    (is (= ["5" "4" "3" "2" "1" "bye!"] @result))
     (stop server)))

 (deftest sse-should-be-utf8-and-have-proper-content-type


imported Texture$WrapMode

imported Texture$WrapMode

--- src/maqueta/hello/terrain.clj
+++ src/maqueta/hello/terrain.clj
@@ -3,7 +3,8 @@

 (ns maqueta.hello.terrain
   (:use (maqueta application assets))
-  (:import com.jme3.terrain.heightmap.ImageBasedHeightMap
+  (:import com.jme3.texture.Texture$WrapMode
+           com.jme3.terrain.heightmap.ImageBasedHeightMap
            (com.jme3.terrain.geomipmap TerrainQuad TerrainLodControl)))

 (def patch-size 65)
@@ -19,9 +20,9 @@
         heightmap (doto (ImageBasedHeightMap. (.getImage hmap-img)) .load)
         terrain (TerrainQuad. "my terrain" patch-size 513 (.getHeightMap heightmap))]
     (.setMoveSpeed fly-cam 50)
-    (.setWrap grass com.jme3.texture.Texture$WrapMode/Repeat)
-    (.setWrap dirt com.jme3.texture.Texture$WrapMode/Repeat)
-    (.setWrap rock com.jme3.texture.Texture$WrapMode/Repeat)
+    (.setWrap grass Texture$WrapMode/Repeat)
+    (.setWrap dirt Texture$WrapMode/Repeat)
+    (.setWrap rock Texture$WrapMode/Repeat)
     (doto mat-terrain
       (.setTexture "Alpha" (load-texture "Textures/Terrain/splat/alphamap.png"))
       (.setTexture "Tex1" grass)


Refactor caused-by-lines

Refactor caused-by-lines

--- src/midje/util/exceptions.clj
+++ src/midje/util/exceptions.clj
@@ -39,9 +39,9 @@

 (defn- caused-by-lines [ex prefix]
   (when-let [cause (.getCause ex)]
-    (let [[data & stacktrace] (friendly-exception-lines cause prefix)]
-      (cons (str line-separator prefix "Caused by: " data)
-            stacktrace))))
+    (let [[message & stacktrace] (friendly-exception-lines cause prefix)]
+      (concat ["" (str prefix "Caused by: " message)]
+              stacktrace))))

 (defn user-error-exception-lines [throwable]
   (cons (str throwable)


Handle incoming NRPN messages

Handle incoming NRPN messages

--- src/mininova_web_ui/midi.cljs
+++ src/mininova_web_ui/midi.cljs
@@ -14,11 +14,33 @@
     (.forEach a #(.push v %))
     (js->clj v)))

+(defn on-nrpn [nrpn-v]
+  (let [msb (nth (first @nrpn-v) 2)
+        lsb (nth (second @nrpn-v) 2)
+        value (nth (nth @nrpn-v 2) 2)]
+    (rf/dispatch [::cc [0xb0 [msb lsb] value]])
+    (reset! nrpn-v [])))
+
+(defn on-cc [nrpn-v data]
+  ;; Check if we are in the middle of NRPN message
+  (if (< 0 (count @nrpn-v))
+    (do
+      (swap! nrpn-v conj data)
+      ;; TODO: Handle 4 len vector
+      (if (= 3 (count @nrpn-v))
+        (on-nrpn nrpn-v)))
+    ;; Check first NRPN message
+    (if (= 0x63 (second data))
+      (swap! nrpn-v conj data)
+      (rf/dispatch [::cc data]))))
+
+(def nrpn-v (atom []))
+
 (defn on-midi-message [data]
   (println ::on-midi-message data)
   (let [status (first data)]
     (condp = status
-      0xb0 (rf/dispatch [::cc data])
+      0xb0 (on-cc nrpn-v data)
       0xc0 (rf/dispatch [::patch data])
       0xf0 (rf/dispatch [::sysex data])
       nil)))


tightenup

tightenup

--- boot/worker/src/boot/jgit.clj
+++ boot/worker/src/boot/jgit.clj
@@ -16,15 +16,18 @@
            (loop [d (.getCanonicalFile (io/file "."))]
              (when d (or (repo d) (recur (.getParentFile d))))))))

+(defmacro with-repo
+  [& body]
+  `(do (assert @repo-dir "This does not appear to be a git repo.")
+       (jgit/with-repo @repo-dir ~@body)))
+
 (defn status
   []
-  (assert @repo-dir "This does not appear to be a git repo.")
-  (jgit/with-repo @repo-dir (jgit/git-status repo)))
+  (with-repo (jgit/git-status repo)))

 (defn branch-current
   []
-  (jgit/with-repo @repo-dir
-    (jgit/git-branch-current repo)))
+  (with-repo (jgit/git-branch-current repo)))

 (defn clean?
   []
@@ -32,14 +35,11 @@

 (defn last-commit
   []
-  (assert @repo-dir "This does not appear to be a git repo.")
-  (jgit/with-repo @repo-dir
-    (->> (jgit/git-log repo) first .getName)))
+  (with-repo (->> (jgit/git-log repo) first .getName)))

 (defn ls-files
   [& {:keys [ref untracked]}]
-  (assert @repo-dir "This does not appear to be a git repo.")
-  (jgit/with-repo @repo-dir
+  (with-repo
     (let [r      (.getRepository repo)
           walk   (RevWalk. r)
           head   (.getRef r (or ref "HEAD"))
@@ -61,7 +61,5 @@

 (defn tag
   [name message]
-  (assert @repo-dir "This does not appear to be a git repo.")
-  (jgit/with-repo @repo-dir
-    (.. repo tag (setName name) (setMessage message) call)))
+  (with-repo (.. repo tag (setName name) (setMessage message) call)))


use some instead of contains?

use some instead of contains?

--- src/oc/storage/api/videos.clj
+++ src/oc/storage/api/videos.clj
@@ -21,7 +21,7 @@
         video-changed (:video-processed entry)]
     (timbre/debug (:state_string video) video entry)
     (when entry
-      (let [error (contains? ["EMPTY" "ERROR"] (:state_string video))
+      (let [error (some #(= (:state_string video) %) ["EMPTY", "ERROR"])
             updated-result (if-not error
                              (entry-res/update-video-data conn video entry)
                              (entry-res/error-video-data conn entry))


specify subclass exception

specify subclass exception

--- src/onyx/state/bookkeeper.clj
+++ src/onyx/state/bookkeeper.clj
@@ -9,7 +9,7 @@
            org.apache.bookkeeper.conf.ServerConfiguration
            org.apache.bookkeeper.proto.BookieServer
            org.apache.commons.io.FileUtils
-           org.apache.zookeeper.KeeperException))
+           [org.apache.zookeeper KeeperException$NodeExistsException]))

 (defn cleanup-dir [dir]
   (FileUtils/deleteDirectory (File. ^String dir)))


key-name and floating-ip validation

key-name and floating-ip validation

--- src/openstack/validations.clj
+++ src/openstack/validations.clj
@@ -28,8 +28,9 @@
 (def openstack-common
   {:openstack
    {:flavor #{:required :String} :tenant #{:required :String}
-    :security-groups #{:Vector :group*} :networks #{:Vector :network*}}}
-  )
+    :security-groups #{:Vector :group*} :networks #{:Vector :network*}
+    :key-name #{:required :String} :floating-ip #{:ip :String}
+    }})

 (defn validate-entity
   "openstack based systems entity validation "


update example

update example

--- example/src/example/core.cljs
+++ example/src/example/core.cljs
@@ -3,11 +3,6 @@
             [goog.dom :as gdom]
             [cljss.core :as css :refer [inject-global]]
             [cljss.rum :refer-macros [defstyled]]))
-
-(inject-global
-  {:body {:margin 0
-          :font "normal 16px sans-serif"
-          :color "#242424"}})

 (def btn-bg-colors
   {:primary "#0052CC"
@@ -115,4 +110,15 @@
      (H2 {} "Clojure Style Sheets"))
    (ButtonsDemo)])

-(rum/mount (app) (gdom/getElement "app"))
+(defn render []
+  (rum/mount (app) (gdom/getElement "app")))
+
+(defn mount []
+  (css/remove-styles!)
+  (inject-global
+    {:body {:margin 0
+            :font "normal 16px sans-serif"
+            :color "#242424"}})
+  (render))
+
+(render)


Use find-first

Use find-first

--- resources/isometric-rpg/utils.clj
+++ resources/isometric-rpg/utils.clj
@@ -161,9 +161,8 @@
 (defn get-entity-at-cursor
   [screen entities input-x input-y]
   (let [cursor-pos (input->screen screen input-x input-y)]
-    (some (fn [{:keys [x y width height npc? health] :as entity}]
-            (-> (rectangle x y width height)
-                (rectangle! :contains (:x cursor-pos) (:y cursor-pos))
-                (and npc? (> health 0))
-                (when entity)))
-          entities)))
+    (find-first (fn [{:keys [x y width height npc? health] :as entity}]
+                  (-> (rectangle x y width height)
+                      (rectangle! :contains (:x cursor-pos) (:y cursor-pos))
+                      (and npc? (> health 0))))
+                entities)))


Implement the `rating/update` function.

Implement the `rating/update` function.

--- src/regarde/models/rating.clj
+++ src/regarde/models/rating.clj
@@ -24,7 +24,10 @@
                                              :users_id (Integer.  rating-user-id) }])))

 (defn update [rating new-rating-value]
-  (println "updating rating"))
+  (sql/update
+   entities/ratings
+   (sql/set-fields {:rating (Integer. new-rating-value)})
+   (sql/where {:id (:id rating)})))

 (defn update-or-create [set user-id value]
   (if-let [rating (find (:id set) user-id)]


Shutdown service after metrics test

Shutdown service after metrics test

--- test/clojure/service_test.clj
+++ test/clojure/service_test.clj
@@ -4,8 +4,7 @@
             [fault.service :as service])
   (:import (java.io IOException)
            (java.util.concurrent CountDownLatch)
-           (fault.metrics ActionMetrics)
-           (fault.service CLJMetrics CLJService)))
+           (fault ServiceExecutor)))

 (set! *warn-on-reflection* true)

@@ -78,4 +77,5 @@
       (service/submit-action metrics-service (fn [] (.await latch)) Long/MAX_VALUE)
       (service/submit-action metrics-service (fn [] 1) Long/MAX_VALUE)
       (.countDown latch)
-      (is (= 1 (-> metrics-service :metrics :max-concurrency-level-exceeded))))))+      (is (= 1 (-> metrics-service :metrics :max-concurrency-level-exceeded)))
+      (service/shutdown metrics-service))))


M0ar tests

M0ar tests

--- test/grimoire/things_test.clj
+++ test/grimoire/things_test.clj
@@ -92,3 +92,12 @@
     (is-assert-error?
      (t/thing->artifact
       (t/thing->group t)))))
+
+(deftest thing->root-to-tests
+  (is (= (t/thing->path (t/thing->platform t))
+         (t/thing->root-to t/platform t))))
+
+(deftest ensure-thing-tests
+  (is (= t (t/ensure-thing (t/thing->path t))))
+  (is (= t (t/ensure-thing t)))
+  (is (thrown? Exception (t/ensure-thing 1))))


Updated the footer.

Updated the footer.

--- test/lambda_blog/fixtures.clj
+++ test/lambda_blog/fixtures.clj
@@ -39,7 +39,14 @@
             (text-centered "Some banner contents"))))

 (defn- footer [_]
-  (text-centered "Some footer contents"))
+  (text-centered
+   "All writing licensed under "
+   (a {:rel :license
+       :href "http://creativecommons.org/licenses/by-sa/4.0/"}
+      (img {:alt "Creative Commons License"
+            :style "border-width:0;"
+            :src "https://i.creativecommons.org/l/by-sa/4.0/80x15.png"}))
+   ". All code released to the Public Domain unless otherwise specified."))

 (def docs {:author "Idorobots"
            :brand "λ-blog"


attempt to use HTML5 history api

attempt to use HTML5 history api

--- src/deathrow/core.cljs
+++ src/deathrow/core.cljs
@@ -6,10 +6,12 @@
 		[crate.core :as crate]
 		[secretary.core :as secretary :include-macros true :refer [defroute]]
 		[goog.events :as events]
-		[goog.history.EventType :as EventType])
-	(:import goog.History))
-
-(def hist (History.))
+		[goog.history.EventType :as EventType]
+		[goog.history.Html5History :as history5])
+
+	)
+;(:import goog.History.Html5History)
+(def hist (goog.history.Html5History.))

 (defroute offenders-path "/"
 	[]
@@ -61,20 +63,28 @@
 (defn init-random-btn-event
 	[]
 	(-> ($ ".load-statement")
-		(.on "click" #(do (secretary/dispatch! (random-path)) (.preventDefault %)))))
+		;(.on "click" #(do (secretary/dispatch! (random-path)) (.preventDefault %)))
+		))

+(defn init-history
+	[]
+	(doto hist
+		(goog.events/listen EventType/NAVIGATE #(do (log "NAVIGATE event")
+													(log %)
+													(log (str "TOKEN: " (.-token %)))
+													(.stopPropagation %)
+													(secretary/dispatch! (.-token %))
+													;(.setToken hist (.-token %))
+													(log "oi"))))
+		(.setUseFragment false)
+		(.setPathPrefix "")
+		(.setEnabled true))

 (defn init
 	[]
 	(do
 		(log "Initializing...")
-		(doto hist
-			(goog.events/listen EventType/NAVIGATE #(do (log "NAVIGATE event")
-														(log %)
-														(secretary/dispatch! (.-token %))
-														;(.setToken hist (.-token %))
-														(log "oi")))
-			(.setEnabled true))))
+		))

-(init)
+(init-history)


Update linting

Update linting

--- src/discuss/views.cljs
+++ src/discuss/views.cljs
@@ -191,7 +191,7 @@

 (defn main-content-view [data]
   (dom/div nil
-           (when-not (empty? (:discussion @lib/app-state))
+           (when (seq (:discussion @lib/app-state))
              (dom/div #js {:className "text-center"}
                       (get-in data [:layout :intro])
                       (dom/br nil)


Layout manager #41

Layout manager #41

--- src/flatgui/layout.clj
+++ src/flatgui/layout.clj
@@ -351,10 +351,10 @@
   (if-let [coord-map (get-property [] :coord-map)]
     (if-let [coord ((:id component) coord-map)]
       (let [ps (get-property [] :clip-size)
-            btop 0.375;TODO see 0.375 - window border
-            bbtm 0.0
-            bleft 0.0
-            bright 0.0]
+            btop (+ 0.375 (awt/px) (awt/px)) ;TODO see 0.375 - window border
+            bbtm (+ (awt/px) (awt/px))
+            bleft (+ (awt/px) (awt/px))
+            bright(+ (awt/px) (awt/px))]
         (m/translation
           (d/round-granular (+ bleft gap (* (:x coord) (- (m/x ps) bleft bright))) (awt/px))
           (d/round-granular (+ btop gap (* (:y coord) (- (m/y ps) btop bbtm))) (awt/px))))
@@ -365,10 +365,10 @@
   (if-let [coord-map (get-property [] :coord-map)]
     (if-let [coord ((:id component) coord-map)]
       (let [ps (get-property [] :clip-size)
-            btop 0.375;TODO see 0.375 - window border
-            bbtm 0.0
-            bleft 0.0
-            bright 0.0]
+            btop (+ 0.375 (awt/px) (awt/px)) ;TODO see 0.375 - window border
+            bbtm (+ (awt/px) (awt/px))
+            bleft (+ (awt/px) (awt/px))
+            bright(+ (awt/px) (awt/px))]
         (m/defpoint
           (d/round-granular (- (* (:w coord) (- (m/x ps) bleft bright)) gap gap) (awt/px))
           (d/round-granular (- (* (:h coord) (- (m/y ps) btop bbtm)) gap gap) (awt/px))))


Update to use reworked actions API

Update to use reworked actions API

--- src/flense_nw/app.cljs
+++ src/flense_nw/app.cljs
@@ -1,12 +1,8 @@
 (ns flense-nw.app
   (:require [cljs.core.async :as async :refer [<!]]
             [cljs.reader :as rdr]
-            [flense.actions :refer [actions defaction]]
+            [flense.actions :refer [default-actions]]
             [flense.actions.history :as hist]
-            flense.actions.clipboard
-            flense.actions.clojure
-            flense.actions.movement
-            flense.actions.paredit
             [flense.editor :refer [editor-view]]
             [flense.model :as model]
             [flense-nw.cli :refer [cli-view]]
@@ -45,6 +41,11 @@
      :tree {:children
             (->> (fs/slurp fpath) model/string->forms (mapv model/form->tree))}}))

+(def actions
+  (assoc default-actions :flense/text-command
+         ;; dummy action to trap ctrl+x keybind
+         (with-meta identity {:tags #{:end-text-editing :text-command}})))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; text commands
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -56,7 +57,7 @@

 (defmethod handle-command "exec" [_ & args]
   (if-let [name (first args)]
-    (if-let [action (-> name rdr/read-string (@actions))]
+    (if-let [action (-> name rdr/read-string actions)]
       (async/put! edit-chan action)
       (raise! "Invalid action \"" name \"))
     (raise! "Must specify an action to execute")))
@@ -73,13 +74,11 @@
 (def ^:dynamic *keymap*)

 (defn- bound-action [ev]
-  (-> ev phalanges/key-set *keymap* (@actions)))
-
-(defaction :flense/text-command :edit identity) ; dummy action to trap ctrl+x keybind
+  (-> ev phalanges/key-set *keymap* actions))

 (defn- handle-key [ev]
   (when-let [action (bound-action ev)]
-    (if (= (:name action) :flense/text-command)
+    (if (contains? (:tags (meta action)) :text-command)
       (.. js/document (getElementById "cli") focus)
       (do (.preventDefault ev)
           (async/put! edit-chan action)))))
@@ -92,9 +91,9 @@
   (when-let [action (bound-action ev)]
     (if (model/stringlike? form)
       ;; prevent all keybinds except those that end editing
-      (#{:flense/text-command :move/up :paredit/insert-outside} (:name action))
+      (contains? (:tags (meta action)) :end-text-editing)
       ;; prevent delete keybind unless text fully selected
-      (or (not= (:name action) :flense/remove)
+      (or (not (contains? (:tags (meta action)) :remove))
           (fully-selected? (.-target ev))))))

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


fixed incorrect download progress

fixed incorrect download progress

--- src/frontend/core.cljs
+++ src/frontend/core.cljs
@@ -90,6 +90,8 @@
   (.emit socket "track-complete"))

 (defn play-track [track-id]
+  (println "TRACK ID! " track-id)
+  (println (:music-files @app-state))
   (let [reader (new js/FileReader)
         song-blob (get (:music-files @app-state) track-id)]
     (.readAsDataURL reader song-blob)
@@ -155,6 +157,7 @@
         (println "Download complete!")
         (swap! app-state assoc :is-file-downloading? true)
         (swap! app-state assoc :download-progress nil)
+        (swap! app-state assoc :data-downloaded 0)

         (if (= (:current-track-id @app-state) track-id)
           (.emit socket "ready-to-start"))))))


Gotta stop doing dumb things

Gotta stop doing dumb things

--- src/lazubot/docker.clj
+++ src/lazubot/docker.clj
@@ -95,15 +95,17 @@
   "Send a Clojure form string to a worker for evaluation.  Return a
   channel onto which the result will be posted."
   [form]
-  (go-loop [form form]
-   (let [worker-doc (acquire-worker-doc!)]
-     (if-not worker-doc
-       (do (<! (timeout 500))
-           (recur form))
-       (let [result-channel (chan)]
-         (>! (:in worker-doc) form)
-         (let [[response channel] (alts! [(:out worker-doc) (timeout 10000)])]
-           (if (= channel (:out worker-doc))
-             (>! result-channel (String. response))
-             (replace-worker! worker-doc)))
-         result-channel)))))
+  (let [result-channel (chan)]
+    (go-loop [form form]
+             (let [worker-doc (acquire-worker-doc!)]
+               (if-not worker-doc
+                 (do (<! (timeout 500))
+                     (recur form))
+                 (let [result-channel (chan)]
+                   (>! (:in worker-doc) form)
+                   (let [[response channel] (alts! [(:out worker-doc) (timeout 10000)])]
+                     (if (nil? response)
+                       (do (replace-worker! worker-doc)
+                           (>! result-channel (str "Evaluation timed out")))
+                       (>! result-channel (String. response))))))))
+    result-channel))


Modify test task so it doesn't load clojure.test in Leiningen's classloader.

--- src/leiningen/test.clj
+++ src/leiningen/test.clj
@@ -1,11 +1,7 @@
 (ns leiningen.test
   "Run the project's tests."
   (:refer-clojure :exclude [test])
-  ;; When using -Xbootclasspath transitive requires break, so we need
-  ;; to require stuff that clojure.test depends on explicitly:
-  (:require [clojure walk template stacktrace])
-  (:use [clojure.test]
-        [clojure.contrib.java-utils :only [file]]
+  (:use [clojure.contrib.java-utils :only [file]]
         [clojure.contrib.find-namespaces :only [find-namespaces-in-dir]]
         [leiningen.compile :only [eval-in-project]]))

@@ -19,11 +15,12 @@
              summary# (reduce (fn [summary# n#]
                                 (require n# :reload-all)
                                 (merge-with add-numbers#
-                                            summary# (run-tests n#)))
+                                            summary#
+                                            (clojure.test/run-tests n#)))
                               {} '~namespaces)]
-         (with-test-out
+         (clojure.test/with-test-out
            (println "\n\n--------------------\nTotal:")
-           (report summary#)))))
+           (clojure.test/report summary#)))))

 (defn test
   "Run the project's tests. Accept a list of namespaces for which to run all


Prefix GitHub HTTPS credentials with EXPERIMENTAL_

- the ability to prefer HTTPS is new and requires further testing
- we should investigate other mechanisms for supplying these credentials

--- src/leiningen/voom.clj
+++ src/leiningen/voom.clj
@@ -148,7 +148,8 @@
    (:lines (git {:gitdir gitdir} "remote" "-v"))))

 (defn https-credentials []
-  (let [creds (keep #(System/getenv %) ["VOOM_GH_USER" "VOOM_GH_PASS"])]
+  (let [creds (keep #(System/getenv %)
+                    ["EXPERIMENTAL_VOOM_GH_USER" "EXPERIMENTAL_VOOM_GH_PASS"])]
     (when (seq creds) (vec creds))))

 (defn github-ssh-repo? [^String repo]


WIP - Evolution du bot CSB en Clojure avec l'objectif d'améliorer le classement en ligue argent

--- clojure/codingame/competition/coders-strike-back/src/coders_strike_back/Player.clj
+++ clojure/codingame/competition/coders-strike-back/src/coders_strike_back/Player.clj
@@ -3,6 +3,7 @@

 (def checkpoint-core-size 100)
 (def delay-between-shield-use 10)
+(def min-distance-to-activate-shield 950)

 (defn inc-atom [curr-val] (inc curr-val))
 (defn dec-atom [curr-val] (dec curr-val))
@@ -32,17 +33,17 @@
   (if (> next-checkpoint-distance 1000)
     (cond
       (and (>= next-checkpoint-angle -90) (<= next-checkpoint-angle 90) (before next-checkpoint-x x))
-      (convert-to-int (+ next-checkpoint-x (* checkpoint-core-size (Math/cos next-checkpoint-angle))))
+      (convert-to-int (+ next-checkpoint-x (* checkpoint-core-size (Math/cos (convert-degree-to-radian next-checkpoint-angle)))))
       (and (>= next-checkpoint-angle -90) (<= next-checkpoint-angle 90) (after next-checkpoint-x x))
-      (convert-to-int (- next-checkpoint-x (* checkpoint-core-size (Math/cos next-checkpoint-angle))))
+      (convert-to-int (- next-checkpoint-x (* checkpoint-core-size (Math/cos (convert-degree-to-radian next-checkpoint-angle)))))
       (or (<= -180 next-checkpoint-angle -90 ) (>= 180 next-checkpoint-angle 90))
-      (convert-to-int (- next-checkpoint-x (* checkpoint-core-size (Math/cos next-checkpoint-angle)))))
+      (convert-to-int (- next-checkpoint-x (* checkpoint-core-size (Math/cos (convert-degree-to-radian next-checkpoint-angle))))))
     next-checkpoint-x))

 (defn compute-y [y next-checkpoint-y next-checkpoint-angle next-checkpoint-distance]
   (if (cond
-        (and (>= next-checkpoint-angle 0)  (<= next-checkpoint-angle 180)) (convert-to-int (- next-checkpoint-y (* checkpoint-core-size (Math/sin next-checkpoint-angle))))
-        (and (< next-checkpoint-angle 0) (>= next-checkpoint-angle -180)) (convert-to-int (+ next-checkpoint-y (* checkpoint-core-size (Math/sin next-checkpoint-angle)))))
+        (and (>= next-checkpoint-angle 0)  (<= next-checkpoint-angle 180)) (convert-to-int (- next-checkpoint-y (* checkpoint-core-size (Math/sin (convert-degree-to-radian next-checkpoint-angle)))))
+        (and (< next-checkpoint-angle 0) (>= next-checkpoint-angle -180)) (convert-to-int (+ next-checkpoint-y (* checkpoint-core-size (Math/sin (convert-degree-to-radian next-checkpoint-angle))))))
     next-checkpoint-y))

 ;;Angle entre 2 points (x1,y1) et (x2,y2)
@@ -58,6 +59,7 @@
   (cond
     ;(>= (Math/abs next-checkpoint-angle) 90) "0"
     (<= next-checkpoint-distance 1000) "40"
+    (<= next-checkpoint-distance 800) "20"
     (<= (Math/abs next-checkpoint-angle) 18) "100"
     true (compute-boost-from-angle (Math/abs next-checkpoint-angle))))

@@ -70,7 +72,7 @@
     (and (not (= @last-boost-value "SHIELD")) (not (= @last-boost-value "BOOST")) (= @last-shield-usage 0))))

 (defn use-shield? [x y opponent-x opponent-y boost-used? game-loop-counter max-shield-usage last-shield-usage last-boost-value]
-  (and (= @last-shield-usage 0) (> @game-loop-counter 10) (> @max-shield-usage 0) (< (distance opponent-x opponent-y x y) 1000)))
+  (and (= @last-shield-usage 0) (> @game-loop-counter 10) (> @max-shield-usage 0) (< (distance opponent-x opponent-y x y) min-distance-to-activate-shield)))

 ;;Compute BOOST, SHIELD or boost value between 0 and 100
 (defn compute-action [next-checkpoint-x next-checkpoint-y next-checkpoint-distance next-checkpoint-angle x y opponent-x opponent-y boost-used? game-loop-counter max-shield-usage last-shield-usage last-boost-value]
@@ -102,21 +104,21 @@

         ; (binding [*out* *err*]
         ;   (println "Debug messages..."))
-        ;(binding [*out* *err*]
-        ;  (println (str "Has the boost been used ? : " @boost-used?))
-        ;  (println (str "Next check point distance coordinates : (" nextCheckpointX "," nextCheckpointY ")"))
-        ;  (println (str "Given next check point distance : " nextCheckpointDist))
-        ;  (println (str "Calculated next check point distance : " (distance x y nextCheckpointX nextCheckpointY)))
-        ;  (println (str "Pod angle with checkpoint : " nextCheckpointAngle))
-        ;  (println (str "Calculated Pod angle with checkpoint : " (angle-between-2-points x y nextCheckpointX nextCheckpointY)))
-        ;  (println (str "Pod Position : (" x "," y ")"))
-        ;  (println (str "Opponent pod Position : (" opponentX "," opponentY ")"))
-        ;  (println (str "Opponent distance : " opponent-distance))
-        ;  (println (str "Calculated Pod angle with opponent : " (angle-between-2-points x y opponentX opponentY)))
-        ;  (println (str "Max Shield Usage : " @max-shield-usage))
-        ;  (println (str "Last Shield Usage : " @last-shield-usage))
-        ;  (println (str "Game loop counter : " @game-loop-counter))
-        ;  (println (str "Last boost value : " @last-boost-value)))
+        (binding [*out* *err*]
+          (println (str "Has the boost been used ? : " @boost-used?))
+          (println (str "Next check point distance coordinates : (" nextCheckpointX "," nextCheckpointY ")"))
+          (println (str "Given next check point distance : " nextCheckpointDist))
+          (println (str "Calculated next check point distance : " (distance x y nextCheckpointX nextCheckpointY)))
+          (println (str "Pod angle with checkpoint : " nextCheckpointAngle))
+          (println (str "Calculated Pod angle with checkpoint : " (angle-between-2-points x y nextCheckpointX nextCheckpointY)))
+          (println (str "Pod Position : (" x "," y ")"))
+          (println (str "Opponent pod Position : (" opponentX "," opponentY ")"))
+          (println (str "Opponent distance : " opponent-distance))
+          (println (str "Calculated Pod angle with opponent : " (angle-between-2-points x y opponentX opponentY)))
+          (println (str "Max Shield Usage : " @max-shield-usage))
+          (println (str "Last Shield Usage : " @last-shield-usage))
+          (println (str "Game loop counter : " @game-loop-counter))
+          (println (str "Last boost value : " @last-boost-value)))


--- clojure/codingame/competition/coders-strike-back/src/coders_strike_back/Player.clj
+++ clojure/codingame/competition/coders-strike-back/src/coders_strike_back/Player.clj
@@ -38,6 +38,10 @@
   (let [d (distance x1 y1 x2 y2) dx (/ (- x2 x1) d) dy (/ (- y2 y1) d) angle (convert-radian-to-degree (Math/acos dx))]
     (if (< dy 0) (- 360.0 angle) angle)))

+(defn adjustement-from-angle [value next-checkpoint-angle]
+  (+ value (* checkpoint-core-size (convert-to-int (Math/signum (Math/cos next-checkpoint-angle))))))
+
+
 (defn compute-x-y [x y next-checkpoint-x next-checkpoint-y next-checkpoint-angle next-checkpoint-distance]
   (cond
     (and (< x next-checkpoint-x) (< y next-checkpoint-y)) (str (- next-checkpoint-x checkpoint-core-size) " " (- next-checkpoint-y checkpoint-core-size))
@@ -52,9 +56,7 @@
 ;;Compute a boost value between 0 and 100
 (defn compute-boost [next-checkpoint-distance next-checkpoint-angle]
   (cond
-    ;(>= (Math/abs next-checkpoint-angle) 90) "40"
     (<= next-checkpoint-distance 1000) "40"
-    ;(<= next-checkpoint-distance 800) "20"
     (<= (Math/abs next-checkpoint-angle) 36) "100"
     true (compute-boost-from-angle (Math/abs next-checkpoint-angle))))


dissoc message/cursor from events before writing to db (#20)

--- src/rill/event_store/psql.clj
+++ src/rill/event_store/psql.clj
@@ -133,7 +133,7 @@

 (defn strip-metadata
   [e]
-  (dissoc e message/type message/id message/number message/timestamp message/stream-id))
+  (dissoc e message/type message/id message/number message/timestamp message/stream-id message/cursor))

 (defrecord PsqlEventStore [spec page-size]
   EventStore


todomvc: be able to get carry-debugger from Clojars; bump Schema dep version

--- examples/todomvc/project.clj
+++ examples/todomvc/project.clj
@@ -5,13 +5,13 @@

                  [org.clojure/core.match "0.3.0-alpha4"]

-                 [reagent "0.6.0-SNAPSHOT" :exclusions [cljsjs/react]]
+                 [reagent "0.6.0-alpha2" :exclusions [cljsjs/react]]
                  [cljsjs/react-with-addons "15.0.2-0"]

                  [com.domkm/silk "0.1.2"]
                  [com.rpl/specter "0.10.0"]
                  [funcool/hodgepodge "0.1.4"]
-                 [prismatic/schema "1.1.0"]
+                 [prismatic/schema "1.1.1"]

                  [binaryage/devtools "0.6.1"]]

@@ -27,19 +27,15 @@
                                            [cljsjs/filesaverjs "1.1.20151003-0"]]}

              :clojars-deps {:dependencies [[carry "0.1.0"]
+                                           [carry-debugger "0.1.0"]
+                                           [carry-history "0.3.0"]
+                                           [carry-logging "0.1.0"]
+                                           [carry-persistence "0.3.0"]
                                            [carry-reagent "0.2.0"]
-                                           [carry-logging "0.1.0"]
-                                           [carry-history "0.3.0"]
-                                           [carry-schema "0.2.0"]
-                                           [carry-persistence "0.3.0"]
-
-                                           ; required by carry-debugger:
-                                           [cljsjs/jquery-ui "1.11.4-0"]
-                                           [cljsjs/filesaverjs "1.1.20151003-0"]]}}
+                                           [carry-schema "0.2.0"]]}}

   :cljsbuild {:builds [{:id           "clojars-deps"
-                        :source-paths ["src"
-                                       "../../contrib/debugger/src"]
+                        :source-paths ["src"]
                         :compiler     {:main                 app.core
                                        :asset-path           "js/compiled/clojars-deps/out"
                                        :output-to            "resources/public/js/compiled/frontend.js"


(SERVER-1183) Changed invalidated to invalidate in env-class-info func

This commit changes the name of the
`invalidated-environment-class-info-entry` function to
`invalidate-environment-class-info-entry`.

--- src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj
+++ src/clj/puppetlabs/services/jruby/jruby_puppet_core.clj
@@ -369,7 +369,7 @@
       inc-cache-generation-id-for-class-info-entry
       (assoc :tag tag)))

-(schema/defn ^:always-valid invalidated-environment-class-info-entry
+(schema/defn ^:always-valid invalidate-environment-class-info-entry
   :- EnvironmentClassInfoCacheEntry
   "Return the supplied 'original-environment-class-info-entry', only updated
   with a nil tag and a cache-generation-id value that has been incremented."
@@ -389,7 +389,7 @@
    env-name :- schema/Str]
   (->> env-name
        (get environment-class-info-cache)
-       invalidated-environment-class-info-entry
+       invalidate-environment-class-info-entry
        (assoc environment-class-info-cache env-name)))

 (schema/defn ^:always-validate
@@ -468,7 +468,7 @@
   [context :- jruby-schemas/PoolContext
    environment-class-info-cache :- (schema/atom EnvironmentClassInfoCache)]
   (swap! environment-class-info-cache
-         (partial ks/mapvals invalidated-environment-class-info-entry))
+         (partial ks/mapvals invalidate-environment-class-info-entry))
   (doseq [jruby-instance (registered-instances context)]
     (-> jruby-instance
         :environment-registry


Move websocket client into separate thread

--- src/clojure/uk/org/potentialdifference/darknet/main.clj
+++ src/clojure/uk/org/potentialdifference/darknet/main.clj
@@ -321,26 +321,27 @@
                                                                              (.toString out))}]))
                                       "stop" (sv (layout this (idle-screen Color/GREEN)))
                                       :default))))]
-             (letfn [(new-client []
-                       (log/i "darknet" "new client called")
-                       (reset! client
-                               (websocket/connect!
-                                (:ws-url config)
-                                {:on-open (fn [_]
-                                            (log/i "darknet" "websocket open")
-                                            (set-status! this Color/GREEN))
-                                 :on-close (fn [code reason remote]
-                                             (log/i "darknet on close" code reason remote)
-                                             (when-not (nil? @client)
-                                               (log/i "darknet unexpected close ... restarting")
-                                               (set-status! this Color/RED)
-                                               (Thread/sleep 1000)
-                                               (new-client)))
-                                 :on-message on-message
-                                 :on-error (fn [e]
-                                             (log/i "darknet on error" (.getMessage e))
-                                             (set-status! this Color/RED))})))]
-               (new-client)))
+             (future
+               (letfn [(new-client []
+                         (log/i "darknet" "new client called")
+                         (reset! client
+                                 (websocket/connect!
+                                  (:ws-url config)
+                                  {:on-open (fn [_]
+                                              (log/i "darknet" "websocket open")
+                                              (set-status! this Color/GREEN))
+                                   :on-close (fn [code reason remote]
+                                               (log/i "darknet on close" code reason remote)
+                                               (when-not (nil? @client)
+                                                 (log/i "darknet unexpected close ... restarting")
+                                                 (set-status! this Color/RED)
+                                                 (Thread/sleep 1000)
+                                                 (new-client)))
+                                   :on-message on-message
+                                   :on-error (fn [e]
+                                               (log/i "darknet on error" (.getMessage e))
+                                               (set-status! this Color/RED))})))]
+                 (new-client))))
            (log/i "darknet on start"))
   (onResume [this]
             (.superOnResume this)


boot_gae.clj: fix run task, handle class strings

* run task can run multiple services
* fix handling of class strings to support hyphenated nss

--- src/migae/boot_gae.clj
+++ src/migae/boot_gae.clj
@@ -30,6 +30,13 @@
 (def web-inf-dir "WEB-INF")
   ;; (let [mod (-> (boot/get-env) :gae :module :name)]
   ;;   (str (if mod (str mod "/")) "WEB-INF")))
+
+(defn name-to-path
+  "Constructs directory structure from fully qualified artifact name:
+  \"foo-bar.baz\" becomes \"foo_bar/baz\"
+  and so on. Uses platform-specific file separators."
+  [s]
+  (-> s (str/replace "-" "_") (str/replace "." java.io.File/separator)))

 ;; http://stackoverflow.com/questions/2751033/clojure-program-reading-its-own-manifest-mf
 (defn manifest-map
@@ -577,11 +584,11 @@
           (appengine :verbose verbose)
           (builtin/sift :move {#"(.*clj$)" (str classes-dir "/$1")})
           (builtin/sift :move {#"(.*\.class$)" (str classes-dir "/$1")})
-          (if servlet
-            identity
-            (comp
-             (builtin/pom)
-             (builtin/jar)))
+          ;; (if servlet
+          ;;   identity
+          ;;   (comp
+          ;;    (builtin/pom)
+          ;;    (builtin/jar)))
           #_(target :servlet servlet :verbose verbose)
           #_(builtin/sift :include #{(re-pattern (str mod ".*jar"))})
           #_(builtin/install)
@@ -776,9 +783,11 @@
    (vec (flatten (for [config (:filters configs)]
           (let [urls (into [] (for [url (:urls config)]
                                 {:path (str url)}))
-                ns (if (:ns config) (:ns config) (:class config)) ]
+                class  (str/replace (:ns config) "-" "_")]
+                ;;ns (if (:ns config) (:ns config) (:class config)) ]
             (merge config {:urls urls
-                           :filter {:ns ns}})))))})
+                           :class class
+                           :filter {:ns (:ns config)}})))))})

 ;; (boot/deftask filters
 ;;   "generate filters class files"
@@ -1453,11 +1462,13 @@
                                           services)))
                             ;; modules))

-          wardirs (remove nil?
-                          (into [] (map #(if (:wardir %)
-                                           (.getAbsolutePath (io/file (:wardir %)))
-                                           nil)
+          wardirs (if services
+                    (remove nil?
+                            (into [] (map #(if (:wardir %)
+                                             (.getAbsolutePath (io/file (:wardir %)))
+                                             nil)
                                           services)))
+                    ["target"])

           _ (println "WARDIRS: " wardirs)

@@ -1501,13 +1512,16 @@

 (defn- normalize-servlet-configs
   [configs]
+  ;;(println "normalizing servlet config: " configs)
   {:servlets
    (vec (flatten (for [config (:servlets configs)]
           (let [urls (into [] (for [url (:urls config)]
                                 {:path (str url)}))
+                class  (str/replace (:ns config) "-" "_")
                 ns (if (:ns config) (:ns config) (:class config)) ]
             (merge config {:urls urls
-                           :servlet {:ns ns}})))))})
+                           :class class
+                           :servlet {:ns (:ns config)}})))))})

 (boot/deftask servlets
   "generate servlets class files"
@@ -1558,8 +1572,9 @@
                                                      (count servlets-edn-files)))))
                      servlets-edn-map (-> (boot/tmp-file servlets-edn-f) slurp read-string)
                      servlets-config-map (normalize-servlet-configs servlets-edn-map)
-                     servlets-config-map {:servlets (filter #(nil? (:class %))
-                                                            (:servlets servlets-config-map))}
+                     ;; _ (println "normalized: " servlets-config-map)
+                     servlets-config-map {:servlets ;;(filter #(nil? (:class %))
+                                                            (:servlets servlets-config-map)}

                      ;; step 2: inject servlets config map into master config map
                      master-config (-> boot-config-edn-map (assoc-in [:servlets]


Add Decodable protocol for byte arrays and hex strings.

--- src/multihash/core.clj
+++ src/multihash/core.clj
@@ -240,8 +240,8 @@
   [mhash]
   (let [length (:length mhash)
         encoded (byte-array (+ length 2))]
-    (aset encoded 0 (byte (:code mhash)))
-    (aset encoded 1 (byte length))
+    (aset-byte encoded 0 (byte (:code mhash)))
+    (aset-byte encoded 1 (byte length))
     (System/arraycopy (:bytes mhash) 0 encoded 2 length)
     encoded))

@@ -275,4 +275,40 @@
       (create code digest))))

-; TODO: (read! InputStream)
+(defprotocol Decodable
+  "This protocol provides a method for data sources which a multihash can be
+  read from."
+
+  (decode
+    [source]
+    "Attempts to read a multihash value from the data source."))
+
+
+(extend-protocol Decodable
+
+  (class (byte-array 0))
+
+  (decode
+    [source]
+    (decode-array source))
+
+
+  String
+
+  (decode
+    [source]
+    (decode-array (hex->bytes source)))
+
+
+  InputStream
+
+  (decode
+    [source]
+    (throw (UnsupportedOperationException. "NYI")))
+
+
+  PushbackInputStream
+
+  (decode
+    [source]
+    (throw (UnsupportedOperationException. "NYI"))))


Removing beanstalk.

Removing beanstalk.


Add :locals metadata to example functions

--- src/main/clojure/com/stuartsierra/lazytest/examples.clj
+++ src/main/clojure/com/stuartsierra/lazytest/examples.clj
@@ -38,22 +38,39 @@
   (vec (filter #(::local (meta %)) (keys env))))

 (defmacro example
+  "Creates an example function, using current context locals for
+  arguments, with expr as its body."
   ([expr] `(example nil ~expr))
   ([docstring expr]
-     `(vary-meta (fn ~(find-locals &env) ~expr)
-                 merge ~(standard-metadata &form docstring))))
+     (let [locals (find-locals &env)]
+       `(vary-meta (fn ~locals ~expr)
+                   merge ~(standard-metadata &form docstring)
+                   {:locals '~locals}))))

-(defmacro group-examples [& examples]
-  (loop [result [], exs examples]
-    (if (seq exs)
-      (if (string? (first exs))
-        (recur (conj result `(example ~(first exs) ~(second exs)))
-               (nnext exs))
-        (recur (conj result `(example ~(first exs)))
-               (next exs)))
+(defmacro group-examples
+  "Creates a vector of example functions from body.  A string in body
+  will be attached as a doc string on the following example."
+  [& body]
+  (loop [result [], forms body]
+    (if (seq forms)
+      (if (string? (first forms))
+        (recur (conj result `(example ~(first forms) ~(second forms)))
+               (nnext forms))
+        (recur (conj result `(example ~(first forms)))
+               (next forms)))
       result)))

-(defmacro group [bindings examples subgroups]
+(defmacro group
+  "Creates an example group.
+
+  bindings is a vector of symbol-context pairs, symbols will become
+  locals in the examples.
+
+  examples is a vector of expressions to be compiled into example
+  functions.
+
+  subgroups is a vector of child example groups."
+  [bindings examples subgroups]
   {:pre [(or-nil vector? bindings)
          (even? (count bindings))]}
   (if (seq bindings)
@@ -76,7 +93,8 @@
     (assert (= *ns* (:ns m)))
     (assert (string? (:file m)))
     (assert (integer? (:line m)))
-    (assert (nil? (:name m)))))
+    (assert (nil? (:name m)))
+    (assert (= [] (:locals m)))))

 (let [c1 (com.stuartsierra.lazytest.contexts/context [] 1)
       e (with-context x c1
@@ -88,4 +106,5 @@
     (assert (= *ns* (:ns m)))
     (assert (string? (:file m)))
     (assert (integer? (:line m)))
-    (assert (nil? (:name m)))))+    (assert (nil? (:name m)))
+    (assert (= '[x] (:locals m)))))


Share footer.

Share footer.

--- src/tryclojure/views/home.clj
+++ src/tryclojure/views/home.clj
@@ -34,8 +34,14 @@

        [:div#console.console]]
       (javascript-tag
-       (str "mode = '" mode "';"))]]]))
+       (str "mode = '" mode "';"))]]]
+   (footer)))

+(defn footer []
+  [:div.footer "home
+                try isla
+                github
+                mary rose cook"])

 (defpage "/repl" []
   (repl-html "isla" "Try Isla"))
@@ -92,6 +98,9 @@
           "]
          ]]
        [:div.footer "by mary rose cook"]
+         ]]]
+       (footer)
+
        (javascript-tag
         (str "
   var _gaq = _gaq || [];
@@ -102,4 +111,4 @@
     var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
     ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
     var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
-  })();"))]]]]))
+  })();"))]]]))


korma++

korma++

--- src/simplex_clj/models/db.clj
+++ src/simplex_clj/models/db.clj
@@ -4,11 +4,24 @@

 (def itemtypes '("image" "link" "text" "video"))

-(defdb dbm (mysql
+(defn convert-db-uri [db-uri]
+  (let [[_ user password host port db x y] (re-matches #"mysql://(?:(.+):(.*)@)?([^:]+)(?::(\d+))?/(.+)(?:\?(.+)=(.+))" db-uri)]
+    {
+      :user user
+      :password password
+      :host host
+      :port (or port 80)
+      :db db
+      (keyword x) y
+    }))
+
+(defdb dbm2 (mysql
   {:db "simplex"
    :user "simplex"
    :password "simplex"
    :delimiters "`"}))
+
+(defdb dbm (mysql (convert-db-uri (System/getenv "CLEARDB_DATABASE_URL"))))

 (defentity users)
 (defentity clj)


empty time is now

empty time is now

--- src/ontrail/parser.clj
+++ src/ontrail/parser.clj
@@ -55,7 +55,9 @@
   (some identity (map #(try-parse % dur-str) duration-regexps)))

 (defn parse-date [date-str]
-  (time/plus (format/parse multi-parser date-str) (time/hours 12)))
+  (if (= "" date-str)
+    (time/now)
+    (time/plus (format/parse multi-parser date-str) (time/hours 12))))

 (defn as-double-km [str]
   (let [x (string/replace str #"," ".")]


get segment from the middle

get segment from the middle

--- stuf/src/sandbox/4clojure.clj
+++ stuf/src/sandbox/4clojure.clj
@@ -936,6 +936,8 @@
         frm (str "~" l ",'0B")]
     (map #(clojure.pprint/cl-format nil frm %) b)))

-(defn f [b line cnt]
-  (for (i (range (/ (- (count line) cnt) 2) (count line))) [i line]))
+(defn f [b line lenth]
+  (let [n (count (first b))
+        start (/ (- n lenth) 2) ]
+    (for [i (range start (+ start lenth))] (get-in b [line i]))))