   block graph. If you reflect the graph though, you'll see that we're working
   from the same block and getting the same result."
   [flat-graph node-sep char-sep]
-  (let [y-graphs (FlatGraph->y-graphs flat-graph node-sep char-sep)]
-    (avg-y-graphs y-graphs)))
+  (let [class-graphs (FlatGraph->ClassGraphs flat-graph)
+        narrowest (apply min-key #(width % node-sep char-sep) class-graphs)
+        narrow-min-y (min-y narrowest node-sep char-sep)
+        narrow-max-y (max-y narrowest node-sep char-sep)]
+    (->> class-graphs
+         (map #(let [delta (if (:aligned-down (meta %))
+                             (- narrow-max-y (max-y % node-sep char-sep))
+                             (- narrow-min-y (min-y % node-sep char-sep)))]
+                 (shift-ys % node-sep char-sep delta)))
+         (apply merge-with #(if (vector? %1) (conj %1 %2) [%1 %2]))
+         (map (fn [[node ys]]
+                (let [sort-ys (sort ys)]
+                  [node (/ (+ (nth sort-ys 1) (nth sort-ys 2)) 2)])))
+         (into {}))))
 
 
 (defn arc-distance

                                      nodes]]))


(defprotocol YPlotted
  (min-y [graph] "Minimum y-coordinate in the graph")
  (max-y [graph] "Maximum y-coordinate in the graph")
  (mid-y [graph] "Midpoint of y-coordinates in the graph")
  (shift-y [graph delta] "Shift the y-coordinate of every node by delta")
  (width [graph] "Width of the graph in y"))

(defrecord BlockGraph [blocks succs preds sources])


    (assoc this
           :src dest
           :dest src)))


(defn calc-rel-ys
  "An abstraction for processing a topologically-sorted seq of nodes (blocks or
  classes in our case) and calcluating y-values for each.  Higher order; takes
  a function that generates a function for mapping, and returns a function that
  returns a map of y-values"
  [map-gen-fn get-preds]
  (fn [items preds node-sep char-sep]
    (let [filter-set (set items)]
      (reduce (fn [ys item]
                (let [pred-ys (map (map-gen-fn ys char-sep)
                                   (get-preds preds item filter-set))
                      item-y (if (empty? pred-ys)
                               0
                               (+ node-sep (apply max pred-ys)))]
                  (assoc ys item item-y)))
              {}
              items))))


(def get-rel-ys
  "Takes topologically-sorted blocks from a single class, plus preds and
  minimum separation between nodes and subnodes, and returns a map of blocks to
  relative y-positions within the class"
  (calc-rel-ys
   (fn [ys char-sep]
     #(+ (get ys (:dest %))
         (* char-sep (dec (:weight %)))))
   (fn [preds item filter-set]
     (filter #(contains? filter-set (:dest %)) (get preds item)))))


(defn gen-get-shift-ys
  "Takes a map of blocks to relative y-positions within classes, and returns a
  function that returns a map of classes to their relative y-positions"
  [rel-ys]
  (calc-rel-ys (fn [ys char-sep]
                 #(- (+ (get ys (:dest %))
                        (get rel-ys (:dest %))
                        (* char-sep (dec (:weight %))))
                     (get rel-ys (:src %))))
               (fn [preds item _] (get preds item))))


(def memo-ys ;; heh
  (memoize
   (fn [this node-sep char-sep]
     (let [{:keys [classes preds block-preds]} this
           rel-ys (reduce #(merge %1 (get-rel-ys %2 block-preds
                                                 node-sep char-sep))
                          {}
                          classes)
           shift-ys (let [get-shift-ys (gen-get-shift-ys rel-ys)]
                      (get-shift-ys classes preds node-sep char-sep))
           block-shift-ys (into {} (mapcat (fn [[class shift]]
                                             (map #(-> [% shift]) class))
                                           shift-ys))]
       (->> rel-ys
            (map (fn [[block rel-y]]
                   [block (+ rel-y (get block-shift-ys block))]))
            (mapcat (fn [[block y]]
                      (->> (filter #(instance? Node %) block)
                           (map #(-> [% y])))))
            (into {}))))))


(defrecord ClassGraph [classes succs preds block-succs block-preds sources sinks]
  Reversible
