From: hikarupsp Date: Mon, 5 May 2014 10:18:19 +0000 (+0900) Subject: エッジの同期を追加。まだ不完全。 X-Git-Url: http://git.osdn.jp/view?p=chnosproject%2FAI004.git;a=commitdiff_plain;h=84a566b0d4a930b53d0da3297a10dbac20a5e24d エッジの同期を追加。まだ不完全。 --- diff --git a/memdb/memdb.js b/memdb/memdb.js index 968dc8d..2f17e33 100644 --- a/memdb/memdb.js +++ b/memdb/memdb.js @@ -7,11 +7,13 @@ function MemoryDB(syncPHPURL){ this.root = new Array(); // this.nodeList = new Array(); + this.edgeList = new Array(); // this.syncPHPURL = syncPHPURL; this.isEnabledNetDB = true; // - this.callback_updatedNode = null; // function(nodeinstance){}; + this.callback_updatedNode = null; // function(nodeInstance){}; + this.callback_updatedEdge = null; // function(edgeInstance){}; } MemoryDB.prototype = { UUID_Null: "00000000-0000-0000-0000-000000000000", @@ -25,20 +27,29 @@ MemoryDB.prototype = { // XMLHttpRequest オブジェクトを作成 rq = new XMLHttpRequest(); }catch(e){} + if(rq){ + return rq; + } // Internet Explorer try{ rq = new ActiveXObject('MSXML2.XMLHTTP.6.0'); }catch(e){} + if(rq){ + return rq; + } try{ rq = new ActiveXObject('MSXML2.XMLHTTP.3.0'); }catch(e){} + if(rq){ + return rq; + } try{ rq = new ActiveXObject('MSXML2.XMLHTTP'); }catch(e){} - if(rq == null){ - return null; + if(rq){ + return rq; } - return rq; + return null; }, requestObjectDisableCache: function(rq){ //call after open request. @@ -75,14 +86,18 @@ MemoryDB.prototype = { syncDB: function(){ // MySQLと同期 // 定期的に呼び出されることを想定 + this.syncDBNode(); + this.syncDBEdge(); + }, + syncDBNode: function(){ var r, a, d; - if(this.root.length == 0){ + if(this.nodeList.length == 0){ // 初回同期時は全て取得 r = this.sendRequestSync("GET", this.syncPHPURL + "?action=getallnode", null); } else{ // 差分のみを取得 d = this.getNodeFromUUID(this.UUID_Node_MemoryDBNetworkTimestamp).identifier; - r = this.sendRequestSync("GET", this.syncPHPURL + "?action=getnodemod&t=" + d, null); + r = this.sendRequestSync("GET", this.syncPHPURL + "?action=getallnodemod&t=" + d, null); } a = r.split("\n"); for(var i = 0, iLen = a.length; i < iLen; i++){ @@ -97,7 +112,40 @@ MemoryDB.prototype = { } this.updateNodeInternal(d[2], d[1], d[0]); } - //console.log(this.root); + }, + syncDBEdge: function(){ + var r, a, d; + if(this.edgeList.length == 0){ + // 初回同期時は全て取得 + r = this.sendRequestSync("GET", this.syncPHPURL + "?action=getalledge", null); + } else{ + // 差分のみを取得 + /* + d = this.getNodeFromUUID(this.UUID_Node_MemoryDBNetworkTimestamp).identifier; + r = this.sendRequestSync("GET", this.syncPHPURL + "?action=getallnodemod&t=" + d, null); + */ + return; + } + a = r.split("\n"); + for(var i = 0, iLen = a.length; i < iLen; i++){ + try{ + d = eval(a[i]); + } catch(e){ + console.log(i + ": " + e + "\n"); + continue; + } + if(d === undefined){ + continue; + } + if( d[0] != this.UUID_Node_MemoryDBNetworkTimestamp && + d[0] != this.UUID_Node_MemoryDBNetworkResponseCode){ + // edge data + this.updateEdgeInternal(d[2], d[3], d[1], d[0]); + } else{ + // node data + this.updateNodeInternal(d[2], d[1], d[0]); + } + } }, updateNode: function(ident, tid, nid){ // 該当タグのデータを書き換え、もしくは新規作成する。 @@ -151,6 +199,61 @@ MemoryDB.prototype = { this.callback_updatedNode(t); } }, + updateEdge: function(nid0, nid1, tid, eid){ + // 該当タグのデータを書き換え、もしくは新規作成する。 + // 可能であればネットワークに反映する + // eid(nodeid)は省略可能で、省略時は新たなUUIDが自動的に付与される + // tid(typeid)も省略可能で、省略時はNullUUIDが付与される + // 戻り値はMemoryDBEdgeTagインスタンス + // エラー発生時はundefinedを返す。 + this.updateEdgeInternal(nid0, nid1, tid, eid, true); + }, + updateEdgeInternal: function(nid0, nid1, tid, eid, enableSync){ + // 基本的にローカルデータのみ変更 + // enableSync == trueでネットワーク同期する + var t, s, r; + if(!tid){ + tid = this.UUID_Null; + } + if(!eid){ + eid = this.createUUID(); + } + // 存在確認 + t = this.getEdgeFromUUID(eid); + if(t){ + // 変更 + /* + t.typeid = tid; + t.identifier = ident; + if(enableSync && this.isEnabledNetDB){ + s = this.syncPHPURL + "?action=updatenode"; + s += "&nid=" + encodeURIComponent(nid); + s += "&tid=" + encodeURIComponent(tid); + s += "&ident=" + encodeURIComponent(ident); + r = this.sendRequestSync("GET", s, null); + //console.log(r); + } + */ + return; + } else{ + // 新規作成 + t = new MemoryDBEdgeTag(eid, tid, nid0, nid1); + this.root.push(t); + this.edgeList.push(t); + if(enableSync && this.isEnabledNetDB){ + s = this.syncPHPURL + "?action=addedge"; + s += "&eid=" + encodeURIComponent(eid); + s += "&tid=" + encodeURIComponent(tid); + s += "&nid0=" + encodeURIComponent(nid0); + s += "&nid1=" + encodeURIComponent(nid1); + r = this.sendRequestSync("GET", s, null); + console.log(r); + } + } + if(this.callback_updatedEdge){ + this.callback_updatedEdge(t); + } + }, createUUID: function(){ var f = this.createUUIDSub; return (f() + f() + "-" + f() + "-" + f() + "-" + f() + "-" + f() + f() + f()); @@ -161,6 +264,9 @@ MemoryDB.prototype = { getNodeFromUUID: function(nodeid){ return this.nodeList.isIncluded(nodeid, function(a, b){ return a.nodeid == b; }); }, + getEdgeFromUUID: function(edgeid){ + return this.edgeList.isIncluded(edgeid, function(a, b){ return a.edgeid == b; }); + }, } function MemoryDBNodeTag(nodeid, typeid, identifier){ @@ -173,8 +279,11 @@ MemoryDBNodeTag.prototype = { } -function MemoryDBEdgeTag(typeUUIDStr){ - this.uuid = null; +function MemoryDBEdgeTag(edgeid, typeid, nodeid0, nodeid1){ + this.edgeid = edgeid; + this.typeid = typeid; + this.nodeid0 = nodeid0; + this.nodeid1 = nodeid1; } MemoryDBEdgeTag.prototype = { diff --git a/memdb/memdb.php b/memdb/memdb.php index c9c9088..e5b6d33 100644 --- a/memdb/memdb.php +++ b/memdb/memdb.php @@ -47,7 +47,7 @@ insert into Node ( define("QUERY_ADD_Node_TYPES", "sssi"); // define("QUERY_ADD_Edge", " -insert into Node ( +insert into Edge ( edgeid, typeid, nodeid0, nodeid1, modtimestamp ) values ( unhex(replace(?, '-', '')), unhex(replace(?, '-', '')), unhex(replace(?, '-', '')), unhex(replace(?, '-', '')), ? @@ -63,10 +63,18 @@ WHERE "); define("QUERY_UPDATE_Node_TYPES", "ssis"); // - +define("QUERY_UPDATE_Edge", " +UPDATE Edge SET + typeid=unhex(replace(?, '-', '')), nodeid0=unhex(replace(?, '-', '')), nodeid1=unhex(replace(?, '-', '')), modtimestamp=? +WHERE + edgeid=unhex(replace(?, '-', '')) +"); +define("QUERY_UPDATE_Edge_TYPES", "sssis"); +// define("QUERY_SELECT_ALL_Node", "select hex(nodeid), hex(typeid), identifier from Node"); define("QUERY_SELECT_ALL_Node_With_modtimestamp", "select hex(nodeid), hex(typeid), identifier, modtimestamp from Node"); define("QUERY_SELECT_ALL_Edge", "select hex(edgeid), hex(typeid), hex(nodeid0), hex(nodeid1) from Edge"); +define("QUERY_SELECT_ALL_Edge_With_modtimestamp", "select hex(edgeid), hex(typeid), hex(nodeid0), hex(nodeid1), modtimestamp from Edge"); define("QUERY_SELECT_modified_Node", "select hex(nodeid), hex(typeid), identifier from Node WHERE modtimestamp>?"); define("QUERY_SELECT_modified_Node_TYPES", "i"); @@ -104,7 +112,30 @@ if(isset($_GET['action'])){ // put timestamp tag echoMemoryDBNetworkTimestamp(); exit(); - } else if(strcmp($action, 'getnodemod') == 0){ + } else if(strcmp($action, 'getalledge') == 0){ + $stmt = $db->prepare(QUERY_SELECT_ALL_Edge); + $stmt->execute(); + // + $stmt->store_result(); + if($stmt->errno != 0){ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B"); + } + + $stmt->bind_result($uuid, $typeid, $nid0, $nid1); + while($stmt->fetch()){ + echoEdge( + getFormedUUIDString($uuid), + getFormedUUIDString($typeid), + getFormedUUIDString($nid0), + getFormedUUIDString($nid1) + ); + echo(PHP_EOL); + } + $stmt->close(); + // put timestamp tag + echoMemoryDBNetworkTimestamp(); + exit(); + } else if(strcmp($action, 'getallnodemod') == 0){ if(isset($_GET['t'])){ $ts = $_GET['t']; } else{ @@ -154,6 +185,29 @@ if(isset($_GET['action'])){ echo($stmt->num_rows); $stmt->close(); exit(" OK " . getTimeStampMs()); + } else if(strcmp($action, 'viewalledge') == 0){ + $stmt = $db->prepare(QUERY_SELECT_ALL_Edge_With_modtimestamp); + $stmt->execute(); + // + $stmt->store_result(); + if($stmt->errno != 0){ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B"); + } + + $stmt->bind_result($uuid, $typeid, $nid0, $nid1, $mts); + while($stmt->fetch()){ + echoEdge( + getFormedUUIDString($uuid), + getFormedUUIDString($typeid), + getFormedUUIDString($nid0), + getFormedUUIDString($nid1) + ); + echo(' @' . $mts); + echo("
"); + } + echo($stmt->num_rows); + $stmt->close(); + exit(" OK " . getTimeStampMs()); } else if(strcmp($action, 'addnode') == 0){ if(isset($_GET['nid'])){ $nodeid = $_GET['nid']; @@ -210,6 +264,72 @@ if(isset($_GET['action'])){ } $stmt->close(); exitWithResponseCode("cea95615-649c-4837-9e24-0c968fa57647", "OK"); + } else if(strcmp($action, 'addedge') == 0){ + if(isset($_GET['eid'])){ + $edgeid = $_GET['eid']; + } else{ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B", "edgeid needed."); + } + if(isset($_GET['tid'])){ + $typeid = $_GET['tid']; + } else{ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B", "typeid needed."); + } + if(isset($_GET['nid0'])){ + $nid0 = $_GET['nid0']; + } else{ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B", "nodeid0 needed."); + } + if(isset($_GET['nid1'])){ + $nid1 = $_GET['nid1']; + } else{ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B", "nodeid1 needed."); + } + + $stmt = $db->prepare(QUERY_ADD_Edge); + $mts = getTimeStampMs(); + $stmt->bind_param(QUERY_ADD_Edge_TYPES, $edgeid, $typeid, $nid0, $nid1, $mts); + $stmt->execute(); + // + $stmt->store_result(); + if($stmt->errno != 0){ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B", mysqli_error($db)); + } + $stmt->close(); + exitWithResponseCode("cea95615-649c-4837-9e24-0c968fa57647", "OK"); + } else if(strcmp($action, 'updateedge') == 0){ + if(isset($_GET['eid'])){ + $edgeid = $_GET['eid']; + } else{ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B", "edgeid needed."); + } + if(isset($_GET['tid'])){ + $typeid = $_GET['tid']; + } else{ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B", "typeid needed."); + } + if(isset($_GET['nid0'])){ + $nid0 = $_GET['nid0']; + } else{ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B", "nodeid0 needed."); + } + if(isset($_GET['nid1'])){ + $nid1 = $_GET['nid1']; + } else{ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B", "nodeid1 needed."); + } + + $stmt = $db->prepare(QUERY_UPDATE_Edge); + $mts = getTimeStampMs(); + $stmt->bind_param(QUERY_UPDATE_Edge_TYPES, $typeid, $nid0, $nid1, $mts, $edgeid); + $stmt->execute(); + // + $stmt->store_result(); + if($stmt->errno != 0){ + exitWithResponseCode("A0518702-C90C-4785-B5EA-1A213DD0205B", mysqli_error($db)); + } + $stmt->close(); + exitWithResponseCode("cea95615-649c-4837-9e24-0c968fa57647", "OK"); } } @@ -236,6 +356,11 @@ function echoNode($nid, $tid, $ident) echo('["' . $nid .'","' . $tid .'","' . $ident . '"]'); } +function echoEdge($eid, $tid, $nid0, $nid1) +{ + echo('["' . $eid .'","' . $tid .'","' . $nid0 .'","' . $nid1 . '"]'); +} + function connectDB() { $db = new mysqli('localhost', DATABASE_USER, DATABASE_PWD, DATABASE_NAME); diff --git a/mgcanvas/index.html b/mgcanvas/index.html index 931bd65..8b70865 100755 --- a/mgcanvas/index.html +++ b/mgcanvas/index.html @@ -21,8 +21,52 @@ var mgmain; var memdb; onload = function() { + var that = this; + var DOM_Node0ID = document.getElementById("nidBox0"); + var DOM_Node0Ident = document.getElementById("identBox0"); + var DOM_Node1ID = document.getElementById("nidBox1"); + var DOM_Node1Ident = document.getElementById("identBox1"); + var DOM_EdgeID = document.getElementById("eidBox"); + var DOM_EdgeTypeID = document.getElementById("etidBox"); + memdb = new MemoryDB("./../memdb/memdb.php"); mgmain = new MGCanvas(document.getElementById("mainCanvas")); + document.getElementById("updateButton0").onclick = function(){ + mgmain.setIdentifierForSelectedNode(DOM_Node0Ident.value); + }; + document.getElementById("updateButton1").onclick = function(){ + mgmain.setIdentifierForSelectedNode(DOM_Node1Ident.value, true); + }; + document.getElementById("connectNodesButton").onclick = function(){ + memdb.updateEdge(DOM_Node0ID.value, DOM_Node1ID.value); + }; + mgmain.callback_selectedNodeChanged = function(newNode){ + if(newNode){ + DOM_Node0ID.value = newNode.nodeid; + DOM_Node0Ident.value = newNode.identifier; + } else{ + DOM_Node0ID.value = "not selected"; + DOM_Node0Ident.value = ""; + } + }; + mgmain.callback_selectedNodeDestinationChanged = function(newNode){ + if(newNode){ + DOM_Node1ID.value = newNode.nodeid; + DOM_Node1Ident.value = newNode.identifier; + } else{ + DOM_Node1ID.value = "not selected"; + DOM_Node1Ident.value = ""; + } + }; + mgmain.callback_selectedEdgeChanged = function(newEdge){ + if(newEdge){ + DOM_EdgeID.value = newEdge.edgeid; + DOM_EdgeTypeID.value = newEdge.typeid; + } else{ + DOM_EdgeID.value = "not selected"; + DOM_EdgeTypeID.value = ""; + } + }; mgmain.setSourceMemoryDB(memdb); } @@ -30,7 +74,7 @@ onload = function() {

Mind Graph Canvas

-
+

Control

@@ -39,11 +83,17 @@ onload = function() { -
-identifier: -
- - +

Node0

+id: +identifier: + +

Node1

+id: +identifier: + +

Edge

+id : +type : \ No newline at end of file diff --git a/mgcanvas/mgcanvas.js b/mgcanvas/mgcanvas.js index b80639d..9594a4c 100755 --- a/mgcanvas/mgcanvas.js +++ b/mgcanvas/mgcanvas.js @@ -1,22 +1,31 @@ function MGCanvas(canvasDOMObj){ var that = this; - + // this.initGraphicContext(canvasDOMObj); + // this.tickPerSecond = 30; this.tickCount = 0; this.tickTimer = window.setInterval(function(){ that.tick(); }, 1000 / this.tickPerSecond); this.isPaused = false; this.isEnabledAutomaticTracking = true; + // this.nodeList = new Array(); this.edgeList = new Array(); + // this.selectedNode = null; + this.callback_selectedNodeChanged = null; //function(newNodeInstance){}; + // + this.selectedNodeDestination = null; + this.callback_selectedNodeDestinationChanged = null; //function(newNodeInstance){}; + // this.selectedEdge = null; + this.callback_selectedEdgeChanged = null; //function(newEdgeInstance){}; + // this.srcMemoryDB = null; this.srcMemoryDBSyncPerTick = 60; this.srcMemoryDBSyncCount = this.srcMemoryDBSyncPerTick; - - var that = this; + window.addEventListener('keydown', function(event){ switch(event.keyCode){ case 37: //左カーソル @@ -56,7 +65,7 @@ function MGCanvas(canvasDOMObj){ var p = that.convertPointToGraphLayerFromCanvasLayerP(that.lastMousePosition); //console.log(p.x + "," + p.y); var node = that.getNodeAtPointP(p); - that.selectNode(node); + that.selectNode(node, e.shiftKey); var edge = that.getEdgeAtPointP(p); that.selectEdge(edge); that.isMouseDown = true; @@ -92,12 +101,32 @@ MGCanvas.prototype = { // 新規追加 n = new MGNode(that, t.identifier); n.nodeid = t.nodeid; + n.typeid = t.typeid; that.nodeList.push(n); } else{ // 更新 n.identifier = t.identifier; + n.typeid = t.typeid; } - } + }; + mdb.callback_updatedEdge = function(t){ + var e; + var n = function(nid){ return that.nodeList.isIncluded(nid, function(a, b){ return (a.nodeid == b); }); }; + e = that.edgeList.isIncluded(t.edgeid, function(a, b){ return a.edgeid == b; }); + if(!e){ + // 新規追加 + e = new MGEdge(that, "", n(t.nodeid0), n(t.nodeid1)); + e.edgeid = t.edgeid; + e.typeid = t.typeid; + that.edgeList.push(e); + } else{ + // 更新 + // e.identifier + e.node0 = n(t.nodeid0); + e.node1 = n(t.nodeid1); + e.typeid = t.typeid; + } + }; }, bringToCenter: function(){ // 重心を求めて、それを表示オフセットに設定する @@ -382,7 +411,7 @@ MGCanvas.prototype = { this.context.translate(w, h); this.displayRect = new Rectangle(-w, -h, this.canvas.width, this.canvas.height); this.currentScale = 1; - this.zoomOut(); + //this.zoomOut(); this.positionOffset = new Point2D(0, 0); }, convertPointToGraphLayerFromCanvasLayerP: function(pCanvas){ @@ -422,16 +451,43 @@ MGCanvas.prototype = { } return null; }, - selectNode: function(node){ - if(this.selectedNode){ - this.selectedNode.isSelected = false; - } - if(node){ - node.isSelected = true; + selectNode: function(node, destNode){ + if(!destNode){ + // 通常のノード選択 + if(this.selectedNode == node){ + return; + } + if(this.selectedNode){ + this.selectedNode.isSelected = false; + } + if(node){ + node.isSelected = true; + } + this.selectedNode = node; + if(this.callback_selectedNodeChanged){ + this.callback_selectedNodeChanged(this.selectedNode); + } + } else{ + // 接続先のノード選択(Shiftキーを押しながら) + if(this.selectedNodeDestination == node){ + return; + } + if(this.selectedNodeDestination){ + this.selectedNodeDestination.isSelected = false; + } + if(node){ + node.isSelected = true; + } + this.selectedNodeDestination = node; + if(this.callback_selectedNodeDestinationChanged){ + this.callback_selectedNodeDestinationChanged(this.selectedNodeDestination); + } } - this.selectedNode = node; }, selectEdge: function(edge){ + if(this.selectedEdge == edge){ + return; + } if(this.selectedEdge){ this.selectedEdge.isSelected = false; } @@ -439,13 +495,26 @@ MGCanvas.prototype = { edge.isSelected = true; } this.selectedEdge = edge; + if(this.callback_selectedEdgeChanged){ + this.callback_selectedEdgeChanged(this.selectedEdge); + } }, - setIdentifierForSelectedNode: function(str){ - if(this.selectedNode){ - if(this.srcMemoryDB){ - this.srcMemoryDB.updateNode(str, this.selectedNode.typeid, this.selectedNode.nodeid); - } else{ - this.selectedNode.identifier = str; + setIdentifierForSelectedNode: function(str, destNode){ + if(!destNode){ + if(this.selectedNode){ + if(this.srcMemoryDB){ + this.srcMemoryDB.updateNode(str, this.selectedNode.typeid, this.selectedNode.nodeid); + } else{ + this.selectedNode.identifier = str; + } + } + } else{ + if(this.selectedNodeDestination){ + if(this.srcMemoryDB){ + this.srcMemoryDB.updateNode(str, this.selectedNodeDestination.typeid, this.selectedNodeDestination.nodeid); + } else{ + this.selectedNodeDestination.identifier = str; + } } } }, @@ -545,9 +614,14 @@ MGNode.prototype = { function MGEdge(env, identifier, node0, node1){ this.env = env; + // this.identifier = identifier; this.node0 = node0; this.node1 = node1; + // + this.edgeid = null; + this.typeid = null; + // this.freeLength = 250; // this.strokeStyle = "rgba(0, 0, 0, 0.5)"; @@ -563,8 +637,9 @@ MGEdge.prototype = { this.env.context.strokeStyle = this.strokeStyle; } if(this.node0 && this.node1){ - this.drawCurvedLineP(this.node0.position, this.node1.position); - this.env.strokeRect(this.centerPoint.x - 8, this.centerPoint.y - 8, 16, 16); + //this.drawCurvedLineP(this.node0.position, this.node1.position); + this.env.drawLineP(this.node0.position, this.node1.position) + //this.env.strokeRect(this.centerPoint.x - 8, this.centerPoint.y - 8, 16, 16); if(this.identifier){ this.env.drawText(this.identifier.toString(), this.centerPoint.x, this.centerPoint.y); }