Clean up removeConnection; port in more tests.

This commit is contained in:
Rachel Fenichel 2016-02-26 14:41:49 -08:00
parent e3b05ad2c1
commit 0a363803f0
3 changed files with 104 additions and 34 deletions

View file

@ -29,6 +29,7 @@ goog.provide('Blockly.BlockSvg.render');
goog.require('Blockly.BlockSvg');
// UI constants for rendering blocks.
/**
* Horizontal space between elements.

View file

@ -63,6 +63,44 @@ Blockly.ConnectionDB.prototype.addConnection_ = function(connection) {
connection.inDB_ = true;
};
/**
* Find the given connection.
* Starts by doing a binary search to find the approximate location, then linearly searches
* nearby for the exact connection.
* @param {Blockly.Connection} conn The connection to find.
* @return The index of the connection, or -1 if the connection was not found.
*/
Blockly.ConnectionDB.prototype.findConnection = function(conn) {
if (this.length == 0) {
return -1;
}
var bestGuess = this.findPositionForConnection_(conn);
if (bestGuess >= this.length) {
// Not in list
return -1;
}
var yPos = conn.y_;
// Walk forward and back on the y axis looking for the connection.
var pointerMin = bestGuess;
var pointerMax = bestGuess;
while(pointerMin >= 0 && this[pointerMin].y_ == yPos) {
if (this[pointerMin] == conn) {
return pointerMin;
}
pointerMin--;
}
while (pointerMax < this.length && this[pointerMax].y_ == yPos) {
if (this[pointerMax] == conn) {
return pointerMax;
}
pointerMax++;
}
return -1;
};
/**
* Finds a candidate position for inserting this connection into the list.
* This will be in the correct y order but makes no guarantees about ordering in the x axis.
@ -99,41 +137,11 @@ Blockly.ConnectionDB.prototype.removeConnection_ = function(connection) {
if (!connection.inDB_) {
throw 'Connection not in database.';
}
connection.inDB_ = false;
// Find the connection using a binary search.
// About 10% faster than a linear search using indexOf.
var pointerMin = 0;
var pointerMax = this.length - 2;
var pointerMid = pointerMax;
while (pointerMin < pointerMid) {
if (this[pointerMid].y_ < connection.y_) {
pointerMin = pointerMid;
} else {
pointerMax = pointerMid;
}
pointerMid = Math.floor((pointerMin + pointerMax) / 2);
var removalIndex = this.findConnection(connection);
if (removalIndex == -1) {
throw 'Unable to find connection in connectionDB.';
}
// Walk forward and back on the y axis looking for the connection.
// When found, splice it out of the array.
pointerMin = pointerMid;
pointerMax = pointerMid;
while (pointerMin >= 0 && this[pointerMin].y_ == connection.y_) {
if (this[pointerMin] == connection) {
this.splice(pointerMin, 1);
return;
}
pointerMin--;
}
do {
if (this[pointerMax] == connection) {
this.splice(pointerMax, 1);
return;
}
pointerMax++;
} while (pointerMax < this.length &&
this[pointerMax].y_ == connection.y_);
throw 'Unable to find connection in connectionDB.';
this.splice(removalIndex, 1);
};
/**

View file

@ -139,6 +139,67 @@ function test_DB_getNeighbours() {
assertEquals(result.length, 0);
}
function test_DB_findPositionForConnection() {
var db = new Blockly.ConnectionDB();
db.addConnection_(helper_createConnection(0, 0, Blockly.PREVIOUS_STATEMENT));
db.addConnection_(helper_createConnection(0, 1, Blockly.PREVIOUS_STATEMENT));
db.addConnection_(helper_createConnection(0, 2, Blockly.PREVIOUS_STATEMENT));
db.addConnection_(helper_createConnection(0, 4, Blockly.PREVIOUS_STATEMENT));
db.addConnection_(helper_createConnection(0, 5, Blockly.PREVIOUS_STATEMENT));
assertEquals(5, db.length);
var conn = helper_createConnection(0, 3, Blockly.PREVIOUS_STATEMENT);
assertEquals(3, db.findPositionForConnection_(conn));
}
function test_DB_findConnection() {
var db = new Blockly.ConnectionDB();
for (var i = 0; i < 10; i++) {
db.addConnection_(helper_createConnection(i, 0, Blockly.PREVIOUS_STATEMENT));
db.addConnection_(helper_createConnection(0, i, Blockly.PREVIOUS_STATEMENT));
}
var conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT);
db.addConnection_(conn);
assertEquals(conn, db[db.findConnection(conn)]);
conn = helper_createConnection(3, 3, Blockly.PREVIOUS_STATEMENT);
assertEquals(-1, db.findConnection(conn));
}
function test_DB_ordering() {
var db = new Blockly.ConnectionDB();
for (var i = 0; i < 10; i++) {
db.addConnection_(helper_createConnection(0, 9 - i, Blockly.PREVIOUS_STATEMENT));
}
for (i = 0; i < 10; i++) {
assertEquals(i, db[i].y_);
}
// quasi-random
var xCoords = [-29, -47, -77, 2, 43, 34, -59, -52, -90, -36, -91, 38, 87, -20, 60, 4, -57,
65, -37, -81, 57, 58, -96, 1, 67, -79, 34, 93, -90, -99, -62, 4, 11, -36, -51, -72,
3, -50, -24, -45, -92, -38, 37, 24, -47, -73, 79, -20, 99, 43, -10, -87, 19, 35,
-62, -36, 49, 86, -24, -47, -89, 33, -44, 25, -73, -91, 85, 6, 0, 89, -94, 36, -35,
84, -9, 96, -21, 52, 10, -95, 7, -67, -70, 62, 9, -40, -95, -9, -94, 55, 57, -96,
55, 8, -48, -57, -87, 81, 23, 65];
var yCoords = [-81, 82, 5, 47, 30, 57, -12, 28, 38, 92, -25, -20, 23, -51, 73, -90, 8, 28,
-51, -15, 81, -60, -6, -16, 77, -62, -42, -24, 35, 95, -46, -7, 61, -16, 14, 91, 57,
-38, 27, -39, 92, 47, -98, 11, -33, -72, 64, 38, -64, -88, -35, -59, -76, -94, 45,
-25, -100, -95, 63, -97, 45, 98, 99, 34, 27, 52, -18, -45, 66, -32, -38, 70, -73,
-23, 5, -2, -13, -9, 48, 74, -97, -11, 35, -79, -16, -77, 83, -57, -53, 35, -44,
100, -27, -15, 5, 39, 33, -19, -20, -95];
for (i = 0; i < xCoords.length; i++) {
db.addConnection_(helper_createConnection(xCoords[i], yCoords[i],
Blockly.PREVIOUS_STATEMENT));
}
for (i = 1; i < xCoords.length; i++) {
assertTrue(db[i].y_ >= db[i - 1].y_);
}
}
function helper_getNeighbours(db, x, y, radius) {
return db.getNeighbours(helper_createConnection(x, y, Blockly.NEXT_STATEMENT), radius);
}