 ;;;           159-167: Flag these blocks as sent
 ;;;                    Marks blocks between start and stop as ACK'd
 ;;;                    Updates totalblocktransmissions and totalblocks
-    (let [pre-acked (map (fn [n]
-                           (let [pos (bit-and (+ block-first n) outgoing-1)]
-                             ;; This raises the spectacle of a huge open question:
-                             ;; do I want to bother with the trappings of a circular
-                             ;; buffer?
-                             ;; It seems likely to reduce GC somewhat, but nowhere
-                             ;; near what I could achieve even just building everything
-                             ;; on byte-arrays.
-                             ;; Which simply is not going to happen until there's
-                             ;; convincing evidence that it's worthwhile.
-                             ;; (It probably is, but not for a first pass, even though
-                             ;; that's a more accurate translation).
-                             ))
-                     (range block-num))]
-      (throw (RuntimeException. "Translate the rest"))
+    (let [acked (reduce (fn [{:keys [::n]
+                              :as acc}
+                             block]
+                          (let [start-pos (::start-pos block)]
+                            (if (<= start
+                                    start-pos
+                                    (+ start-pos (::length block))
+                                    stop)
+                              (-> acc
+                                  (assoc-in [::blocks n ::time] 0)
+                                  (update ::total-blocks inc)
+                                  (update ::total-block-transmissions + (::transmissions block)))
+                              (update acc ::n inc))))
+                        (assoc state ::n 0)
+                        blocks)]
+      ;; To match the next block, the main point is to discard
+      ;; the first sequence of blocks that have been ACK'd
+      ;; drop-while seems obvious
+      ;; However, we also need to update send-acked, send-bytes, and send-processed
 ;;;           168-176: Updates globals for adjacent blocks that
 ;;;                    have been ACK'd
 ;;;                    This includes some counters that seem important:


(s/def ::block (s/keys :req [::length
                             ::start-pos
                             ::time]))
(s/def ::blocks (s/and (s/coll-of ::block)
                       ;; Actually, the length must be a power of 2
                       ;; TODO: Improve this spec!
                       ;; (Reference implementation uses 128)
                       #(= (rem (count %) 2) 0)))

;;; Index into the start of a circular queue
;;; Q: Is this a good idea?
(s/def ::block-first int?)

;; Number of outgoing blocks being tracked
(s/def ::block-num integer?)

;; If nonzero: minimum of active ::time values
(s/def ::earliest-time integer?)

(s/def ::state (s/keys ::req [::block-first
                              ::block-num
                              ::blocks
                              ::earliest-time]))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Internal

;;;                        sendbytes
;;;                        sendprocessed
;;;                        blockfirst
      (let [[to-drop to-keep] (split-with #(= 0 (::time %)) acked)
            dropped-block-lengths (apply + (map ::length to-drop))
            state (update state ::send-acked + dropped-block-lengths)
            state (update state ::send-bytes - dropped-block-lengths)
            state (update state ::send-processed - dropped-block-lengths)
;;;           177-182: Possibly set sendeofacked flag
            state (or (when (and send-eof
                                 (= start 0)
                                 (> stop (+ (::send-acked state)
                                            (::send-bytes state)))
                                 (not send-eof-acked))
                        (update state ::send-eof-acked true))
                      state)]
;;;           183: earliestblocktime_compute()
        (assoc state ::earliest-time (earliest-block-time blocks))))
    ;;; No change
    state))

