added bower
This commit is contained in:
parent
355cfba78e
commit
5d453fb0a5
@ -40,7 +40,6 @@ One downside is that the History Buffer holds at least as many operations as the
|
|||||||
In contrast, an OT algorithm can have an empty History Buffer while the document size is very big.
|
In contrast, an OT algorithm can have an empty History Buffer while the document size is very big.
|
||||||
|
|
||||||
So, how did I come up with the name for the implementation (Yatta! is not Yata)?
|
So, how did I come up with the name for the implementation (Yatta! is not Yata)?
|
||||||

|
|
||||||
Yatta! means "I did it!" in Japanese. You scream it when you accomplish something (for proper application I refer to the Yatta-man in [Heroes](http://heroeswiki.com/Yatta!)).
|
Yatta! means "I did it!" in Japanese. You scream it when you accomplish something (for proper application I refer to the Yatta-man in [Heroes](http://heroeswiki.com/Yatta!)).
|
||||||
There is also this awesome video on the Internet that will change your life [Yatta](https://www.youtube.com/watch?v=kL5DDSglM_s).
|
There is also this awesome video on the Internet that will change your life [Yatta](https://www.youtube.com/watch?v=kL5DDSglM_s).
|
||||||
|
|
||||||
|
27
bower.json
Normal file
27
bower.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "Yatta!",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"homepage": "https://github.com/DadaMonad/Yatta",
|
||||||
|
"authors": [
|
||||||
|
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
||||||
|
],
|
||||||
|
"description": "A Framework for Real-Time collaboration on arbitrary data structures.",
|
||||||
|
"main": "./dest/browser/**",
|
||||||
|
"keywords": [
|
||||||
|
"OT",
|
||||||
|
"collaboration",
|
||||||
|
"synchronization",
|
||||||
|
"ShareJS",
|
||||||
|
"Coweb",
|
||||||
|
"concurrency"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"ignore": [
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"bower_components",
|
||||||
|
"test",
|
||||||
|
"Gruntfile.coffee",
|
||||||
|
"extras"
|
||||||
|
]
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Test GOTOjs</title>
|
<title>Test Yatta!</title>
|
||||||
<link rel="stylesheet" href="../../../node_modules/mocha/mocha.css" />
|
<link rel="stylesheet" href="../../../node_modules/mocha/mocha.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -21,34 +21,33 @@
|
|||||||
Connector_uninitialized = require("../lib/Connectors/TestConnector.coffee");
|
Connector_uninitialized = require("../lib/Connectors/TestConnector.coffee");
|
||||||
|
|
||||||
Test = (function() {
|
Test = (function() {
|
||||||
function Test() {
|
function Test(name_suffix) {
|
||||||
|
this.name_suffix = name_suffix != null ? name_suffix : "";
|
||||||
this.applyRandomOp = __bind(this.applyRandomOp, this);
|
this.applyRandomOp = __bind(this.applyRandomOp, this);
|
||||||
this.generateRandomOp = __bind(this.generateRandomOp, this);
|
this.generateRandomOp = __bind(this.generateRandomOp, this);
|
||||||
this.generateDeleteOp = __bind(this.generateDeleteOp, this);
|
this.generateDeleteOp = __bind(this.generateDeleteOp, this);
|
||||||
this.generateReplaceOp = __bind(this.generateReplaceOp, this);
|
this.generateReplaceOp = __bind(this.generateReplaceOp, this);
|
||||||
this.generateInsertOp = __bind(this.generateInsertOp, this);
|
this.generateInsertOp = __bind(this.generateInsertOp, this);
|
||||||
this.number_of_test_cases_multiplier = 1;
|
this.number_of_test_cases_multiplier = 1;
|
||||||
this.repeat_this = 1 * this.number_of_test_cases_multiplier;
|
this.repeat_this = 5 * this.number_of_test_cases_multiplier;
|
||||||
this.doSomething_amount = 5000 * this.number_of_test_cases_multiplier;
|
this.doSomething_amount = 1000 * this.number_of_test_cases_multiplier;
|
||||||
this.number_of_engines = 10 + this.number_of_test_cases_multiplier - 1;
|
this.number_of_engines = 10 + this.number_of_test_cases_multiplier - 1;
|
||||||
this.time = 0;
|
this.time = 0;
|
||||||
this.ops = 0;
|
this.ops = 0;
|
||||||
this.time_now = 0;
|
this.time_now = 0;
|
||||||
this.debug = false;
|
this.debug = true;
|
||||||
this.reinitialize();
|
this.reinitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
Test.prototype.reinitialize = function() {
|
Test.prototype.reinitialize = function() {
|
||||||
var i, _i, _ref, _results;
|
var i, _i, _ref;
|
||||||
this.users = [];
|
this.users = [];
|
||||||
this.Connector = Connector_uninitialized(this.users);
|
this.Connector = Connector_uninitialized(this.users);
|
||||||
this.users.push(new Yatta(0, this.Connector));
|
for (i = _i = 0, _ref = this.number_of_engines; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
|
||||||
this.users[0].val('name', "initial");
|
this.users.push(new Yatta(i + this.name_suffix, this.Connector));
|
||||||
_results = [];
|
|
||||||
for (i = _i = 1, _ref = this.number_of_engines; 1 <= _ref ? _i < _ref : _i > _ref; i = 1 <= _ref ? ++_i : --_i) {
|
|
||||||
_results.push(this.users.push(new Yatta(i, this.Connector)));
|
|
||||||
}
|
}
|
||||||
return _results;
|
this.users[0].val('name', "i");
|
||||||
|
return this.flushAll();
|
||||||
};
|
};
|
||||||
|
|
||||||
Test.prototype.getSomeUser = function() {
|
Test.prototype.getSomeUser = function() {
|
||||||
@ -85,7 +84,7 @@
|
|||||||
var length, ops1, pos;
|
var length, ops1, pos;
|
||||||
if (this.users[user_num].val('name').val().length > 0) {
|
if (this.users[user_num].val('name').val().length > 0) {
|
||||||
pos = _.random(0, this.users[user_num].val('name').val().length - 1);
|
pos = _.random(0, this.users[user_num].val('name').val().length - 1);
|
||||||
length = 1;
|
length = _.random(0, this.users[user_num].val('name').val().length - pos);
|
||||||
ops1 = this.users[user_num].val('name').deleteText(pos, length);
|
ops1 = this.users[user_num].val('name').deleteText(pos, length);
|
||||||
}
|
}
|
||||||
return void 0;
|
return void 0;
|
||||||
@ -93,7 +92,7 @@
|
|||||||
|
|
||||||
Test.prototype.generateRandomOp = function(user_num) {
|
Test.prototype.generateRandomOp = function(user_num) {
|
||||||
var i, op, op_gen;
|
var i, op, op_gen;
|
||||||
op_gen = [this.generateDeleteOp, this.generateInsertOp, this.generateReplaceOp];
|
op_gen = [this.generateInsertOp, this.generateDeleteOp, this.generateReplaceOp];
|
||||||
i = _.random(op_gen.length - 1);
|
i = _.random(op_gen.length - 1);
|
||||||
return op = op_gen[i](user_num);
|
return op = op_gen[i](user_num);
|
||||||
};
|
};
|
||||||
@ -136,20 +135,19 @@
|
|||||||
if (test_number != null) {
|
if (test_number != null) {
|
||||||
console.log(("" + test_number + "/" + this.repeat_this + ": Every collaborator (" + this.users.length + ") applied " + number_of_created_operations + " ops in a different order.") + (" Over all we consumed " + this.ops + " operations in " + (this.time / 1000) + " seconds (" + ops_per_msek + " ops/msek)."));
|
console.log(("" + test_number + "/" + this.repeat_this + ": Every collaborator (" + this.users.length + ") applied " + number_of_created_operations + " ops in a different order.") + (" Over all we consumed " + this.ops + " operations in " + (this.time / 1000) + " seconds (" + ops_per_msek + " ops/msek)."));
|
||||||
}
|
}
|
||||||
console.log(this.users.length);
|
|
||||||
_results = [];
|
_results = [];
|
||||||
for (i = _j = 0, _ref1 = this.users.length - 1; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
|
for (i = _j = 0, _ref1 = this.users.length - 1; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
|
||||||
if (!this.debug) {
|
if (this.debug) {
|
||||||
_results.push(expect(this.users[i].val('name').val()).to.equal(this.users[i + 1].val('name').val()));
|
|
||||||
} else {
|
|
||||||
if (this.users[i].val('name').val() !== this.users[i + 1].val('name').val()) {
|
if (this.users[i].val('name').val() !== this.users[i + 1].val('name').val()) {
|
||||||
printOpsInExecutionOrder = (function(_this) {
|
printOpsInExecutionOrder = (function(_this) {
|
||||||
return function(otnumber, otherotnumber) {
|
return function(otnumber, otherotnumber) {
|
||||||
var j, o, ops, s, _k, _l, _len, _len1;
|
var j, o, ops, s, _k, _l, _len, _len1;
|
||||||
ops = _this.users[otnumber].getConnector().getOpsInExecutionOrder();
|
ops = _.filter(_this.users[otnumber].getConnector().getOpsInExecutionOrder(), function(o) {
|
||||||
for (_k = 0, _len = ops.length; _k < _len; _k++) {
|
return typeof o.uid.op_name !== 'string' && o.uid.creator !== '_';
|
||||||
s = ops[_k];
|
});
|
||||||
console.log(JSON.stringify(s));
|
for (j = _k = 0, _len = ops.length; _k < _len; j = ++_k) {
|
||||||
|
s = ops[j];
|
||||||
|
console.log(("op" + j + " = ") + (JSON.stringify(s)));
|
||||||
}
|
}
|
||||||
console.log("");
|
console.log("");
|
||||||
s = "ops = [";
|
s = "ops = [";
|
||||||
@ -162,8 +160,8 @@
|
|||||||
}
|
}
|
||||||
s += "]";
|
s += "]";
|
||||||
console.log(s);
|
console.log(s);
|
||||||
console.log("@users[@last_user].ot.applyOps ops");
|
console.log("@test_user.engine.applyOps ops");
|
||||||
console.log("expect(@users[@last_user].ot.val('name')).to.equal(\"" + (_this.users[otherotnumber].val('name')) + "\")");
|
console.log("expect(@test_user.val('name').val()).to.equal(\"" + (_this.users[otherotnumber].val('name').val()) + "\")");
|
||||||
return ops;
|
return ops;
|
||||||
};
|
};
|
||||||
})(this);
|
})(this);
|
||||||
@ -173,17 +171,19 @@
|
|||||||
_ref2 = this.users;
|
_ref2 = this.users;
|
||||||
for (j = _k = 0, _len = _ref2.length; _k < _len; j = ++_k) {
|
for (j = _k = 0, _len = _ref2.length; _k < _len; j = ++_k) {
|
||||||
u = _ref2[j];
|
u = _ref2[j];
|
||||||
console.log(("OT" + j + ": ") + u.val('name'));
|
console.log(("OT" + j + ": ") + u.val('name').val());
|
||||||
}
|
}
|
||||||
console.log("\nOT execution order (" + i + "," + (i + 1) + "):");
|
console.log("\nOT execution order (" + i + "," + (i + 1) + "):");
|
||||||
printOpsInExecutionOrder(i, i + 1);
|
printOpsInExecutionOrder(i, i + 1);
|
||||||
console.log("");
|
console.log("");
|
||||||
ops = printOpsInExecutionOrder(i + 1, i);
|
ops = printOpsInExecutionOrder(i + 1, i);
|
||||||
_results.push(console.log(""));
|
console.log("");
|
||||||
} else {
|
|
||||||
_results.push(void 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.users[i].val('name').val() !== this.users[i + 1].val('name').val()) {
|
||||||
|
console.log("found error");
|
||||||
|
}
|
||||||
|
_results.push(expect(this.users[i].val('name').val()).to.equal(this.users[i + 1].val('name').val()));
|
||||||
}
|
}
|
||||||
return _results;
|
return _results;
|
||||||
};
|
};
|
||||||
@ -198,18 +198,33 @@
|
|||||||
this.doSomething();
|
this.doSomething();
|
||||||
}
|
}
|
||||||
this.compareAll(times);
|
this.compareAll(times);
|
||||||
|
this.testHBencoding();
|
||||||
|
if (times !== this.repeat_this) {
|
||||||
_results.push(this.reinitialize());
|
_results.push(this.reinitialize());
|
||||||
|
} else {
|
||||||
|
_results.push(void 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return _results;
|
return _results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Test.prototype.testHBencoding = function() {
|
||||||
|
var user;
|
||||||
|
user = new Yatta('testuser', Connector_uninitialized([]));
|
||||||
|
user.engine.applyOps(this.users[0].HB._encode());
|
||||||
|
return expect(user.value.name.val()).to.equal(this.users[0].value.name.val());
|
||||||
|
};
|
||||||
|
|
||||||
return Test;
|
return Test;
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
describe("JsonYatta", function() {
|
describe("JsonYatta", function() {
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
|
this.timeout(50000);
|
||||||
this.yTest = new Test();
|
this.yTest = new Test();
|
||||||
|
this.users = this.yTest.users;
|
||||||
|
this.test_user = new Yatta(0, Connector_uninitialized([]));
|
||||||
return done();
|
return done();
|
||||||
});
|
});
|
||||||
it("has a JsonWrapper", function() {
|
it("has a JsonWrapper", function() {
|
||||||
@ -230,6 +245,19 @@
|
|||||||
expect(w.x).to.equal("dtrn");
|
expect(w.x).to.equal("dtrn");
|
||||||
return expect(w.set.x).to.equal("x");
|
return expect(w.set.x).to.equal("x");
|
||||||
});
|
});
|
||||||
|
it("handles double-late-join", function() {
|
||||||
|
var ops1, ops2, test, u1, u2;
|
||||||
|
test = new Test("doubble");
|
||||||
|
test.run();
|
||||||
|
this.yTest.run();
|
||||||
|
u1 = test.users[0];
|
||||||
|
u2 = this.yTest.users[1];
|
||||||
|
ops1 = u1.HB._encode();
|
||||||
|
ops2 = u2.HB._encode();
|
||||||
|
u1.engine.applyOps(ops2);
|
||||||
|
u2.engine.applyOps(ops1);
|
||||||
|
return expect(u2.value.name.val()).to.equal(u2.value.name.val());
|
||||||
|
});
|
||||||
it("can handle creaton of complex json", function() {
|
it("can handle creaton of complex json", function() {
|
||||||
this.yTest.getSomeUser().val('x', {
|
this.yTest.getSomeUser().val('x', {
|
||||||
'a': 'b'
|
'a': 'b'
|
||||||
@ -264,9 +292,151 @@
|
|||||||
expect(this.yTest.getSomeUser().val('number')).to.equal(4);
|
expect(this.yTest.getSomeUser().val('number')).to.equal(4);
|
||||||
return expect(this.yTest.getSomeUser().val('object').val('q')).to.equal("rr");
|
return expect(this.yTest.getSomeUser().val('object').val('q')).to.equal("rr");
|
||||||
});
|
});
|
||||||
return it("can handle many engines, many operations, concurrently (random)", function() {
|
it("can handle many engines, many operations, concurrently (random)", function() {
|
||||||
return this.yTest.run();
|
return this.yTest.run();
|
||||||
});
|
});
|
||||||
|
return it("converges t1", function() {
|
||||||
|
var op0, op1, op2, op3, op4, op5, op6, op7, op8, ops;
|
||||||
|
op0 = {
|
||||||
|
"type": "Delimiter",
|
||||||
|
"uid": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 0
|
||||||
|
},
|
||||||
|
"next": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
op1 = {
|
||||||
|
"type": "Delimiter",
|
||||||
|
"uid": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 1
|
||||||
|
},
|
||||||
|
"prev": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
op2 = {
|
||||||
|
"type": "Word",
|
||||||
|
"uid": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 2
|
||||||
|
},
|
||||||
|
"beginning": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
op3 = {
|
||||||
|
"type": "AddName",
|
||||||
|
"uid": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 3
|
||||||
|
},
|
||||||
|
"map_manager": {
|
||||||
|
"creator": "_",
|
||||||
|
"op_number": "_"
|
||||||
|
},
|
||||||
|
"name": "name"
|
||||||
|
};
|
||||||
|
op4 = {
|
||||||
|
"type": "Replaceable",
|
||||||
|
"content": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 2
|
||||||
|
},
|
||||||
|
"ReplaceManager": {
|
||||||
|
"creator": "_",
|
||||||
|
"op_number": "___RM_name"
|
||||||
|
},
|
||||||
|
"prev": {
|
||||||
|
"creator": "_",
|
||||||
|
"op_number": "___RM_name_beginning"
|
||||||
|
},
|
||||||
|
"next": {
|
||||||
|
"creator": "_",
|
||||||
|
"op_number": "___RM_name_end"
|
||||||
|
},
|
||||||
|
"uid": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 4
|
||||||
|
}
|
||||||
|
};
|
||||||
|
op5 = {
|
||||||
|
"type": "TextInsert",
|
||||||
|
"content": "u",
|
||||||
|
"uid": {
|
||||||
|
"creator": 1,
|
||||||
|
"op_number": 2
|
||||||
|
},
|
||||||
|
"prev": {
|
||||||
|
"creator": 1,
|
||||||
|
"op_number": 0
|
||||||
|
},
|
||||||
|
"next": {
|
||||||
|
"creator": 1,
|
||||||
|
"op_number": 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
op6 = {
|
||||||
|
"type": "TextInsert",
|
||||||
|
"content": "w",
|
||||||
|
"uid": {
|
||||||
|
"creator": 2,
|
||||||
|
"op_number": 0
|
||||||
|
},
|
||||||
|
"prev": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 0
|
||||||
|
},
|
||||||
|
"next": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
op7 = {
|
||||||
|
"type": "TextInsert",
|
||||||
|
"content": "d",
|
||||||
|
"uid": {
|
||||||
|
"creator": 1,
|
||||||
|
"op_number": 0
|
||||||
|
},
|
||||||
|
"prev": {
|
||||||
|
"creator": 0,
|
||||||
|
"op_number": 0
|
||||||
|
},
|
||||||
|
"next": {
|
||||||
|
"creator": 2,
|
||||||
|
"op_number": 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
op8 = {
|
||||||
|
"type": "TextInsert",
|
||||||
|
"content": "a",
|
||||||
|
"uid": {
|
||||||
|
"creator": 1,
|
||||||
|
"op_number": 1
|
||||||
|
},
|
||||||
|
"prev": {
|
||||||
|
"creator": 1,
|
||||||
|
"op_number": 0
|
||||||
|
},
|
||||||
|
"next": {
|
||||||
|
"creator": 2,
|
||||||
|
"op_number": 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ops = [op0, op1, op2, op3, op4, op5, op6, op7, op8];
|
||||||
|
this.test_user.engine.applyOps(ops);
|
||||||
|
return expect(this.test_user.val('name').val()).to.equal("duaw");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user