 
         cb?()
 
-
+class DSync1
+    constructor: (opts) ->
+        opts = defaults opts,
+            id   : undefined
+            doc  : required
+        if not opts.id?
+            @id = misc.uuid()
+        else
+            @id = opts.id
+
+        @live                  = opts.doc
+        @shadow                = @_copy(@live)
+
+    status: () =>
+        return {'id':@id, 'live':@live, 'shadow':@shadow}
+
+    restart: (reason) =>
+        console.log("*********************************************************")
+        console.log("* THINGS WENT TO HELL. -- #{reason} --  HAVE TO RESTART!!!!! *")
+        console.log("*********************************************************")
+        throw("dang")
+
+    # Copy a document; strings are immutable and the default, so we
+    # just return the object.
+    _copy: (doc) =>
+        return doc
+
+    # Determine array of edits between the two versions of the document
+    _compute_edits: (version0, version1) =>
+        return dmp.patch_make(version0, version1)
+
+    # "Best effort" application of array of edits.
+    _apply_edits: (edits, doc) =>
+        return dmp.patch_apply(edits, doc)[0]
+
+    # Return a checksum of a document
+    _checksum: (doc) =>
+        return doc.length
+
+    # Connect this client to the other end of the connection, the "server".
+    connect: (server) =>
+        @server = server
+
+    # Create a list of new edits, then send all edits not yet
+    # processed to the other end of the connection.
+    push_edits: (cb) =>
+        snapshot = @_copy(@live)
+        edits    = @_compute_edits(@shadow, snapshot)
+
+        if edits.length == 0
+            cb?()
+            return
+
+        @server.recv_edits edits, @_checksum(@shadow), (err) =>
+            if err
+                cb?(err)
+            else
+                @shadow = @_copy(snapshot)
+                cb?()
+
+
+    # Receive and process the edits from the other end of the sync connection.
+    recv_edits: (edits, checksum, cb) =>
+        if Math.random() < .5
+            cb(true)
+            return
+        if checksum != @_checksum(@shadow)
+            # Data corruption in memory or network -- there should be no other way for this to happen.
+            # In this case, we have to just restart everything from scratch.
+            @restart("checksum")
+            cb(true)
+            return
+
+        @shadow = @_apply_edits(edits, @shadow)
+        @live = @_apply_edits(edits, @live)
+        cb?()
+
+
+
+DSync = DSync0
 exports.test1 = () ->
     client = new DSync(doc:"sage", id:"client")
     server = new DSync(doc:"sage", id:"server")

        console.log(misc.to_json(server.status()))
        console.log("------------------------")

    status()
    client.push_edits()
    server.push_edits()
    status()

    client.live += "\nmore stuff"
    status()
    client.push_edits()
    server.push_edits()
    status()

    client.push_edits()

    client.live = 'bar1\n' + client.live
    server.live = 'bar2\n'
    status()
    while client.live != server.live
        try
            client.push_edits()
            server.push_edits()
            status()
        catch e
            status()
            break


dmp = new diff_match_patch()

class DSync0
    constructor: (opts) ->
        opts = defaults opts,
            id   : undefined
