 
 ;; Zipper
 ;; ======
-(defn- branch? [node]
+(defn- branch?
+  "Returns true if the node is a distributor or isolator"
+  [node]
   (or
    (= :distributor (first node))
    (= :isolator (first node))))
 
-(defn- children [node]
+(defn- children
+  "Returns all the children of the node"
+  [node]
   (rest node))
 
-(defn- make-node [node children]
+(defn- make-node
+  "Given the existing node and new children, returns a new node"
+  [node children]
   (cons (first node) children))
 
 (defn- zipper
+  "Builds our gigrig custom zipper"
   ([] (zipper :distributor))
   ([root] (zip/zipper branch? children make-node [root])))
-
-(defn- location-type [loc]
-  (-> loc zip/node first))
 
 
 ;; Tree

              keys
              last)})

(defn- zip-pedal [pedal]
  [:pedal (:name pedal)])

(defn- group-by-power [pedals]
  (-> (group-by :power pedals)))

(defn- zip-isolators [isolators]
  (for [pedals (partition-all ISOLATOR_LIMIT isolators)]
    (cons :isolator (map zip-pedal pedals))))

(defn- iterate-groups [groups]
  (reduce
   (fn [loc pedal] (insert loc pedal))
   (zipper)
   (concat
    (map zip-pedal (:distributor groups))
    (zip-isolators (:isolator groups)))))

;; Main
;; ====
(defn build
  "Builds the powertree for the given pedals"
  [pedals]
  (-> (map simplify pedals)
      group-by-power
      iterate-groups))

(def DISTRIBUTOR_LIMIT 6)
(def ISOLATOR_LIMIT 4)

(defn- insert
  "Inserts a pedal at the given location in zipper. When full, the
  last child will be replaced with a new branch containing both the
  removed child and the new one."
  [loc pedal]
  (if (< (count (zip/children loc)) DISTRIBUTOR_LIMIT)
    (zip/append-child loc pedal)
    (let [new-node (zip/make-node loc [:distributor] [(last (zip/children loc)) pedal])]
