Skip to content

Instantly share code, notes, and snippets.

@tonsky
Created January 17, 2019 17:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tonsky/2044470ea37076a13deeb65bda38864d to your computer and use it in GitHub Desktop.
Save tonsky/2044470ea37076a13deeb65bda38864d to your computer and use it in GitHub Desktop.
(ns datomicdemo.core
(:require
[clojure.edn]
[clojure.string :as str]
[datomic.api :as d]))
(def url "datomic:free://localhost:4334/datomicdemo")
(d/create-database url)
(def conn (d/connect url))
(d/q '[:find ?e ?i
:where [?e :db/ident ?i]]
(d/db conn))
@(d/transact conn
[{:db/ident :location/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/unique :db.unique/identity}
{:db/ident :category/name
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db/unique :db.unique/identity}
{:db/ident :booking/id
:db/valueType :db.type/long
:db/cardinality :db.cardinality/one
:db/unique :db.unique/identity}
{:db/ident :booking/license-plate
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one}
{:db/ident :booking/category
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one}
{:db/ident :booking/checkin
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "ref to location"}
{:db/ident :booking/checkout
:db/valueType :db.type/ref
:db/cardinality :db.cardinality/one
:db/doc "ref to location"}
{:db/ident :booking/status
:db/valueType :db.type/keyword
:db/cardinality :db.cardinality/one}
{:db/ident :booking/checkin-datetime
:db/valueType :db.type/instant
:db/cardinality :db.cardinality/one}
{:db/ident :booking/checkout-datetime
:db/valueType :db.type/instant
:db/cardinality :db.cardinality/one}])
(clojure.edn/read-string "[156647,\"64-SO-17 | Corsica \",\"Active Plus\",\"Milan Malpensa\",\"Milan Malpensa\",\"closing\",\"2018-06-30T11:30:00\",\"2018-07-10T11:00:00\"]")
(def lines (-> (slurp "bookings.csv")
(str/split #"\n")
next))
(defn parse-line [line]
(let [[id plate category checkin checkout status checkin-time checkout-time] (clojure.edn/read-string (str "[" line "]"))
status (keyword status)
checkin-time (clojure.instant/read-instant-date checkin-time)
checkout-time (clojure.instant/read-instant-date checkout-time)]
{:booking/id id
:booking/license-plate plate
:booking/category category
:booking/checkin checkin
:booking/checkout checkout
:booking/status status
:booking/checkin-datetime checkin-time
:booking/checkout-datetime checkout-time}))
(parse-line "164541,\"60-RC-87\",\"Active M\",\"Lisbon\",\"Lisbon\",\"closing\",\"2018-08-20T15:30:00\",\"2018-08-29T11:00:00\"")
(def parsed-lines
(for [line lines]
(parse-line line)))
(doseq [cat (into #{} (map :booking/category parsed-lines))]
@(d/transact conn [{:category/name cat}]))
(doseq [loc (into #{}
(concat (map :booking/checkin parsed-lines)
(map :booking/checkout parsed-lines)))]
@(d/transact conn [{:location/name loc}]))
(doseq [line parsed-lines]
@(d/transact conn [
(assoc line
:booking/category (d/entid (d/db conn) [:category/name (:booking/category line)])
:booking/checkin [:location/name (:booking/checkin line)]
:booking/checkout [:location/name (:booking/checkout line)])
]))
(def plates
(d/q '[:find [?plate ...]
:in $ ?from ?till
:where [?ent :booking/checkin-datetime ?s]
[?ent :booking/checkout-datetime ?e]
(not
(or-join [?from ?till ?s ?e]
(and [(< ?s ?from)] [(< ?from ?e)])
(and [(< ?s ?till)] [(< ?till ?e)])
(and [(< ?from ?s)] [(< ?s ?till)])
(and [(< ?from ?e)] [(< ?e ?till)])))
[?ent :booking/license-plate ?plate]]
(d/db conn)
#inst "2018-10-18"
#inst "2018-10-22"))
(def plates2
(d/q '[:find [?plate ...]
:in $ ?from ?till
:where [?ent :booking/checkin-datetime ?s]
[?ent :booking/checkout-datetime ?e]
[?ent :booking/checkout [:location/name "Lisbon"]]
(or-join [?s ?e ?from ?till] [(> ?s ?from)] [(> ?from ?e)])
(or-join [?s ?e ?from ?till] [(> ?s ?till)] [(> ?till ?e)])
(or-join [?s ?e ?from ?till] [(> ?from ?s)] [(> ?s ?till)])
(or-join [?s ?e ?from ?till] [(> ?from ?e)] [(> ?e ?till)])
[?ent :booking/license-plate ?plate]]
(d/db conn)
#inst "2018-10-18"
#inst "2018-10-22"))
(count plates)
(count plates2)
((set plates) "17-RA-67")
(let [tuples (d/q '[:find ?plate ?e ?ln
:in $ ?from ?till
:where [?ent :booking/checkout-datetime ?e]
[(< ?e ?from)]
[?ent :booking/license-plate ?plate]
[?ent :booking/checkout ?l]
[?l :location/name ?ln]]
(d/db conn)
#inst "2018-10-18"
#inst "2018-10-22")
lasts (reduce
(fn [acc [plate end loc]]
(cond
(nil? (get acc plate))
(assoc acc plate {:end end :loc loc})
(neg? (compare (get-in acc [plate :end]) end))
(assoc acc plate {:end end :loc loc})
:else
acc))
{} tuples)]
(get lasts "17-RA-67"))
@(d/transact conn [[:db/add "n" :person/name "Nikita"]])
(count (seq (d/datoms (d/db conn) :eavt)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment