serversFull :: Int -> [(ServerCfg, Maybe Int)] -> Bool
serversFull max = all (isStoppedOrFull . snd)
  where isStoppedOrFull (Just cnt) = cnt >= max
        isStoppedOrFull Nothing   = True

firstDown :: [(ServerCfg, Maybe Int)] -> Maybe ServerCfg
firstDown = (fst <$>) . find (isNothing . snd)

needToStop :: Int -> [(ServerCfg, Maybe Int)] -> [ServerCfg]
needToStop max srvs = map fst $ case nonEmpty of
                                  [] -> drop 1 empty
                                  _ -> empty
  where running = map (fmap fromJust) $ filter (isJust . snd) srvs
        nonFull = filter ((< max) . snd) running
        (nonEmpty, empty) = partition ((> 0) . snd) nonFull