mirror of
https://github.com/kiwix/kiwix-js.git
synced 2025-09-22 03:52:21 -04:00
Several fixes for the nearby article search algorithm + some more unit tests + some debug logs in the console (to be removed afterwards)
This commit is contained in:
parent
a2ecf1f3a7
commit
ee101bced8
@ -207,6 +207,9 @@ define(function(require) {
|
||||
ok(rect6.intersect(rect2), "rect6 intersects rect2");
|
||||
ok(rect6.intersect(rect3), "rect6 intersects rect3");
|
||||
ok(!rect6.intersect(rect5), "rect6 intersects rect5");
|
||||
var rect7 = new geometry.rect(0,0,45.5,90,5);
|
||||
var rect8 = new geometry.rect(0,40,10,10);
|
||||
ok(rect8.intersect(rect7), "rect8 intersects rect7");
|
||||
});
|
||||
test("check rectangle contains a point", function() {
|
||||
var rect1 = new geometry.rect(2,3,4,5);
|
||||
@ -321,7 +324,7 @@ define(function(require) {
|
||||
|
||||
start();
|
||||
};
|
||||
var rectFranceGermany = new geometry.rect(0,40,10,10);
|
||||
var rectFranceGermany = new geometry.rect(40,0,10,10);
|
||||
localArchive.getTitlesInCoords(rectFranceGermany, 10, callbackTitlesNearbyFound);
|
||||
});
|
||||
|
||||
@ -329,7 +332,7 @@ define(function(require) {
|
||||
expect(3);
|
||||
var callbackTitlesNearbyLondonFound = function(titleList) {
|
||||
ok(titleList !== null, "Some titles should be found");
|
||||
ok(titleList.length > 0, "At least one title should be found");
|
||||
equal(titleList.length, 1, "1 title should be found");
|
||||
var titleLondon = null;
|
||||
for (var i=0; i<titleList.length; i++) {
|
||||
var title = titleList[i];
|
||||
@ -348,7 +351,33 @@ define(function(require) {
|
||||
pointLondon.y - maxDistance,
|
||||
maxDistance * 2,
|
||||
maxDistance * 2);
|
||||
localArchive.getTitlesInCoords(rectLondon, 100, callbackTitlesNearbyLondonFound);
|
||||
localArchive.getTitlesInCoords(rectLondon, 10, callbackTitlesNearbyLondonFound);
|
||||
});
|
||||
|
||||
asyncTest("check articles found nearby Amsterdam", function() {
|
||||
expect(3);
|
||||
var callbackTitlesNearbyAmsterdamFound = function(titleList) {
|
||||
ok(titleList !== null, "Some titles should be found");
|
||||
equal(titleList.length, 1, "1 title should be found");
|
||||
var titleAmsterdam = null;
|
||||
for (var i=0; i<titleList.length; i++) {
|
||||
var title = titleList[i];
|
||||
if (title.name === "Amsterdam") {
|
||||
titleAmsterdam = title;
|
||||
}
|
||||
}
|
||||
ok(titleAmsterdam !== null, "The title 'Amsterdam' should be found");
|
||||
|
||||
start();
|
||||
};
|
||||
var pointAmsterdam = new geometry.point(55, 5);
|
||||
var maxDistance = 5;
|
||||
var rectAmsterdam = new geometry.rect(
|
||||
pointAmsterdam.x - maxDistance,
|
||||
pointAmsterdam.y - maxDistance,
|
||||
maxDistance * 2,
|
||||
maxDistance * 2);
|
||||
localArchive.getTitlesInCoords(rectAmsterdam, 10, callbackTitlesNearbyAmsterdamFound);
|
||||
});
|
||||
|
||||
module("evopedia_random_title");
|
||||
|
@ -43,7 +43,7 @@ define(function(require) {
|
||||
// Size of chunks read in the dump files : 128 KB
|
||||
var CHUNK_SIZE = 131072;
|
||||
// A rectangle representing all the earth globe
|
||||
var GLOBE_RECTANGLE = new geometry.rect(-181, -90, 361, 181);
|
||||
var GLOBE_RECTANGLE = new geometry.rect(-91, -181, 182, 362);
|
||||
|
||||
/**
|
||||
* LocalArchive class : defines a wikipedia dump on the filesystem
|
||||
@ -637,6 +637,9 @@ define(function(require) {
|
||||
reader.readAsArrayBuffer(blob);
|
||||
};
|
||||
|
||||
// This is a global counter that helps find out when the search for articles nearby is over
|
||||
var callbackCounterForTitlesInCoordsSearch = 0;
|
||||
|
||||
/**
|
||||
* Finds titles that are located inside the given rectangle
|
||||
* This is the main function, that has to be called from the application
|
||||
@ -646,9 +649,17 @@ define(function(require) {
|
||||
* @param callbackFunction Function to call with the list of titles found
|
||||
*/
|
||||
LocalArchive.prototype.getTitlesInCoords = function(rect, maxTitles, callbackFunction) {
|
||||
if (callbackCounterForTitlesInCoordsSearch > 0) {
|
||||
alert("The last nearby search did not seem to end well : please try again");
|
||||
callbackCounterForTitlesInCoordsSearch = 0;
|
||||
return;
|
||||
}
|
||||
var normalizedRectangle = rect.normalized();
|
||||
var i = 0;
|
||||
LocalArchive.getTitlesInCoordsInt(this, i, 0, normalizedRectangle, GLOBE_RECTANGLE, maxTitles, new Array(), callbackFunction, LocalArchive.callbackGetTitlesInCoordsInt);
|
||||
var titlePositionsFound = new Array();
|
||||
for (var i = 0; i < this.coordinateFiles.length; i++) {
|
||||
callbackCounterForTitlesInCoordsSearch++;
|
||||
LocalArchive.getTitlesInCoordsInt(this, i, 0, normalizedRectangle, GLOBE_RECTANGLE, maxTitles, titlePositionsFound, callbackFunction, LocalArchive.callbackGetTitlesInCoordsInt);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -666,20 +677,15 @@ define(function(require) {
|
||||
* @param {type} normalizedRectangle
|
||||
* @param {type} callbackFunction
|
||||
*/
|
||||
LocalArchive.callbackGetTitlesInCoordsInt = function(localArchive, titlePositionsFound, i, maxTitles, normalizedRectangle, callbackFunction) {
|
||||
i++;
|
||||
if (titlePositionsFound.length < maxTitles && i < localArchive.coordinateFiles.length) {
|
||||
LocalArchive.getTitlesInCoordsInt(localArchive, i, 0, normalizedRectangle, GLOBE_RECTANGLE, maxTitles, titlePositionsFound, callbackFunction, LocalArchive.callbackGetTitlesInCoordsInt);
|
||||
LocalArchive.callbackGetTitlesInCoordsInt = function(localArchive, titlePositionsFound, maxTitles, callbackFunction) {
|
||||
// Search is over : now let's convert the title positions into Title instances
|
||||
if (titlePositionsFound && titlePositionsFound.length > 0) {
|
||||
LocalArchive.readTitlesFromTitleCoordsInTitleFile(localArchive, titlePositionsFound, 0, new Array(), callbackFunction);
|
||||
}
|
||||
else {
|
||||
// Search is over : now let's convert the title positions into Title instances
|
||||
if (titlePositionsFound && titlePositionsFound.length > 0) {
|
||||
LocalArchive.readTitlesFromTitleCoordsInTitleFile(localArchive, titlePositionsFound, 0, new Array(), callbackFunction);
|
||||
}
|
||||
else {
|
||||
callbackFunction(titlePositionsFound);
|
||||
}
|
||||
callbackFunction(titlePositionsFound);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -722,7 +728,7 @@ define(function(require) {
|
||||
readCoordinates = function(byteArray, startIndex) {
|
||||
var lat = util.readFloatFrom4Bytes(byteArray, startIndex, true);
|
||||
var long = util.readFloatFrom4Bytes(byteArray, startIndex + 4, true);
|
||||
var point = new geometry.point(long, lat);
|
||||
var point = new geometry.point(lat, long);
|
||||
return point;
|
||||
};
|
||||
|
||||
@ -740,6 +746,7 @@ define(function(require) {
|
||||
* @param {type} callbackGetTitlesInCoordsInt
|
||||
*/
|
||||
LocalArchive.getTitlesInCoordsInt = function(localArchive, coordinateFileIndex, coordFilePos, targetRect, thisRect, maxTitles, titlePositionsFound, callbackFunction, callbackGetTitlesInCoordsInt) {
|
||||
console.log("getTitlesInCoordsInt called : coord file number=" + coordinateFileIndex + " coordFilepos=" + coordFilePos + " x=" + thisRect.x + " y=" + thisRect.y + " w=" + thisRect.width + " h=" + thisRect.height + " callbackCounterForTitlesInCoordsSearch=" + callbackCounterForTitlesInCoordsSearch);
|
||||
var reader = new FileReader();
|
||||
reader.onerror = errorHandler;
|
||||
reader.onabort = function(e) {
|
||||
@ -747,10 +754,12 @@ define(function(require) {
|
||||
};
|
||||
|
||||
reader.onload = function(e) {
|
||||
callbackCounterForTitlesInCoordsSearch--;
|
||||
var binaryTitleFile = e.target.result;
|
||||
var byteArray = new Uint8Array(binaryTitleFile);
|
||||
// Compute selector
|
||||
var selector = util.readIntegerFrom2Bytes(byteArray, 0);
|
||||
console.log("selector=" + selector);
|
||||
|
||||
// 0xFFFF = 65535 in decimal
|
||||
if (selector === 65535) {
|
||||
@ -765,23 +774,49 @@ define(function(require) {
|
||||
var pos2 = pos1 + lense;
|
||||
var pos3 = pos2 + lennw;
|
||||
// Compute the 4 rectangles around
|
||||
var rectSW = new geometry.rect(thisRect.origin(), center);
|
||||
var rectSE = (new geometry.rect(thisRect.topRight(), center)).normalized();
|
||||
var rectNW = (new geometry.rect(thisRect.bottomLeft(), center)).normalized();
|
||||
var rectNE = (new geometry.rect(thisRect.corner(), center)).normalized();
|
||||
var rectSW = (new geometry.rect(thisRect.sw(), center)).normalized();
|
||||
var rectNE = (new geometry.rect(thisRect.ne(), center)).normalized();
|
||||
var rectSE = (new geometry.rect(thisRect.se(), center)).normalized();
|
||||
var rectNW = (new geometry.rect(thisRect.nw(), center)).normalized();
|
||||
console.log("center=" + center);
|
||||
console.log("pos0=" + pos0);
|
||||
console.log("pos1=" + pos1);
|
||||
console.log("pos2=" + pos2);
|
||||
console.log("pos3=" + pos3);
|
||||
console.log("rectSW=" + rectSW);
|
||||
console.log("rectNW=" + rectNW);
|
||||
console.log("rectSE=" + rectSE);
|
||||
console.log("rectNE=" + rectNE);
|
||||
// Recursively call this function for each rectangle around
|
||||
console.log("Does the target rectangle intersect SW?");
|
||||
if (targetRect.intersect(rectSW)) {
|
||||
console.log("Target rectangle intersects SW : looking for archives in it");
|
||||
callbackCounterForTitlesInCoordsSearch++;
|
||||
LocalArchive.getTitlesInCoordsInt(localArchive, coordinateFileIndex, pos0, targetRect, rectSW, maxTitles, titlePositionsFound, callbackFunction, callbackGetTitlesInCoordsInt);
|
||||
}
|
||||
if (targetRect.intersect(rectSE)) {
|
||||
LocalArchive.getTitlesInCoordsInt(localArchive, coordinateFileIndex, pos1, targetRect, rectSE, maxTitles, titlePositionsFound, callbackFunction, callbackGetTitlesInCoordsInt);
|
||||
}
|
||||
console.log("Does the target rectangle intersect NW?");
|
||||
if (targetRect.intersect(rectNW)) {
|
||||
LocalArchive.getTitlesInCoordsInt(localArchive, coordinateFileIndex, pos2, targetRect, rectNW, maxTitles, titlePositionsFound, callbackFunction, callbackGetTitlesInCoordsInt);
|
||||
console.log("Target rectangle intersects NW : looking for archives in it");
|
||||
callbackCounterForTitlesInCoordsSearch++;
|
||||
LocalArchive.getTitlesInCoordsInt(localArchive, coordinateFileIndex, pos1, targetRect, rectNW, maxTitles, titlePositionsFound, callbackFunction, callbackGetTitlesInCoordsInt);
|
||||
}
|
||||
console.log("Does the target rectangle intersect SE?");
|
||||
if (targetRect.intersect(rectSE)) {
|
||||
console.log("Target rectangle intersects SE : looking for archives in it");
|
||||
callbackCounterForTitlesInCoordsSearch++;
|
||||
LocalArchive.getTitlesInCoordsInt(localArchive, coordinateFileIndex, pos2, targetRect, rectSE, maxTitles, titlePositionsFound, callbackFunction, callbackGetTitlesInCoordsInt);
|
||||
}
|
||||
console.log("Does the target rectangle intersect NE?");
|
||||
if (targetRect.intersect(rectNE)) {
|
||||
console.log("Target rectangle intersects NE : looking for archives in it");
|
||||
callbackCounterForTitlesInCoordsSearch++;
|
||||
LocalArchive.getTitlesInCoordsInt(localArchive, coordinateFileIndex, pos3, targetRect, rectNE, maxTitles, titlePositionsFound, callbackFunction, callbackGetTitlesInCoordsInt);
|
||||
}
|
||||
console.log("end");
|
||||
if (callbackCounterForTitlesInCoordsSearch === 0) {
|
||||
console.log("callbackCounterForTitlesInCoordsSearch reached 0 : return the titles found")
|
||||
callbackGetTitlesInCoordsInt(localArchive, titlePositionsFound, maxTitles, callbackFunction);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This is a leaf node : let's see if its articles are in the
|
||||
@ -790,21 +825,28 @@ define(function(require) {
|
||||
var indexInByteArray = 2 + i * 12;
|
||||
|
||||
var articleCoordinates = readCoordinates(byteArray, indexInByteArray);
|
||||
console.log("articleCoordinates=" + articleCoordinates);
|
||||
// Read position (in title file) of title
|
||||
var title_pos = util.readIntegerFrom4Bytes(byteArray, indexInByteArray + 8);
|
||||
if (!targetRect.containsPoint(articleCoordinates)) {
|
||||
console.log("target rectangle does not contain this point");
|
||||
continue;
|
||||
}
|
||||
// We currently do not use the article coordinates
|
||||
// so it's no use putting it in the result list : we only put
|
||||
// the position in title list
|
||||
console.log("target rectangle contains this point : adding to the list");
|
||||
titlePositionsFound.push(title_pos);
|
||||
if (maxTitles >= 0 && titlePositionsFound.length >= maxTitles) {
|
||||
callbackGetTitlesInCoordsInt(localArchive, titlePositionsFound, coordinateFileIndex, maxTitles, targetRect, callbackFunction);
|
||||
return;
|
||||
}
|
||||
console.log("maxTitles="+maxTitles+" titlePositionsFound.length="+titlePositionsFound.length);
|
||||
// TODO : reactivate to enforce the maximum titles to be searched
|
||||
// if (maxTitles >= 0 && titlePositionsFound.length >= maxTitles) {
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
if (callbackCounterForTitlesInCoordsSearch === 0) {
|
||||
console.log("callbackCounter reached 0 : return the titles found")
|
||||
callbackGetTitlesInCoordsInt(localArchive, titlePositionsFound, maxTitles, callbackFunction);
|
||||
}
|
||||
callbackGetTitlesInCoordsInt(localArchive, titlePositionsFound, coordinateFileIndex, maxTitles, targetRect, callbackFunction);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -278,8 +278,21 @@ define(function(require) {
|
||||
|
||||
rect.prototype = {
|
||||
toString: function() {
|
||||
return this.origin().toString() + ' ' + this.corner().toString();
|
||||
return 'x=' + this.x + ' y=' + this.y + ' w=' + this.width + ' h=' + this.height;
|
||||
},
|
||||
sw : function() {
|
||||
return point(this.x, this.y);
|
||||
},
|
||||
nw : function() {
|
||||
return point(this.x, this.y + this.height);
|
||||
},
|
||||
se : function() {
|
||||
return point(this.x + this.width, this.y);
|
||||
},
|
||||
ne : function() {
|
||||
return point(this.x + this.width, this.y + this.height);
|
||||
},
|
||||
// TODO : rename all this right/left/top/bottom terms because they are misleading (and wrong) in the Evopedia context : replace with N/S/E/W
|
||||
origin: function() {
|
||||
return point(this.x, this.y);
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user