///|
pub fn position(g : Graph) -> Unit {
  let simple = as_non_compound_graph(g)
  position_y(simple)
  let xs = position_bk_x(simple)
  for v in simple.nodes() {
    if g.node_opt(v) is Some(node) {
      node.set_float("x", xs.get_or_default(v, 0.0))
      node.set_float("y", simple.node(v).get_float_or("y", 0.0))
    }
  }
}

///|
pub fn position_y(g : Graph) -> Unit {
  let layering = build_layer_matrix(g)
  let rank_sep = g.graph().get_float_or("ranksep", 50.0)
  let mut prev_y = 0.0
  for layer in layering {
    let mut max_height = 0.0
    for v in layer {
      if position_is_layer_hole(v) {
        continue
      }
      let h = g.node(v).get_float_or("height", 0.0)
      if h > max_height {
        max_height = h
      }
    }
    for v in layer {
      if position_is_layer_hole(v) {
        continue
      }
      let node = g.node(v)
      node.set_float("y", prev_y + max_height / 2.0)
    }
    prev_y = prev_y + max_height + rank_sep
  }
}

///|
pub fn position_x(g : Graph) -> Map[String, Double] {
  position_bk_x(g)
}

///|
fn position_is_layer_hole(v : String) -> Bool {
  v == ""
}