Skip to content

Instantly share code, notes, and snippets.

@metacritical
Created June 27, 2018 13:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save metacritical/4384673c1f2c0743e102acc78549d3b3 to your computer and use it in GitHub Desktop.
Save metacritical/4384673c1f2c0743e102acc78549d3b3 to your computer and use it in GitHub Desktop.
(ns dbooked-clj.core
(:import (java.time LocalDateTime format.DateTimeFormatter)))
(defn parse-datetime [date-str]
"Parse datetime."
(LocalDateTime/parse date-str (DateTimeFormatter/ISO_DATE_TIME)))
(defn is-before? [this that]
"Is this time before that?"
(.isBefore this that))
(defn is-after? [this that]
"Is this time after that?"
(.isAfter this that))
(defn in-between? [time start end]
"Finds if a time falls between two time events."
(and
(is-before? (parse-datetime time) (parse-datetime end))
(is-after? (parse-datetime time) (parse-datetime start))))
(defn overlaps? [{sta1 :sta end1 :end} {sta2 :sta end2 :end}]
"Parses and compares datetime object."
(or
(in-between? sta1 sta2 end2)
(in-between? sta2 sta1 end1)))
(defn event-sort [events]
(sort-by #(:sta %) events))
(defn merge-intervals [sorted-events]
(loop [acc [] [frst secnd & rst] sorted-events]
(cond
(compare (secnd :sta) (frst :end)))
))
(defn find-overlaps [coll]
(loop [[frst & rst] coll event-pairs []]
(if (empty? rst)
(vec event-pairs)
(let [all-overlaps (filter (partial overlaps? frst) rst)
combo-pairs (map (partial vector frst) all-overlaps)]
(recur rst (concat event-pairs combo-pairs))))))
(ns dbooked-clj.core-test
(:require [clojure.test :refer :all]
[dbooked-clj.core :refer :all]))
(def events-calendar
[{:sta "2018-06-24T09:10:12" :end "2018-06-24T10:00:00"}
{:sta "2018-06-24T12:00:00" :end "2018-06-24T15:00:00"}
{:sta "2018-06-24T12:30:00" :end "2018-06-24T13:30:00"}
{:sta "2018-06-24T10:00:00" :end "2018-06-24T10:30:00"}
{:sta "2018-06-24T10:15:00" :end "2018-06-24T10:45:00"}
{:sta "2018-06-24T10:30:00" :end "2018-06-24T11:30:00"}
{:sta "2018-06-24T13:30:00" :end "2018-06-24T14:00:00"}
{:sta "2018-06-24T15:30:00" :end "2018-06-24T16:00:00"}
{:sta "2018-06-24T16:00:00" :end "2018-06-24T16:30:00"}
{:sta "2018-06-24T16:30:00" :end "2018-06-24T17:00:00"}
{:sta "2018-06-24T14:00:00" :end "2018-06-24T15:00:00"}
{:sta "2018-06-24T14:30:00" :end "2018-06-24T15:00:00"}
{:sta "2018-06-24T11:00:00" :end "2018-06-24T12:00:00"}
{:sta "2018-06-24T15:30:00" :end "2018-06-24T15:45:00"}
{:sta "2018-06-24T17:00:00" :end "2018-06-24T17:30:00"}])
(def sample-overlap
[[{:sta "2018-06-24T10:00:00" :end "2018-06-24T10:30:00"}
{:sta "2018-06-24T10:15:00" :end "2018-06-24T10:45:00"}]
[{:sta "2018-06-24T10:15:00" :end "2018-06-24T10:45:00"}
{:sta "2018-06-24T10:30:00" :end "2018-06-24T11:30:00"}]
[{:sta "2018-06-24T10:30:00" :end "2018-06-24T11:30:00"}
{:sta "2018-06-24T11:00:00" :end "2018-06-24T12:00:00"}]
[{:sta "2018-06-24T12:00:00" :end "2018-06-24T15:00:00"}
{:sta "2018-06-24T12:30:00" :end "2018-06-24T13:30:00"}]
[{:sta "2018-06-24T12:00:00" :end "2018-06-24T15:00:00"}
{:sta "2018-06-24T13:30:00" :end "2018-06-24T14:00:00"}]
[{:sta "2018-06-24T12:00:00" :end "2018-06-24T15:00:00"}
{:sta "2018-06-24T14:00:00" :end "2018-06-24T15:00:00"}]
[{:sta "2018-06-24T12:00:00" :end "2018-06-24T15:00:00"}
{:sta "2018-06-24T14:30:00" :end "2018-06-24T15:00:00"}]
[{:sta "2018-06-24T14:00:00" :end "2018-06-24T15:00:00"}
{:sta "2018-06-24T14:30:00" :end "2018-06-24T15:00:00"}]])
(def events-table
[{:sta "2018-06-24T10:15:00" :end "2018-06-24T10:45:00"}
{:sta "2018-06-24T09:10:12" :end "2018-06-24T10:00:00"}
{:sta "2018-06-24T12:00:00" :end "2018-06-24T15:00:00"}
{:sta "2018-06-24T12:30:00" :end "2018-06-24T13:30:00"}
{:sta "2018-06-24T10:00:00" :end "2018-06-24T10:30:00"}])
(def sorted-events
[{:sta "2018-06-24T09:10:12" :end "2018-06-24T10:00:00"}
{:sta "2018-06-24T10:00:00" :end "2018-06-24T10:30:00"}
{:sta "2018-06-24T10:15:00" :end "2018-06-24T10:45:00"}
{:sta "2018-06-24T12:00:00" :end "2018-06-24T15:00:00"}
{:sta "2018-06-24T12:30:00" :end "2018-06-24T13:30:00"}])
(deftest test-parse-datetime
(testing "Test if datetime is parsed correctly."
(let [ev (:sta (events-calendar 0))]
(let [pdt (parse-datetime ev)]
(is (= (.getYear pdt) 2018))
(is (= (.toString (.getMonth pdt)) "JUNE"))
(is (= (.getDayOfMonth pdt) 24))
(is (= (.getYear pdt) 2018))
(is (= (.getHour pdt) 9))
(is (= (.getMinute pdt) 10))
(is (= (.getSecond pdt) 12))))))
(def merged-events [])
(deftest test-event-overlap
(testing "Find if there is an overlap in two input events."
(let [ev1 (events-calendar 0) ev2 (events-calendar 1)]
(is (= (overlaps? ev1 ev2) false)))
;; (let [ev1 (events-calendar 5) ev2 (events-calendar 6)]
;; (is (= (overlaps? ev1 ev2) true)))
(let [ev1 (events-calendar 12) ev2 (events-calendar 13)]
(is (= (overlaps? ev1 ev2) false)))))
(deftest test-find-ovelapping-pairs-visually
(testing "find pairs by printing to console."
(println (find-overlaps events-calendar))))
(deftest test-find-ovelapping-pairs
(testing "find the number of overlapping pairs."
(is (= (count (find-overlaps events-calendar)) 8))
(is (= (find-overlaps (event-sort events-calendar)) sample-overlap))
))
(deftest test-sort-event-calendar-by-time
(testing "Sort events in the calendar"
(println "\n" (find-overlaps (event-sort events-calendar)))
(is (= (event-sort events-table) sorted-events))))
(deftest test-merge-intervals
(testing "Merge overlapping intervals"
;; (is (= (merge-intervals sorted-events) merged-events))
(println "\n" (merge-intervals sorted-events))
))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment