<commit_before>(ns viz.core
  (:require [quil.core :as q :include-macros true]
            [quil.middleware :as m]
            [viz.forest :as forest]
            [viz.grid :as grid]
            [viz.ghost :as ghost]
            [goog.string :as gstring]
            [goog.string.format]
            ;[gil.core :as gil]
            ))

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

(def window-size [ (- (aget js/document "documentElement" "clientWidth") 20)
                   (- (aget js/document "documentElement" "clientHeight") 20)
                   ])
(def window-half-size (apply vector (map #(float (/ %1 2)) window-size)))

(defn- new-state []
  {:frame-rate 30
   :exit-wait-frames 40
   :tail-length 40
   :frame 0
   :gif-seconds 0
   :grid-width 60 ; from the center
   :ghost (-> (ghost/new-ghost grid/euclidean)
              (ghost/new-active-node [0 0])
              )
   })

(defn- curr-second [state]
  (float (/ (:frame state) (:frame-rate state))))

(defn- grid-size [state]
  (let [h (int (* (window-size 1)
                  (float (/ (:grid-width state) (window-size 0)))))]
             [(:grid-width state) h]))

(defn- positive [n] (if (> 0 n) (- n) n))

(defn- spawn-chance [state]
  (let [period-seconds 1
        period-frames (* (:frame-rate state) period-seconds)]
  (if (zero? (rem (:frame state) period-frames))
    1 100)
    ))

  ;(let [period-seconds 1
  ;      rad-per-second (float (/ (/ Math/PI 2) period-seconds))
  ;      rad (* rad-per-second (curr-second state))
  ;      chance-raw (positive (q/sin rad))
  ;      ]
  ;    (if (> chance-raw 0.97) 3 50)
  ;  ))


(defn- mk-poss-fn [state]
  (let [chance (spawn-chance state)]
    (fn [pos adj-poss]
      (if (zero? (rand-int chance))
        adj-poss
        (take 1 (shuffle adj-poss))))
    ))

(defn setup []
  (let [state (new-state)]
    (q/frame-rate (:frame-rate state))
    state))

(defn- scale [state xy]
  (map-indexed #(* %2 (float (/ (window-half-size %1)
                                ((grid-size state) %1)))) xy))

; each bound is a position vector
(defn- in-bounds? [min-bound max-bound pos]
  (let [pos-k (keep-indexed #(let [mini (min-bound %1)
                                   maxi (max-bound %1)]
                               (when (and (>= %2 mini) (<= %2 maxi)) %2)) pos)]
    (= (count pos) (count pos-k))))

(defn- quil-bounds [state buffer]
  (let [[w h] (apply vector (map #(- % buffer) (grid-size state)))]
    [[(- w) (- h)] [w h]]))

(defn- ghost-incr [state]
  (assoc state :ghost
         (ghost/filter-active-nodes (ghost/incr (:ghost state) (mk-poss-fn state))
                                    #(let [[minb maxb] (quil-bounds state 2)]
                                       (in-bounds? minb maxb (:pos %1))))))

(defn- ghost-expire-roots [state]
  (if-not (< (:tail-length state) (:frame state)) state
    (update-in state [:ghost] ghost/remove-roots)))

(defn- maybe-exit [state]
  (if (empty? (get-in state [:ghost :active-node-ids]))
    (if (zero? (:exit-wait-frames state)) (new-state)
      (update-in state [:exit-wait-frames] dec))
    state))

(defn update-state [state]
  (-> state
      (ghost-incr)
      (ghost-expire-roots)
      (update-in [:frame] inc)
      (maybe-exit)))

(defn- ellipse [state pos size] ; size is [w h]
  (let [scaled-pos (scale state pos)
        scaled-size (map int (scale state size))]
    (apply q/ellipse (concat scaled-pos scaled-size))))

(defn draw-state [state]
  ; Clear the sketch by filling it with light-grey color.
  (q/background 0xFFFFFFFF)
  (q/with-translation [(/ (window-size 0) 2)
                       (/ (window-size 1) 2)]
    (let [lines (forest/lines (get-in state [:ghost :forest]))
          leaves (forest/leaves (get-in state [:ghost :forest]))
          active (ghost/active-nodes (:ghost state))
          roots (forest/roots (get-in state [:ghost :forest]))
          ]

      (q/stroke 0xFF000000)
      (doseq [line lines]
        (apply q/line (apply concat (map #(scale state %) line))))

      (q/stroke 0xFF000000)
      (q/fill 0xFFFFFFFF)
      (doseq [leef leaves]
        (let [pos (:pos leef)]
          (ellipse state pos [0.5 0.5])
          ))

      (q/stroke 0xFF000000)
      (q/fill 0xFF000000)
      (doseq [active-node active]
        (let [pos (:pos active-node)]
          (ellipse state pos [0.5 0.5])
          ))

      ))

    ;(when-not (zero? (:gif-seconds state))
    ;  (let [anim-frames (* (:gif-seconds state) (:frame-rate state))]
    ;    (gil/save-animation "quil.gif" anim-frames 0)
    ;    (when (> (:frame state) anim-frames) (q/exit))))

    ;(q/text (clojure.string/join
    ;          "\n"<commit_msg>a little somethin I dunno what<commit_after>(ns viz.core
  (:require [quil.core :as q :include-macros true]
            [quil.middleware :as m]
            [viz.forest :as forest]
            [viz.grid :as grid]
            [viz.ghost :as ghost]
            [goog.string :as gstring]
            [goog.string.format]
            ;[gil.core :as gil]
            ))

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

(def window-size [ (- (aget js/document "documentElement" "clientWidth") 20)
                   (- (aget js/document "documentElement" "clientHeight") 20)
                   ])
(def window-half-size (apply vector (map #(float (/ %1 2)) window-size)))

(defn- new-state []
  {:frame-rate 30
   :exit-wait-frames 40
   :tail-length 40
   :frame 0
   :gif-seconds 0
   :grid-width 60 ; from the center
   :ghost (-> (ghost/new-ghost grid/euclidean)
              (ghost/new-active-node [0 0])
              )
   })

(defn- curr-second [state]
  (float (/ (:frame state) (:frame-rate state))))

(defn- grid-size [state]
  (let [h (int (* (window-size 1)
                  (float (/ (:grid-width state) (window-size 0)))))]
             [(:grid-width state) h]))

(defn- positive [n] (if (> 0 n) (- n) n))

(defn- spawn-chance [state]
  (let [period-seconds 1
        period-frames (* (:frame-rate state) period-seconds)]
  (if (zero? (rem (:frame state) period-frames))
    1 100)
    ))

  ;(let [period-seconds 1
  ;      rad-per-second (float (/ (/ Math/PI 2) period-seconds))
  ;      rad (* rad-per-second (curr-second state))
  ;      chance-raw (positive (q/sin rad))
  ;      ]
  ;    (if (> chance-raw 0.97) 3 50)
  ;  ))


(defn- mk-poss-fn [state]
  (let [chance (spawn-chance state)]
    (fn [pos adj-poss]
      (if (zero? (rand-int chance))
        adj-poss
        (take 1 (shuffle adj-poss))))
    ))

(defn setup []
  (let [state (new-state)]
    (q/frame-rate (:frame-rate state))
    state))

(defn- scale [state xy]
  (map-indexed #(* %2 (float (/ (window-half-size %1)
                                ((grid-size state) %1)))) xy))

; each bound is a position vector
(defn- in-bounds? [min-bound max-bound pos]
  (let [pos-k (keep-indexed #(let [mini (min-bound %1)
                                   maxi (max-bound %1)]
                               (when (and (>= %2 mini) (<= %2 maxi)) %2)) pos)]
    (= (count pos) (count pos-k))))

(defn- quil-bounds [state buffer]
  (let [[w h] (apply vector (map #(- % buffer) (grid-size state)))]
    [[(- w) (- h)] [w h]]))

(defn- ghost-incr [state]
  (assoc state :ghost
         (ghost/filter-active-nodes (ghost/incr (:ghost state) (mk-poss-fn state))
                                    #(let [[minb maxb] (quil-bounds state 2)]
                                       (in-bounds? minb maxb (:pos %1))))))

(defn- ghost-expire-roots [state]
  (if-not (< (:tail-length state) (:frame state)) state
    (update-in state [:ghost] ghost/remove-roots)))

(defn- maybe-exit [state]
  (if (empty? (get-in state [:ghost :active-node-ids]))
    (if (zero? (:exit-wait-frames state)) (new-state)
      (update-in state [:exit-wait-frames] dec))
    state))

(defn update-state [state]
  (-> state
      (ghost-incr)
      (ghost-expire-roots)
      (update-in [:frame] inc)
      (maybe-exit)))

(defn- ellipse [state pos size] ; size is [w h]
  (let [scaled-pos (scale state pos)
        scaled-size (map int (scale state size))]
    (apply q/ellipse (concat scaled-pos scaled-size))))

(defn draw-state [state]
  ; Clear the sketch by filling it with light-grey color.
  (q/background 0xFFFFFFFF)
  (q/with-translation [(/ (window-size 0) 2)
                       (/ (window-size 1) 2)]
    (let [lines (forest/lines (get-in state [:ghost :forest]))
          leaves (forest/leaves (get-in state [:ghost :forest]))
          active (ghost/active-nodes (:ghost state))
          roots (forest/roots (get-in state [:ghost :forest]))
          ]

      (q/stroke 0xFF000000)
      (doseq [line lines]
        (apply q/line (apply concat (map #(scale state %) line))))

      (q/stroke 0xFF000000)
      (q/fill 0xFFFFFFFF)
      (doseq [leef leaves]
        (let [pos (:pos leef)]
          (ellipse state pos [0.3 0.3])
          ))

      (q/stroke 0xFF000000)
      (q/fill 0xFF000000)
      (doseq [active-node active]
        (let [pos (:pos active-node)]
          (ellipse state pos [0.35 0.35])
          ))

      ))

    ;(when-not (zero? (:gif-seconds state))
    ;  (let [anim-frames (* (:gif-seconds state) (:frame-rate state))]
    ;    (gil/save-animation "quil.gif" anim-frames 0)
    ;    (when (> (:frame state) anim-frames) (q/exit))))

    ;(q/text (clojure.string/join
    ;          "\n"
{'fraction_non_alphanumeric': 0.18628389154704944, 'fraction_numerical': 0.018926103136629454, 'mean_word_length': 2.085958005249344, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1155147', 'n_tokens_mistral': 3585, 'n_tokens_neox': 3266, 'n_words': 872}