added bower

This commit is contained in:
Kevin Jahns 2014-08-08 05:25:30 +02:00
parent 355cfba78e
commit 5d453fb0a5
5 changed files with 227 additions and 13578 deletions

View File

@ -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!](./extras/imgs/YATTA.png)
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
View 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

View File

@ -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>

View File

@ -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);