Skip to content

Instantly share code, notes, and snippets.

(defn added-items [new-items {:bag/keys [id owner items capacity]}]
(assert capacity)
(let [existing-items items
by-base (volatile! (group-by :item/base existing-items))
by-index (volatile! (-> (group-by :item/index existing-items)
(update-vals peek)))
incoming-items (volatile! new-items)]
(loop [items-to-process @incoming-items
acc []]
(let [{:item/keys [base quantity index expires-at] :as incoming-item} (first items-to-process)
(ns app.util.rand
(:require #?(:clj [fastmath.random :as random])
[malli.core :as m]
#?(:clj [fastmath.core :as math])))
(defn weighted-randomizer
[weights & {:keys [rng] :or {rng #?(:clj (random/rng :jdk)
:cljs nil)}}]
(let [N (count weights)
avg (/ (reduce + weights) N)
@nivekuil
nivekuil / poker.cljc
Created September 10, 2024 04:02
poker.cljc
(ns game.poker
(:require [meander.epsilon :as mean]
[hyperfiddle.rcf :as rcf]))
(defn match [hand]
(mean/find
hand
(mean/scan {::rank ?x} ..4)
::Quad
@nivekuil
nivekuil / fasthash.cljs
Created January 11, 2024 13:42
fast hash types
(deftype IdAttr [id attr ^:mutable ^number _hasheq]
IEquiv
(-equiv
[this that]
(boolean
(or (identical? this that)
(and (instance? IdAttr that)
(= id (.-id ^IdAttr that))
(= attr (.-attr ^IdAttr that))))))
@nivekuil
nivekuil / flowdiff.cljc
Last active January 9, 2024 06:01
missionary flow managing effects from diffs
;; Essentially we want to make a tee, passing through diffs for rendering but also taking advantage of missionary's supervision
;; for mount/unmount effects. Thus the diffs have to have a concept of corresponding to an identity. 3rd try is the charm?
(def sender (y/observe (fn [!] (def send! !) #(prn "sender dead"))))
(defn boot [flow]((y/reduce {}nil flow) prn prn))
(def !state (atom 0))
(def flow (y/ap
(let [diff (y/?= sender)
res (y/?> (y/observe (fn[!]
(dom/div
(let [!cs (atom [0 1 2 3 4]) cs (e/watch !cs)]
(e/for [c cs]
(ui/button
(e/fn [] (reset! !cs (vec (remove #{c} cs))))
(dom/props {:class "fade-in"})
(dom/text "REMOVE " c)))
(ui/button
(e/fn [] (swap! !cs conj (inc (peek cs))))
(dom/text "ADD"))))
@nivekuil
nivekuil / gist:f3698345ac51f6adf8039b475288461a
Created October 14, 2023 18:59
clojurescript relative time
#?(:cljs (def relative-time-formatter
(js/Intl.RelativeTimeFormat. "en" #js{:numeric "auto"})))
(defn timeago [time]
#?(:clj (str time)
:cljs (let [seconds-ago (t/seconds (t/between (t/now) time))
[divide unit] (condp #(> %1 (abs %2)) seconds-ago
60 [1 "second"]
3600 [60 "minute"]
86400 [3600 "hour"]
[86460 "day"])]
@nivekuil
nivekuil / animated.clj
Last active October 6, 2023 18:22
animated value in electric
(def timer*
(->> e/<clock ;; produce time
(y/sample e/-get-system-time-ms) ;; label time
(y/reductions (fn([] {:t (e/-get-system-time-ms) :dt 0})
([acc next] ;; produce difference
{:t (e/-get-system-time-ms)
:dt (- next (:t acc))})))))
(defn pid [<setpoint {:keys [<force error-threshold k <clock]
:or {<force (y/watch (atom 10))
@nivekuil
nivekuil / x.clj
Created September 4, 2023 19:02
electric odoyle
(ns app.todo-list
(:require contrib.str
[hyperfiddle.electric :as e]
[hyperfiddle.electric-dom2 :as dom]
[hyperfiddle.electric-ui4 :as ui]
[odoyle.rules :as o]
[missionary.core :as y])
#?(:clj (:import [clojure.lang IFn IDeref])))
(defn rule->subject [*s whats then]
@nivekuil
nivekuil / randomizer.cljc
Created January 10, 2023 10:41
weighted randomizer
;; port of https://blog.bruce-hill.com/a-faster-weighted-random-choice
(defn weighted-randomizer [weights]
(let [N (count weights)
avg (/ (reduce + weights) N)
aliases (volatile! (vec (repeat N [1 nil])))
{:keys [smalls bigs]} (->> (map-indexed
(fn [idx weight]
(if (< weight avg)
[[idx (/ weight avg)] :smalls]