splitNodes :: Input a => StGNG a ()
splitNodes = State.get >>= f
    <$> (+1) . (^.splitPeriod)
    <*> (\a -> a^.settings^.splitSpan)
    <*> (^.nodes)
    <*> (^.edges)
  where
    f sp ss ns es | sp < ss   = return ()
                  | otherwise = do
        State.modify $ (&splitPeriod .~ 0)
        case headMay (intersect (n1^.edgeIds) (n2^.edgeIds)) >>= flip Map.lookup es of
            Nothing -> return ()
            Just e  -> do
                deleteEdges [e^.edgeId]
                deleteEdgeFromNodes e
                new <- newNode newValue
                mapM_ (modifyNode (&moved .~ mh)) $ map (^.nodeId) [new, n1]
                newEdges <- mapM (newEdge new) [n1, n2]
                mapM_ (modifyEdge (&age .~ e^.age)) $ map (^.edgeId) newEdges
      where
        maximumByMoved = maximumBy (\a b -> compare (a^.moved) (b^.moved))
        n1 = maximumByMoved $ Map.elems ns
        n2 = maximumByMoved . getAll ns . map (otherNode n1) . getAll es $ n1^.edgeIds
        mh = n1^.moved / 2
        newValue = mul (add (n1^.value) (n2^.value)) 0.5
splitNodes :: Input a => StGNG a ()
splitNodes = State.get >>= f
    <$> (+1) . (^.splitPeriod)
    <*> (\a -> a^.settings^.splitSpan)
    <*> (^.nodes)
    <*> (^.edges)
  where
    f sp ss ns es | sp < ss   = return ()
                  | otherwise = do
        State.modify $ (&splitPeriod .~ 0)
        case headMay (intersect (n1^.edgeIds) (n2^.edgeIds)) >>= flip Map.lookup es of
            Nothing -> return ()
            Just e  -> do
                deleteEdges [e^.edgeId]
                deleteEdgeFromNodes e
                new <- newNode newValue
                mapM_ (modifyNode (&moved .~ mh)) $ map (^.nodeId) [new, n1]
                newEdges <- mapM (newEdge new) [n1, n2]
                mapM_ (modifyEdge (&age .~ e^.age)) $ map (^.edgeId) newEdges
      where
        maximumByMoved = maximumBy (\a b -> compare (a^.moved) (b^.moved))
        n1 = maximumByMoved $ Map.elems ns
        n2 = maximumByMoved . getAll ns . map (otherNode n1) . getAll es $ n1^.edgeIds
        mh = n1^.moved / 2
        newValue = mul (add (n1^.value) (n2^.value)) 0.5
splitNodes = State.get >>= f
    <$> (+1) . (^.splitPeriod)
    <*> (\a -> a^.settings^.splitSpan)
    <*> (^.nodes)
    <*> (^.edges)
  where
    f sp ss ns es | sp < ss   = return ()
                  | otherwise = do
        State.modify $ (&splitPeriod .~ 0)
        case headMay (intersect (n1^.edgeIds) (n2^.edgeIds)) >>= flip Map.lookup es of
            Nothing -> return ()
            Just e  -> do
                deleteEdges [e^.edgeId]
                deleteEdgeFromNodes e
                new <- newNode newValue
                mapM_ (modifyNode (&moved .~ mh)) $ map (^.nodeId) [new, n1]
                newEdges <- mapM (newEdge new) [n1, n2]
                mapM_ (modifyEdge (&age .~ e^.age)) $ map (^.edgeId) newEdges
      where
        maximumByMoved = maximumBy (\a b -> compare (a^.moved) (b^.moved))
        n1 = maximumByMoved $ Map.elems ns
        n2 = maximumByMoved . getAll ns . map (otherNode n1) . getAll es $ n1^.edgeIds
        mh = n1^.moved / 2
        newValue = mul (add (n1^.value) (n2^.value)) 0.5