more exhaustive test suite
This commit is contained in:
parent
8aa5dc9866
commit
e9783c8a25
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
build/browser/Frameworks/JsonYatta.min.js
vendored
2
build/browser/Frameworks/JsonYatta.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
build/browser/Frameworks/TextYatta.min.js
vendored
2
build/browser/Frameworks/TextYatta.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
build/browser/Types/JsonTypes.min.js
vendored
2
build/browser/Types/JsonTypes.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
build/browser/Types/StructuredTypes.min.js
vendored
2
build/browser/Types/StructuredTypes.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
build/browser/Types/TextTypes.min.js
vendored
2
build/browser/Types/TextTypes.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
build/browser/index.min.js
vendored
4
build/browser/index.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
{"version":3,"file":"Connectors/PeerJsConnector.js","sources":["Connectors/PeerJsConnector.coffee"],"names":[],"mappings":"CAIA,WAAA,GAAA,EAAA,GAAwB,SAAC,EAAoB,GAE3C,GAAA,GAAA,QAAA,GAAW,GAAA,MAAK,GAKV,EAAA,WAQS,QAAA,GAAE,EAAS,EAAK,EAAqB,GAEhD,GAAA,EAFY,MAAC,OAAA,EAAQ,KAAC,GAAA,EAAI,KAAC,mBAAA,EAAoB,KAAC,MAAA,EAEhD,KAAC,KAAO,EACR,KAAC,eAED,KAAC,KAAK,GAAG,aAAc,SAAA,SAAA,UAAC,SACtB,GAAK,KAAK,OACV,EAAC,cAAc,KAFM,OAIvB,EAAQ,SAAA,SAAA,UAAC,SACP,GAAC,KAAK,KADA,MAER,KAAC,mBAAmB,KAAK,SAX3B,GAAA,UAaA,cAAe,SAAC,GACd,MAAO,OAAA,KAAA,YAAA,IAAsB,IAAQ,KAAC,MAAM,YAC1C,KAAC,cAAc,EAAK,QAAQ,IAD9B,QAdF,EAAA,UAiBA,oBAAqB,WACnB,GAAA,GAAA,CAAA,UAAA,IAAA,MAAA,YACE,EAAA,KAAA,aAnBJ,EAAA,UAqBA,cAAe,SAAC,GACd,GAAA,SAAA,MAAC,YAAY,EAAK,MAAQ,EAE1B,EAAK,GAAG,OAAQ,SAAA,SAAA,UAAC,GACf,GAAA,GAAA,EAAA,EAAA,EAAA,CAAA,IAAW,QAAR,QACD,SAAQ,IAAI,uDACT,IAAG,MAAA,EAAA,SACN,GAAC,OAAO,oBAAoB,EAAK,GAC9B,IAAG,MAAA,EAAA,SACN,GAAC,OAAO,QAAQ,EAAK,GAClB,IAAG,MAAA,EAAA,MAAH,KACH,EAAA,EAAA,MAAA,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACE,EAAA,KAAA,EAAC,cAAc,aAEjB,KAAU,IAAA,OAAM,gCAXJ,OAahB,EAAS,SAAA,SAAA,kBACP,GAAK,MACH,GAAI,EAAC,MAAM,mBAAmB,YAChC,EAAK,MACH,MAAO,EAAC,0BAJH,MAMT,WAAW,EAAQ,MA3CrB,EAAA,UAiDA,KAAM,SAAC,GACL,GAAA,GAAA,EAAA,EAAA,CAAA,IAAG,EAAE,IAAI,UAAW,KAAC,GAAG,aAA6C,gBAA5B,GAAS,IAAI,UAAtD,CACE,EAAA,KAAA,YAAA,SAAA,IAAA,UACE,EAAA,KAAA,EAAK,MACH,GAAI,gBArDZ,EAAA,UA2DA,QAAS,SAAC,GACR,MAAG,GAAE,IAAI,UAAa,KAAC,GAAG,YACxB,KAAC,OAAO,QAAQ,GADlB,aAGJ,EAAK,GAAG,OAAQ,SAAC,SACf,GAAS,EAAiB,MAG9B,OAAO,QAAU,EACd,mBAAA,SAAA,OAAA,SACM,MAAA,OAAA,IACL,OAAO,MACT,OAAO,EAAE,sBAAwB","sourcesContent":["\n#\n# @param {Function} callback The callback is called when the connector is initialized.\n#\ncreatePeerJsConnector = (peer_js_parameters, callback)->\n\n peer = new Peer peer_js_parameters \n\n #\n # @see http://peerjs.com\n #\n class PeerJsConnector\n\n #\n # @param {Engine} engine The transformation engine\n # @param {HistoryBuffer} HB\n # @param {Array<Function>} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called.\n # @param {Yatta} yatta The Yatta framework.\n #\n constructor: (@engine, @HB, @execution_listener, @yatta)->\n\n @peer = peer\n @connections = {}\n\n @peer.on 'connection', (conn)=>\n conn.send \"hey\" # is never send. But without it it won't work either..\n @addConnection conn\n\n send_ = (o)=>\n @send o\n @execution_listener.push send_\n\n connectToPeer: (id)->\n if not @connections[id]? and id isnt @yatta.getUserId()\n @addConnection peer.connect id\n\n getAllConnectionIds: ()->\n for conn_id of @connections\n conn_id\n\n addConnection: (conn)->\n @connections[conn.peer] = conn\n\n conn.on 'data', (data)=>\n if data is \"hey\"\n console.log \"Yatta: Connection received with init message (debug)\" # I can remove this hey stuff when this happens.\n else if data.HB?\n @engine.applyOpsCheckDouble data.HB\n else if data.op?\n @engine.applyOp data.op\n else if data.conns?\n for conn_id in data.conns\n @connectToPeer conn_id\n else\n throw new Error \"Can't parse this operation\"\n\n sendHB = ()=>\n conn.send\n HB: @yatta.getHistoryBuffer()._encode()\n conn.send\n conns: @getAllConnectionIds()\n\n setTimeout sendHB, 1000\n\n #\n # This function is called whenever an operation was executed.\n # @param {Operation} o The operation that was executed.\n #\n send: (o)->\n if o.uid.creator is @HB.getUserId() and (typeof o.uid.op_number isnt \"string\")\n for conn_id,conn of @connections\n conn.send\n op: o\n\n #\n # This function is called whenever an operation was received from another peer.\n # @param {Operation} o The operation that was received.\n #\n receive: (o)->\n if o.uid.creator isnt @HB.getUserId()\n @engine.applyOp o\n\n peer.on 'open', (id)->\n callback PeerJsConnector, id\n\n\nmodule.exports = createPeerJsConnector\nif window?\n if not window.Y?\n window.Y = {}\n window.Y.createPeerJsConnector = createPeerJsConnector\n\n"],"sourceRoot":"/source/"}
|
||||
{"version":3,"file":"Connectors/PeerJsConnector.js","sources":["Connectors/PeerJsConnector.coffee"],"names":[],"mappings":"CAIA,WAAA,GAAA,EAAA,GAAwB,SAAC,EAAoB,GAE3C,GAAA,GAAA,QAAA,GAAW,GAAA,MAAK,GAKV,EAAA,WAQS,QAAA,GAAE,EAAS,EAAK,EAAqB,GAEhD,GAAA,EAFY,MAAC,OAAA,EAAQ,KAAC,GAAA,EAAI,KAAC,mBAAA,EAAoB,KAAC,MAAA,EAEhD,KAAC,KAAO,EACR,KAAC,eAED,KAAC,KAAK,GAAG,aAAc,SAAA,SAAA,UAAC,SACtB,GAAK,KAAK,OACV,EAAC,cAAc,KAFM,OAIvB,EAAQ,SAAA,SAAA,UAAC,SACP,GAAC,KAAK,KADA,MAER,KAAC,mBAAmB,KAAK,SAX3B,GAAA,UAaA,cAAe,SAAC,GACd,MAAO,OAAA,KAAA,YAAA,IAAsB,IAAQ,KAAC,MAAM,YAC1C,KAAC,cAAc,EAAK,QAAQ,IAD9B,QAdF,EAAA,UAiBA,oBAAqB,WACnB,GAAA,GAAA,CAAA,UAAA,IAAA,MAAA,YACE,EAAA,KAAA,aAnBJ,EAAA,UAqBA,cAAe,SAAC,GACd,GAAA,SAAA,MAAC,YAAY,EAAK,MAAQ,EAE1B,EAAK,GAAG,OAAQ,SAAA,SAAA,UAAC,GACf,GAAA,GAAA,EAAA,EAAA,EAAA,CAAA,IAAW,QAAR,QACD,SAAQ,IAAI,uDACT,IAAG,MAAA,EAAA,SACN,GAAC,OAAO,oBAAoB,EAAK,GAC9B,IAAG,MAAA,EAAA,SACN,GAAC,OAAO,QAAQ,EAAK,GAClB,IAAG,MAAA,EAAA,MAAH,KACH,EAAA,EAAA,MAAA,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACE,EAAA,KAAA,EAAC,cAAc,aAEjB,KAAU,IAAA,OAAM,gCAXJ,OAahB,EAAS,SAAA,SAAA,kBACP,GAAK,MACH,GAAI,EAAC,MAAM,mBAAmB,YAChC,EAAK,MACH,MAAO,EAAC,0BAJH,MAMT,WAAW,EAAQ,MA3CrB,EAAA,UAiDA,KAAM,SAAC,GACL,GAAA,GAAA,EAAA,EAAA,CAAA,IAAG,EAAE,IAAI,UAAW,KAAC,GAAG,aAA6C,gBAA5B,GAAS,IAAI,UAAtD,CACE,EAAA,KAAA,YAAA,SAAA,IAAA,UACE,EAAA,KAAA,EAAK,MACH,GAAI,gBArDZ,EAAA,UA2DA,QAAS,SAAC,GACR,MAAG,GAAE,IAAI,UAAa,KAAC,GAAG,YACxB,KAAC,OAAO,QAAQ,GADlB,aAGJ,EAAK,GAAG,OAAQ,SAAC,SACf,GAAS,EAAiB,MAG9B,OAAO,QAAU,EACd,mBAAA,SAAA,OAAA,SACM,MAAA,OAAA,IACL,OAAO,MACT,OAAO,EAAE,sBAAwB","sourcesContent":["\n#\n# @param {Function} callback The callback is called when the connector is initialized.\n#\ncreatePeerJsConnector = (peer_js_parameters, callback)->\n\n peer = new Peer peer_js_parameters\n\n #\n # @see http://peerjs.com\n #\n class PeerJsConnector\n\n #\n # @param {Engine} engine The transformation engine\n # @param {HistoryBuffer} HB\n # @param {Array<Function>} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called.\n # @param {Yatta} yatta The Yatta framework.\n #\n constructor: (@engine, @HB, @execution_listener, @yatta)->\n\n @peer = peer\n @connections = {}\n\n @peer.on 'connection', (conn)=>\n conn.send \"hey\" # is never send. But without it it won't work either..\n @addConnection conn\n\n send_ = (o)=>\n @send o\n @execution_listener.push send_\n\n connectToPeer: (id)->\n if not @connections[id]? and id isnt @yatta.getUserId()\n @addConnection peer.connect id\n\n getAllConnectionIds: ()->\n for conn_id of @connections\n conn_id\n\n addConnection: (conn)->\n @connections[conn.peer] = conn\n\n conn.on 'data', (data)=>\n if data is \"hey\"\n console.log \"Yatta: Connection received with init message (debug)\" # I can remove this hey stuff when this happens.\n else if data.HB?\n @engine.applyOpsCheckDouble data.HB\n else if data.op?\n @engine.applyOp data.op\n else if data.conns?\n for conn_id in data.conns\n @connectToPeer conn_id\n else\n throw new Error \"Can't parse this operation\"\n\n sendHB = ()=>\n conn.send\n HB: @yatta.getHistoryBuffer()._encode()\n conn.send\n conns: @getAllConnectionIds()\n\n setTimeout sendHB, 1000\n\n #\n # This function is called whenever an operation was executed.\n # @param {Operation} o The operation that was executed.\n #\n send: (o)->\n if o.uid.creator is @HB.getUserId() and (typeof o.uid.op_number isnt \"string\")\n for conn_id,conn of @connections\n conn.send\n op: o\n\n #\n # This function is called whenever an operation was received from another peer.\n # @param {Operation} o The operation that was received.\n #\n receive: (o)->\n if o.uid.creator isnt @HB.getUserId()\n @engine.applyOp o\n\n peer.on 'open', (id)->\n callback PeerJsConnector, id\n\n\nmodule.exports = createPeerJsConnector\nif window?\n if not window.Y?\n window.Y = {}\n window.Y.createPeerJsConnector = createPeerJsConnector\n\n"],"sourceRoot":"/source/"}
|
@ -1 +1 @@
|
||||
{"version":3,"file":"Engine.js","sources":["Engine.coffee"],"names":[],"mappings":"CAIA,WAAA,GAAA,EAAM,GAAA,WAMS,QAAA,GAAE,EAAK,GAAN,KAAC,GAAA,EAAI,KAAC,OAAA,EAClB,KAAC,yBADH,GAAA,UAMA,eAAgB,SAAC,GACf,GAAA,EACA,IADA,EAAa,KAAC,OAAO,EAAK,MACvB,MAAA,QACD,GAAW,EAEX,MAAU,IAAA,OAAO,2CAAyC,EAAK,KAAM,oBAAkB,KAAK,UAAU,GAAM,MAXhH,EAAA,UAiBA,eAAgB,SAAC,GACf,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CACA,KADA,KACA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACE,EAAI,KAAK,KAAC,eAAe,GAC3B,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACE,KAAC,GAAG,aAAa,EACnB,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACK,EAAM,WACP,KAAC,gBAAgB,KAAK,SAC1B,MAAC,kBA1BH,EAAA,UAgCA,oBAAqB,SAAC,GACpB,GAAA,GAAA,EAAA,EAAA,MAAA,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,kBACS,MAAA,KAAA,GAAA,aAAA,EAAA,KACL,KAAC,QAAQ,qBAnCf,EAAA,UAwCA,SAAU,SAAC,GACT,GAAA,GAAA,EAAA,EAAA,MAAA,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACE,EAAA,KAAA,KAAC,QAAQ,cA1Cb,EAAA,UA+CA,QAAS,SAAC,GAER,GAAA,SAAA,GAAI,KAAC,eAAe,GACpB,KAAC,GAAG,aAAa,GAEd,EAAM,UAGP,KAAC,GAAG,aAAa,GAFjB,KAAC,gBAAgB,KAAK,GAGxB,KAAC,kBAxDH,EAAA,UA8DA,eAAgB,WACd,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,EAAA,MAAA,OAAA,CAGE,IAFA,EAAa,KAAC,gBAAgB,OAC9B,KACA,EAAA,KAAA,gBAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACK,EAAO,UAGR,KAAC,GAAG,aAAa,GAFjB,EAAY,KAAK,EAIrB,IADA,KAAC,gBAAkB,EAChB,KAAC,gBAAgB,SAAU,EAC5B,oCAKR,OAAO,QAAU","sourcesContent":["\r\n#\r\n# The Engine handles how and in which order to execute operations and add operations to the HistoryBuffer.\r\n#\r\nclass Engine\r\n\r\n #\r\n # @param {HistoryBuffer} HB\r\n # @param {Array} parser Defines how to parse encoded messages.\r\n #\r\n constructor: (@HB, @parser)->\r\n @unprocessed_ops = []\r\n\r\n #\r\n # Parses an operatio from the json format. It uses the specified parser in your OperationType module.\r\n #\r\n parseOperation: (json)->\r\n typeParser = @parser[json.type]\r\n if typeParser?\r\n typeParser json\r\n else\r\n throw new Error \"You forgot to specify a parser for type #{json.type}. The message is #{JSON.stringify json}.\"\r\n\r\n #\r\n # Apply a set of operations. E.g. the operations you received from another users HB.toJson().\r\n # @note You must not use this method when you already have ops in your HB!\r\n #\r\n applyOpsBundle: (ops_json)->\r\n ops = []\r\n for o in ops_json\r\n ops.push @parseOperation o\r\n for o in ops\r\n @HB.addOperation o\r\n for o in ops\r\n if not o.execute()\r\n @unprocessed_ops.push o\r\n @tryUnprocessed()\r\n\r\n #\r\n # Same as applyOps but operations that are already in the HB are not applied.\r\n # @see Engine.applyOps\r\n #\r\n applyOpsCheckDouble: (ops_json)->\r\n for o in ops_json\r\n if not @HB.getOperation(o.uid)?\r\n @applyOp o\r\n\r\n #\r\n # Apply a set of operations. (Helper for using applyOp on Arrays)\r\n # @see Engine.applyOp\r\n applyOps: (ops_json)->\r\n for o in ops_json\r\n @applyOp o\r\n\r\n #\r\n # Apply an operation that you received from another peer.\r\n #\r\n applyOp: (op_json)->\r\n # $parse_and_execute will return false if $o_json was parsed and executed, otherwise the parsed operadion\r\n o = @parseOperation op_json\r\n @HB.addToCounter o\r\n # @HB.addOperation o\r\n if not o.execute()\r\n @unprocessed_ops.push o\r\n else\r\n @HB.addOperation o\r\n @tryUnprocessed()\r\n\r\n #\r\n # Call this method when you applied a new operation.\r\n # It checks if operations that were previously not executable are now executable.\r\n #\r\n tryUnprocessed: ()->\r\n while true\r\n old_length = @unprocessed_ops.length\r\n unprocessed = []\r\n for op in @unprocessed_ops\r\n if not op.execute()\r\n unprocessed.push op\r\n else\r\n @HB.addOperation op\r\n @unprocessed_ops = unprocessed\r\n if @unprocessed_ops.length is old_length\r\n break\r\n\r\n\r\n\r\n\r\nmodule.exports = Engine\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"],"sourceRoot":"/source/"}
|
||||
{"version":3,"file":"Engine.js","sources":["Engine.coffee"],"names":[],"mappings":"CAIA,WAAA,GAAA,EAAM,GAAA,WAMS,QAAA,GAAE,EAAK,GAAN,KAAC,GAAA,EAAI,KAAC,OAAA,EAClB,KAAC,yBADH,GAAA,UAMA,eAAgB,SAAC,GACf,GAAA,EACA,IADA,EAAa,KAAC,OAAO,EAAK,MACvB,MAAA,QACD,GAAW,EAEX,MAAU,IAAA,OAAO,2CAAyC,EAAK,KAAM,oBAAkB,KAAK,UAAU,GAAM,MAXhH,EAAA,UAiBA,eAAgB,SAAC,GACf,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CACA,KADA,KACA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACE,EAAI,KAAK,KAAC,eAAe,GAC3B,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACE,KAAC,GAAG,aAAa,EACnB,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACK,EAAM,WACP,KAAC,gBAAgB,KAAK,SAC1B,MAAC,kBA1BH,EAAA,UAgCA,oBAAqB,SAAC,GACpB,GAAA,GAAA,EAAA,EAAA,MAAA,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,kBACS,MAAA,KAAA,GAAA,aAAA,EAAA,KACL,KAAC,QAAQ,qBAnCf,EAAA,UAwCA,SAAU,SAAC,GACT,GAAA,GAAA,EAAA,EAAA,MAAA,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACE,EAAA,KAAA,KAAC,QAAQ,cA1Cb,EAAA,UA+CA,QAAS,SAAC,GAER,GAAA,SAAA,GAAI,KAAC,eAAe,GACpB,KAAC,GAAG,aAAa,GAEd,EAAM,UAGP,KAAC,GAAG,aAAa,GAFjB,KAAC,gBAAgB,KAAK,GAGxB,KAAC,kBAxDH,EAAA,UA8DA,eAAgB,WACd,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,EAAA,MAAA,OAAA,CAGE,IAFA,EAAa,KAAC,gBAAgB,OAC9B,KACA,EAAA,KAAA,gBAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,WACK,EAAO,UAGR,KAAC,GAAG,aAAa,GAFjB,EAAY,KAAK,EAIrB,IADA,KAAC,gBAAkB,EAChB,KAAC,gBAAgB,SAAU,EAC5B,oCAKR,OAAO,QAAU","sourcesContent":["\r\n#\r\n# The Engine handles how and in which order to execute operations and add operations to the HistoryBuffer.\r\n#\r\nclass Engine\r\n\r\n #\r\n # @param {HistoryBuffer} HB\r\n # @param {Array} parser Defines how to parse encoded messages.\r\n #\r\n constructor: (@HB, @parser)->\r\n @unprocessed_ops = []\r\n\r\n #\r\n # Parses an operatio from the json format. It uses the specified parser in your OperationType module.\r\n #\r\n parseOperation: (json)->\r\n typeParser = @parser[json.type]\r\n if typeParser?\r\n typeParser json\r\n else\r\n throw new Error \"You forgot to specify a parser for type #{json.type}. The message is #{JSON.stringify json}.\"\r\n\r\n #\r\n # Apply a set of operations. E.g. the operations you received from another users HB._encode().\r\n # @note You must not use this method when you already have ops in your HB!\r\n #\r\n applyOpsBundle: (ops_json)->\r\n ops = []\r\n for o in ops_json\r\n ops.push @parseOperation o\r\n for o in ops\r\n @HB.addOperation o\r\n for o in ops\r\n if not o.execute()\r\n @unprocessed_ops.push o\r\n @tryUnprocessed()\r\n\r\n #\r\n # Same as applyOps but operations that are already in the HB are not applied.\r\n # @see Engine.applyOps\r\n #\r\n applyOpsCheckDouble: (ops_json)->\r\n for o in ops_json\r\n if not @HB.getOperation(o.uid)?\r\n @applyOp o\r\n\r\n #\r\n # Apply a set of operations. (Helper for using applyOp on Arrays)\r\n # @see Engine.applyOp\r\n applyOps: (ops_json)->\r\n for o in ops_json\r\n @applyOp o\r\n\r\n #\r\n # Apply an operation that you received from another peer.\r\n #\r\n applyOp: (op_json)->\r\n # $parse_and_execute will return false if $o_json was parsed and executed, otherwise the parsed operadion\r\n o = @parseOperation op_json\r\n @HB.addToCounter o\r\n # @HB.addOperation o\r\n if not o.execute()\r\n @unprocessed_ops.push o\r\n else\r\n @HB.addOperation o\r\n @tryUnprocessed()\r\n\r\n #\r\n # Call this method when you applied a new operation.\r\n # It checks if operations that were previously not executable are now executable.\r\n #\r\n tryUnprocessed: ()->\r\n while true\r\n old_length = @unprocessed_ops.length\r\n unprocessed = []\r\n for op in @unprocessed_ops\r\n if not op.execute()\r\n unprocessed.push op\r\n else\r\n @HB.addOperation op\r\n @unprocessed_ops = unprocessed\r\n if @unprocessed_ops.length is old_length\r\n break\r\n\r\n\r\n\r\n\r\nmodule.exports = Engine\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"],"sourceRoot":"/source/"}
|
@ -1,2 +1,2 @@
|
||||
(function(){var t,e,n,o;o=require("../Types/JsonTypes"),e=require("../HistoryBuffer"),t=require("../Engine"),n=function(){function n(n,r){var i,u;this.HB=new e(n),u=o(this.HB),this.engine=new t(this.HB,u.parser),this.connector=new r(this.engine,this.HB,u.execution_listener,this),i=new u.types.JsonType(this.HB.getReservedUniqueIdentifier()),this.HB.addOperation(i).execute(),this.root_element=i}return n.prototype.getRootElement=function(){return this.root_element},n.prototype.getEngine=function(){return this.engine},n.prototype.getConnector=function(){return this.connector},n.prototype.getHistoryBuffer=function(){return this.HB},n.prototype.setMutableDefault=function(t){return this.root_element.setMutableDefault(t)},n.prototype.getUserId=function(){return this.HB.getUserId()},n.prototype.val=function(t,e,n){return this.root_element.val(t,e,n)},Object.defineProperty(n.prototype,"value",{get:function(){return this.root_element.value},set:function(t){var e,n,o;if(t.constructor==={}.constructor){o=[];for(e in t)n=t[e],o.push(this.val(e,n,"immutable"));return o}throw new Error("You must only set Object values!")}}),n}(),module.exports=n,"undefined"!=typeof window&&null!==window&&(null==window.Y&&(window.Y={}),window.Y.JsonYatta=n)}).call(this);
|
||||
(function(){var t,e,n,o;o=require("../Types/JsonTypes"),e=require("../HistoryBuffer"),t=require("../Engine"),n=function(){function n(n,r){var i,s;this.HB=new e(n),s=o(this.HB),this.types=s.types,this.engine=new t(this.HB,s.parser),this.connector=new r(this.engine,this.HB,s.execution_listener,this),i=new this.types.JsonType(this.HB.getReservedUniqueIdentifier()),this.HB.addOperation(i).execute(),this.root_element=i}return n.prototype.getRootElement=function(){return this.root_element},n.prototype.getEngine=function(){return this.engine},n.prototype.getConnector=function(){return this.connector},n.prototype.getHistoryBuffer=function(){return this.HB},n.prototype.setMutableDefault=function(t){return this.root_element.setMutableDefault(t)},n.prototype.getUserId=function(){return this.HB.getUserId()},n.prototype.toJson=function(){return this.root_element.toJson()},n.prototype.val=function(t,e,n){return this.root_element.val(t,e,n)},Object.defineProperty(n.prototype,"value",{get:function(){return this.root_element.value},set:function(t){var e,n,o;if(t.constructor==={}.constructor){o=[];for(e in t)n=t[e],o.push(this.val(e,n,"immutable"));return o}throw new Error("You must only set Object values!")}}),n}(),module.exports=n,"undefined"!=typeof window&&null!==window&&(null==window.Y&&(window.Y={}),window.Y.JsonYatta=n)}).call(this);
|
||||
//# sourceMappingURL=../Frameworks/JsonYatta.js.map
|
@ -1 +1 @@
|
||||
{"version":3,"file":"Frameworks/JsonYatta.js","sources":["Frameworks/JsonYatta.coffee"],"names":[],"mappings":"CACA,WAAA,GAAA,GAAA,EAAA,EAAA,CAAA,GAA2B,QAAQ,sBACnC,EAAgB,QAAQ,oBACxB,EAAS,QAAQ,aASX,EAAA,WAMS,QAAA,GAAC,EAAS,GACrB,GAAA,GAAA,CAAA,MAAC,GAAS,GAAA,GAAc,GACxB,EAAa,EAAyB,KAAC,IACvC,KAAC,OAAa,GAAA,GAAO,KAAC,GAAI,EAAW,QACrC,KAAC,UAAgB,GAAA,GAAU,KAAC,OAAQ,KAAC,GAAI,EAAW,mBAAoB,MAExE,EAAiB,GAAA,GAAW,MAAM,SAAS,KAAC,GAAG,+BAC/C,KAAC,GAAG,aAAa,GAAY,UAC7B,KAAC,aAAe,QARlB,GAAA,UAaA,eAAgB,iBACd,MAAC,cAdH,EAAA,UAmBA,UAAW,iBACT,MAAC,QApBH,EAAA,UAyBA,aAAc,iBACZ,MAAC,WA1BH,EAAA,UA+BA,iBAAkB,iBAChB,MAAC,IAhCH,EAAA,UAqCA,kBAAmB,SAAC,SAClB,MAAC,aAAa,kBAAkB,IAtClC,EAAA,UA6CA,UAAW,iBACT,MAAC,GAAG,aA9CN,EAAA,UAmDA,IAAM,SAAC,EAAM,EAAS,SACpB,MAAC,aAAa,IAAI,EAAM,EAAS,IAKnC,OAAO,eAAe,EAAU,UAAW,SACzC,IAAM,iBAAG,MAAC,aAAa,OACvB,IAAM,SAAC,GACL,GAAA,GAAA,EAAA,CAAA,IAAG,EAAE,iBAAkB,YAAvB,CACE,SAAA,IAAA,UACE,EAAA,KAAA,KAAC,IAAI,EAAQ,EAAO,uBAEtB,KAAU,IAAA,OAAM,4CAExB,OAAO,QAAU,EACd,mBAAA,SAAA,OAAA,SACM,MAAA,OAAA,IACL,OAAO,MACT,OAAO,EAAE,UAAY","sourcesContent":["\njson_types_uninitialized = require \"../Types/JsonTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Json data-structures.\n# Known values that are supported:\n# * String\n# * Integer\n# * Array\n#\nclass JsonYatta\n\n #\n # @param {String} user_id Unique id of the peer.\n # @param {Connector} Connector the connector class.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n json_types = json_types_uninitialized @HB\n @engine = new Engine @HB, json_types.parser\n @connector = new Connector @engine, @HB, json_types.execution_listener, @\n\n first_word = new json_types.types.JsonType @HB.getReservedUniqueIdentifier()\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result JsonType\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # @see JsonType.setMutableDefault\n #\n setMutableDefault: (mutable)->\n @root_element.setMutableDefault(mutable)\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val : (name, content, mutable)->\n @root_element.val(name, content, mutable)\n\n #\n # @see JsonType.value\n #\n Object.defineProperty JsonYatta.prototype, 'value',\n get : -> @root_element.value\n set : (o)->\n if o.constructor is {}.constructor\n for o_name,o_obj of o\n @val(o_name, o_obj, 'immutable')\n else\n throw new Error \"You must only set Object values!\"\n\nmodule.exports = JsonYatta\nif window?\n if not window.Y?\n window.Y = {}\n window.Y.JsonYatta = JsonYatta\n"],"sourceRoot":"/source/"}
|
||||
{"version":3,"file":"Frameworks/JsonYatta.js","sources":["Frameworks/JsonYatta.coffee"],"names":[],"mappings":"CACA,WAAA,GAAA,GAAA,EAAA,EAAA,CAAA,GAA2B,QAAQ,sBACnC,EAAgB,QAAQ,oBACxB,EAAS,QAAQ,aASX,EAAA,WAMS,QAAA,GAAC,EAAS,GACrB,GAAA,GAAA,CAAA,MAAC,GAAS,GAAA,GAAc,GACxB,EAAe,EAAyB,KAAC,IACzC,KAAC,MAAQ,EAAa,MACtB,KAAC,OAAa,GAAA,GAAO,KAAC,GAAI,EAAa,QACvC,KAAC,UAAgB,GAAA,GAAU,KAAC,OAAQ,KAAC,GAAI,EAAa,mBAAoB,MAE1E,EAAiB,GAAA,MAAC,MAAM,SAAS,KAAC,GAAG,+BACrC,KAAC,GAAG,aAAa,GAAY,UAC7B,KAAC,aAAe,QATlB,GAAA,UAcA,eAAgB,iBACd,MAAC,cAfH,EAAA,UAoBA,UAAW,iBACT,MAAC,QArBH,EAAA,UA0BA,aAAc,iBACZ,MAAC,WA3BH,EAAA,UAgCA,iBAAkB,iBAChB,MAAC,IAjCH,EAAA,UAsCA,kBAAmB,SAAC,SAClB,MAAC,aAAa,kBAAkB,IAvClC,EAAA,UA8CA,UAAW,iBACT,MAAC,GAAG,aA/CN,EAAA,UAoDA,OAAS,iBACP,MAAC,aAAa,UArDhB,EAAA,UA0DA,IAAM,SAAC,EAAM,EAAS,SACpB,MAAC,aAAa,IAAI,EAAM,EAAS,IAKnC,OAAO,eAAe,EAAU,UAAW,SACzC,IAAM,iBAAG,MAAC,aAAa,OACvB,IAAM,SAAC,GACL,GAAA,GAAA,EAAA,CAAA,IAAG,EAAE,iBAAkB,YAAvB,CACE,SAAA,IAAA,UACE,EAAA,KAAA,KAAC,IAAI,EAAQ,EAAO,uBAEtB,KAAU,IAAA,OAAM,4CAExB,OAAO,QAAU,EACd,mBAAA,SAAA,OAAA,SACM,MAAA,OAAA,IACL,OAAO,MACT,OAAO,EAAE,UAAY","sourcesContent":["\njson_types_uninitialized = require \"../Types/JsonTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Json data-structures.\n# Known values that are supported:\n# * String\n# * Integer\n# * Array\n#\nclass JsonYatta\n\n #\n # @param {String} user_id Unique id of the peer.\n # @param {Connector} Connector the connector class.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n type_manager = json_types_uninitialized @HB\n @types = type_manager.types\n @engine = new Engine @HB, type_manager.parser\n @connector = new Connector @engine, @HB, type_manager.execution_listener, @\n\n first_word = new @types.JsonType @HB.getReservedUniqueIdentifier()\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result JsonType\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # @see JsonType.setMutableDefault\n #\n setMutableDefault: (mutable)->\n @root_element.setMutableDefault(mutable)\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.toJson\n #\n toJson : ()->\n @root_element.toJson()\n\n #\n # @see JsonType.val\n #\n val : (name, content, mutable)->\n @root_element.val(name, content, mutable)\n\n #\n # @see JsonType.value\n #\n Object.defineProperty JsonYatta.prototype, 'value',\n get : -> @root_element.value\n set : (o)->\n if o.constructor is {}.constructor\n for o_name,o_obj of o\n @val(o_name, o_obj, 'immutable')\n else\n throw new Error \"You must only set Object values!\"\n\nmodule.exports = JsonYatta\nif window?\n if not window.Y?\n window.Y = {}\n window.Y.JsonYatta = JsonYatta\n"],"sourceRoot":"/source/"}
|
@ -1,2 +1,2 @@
|
||||
(function(){var e,t,n,o;o=require("../Types/TextTypes"),t=require("../HistoryBuffer"),e=require("../Engine"),n=function(){function n(n,r){var i,u,s,p,c;this.HB=new t(n),p=o(this.HB),c=p.types,this.engine=new e(this.HB,p.parser),this.connector=new r(this.engine,this.HB,p.execution_listener,this),i=this.HB.addOperation(new c.Delimiter({creator:"_",op_number:"_beginning"},void 0,void 0)),u=this.HB.addOperation(new c.Delimiter({creator:"_",op_number:"_end"},i,void 0)),i.next_cl=u,i.execute(),u.execute(),s=new p.types.Word({creator:"_",op_number:"_"},i,u),this.HB.addOperation(s).execute(),this.root_element=s}return n.prototype.getRootElement=function(){return this.root_element},n.prototype.getEngine=function(){return this.engine},n.prototype.getConnector=function(){return this.connector},n.prototype.getHistoryBuffer=function(){return this.HB},n.prototype.getUserId=function(){return this.HB.getUserId()},n.prototype.val=function(){return this.root_element.val()},n.prototype.insertText=function(e,t){return this.root_element.insertText(e,t)},n.prototype.deleteText=function(e,t){return this.root_element.deleteText(e,t)},n.prototype.bind=function(e){return this.root_element.bind(e)},n.prototype.replaceText=function(e){return this.root_element.replaceText(e)},n}(),module.exports=n,"undefined"!=typeof window&&null!==window&&(null==window.Y&&(window.Y={}),window.Y.TextYatta=n)}).call(this);
|
||||
(function(){var e,t,n,o;o=require("../Types/TextTypes"),t=require("../HistoryBuffer"),e=require("../Engine"),n=function(){function n(n,r){var i,s,p,u,c,a,d,h;this.HB=new t(n),c=o(this.HB),this.types=c.types,this.engine=new e(this.HB,c.parser),this.connector=new r(this.engine,this.HB,c.execution_listener,this),s=this.HB.addOperation(new this.types.Delimiter({creator:"_",op_number:"_beginning"},void 0,void 0)),p=this.HB.addOperation(new this.types.Delimiter({creator:"_",op_number:"_end"},s,void 0)),s.next_cl=p,s.execute(),p.execute(),u=new this.types.Word({creator:"_",op_number:"_"},s,p),this.HB.addOperation(u).execute(),h={creator:"_",op_number:"RM"},a={creator:"_",op_number:"_RM_beginning"},d={creator:"_",op_number:"_RM_end"},i=this.HB.addOperation(new this.types.Delimiter(a,void 0,d)).execute(),p=this.HB.addOperation(new this.types.Delimiter(d,i,void 0)).execute(),this.root_element=this.HB.addOperation(new this.types.ReplaceManager(void 0,h,i,p)).execute(),this.root_element.replace(u,{creator:"_",op_number:"Replaceable"})}return n.prototype.getRootElement=function(){return this.root_element.val()},n.prototype.getEngine=function(){return this.engine},n.prototype.getConnector=function(){return this.connector},n.prototype.getHistoryBuffer=function(){return this.HB},n.prototype.getUserId=function(){return this.HB.getUserId()},n.prototype.val=function(){return this.getRootElement().val()},n.prototype.insertText=function(e,t){return this.getRootElement().insertText(e,t)},n.prototype.deleteText=function(e,t){return this.getRootElement().deleteText(e,t)},n.prototype.bind=function(e){return this.getRootElement().bind(e)},n.prototype.replaceText=function(e){return this.getRootElement().replaceText(e)},n}(),module.exports=n,"undefined"!=typeof window&&null!==window&&(null==window.Y&&(window.Y={}),window.Y.TextYatta=n)}).call(this);
|
||||
//# sourceMappingURL=../Frameworks/TextYatta.js.map
|
@ -1 +1 @@
|
||||
{"version":3,"file":"Frameworks/TextYatta.js","sources":["Frameworks/TextYatta.coffee"],"names":[],"mappings":"CACA,WAAA,GAAA,GAAA,EAAA,EAAA,CAAA,GAA2B,QAAQ,sBACnC,EAAgB,QAAQ,oBACxB,EAAS,QAAQ,aAKX,EAAA,WAMS,QAAA,GAAC,EAAS,GACrB,GAAA,GAAA,EAAA,EAAA,EAAA,CAAA,MAAC,GAAS,GAAA,GAAc,GACxB,EAAa,EAAyB,KAAC,IACvC,EAAQ,EAAW,MACnB,KAAC,OAAa,GAAA,GAAO,KAAC,GAAI,EAAW,QACrC,KAAC,UAAgB,GAAA,GAAU,KAAC,OAAQ,KAAC,GAAI,EAAW,mBAAoB,MAExE,EAAY,KAAC,GAAG,aAAiB,GAAA,GAAM,WAAW,QAAS,IAAK,UAAW,cAAgB,OAAW,SACtG,EAAY,KAAC,GAAG,aAAiB,GAAA,GAAM,WAAW,QAAS,IAAK,UAAW,QAAgB,EAAW,SACtG,EAAU,QAAU,EACpB,EAAU,UACV,EAAI,UACJ,EAAiB,GAAA,GAAW,MAAM,MAAM,QAAS,IAAK,UAAW,KAAM,EAAW,GAClF,KAAC,GAAG,aAAa,GAAY,UAC7B,KAAC,aAAe,QAdlB,GAAA,UAmBA,eAAgB,iBACd,MAAC,cApBH,EAAA,UAyBA,UAAW,iBACT,MAAC,QA1BH,EAAA,UA+BA,aAAc,iBACZ,MAAC,WAhCH,EAAA,UAqCA,iBAAkB,iBAChB,MAAC,IAtCH,EAAA,UA6CA,UAAW,iBACT,MAAC,GAAG,aA9CN,EAAA,UAmDA,IAAK,iBACH,MAAC,aAAa,OApDhB,EAAA,UAyDA,WAAY,SAAC,EAAK,SAChB,MAAC,aAAa,WAAW,EAAK,IA1DhC,EAAA,UA+DA,WAAY,SAAC,EAAK,SAChB,MAAC,aAAa,WAAW,EAAK,IAhEhC,EAAA,UAqEA,KAAM,SAAC,SACL,MAAC,aAAa,KAAK,IAtErB,EAAA,UA2EA,YAAa,SAAC,SACZ,MAAC,aAAa,YAAY,SAG9B,OAAO,QAAU,EACd,mBAAA,SAAA,OAAA,SACM,MAAA,OAAA,IACL,OAAO,MACT,OAAO,EAAE,UAAY","sourcesContent":["\ntext_types_uninitialized = require \"../Types/TextTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Text Datastructures.\n#\nclass TextYatta\n\n #\n # @param {String} user_id Uniqe user id that defines this peer.\n # @param {Connector} Connector The connector defines how you connect to the other peers.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n text_types = text_types_uninitialized @HB\n types = text_types.types\n @engine = new Engine @HB, text_types.parser\n @connector = new Connector @engine, @HB, text_types.execution_listener, @\n\n beginning = @HB.addOperation new types.Delimiter {creator: '_', op_number: '_beginning'} , undefined, undefined\n end = @HB.addOperation new types.Delimiter {creator: '_', op_number: '_end'} , beginning, undefined\n beginning.next_cl = end\n beginning.execute()\n end.execute()\n first_word = new text_types.types.Word {creator: '_', op_number: '_'}, beginning, end\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result Word\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val: ()->\n @root_element.val()\n\n #\n # @see Word.insertText\n #\n insertText: (pos, content)->\n @root_element.insertText pos, content\n\n #\n # @see Word.deleteText\n #\n deleteText: (pos, length)->\n @root_element.deleteText pos, length\n\n #\n # @see Word.bind\n #\n bind: (textarea)->\n @root_element.bind textarea\n\n #\n # @see Word.replaceText\n #\n replaceText: (text)->\n @root_element.replaceText text\n\n\nmodule.exports = TextYatta\nif window?\n if not window.Y?\n window.Y = {}\n window.Y.TextYatta = TextYatta\n"],"sourceRoot":"/source/"}
|
||||
{"version":3,"file":"Frameworks/TextYatta.js","sources":["Frameworks/TextYatta.coffee"],"names":[],"mappings":"CACA,WAAA,GAAA,GAAA,EAAA,EAAA,CAAA,GAA2B,QAAQ,sBACnC,EAAgB,QAAQ,oBACxB,EAAS,QAAQ,aAKX,EAAA,WAMS,QAAA,GAAC,EAAS,GACrB,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA,MAAC,GAAS,GAAA,GAAc,GACxB,EAAa,EAAyB,KAAC,IACvC,KAAC,MAAQ,EAAW,MACpB,KAAC,OAAa,GAAA,GAAO,KAAC,GAAI,EAAW,QACrC,KAAC,UAAgB,GAAA,GAAU,KAAC,OAAQ,KAAC,GAAI,EAAW,mBAAoB,MAExE,EAAY,KAAC,GAAG,aAAiB,GAAA,MAAC,MAAM,WAAW,QAAS,IAAK,UAAW,cAAgB,OAAW,SACvG,EAAY,KAAC,GAAG,aAAiB,GAAA,MAAC,MAAM,WAAW,QAAS,IAAK,UAAW,QAAgB,EAAW,SACvG,EAAU,QAAU,EACpB,EAAU,UACV,EAAI,UACJ,EAAiB,GAAA,MAAC,MAAM,MAAM,QAAS,IAAK,UAAW,KAAM,EAAW,GACxE,KAAC,GAAG,aAAa,GAAY,UAE7B,GAAU,QAAS,IAAK,UAAW,MACnC,GAAY,QAAS,IAAK,UAAW,iBACrC,GAAY,QAAS,IAAK,UAAW,WACrC,EAAM,KAAC,GAAG,aAAiB,GAAA,MAAC,MAAM,UAAU,EAAS,OAAW,IAAS,UACzE,EAAM,KAAC,GAAG,aAAiB,GAAA,MAAC,MAAM,UAAU,EAAS,EAAK,SAAW,UACrE,KAAC,aAAe,KAAC,GAAG,aAAiB,GAAA,MAAC,MAAM,eAAe,OAAW,EAAO,EAAK,IAAK,UACvF,KAAC,aAAa,QAAQ,GAAc,QAAS,IAAK,UAAW,sBArB/D,GAAA,UA2BA,eAAgB,iBACd,MAAC,aAAa,OA5BhB,EAAA,UAiCA,UAAW,iBACT,MAAC,QAlCH,EAAA,UAuCA,aAAc,iBACZ,MAAC,WAxCH,EAAA,UA6CA,iBAAkB,iBAChB,MAAC,IA9CH,EAAA,UAqDA,UAAW,iBACT,MAAC,GAAG,aAtDN,EAAA,UA2DA,IAAK,iBACH,MAAC,iBAAiB,OA5DpB,EAAA,UAiEA,WAAY,SAAC,EAAK,SAChB,MAAC,iBAAiB,WAAW,EAAK,IAlEpC,EAAA,UAuEA,WAAY,SAAC,EAAK,SAChB,MAAC,iBAAiB,WAAW,EAAK,IAxEpC,EAAA,UA6EA,KAAM,SAAC,SACL,MAAC,iBAAiB,KAAK,IA9EzB,EAAA,UAmFA,YAAa,SAAC,SACZ,MAAC,iBAAiB,YAAY,SAGlC,OAAO,QAAU,EACd,mBAAA,SAAA,OAAA,SACM,MAAA,OAAA,IACL,OAAO,MACT,OAAO,EAAE,UAAY","sourcesContent":["\ntext_types_uninitialized = require \"../Types/TextTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Text Datastructures.\n#\nclass TextYatta\n\n #\n # @param {String} user_id Uniqe user id that defines this peer.\n # @param {Connector} Connector The connector defines how you connect to the other peers.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n text_types = text_types_uninitialized @HB\n @types = text_types.types\n @engine = new Engine @HB, text_types.parser\n @connector = new Connector @engine, @HB, text_types.execution_listener, @\n\n beginning = @HB.addOperation new @types.Delimiter {creator: '_', op_number: '_beginning'} , undefined, undefined\n end = @HB.addOperation new @types.Delimiter {creator: '_', op_number: '_end'} , beginning, undefined\n beginning.next_cl = end\n beginning.execute()\n end.execute()\n first_word = new @types.Word {creator: '_', op_number: '_'}, beginning, end\n @HB.addOperation(first_word).execute()\n\n uid_r = { creator: '_', op_number: \"RM\" }\n uid_beg = { creator: '_', op_number: \"_RM_beginning\" }\n uid_end = { creator: '_', op_number: \"_RM_end\" }\n beg = @HB.addOperation(new @types.Delimiter uid_beg, undefined, uid_end).execute()\n end = @HB.addOperation(new @types.Delimiter uid_end, beg, undefined).execute()\n @root_element = @HB.addOperation(new @types.ReplaceManager undefined, uid_r, beg, end).execute()\n @root_element.replace first_word, { creator: '_', op_number: 'Replaceable'}\n\n\n #\n # @result Word\n #\n getRootElement: ()->\n @root_element.val()\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val: ()->\n @getRootElement().val()\n\n #\n # @see Word.insertText\n #\n insertText: (pos, content)->\n @getRootElement().insertText pos, content\n\n #\n # @see Word.deleteText\n #\n deleteText: (pos, length)->\n @getRootElement().deleteText pos, length\n\n #\n # @see Word.bind\n #\n bind: (textarea)->\n @getRootElement().bind textarea\n\n #\n # @see Word.replaceText\n #\n replaceText: (text)->\n @getRootElement().replaceText text\n\n\nmodule.exports = TextYatta\nif window?\n if not window.Y?\n window.Y = {}\n window.Y.TextYatta = TextYatta\n"],"sourceRoot":"/source/"}
|
@ -1,2 +1,2 @@
|
||||
(function(){var t,e={}.hasOwnProperty,r=function(t,r){function n(){this.constructor=t}for(var o in r)e.call(r,o)&&(t[o]=r[o]);return n.prototype=r.prototype,t.prototype=new n,t.__super__=r.prototype,t};t=require("./TextTypes"),module.exports=function(e){var n,o,u,i,a;return i=t(e),a=i.types,u=i.parser,o=function(t){var e;return new(e=function(){function t(e){var r,u,i,l;l=e.map,i=function(r,u){return Object.defineProperty(t.prototype,r,{get:function(){var t;return t=u.val(),t instanceof n?o(t):t instanceof a.ImmutableObject?t.val():t},set:function(t){var n,o,u,i;if(t.constructor==={}.constructor){u=e.val(r),i=[];for(n in t)o=t[n],i.push(u.val(n,o,"immutable"));return i}return e.val(r,t,"immutable")},enumerable:!0,configurable:!1})};for(r in l)u=l[r],i(r,u)}return t}())(t)},n=function(t){function n(t,e,r){var o,u;if(n.__super__.constructor.call(this,t),null!=e){if("object"!=typeof e)throw new Error("The initial value of JsonTypes must be of type Object! (current type: "+typeof e+")");for(o in e)u=e[o],this.val(o,u,r)}}return r(n,t),n.prototype.mutable_default=!0,n.prototype.setMutableDefault=function(t){if(t===!0||"mutable"===t)n.prototype.mutable_default=!0;else{if(t!==!1&&"immutable"!==t)throw new Error('Set mutable either "mutable" or "immutable"!');n.prototype.mutable_default=!1}return"OK"},n.prototype.val=function(t,r,o){var u,i,l,c,p;if("object"==typeof t){for(l in t)i=t[l],this.val(l,i,r);return this}if(null!=t&&null!=r){if(o=null!=o?o===!0||"mutable"===o?!0:!1:this.mutable_default,"function"==typeof r)return this;if(o&&"number"!=typeof r||r.constructor===Object){if("string"==typeof r)return p=e.addOperation(new a.Word(void 0)).execute(),p.insertText(0,r),n.__super__.val.call(this,t,p);if(r.constructor===Object)return u=e.addOperation(new n(void 0,r,o)).execute(),n.__super__.val.call(this,t,u);throw new Error("You must not set "+typeof r+"-types in collaborative Json-objects!")}return c=e.addOperation(new a.ImmutableObject(void 0,r)).execute(),n.__super__.val.call(this,t,c)}return n.__super__.val.call(this,t,r)},Object.defineProperty(n.prototype,"value",{get:function(){return o(this)},set:function(t){var e,r,n;if(t.constructor==={}.constructor){n=[];for(e in t)r=t[e],n.push(this.val(e,r,"immutable"));return n}throw new Error("You must only set Object values!")}}),n.prototype._encode=function(){return{type:"JsonType",uid:this.getUid()}},n}(a.MapManager),u.JsonType=function(t){var e;return e=t.uid,new n(e)},a.JsonType=n,i}}).call(this);
|
||||
(function(){var t,e={}.hasOwnProperty,r=function(t,r){function o(){this.constructor=t}for(var n in r)e.call(r,n)&&(t[n]=r[n]);return o.prototype=r.prototype,t.prototype=new o,t.__super__=r.prototype,t};t=require("./TextTypes"),module.exports=function(e){var o,n,u,i,a;return i=t(e),a=i.types,u=i.parser,n=function(t){var e;return new(e=function(){function t(e){var r,u,i,l;l=e.map,i=function(r,u){return Object.defineProperty(t.prototype,r,{get:function(){var t;return t=u.val(),t instanceof o?n(t):t instanceof a.ImmutableObject?t.val():t},set:function(t){var o,n,u,i;if(u=e.val(r),t.constructor==={}.constructor&&u instanceof a.Operation){i=[];for(o in t)n=t[o],i.push(u.val(o,n,"immutable"));return i}return e.val(r,t,"immutable")},enumerable:!0,configurable:!1})};for(r in l)u=l[r],i(r,u)}return t}())(t)},o=function(t){function o(t,e,r){var n,u;if(o.__super__.constructor.call(this,t),null!=e){if("object"!=typeof e)throw new Error("The initial value of JsonTypes must be of type Object! (current type: "+typeof e+")");for(n in e)u=e[n],this.val(n,u,r)}}return r(o,t),o.prototype.toJson=function(){var t,e,r,o;o=this.val(),t={};for(e in o)if(r=o[e],r.constructor==={}.constructor)t[e]=this.val(e).toJson();else if(r instanceof a.Operation){for(;r instanceof a.Operation;)r=r.val();t[e]=r}else t[e]=r;return t},o.prototype.mutable_default=!0,o.prototype.setMutableDefault=function(t){if(t===!0||"mutable"===t)o.prototype.mutable_default=!0;else{if(t!==!1&&"immutable"!==t)throw new Error('Set mutable either "mutable" or "immutable"!');o.prototype.mutable_default=!1}return"OK"},o.prototype.val=function(t,r,n){var u,i,l,c,s;if("object"==typeof t){for(l in t)i=t[l],this.val(l,i,r);return this}if(null!=t&&null!=r){if(n=null!=n?n===!0||"mutable"===n?!0:!1:this.mutable_default,"function"==typeof r)return this;if(n&&"number"!=typeof r||r.constructor===Object){if("string"==typeof r)return s=e.addOperation(new a.Word(void 0)).execute(),s.insertText(0,r),o.__super__.val.call(this,t,s);if(r.constructor===Object)return u=e.addOperation(new o(void 0,r,n)).execute(),o.__super__.val.call(this,t,u);throw new Error("You must not set "+typeof r+"-types in collaborative Json-objects!")}return c=e.addOperation(new a.ImmutableObject(void 0,r)).execute(),o.__super__.val.call(this,t,c)}return o.__super__.val.call(this,t,r)},Object.defineProperty(o.prototype,"value",{get:function(){return n(this)},set:function(t){var e,r,o;if(t.constructor==={}.constructor){o=[];for(e in t)r=t[e],o.push(this.val(e,r,"immutable"));return o}throw new Error("You must only set Object values!")}}),o.prototype._encode=function(){return{type:"JsonType",uid:this.getUid()}},o}(a.MapManager),u.JsonType=function(t){var e;return e=t.uid,new o(e)},a.JsonType=o,i}}).call(this);
|
||||
//# sourceMappingURL=../Types/JsonTypes.js.map
|
File diff suppressed because one or more lines are too long
@ -1,2 +1,2 @@
|
||||
(function(){var e,t={}.hasOwnProperty,n=function(e,n){function i(){this.constructor=e}for(var r in n)t.call(n,r)&&(e[r]=n[r]);return i.prototype=n.prototype,e.prototype=new i,e.__super__=n.prototype,e};e=require("./BasicTypes"),module.exports=function(t){var i,r,a,o,p,s,u,c;return s=e(t),c=s.types,u=s.parser,a=function(e){function r(e){this.map={},r.__super__.constructor.call(this,e)}return n(r,e),r.prototype.val=function(e,n){var a,o,p,s,u;if(null!=n)return null==this.map[e]&&t.addOperation(new i(void 0,this,e)).execute(),this.map[e].replace(n),this;if(null!=e)return o=null!=(s=this.map[e])?s.val():void 0,o instanceof c.ImmutableObject?o.val():o;p={},u=this.map;for(e in u)a=u[e],o=a.val(),(o instanceof c.ImmutableObject||o instanceof r)&&(o=o.val()),p[e]=o;return p},r}(c.Operation),i=function(e){function i(e,t,n){this.name=n,this.saveOperation("map_manager",t),i.__super__.constructor.call(this,e)}return n(i,e),i.prototype.execute=function(){var e,n,r,a,p;return this.validateSavedOperations()?(p=this.map_manager.getUid(),p.op_number="_"+p.op_number+"_RM_"+this.name,null==t.getOperation(p)&&(r=this.map_manager.getUid(),r.op_number="_"+r.op_number+"_RM_"+this.name+"_beginning",a=this.map_manager.getUid(),a.op_number="_"+a.op_number+"_RM_"+this.name+"_end",e=t.addOperation(new c.Delimiter(r,void 0,a)).execute(),n=t.addOperation(new c.Delimiter(a,e,void 0)).execute(),this.map_manager.map[this.name]=t.addOperation(new o(void 0,p,e,n)).execute()),i.__super__.execute.apply(this,arguments)):!1},i.prototype._encode=function(){return{type:"AddName",uid:this.getUid(),map_manager:this.map_manager.getUid(),name:this.name}},i}(c.Operation),u.AddName=function(e){var t,n,r;return t=e.map_manager,r=e.uid,n=e.name,new i(r,t,n)},r=function(e){function i(e,n,r,a,o,p){null!=n&&null!=r?(this.saveOperation("beginning",n),this.saveOperation("end",r)):(this.beginning=t.addOperation(new c.Delimiter(void 0,void 0,void 0)),this.end=t.addOperation(new c.Delimiter(void 0,this.beginning,void 0)),this.beginning.next_cl=this.end,this.beginning.execute(),this.end.execute()),i.__super__.constructor.call(this,e,a,o,p)}return n(i,e),i.prototype.execute=function(){return this.validateSavedOperations()?(this.beginning.setParent(this),this.end.setParent(this),i.__super__.execute.apply(this,arguments)):!1},i.prototype.getLastOperation=function(){return this.end.prev_cl},i.prototype.getFirstOperation=function(){return this.beginning.next_cl},i.prototype.toArray=function(){var e,t;for(e=this.beginning.next_cl,t=[];e!==this.end;)t.push(e),e=e.next_cl;return t},i.prototype.getOperationByPosition=function(e){var t;if(t=this.beginning.next_cl,(e>0||t.isDeleted())&&!(t instanceof c.Delimiter)){for(;t.isDeleted()&&!(t instanceof c.Delimiter);)t=t.next_cl;for(;;){if(t instanceof c.Delimiter)break;if(0>=e&&!t.isDeleted())break;t=t.next_cl,t.isDeleted()||(e-=1)}}return t},i}(c.Insert),o=function(e){function i(e,t,n,r,a,o,p){i.__super__.constructor.call(this,t,n,r,a,o,p),null!=e&&this.replace(e)}return n(i,e),i.prototype.replace=function(e){var n,i;return n=this.getLastOperation(),i=new p(e,this,void 0,n,n.next_cl),t.addOperation(i).execute()},i.prototype.val=function(){var e;if(e=this.getLastOperation(),e instanceof c.Delimiter)throw new Error("dtrn");return e.val()},i.prototype._encode=function(){var e;return e={type:"ReplaceManager",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&null!=this.next_cl&&(e.prev=this.prev_cl.getUid(),e.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},i}(r),u.ReplaceManager=function(e){var t,n,i,r,a,p,s;return n=e.content,s=e.uid,p=e.prev,r=e.next,a=e.origin,t=e.beginning,i=e.end,new o(n,s,t,i,p,r,a)},p=function(e){function t(e,n,i,r,a,o){if(this.saveOperation("content",e),this.saveOperation("parent",n),null==r||null==a||null==e)throw new Error("You must define content, prev, and next for Replaceable-types!");t.__super__.constructor.call(this,i,r,a,o)}return n(t,e),t.prototype.val=function(){return this.content},t.prototype.replace=function(e){return this.parent.replace(e)},t.prototype.execute=function(){var e;return this.validateSavedOperations()?("function"==typeof(e=this.content).setReplaceManager&&e.setReplaceManager(this.parent),t.__super__.execute.apply(this,arguments)):!1},t.prototype._encode=function(){var e;return e={type:"Replaceable",content:this.content.getUid(),ReplaceManager:this.parent.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid(),uid:this.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},t}(c.Insert),u.Replaceable=function(e){var t,n,i,r,a,o;return t=e.content,r=e.ReplaceManager,o=e.uid,a=e.prev,n=e.next,i=e.origin,new p(t,r,o,a,n,i)},c.ListManager=r,c.MapManager=a,c.ReplaceManager=o,c.Replaceable=p,s}}).call(this);
|
||||
(function(){var e,t={}.hasOwnProperty,n=function(e,n){function i(){this.constructor=e}for(var r in n)t.call(n,r)&&(e[r]=n[r]);return i.prototype=n.prototype,e.prototype=new i,e.__super__=n.prototype,e};e=require("./BasicTypes"),module.exports=function(t){var i,r,a,o,p,s,u,c;return s=e(t),c=s.types,u=s.parser,a=function(e){function r(e){this.map={},r.__super__.constructor.call(this,e)}return n(r,e),r.prototype.val=function(e,n){var a,o,p,s,u;if(null!=n)return null==this.map[e]&&t.addOperation(new i(void 0,this,e)).execute(),this.map[e].replace(n),this;if(null!=e)return o=null!=(s=this.map[e])?s.val():void 0,o instanceof c.ImmutableObject?o.val():o;p={},u=this.map;for(e in u)a=u[e],o=a.val(),(o instanceof c.ImmutableObject||o instanceof r)&&(o=o.val()),p[e]=o;return p},r}(c.Operation),i=function(e){function i(e,t,n){this.name=n,this.saveOperation("map_manager",t),i.__super__.constructor.call(this,e)}return n(i,e),i.prototype.execute=function(){var e,n,r,a,p;return this.validateSavedOperations()?(p=this.map_manager.getUid(),p.op_number="_"+p.op_number+"_RM_"+this.name,null==t.getOperation(p)&&(r=this.map_manager.getUid(),r.op_number="_"+r.op_number+"_RM_"+this.name+"_beginning",a=this.map_manager.getUid(),a.op_number="_"+a.op_number+"_RM_"+this.name+"_end",e=t.addOperation(new c.Delimiter(r,void 0,a)).execute(),n=t.addOperation(new c.Delimiter(a,e,void 0)).execute(),this.map_manager.map[this.name]=t.addOperation(new o(void 0,p,e,n)).execute()),i.__super__.execute.apply(this,arguments)):!1},i.prototype._encode=function(){return{type:"AddName",uid:this.getUid(),map_manager:this.map_manager.getUid(),name:this.name}},i}(c.Operation),u.AddName=function(e){var t,n,r;return t=e.map_manager,r=e.uid,n=e.name,new i(r,t,n)},r=function(e){function i(e,n,r,a,o,p){null!=n&&null!=r?(this.saveOperation("beginning",n),this.saveOperation("end",r)):(this.beginning=t.addOperation(new c.Delimiter(void 0,void 0,void 0)),this.end=t.addOperation(new c.Delimiter(void 0,this.beginning,void 0)),this.beginning.next_cl=this.end,this.beginning.execute(),this.end.execute()),i.__super__.constructor.call(this,e,a,o,p)}return n(i,e),i.prototype.execute=function(){return this.validateSavedOperations()?(this.beginning.setParent(this),this.end.setParent(this),i.__super__.execute.apply(this,arguments)):!1},i.prototype.getLastOperation=function(){return this.end.prev_cl},i.prototype.getFirstOperation=function(){return this.beginning.next_cl},i.prototype.toArray=function(){var e,t;for(e=this.beginning.next_cl,t=[];e!==this.end;)t.push(e),e=e.next_cl;return t},i.prototype.getOperationByPosition=function(e){var t;if(t=this.beginning.next_cl,(e>0||t.isDeleted())&&!(t instanceof c.Delimiter)){for(;t.isDeleted()&&!(t instanceof c.Delimiter);)t=t.next_cl;for(;;){if(t instanceof c.Delimiter)break;if(0>=e&&!t.isDeleted())break;t=t.next_cl,t.isDeleted()||(e-=1)}}return t},i}(c.Insert),o=function(e){function i(e,t,n,r,a,o,p){i.__super__.constructor.call(this,t,n,r,a,o,p),null!=e&&this.replace(e)}return n(i,e),i.prototype.replace=function(e,n){var i,r;return i=this.getLastOperation(),r=new p(e,this,n,i,i.next_cl),t.addOperation(r).execute()},i.prototype.val=function(){var e;return e=this.getLastOperation(),"function"==typeof e.val?e.val():void 0},i.prototype._encode=function(){var e;return e={type:"ReplaceManager",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&null!=this.next_cl&&(e.prev=this.prev_cl.getUid(),e.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},i}(r),u.ReplaceManager=function(e){var t,n,i,r,a,p,s;return n=e.content,s=e.uid,p=e.prev,r=e.next,a=e.origin,t=e.beginning,i=e.end,new o(n,s,t,i,p,r,a)},p=function(e){function t(e,n,i,r,a,o){if(this.saveOperation("content",e),this.saveOperation("parent",n),null==r||null==a||null==e)throw new Error("You must define content, prev, and next for Replaceable-types!");t.__super__.constructor.call(this,i,r,a,o)}return n(t,e),t.prototype.val=function(){return this.content},t.prototype.replace=function(e){return this.parent.replace(e)},t.prototype.execute=function(){var e;return this.validateSavedOperations()?("function"==typeof(e=this.content).setReplaceManager&&e.setReplaceManager(this.parent),t.__super__.execute.apply(this,arguments)):!1},t.prototype._encode=function(){var e;return e={type:"Replaceable",content:this.content.getUid(),ReplaceManager:this.parent.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid(),uid:this.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},t}(c.Insert),u.Replaceable=function(e){var t,n,i,r,a,o;return t=e.content,r=e.ReplaceManager,o=e.uid,a=e.prev,n=e.next,i=e.origin,new p(t,r,o,a,n,i)},c.ListManager=r,c.MapManager=a,c.ReplaceManager=o,c.Replaceable=p,s}}).call(this);
|
||||
//# sourceMappingURL=../Types/StructuredTypes.js.map
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
||||
{"version":3,"file":"Types/XmlTypes.js","sources":["Types/XmlTypes.coffee"],"names":[],"mappings":"CAyRkB","sourcesContent":[""],"sourceRoot":"/source/"}
|
||||
{"version":3,"file":"Types/XmlTypes.js","sources":["Types/XmlTypes.coffee"],"names":[],"mappings":"CA0H8B","sourcesContent":[""],"sourceRoot":"/source/"}
|
14337
build/test/JsonYatta_test.js
Normal file
14337
build/test/JsonYatta_test.js
Normal file
File diff suppressed because one or more lines are too long
14062
build/test/TextYatta_test.js
Normal file
14062
build/test/TextYatta_test.js
Normal file
File diff suppressed because one or more lines are too long
13898
build/test/Yatta_test.js
13898
build/test/Yatta_test.js
File diff suppressed because one or more lines are too long
@ -8,7 +8,8 @@
|
||||
<div id="mocha"></div>
|
||||
<script src="../../node_modules/mocha/mocha.js"></script>
|
||||
<script>mocha.setup('bdd')</script>
|
||||
<script src="Yatta_test.js"></script>
|
||||
<script src="TextYatta_test.js"></script>
|
||||
<script src="JsonYatta_test.js"></script>
|
||||
<script>
|
||||
mocha.checkLeaks();
|
||||
mocha.run();
|
||||
|
@ -15,6 +15,14 @@ Open [index.html](./index.html) in order to start collaboration.
|
||||
var yatta;
|
||||
|
||||
function init(){
|
||||
```
|
||||
|
||||
|
||||
First create the connector - the underlaying communication protocol.
|
||||
Here, we use the PeerJs connector. Its first parameter is the API key that you need to specify (see [website](http://peerjs.com/))
|
||||
|
||||
|
||||
```js
|
||||
Y.createPeerJsConnector({key: 'h7nlefbgavh1tt9'}, function(Connector, user_id){
|
||||
```
|
||||
|
||||
|
@ -23,7 +23,7 @@ files =
|
||||
lib : ['./lib/**/*.coffee']
|
||||
build : ['./build/**']
|
||||
browser : ['./lib/**/*.coffee', './lib/Connectors/**/*', './lib/Frameworks/**/*', './lib/index.coffee']
|
||||
test : ['./test/**/*.coffee']
|
||||
test : ['./test/**/*_test.coffee']
|
||||
gulp : ['./gulpfile.coffee']
|
||||
examples : ['./examples/**/*.js']
|
||||
|
||||
@ -56,6 +56,15 @@ gulp.task 'browser', ->
|
||||
.pipe gulp.dest 'build/browser'
|
||||
.pipe gulpif '!**/', git.add({args : "-A"})
|
||||
|
||||
gulp.src files.test, {read: false}
|
||||
.pipe browserify
|
||||
transform: ['coffeeify']
|
||||
extensions: ['.coffee']
|
||||
debug: true
|
||||
.pipe rename
|
||||
extname: ".js"
|
||||
.pipe gulp.dest './build/test'
|
||||
|
||||
gulp.task 'test', ->
|
||||
gulp.src files.test, { read: false }
|
||||
.pipe mocha {reporter : 'list'}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#
|
||||
createPeerJsConnector = (peer_js_parameters, callback)->
|
||||
|
||||
peer = new Peer peer_js_parameters
|
||||
peer = new Peer peer_js_parameters
|
||||
|
||||
#
|
||||
# @see http://peerjs.com
|
||||
|
@ -22,7 +22,7 @@ class Engine
|
||||
throw new Error "You forgot to specify a parser for type #{json.type}. The message is #{JSON.stringify json}."
|
||||
|
||||
#
|
||||
# Apply a set of operations. E.g. the operations you received from another users HB.toJson().
|
||||
# Apply a set of operations. E.g. the operations you received from another users HB._encode().
|
||||
# @note You must not use this method when you already have ops in your HB!
|
||||
#
|
||||
applyOpsBundle: (ops_json)->
|
||||
|
@ -18,11 +18,12 @@ class JsonYatta
|
||||
#
|
||||
constructor: (user_id, Connector)->
|
||||
@HB = new HistoryBuffer user_id
|
||||
json_types = json_types_uninitialized @HB
|
||||
@engine = new Engine @HB, json_types.parser
|
||||
@connector = new Connector @engine, @HB, json_types.execution_listener, @
|
||||
type_manager = json_types_uninitialized @HB
|
||||
@types = type_manager.types
|
||||
@engine = new Engine @HB, type_manager.parser
|
||||
@connector = new Connector @engine, @HB, type_manager.execution_listener, @
|
||||
|
||||
first_word = new json_types.types.JsonType @HB.getReservedUniqueIdentifier()
|
||||
first_word = new @types.JsonType @HB.getReservedUniqueIdentifier()
|
||||
@HB.addOperation(first_word).execute()
|
||||
@root_element = first_word
|
||||
|
||||
@ -64,6 +65,12 @@ class JsonYatta
|
||||
getUserId: ()->
|
||||
@HB.getUserId()
|
||||
|
||||
#
|
||||
# @see JsonType.toJson
|
||||
#
|
||||
toJson : ()->
|
||||
@root_element.toJson()
|
||||
|
||||
#
|
||||
# @see JsonType.val
|
||||
#
|
||||
|
@ -15,24 +15,32 @@ class TextYatta
|
||||
constructor: (user_id, Connector)->
|
||||
@HB = new HistoryBuffer user_id
|
||||
text_types = text_types_uninitialized @HB
|
||||
types = text_types.types
|
||||
@types = text_types.types
|
||||
@engine = new Engine @HB, text_types.parser
|
||||
@connector = new Connector @engine, @HB, text_types.execution_listener, @
|
||||
|
||||
beginning = @HB.addOperation new types.Delimiter {creator: '_', op_number: '_beginning'} , undefined, undefined
|
||||
end = @HB.addOperation new types.Delimiter {creator: '_', op_number: '_end'} , beginning, undefined
|
||||
beginning = @HB.addOperation new @types.Delimiter {creator: '_', op_number: '_beginning'} , undefined, undefined
|
||||
end = @HB.addOperation new @types.Delimiter {creator: '_', op_number: '_end'} , beginning, undefined
|
||||
beginning.next_cl = end
|
||||
beginning.execute()
|
||||
end.execute()
|
||||
first_word = new text_types.types.Word {creator: '_', op_number: '_'}, beginning, end
|
||||
first_word = new @types.Word {creator: '_', op_number: '_'}, beginning, end
|
||||
@HB.addOperation(first_word).execute()
|
||||
@root_element = first_word
|
||||
|
||||
uid_r = { creator: '_', op_number: "RM" }
|
||||
uid_beg = { creator: '_', op_number: "_RM_beginning" }
|
||||
uid_end = { creator: '_', op_number: "_RM_end" }
|
||||
beg = @HB.addOperation(new @types.Delimiter uid_beg, undefined, uid_end).execute()
|
||||
end = @HB.addOperation(new @types.Delimiter uid_end, beg, undefined).execute()
|
||||
@root_element = @HB.addOperation(new @types.ReplaceManager undefined, uid_r, beg, end).execute()
|
||||
@root_element.replace first_word, { creator: '_', op_number: 'Replaceable'}
|
||||
|
||||
|
||||
#
|
||||
# @result Word
|
||||
#
|
||||
getRootElement: ()->
|
||||
@root_element
|
||||
@root_element.val()
|
||||
|
||||
#
|
||||
# @see Engine
|
||||
@ -64,31 +72,31 @@ class TextYatta
|
||||
# @see JsonType.val
|
||||
#
|
||||
val: ()->
|
||||
@root_element.val()
|
||||
@getRootElement().val()
|
||||
|
||||
#
|
||||
# @see Word.insertText
|
||||
#
|
||||
insertText: (pos, content)->
|
||||
@root_element.insertText pos, content
|
||||
@getRootElement().insertText pos, content
|
||||
|
||||
#
|
||||
# @see Word.deleteText
|
||||
#
|
||||
deleteText: (pos, length)->
|
||||
@root_element.deleteText pos, length
|
||||
@getRootElement().deleteText pos, length
|
||||
|
||||
#
|
||||
# @see Word.bind
|
||||
#
|
||||
bind: (textarea)->
|
||||
@root_element.bind textarea
|
||||
@getRootElement().bind textarea
|
||||
|
||||
#
|
||||
# @see Word.replaceText
|
||||
#
|
||||
replaceText: (text)->
|
||||
@root_element.replaceText text
|
||||
@getRootElement().replaceText text
|
||||
|
||||
|
||||
module.exports = TextYatta
|
||||
|
@ -81,8 +81,8 @@ module.exports = (HB)->
|
||||
else
|
||||
x
|
||||
set : (o)->
|
||||
if o.constructor is {}.constructor
|
||||
overwrite = jsonType.val(name)
|
||||
overwrite = jsonType.val(name)
|
||||
if o.constructor is {}.constructor and overwrite instanceof types.Operation
|
||||
for o_name,o_obj of o
|
||||
overwrite.val(o_name, o_obj, 'immutable')
|
||||
else
|
||||
@ -109,6 +109,24 @@ module.exports = (HB)->
|
||||
for name,o of initial_value
|
||||
@val name, o, mutable
|
||||
|
||||
#
|
||||
# Transform this to a Json and loose all the sharing-abilities (the new object will be a deep clone)!
|
||||
# @return {Json}
|
||||
#
|
||||
toJson: ()->
|
||||
val = @val()
|
||||
json = {}
|
||||
for name, o of val
|
||||
if o.constructor is {}.constructor
|
||||
json[name] = @val(name).toJson()
|
||||
else if o instanceof types.Operation
|
||||
while o instanceof types.Operation
|
||||
o = o.val()
|
||||
json[name] = o
|
||||
else
|
||||
json[name] = o
|
||||
json
|
||||
|
||||
#
|
||||
# Whether the default is 'mutable' (true) or 'immutable' (false)
|
||||
#
|
||||
|
@ -77,7 +77,6 @@ module.exports = (HB)->
|
||||
uid_end.op_number = "_#{uid_end.op_number}_RM_#{@name}_end"
|
||||
beg = HB.addOperation(new types.Delimiter uid_beg, undefined, uid_end).execute()
|
||||
end = HB.addOperation(new types.Delimiter uid_end, beg, undefined).execute()
|
||||
#beg.execute()
|
||||
@map_manager.map[@name] = HB.addOperation(new ReplaceManager undefined, uid_r, beg, end).execute()
|
||||
super
|
||||
|
||||
@ -191,9 +190,12 @@ module.exports = (HB)->
|
||||
#
|
||||
# Replace the existing word with a new word.
|
||||
#
|
||||
replace: (content)->
|
||||
# @param content {Operation} The new value of this ReplaceManager.
|
||||
# @param replaceable_uid {UID} Optional: Unique id of the Replaceable that is created
|
||||
#
|
||||
replace: (content, replaceable_uid)->
|
||||
o = @getLastOperation()
|
||||
op = new Replaceable content, @, undefined, o, o.next_cl
|
||||
op = new Replaceable content, @, replaceable_uid, o, o.next_cl
|
||||
HB.addOperation(op).execute()
|
||||
|
||||
#
|
||||
@ -202,9 +204,9 @@ module.exports = (HB)->
|
||||
#
|
||||
val: ()->
|
||||
o = @getLastOperation()
|
||||
if o instanceof types.Delimiter
|
||||
throw new Error "dtrn"
|
||||
o.val()
|
||||
#if o instanceof types.Delimiter
|
||||
# throw new Error "Replace Manager doesn't contain anything."
|
||||
o.val?() # ? - for the case that (currently) the RM does not contain anything (then o is a Delimiter)
|
||||
|
||||
#
|
||||
# Encode this operation in such a way that it can be parsed by remote peers.
|
||||
|
138
test/JsonYatta_test.coffee
Normal file
138
test/JsonYatta_test.coffee
Normal file
@ -0,0 +1,138 @@
|
||||
chai = require('chai')
|
||||
expect = chai.expect
|
||||
should = chai.should()
|
||||
sinon = require('sinon')
|
||||
sinonChai = require('sinon-chai')
|
||||
_ = require("underscore")
|
||||
|
||||
chai.use(sinonChai)
|
||||
|
||||
Y = require "../lib/index"
|
||||
Connector_uninitialized = require "../lib/Connectors/TestConnector"
|
||||
|
||||
Test = require "./TestSuite"
|
||||
|
||||
class JsonTest extends Test
|
||||
makeNewUser: (user, conn)->
|
||||
new Y.JsonYatta user, conn
|
||||
|
||||
getRandomRoot: (user_num, root)->
|
||||
root ?= @users[user_num].getRootElement()
|
||||
types = @users[user_num].types
|
||||
if _.random(0,1) is 1 # take root
|
||||
root
|
||||
else # take child
|
||||
properties =
|
||||
for oname,val of root.val()
|
||||
oname
|
||||
properties.filter (oname)->
|
||||
root[oname] instanceof types.Operation
|
||||
if properties.length is 0
|
||||
root
|
||||
else
|
||||
p = root[properties[_.random(0, properties.length-1)]]
|
||||
@getRandomRoot user_num, p
|
||||
|
||||
getContent: (user_num)->
|
||||
@users[user_num].toJson()
|
||||
|
||||
getGeneratingFunctions: (user_num)->
|
||||
types = @users[user_num].types
|
||||
super(user_num).concat [
|
||||
f : (y)=> # SET PROPERTY
|
||||
y.val(@getRandomKey(), @getRandomText(), 'immutable')
|
||||
null
|
||||
types : [types.JsonType]
|
||||
,
|
||||
f : (y)=> # SET Object Property 1)
|
||||
y.val(@getRandomObject())
|
||||
types: [types.JsonType]
|
||||
,
|
||||
f : (y)=> # SET Object Property 2)
|
||||
y.val(@getRandomKey(), @getRandomObject())
|
||||
types: [types.JsonType]
|
||||
,
|
||||
f : (y)=> # SET PROPERTY TEXT
|
||||
y.val(@getRandomKey(), @getRandomText(), 'mutable')
|
||||
types: [types.JsonType]
|
||||
]
|
||||
|
||||
|
||||
|
||||
describe "JsonYatta", ->
|
||||
beforeEach (done)->
|
||||
@timeout 50000
|
||||
@yTest = new JsonTest()
|
||||
@users = @yTest.users
|
||||
|
||||
@test_user = @yTest.makeNewUser 0, (Connector_uninitialized [])
|
||||
done()
|
||||
|
||||
it "can handle many engines, many operations, concurrently (random)", ->
|
||||
@yTest.run()
|
||||
|
||||
it "has a JsonWrapper", ->
|
||||
y = this.yTest.getSomeUser().root_element
|
||||
y.val('x',"dtrn", 'immutable')
|
||||
y.val('set',{x:"x"}, 'immutable')
|
||||
w = y.value
|
||||
w.x
|
||||
w.set = {y:""}
|
||||
w.x
|
||||
w.set
|
||||
w.set.x
|
||||
expect(w.x).to.equal("dtrn")
|
||||
expect(w.set.x).to.equal("x")
|
||||
y.value.x = {q:4}
|
||||
expect(y.value.x.q).to.equal(4)
|
||||
|
||||
it "handles double-late-join", ->
|
||||
test = new JsonTest("double")
|
||||
test.run()
|
||||
@yTest.run()
|
||||
u1 = test.users[0]
|
||||
u2 = @yTest.users[1]
|
||||
ops1 = u1.HB._encode()
|
||||
ops2 = u2.HB._encode()
|
||||
u1.engine.applyOps ops2
|
||||
u2.engine.applyOps ops1
|
||||
expect(u2.value.name.val()).to.equal(u2.value.name.val())
|
||||
|
||||
|
||||
|
||||
it "can handle creaton of complex json", ->
|
||||
@yTest.getSomeUser().val('x', {'a':'b'})
|
||||
@yTest.getSomeUser().val('a', {'a':{q:"dtrndtrtdrntdrnrtdnrtdnrtdnrtdnrdnrdt"}})
|
||||
@yTest.getSomeUser().val('b', {'a':{}})
|
||||
@yTest.getSomeUser().val('c', {'a':'c'})
|
||||
@yTest.getSomeUser().val('c', {'a':'b'})
|
||||
@yTest.compareAll()
|
||||
@yTest.getSomeUser().value.a.a.q.insertText(0,'AAA')
|
||||
@yTest.compareAll()
|
||||
expect(@yTest.getSomeUser().value.a.a.q.val()).to.equal("AAAdtrndtrtdrntdrnrtdnrtdnrtdnrtdnrdnrdt")
|
||||
|
||||
|
||||
it "handles some immutable tests", ->
|
||||
@yTest.getSomeUser().val('string', "text", "immutable")
|
||||
@yTest.getSomeUser().val('number', 4, "immutable")
|
||||
@yTest.getSomeUser().val('object', {q:"rr"}, "immutable")
|
||||
@yTest.compareAll()
|
||||
expect(@yTest.getSomeUser().val('string')).to.equal "text"
|
||||
expect(@yTest.getSomeUser().val('number')).to.equal 4
|
||||
expect(@yTest.getSomeUser().val('object').val('q')).to.equal "rr"
|
||||
|
||||
it "converges t1", ->
|
||||
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]
|
||||
@test_user.engine.applyOps ops
|
||||
expect(@test_user.val('name').val()).to.equal("duaw")
|
||||
|
187
test/TestSuite.coffee
Normal file
187
test/TestSuite.coffee
Normal file
@ -0,0 +1,187 @@
|
||||
chai = require('chai')
|
||||
expect = chai.expect
|
||||
should = chai.should()
|
||||
sinon = require('sinon')
|
||||
sinonChai = require('sinon-chai')
|
||||
_ = require("underscore")
|
||||
|
||||
chai.use(sinonChai)
|
||||
|
||||
Y = require "../lib/index"
|
||||
Connector_uninitialized = require "../lib/Connectors/TestConnector"
|
||||
|
||||
module.exports = class Test
|
||||
constructor: (@name_suffix = "")->
|
||||
@number_of_test_cases_multiplier = 1
|
||||
@repeat_this = 1 * @number_of_test_cases_multiplier
|
||||
@doSomething_amount = 200 * @number_of_test_cases_multiplier
|
||||
@number_of_engines = 7 + @number_of_test_cases_multiplier - 1
|
||||
|
||||
@time = 0
|
||||
@ops = 0
|
||||
@time_now = 0
|
||||
|
||||
@debug = false
|
||||
|
||||
@reinitialize()
|
||||
|
||||
reinitialize: ()->
|
||||
@users = []
|
||||
@Connector = Connector_uninitialized @users
|
||||
for i in [0...@number_of_engines]
|
||||
@users.push @makeNewUser (i+@name_suffix), @Connector
|
||||
@users[0].val('name',"i")
|
||||
@flushAll()
|
||||
|
||||
makeNewUser: (user_id, Connector)->
|
||||
throw new Error "overwrite me!"
|
||||
|
||||
getSomeUser: ()->
|
||||
i = _.random 0, (@users.length-1)
|
||||
@users[i]
|
||||
|
||||
getRandomText: (chars, min_length = 0)->
|
||||
chars ?= "abcdefghijklmnopqrstuvwxyz"
|
||||
length = _.random min_length, 10
|
||||
nextchar = chars[(_.random 0, (chars.length-1))]
|
||||
text = ""
|
||||
_(length).times ()-> text += nextchar
|
||||
text
|
||||
|
||||
getRandomObject: ()->
|
||||
result = {}
|
||||
key1 = @getRandomKey()
|
||||
key2 = @getRandomKey()
|
||||
val1 = @getRandomText()
|
||||
val2 = null
|
||||
if _.random(0,1) is 1
|
||||
val2 = @getRandomObject()
|
||||
else
|
||||
val2 = @getRandomText()
|
||||
result[key1] = val1
|
||||
result[key2] = val2
|
||||
result
|
||||
|
||||
getRandomKey: ()->
|
||||
@getRandomText [1,2,'x','y'], 1 # only 4 keys
|
||||
|
||||
getGeneratingFunctions: (user_num)=>
|
||||
types = @users[user_num].types
|
||||
[
|
||||
f : (y)=> # INSERT TEXT
|
||||
y
|
||||
pos = _.random 0, (y.val().length-1)
|
||||
y.insertText pos, @getRandomText()
|
||||
null
|
||||
types: [types.Word]
|
||||
,
|
||||
f : (y)=> # REPLACE TEXT
|
||||
y.replaceText @getRandomText()
|
||||
null
|
||||
types: [types.Word]
|
||||
,
|
||||
f : (y)-> # DELETE TEXT
|
||||
if y.val().length > 0
|
||||
pos = _.random 0, (y.val().length-1)
|
||||
length = _.random 0, (y.val().length - pos)
|
||||
ops1 = y.deleteText pos, length
|
||||
undefined
|
||||
types : [types.Word]
|
||||
]
|
||||
|
||||
getRandomRoot: (user_num)->
|
||||
throw new Error "overwrite me!"
|
||||
|
||||
getContent: (user_num)->
|
||||
throw new Error "overwrite me!"
|
||||
|
||||
generateRandomOp: (user_num)=>
|
||||
y = @getRandomRoot(user_num)
|
||||
choices = @getGeneratingFunctions(user_num).filter (gf)->
|
||||
_.some gf.types, (type)->
|
||||
y instanceof type
|
||||
|
||||
if choices.length is 0
|
||||
throw new Error "You forgot to specify a test generation methot for this Operation!"
|
||||
i = _.random 0, (choices.length-1)
|
||||
choices[i].f y
|
||||
|
||||
applyRandomOp: (user_num)=>
|
||||
user = @users[user_num]
|
||||
user.getConnector().flushOneRandom()
|
||||
|
||||
doSomething: ()->
|
||||
user_num = _.random (@number_of_engines-1)
|
||||
choices = [@applyRandomOp, @generateRandomOp]
|
||||
choice = _.random (choices.length-1)
|
||||
choices[choice](user_num)
|
||||
|
||||
flushAll: ()->
|
||||
for user,user_number in @users
|
||||
user.getConnector().flushAll()
|
||||
|
||||
compareAll: (test_number)->
|
||||
@flushAll()
|
||||
|
||||
@time += (new Date()).getTime() - @time_now
|
||||
|
||||
number_of_created_operations = 0
|
||||
for i in [0...(@users.length)]
|
||||
number_of_created_operations += @users[i].getConnector().getOpsInExecutionOrder().length
|
||||
@ops += number_of_created_operations*@users.length
|
||||
|
||||
ops_per_msek = Math.floor(@ops/@time)
|
||||
if test_number? and @debug
|
||||
console.log "#{test_number}/#{@repeat_this}: Every collaborator (#{@users.length}) applied #{number_of_created_operations} ops in a different order." + " Over all we consumed #{@ops} operations in #{@time/1000} seconds (#{ops_per_msek} ops/msek)."
|
||||
|
||||
for i in [0...(@users.length-1)]
|
||||
if @debug
|
||||
if not _.isEqual @getContent(i), @getContent(i+1)
|
||||
printOpsInExecutionOrder = (otnumber, otherotnumber)=>
|
||||
ops = _.filter @users[otnumber].getConnector().getOpsInExecutionOrder(), (o)->
|
||||
typeof o.uid.op_name isnt 'string' and o.uid.creator isnt '_'
|
||||
for s,j in ops
|
||||
console.log "op#{j} = " + (JSON.stringify s)
|
||||
console.log ""
|
||||
s = "ops = ["
|
||||
for o,j in ops
|
||||
if j isnt 0
|
||||
s += ", "
|
||||
s += "op#{j}"
|
||||
s += "]"
|
||||
console.log s
|
||||
console.log "@test_user.engine.applyOps ops"
|
||||
console.log "expect(@test_user.val('name').val()).to.equal(\"#{@users[otherotnumber].val('name').val()}\")"
|
||||
ops
|
||||
console.log ""
|
||||
console.log "Found an OT Puzzle!"
|
||||
console.log "OT states:"
|
||||
for u,j in @users
|
||||
console.log "OT#{j}: "+u.val('name').val()
|
||||
console.log "\nOT execution order (#{i},#{i+1}):"
|
||||
printOpsInExecutionOrder i, i+1
|
||||
console.log ""
|
||||
ops = printOpsInExecutionOrder i+1, i
|
||||
|
||||
console.log ""
|
||||
expect(@getContent(i)).to.deep.equal(@getContent(i+1))
|
||||
|
||||
run: ()->
|
||||
if @debug
|
||||
console.log ''
|
||||
for times in [1..@repeat_this]
|
||||
@time_now = (new Date).getTime()
|
||||
for i in [1..@doSomething_amount]
|
||||
@doSomething()
|
||||
|
||||
@compareAll(times)
|
||||
@testHBencoding()
|
||||
if times isnt @repeat_this
|
||||
@reinitialize()
|
||||
|
||||
testHBencoding: ()->
|
||||
@users[@users.length] = @makeNewUser 'testuser', (Connector_uninitialized [])
|
||||
@users[@users.length-1].engine.applyOps @users[0].HB._encode()
|
||||
|
||||
expect(@getContent(@users.length-1)).to.deep.equal(@getContent(0))
|
||||
|
36
test/TextYatta_test.coffee
Normal file
36
test/TextYatta_test.coffee
Normal file
@ -0,0 +1,36 @@
|
||||
chai = require('chai')
|
||||
expect = chai.expect
|
||||
should = chai.should()
|
||||
sinon = require('sinon')
|
||||
sinonChai = require('sinon-chai')
|
||||
_ = require("underscore")
|
||||
|
||||
chai.use(sinonChai)
|
||||
|
||||
Y = require "../lib/index"
|
||||
Connector_uninitialized = require "../lib/Connectors/TestConnector"
|
||||
|
||||
Test = require "./TestSuite"
|
||||
|
||||
class TextTest extends Test
|
||||
makeNewUser: (user, conn)->
|
||||
new Y.TextYatta user, conn
|
||||
|
||||
getRandomRoot: (user_num)->
|
||||
@users[user_num].getRootElement()
|
||||
|
||||
getContent: (user_num)->
|
||||
@users[user_num].val()
|
||||
|
||||
|
||||
describe "TextYatta", ->
|
||||
beforeEach (done)->
|
||||
@timeout 50000
|
||||
@yTest = new TextTest()
|
||||
@users = @yTest.users
|
||||
|
||||
@test_user = @yTest.makeNewUser 0, (Connector_uninitialized [])
|
||||
done()
|
||||
|
||||
it "can handle many engines, many operations, concurrently (random)", ->
|
||||
@yTest.run()
|
@ -1,223 +0,0 @@
|
||||
chai = require('chai')
|
||||
expect = chai.expect
|
||||
should = chai.should()
|
||||
sinon = require('sinon')
|
||||
sinonChai = require('sinon-chai')
|
||||
_ = require("underscore")
|
||||
|
||||
chai.use(sinonChai)
|
||||
|
||||
Yatta = require "../lib/Frameworks/JsonYatta"
|
||||
Connector_uninitialized = require "../lib/Connectors/TestConnector"
|
||||
|
||||
class Test
|
||||
constructor: (@name_suffix = "")->
|
||||
@number_of_test_cases_multiplier = 1
|
||||
@repeat_this = 1 * @number_of_test_cases_multiplier
|
||||
@doSomething_amount = 1000 * @number_of_test_cases_multiplier
|
||||
@number_of_engines = 2 + @number_of_test_cases_multiplier - 1
|
||||
|
||||
@time = 0
|
||||
@ops = 0
|
||||
@time_now = 0
|
||||
|
||||
@debug = true
|
||||
|
||||
@reinitialize()
|
||||
|
||||
reinitialize: ()->
|
||||
|
||||
@users = []
|
||||
@Connector = Connector_uninitialized @users
|
||||
for i in [0...@number_of_engines]
|
||||
@users.push(new Yatta (i+@name_suffix), @Connector)
|
||||
@users[0].val('name',"i")
|
||||
@flushAll()
|
||||
|
||||
getSomeUser: ()->
|
||||
i = _.random 0, (@users.length-1)
|
||||
@users[i]
|
||||
|
||||
getRandomText: ()->
|
||||
chars = "abcdefghijklmnopqrstuvwxyz"
|
||||
length = _.random 0, 10
|
||||
nextchar = chars[(_.random 0, (chars.length-1))]
|
||||
text = ""
|
||||
_(length).times ()-> text += nextchar
|
||||
text
|
||||
|
||||
generateInsertOp: (user_num)=>
|
||||
pos = _.random 0, (@users[user_num].val('name').val().length-1)
|
||||
@users[user_num].val('name').insertText pos, @getRandomText()
|
||||
null
|
||||
|
||||
generateReplaceOp: (user_num)=>
|
||||
@users[user_num].val('name').replaceText @getRandomText()
|
||||
null
|
||||
|
||||
generateDeleteOp: (user_num)=>
|
||||
if @users[user_num].val('name').val().length > 0
|
||||
pos = _.random 0, (@users[user_num].val('name').val().length-1) # TODO!!!!
|
||||
length = _.random 0, (@users[user_num].val('name').val().length - pos)
|
||||
ops1 = @users[user_num].val('name').deleteText pos, length
|
||||
undefined
|
||||
|
||||
generateRandomOp: (user_num)=>
|
||||
op_gen = [@generateInsertOp, @generateDeleteOp, @generateReplaceOp]
|
||||
i = _.random (op_gen.length - 1)
|
||||
op = op_gen[i](user_num)
|
||||
|
||||
applyRandomOp: (user_num)=>
|
||||
user = @users[user_num]
|
||||
user.getConnector().flushOneRandom()
|
||||
|
||||
doSomething: ()->
|
||||
user_num = _.random (@number_of_engines-1)
|
||||
choices = [@applyRandomOp, @generateRandomOp]
|
||||
choice = _.random (choices.length-1)
|
||||
choices[choice](user_num)
|
||||
|
||||
flushAll: ()->
|
||||
for user,user_number in @users
|
||||
user.getConnector().flushAll()
|
||||
|
||||
compareAll: (test_number)->
|
||||
@flushAll()
|
||||
|
||||
@time += (new Date()).getTime() - @time_now
|
||||
|
||||
number_of_created_operations = 0
|
||||
for i in [0...(@users.length)]
|
||||
number_of_created_operations += @users[i].getConnector().getOpsInExecutionOrder().length
|
||||
@ops += number_of_created_operations*@users.length
|
||||
|
||||
ops_per_msek = Math.floor(@ops/@time)
|
||||
if test_number?
|
||||
console.log "#{test_number}/#{@repeat_this}: Every collaborator (#{@users.length}) applied #{number_of_created_operations} ops in a different order." + " Over all we consumed #{@ops} operations in #{@time/1000} seconds (#{ops_per_msek} ops/msek)."
|
||||
#console.log users[0].val('name').val()
|
||||
for i in [0...(@users.length-1)]
|
||||
if @debug
|
||||
if ((@users[i].val('name').val() isnt @users[i+1].val('name').val()) )# and (number_of_created_operations <= 6 or true)) or found_error
|
||||
printOpsInExecutionOrder = (otnumber, otherotnumber)=>
|
||||
ops = _.filter @users[otnumber].getConnector().getOpsInExecutionOrder(), (o)->
|
||||
typeof o.uid.op_name isnt 'string' and o.uid.creator isnt '_'
|
||||
for s,j in ops
|
||||
console.log "op#{j} = " + (JSON.stringify s)
|
||||
console.log ""
|
||||
s = "ops = ["
|
||||
for o,j in ops
|
||||
if j isnt 0
|
||||
s += ", "
|
||||
s += "op#{j}"
|
||||
s += "]"
|
||||
console.log s
|
||||
console.log "@test_user.engine.applyOps ops"
|
||||
console.log "expect(@test_user.val('name').val()).to.equal(\"#{@users[otherotnumber].val('name').val()}\")"
|
||||
ops
|
||||
console.log ""
|
||||
console.log "Found an OT Puzzle!"
|
||||
console.log "OT states:"
|
||||
for u,j in @users
|
||||
console.log "OT#{j}: "+u.val('name').val()
|
||||
console.log "\nOT execution order (#{i},#{i+1}):"
|
||||
printOpsInExecutionOrder i, i+1
|
||||
console.log ""
|
||||
ops = printOpsInExecutionOrder i+1, i
|
||||
|
||||
console.log ""
|
||||
if (@users[i].val('name').val() isnt @users[i+1].val('name').val())
|
||||
console.log "found error"
|
||||
expect(@users[i].val('name').val()).to.equal(@users[i+1].val('name').val())
|
||||
|
||||
run: ()->
|
||||
console.log ''
|
||||
for times in [1..@repeat_this]
|
||||
@time_now = (new Date).getTime()
|
||||
for i in [1..@doSomething_amount]
|
||||
@doSomething()
|
||||
|
||||
@compareAll(times)
|
||||
@testHBencoding()
|
||||
if times isnt @repeat_this
|
||||
@reinitialize()
|
||||
|
||||
testHBencoding: ()->
|
||||
user = new Yatta 'testuser', (Connector_uninitialized [])
|
||||
user.engine.applyOps @users[0].HB._encode()
|
||||
expect(user.value.name.val()).to.equal(@users[0].value.name.val())
|
||||
|
||||
describe "JsonYatta", ->
|
||||
beforeEach (done)->
|
||||
@timeout 50000
|
||||
@yTest = new Test()
|
||||
@users = @yTest.users
|
||||
|
||||
@test_user = new Yatta 0, (Connector_uninitialized [])
|
||||
done()
|
||||
|
||||
it "has a JsonWrapper", ->
|
||||
y = this.yTest.getSomeUser().root_element
|
||||
y.val('x',"dtrn", 'immutable')
|
||||
y.val('set',{x:"x"}, 'immutable')
|
||||
w = y.value
|
||||
w.x
|
||||
w.set = {y:""}
|
||||
w.x
|
||||
w.set
|
||||
w.set.x
|
||||
expect(w.x).to.equal("dtrn")
|
||||
expect(w.set.x).to.equal("x")
|
||||
|
||||
it "handles double-late-join", ->
|
||||
test = new Test("double")
|
||||
test.run()
|
||||
@yTest.run()
|
||||
u1 = test.users[0]
|
||||
u2 = @yTest.users[1]
|
||||
ops1 = u1.HB._encode()
|
||||
ops2 = u2.HB._encode()
|
||||
u1.engine.applyOps ops2
|
||||
u2.engine.applyOps ops1
|
||||
expect(u2.value.name.val()).to.equal(u2.value.name.val())
|
||||
|
||||
|
||||
|
||||
it "can handle creaton of complex json", ->
|
||||
@yTest.getSomeUser().val('x', {'a':'b'})
|
||||
@yTest.getSomeUser().val('a', {'a':{q:"dtrndtrtdrntdrnrtdnrtdnrtdnrtdnrdnrdt"}})
|
||||
@yTest.getSomeUser().val('b', {'a':{}})
|
||||
@yTest.getSomeUser().val('c', {'a':'c'})
|
||||
@yTest.getSomeUser().val('c', {'a':'b'})
|
||||
@yTest.compareAll()
|
||||
@yTest.getSomeUser().value.a.a.q.insertText(0,'AAA')
|
||||
@yTest.compareAll()
|
||||
expect(@yTest.getSomeUser().value.a.a.q.val()).to.equal("AAAdtrndtrtdrntdrnrtdnrtdnrtdnrtdnrdnrdt")
|
||||
|
||||
|
||||
it "handles some immutable tests", ->
|
||||
@yTest.getSomeUser().val('string', "text", "immutable")
|
||||
@yTest.getSomeUser().val('number', 4, "immutable")
|
||||
@yTest.getSomeUser().val('object', {q:"rr"}, "immutable")
|
||||
@yTest.compareAll()
|
||||
expect(@yTest.getSomeUser().val('string')).to.equal "text"
|
||||
expect(@yTest.getSomeUser().val('number')).to.equal 4
|
||||
expect(@yTest.getSomeUser().val('object').val('q')).to.equal "rr"
|
||||
|
||||
it "can handle many engines, many operations, concurrently (random)", ->
|
||||
@yTest.run()
|
||||
|
||||
it "converges t1", ->
|
||||
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]
|
||||
@test_user.engine.applyOps ops
|
||||
expect(@test_user.val('name').val()).to.equal("duaw")
|
||||
|
Loading…
x
Reference in New Issue
Block a user