(ns incise.core
  (:require (incise [load :refer [load-parsers-and-layouts]]
                    [config :as conf]
                    [once :refer [once]]
                    [utils :refer [delete-recursively]])
            [incise.deploy.core :refer [deploy]]
            [taoensso.timbre :refer [warn]]
            [clojure.string :as s]
            [clojure.tools.cli :refer [cli]]
            [incise.server :refer [wrap-log-exceptions serve]]))

(def ^:private valid-methods #{"serve" "once" "deploy"})
(defn- parse-method [method]
  (if (contains? valid-methods method)
    (keyword method)
    (do
      (when (seq method)
        (warn (str \" method
                   "\" is not a valid method (must be in "
                   (s/join ", " valid-methods) "). Defaulting to serve.")))
      :serve)))

(defn- with-args*
  "A helper function to with-args macro which does all the work.

  1.  Load in the config
  2.  Parse arguments
  3.  Merge into config
  4.  Handle help or continue"
  [args body-fn]
  (conf/load)
  (let [uri-root-desc (str "The path relative to the domain root where the "
                           "generated site will be hosted.")
        [options cli-args banner]
        (cli args
             "A tool for incising."
             ["-h" "--help" "Print this help." :default false :flag true]
             ["-m" "--method" "serve, once, or deploy"
              :default :serve :parse-fn parse-method]
             ["-i" "--in-dir" "The directory to get source from"]
             ["-o" "--out-dir" "The directory to put content into"]
             ["-u" "--uri-root" uri-root-desc])]
    (conf/merge options)
    (if (:help options)
      (do (println banner)
          (System/exit 0))
      (body-fn options cli-args))))

(defmacro with-args
  "Take arguments parsing them using cli and handle help accordingly."
  [args & body]
  `(with-args* ~args (fn [~'options ~'cli-args] ~@body)))

(defn wrap-pre [func pre-func & more]
  (fn [& args]
    (apply pre-func more)
    (apply func args)))

(defn wrap-post [func post-func & more]
  (fn [& args]
    (let [return-value (apply func args)]
      (apply post-func more)
      return-value)))

(defn wrap-serve
  [main-func]
  (-> main-func
      (wrap-pre conf/avow!)
      (wrap-log-exceptions :bubble false)))

(defn wrap-main
  [main-func]
  (-> main-func
      (wrap-serve)
      (wrap-post #(System/exit 0))))

(defn -main
  "Based on the given args either deploy, compile or start the development
  server."
  [& args]
  (with-args args
    ((case (:method options)
       :deploy (wrap-main deploy)
       :once (wrap-main once)
       :serve (wrap-serve serve)))))

(ns incise.core
  (:require (incise [load :refer [load-parsers-and-layouts]]
                    [config :as conf]
                    [once :refer [once]]
                    [utils :refer [delete-recursively]])
            [incise.deploy.core :refer [deploy]]
            [taoensso.timbre :refer [warn]]
            [clojure.string :as s]
            [clojure.tools.cli :refer [cli]]
            [incise.server :refer [wrap-log-exceptions serve]]))

(def ^:private valid-methods #{"serve" "once" "deploy"})
(defn- parse-method [method]
  (if (contains? valid-methods method)
    (keyword method)
    (do
      (when (seq method)
        (warn (str \" method
                   "\" is not a valid method (must be in "
                   (s/join ", " valid-methods) "). Defaulting to serve.")))
      :serve)))

(defn- with-args*
  "A helper function to with-args macro which does all the work.

  1.  Parse arguments
  2.  Load in the config
  3.  Merge some options into config
  4.  Handle help or call body-fn with options and cli arguments"
  [args body-fn]
  (let [uri-root-desc (str "The path relative to the domain root where the "
                           "generated site will be hosted.")
        [options cli-args banner]
        (cli args
             "A tool for incising."
             ["-h" "--help" "Print this help." :default false :flag true]
             ["-m" "--method" "serve, once, or deploy"
              :default :serve :parse-fn parse-method]
             ["-c" "--config" (str "The path to an edn file acting as "
                                   "configuration for incise")]
             ["-i" "--in-dir" "The directory to get source from"]
             ["-o" "--out-dir" "The directory to put content into"]
             ["-u" "--uri-root" uri-root-desc])]
    (conf/load (options :config))
    (conf/merge (dissoc options :config :help))
    (if (:help options)
      (do (println banner)
          (System/exit 0))
      (body-fn options cli-args))))

(defmacro with-args
  "Take arguments parsing them using cli and handle help accordingly."
  [args & body]
  `(with-args* ~args (fn [~'options ~'cli-args] ~@body)))

(defn wrap-pre [func pre-func & more]
  (fn [& args]
    (apply pre-func more)
    (apply func args)))

(defn wrap-post [func post-func & more]
  (fn [& args]
    (let [return-value (apply func args)]
      (apply post-func more)
      return-value)))

(defn wrap-serve
  [main-func]
  (-> main-func
      (wrap-pre conf/avow!)
      (wrap-log-exceptions :bubble false)))

(defn wrap-main
  [main-func]
  (-> main-func
      (wrap-serve)
      (wrap-post #(System/exit 0))))

(defn -main
  "Based on the given args either deploy, compile or start the development
  server."
  [& args]
  (with-args args
    ((case (:method options)
       :deploy (wrap-main deploy)
       :once (wrap-main once)
       :serve (wrap-serve serve)))))

Add config option to cli.

Add config option to cli.


(ns reagent.ratom
  (:refer-clojure :exclude [run!])
  (:require [reagent.debug :as d]))

(defmacro reaction [& body]
  `(reagent.ratom/make-reaction
    (fn [] ~@body)))

(defmacro run!
  "Runs body immediately, and runs again whenever atoms deferenced in the body change. Body should side effect."
  [& body]
  `(let [co# (reagent.ratom/make-reaction (fn [] ~@body)
                                         :auto-run true)]
     (deref co#)
     co#))

(defmacro with-let [bindings & body]
  (assert (vector? bindings)
          (str "with-let bindings must be a vector, not "
               (pr-str bindings)))
  (let [v (gensym "with-let")
        k (keyword v)
        init (gensym "init")
        bs (into [init `(zero? (alength ~v))]
                 (map-indexed (fn [i x]
                                (if (even? i)
                                  x
                                  (let [j (quot i 2)]
                                    `(if ~init
                                       (aset ~v ~j ~x)
                                       (aget ~v ~j)))))
                              bindings))
        [forms destroy] (let [fin (last body)]
                          (if (and (list? fin)
                                   (= 'finally (first fin)))
                            [(butlast body) `(fn [] ~@(rest fin))]
                            [body nil]))
        add-destroy (when destroy
                      `(let [destroy# ~destroy]
                         (if (reagent.ratom/reactive?)
                           (when (nil? (.-destroy ~v))
                             (set! (.-destroy ~v) destroy#))
                           (destroy#))))
        asserting (if *assert* true false)]
    `(let [~v (reagent.ratom/with-let-values ~k)]
       (when ~asserting
         (when-some [c# reagent.ratom/*ratom-context*]
           (when (== (.-generation ~v) (.-ratomGeneration c#))
             (d/error "Warning: The same with-let is being used more "
                      "than once in the same reactive context."))
           (set! (.-generation ~v) (.-ratomGeneration c#))))
       (let ~bs
         (let [res# (do ~@forms)]
           ~add-destroy
           res#)))))

(ns reagent.ratom
  (:refer-clojure :exclude [run!])
  (:require [reagent.debug :as d]))

(defmacro reaction [& body]
  `(reagent.ratom/make-reaction
    (fn [] ~@body)))

(defmacro run!
  "Runs body immediately, and runs again whenever atoms deferenced in the body change. Body should side effect."
  [& body]
  `(let [co# (reagent.ratom/make-reaction (fn [] ~@body)
                                         :auto-run true)]
     (deref co#)
     co#))

; taken from cljs.core
; https://github.com/binaryage/cljs-oops/issues/14
(defmacro unchecked-aget
  ([array idx]
   (list 'js* "(~{}[~{}])" array idx))
  ([array idx & idxs]
   (let [astr (apply str (repeat (count idxs) "[~{}]"))]
     `(~'js* ~(str "(~{}[~{}]" astr ")") ~array ~idx ~@idxs))))

; taken from cljs.core
; https://github.com/binaryage/cljs-oops/issues/14
(defmacro unchecked-aset
  ([array idx val]
   (list 'js* "(~{}[~{}] = ~{})" array idx val))
  ([array idx idx2 & idxv]
   (let [n (dec (count idxv))
         astr (apply str (repeat n "[~{}]"))]
     `(~'js* ~(str "(~{}[~{}][~{}]" astr " = ~{})") ~array ~idx ~idx2 ~@idxv))))

(defmacro with-let [bindings & body]
  (assert (vector? bindings)
          (str "with-let bindings must be a vector, not "
               (pr-str bindings)))
  (let [v (gensym "with-let")
        k (keyword v)
        init (gensym "init")
        bs (into [init `(zero? (alength ~v))]
                 (map-indexed (fn [i x]
                                (if (even? i)
                                  x
                                  (let [j (quot i 2)]
                                    `(if ~init
                                       (unchecked-aset ~v ~j ~x)
                                       (unchecked-aget ~v ~j)))))
                              bindings))
        [forms destroy] (let [fin (last body)]
                          (if (and (list? fin)
                                   (= 'finally (first fin)))
                            [(butlast body) `(fn [] ~@(rest fin))]
                            [body nil]))
        add-destroy (when destroy
                      `(let [destroy# ~destroy]
                         (if (reagent.ratom/reactive?)
                           (when (nil? (.-destroy ~v))
                             (set! (.-destroy ~v) destroy#))
                           (destroy#))))
        asserting (if *assert* true false)]
    `(let [~v (reagent.ratom/with-let-values ~k)]
       (when ~asserting
         (when-some [c# reagent.ratom/*ratom-context*]
           (when (== (.-generation ~v) (.-ratomGeneration c#))
             (d/error "Warning: The same with-let is being used more "
                      "than once in the same reactive context."))
           (set! (.-generation ~v) (.-ratomGeneration c#))))
       (let ~bs
         (let [res# (do ~@forms)]
           ~add-destroy
           res#)))))

Use unchecked-aget/aset in with-let macro


(ns riemann.kafka
  "Receives events from and forwards events to Kafka."
  (:require [kinsky.client :as client]
            [cheshire.core :as json]
            [riemann.test :as test])
  (:use [riemann.common        :only [event]]
        [riemann.core          :only [stream!]]
        [riemann.service       :only [Service ServiceEquiv]]
        [clojure.tools.logging :only [info error]]))

(defn kafka
  "Returns a function that is invoked with a topic name and an optional message key and returns a stream. That stream is a function which takes an event or a sequence of events and sends them to Kafka.

  (def kafka-output (kafka))

  (changed :state
    (kafka-output \"mytopic\"))

  Options:

  For a complete list of producer configuration options see https://kafka.apache.org/documentation/#producerconfigs

  :bootstrap.servers  Bootstrap configuration, default is \"localhost:9092\".
  :value.serializer   Value serializer, default is json-serializer.

  Example with SSL enabled:

  (def kafka-output (kafka {:bootstrap.servers \"kafka.example.com:9092\"
                            :security.protocol \"SSL\"
                            :ssl.truststore.location \"/path/to/my/truststore.jks\"
                            :ssl.truststore.password \"mypassword\"}))"

  ([] (kafka {}))
  ([opts]
   (let [opts (merge {:bootstrap.servers "localhost:9092"
                      :value.serializer client/json-serializer}
                     opts)
         producer (client/producer (dissoc opts :value.serializer)
                                   (:value.serializer opts))]
     (fn make-stream [& args]
       (fn stream [event]
         (let [[topic message-key] args]
           (client/send!
             producer topic message-key event)))))))

(defn json-deserializer
  "Deserialize JSON. Let bad payload not break the consumption."
  []
  (client/deserializer
    (fn [_ payload]
      (when payload
        (try
          (json/parse-string (String. payload "UTF-8") true)
        (catch Exception e
          (error e "Could not decode message")))))))

(defn start-kafka-thread
  "Start a kafka thread which will pop messages off the queue as long
  as running? is true"
  [running? core opts]
  (let [opts (merge {:consumer.config {:bootstrap.servers "localhost:9092"
                                       :group.id "riemann"}
                     :topics ["riemann"]
                     :key.deserializer client/keyword-deserializer
                     :value.deserializer json-deserializer
                     :poll.timeout.ms 100}
                    opts)
        consumer (client/consumer (dissoc (:consumer.config opts) :enable.auto.commit)
                                  (:key.deserializer opts)
                                  (:value.deserializer opts))
        topics (flatten (:topics opts))]
    (future
      (try
        (info "Subscribing to " topics "...")
        (client/subscribe! consumer topics)
        (while running?
          (let [msgs (client/poll! consumer (:poll.timeout.ms opts))
                msgs-by-topic (get msgs :by-topic)]
            (doseq [records msgs-by-topic
                    record (last records)]
              (let [event (event (get record :value))]
                (stream! @core event)))))
        (catch Exception e
          (error e "Interrupted consumption"))
        (finally
          (client/close! consumer))))))

(defn kafka-consumer
  "Yield a kafka consumption service"
  [opts]
  (let [running? (atom true)
        core     (atom nil)]
    (reify
      clojure.lang.ILookup
      (valAt [this k not-found]
        (or (.valAt this k) not-found))
      (valAt [this k]
        (info "Looking up: " k)
        (when (= (name k) "opts") opts))
      ServiceEquiv
      (equiv? [this other]
        (= opts (:opts other)))
      Service
      (conflict? [this other]
        (= opts (:opts other)))
      (start! [this]
        (when-not test/*testing*
          (do (info "Starting kafka consumer")
              (start-kafka-thread running? core opts))))
      (reload! [this new-core]
        (info "Reload called, setting new core value")
        (reset! core new-core))
      (stop! [this]
        (reset! running? false)
        (info "Stopping kafka consumer")))))

(ns riemann.kafka
  "Receives events from and forwards events to Kafka."
  (:require [kinsky.client :as client]
            [cheshire.core :as json]
            [riemann.test :as test])
  (:use [riemann.common        :only [event]]
        [riemann.core          :only [stream!]]
        [riemann.service       :only [Service ServiceEquiv]]
        [clojure.tools.logging :only [info error]]))

(defn kafka
  "Returns a function that is invoked with a topic name and an optional message key and returns a stream. That stream is a function which takes an event or a sequence of events and sends them to Kafka.

  (def kafka-output (kafka))

  (changed :state
    (kafka-output \"mytopic\"))

  Options:

  For a complete list of producer configuration options see https://kafka.apache.org/documentation/#producerconfigs

  :bootstrap.servers  Bootstrap configuration, default is \"localhost:9092\".
  :value.serializer   Value serializer, default is json-serializer.

  Example with SSL enabled:

  (def kafka-output (kafka {:bootstrap.servers \"kafka.example.com:9092\"
                            :security.protocol \"SSL\"
                            :ssl.truststore.location \"/path/to/my/truststore.jks\"
                            :ssl.truststore.password \"mypassword\"}))"

  ([] (kafka {}))
  ([opts]
   (let [opts (merge {:bootstrap.servers "localhost:9092"
                      :value.serializer client/json-serializer}
                     opts)
         producer (client/producer (dissoc opts :value.serializer)
                                   (:value.serializer opts))]
     (fn make-stream [& args]
       (fn stream [event]
         (let [[topic message-key] args]
           (client/send!
             producer topic message-key event)))))))

(defn json-deserializer
  "Deserialize JSON. Let bad payload not break the consumption."
  []
  (client/deserializer
    (fn [_ payload]
      (when payload
        (try
          (json/parse-string (String. payload "UTF-8") true)
        (catch Exception e
          (error e "Could not decode message")))))))

(defn start-kafka-thread
  "Start a kafka thread which will pop messages off the queue as long
  as running? is true"
  [running? core opts]
  (let [opts (merge {:consumer.config {:bootstrap.servers "localhost:9092"
                                       :group.id "riemann"}
                     :topics ["riemann"]
                     :key.deserializer client/keyword-deserializer
                     :value.deserializer json-deserializer
                     :poll.timeout.ms 100}
                    opts)
        consumer (client/consumer (dissoc (:consumer.config opts) :enable.auto.commit)
                                  (:key.deserializer opts)
                                  (:value.deserializer opts))
        topics (flatten (:topics opts))]
    (future
      (try
        (info "Subscribing to " topics "...")
        (client/subscribe! consumer topics)
        (while @running?
          (let [msgs (client/poll! consumer (:poll.timeout.ms opts))
                msgs-by-topic (get msgs :by-topic)]
            (doseq [records msgs-by-topic
                    record (last records)]
              (let [event (event (get record :value))]
                (stream! @core event)))))
        (catch Exception e
          (error e "Interrupted consumption"))
        (finally
          (client/close! consumer))))))

(defn kafka-consumer
  "Yield a kafka consumption service"
  [opts]
  (let [running? (atom true)
        core     (atom nil)]
    (reify
      clojure.lang.ILookup
      (valAt [this k not-found]
        (or (.valAt this k) not-found))
      (valAt [this k]
        (info "Looking up: " k)
        (when (= (name k) "opts") opts))
      ServiceEquiv
      (equiv? [this other]
        (= opts (:opts other)))
      Service
      (conflict? [this other]
        (= opts (:opts other)))
      (start! [this]
        (when-not test/*testing*
          (do (info "Starting kafka consumer")
              (start-kafka-thread running? core opts))))
      (reload! [this new-core]
        (info "Reload called, setting new core value")
        (reset! core new-core))
      (stop! [this]
        (reset! running? false)
        (info "Stopping kafka consumer")))))

Add missing atom deref to properly close kafka client


(ns korhal.core
  (:import (jnibwapi.JNIBWAPI)
           (jnibwapi.BWAPIEventListener)
           (jnibwapi.model.Unit)
           (jnibwapi.types.UnitType$UnitTypes)))

(gen-class
 :name "korhal.core"
 :implements [jnibwapi.BWAPIEventListener]
 :state state
 :init init
 :main true
 :constructors {[] []}
 :prefix "korhal-")

(defn swap-key [curr-val k v]
  (merge curr-val {k v}))

(defmacro swap-keys [swap-atom & forms]
  (for [pair (partition 2 forms)]
    `(swap! ~swap-atom swap-key ~@pair)))

(defn korhal-main [& args]
  (let [ai (korhal.core.)
        api (jnibwapi.JNIBWAPI. ai)]
    (swap! (.state ai) swap-key :api api)
    (.start (:api @(.state ai)))))

(defn korhal-init []
  [[] (atom {})])

(defn korhal-deref [this]
  @(.state this))

(defn korhal-connected [this]
  (.loadTypeData (:api @this)))

(defn korhal-gameStarted [this]
  (println "Here we go!")
  (doto (:api @this)
    (.enableUserInput)
    (.enablePerfectInformation)
    (.setGameSpeed 0)
    (.loadMapData true))
  (swap-keys (.state this)
    :claimed []
    :morphed-drone false
    :pool-drone -1
    :supply-cap 0))

(defn korhal-gameUpdate [this]

  ;; spawn a drone
  (for [unit (.getMyUnits (:api @this))]
    (when (= (.getTypeID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Zerg_Larva))
      (when (and (< 50 (.. (:api @this) getSelf getMinerals)) (not (:morphed-drone this)))
        (.morph (:api @this) (.getID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Zerg_Drone))
        (swap-keys (.state this) :morphed-drone true))))

  ;; collect minerals
  (for [unit (.getMyUnits (:api @this))]
    (when (= (.getTypeID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Zerg_Drone))
      (when (and (.isIdle unit) (not (= (.getID unit) (:pool-drone @this))))
        (let [mineral? (fn [unit] (= (.getTypeID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Mineral_Field)))
              mineral (first (filter mineral? (.getNeutralUnits (:api @this))))]
        (.rightClick (.getID unit) (.getID mineral)))))))

(defn korhal-gameEnded [this])
(defn korhal-keyPressed [this keycode])
(defn korhal-matchEnded [this winner])
(defn korhal-sendText [this text])
(defn korhal-receiveText [this text])
(defn korhal-nukeDetect [this x y])
(defn korhal-playerLeft [this playerID])
(defn korhal-unitCreate [this unitID])
(defn korhal-unitDestroy [this unitID])
(defn korhal-unitDiscover [this unitID])
(defn korhal-unitEvade [this unitID])
(defn korhal-unitHide [this unitID])
(defn korhal-unitMorph [this unitID])
(defn korhal-unitShow [this unitID])
(defn korhal-unitRenegade [this unitID])
(defn korhal-saveGame [this gameName])
(defn korhal-unitComplete [this unitID])
(defn korhal-playerDropped [this playerID])

(ns korhal.core
  (:import (jnibwapi.JNIBWAPI)
           (jnibwapi.BWAPIEventListener)
           (jnibwapi.model.Unit)
           (jnibwapi.types.UnitType$UnitTypes)))

(gen-class
 :name "korhal.core"
 :implements [jnibwapi.BWAPIEventListener]
 :state state
 :init init
 :main true
 :constructors {[] []}
 :prefix "korhal-")

(defn swap-key [curr-val k v]
  (merge curr-val {k v}))

(defmacro swap-keys [swap-atom & forms]
  (for [pair (partition 2 forms)]
    `(swap! ~swap-atom swap-key ~@pair)))

(defn korhal-main [& args]
  (let [ai (korhal.core.)
        api (jnibwapi.JNIBWAPI. ai)]
    (swap! (.state ai) swap-key :api api)
    (.start (:api @(.state ai)))))

(defn korhal-init []
  [[] (atom {})])

(defn korhal-deref [this]
  @(.state this))

(defn korhal-connected [this]
  (.loadTypeData (:api @this)))

(defn korhal-gameStarted [this]
  (println "Here we go!")
  (doto (:api @this)
    (.enableUserInput)
    (.enablePerfectInformation)
    (.setGameSpeed 0)
    (.loadMapData true))
  (swap-keys (.state this)
    :claimed []
    :morphed-drone false
    :pool-drone -1
    :supply-cap 0))

(defn korhal-gameUpdate [this]

  ;; spawn a drone
  (for [unit (.getMyUnits (:api @this))]
    (when (= (.getTypeID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Zerg_Larva))
      (when (and (>= (.. (:api @this) getSelf getMinerals) 50) (not (:morphed-drone this)))
        (.morph (:api @this) (.getID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Zerg_Drone))
        (swap-keys (.state this) :morphed-drone true))))

  ;; collect minerals
  (for [unit (.getMyUnits (:api @this))]
    (when (= (.getTypeID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Zerg_Drone))
      (when (and (.isIdle unit) (not (= (.getID unit) (:pool-drone @this))))
        (let [mineral? (fn [unit] (= (.getTypeID unit) (.getID jnibwapi.types.UnitType$UnitTypes/Mineral_Field)))
              mineral (first (filter mineral? (.getNeutralUnits (:api @this))))]
        (.rightClick (.getID unit) (.getID mineral)))))))

(defn korhal-gameEnded [this])
(defn korhal-keyPressed [this keycode])
(defn korhal-matchEnded [this winner])
(defn korhal-sendText [this text])
(defn korhal-receiveText [this text])
(defn korhal-nukeDetect [this x y])
(defn korhal-playerLeft [this playerID])
(defn korhal-unitCreate [this unitID])
(defn korhal-unitDestroy [this unitID])
(defn korhal-unitDiscover [this unitID])
(defn korhal-unitEvade [this unitID])
(defn korhal-unitHide [this unitID])
(defn korhal-unitMorph [this unitID])
(defn korhal-unitShow [this unitID])
(defn korhal-unitRenegade [this unitID])
(defn korhal-saveGame [this gameName])
(defn korhal-unitComplete [this unitID])
(defn korhal-playerDropped [this playerID])

Make drones

Make drones


(ns rrm.citizen
  (:require [goog.events :as events]
            [secretary.core :as secretary]
            [goog.net.XhrIo :as xhr]
            [reagent.core :as r]
            [cognitect.transit :as t]
            [goog.structs :as structs]
            [cljs-time.format :as f]
            [cljs-time.core :as tt]
            [cljs-time.coerce :as c]
            [cljs-time.predicates :as p]
            [cljsjs.react-bootstrap]
            [clojure.string :as st]
            [goog.dom :as dom]
            [goog.history.EventType :as EventType]
            [bouncer.core :as b]
            [bouncer.validators :as v])
  (:import goog.History
           goog.json.Serializer
           goog.date.Date
           goog.array))

(def serverhost "http://localhost:9000/")

(defonce citizen-storage (r/atom {:mutations {}
                                  :current-page 1
                                  :total-pages 0
                                  :page-location nil
                                  :districts nil
                                  :subdivisions nil
                                  :villages {}
                                  :o2mutations {}
                                  :o4mutations {}
                                  :o6mutations {}
                                  :token ""
                                  :is-searched-results false
                                  :user nil
                                  :message nil}))

(defn set-key-value [k v]
  (reset! citizen-storage (assoc @citizen-storage k v)))

(defn get-value! [k]
  (k @citizen-storage))

(defn getdata [res]
  (.getResponseJson (.-target res)))

(defn http-get [url callback]
  (xhr/send url callback))

(defn get-total-rec-no [nos]
  (let [totrec (quot nos 10)]
    (if (zero? (mod nos 10))
      totrec
      (+ 1 totrec))))

(declare render-mutations)

(def button-tool-bar (r/adapt-react-class (aget js/ReactBootstrap "ButtonToolbar")))
(def button (r/adapt-react-class (aget js/ReactBootstrap "Button")))
(def pager-elem (r/adapt-react-class (aget js/ReactBootstrap "Pagination")))

(defn get-search-url [vid mutno fp
                      sp nop kkn
                      o2n tit kn
                      o4n o6n]
  (let [purl (str serverhost "mutations/search?")]

    (cond (not (st/blank? mutno)) (str purl "mutationNo="mutno)
          :else (str purl "villageId="(int vid)"&firstparty="fp"&secondparty="sp"&nameofpo="nop"&khatakhatuninumber="kkn"&o2number="o2n"&title="tit"&khasranumber="kn"&o4number="o4n"&o6number="o6n))))

(defn get-index-url [is-searched-results sel-page vid
                     mutno fp sp nop kkn o2n tit kn
                     o4n o6n]
  (cond (= true is-searched-results)(str (get-search-url vid mutno fp sp nop kkn o2n tit kn o4n o6n)"&pageIndex="sel-page"&pageSize=10")
        :else (str serverhost "mutations?pageIndex="sel-page "&pageSize=10")))

(defn set-pager-data [sel-page-no]
  (let [mn   (.-value (.getElementById js/document "mutationnumber"))
        st   (.-value (.getElementById js/document "stitle"))
        vid  (.-value (.getElementById js/document "src-vill"))
        po   (.-value (.getElementById js/document "svillagename"))
        so2  (.-value (.getElementById js/document "so2number"))
        so4  (.-value (.getElementById js/document "so4number"))
        so6  (.-value (.getElementById js/document "so6number"))
        knum (.-value (.getElementById js/document "skhasranumber"))
        kknum (.-value (.getElementById js/document "skhatakhatuninumber"))
        fp (.-value (.getElementById js/document "snameofthefirstparty"))
        sp (.-value (.getElementById js/document "snameofthesecondparty"))
        onres (fn[json]
                (let [dt (getdata json)]
                  (set-key-value :mutations (.-data dt))
                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
                  (r/render [render-mutations (get-value! :mutations)]
                            (.getElementById js/document "app1"))))]
    (http-get (get-index-url (get-value! :is-searched-results)
                             (dec (get-value! :current-page))
                             vid mn fp sp po
                             kknum so2 st knum
                             so4 so6)
              onres)))

(defn pager [value total-rec]
  [pager-elem {:bsSize "large"
               :prev true
               :next true
               :first true
               :last true
               :ellipsis true
               :items (:total-pages @citizen-storage)
               :activePage (:current-page @citizen-storage)
               :maxButtons 5
               :onSelect (fn [s1 s2]
                           (do
                             (set-key-value :current-page (.-eventKey s2))
                             (set-pager-data (get-value! :current-page))))}])

(defn shared-state [totalRec]
  (let [val (r/atom 1)
        trec (r/atom totalRec)]
    [:div.row
     [pager val trec]]))

(defn datalist1 []
  [:datalist {:id "combo1"}
   (let [name-po ["Kumar" "Sai" "Bhaskar" "Rajesh"]]
     (for [i name-po]
       ^{:key i}
       [:option {:value i}]))])

(defn src-dist-onchange [val]
  (let [res (fn [json]
              (let [dt (getdata json)]
                (set-key-value :subdivisions dt)
                (set-key-value :villages nil)))]
    (http-get (str  serverhost "districts/" val  "/subdivisions") res)))

(defn src-dist-sel-tag []
  [:select.form-control {:id :src-dist
                         :placeholder "District Name"
                         :on-change #(src-dist-onchange (-> % .-target .-value)) }
   [:option {:value 0} "--Select--"]
   (for [d  (@citizen-storage :districts)]
     ^{:key (.-id d)}
     [:option {:value (.-id d)} (.-name d)])])

(defn src-sub-onchange [ val]
  (let [res (fn [json]
              (let [dt (getdata json)]
                (set-key-value :villages dt)))]
    (http-get (str serverhost "subdivisions/" val  "/villages") res)))

(defn src-sub-sel-tag []
  [:select.form-control {:id :src-sub
                         :placeholder "Sub Division Name"
                         :on-change  #(src-sub-onchange (-> % .-target .-value)) }
   [:option {:value 0} "--Select--"]
   (for [d  (@citizen-storage :subdivisions)]
     ^{:key (.-id d)}
     [:option {:value (.-id d)} (.-subdivisionname d)])])

(defn src-vill-sel-tag []
  [:select.form-control {:id :src-vill
                         :placeholder "Village Name"
                         }
   [:option {:value 0} "--Select--"]
   (for [d  (@citizen-storage :villages)]
     ^{:key (.-id d)}
     [:option {:value (.-id d)} (.-villagename d)])])

(defn search [event]
  (let [mn   (.-value (.getElementById js/document "mutationnumber"))
        st   (.-value (.getElementById js/document "stitle"))
        vid  (.-value (.getElementById js/document "src-vill"))
        po   (.-value (.getElementById js/document "svillagename"))
        so2  (.-value (.getElementById js/document "so2number"))
        so4  (.-value (.getElementById js/document "so4number"))
        so6  (.-value (.getElementById js/document "so6number"))
        knum (.-value (.getElementById js/document "skhasranumber"))
        kknum (.-value (.getElementById js/document "skhatakhatuninumber"))
        fp (.-value (.getElementById js/document "snameofthefirstparty"))
        sp (.-value (.getElementById js/document "snameofthesecondparty"))
        onres (fn [json] (let [data (getdata json)]
                           (if (empty? (.-data data))
                             (do
                               (set-key-value :message "No Records to Display")
                               (set-key-value :mutations nil)
                               (set-key-value :total-pages (get-total-rec-no (.-pagesCount data)))
                               (r/render [render-mutations (get-value! :mutations)]  (.getElementById js/document "app1")))
                             (do
                               (set-key-value :message nil)
                               (set-key-value :mutations (.-data data))
                               (set-key-value :total-pages (get-total-rec-no (.-pagesCount data)))
                               (r/render [render-mutations (get-value! :mutations)]  (.getElementById js/document "app1"))))))]
    (set-key-value :current-page 1)
    (set-key-value :is-searched-results true)
    (http-get (str (get-search-url
                    vid mn fp sp po
                    kknum so2 st knum so4 so6)"&pageIndex=0&pageSize=10") onres)))

(defn get-data [val]
  (let [res (fn [json]
              (let [dt (getdata json)]
                (swap! citizen-storage assoc :mutationnumbers dt)))]
    (http-get (str  serverhost  "mutations/pluck?column=mutationnumber&value=" val ) res)))

(defn datalist [data]
  [:datalist {:id "combo"}
   (for [i data]
     ^{:key i}
     [:option {:value i}])])

(defn render-mutations [mutations]
  [:div.col-md-12
   [:div {:class "box"}
    [:div {:class "box-header"}
     [:h3.box-title "Search for Mutation Records"]]
    [:div.box-body
     [:div.form-group
      [:div.row
       [:div.col-sm-2 "Mutation Number"
        [:input.form-control {:id "mutationnumber"
                              :list "combo"
                              :type "text"
                              :placeholder  "Enter search by Mutation Number"
                              :on-change #(get-data (-> % .-target .-value))
                              }]
        [datalist (:mutationnumbers @citizen-storage)]]]]

     [:div.form-group
      [:div.row
       [:span {:style {:float "right" :width "50%"}} [:b "OR"]]
       [:hr]]]

     [:div.form-group
      [:div.row
       [:div.col-sm-2
        [:label "District Name"]
        [src-dist-sel-tag]]
       [:div.col-sm-2
        [:label"Sub Division Name"]
        [src-sub-sel-tag]]
       [:div.col-sm-2
        [:label "Village Name"]
        [src-vill-sel-tag]]
       [:div.col-sm-2
        [:label "O2 Number"]
        [:input.form-control {:id "so2number"
                              :type "text"
                              :placeholder "O2 Number"}]]
       [:div.col-sm-2
        [:label "O4 Number"]
        [:input.form-control {:id "so4number"
                              :type "text"
                              :placeholder "O4 Number"}]]
       [:div.col-sm-2
        [:label "O6 Number"]
        [:input.form-control {:id "so6number"
                              :type "text"
                              :placeholder "O6 Number"}]]]]
     [:div.form-group
      [:div.row
       [:div.col-sm-2
        [:label "Name of the First Party"]
        [:input.form-control {:id "snameofthefirstparty"
                              :type "text"
                              :placeholder "Name of the First Party"}]]
       [:div.col-sm-2
        [:label "Name of the Second Party"]
        [:input.form-control {:id "snameofthesecondparty"
                              :type "text"
                              :placeholder "Name of the Second Party"}]]
       [:div.col-sm-2
        [:label "Name of P.O"]
        [:input.form-control {:id "svillagename"
                              :list "combo1"
                              :placeholder "Name of P.O"}[datalist1]]]
       [:div.col-sm-2
        [:label "Title"]
        [:input.form-control {:id "stitle"
                              :type "text"
                              :placeholder "Title"}]]
       [:div.col-sm-2
        [:label "Khasra Number"]
        [:input.form-control {:id "skhasranumber"
                              :type "text"
                              :placeholder "Khasra Number"} ]]
       [:div.col-sm-2
        [:label "Khata khatuni Number"]
        [:input.form-control {:id "skhatakhatuninumber"
                              :type "text"
                              :placeholder "Khata Khatuni Number"}]]]]
     [:div.form-group
      [:div.row
       [:div.col-sm-6
        [button {:bs-style "primary" :on-click search } "Search"]]
       [:div.col-sm-6.col-md-offset-5
        [:h3 {:style  {:color "red"}} (str (:message @citizen-storage))]]]]
     ]]

   [:div.box
    [:div.box-header
     [:h3.box-title "List of Mutations"]]
    [:div {:class "box-body table-responsive"}
     [:table {:class "table table-bordered table-striped"
              :style {:width: "100%"}}
      [:thead
       [:tr
        [:th "Mutation Number"]
        [:th "Name of the First Party"]
        [:th "Name of the Second Party"]
        [:th "Date of Institution"]
        [:th "Name of P.O"]
        [:th "Name of District"]
        [:th "Sub Division Name"]
        [:th "Name of Village"]
        [:th "O2 Number"]
        [:th "O4 Number"]
        [:th "O6 Number"]
        [:th "Khasra Number"]
        [:th "Khata khatuni Number"]
        [:th "Rack Number"]
        [:th "Sent Date"]
        [:th "Received Date "]
        ]]
      [:tbody
       (doall (for [mt mutations]
                ^{:key (.-id mt)} [:tr
                                   (when  (.-senddate mt)
                                     {:style {:background-color  "#fbcfd1"}})
                                   [:td (.-mutationnumber (.-numbers mt))]
                                   [:td (.-nameofthefirstparty mt)]
                                   [:td (.-nameofthesecondparty mt)]
                                   [:td (.-dateofinstitution mt)]
                                   [:td (.-nameofpo mt)]
                                   [:td (.-name (.-district  mt))]
                                   [:td (.-name (.-subdivision mt))]
                                   [:td (.-name (.-village mt))]
                                   [:td (.-o2number (.-numbers  mt))]
                                   [:td (.-o4number (.-numbers mt))]
                                   [:td (.-o6number (.-numbers mt))]
                                   [:td (.-khasranumber (.-numbers mt))]
                                   [:td (.-khatakhatuninumber (.-numbers mt))]
                                   [:td (.-racknumber (.-numbers mt))]
                                   [:td (.-senddate mt)]
                                   [:td (.-receiveddate mt)]
                                   ]))]]]
    [:div{:class "col-xs-6 col-centered col-max"}] [shared-state 0]]])

(defn main []
  (let [onres (fn [json] ((set-key-value :districts (getdata json))
                         (r/render [render-mutations]
                                   (.getElementById js/document "app1"))))]
    (http-get (str serverhost "districts") onres)))

(main)

(ns rrm.citizen
  (:require [goog.events :as events]
            [secretary.core :as secretary]
            [goog.net.XhrIo :as xhr]
            [reagent.core :as r]
            [cognitect.transit :as t]
            [goog.structs :as structs]
            [cljs-time.format :as f]
            [cljs-time.core :as tt]
            [cljs-time.coerce :as c]
            [cljs-time.predicates :as p]
            [cljsjs.react-bootstrap]
            [clojure.string :as st]
            [goog.dom :as dom]
            [goog.history.EventType :as EventType]
            [bouncer.core :as b]
            [bouncer.validators :as v])
  (:import goog.History
           goog.json.Serializer
           goog.date.Date
           goog.array))

(def serverhost "http://localhost:9000/")

(defonce citizen-storage (r/atom {:mutations {}
                                  :current-page 1
                                  :total-pages 0
                                  :page-location nil
                                  :districts nil
                                  :subdivisions nil
                                  :villages {}
                                  :o2mutations {}
                                  :o4mutations {}
                                  :o6mutations {}
                                  :token ""
                                  :is-searched-results false
                                  :user nil
                                  :message nil}))

(defn set-key-value [k v]
  (reset! citizen-storage (assoc @citizen-storage k v)))

(defn get-value! [k]
  (k @citizen-storage))

(defn getdata [res]
  (.getResponseJson (.-target res)))

(defn http-get [url callback]
  (xhr/send url callback))

(defn get-total-rec-no [nos]
  (let [totrec (quot nos 10)]
    (if (zero? (mod nos 10))
      totrec
      (+ 1 totrec))))

(declare render-mutations)

(def button-tool-bar (r/adapt-react-class (aget js/ReactBootstrap "ButtonToolbar")))
(def button (r/adapt-react-class (aget js/ReactBootstrap "Button")))
(def pager-elem (r/adapt-react-class (aget js/ReactBootstrap "Pagination")))

(defn get-search-url [vid mutno fp
                      sp nop kkn
                      o2n tit kn
                      o4n o6n]
  (let [purl (str serverhost "mutations/search?")]

    (cond (not (st/blank? mutno)) (str purl "mutationNo="mutno)
          :else (str purl "villageId="(int vid)"&firstparty="fp"&secondparty="sp"&nameofpo="nop"&khatakhatuninumber="kkn"&o2number="o2n"&title="tit"&khasranumber="kn"&o4number="o4n"&o6number="o6n))))

(defn get-index-url [is-searched-results sel-page vid
                     mutno fp sp nop kkn o2n tit kn
                     o4n o6n]
  (cond (= true is-searched-results)(str (get-search-url vid mutno fp sp nop kkn o2n tit kn o4n o6n)"&pageIndex="sel-page"&pageSize=10")
        :else (str serverhost "mutations?pageIndex="sel-page "&pageSize=10")))

(defn set-pager-data [sel-page-no]
  (let [mn   (.-value (.getElementById js/document "mutationnumber"))
        st   (.-value (.getElementById js/document "stitle"))
        vid  (.-value (.getElementById js/document "src-vill"))
        po   (.-value (.getElementById js/document "svillagename"))
        so2  (.-value (.getElementById js/document "so2number"))
        so4  (.-value (.getElementById js/document "so4number"))
        so6  (.-value (.getElementById js/document "so6number"))
        knum (.-value (.getElementById js/document "skhasranumber"))
        kknum (.-value (.getElementById js/document "skhatakhatuninumber"))
        fp (.-value (.getElementById js/document "snameofthefirstparty"))
        sp (.-value (.getElementById js/document "snameofthesecondparty"))
        onres (fn[json]
                (let [dt (getdata json)]
                  (set-key-value :mutations (.-data dt))
                  (set-key-value :total-pages (get-total-rec-no (.-pagesCount dt)))
                  (r/render [render-mutations (get-value! :mutations)]
                            (.getElementById js/document "app1"))))]
    (http-get (get-index-url (get-value! :is-searched-results)
                             (dec (get-value! :current-page))
                             vid mn fp sp po
                             kknum so2 st knum
                             so4 so6)
              onres)))

(defn pager [value total-rec]
  [pager-elem {:bsSize "large"
               :prev true
               :next true
               :first true
               :last true
               :ellipsis true
               :items (:total-pages @citizen-storage)
               :activePage (:current-page @citizen-storage)
               :maxButtons 5
               :onSelect (fn [s1 s2]
                           (do
                             (set-key-value :current-page (.-eventKey s2))
                             (set-pager-data (get-value! :current-page))))}])

(defn shared-state [totalRec]
  (let [val (r/atom 1)
        trec (r/atom totalRec)]
    [:div.row
     [pager val trec]]))

(defn datalist1 []
  [:datalist {:id "combo1"}
   (let [name-po ["Kumar" "Sai" "Bhaskar" "Rajesh"]]
     (for [i name-po]
       ^{:key i}
       [:option {:value i}]))])

(defn src-dist-onchange [val]
  (let [res (fn [json]
              (let [dt (getdata json)]
                (set-key-value :subdivisions dt)
                (set-key-value :villages nil)))]
    (http-get (str  serverhost "districts/" val  "/subdivisions") res)))

(defn src-dist-sel-tag []
  [:select.form-control {:id :src-dist
                         :placeholder "District Name"
                         :on-change #(src-dist-onchange (-> % .-target .-value)) }
   [:option {:value 0} "--Select--"]
   (for [d  (@citizen-storage :districts)]
     ^{:key (.-id d)}
     [:option {:value (.-id d)} (.-name d)])])

(defn src-sub-onchange [ val]
  (let [res (fn [json]
              (let [dt (getdata json)]
                (set-key-value :villages dt)))]
    (http-get (str serverhost "subdivisions/" val  "/villages") res)))

(defn src-sub-sel-tag []
  [:select.form-control {:id :src-sub
                         :placeholder "Sub Division Name"
                         :on-change  #(src-sub-onchange (-> % .-target .-value)) }
   [:option {:value 0} "--Select--"]
   (for [d  (@citizen-storage :subdivisions)]
     ^{:key (.-id d)}
     [:option {:value (.-id d)} (.-subdivisionname d)])])

(defn src-vill-sel-tag []
  [:select.form-control {:id :src-vill
                         :placeholder "Village Name"
                         }
   [:option {:value 0} "--Select--"]
   (for [d  (@citizen-storage :villages)]
     ^{:key (.-id d)}
     [:option {:value (.-id d)} (.-villagename d)])])

(defn search [event]
  (let [mn   (.-value (.getElementById js/document "mutationnumber"))
        st   (.-value (.getElementById js/document "stitle"))
        vid  (.-value (.getElementById js/document "src-vill"))
        po   (.-value (.getElementById js/document "svillagename"))
        so2  (.-value (.getElementById js/document "so2number"))
        so4  (.-value (.getElementById js/document "so4number"))
        so6  (.-value (.getElementById js/document "so6number"))
        knum (.-value (.getElementById js/document "skhasranumber"))
        kknum (.-value (.getElementById js/document "skhatakhatuninumber"))
        fp (.-value (.getElementById js/document "snameofthefirstparty"))
        sp (.-value (.getElementById js/document "snameofthesecondparty"))
        onres (fn [json] (let [data (getdata json)]
                           (if (empty? (.-data data))
                             (do
                               (set-key-value :message "No Records to Display")
                               (set-key-value :mutations nil)
                               (set-key-value :total-pages (get-total-rec-no (.-pagesCount data)))
                               (r/render [render-mutations (get-value! :mutations)]  (.getElementById js/document "app1")))
                             (do
                               (set-key-value :message nil)
                               (set-key-value :mutations (.-data data))
                               (set-key-value :total-pages (get-total-rec-no (.-pagesCount data)))
                               (r/render [render-mutations (get-value! :mutations)]  (.getElementById js/document "app1"))))))]
    (set-key-value :current-page 1)
    (set-key-value :is-searched-results true)
    (http-get (str (get-search-url
                    vid mn fp sp po
                    kknum so2 st knum so4 so6)"&pageIndex=0&pageSize=10") onres)))

(defn get-data [val]
  (let [res (fn [json]
              (let [dt (getdata json)]
                (swap! citizen-storage assoc :mutationnumbers dt)))]
    (http-get (str  serverhost  "mutations/pluck?column=mutationnumber&value=" val ) res)))

(defn datalist [data]
  [:datalist {:id "combo"}
   (for [i data]
     ^{:key i}
     [:option {:value i}])])

(defn render-mutations [mutations]
  [:div.col-md-12
   [:div {:class "box"}
    [:div {:class "box-header"}
     [:h3.box-title "Search for Mutation Records"]]
    [:div.box-body
     [:div.form-group
      [:div.row
       [:div.col-sm-2 "Mutation Number"
        [:input.form-control {:id "mutationnumber"
                              :list "combo"
                              :type "text"
                              :placeholder  "Enter search by Mutation Number"
                              :on-change #(get-data (-> % .-target .-value))
                              }]
        [datalist (:mutationnumbers @citizen-storage)]]]]

     [:div.form-group
      [:div.row
       [:span {:style {:float "right" :width "50%"}} [:b "OR"]]
       [:hr]]]

     [:div.form-group
      [:div.row
       [:div.col-sm-2
        [:label "District Name"]
        [src-dist-sel-tag]]
       [:div.col-sm-2
        [:label"Sub Division Name"]
        [src-sub-sel-tag]]
       [:div.col-sm-2
        [:label "Village Name"]
        [src-vill-sel-tag]]
       [:div.col-sm-2
        [:label "O2 Number"]
        [:input.form-control {:id "so2number"
                              :type "text"
                              :placeholder "O2 Number"}]]
       [:div.col-sm-2
        [:label "O4 Number"]
        [:input.form-control {:id "so4number"
                              :type "text"
                              :placeholder "O4 Number"}]]
       [:div.col-sm-2
        [:label "O6 Number"]
        [:input.form-control {:id "so6number"
                              :type "text"
                              :placeholder "O6 Number"}]]]]
     [:div.form-group
      [:div.row
       [:div.col-sm-2
        [:label "Name of the First Party"]
        [:input.form-control {:id "snameofthefirstparty"
                              :type "text"
                              :placeholder "Name of the First Party"}]]
       [:div.col-sm-2
        [:label "Name of the Second Party"]
        [:input.form-control {:id "snameofthesecondparty"
                              :type "text"
                              :placeholder "Name of the Second Party"}]]
       [:div.col-sm-2
        [:label "Name of P.O"]
        [:input.form-control {:id "svillagename"
                              :list "combo1"
                              :placeholder "Name of P.O"}[datalist1]]]
       [:div.col-sm-2
        [:label "Nature of Case"]
        [:input.form-control {:id "stitle"
                              :type "text"
                              :placeholder "Nature of Case"}]]
       [:div.col-sm-2
        [:label "Khasra Number"]
        [:input.form-control {:id "skhasranumber"
                              :type "text"
                              :placeholder "Khasra Number"} ]]
       [:div.col-sm-2
        [:label "Khata khatuni Number"]
        [:input.form-control {:id "skhatakhatuninumber"
                              :type "text"
                              :placeholder "Khata Khatuni Number"}]]]]
     [:div.form-group
      [:div.row
       [:div.col-sm-6
        [button {:bs-style "primary" :on-click search } "Search"]]
       [:div.col-sm-6.col-md-offset-5
        [:h3 {:style  {:color "red"}} (str (:message @citizen-storage))]]]]
     ]]

   [:div.box
    [:div.box-header
     [:h3.box-title "List of Mutations"]]
    [:div {:class "box-body table-responsive"}
     [:table {:class "table table-bordered table-striped"
              :style {:width: "100%"}}
      [:thead
       [:tr
        [:th "Mutation Number"]
        [:th "Name of the First Party"]
        [:th "Name of the Second Party"]
        [:th "Date of Institution"]
        [:th "Name of P.O"]
        [:th "Name of District"]
        [:th "Sub Division Name"]
        [:th "Name of Village"]
        [:th "O2 Number"]
        [:th "O4 Number"]
        [:th "O6 Number"]
        [:th "Nature of Case"]
        [:th "Khasra Number"]
        [:th "Khata khatuni Number"]
        ]]
      [:tbody
       (doall (for [mt mutations]
                ^{:key (.-id mt)} [:tr
                                   (when (and  (.-senddate mt) (not (.-receiveddate mt)))
                                     {:style {:background-color "#fbcfd1"}})
                                   [:td (.-mutationnumber (.-numbers mt))]
                                   [:td (.-nameofthefirstparty mt)]
                                   [:td (.-nameofthesecondparty mt)]
                                   [:td (.-dateofinstitution mt)]
                                   [:td (.-nameofpo mt)]
                                   [:td (.-name (.-district  mt))]
                                   [:td (.-name (.-subdivision mt))]
                                   [:td (.-name (.-village mt))]
                                   [:td (.-o2number (.-numbers  mt))]
                                   [:td (.-o4number (.-numbers mt))]
                                   [:td (.-o6number (.-numbers mt))]
                                   [:td (.-title mt)]
                                   [:td (.-khasranumber (.-numbers mt))]
                                   [:td (.-khatakhatuninumber (.-numbers mt))]
                                   ]))]]]
    [:div{:class "col-xs-6 col-centered col-max"}] [shared-state 0]]])

(defn main []
  (let [onres (fn [json] ((set-key-value :districts (getdata json))
                         (r/render [render-mutations]
                                   (.getElementById js/document "app1"))))]
    (http-get (str serverhost "districts") onres)))

(main)

update citizen_cljs

update citizen_cljs


(ns clstreams.processor
  (:import [org.apache.kafka.streams.processor Processor ProcessorSupplier]))

(deftype TransducingProcessor [init-reducer-fn init-state-fn
                               ^:volatile-mutable reducer
                               ^:volatile-mutable state]

  Processor

  (init [this ctx]
    (set! reducer (init-reducer-fn ctx))
    (set! state (init-state-fn ctx)))

  (process [this key value]
    (set! state (reducer state [key value])))

  (punctuate [this timestamp] nil)

  (close [this]
    (reducer state)))

(defn transducing-processor
  ([init-reducer-fn init-state-fn]
   (reify
     ProcessorSupplier
     (get [this] (->TransducingProcessor init-reducer-fn init-state-fn nil nil)))))

(defn forward-reducer
  ([] nil)
  ([context] context)
  ([context [key value]]
   (.forward context key value)
   context))

(defn key-value-processor
  ([xform]
   (transducing-processor
    (fn [context] (xform forward-reducer))
    identity))
  ([xform1 xform2 & xforms]
   (key-value-processor (apply comp xform1 xform2 xforms))))

(defn xform-values [xform & xforms]
  (let [value-xform (apply comp xform xforms)
        current-key (volatile! ::none)]
    (letfn [(separate-key-xform [rf]
              (fn
                ([] (rf))
                ([result] (rf result))
                ([result [key value]]
                 (vreset! current-key key)
                 (rf result value))))
            (remix-key-xform [rf]
              (fn
                ([] (rf))
                ([result] (rf result))
                ([result value] (rf result [@current-key value]))))]
      (comp separate-key-xform value-xform remix-key-xform))))

(ns clstreams.processor
  (:import [org.apache.kafka.streams.processor Processor ProcessorSupplier]))

(deftype TransducingProcessor [init-reducer-fn init-state-fn
                               ^:volatile-mutable reducer
                               ^:volatile-mutable state]

  Processor

  (init [this ctx]
    (set! reducer (init-reducer-fn ctx))
    (set! state (init-state-fn ctx)))

  (process [this key value]
    (set! state (reducer state [key value])))

  (punctuate [this timestamp] nil)

  (close [this]
    (reducer state)))

(defn transducing-processor
  ([init-reducer-fn init-state-fn]
   (reify
     ProcessorSupplier
     (get [this] (->TransducingProcessor init-reducer-fn init-state-fn nil nil)))))

(defn forward-reducer
  ([] nil)
  ([context] context)
  ([context [key value]]
   (.forward context key value)
   context))

(deftype KeyValueProcessor [reducer
                            ^:volatile-mutable context]

  Processor

  (init [this ctx]
    (set! context ctx))

  (process [this key value]
    (reducer context [key value]))

  (punctuate [this timestamp] nil)

  (close [this]
    (reducer context)))

(defn key-value-processor
  ([xform]
   (reify
     ProcessorSupplier
     (get [this] (->KeyValueProcessor (xform forward-reducer) nil))))
  ([xform1 xform2 & xforms]
   (key-value-processor (apply comp xform1 xform2 xforms))))

(defn xform-values [xform & xforms]
  (let [value-xform (apply comp xform xforms)
        current-key (volatile! ::none)]
    (letfn [(separate-key-xform [rf]
              (fn
                ([] (rf))
                ([result] (rf result))
                ([result [key value]]
                 (vreset! current-key key)
                 (rf result value))))
            (remix-key-xform [rf]
              (fn
                ([] (rf))
                ([result] (rf result))
                ([result value] (rf result [@current-key value]))))]
      (comp separate-key-xform value-xform remix-key-xform))))

Remove key-value-processor's dependency on transducing-processor.

...as a step to remove transducing-processor, which is a funny
abstraction.


(ns subrosa.netty
  (:use [subrosa.server :only [reset-all-state!]]
        [subrosa.client :only [add-channel! remove-channel! send-to-client
                               send-to-client*]]
        [subrosa.commands :only [dispatch-message]])
  (:import [java.net InetSocketAddress]
           [java.util.concurrent Executors]
           [org.jboss.netty.bootstrap ServerBootstrap]
           [org.jboss.netty.channel ChannelUpstreamHandler
            ChannelDownstreamHandler ChannelEvent ChannelState ChannelStateEvent
            ExceptionEvent MessageEvent]
           [org.jboss.netty.channel.group DefaultChannelGroup]
           [org.jboss.netty.channel.socket.nio NioServerSocketChannelFactory]
           [org.jboss.netty.handler.codec.frame Delimiters
            DelimiterBasedFrameDecoder]
           [org.jboss.netty.handler.codec.string StringDecoder StringEncoder]))

;; Some code and a lot of inspiration for the layout of this namespace came from
;; Zach Tellman's awesome aleph project: http://github.com/ztellman/aleph

(defn event->address [event]
  (-> event
      .getChannel
      .getRemoteAddress))

(defn upstream-stage [handler]
  (reify ChannelUpstreamHandler
         (handleUpstream [_ ctx evt]
                         (.sendUpstream ctx (or (handler evt) evt)))))

(defn downstream-stage [handler]
  (reify ChannelDownstreamHandler
         (handleDownstream [_ ctx evt]
                           (.sendDownstream ctx (or (handler evt) evt)))))

(defn message-stage [handler]
  (upstream-stage
   (fn [evt]
     (when (instance? MessageEvent evt)
       (handler evt)))))

(defn netty-error-handler [up-or-down evt]
  (when (instance? ExceptionEvent evt)
    (if (instance? clojure.contrib.condition.Condition (.getCause evt))
      (let [condition (meta (.getCause evt))]
        (when (= :client-error (:type condition))
          (send-to-client
           (.getChannel evt) (:code condition) (:msg condition)))
        (when (= :client-disconnect (:type condition))
          (println "Tried to grab data about a client after disconnect.")))
      (when (not (some #{(class (.getCause evt))}
                       #{java.io.IOException
                         java.nio.channels.ClosedChannelException}))
        (println up-or-down "ERROR")
        (.printStackTrace (.getCause evt)))))
  evt)

(defn connect-handler [channel-group evt]
  (when (and (instance? ChannelStateEvent evt)
             (= (.getState evt) (ChannelState/CONNECTED))
             (.getValue evt))
    (.add channel-group (.getChannel evt))
    (dosync
     (add-channel! (.getChannel evt))))
  evt)

(defn message-handler [evt]
  (dispatch-message (.getMessage evt) (.getChannel evt))
  evt)

(defn disconnect-handler [evt]
  (when (and (instance? ChannelStateEvent evt)
             (= (.getState evt) (ChannelState/CONNECTED))
             (not (.getValue evt)))
    (dosync
     (remove-channel! (.getChannel evt))))
  evt)

(defn add-string-codec! [pipeline]
  (doto pipeline
    (.addLast "framer"
              (DelimiterBasedFrameDecoder. 8192 (Delimiters/lineDelimiter)))
    (.addLast "decoder" (StringDecoder.))
    (.addLast "encoder" (StringEncoder.))))

(defn add-irc-codec! [pipeline channel-group]
  (doto pipeline
    (.addLast "upstream-error"
              (upstream-stage (partial #'netty-error-handler "UPSTREAM")))
    (.addLast "connect" (upstream-stage
                         (partial #'connect-handler channel-group)))
    (.addLast "message" (message-stage #'message-handler))
    (.addLast "disconnect" (upstream-stage #'disconnect-handler))
    (.addLast "downstream-error"
              (downstream-stage (partial #'netty-error-handler "DOWNSTREAM")))))

(defn create-server [port]
  (let [channel-factory (NioServerSocketChannelFactory.
                         (Executors/newCachedThreadPool)
                         (Executors/newCachedThreadPool))
        bootstrap (ServerBootstrap. channel-factory)
        pipeline (.getPipeline bootstrap)
        channel-group (DefaultChannelGroup.)]
    (doto pipeline
      add-string-codec!
      (add-irc-codec! channel-group))
    (doto bootstrap
      (.setOption "child.tcpNoDelay" true)
      (.setOption "child.keepAlive" true))
    {:start-fn (fn []
                 (println "Starting Subrosa.")
                 (reset-all-state!)
                 (->> port
                      InetSocketAddress.
                      (.bind bootstrap)
                      (.add channel-group)))
     :stop-fn (fn []
                (println "Shutting down Subrosa.")
                (doseq [channel channel-group]
                  (send-to-client* channel "ERROR :Server going down"))
                (-> channel-group .close .awaitUninterruptibly)
                (.releaseExternalResources channel-factory))}))

fix indentation on reify

fix indentation on reify


;; Copyright 2014-2015 Red Hat, Inc, and individual contributors.
;;
;; Licensed under the Apache License, Version 2.0 (the "License");
;; you may not use this file except in compliance with the License.
;; You may obtain a copy of the License at
;;
;; http://www.apache.org/licenses/LICENSE-2.0
;;
;; Unless required by applicable law or agreed to in writing, software
;; distributed under the License is distributed on an "AS IS" BASIS,
;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;; See the License for the specific language governing permissions and
;; limitations under the License.

(ns immutant.web.async-test
  (:require [clojure.test :refer :all]
            [immutant.web :refer :all]
            [immutant.web.async :refer :all]
            [immutant.web.middleware :refer [wrap-session wrap-websocket]]
            [ring.util.response :refer [response]]
            [http.async.client :as http]
            [testing.web :refer [hello get-body]]
            [gniazdo.core :as ws]
            [clojure.string :refer [upper-case]])
  (:import [io.undertow.util Sessions]))

(def url "http://localhost:8080/")

(defn test-websocket
  [create-handler]
  (let [path "/test"
        events (atom [])
        result (promise)
        handler (create-handler
                  {:on-open    (fn [_]
                                 (swap! events conj :open))
                   :on-close   (fn [_ {c :code}]
                                 (deliver result (swap! events conj c)))
                   :on-message (fn [_ m]
                                 (swap! events conj m))})]
    (try
      (run handler {:path path})
      (let [socket (ws/connect (str "ws://localhost:8080" path))]
        (ws/send-msg socket "hello")
        (ws/close socket))
      (deref result 2000 :fail)
      (finally
        (stop {:path path})))))

(defn ws-init-handler [callbacks]
  (fn [req]
    (if (:websocket? req)
      (as-channel req callbacks)
      {:status 404})))

;; (deftest jsr-356-websocket
;;   (let [expected [:open "hello" 1000]]
;;     (is (= expected (test-websocket (comp (partial attach-endpoint (create-servlet hello)) create-endpoint))))))

(deftest middleware-websocket
  (let [expected [:open "hello" 1000]]
    (is (= expected (test-websocket (partial wrap-websocket hello))))))

(deftest remote-sending-to-client-using-gniazdo-and-init-ws
  (let [result (promise)
        server (run (ws-init-handler {:on-message (fn [c m] (send! c (upper-case m)))
                                      :on-error (fn [_ e] (.printStackTrace e))}))
        socket (ws/connect "ws://localhost:8080" :on-receive #(deliver result %))]
    (try
      (ws/send-msg socket "hello")
      (is (= "HELLO" (deref result 2000 :failure)))
      (finally
        (ws/close socket)
        (stop server)))))

(deftest remote-sending-to-client-using-gniazdo
  (let [result (promise)
        server (run (wrap-websocket nil {:on-message (fn [c m] (send! c (upper-case m)))}))
        socket (ws/connect "ws://localhost:8080" :on-receive #(deliver result %))]
    (try
      (ws/send-msg socket "hello")
      (is (= "HELLO" (deref result 2000 "goodbye")))
      (finally
        (ws/close socket)
        (stop server)))))

(deftest remote-sending-to-client-using-httpasyncclient
  (let [result (promise)
        server (run (wrap-websocket nil {:on-message (fn [c m] (send! c (upper-case m)))}))]
    (try
      (with-open [client (http/create-client)
                  socket (http/websocket client "ws://localhost:8080"
                           :text (fn [_ m] (deliver result m)))]
        (http/send socket :text "hello")
        (is (= "HELLO" (deref result 2000 "goodbye"))))
      (finally
        (stop server)))))

(deftest handshake-headers
  (let [result (promise)
        endpoint (wrap-websocket nil :on-open (fn [ch] (deliver result (handshake ch))))]
    (run endpoint)
    (with-open [client (http/create-client)
                socket (http/websocket client "ws://localhost:8080/?x=y&j=k")]
      (let [handshake (deref result 1000 nil)]
        (is (not (nil? handshake)))
        (is (= "Upgrade"   (-> handshake headers (get "Connection") first)))
        (is (= "k"         (-> handshake parameters (get "j") first)))
        (is (= "x=y&j=k"   (-> handshake query-string)))
        ;; TODO: bug in undertow! (is (= "/?x=y&j=k" (-> handshake uri str)))
        (is (false?        (-> handshake (user-in-role? "admin"))))))
    (stop)))

(deftest share-session-with-websocket
  (let [result (promise)
        handler (fn [{{:keys [id] :or {id (str (rand))}} :session}]
                  (-> id response (assoc :session {:id id})))]
    (run (wrap-websocket (wrap-session handler)
           :on-open (fn [ch] (deliver result (-> ch handshake session :id)))))
    ;; establish the id in the session with the first request
    (let [id (get-body url :cookies nil)]
      ;; make sure we get it again if we pass the returned cookie
      (is (= id (get-body url)))
      ;; now open a websocket connection with the same cookie
      (with-open [client (http/create-client)
                  socket (http/websocket client "ws://localhost:8080"
                           :cookies @testing.web/cookies)]
        ;; and verify the websocket sees the same id
        (is (= id (deref result 1000 :failure)))))
    (stop)))

(deftest http-session-invalidation
  (let [http (atom {})
        handler (fn [req]
                  (let [result (if-not (-> req :session :foo)
                                 (-> (response "yay")
                                   (assoc :session {:foo "yay"}))
                                 (-> (response "boo")
                                   (assoc :session nil)))]
                    (reset! http (-> req :server-exchange Sessions/getOrCreateSession))
                    result))]
    (run (wrap-session handler))
    (is (= "yay" (get-body url :cookies nil)))
    (is (= "yay" (-> @http (.getAttribute "ring-session-data") :foo)))
    (is (= "boo" (get-body url)))
    (is (thrown? IllegalStateException (-> @http (.getAttribute "ring-session-data") :foo)))
    (is (= "yay" (get-body url)))
    (is (= "yay" (-> @http (.getAttribute "ring-session-data") :foo)))
    (stop)))

(defmethod initialize-stream :test
  [& _])

(deftest as-channel-should-accept-kwargs-and-map
  (as-channel {:handler-type :test} :on-open identity)
  (as-channel {:handler-type :test} {:on-open identity}))

(deftest as-channel-should-throw-with-invalid-callback
  (is (thrown? IllegalArgumentException
        (as-channel {:handler-type :test} {:on-fire nil}))))

(deftest on-close-should-be-invoked-when-closing-on-server-side
  (let [reason (promise)]
    (run (fn [req]
           (as-channel req
             :on-open close
             :on-close (fn [_ r] (deliver reason r)))))
    (let [socket (ws/connect "ws://localhost:8080")]
        (ws/send-msg socket "hello"))
    (is (deref reason 5000 nil))))

Verify closing a ws from the server-side triggers :on-close.


(ns org.altlaw.www.render
  (:require [org.altlaw.util.context :as context])
  (:use [clojure.contrib.test-is :only (with-test is testing)]
        [clojure.contrib.duck-streams :only (reader)]
        [clojure.contrib.walk :only (stringify-keys)])
  (:import (org.antlr.stringtemplate StringTemplate StringTemplateGroup)
           (org.antlr.stringtemplate.language DefaultTemplateLexer)
           (org.apache.commons.lang StringEscapeUtils)))

(defn- string [x]
  (if (keyword? x)
    (name x)
    (str x)))

(with-test
 (defn- render-template
   "Assigns attributes to a StringTemplate and renders it.  Attributes
   are a :keyword=>value map, where values may be scalars or collections."
   [template attrs]
   (.setAttributes template (stringify-keys attrs))
   (str template))

 (is (= "Goodbye, Bob!"
        (render-template (StringTemplate. "$greeting$, $name$!")
                         {:greeting "Goodbye" :name "Bob"})))

 (testing "list separators"
          (is (= "Welcome, foo,bar,baz."
                 (render-template (StringTemplate.
                                   "$greeting$, $names; separator=\",\"$.")
                                  {:greeting "Welcome"
                                   :names ["foo" "bar" "baz"]}))))
 (testing "rest() operator"
          (is (= "Hello: First:foo,bar,baz"
                 (render-template (StringTemplate.
                                   "Hello: First:$first(names)$,$rest(names); separator=\",\"$")
                                  {:names ["foo" "bar" "baz"]}))))

 (testing "last() operator"
          (is (= "foo,bar,baz,last:baz"
                 (render-template (StringTemplate.
                                   "$names; separator=\",\"$,last:$last(names)$")
                                  {:names ["foo" "bar" "baz"]}))))

 (testing "nested maps in values"
          (is (= "Foo: fooness  Bar: barness"
                 (render-template (StringTemplate.
                                   "Foo: $user.foo$  Bar: $user.bar$")
                                  {:user {:foo "fooness" :bar "barness"}}))))
 (testing "seq of nested maps in values"
          (is (= "Foo: f1f2f3"
                 (render-template (StringTemplate.
                                   "Foo: $user:{f$it.foo$}$")
                                  {:user [{:foo 1} {:foo 2} {:foo 3}]})))))

(def #^{:private true} template-group
     (memoize (fn []
                (let [page-templates (StringTemplateGroup. "org.altlaw.www.templates")]
                  ;; By default, templates are never refreshed.
                  ;; In development mode, always refresh.
                  (when (= (context/altlaw-env) "development")
                    (.setRefreshInterval page-templates 0))
                  page-templates))))

(with-test
 (defn render
   "Renders a template from a file.  name does not include the '.st'
   extension.  attrs is a :keyword=>value map as with
   render-template."
   [name & attrs]
   (-> (template-group)
       (.getInstanceOf (str "org/altlaw/www/templates/" (string name)))
       (render-template (if (map? (first attrs))
                          (if (next attrs)
                            (apply conj (first attrs) (next attrs))
                            (first attrs))
                          (apply array-map attrs)))))

 (is (= "\nHello, Harry.\n"
        (render "test1" {:name "Harry"})))
 (is (= "\nHello, Harry.\n"
        (render :test1 :name "Harry")))
 (is (= "\nHello, .\n"
        (render :test1))))

(defn h
  "Converts x to String and escapes HTML using XML entities."
  [x]
  (StringEscapeUtils/escapeXml (str x)))

(ns org.altlaw.www.render
  (:require [org.altlaw.util.context :as context]
            [clojure.contrib.java-utils :as java]
            [clojure.contrib.classpath :as cp]
            [clojure.contrib.singleton :as sing])
  (:use [clojure.contrib.test-is :only (with-test is testing)]
        [clojure.contrib.walk :only (stringify-keys)])
  (:import (org.antlr.stringtemplate StringTemplate StringTemplateGroup)
           (org.antlr.stringtemplate.language DefaultTemplateLexer)
           (org.apache.commons.lang StringEscapeUtils)))

(with-test
 (defn- render-template
   "Assigns attributes to a StringTemplate and renders it.  Attributes
   are a :keyword=>value map, where values may be scalars or collections."
   [template attrs]
   (.setAttributes template (stringify-keys attrs))
   (str template))

 (is (= "Goodbye, Bob!"
        (render-template (StringTemplate. "$greeting$, $name$!")
                         {:greeting "Goodbye" :name "Bob"})))

 (testing "list separators"
          (is (= "Welcome, foo,bar,baz."
                 (render-template (StringTemplate.
                                   "$greeting$, $names; separator=\",\"$.")
                                  {:greeting "Welcome"
                                   :names ["foo" "bar" "baz"]}))))
 (testing "rest() operator"
          (is (= "Hello: First:foo,bar,baz"
                 (render-template (StringTemplate.
                                   "Hello: First:$first(names)$,$rest(names); separator=\",\"$")
                                  {:names ["foo" "bar" "baz"]}))))

 (testing "last() operator"
          (is (= "foo,bar,baz,last:baz"
                 (render-template (StringTemplate.
                                   "$names; separator=\",\"$,last:$last(names)$")
                                  {:names ["foo" "bar" "baz"]}))))

 (testing "nested maps in values"
          (is (= "Foo: fooness  Bar: barness"
                 (render-template (StringTemplate.
                                   "Foo: $user.foo$  Bar: $user.bar$")
                                  {:user {:foo "fooness" :bar "barness"}}))))
 (testing "seq of nested maps in values"
          (is (= "Foo: f1f2f3"
                 (render-template (StringTemplate.
                                   "Foo: $user:{f$it.foo$}$")
                                  {:user [{:foo 1} {:foo 2} {:foo 3}]})))))

(defn www-templates-dir []
  (some
   (fn [dir]
     (let [template-dir
           (java/file dir "org" "altlaw" "www" "templates")]
       (when (.exists template-dir) template-dir)))
   (cp/classpath-directories)))

(def #^{:private true} template-group
     (sing/global-singleton
      (fn []
        (let [page-templates (StringTemplateGroup. "org.altlaw.www.templates"
                                                   (str (www-templates-dir)))]
          ;; By default, templates are never refreshed.
          ;; In development mode, always refresh.
          (when (= (context/altlaw-env) "development")
            (.setRefreshInterval page-templates 0))
          page-templates))))

(with-test
 (defn render
   "Renders a template from a file.  name does not include the '.st'
   extension.  attrs is a :keyword=>value map as with
   render-template."
   [name & attrs]
   (-> (template-group)
       (.getInstanceOf (java/as-str name))
       (render-template (if (map? (first attrs))
                          (if (next attrs)
                            (apply conj (first attrs) (next attrs))
                            (first attrs))
                          (apply array-map attrs)))))

 (is (= "\nHello, Harry.\n"
        (render "test1" {:name "Harry"})))
 (is (= "\nHello, Harry.\n"
        (render :test1 :name "Harry")))
 (is (= "\nHello, .\n"
        (render :test1))))

(defn h
  "Converts x to String and escapes HTML using XML entities."
  [x]
  (StringEscapeUtils/escapeXml (str x)))

load StringTemplateGroup from directory

www/render.clj: load StringTemplateGroup from directory


(set-env!
 :dependencies '[;; Boot deps
                 [adzerk/boot-cljs            "1.7.228-1" :scope "test"]
                 [pandeiro/boot-http          "0.7.1-SNAPSHOT" :scope "test"]
                 [adzerk/boot-reload          "0.4.4" :scope "test"]
                 [degree9/boot-semver         "1.2.1" :scope "test"]

                 ;; Repl
                 [adzerk/boot-cljs-repl       "0.3.0"  :scope "test"]
                 [com.cemerick/piggieback     "0.2.1"  :scope "test"]
                 [weasel                      "0.7.0"  :scope "test"]
                 [org.clojure/tools.nrepl     "0.2.12" :scope "test"]

                 ;; Tests
                 [crisptrutski/boot-cljs-test "0.2.2-SNAPSHOT"  :scope "test"]
                 [adzerk/boot-test            "1.0.7"      :scope "test"]

                 ;; App deps
                 [org.clojure/clojure         "1.7.0"]
                 [org.clojure/clojurescript   "1.7.228"]
                 [org.clojure/core.async      "0.2.374"]
                 [reagent                     "0.5.1"]
                 [re-frame                    "0.5.0"]
                 [replumb/replumb             "0.1.5-SNAPSHOT"]
                 [cljsjs/jqconsole            "2.13.1-0"]
                 [cljsjs/highlight            "8.4-0"]
                 [re-com                      "0.7.0-alpha2"]
                 [cljs-ajax                   "0.5.1"]
                 [endophile                   "0.1.2"]
                 [markdown-clj                "0.9.78"]
                 [hickory                     "0.5.4"]
                 [cljsjs/showdown             "0.4.0-1"]
                 [org.clojure/tools.reader    "1.0.0-alpha3"]
                 [cljsjs/enquire              "2.1.2-0"]
                 [com.cemerick/piggieback     "0.2.1"]
                 [binaryage/devtools          "0.4.1"]
                 [day8/re-frame-tracer        "0.1.0-SNAPSHOT"]
                 [cljsjs/codemirror           "5.10.0-0"]])

(require '[adzerk.boot-cljs             :refer [cljs]]
         '[adzerk.boot-reload           :refer [reload]]
         '[pandeiro.boot-http           :refer [serve]]
         '[crisptrutski.boot-cljs-test  :refer [test-cljs]]
         '[adzerk.boot-cljs-repl        :refer [cljs-repl start-repl]]
         '[boot-semver.core :refer :all])

(def +version+ (get-version))

(task-options! pom {:project "cljs-repl-web"
                    :version +version+}
               test-cljs {:js-env :phantom
                          :out-file "phantom-tests.js"})

;;;;;;;;;;;;;;;;;;;;;;
;;;    Options     ;;;
;;;;;;;;;;;;;;;;;;;;;;

(def dev-compiler-options
  {:source-map-timestamp true})

(def prod-compiler-options
  {:closure-defines {"goog.DEBUG" false}
   :optimize-constants true
   :static-fns true
   :elide-asserts true
   :pretty-print false
   :source-map-timestamp true})

(def test-namespaces
  #{"cljs-repl-web.core-test"
    "cljs-repl-web.code-mirror.app-test"})

(defmulti options
  "Return the correct option map for the build, dispatching on identity"
  identity)

(defmethod options :dev
  [selection]
  {:type :dev
   :env {:source-paths #{"src/clj" "src/cljs" "env/dev/cljs"}
         :resource-paths #{"resources/public/"}
         :cljs {:source-map true
                :optimizations :none
                :compiler-options dev-compiler-options}}
   :test-cljs {:optimizations :none
               :cljs-opts dev-compiler-options
               :namespaces test-namespaces}})

(defmethod options :prod
  [selection]
  {:type :prod
   :env {:source-paths #{"src/clj" "src/cljs" "env/prod/cljs"}
         :resource-paths #{"resources/public/"}}
   :cljs {:source-map true
          :optimizations :simple
          :compiler-options prod-compiler-options}
   :test-cljs {:optimizations :simple
               :cljs-opts prod-compiler-options
               :namespaces test-namespaces}})

(deftask build
  "Build the final artifact, if no type is passed in, it builds production."
  [t type VAL kw "The build type, either prod or dev"]

  (let [options (options (or type :prod))]
    (boot.util/info "Building %s profile...\n" (:type options))
    (apply set-env! (reduce #(into %2 %1) [] (:env options)))
    (comp (apply cljs (reduce #(into %2 %1) [] (:cljs options)))
          (target))))

(deftask dev
  "Start the dev interactive environment."
  []
  (boot.util/info "Starting interactive dev...\n")
  (let [options (options :dev)]
    (apply set-env! (reduce #(into %2 %1) [] (:env options)))
    (comp (serve)
          (watch)
          (cljs-repl)
          (build :type :dev)
          (reload :on-jsload 'cljs-repl-web.core/main))))

;; This prevents a name collision WARNING between the test task and
;; clojure.core/test, a function that nobody really uses or cares
;; about.
(ns-unmap 'boot.user 'test)

(deftask test
  "Run tests, if no type is passed in, it tests against production."
  [t type VAL kw "The build type, either prod or dev"]
  (let [options (options (or type :prod))]
    (boot.util/info "Testing %s profile...\n" (:type options))
    (set-env! :source-paths (conj (get-in options [:env :source-paths]) "test/cljs" ))
    (apply test-cljs (reduce #(into %2 %1) [] (:test-cljs options)))))

(deftask auto-test
  "Run tests while updating on file change.

  Always runs against :dev.

  It automatically enables test sound notifications, use the -n parameter for
  switching them off."
  [n no-sounds bool "Enable notifications during tests"]
  (comp (watch)
        (if no-sounds identity (speak))
        (test :type :dev)))

(set-env!
 :dependencies '[;; Boot deps
                 [adzerk/boot-cljs            "1.7.228-1" :scope "test"]
                 [pandeiro/boot-http          "0.7.1-SNAPSHOT" :scope "test"]
                 [adzerk/boot-reload          "0.4.4" :scope "test"]
                 [degree9/boot-semver         "1.2.1" :scope "test"]

                 ;; Repl
                 [adzerk/boot-cljs-repl       "0.3.0"  :scope "test"]
                 [com.cemerick/piggieback     "0.2.1"  :scope "test"]
                 [weasel                      "0.7.0"  :scope "test"]
                 [org.clojure/tools.nrepl     "0.2.12" :scope "test"]

                 ;; Tests
                 [crisptrutski/boot-cljs-test "0.2.2-SNAPSHOT"  :scope "test"]
                 [adzerk/boot-test            "1.0.7"      :scope "test"]

                 ;; App deps
                 [org.clojure/clojure         "1.7.0"]
                 [org.clojure/clojurescript   "1.7.228"]
                 [org.clojure/core.async      "0.2.374"]
                 [reagent                     "0.5.1"]
                 [re-frame                    "0.5.0"]
                 [replumb/replumb             "0.1.5-SNAPSHOT"]
                 [cljsjs/jqconsole            "2.13.1-0"]
                 [cljsjs/highlight            "8.4-0"]
                 [re-com                      "0.7.0-alpha2"]
                 [cljs-ajax                   "0.5.1"]
                 [endophile                   "0.1.2"]
                 [markdown-clj                "0.9.78"]
                 [hickory                     "0.5.4"]
                 [cljsjs/showdown             "0.4.0-1"]
                 [org.clojure/tools.reader    "1.0.0-alpha3"]
                 [cljsjs/enquire              "2.1.2-0"]
                 [com.cemerick/piggieback     "0.2.1"]
                 [binaryage/devtools          "0.4.1"]
                 [day8/re-frame-tracer        "0.1.0-SNAPSHOT"]
                 [cljsjs/codemirror           "5.10.0-0"]])

(require '[adzerk.boot-cljs             :refer [cljs]]
         '[adzerk.boot-reload           :refer [reload]]
         '[pandeiro.boot-http           :refer [serve]]
         '[crisptrutski.boot-cljs-test  :refer [test-cljs]]
         '[adzerk.boot-cljs-repl        :refer [cljs-repl start-repl]]
         '[boot-semver.core :refer :all])

(def +version+ (get-version))

(task-options! pom {:project "cljs-repl-web"
                    :version +version+}
               test-cljs {:js-env :phantom
                          :out-file "phantom-tests.js"})

;;;;;;;;;;;;;;;;;;;;;;
;;;    Options     ;;;
;;;;;;;;;;;;;;;;;;;;;;

(def dev-compiler-options
  {:source-map-timestamp true})

(def prod-compiler-options
  {:closure-defines {"goog.DEBUG" false}
   :optimize-constants true
   :static-fns true
   :elide-asserts true
   :pretty-print false
   :source-map-timestamp true})

(def test-namespaces
  #{"cljs-repl-web.core-test"
    "cljs-repl-web.code-mirror.app-test"})

(defmulti options
  "Return the correct option map for the build, dispatching on identity"
  identity)

(defmethod options :dev
  [selection]
  {:type :dev
   :env {:source-paths #{"src/clj" "src/cljs" "env/dev/cljs"}
         :resource-paths #{"resources/public/"}
         :cljs {:source-map true
                :optimizations :none
                :compiler-options dev-compiler-options}}
   :test-cljs {:optimizations :none
               :cljs-opts dev-compiler-options
               :namespaces test-namespaces}})

(defmethod options :prod
  [selection]
  {:type :prod
   :env {:source-paths #{"src/clj" "src/cljs" "env/prod/cljs"}
         :resource-paths #{"resources/public/"}}
   :cljs {:source-map true
          :optimizations :simple
          :compiler-options prod-compiler-options}
   :test-cljs {:optimizations :simple
               :cljs-opts prod-compiler-options
               :namespaces test-namespaces}})

(deftask version-file
  "A task that includes the version.properties file in the fileset."
  []
  (boot.util/info "Add version.properties...\n")
  (with-pre-wrap [fileset]
    (-> fileset
        (add-resource (java.io.File. ".") :include #{#"^version\.properties$"})
        commit!)))

(deftask build
  "Build the final artifact, if no type is passed in, it builds production."
  [t type VAL kw "The build type, either prod or dev"]

  (let [options (options (or type :prod))]
    (boot.util/info "Building %s profile...\n" (:type options))
    (apply set-env! (reduce #(into %2 %1) [] (:env options)))
    (comp (apply cljs (reduce #(into %2 %1) [] (:cljs options)))
          (version-file)
          (target))))

(deftask dev
  "Start the dev interactive environment."
  []
  (boot.util/info "Starting interactive dev...\n")
  (let [options (options :dev)]
    (apply set-env! (reduce #(into %2 %1) [] (:env options)))
    (comp (serve)
          (watch)
          (cljs-repl)
          (build :type :dev)
          (reload :on-jsload 'cljs-repl-web.core/main))))

;; This prevents a name collision WARNING between the test task and
;; clojure.core/test, a function that nobody really uses or cares
;; about.
(ns-unmap 'boot.user 'test)

(deftask test
  "Run tests, if no type is passed in, it tests against production."
  [t type VAL kw "The build type, either prod or dev"]
  (let [options (options (or type :prod))]
    (boot.util/info "Testing %s profile...\n" (:type options))
    (set-env! :source-paths (conj (get-in options [:env :source-paths]) "test/cljs" ))
    (apply test-cljs (reduce #(into %2 %1) [] (:test-cljs options)))))

(deftask auto-test
  "Run tests while updating on file change.

  Always runs against :dev.

  It automatically enables test sound notifications, use the -n parameter for
  switching them off."
  [n no-sounds bool "Enable notifications during tests"]
  (comp (watch)
        (if no-sounds identity (speak))
        (test :type :dev)))

Include version.properties in the build

Include version.properties in the build


#!/usr/bin/env boot

#tailrecursion.boot.core/version "2.3.1"

(set-env!
  :dependencies  [['tailrecursion/boot.task   "2.1.2"]
                  ['tailrecursion/hoplon      "5.7.0"]
                  ['markdown-clj              "0.9.41"]
                  ['org.clojure/clojurescript "0.0-2156"]]
  :src-paths     #{"src"}
  :out-path      "resources/public")

(add-sync! (get-env :out-path) #{"resources/assets"})

(require
  ['tailrecursion.boot.task   :refer :all]
  ['tailrecursion.hoplon.boot :refer :all])

(deftask dev
  "Build hoplon.io for local development."
  []
  (comp (watch) (hoplon {:pretty-print  true
                         :prerender     false
                         :optimizations :whitespace})))

(deftask prod
  "Build hoplon.io for production deployment."
  []
  (hoplon {:optimizations :advanced}))

#!/usr/bin/env boot

#tailrecursion.boot.core/version "2.3.1"

(set-env!
  :dependencies  '[[tailrecursion/boot.task   "2.1.2"]
                   [tailrecursion/hoplon      "5.7.0"]
                   [markdown-clj              "0.9.41"]
                   [tailrecursion/boot.ring   "0.1.0-SNAPSHOT"]
                   [org.clojure/clojurescript "0.0-2156"]]
  :src-paths     #{"src"}
  :out-path      "resources/public")

(add-sync! (get-env :out-path) #{"resources/assets"})

(require
  '[tailrecursion.boot.task   :refer :all]
  '[tailrecursion.boot.task.ring   :refer [dev-server]]
  '[tailrecursion.hoplon.boot :refer :all])

(deftask dev
  "Build hoplon.io for local development."
  []
  (comp (watch) (hoplon {:pretty-print  true
                         :prerender     false
                         :optimizations :whitespace}) (dev-server)))

(deftask prod
  "Build hoplon.io for production deployment."
  []
  (hoplon {:optimizations :advanced}))

Add dev-server to stop Hyphenator errors


(set-env!
  :source-paths #{"src/clj" "src/cljs"}
  :resource-paths #{"resources"}
  :dependencies '[[org.clojure/test.check "0.9.0" :scope "test"]
                  [adzerk/boot-cljs "2.1.4" :scope "test"]
                  ; cljs deps
                  [org.clojure/clojurescript "1.9.946" :scope "test"]
                  [paren-soup "2.9.1" :scope "test"]
                  [mistakes-were-made "1.7.3" :scope "test"]
                  [cljsjs/codemirror "5.24.0-1" :scope "test"]
                  ; clj deps
                  [org.clojure/clojure "1.9.0-beta3"]
                  [javax.xml.bind/jaxb-api "2.3.0" :scope "test"] ; necessary for Java 9 compatibility
                  [leiningen "2.8.1" :exclusions [leiningen.search]]
                  [ring "1.6.1"]
                  [hawk "0.2.11"]
                  [play-cljs/lein-template "0.10.2"]
                  [eval-soup "1.2.3" :exclusions [org.clojure/core.async]]
                  [org.eclipse.jgit/org.eclipse.jgit "4.6.0.201612231935-r"]]
  :repositories (conj (get-env :repositories)
                  ["clojars" {:url "https://clojars.org/repo/"
                              :username (System/getenv "CLOJARS_USER")
                              :password (System/getenv "CLOJARS_PASS")}]))

(require
  '[adzerk.boot-cljs :refer [cljs]]
  '[clojure.java.io :as io])

(task-options!
  sift {:include #{#"\.jar$"}}
  pom {:project 'nightcode
       :version "2.5.2-SNAPSHOT"
       :description "An IDE for Clojure"
       :url "https://github.com/oakes/Nightcode"
       :license {"Public Domain" "http://unlicense.org/UNLICENSE"}}
  push {:repo "clojars"}
  aot {:namespace '#{nightcode.core
                     nightcode.lein}}
  jar {:main 'nightcode.core
       :manifest {"Description" "An IDE for Clojure and ClojureScript"
                  "Url" "https://github.com/oakes/Nightcode"}
       :file "project.jar"})

(deftask run []
  (comp
    (aot)
    (with-pass-thru _
      (require
        '[clojure.spec.test.alpha :refer [instrument]]
        '[nightcode.core :refer [dev-main]])
      ((resolve 'instrument))
      ((resolve 'dev-main)))))

(def jar-exclusions
  ;; the standard exclusions don't work on windows,
  ;; because we need to use backslashes
  (conj boot.pod/standard-jar-exclusions
    #"(?i)^META-INF\\[^\\]*\.(MF|SF|RSA|DSA)$"
    #"(?i)^META-INF\\INDEX.LIST$"))

(deftask build []
  (comp (aot) (pom) (uber :exclude jar-exclusions) (jar) (sift) (target)))

(deftask build-cljs []
  (comp
    (cljs :optimizations :advanced)
    (target)
    (with-pass-thru _
      (.renameTo (io/file "target/public/paren-soup.js") (io/file "resources/public/paren-soup.js"))
      (.renameTo (io/file "target/public/codemirror.js") (io/file "resources/public/codemirror.js")))))

(deftask local []
  (set-env! :resource-paths #{"src/clj" "src/cljs"})
  (comp (pom) (jar) (install)))

(deftask deploy []
  (set-env! :resource-paths #{"src/clj" "src/cljs"})
  (comp (pom) (jar) (push)))

(set-env!
  :source-paths #{"src/clj" "src/cljs"}
  :resource-paths #{"resources"}
  :dependencies '[[org.clojure/test.check "0.9.0" :scope "test"]
                  [adzerk/boot-cljs "2.1.4" :scope "test"]
                  ; cljs deps
                  [org.clojure/clojurescript "1.9.946" :scope "test"]
                  [paren-soup "2.9.1" :scope "test"]
                  [mistakes-were-made "1.7.3" :scope "test"]
                  [cljsjs/codemirror "5.24.0-1" :scope "test"]
                  ; clj deps
                  [org.clojure/clojure "1.9.0-beta3"]
                  [javax.xml.bind/jaxb-api "2.3.0" :scope "test"] ; necessary for Java 9 compatibility
                  [leiningen "2.8.1" :exclusions [leiningen.search]]
                  [ring "1.6.1"]
                  [hawk "0.2.11"]
                  [play-cljs/lein-template "0.10.2"]
                  [eval-soup "1.2.3" :exclusions [org.clojure/core.async]]
                  [org.eclipse.jgit/org.eclipse.jgit "4.6.0.201612231935-r"]]
  :repositories (conj (get-env :repositories)
                  ["clojars" {:url "https://clojars.org/repo/"
                              :username (System/getenv "CLOJARS_USER")
                              :password (System/getenv "CLOJARS_PASS")}]))

(require
  '[adzerk.boot-cljs :refer [cljs]]
  '[clojure.java.io :as io])

(task-options!
  sift {:include #{#"\.jar$"}}
  pom {:project 'nightcode
       :version "2.5.2"
       :description "An IDE for Clojure"
       :url "https://github.com/oakes/Nightcode"
       :license {"Public Domain" "http://unlicense.org/UNLICENSE"}}
  push {:repo "clojars"}
  aot {:namespace '#{nightcode.core
                     nightcode.lein}}
  jar {:main 'nightcode.core
       :manifest {"Description" "An IDE for Clojure and ClojureScript"
                  "Url" "https://github.com/oakes/Nightcode"}
       :file "project.jar"})

(deftask run []
  (comp
    (aot)
    (with-pass-thru _
      (require
        '[clojure.spec.test.alpha :refer [instrument]]
        '[nightcode.core :refer [dev-main]])
      ((resolve 'instrument))
      ((resolve 'dev-main)))))

(def jar-exclusions
  ;; the standard exclusions don't work on windows,
  ;; because we need to use backslashes
  (conj boot.pod/standard-jar-exclusions
    #"(?i)^META-INF\\[^\\]*\.(MF|SF|RSA|DSA)$"
    #"(?i)^META-INF\\INDEX.LIST$"))

(deftask build []
  (comp (aot) (pom) (uber :exclude jar-exclusions) (jar) (sift) (target)))

(deftask build-cljs []
  (comp
    (cljs :optimizations :advanced)
    (target)
    (with-pass-thru _
      (.renameTo (io/file "target/public/paren-soup.js") (io/file "resources/public/paren-soup.js"))
      (.renameTo (io/file "target/public/codemirror.js") (io/file "resources/public/codemirror.js")))))

(deftask local []
  (set-env! :resource-paths #{"src/clj" "src/cljs"})
  (comp (pom) (jar) (install)))

(deftask deploy []
  (set-env! :resource-paths #{"src/clj" "src/cljs"})
  (comp (pom) (jar) (push)))

Increment version number

Increment version number


(set-env!
  :resource-paths #{"src"}
  :source-paths #{"test"}
  :dependencies   '[[org.clojure/clojure       "1.7.0"  :scope "provided"]
                    [adzerk/boot-test          "1.1.0"  :scope "test"]
                    [pandeiro/boot-http        "0.7.0"  :scope "test"]
                    [org.clojure/clojurescript "1.7.228" :scope "test"]
                    [ns-tracker                "0.3.0"  :scope "test"]])

(require '[adzerk.boot-test   :refer [test]]
         '[adzerk.boot-cljs   :refer [cljs]]
         '[pandeiro.boot-http :refer [serve]])

(def +version+ "1.7.228-3-SNAPSHOT")

(task-options!
  pom {:project     'adzerk/boot-cljs
       :version     +version+
       :description "Boot task to compile ClojureScript applications."
       :url         "https://github.com/adzerk/boot-cljs"
       :scm         {:url "https://github.com/adzerk/boot-cljs"}
       :license     {"EPL" "http://www.eclipse.org/legal/epl-v10.html"}})

(deftask run-tests
  [O optimizations   LEVEL kw  "Compiler optimization level."
   j junit-output-to JUNIT str "Test report destination."]
  (comp (serve)
        (cljs :optimizations (or optimizations :whitespace))
        (test :namespaces #{'adzerk.boot-cljs-test 'adzerk.boot-cljs.util-test}
              :junit-output-to junit-output-to)))

(deftask build []
  (comp
   (pom)
   (jar)
   (install)))

(deftask dev []
  (comp
    (watch)
    (build)
    (repl :server true)))

(deftask deploy []
  (comp
   (build)
   (push :repo "clojars" :gpg-sign (not (.endsWith +version+ "-SNAPSHOT")))))

(set-env!
  :resource-paths #{"src"}
  :source-paths #{"test"}
  :dependencies   '[[org.clojure/clojure       "1.7.0"  :scope "provided"]
                    [adzerk/boot-test          "1.1.0"  :scope "test"]
                    [pandeiro/boot-http        "0.7.0"  :scope "test"]
                    [org.clojure/clojurescript "1.7.228" :scope "test"]
                    [ns-tracker                "0.3.0"  :scope "test"]])

(require '[adzerk.boot-test   :refer [test]]
         '[adzerk.boot-cljs   :refer [cljs]]
         '[pandeiro.boot-http :refer [serve]])

(def +version+ "2.0.0-SNAPSHOT")

(task-options!
  pom {:project     'adzerk/boot-cljs
       :version     +version+
       :description "Boot task to compile ClojureScript applications."
       :url         "https://github.com/adzerk/boot-cljs"
       :scm         {:url "https://github.com/adzerk/boot-cljs"}
       :license     {"EPL" "http://www.eclipse.org/legal/epl-v10.html"}})

(deftask run-tests
  [O optimizations   LEVEL kw  "Compiler optimization level."
   j junit-output-to JUNIT str "Test report destination."]
  (comp (serve)
        (cljs :optimizations (or optimizations :whitespace))
        (test :namespaces #{'adzerk.boot-cljs-test 'adzerk.boot-cljs.util-test}
              :junit-output-to junit-output-to)))

(deftask build []
  (comp
   (pom)
   (jar)
   (install)))

(deftask dev []
  (comp
    (watch)
    (build)
    (repl :server true)))

(deftask deploy []
  (comp
   (build)
   (push :repo "clojars" :gpg-sign (not (.endsWith +version+ "-SNAPSHOT")))))

Bump version: 2.0.0 :cake:

Bump version: 2.0.0 :cake: