<commit_before>(ns joy.ch14
  (:require [clojure.data :as d]
            [clojure.edn :as edn]
            [clojure.set :as sql]))

(rand-int 1024)
(+ (rand-int 100) (rand-int 100))

(def ascii (map char (range 65 (+ 65 26))))
ascii

(defn rand-str [sz alphabet]
  (apply str (repeatedly sz #(rand-nth alphabet))))

(rand-str 10 ascii)

(def rand-sym #(symbol (rand-str %1 %2)))
(def rand-key #(keyword (rand-str %1 %2)))

(rand-key 10 ascii)
(rand-sym 10 ascii)

(defn rand-vec [& generators]
  (into [] (map #(%) generators)))
(rand-vec #(rand-sym 5 ascii)
          #(rand-key 10 ascii)
          #(rand-int 1024))

(defn rand-map [sz kgen vgen]
  (into {}
       (repeatedly sz #(rand-vec kgen vgen))))

(rand-map 3 #(rand-key 5 ascii) #(rand-int 100))

(assert (= [1 2 3] (conj [1 2] 3)))

(d/diff [1 2 3] [1 2 4])

(defn filter-rising [segments]
  (clojure.set/select
   (fn [{:keys [p1 p2]}]
     (> 0
        (/ (- (p2 0) (p1 0))
           (- (p2 1) (p1 1)))))
   segments))

(filter-rising #{{:p1 [0 0] :p2 [1 1]}
                 {:p1 [4 15] :p2 [3 21]}})

#inst "1969-08-18"

(defn convert [context descriptor]
  (reduce (fn [result [mag unit]]
            (+ result
               (let [val (get context unit)]
                 (if (vector? val)
                   (* mag (convert context val))
                   (* mag val)))))
          0
          (partition 2 descriptor)))

(def distance-reader
  (partial convert
           {:m 1
            :km 1000
            :cm 1/100
            :mm [1/10 :cm]}))

;;#unit/legth [1 :km]

(def time-reader
  (partial convert
           {:sec 1
            :min 60
            :hr [60 :min]
            :day [24 :hr]}))

(binding [*data-readers* {'ch14/time #'joy.ch14/time-reader}]
  (read-string "#ch14/time [1 :min 30 :sec]"))

(binding [*default-data-reader-fn* #(-> {:tag %1 :payload %2})]
  (read-string "#nope [:doesnt-exist]"))

#_(edn/read-string "#uuid ")

(edn/read-string "42")

#_(edn/read-string "#ch14/time [1 :min 30 :sec]")

(def T ('ch14/time #'joy.ch14/time-reader))

#_(edn/read-string {:readers T} "#ch14/time [1 :min 30 :sec]")

(edn/read-string {:readers T, :default vector} "#what/the :huh?")

;; 14.3
(defn valid? [event]
  (boolean (:result event)))

(valid? {})
(valid? {:result 42})

(defn effect [{:keys [ab h] :or {ab 0, h 0}} event]
  (let [ab (inc ab)
        h (if (= :hit (:result event)) (inc h) h)
        avg (double (/ h ab))]
    {:ab ab :h h :avg avg}))

(effect {} {:result :hit})

(effect {:ab 599 :h 180}
        {:result :out})

(defn apply-effect [state event]
  (if (valid? event) (effect state event) state))

(apply-effect {:ab 600 :h 180}
              {:result :hit})

(def effect-all #(reduce apply-effect %1 %2))

(effect-all {:ab 0 :h 0}
            [{:result :hit}
             {:result :out}
             {:result :hit}
             {:result :out}])

(def events
  (repeatedly 100
              (fn [] (rand-map 1
                              #(-> :result)
                              #(if (<  (rand-int 10) 3)
                                 :hit :out)))))

(effect-all {} events)
(effect-all {} (take 50 events))

(def fx-timeline #(reductions apply-effect %1 %2))

(fx-timeline {} (take 3 events))<commit_msg>part way through ch 14.3<commit_after>(ns joy.ch14
  (:require [clojure.data :as d]
            [clojure.edn :as edn]
            [clojure.set :as sql]))

(rand-int 1024)
(+ (rand-int 100) (rand-int 100))

(def ascii (map char (range 65 (+ 65 26))))
ascii

(defn rand-str [sz alphabet]
  (apply str (repeatedly sz #(rand-nth alphabet))))

(rand-str 10 ascii)

(def rand-sym #(symbol (rand-str %1 %2)))
(def rand-key #(keyword (rand-str %1 %2)))

(rand-key 10 ascii)
(rand-sym 10 ascii)

(defn rand-vec [& generators]
  (into [] (map #(%) generators)))
(rand-vec #(rand-sym 5 ascii)
          #(rand-key 10 ascii)
          #(rand-int 1024))

(defn rand-map [sz kgen vgen]
  (into {}
       (repeatedly sz #(rand-vec kgen vgen))))

(rand-map 3 #(rand-key 5 ascii) #(rand-int 100))

(assert (= [1 2 3] (conj [1 2] 3)))

(d/diff [1 2 3] [1 2 4])

(defn filter-rising [segments]
  (clojure.set/select
   (fn [{:keys [p1 p2]}]
     (> 0
        (/ (- (p2 0) (p1 0))
           (- (p2 1) (p1 1)))))
   segments))

(filter-rising #{{:p1 [0 0] :p2 [1 1]}
                 {:p1 [4 15] :p2 [3 21]}})

#inst "1969-08-18"

(defn convert [context descriptor]
  (reduce (fn [result [mag unit]]
            (+ result
               (let [val (get context unit)]
                 (if (vector? val)
                   (* mag (convert context val))
                   (* mag val)))))
          0
          (partition 2 descriptor)))

(def distance-reader
  (partial convert
           {:m 1
            :km 1000
            :cm 1/100
            :mm [1/10 :cm]}))

;;#unit/legth [1 :km]

(def time-reader
  (partial convert
           {:sec 1
            :min 60
            :hr [60 :min]
            :day [24 :hr]}))

(binding [*data-readers* {'ch14/time #'joy.ch14/time-reader}]
  (read-string "#ch14/time [1 :min 30 :sec]"))

(binding [*default-data-reader-fn* #(-> {:tag %1 :payload %2})]
  (read-string "#nope [:doesnt-exist]"))

#_(edn/read-string "#uuid ")

(edn/read-string "42")

#_(edn/read-string "#ch14/time [1 :min 30 :sec]")

(def T ('ch14/time #'joy.ch14/time-reader))

#_(edn/read-string {:readers T} "#ch14/time [1 :min 30 :sec]")

(edn/read-string {:readers T, :default vector} "#what/the :huh?")

;; 14.3
(defn valid? [event]
  (boolean (:result event)))

(valid? {})
(valid? {:result 42})

(defn effect [{:keys [ab h] :or {ab 0, h 0}} event]
  (let [ab (inc ab)
        h (if (= :hit (:result event)) (inc h) h)
        avg (double (/ h ab))]
    {:ab ab :h h :avg avg}))

(effect {} {:result :hit})

(effect {:ab 599 :h 180}
        {:result :out})

(defn apply-effect [state event]
  (if (valid? event) (effect state event) state))

(apply-effect {:ab 600 :h 180}
              {:result :hit})

(def effect-all #(reduce apply-effect %1 %2))

(effect-all {:ab 0 :h 0}
            [{:result :hit}
             {:result :out}
             {:result :hit}
             {:result :out}])

(def events
  (repeatedly 100
              (fn [] (rand-map 1
                              #(-> :result)
                              #(if (<  (rand-int 10) 3)
                                 :hit :out)))))

(effect-all {} events)
(effect-all {} (take 50 events))

(def fx-timeline #(reductions apply-effect %1 %2))

(fx-timeline {} (take 3 events))

(def PLAYERS #{{:player "Nick" :ability 32} {:player "Matt" :ability 26} {:player "Ryan" :ability 19}})

(defn lookup [db name]
  (first (sql/select #(= name (:player %)) db)))

(lookup PLAYERS "Nick")

(defn update-stats [db event]
  (let [player (lookup db (:player event))
        less-db (sql/difference db #{player})]
    (conj less-db (merge player (effect player event)))))

(update-stats PLAYERS {:player "Nick" :result :hit})

(defn commit-event [db event]
  (dosync (alter db update-stats event)))

(commit-event (ref PLAYERS) {:player "Nick" :result :hit})

(defn rand-event [{ability :ability}]
  (let [able (numerator ability)
        max (denominator ability)]
    (rand-map 1 #(-> :result) #(if
                                  (< (rand-int max) able)
                                :hit :out))))

(defn rand-events [total player]
  (take total (repeatedly #(assoc
                               (rand-event player) :player
                               (:player player)))))

(rand-events 3 {:player "Nick" :ability 32/100})

(def agent-for-player
  (memoize (fn [player-name]
             (-> (agent [])
                 (set-error-handler! #(println "ERROR:   " %1 %2))
                 (set-error-mode! :fail)))))
(defn feed [db event]
  (let [a (agent-for-player (:player event))]
    (send a
          (fn [state]
            (commit-event db event
                          (conj state event))))))
{'fraction_non_alphanumeric': 0.18757921419518378, 'fraction_numerical': 0.04512040557667934, 'mean_word_length': 2.107916502560063, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3465023', 'n_tokens_mistral': 3228, 'n_tokens_neox': 2886, 'n_words': 875}