Skip to content

Commit

Permalink
Updating terminology in function names and comments so that operation…
Browse files Browse the repository at this point in the history
…s are streams of changes, not streams of (levenshtein distance) operations which was confusing
  • Loading branch information
fitzgen committed Apr 5, 2011
1 parent 35643e5 commit 051354c
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 107 deletions.
22 changes: 11 additions & 11 deletions apply.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,34 @@
/*global define */

define(["./operations"], function (operations) {
return function (ops, doc) {
return function (op, doc) {
var i,
len,
index = 0,
newDoc = "";
for ( i = 0, len = ops.length; i < len; i += 1 ) {
switch ( operations.type(ops[i]) ) {
for ( i = 0, len = op.length; i < len; i += 1 ) {
switch ( operations.type(op[i]) ) {
case "retain":
newDoc += doc.slice(0, operations.val(ops[i]));
doc = doc.slice(operations.val(ops[i]));
newDoc += doc.slice(0, operations.val(op[i]));
doc = doc.slice(operations.val(op[i]));
break;
case "insert":
newDoc += operations.val(ops[i]);
newDoc += operations.val(op[i]);
break;
case "delete":
if ( doc.indexOf(operations.val(ops[i])) !== 0 ) {
throw new TypeError("Expected '" + operations.val(ops[i])
if ( doc.indexOf(operations.val(op[i])) !== 0 ) {
throw new TypeError("Expected '" + operations.val(op[i])
+ "' to delete, found '" + doc.slice(0, 10)
+ "...'");
} else {
doc = doc.slice(operations.val(ops[i]).length);
doc = doc.slice(operations.val(op[i]).length);
break;
}
default:
throw new TypeError("Unknown operation: "
+ operations.type(ops[i]));
+ operations.type(op[i]));
}
}
return newDoc;
}
};
});
12 changes: 6 additions & 6 deletions client.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ define([
var i, len, msg;
for ( i = 0, len = outgoing.length; i < len; i++ ) {
msg = outgoing[i];
xform(messages.operations(msg), ops, function (aPrime, bPrime) {
messages.operations(msg, aPrime);
xform(messages.operation(msg), ops, function (aPrime, bPrime) {
messages.operation(msg, aPrime);
messages.document(msg, apply(messages.document(msg), aPrime));
messages.revision(msg, messages.revision(msg)+1);
ops = bPrime;
Expand Down Expand Up @@ -62,7 +62,7 @@ define([
uiDoc = ui.getDocument();
if ( uiDoc !== previousDoc ) {
msg = {};
messages.operations(msg, operations.getOperations(previousDoc, uiDoc));
messages.operation(msg, operations.operation(previousDoc, uiDoc));
messages.document(msg, uiDoc);
messages.revision(msg, ++previousRevision);
messages.id(msg, id);
Expand All @@ -87,8 +87,8 @@ define([
// to have to do a deep equality test on every check here.
function isOurOutgoing (msg, outgoing) {
var top = outgoing[0],
topOps = messages.operations(top),
msgOps = messages.operations(msg),
topOps = messages.operation(top),
msgOps = messages.operation(msg),
i = 0,
len = msgOps.length;
if ( messages.id(msg) !== messages.id(top) ) {
Expand Down Expand Up @@ -144,7 +144,7 @@ define([
outgoing.shift();
} else {
// TODO: need to handle cursor selection and index
xformEach(outgoing, messages.operations(msg));
xformEach(outgoing, messages.operation(msg));

// TODO: cursor position
if ( outgoing.length ) {
Expand Down
2 changes: 1 addition & 1 deletion messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ define(function () {
// client connect.
document: defineGetSet("doc"),
revision: defineGetSet("rev"),
operations: defineGetSet("ops"),
operation: defineGetSet("op"),
id: defineGetSet("id")
};

Expand Down
76 changes: 39 additions & 37 deletions operations.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This module defines the implementation of our operations. How they are
// represented, their construction, and how to calculate the set of operations
// to change some document A in to document B.
// Operations are a stream of individual changes which span the whole document
// from start to finish. Changes have a type which is one of retain, insert, or
// delete, and have associated data based on their type.


/*jslint onevar: true, undef: true, eqeqeq: true, bitwise: true,
Expand All @@ -11,7 +11,7 @@

define(function () {

// Simple operation constructors.
// Simple change constructors.

function insert (chars) {
return ["insert", chars];
Expand All @@ -25,12 +25,12 @@ define(function () {
return ["retain", n];
}

function type (operation) {
return operation[0];
function type (change) {
return change[0];
}

function val (operation) {
return operation[1];
function val (change) {
return change[1];
}

// We don't want to copy arrays all the time, aren't mutating lists, and
Expand Down Expand Up @@ -69,20 +69,20 @@ define(function () {
// Abstract out the table in case I want to change the implementation to
// arrays of arrays or something.

function put (table, x, y, ops) {
return (table[String(x) + "," + String(y)] = ops);
function put (table, x, y, changes) {
return (table[String(x) + "," + String(y)] = changes);
}

function get (table, x, y) {
var ops = table[String(x) + "," + String(y)];
if ( ops ) {
return ops;
var changes = table[String(x) + "," + String(y)];
if ( changes ) {
return changes;
} else {
throw new TypeError("No operations at " + String(x) + "," + String(y));
}
}

function makeOperationsTable (s, t) {
function makeChangesTable (s, t) {
var table = {},
n = s.length,
m = t.length,
Expand All @@ -101,50 +101,52 @@ define(function () {
}

function chooseCell (table, x, y, k) {
var prevOps = get(table, x, y-1),
min = prevOps.length,
var prevChanges = get(table, x, y-1),
min = prevChanges.length,
direction = "up";

if ( get(table, x-1, y).length < min ) {
prevOps = get(table, x-1, y);
min = prevOps.length;
prevChanges = get(table, x-1, y);
min = prevChanges.length;
direction = "left";
}

if ( get(table, x-1, y-1).length < min ) {
prevOps = get(table, x-1, y-1);
min = prevOps.length;
prevChanges = get(table, x-1, y-1);
min = prevChanges.length;
direction = "diagonal";
}

return k(direction, prevOps);
return k(direction, prevChanges);
}

return {

getOperations: function (s, t) {
// Constructor for operations (which are a stream of changes). Uses
// variation of Levenshtein Distance.
operation: function (s, t) {
var n = s.length,
m = t.length,
i,
j,
ops = makeOperationsTable(s, t);
changes = makeChangesTable(s, t);
for ( i = 1; i <= m; i += 1 ) {
for ( j = 1; j <= n; j += 1 ) {
chooseCell(ops, i, j, function (direction, prevOps) {
chooseCell(changes, i, j, function (direction, prevChanges) {
switch ( direction ) {
case "left":
put(ops, i, j, cons(insert(t.charAt(i-1)), prevOps));
put(changes, i, j, cons(insert(t.charAt(i-1)), prevChanges));
break;
case "up":
put(ops, i, j, cons(del(s.charAt(j-1)), prevOps));
put(changes, i, j, cons(del(s.charAt(j-1)), prevChanges));
break;
case "diagonal":
if ( s.charAt(j-1) === t.charAt(i-1) ) {
put(ops, i, j, cons(retain(1), prevOps));
put(changes, i, j, cons(retain(1), prevChanges));
} else {
put(ops, i, j, cons(insert(t.charAt(i-1)),
cons(del(s.charAt(j-1)),
prevOps)));
put(changes, i, j, cons(insert(t.charAt(i-1)),
cons(del(s.charAt(j-1)),
prevChanges)));
}
break;
default:
Expand All @@ -153,7 +155,7 @@ define(function () {
});
}
}
return get(ops, i-1, j-1).toArray().reverse();
return get(changes, i-1, j-1).toArray().reverse();
},

insert: insert,
Expand All @@ -162,16 +164,16 @@ define(function () {
type: type,
val: val,

isDelete: function (op) {
return typeof op === "object" && type(op) === "delete";
isDelete: function (change) {
return typeof change === "object" && type(change) === "delete";
},

isRetain: function (op) {
return typeof op === "object" && type(op) === "retain";
isRetain: function (change) {
return typeof change === "object" && type(change) === "retain";
},

isInsert: function (op) {
return typeof op === "object" && type(op) === "insert";
isInsert: function (change) {
return typeof change === "object" && type(change) === "insert";
}

};
Expand Down
8 changes: 4 additions & 4 deletions ot.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ define([
}.bind(this));
};

manager.applyOperations = function (message) {
manager.applyOperation = function (message) {
var id = messages.id(message),
newRev = messages.revision(message),
ops = messages.operations(message),
op = messages.operation(message),
emit = this.emit.bind(this);

store.getDocument(id, function (err, doc) {
Expand All @@ -55,7 +55,7 @@ define([
} else {
if ( newRev === doc.rev+1 ) {
try {
doc.doc = apply(ops, doc.doc);
doc.doc = apply(op, doc.doc);
} catch (e) {
emit("error", e);
return;
Expand All @@ -74,7 +74,7 @@ define([
msg = {};
messages.revision(msg, doc.rev);
messages.id(msg, doc.id);
messages.operations(msg, ops);
messages.operation(msg, op);
messages.document(msg, doc.doc);
emit("update", msg);
}
Expand Down
Loading

0 comments on commit 051354c

Please sign in to comment.