-
-
Save coldnew/bb5bf23b81ef1d46d693 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns jsync.elevator | |
(:refer-clojure :exclude [map reduce into partition partition-by take merge]) | |
(:require [clojure.core.async :refer :all :as async])) | |
;; This is necessary to check and see what is on the persistent queue | |
(defmethod print-method clojure.lang.PersistentQueue | |
[q, w] | |
(print-method '<- w) | |
(print-method (seq q) w) | |
(print-method '-< w)) | |
;; setting up the management tools for state | |
(def elevator (atom {})) | |
(def presses (chan)) | |
(def move-requests (atom clojure.lang.PersistentQueue/EMPTY)) | |
(def update (partial swap! elevator assoc)) | |
;; gives the elevator a starting value | |
(defn start [] | |
(reset! elevator {:floor 1 :pressed-1 false :pressed-2 false :open true})) | |
;; main function to put the elevator in various states. Println is for debugging. Only runs when queue has count of 1. | |
(defn move-elevator [] | |
(cond | |
(and (= (count @move-requests) 1) (:pressed-1 @elevator)) | |
(do | |
(update :floor 1) | |
(update :pressed-1 false) | |
(println "door open") | |
(update :open true) | |
(Thread/sleep 5000) | |
(println "door closed") | |
(update :open false) | |
(update :floor 2) | |
(println "second floor") | |
(println "door open") | |
(update :open true) | |
(Thread/sleep 5000) | |
(println "door closed") | |
(update :open false) | |
(println "first floor") | |
(update :floor 1) | |
(println "done") | |
(swap! move-requests pop)) | |
(and (< (count @move-requests) 2) (:pressed-2 @elevator)) | |
(do | |
(update :floor 2) | |
(update :pressed-2 false) | |
(println "door open") | |
(update :open true) | |
(Thread/sleep 5000) | |
(println "door closed") | |
(update :open false) | |
(update :floor 1) | |
(println "first floor") | |
(println "door open") | |
(update :open true) | |
(println "done") | |
(swap! move-requests pop)) | |
(and (false? (:pressed-1 @elevator)) (false? (:pressed-2 @elevator))) | |
(start)) | |
(if (or (:pressed-1 @elevator) (:pressed-2 @elevator)) (recur))) | |
;; continuously listens for button presses on the presses channel with a go-loop | |
(defn listen-for-presses [] | |
(go-loop [] | |
(when-let [p (<! presses)] | |
(if | |
(= p :up) | |
(update :pressed-1 true) | |
(update :pressed-2 true)) | |
(move-elevator) | |
(recur)))) | |
;; starting the machine up with default values and a listener | |
(defn init [] | |
(start) | |
(listen-for-presses) | |
(reset! move-requests clojure.lang.PersistentQueue/EMPTY)) | |
;; main api functions, called by elevtor users via pressing buttons outside the doors | |
(defn move-up [] | |
(if (and (< (count @move-requests) 2) (not (some :move-up @move-requests))) | |
(do (>!! presses :up) | |
(swap! move-requests conj :move-up)))) | |
(defn move-down [] | |
(if (and (< (count @move-requests) 2) (not (some :move-down @move-requests))) | |
(do (>!! presses :down) | |
(swap! move-requests conj :move-down)))) | |
;; Testing it out | |
@elevator | |
(init) | |
(move-up) | |
(move-down) | |
@move-requests |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment