(ns c.test (:use [clojure.core.match :only (match)]) (:require [clojure.string :as str] [crux.api :as crux] [clojure.set :as set]) (:import (crux.api ICruxAPI))) (def ^ICruxAPI node (crux/start-node {:crux.node/topology :crux.standalone/topology :crux.node/kv-store "crux.kv.memdb/kv" :crux.kv/db-dir "data/db-dir-1" :crux.standalone/event-log-dir "data/eventlog-1" :crux.standalone/event-log-kv-store "crux.kv.memdb/kv"})) (defn read-rules [file] (with-open [rdr (clojure.java.io/reader file)] (reduce conj [] (map #(vec (.split % " ")) (line-seq rdr))))) (defn parse-deps [d] (let [escape-coma (map #(re-find #"[^,]+" %) d) split-or (map #(if (str/includes? % "|") (vec (str/split % #"[|]")) %) escape-coma)] (vector (vec split-or)))) (defn match-rule [v] (match v [target "<="] {:crux.db/id (keyword target) :target target :deps nil} [target "<=" & deps] {:crux.db/id (keyword target) :target target :deps (parse-deps deps)})) (defn parse-rules [rules] (map match-rule rules)) (parse-rules (read-rules "resources/rules.txt")) => ({:crux.db/id :source0, :target "source0", :deps nil} {:crux.db/id :source1, :target "source1", :deps [["source0"]]} {:crux.db/id :source01, :target "source01", :deps [["source0" "source1"]]} {:crux.db/id :source2, :target "source2", :deps [["source0" "source5"]]} {:crux.db/id :source02, :target "source02", :deps [["source1"]]} {:crux.db/id :source3, :target "source3", :deps [["source1" "source2"]]} {:crux.db/id :source03, :target "source03", :deps [["source01"]]} {:crux.db/id :source001, :target "source001", :deps [["source3" "source01" ["source02" "source2"]]]}) (defn submit-crux [targets] (doseq [t targets] (crux/submit-tx node [[:crux.tx/put t]]))) (submit-crux (parse-rules (read-rules "resources/rules.txt"))) (defn find-all-targets [] (crux/q (crux/db node) '{:find [t d] :where [[id :target t] [id :deps d]]})) (find-all-targets) => #{["source02" ["source1"]] ["source3" ["source1" "source2"]] ["source03" ["source01"]] ["source1" ["source0"]] ["source2" ["source0" "source5"]] ["source0" nil] ["source01" ["source0" "source1"]] ["source001" ["source3" "source01" ["source02" "source2"]]]} (defn only-computable [targets] (let [t (set (map first targets)) d (set (flatten (map second targets))) not-computable (set (remove nil? (set/difference d t)))] (filter #(empty? (-> % second flatten set (set/intersection not-computable))) targets))) (only-computable (find-all-targets)) => (["source02" ["source1"]] ["source3" ["source1" "source2"]] ["source03" ["source01"]] ["source1" ["source0"]] ["source0" nil] ["source01" ["source0" "source1"]] ["source001" ["source3" "source01" ["source02" "source2"]]])