allex_browsercore
Version:
AllexJS Browser Core
1,641 lines (1,499 loc) • 1.48 MB
JavaScript
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
function createArrayHelpers (extend, readPropertyFromDotDelimitedString, isFunction, Map, AllexJSONizingError) {
'use strict';
function equaler (item, propval, scalarpropname, index) {
return item[scalarpropname] == propval[index];
}
function propnamevalequal (item, propname, propval) {
var ret = propname.every(equaler.bind(null, item, propval));
item = null;
propval = null;
return ret;
}
function propvals (item, propname) {
var ret = propname.map(function (scalarpropname) {
return item[scalarpropname];
});
item = null;
return ret;
}
function finderwithindex(findobj, propname, propval, item, index){
if (item && propnamevalequal(item, propname, propval)) {
findobj.element = item;
findobj.index = index;
return true;
}
}
function plaincompare (a, b) {
if (a == b) {return 0;}
if (a > b) {return 1;}
return -1;
}
function scalarcompare(ret, item, index) {
if (ret.ret != 0) {
return ret;
}
var pcres = plaincompare(item, ret.other[index]);
ret.ret = pcres;
return ret;
}
function compare (a, b) {
return a.reduce(scalarcompare, {other: b, ret: 0}).ret;
}
function finderwithindexandinsertindex(findobj, propname, propval, item, index){
var val, cmpval;
val = propvals(item, propname);
cmpval = compare(val, propval);
if (cmpval == 0) {
findobj.element = item;
findobj.index = index;
return true;
}
if (cmpval<0) {
findobj.insertafter = index;
}
}
return {
finderwithindex: finderwithindex,
finderwithindexandinsertindex: finderwithindexandinsertindex
};
}
module.exports = createArrayHelpers;
},{}],2:[function(require,module,exports){
function createHelpers (extend, readPropertyFromDotDelimitedString, isFunction, Map, AllexJSONizingError) {
'use strict';
return {
scalar: require('./scalarcreator')(extend, readPropertyFromDotDelimitedString, isFunction, Map, AllexJSONizingError),
array: require('./arraycreator')(extend, readPropertyFromDotDelimitedString, isFunction, Map, AllexJSONizingError)
};
}
module.exports = createHelpers;
},{"./arraycreator":1,"./scalarcreator":3}],3:[function(require,module,exports){
function createScalarHelpers (extend, readPropertyFromDotDelimitedString, isFunction, Map, AllexJSONizingError) {
'use strict';
function finderwithindex(findobj, propname, propval, item, index){
if (item && item[propname] === propval) {
findobj.element = item;
findobj.index = index;
return true;
}
}
function compare (a, b) {
if (a == b) {return 0;}
if (a > b) {return 1;}
return -1;
}
function finderwithindexandinsertindex(findobj, propname, propval, item, index){
var val, cmpval;
val = item[propname];
if (val === propval) {
findobj.element = item;
findobj.index = index;
return true;
}
cmpval = compare(val, propval);
if (cmpval<0) {
findobj.insertafter = index;
}
}
return {
finderwithindex: finderwithindex,
finderwithindexandinsertindex: finderwithindexandinsertindex
};
}
module.exports = createScalarHelpers;
},{}],4:[function(require,module,exports){
module.exports = function createArryOperations(extend, readPropertyFromDotDelimitedString, isFunction, Map, AllexJSONizingError) {
var helpers = require('./helpers')(extend, readPropertyFromDotDelimitedString, isFunction, Map, AllexJSONizingError);
function isArray (val) {return 'object' === typeof(val) && val instanceof Array;}
function helperselector (propname, propval, helpername) {
if (isArray(propname)) {
if (!isArray(propval)) {
throw new Error('propname-propval type mismatch');
}
if (propname.length != propval.length) {
throw new Error('propname-propval length mismatch');
}
return helpers.array[helpername];
}
return helpers.scalar[helpername];
}
function union(a1, a2) {
var ret = a1.slice();
appendNonExistingItems(ret, a2);
return ret;
}
function appendNonExistingItems(a1, a2) {
a2.forEach(function (a2e) {
if (a1.indexOf(a2e)<0) {
a1.push(a2e);
}
});
a1 = null;
}
function finder(findobj, propname, propval, item){
var und;
//if (item[propname] === propval) {
if (propval !== und && readPropertyFromDotDelimitedString(item, propname) === propval) {
findobj.found = item;
return true;
}
}
function findElementWithProperty(a, propname, propval) {
if (!(a && a.some)) {
return;
}
var und, findobj = {found: und}, ret;
a.some(finder.bind(null, findobj, propname, propval));
ret = findobj.found;
findobj.found = null;
findobj = null;
return ret;
}
function lastfinder (propname, propval, result, item) {
var und;
if (propval !== und && readPropertyFromDotDelimitedString(item, propname) === propval) {
return item;
}
return result;
}
function findLastElementWithProperty(a, propname, propval) {
var ret;
if (!(a && a.reduce)) {
return;
}
ret = a.reduce(lastfinder.bind(null, propname, propval), void 0);
propname = null;
propval = null;
return ret;
}
function findElementAndIndexWithProperty(a, propname, propval) {
if (!(a && a.some)) {
return;
}
var und, findobj = {element: und, index: und};
a.some(helperselector(propname, propval, 'finderwithindex').bind(null, findobj, propname, propval));
return findobj;
}
function findElementIndexAndInsertIndexWithProperty(a, propname, propval) {
if (!(a && a.some)) {
return;
}
var und, findobj = {element: und, index: und, insertafter: und}, _fo = findobj;
a.some(helperselector(propname, propval, 'finderwithindexandinsertindex').bind(null, _fo, propname, propval));
_fo = null;
propname = null;
propval = null;
return findobj;
}
function findToMatchFilter (a, filter) {
var ret = [];
for (var i = 0; i < a.length; i++) {
if (filter.isOK(a[i])) ret.push (a[i]);
}
return ret;
}
function findFirstToMatchFilter (a, filter) {
for (var i = 0; i < a.length; i++) {
if (filter.isOK(a[i])) return a[i];
}
}
function findWithProperty (arr, propname, propval) {
return arr.filter (finder.bind(null, {}, propname, propval));
}
function checkerForPropertyName(propertyname, propertyprocessor, arry, object, index) {
if (!object.hasOwnProperty(propertyname)) {
throw(new AllexJSONizingError('NO_PROPERTY', object, 'No propertyname'));
return;
}
var prop = object[propertyname], existing;
if (propertyprocessor) {
prop = propertyprocessor(prop);
}
existing = findElementAndIndexWithProperty(arry, propertyname, prop);
if (existing.element) {
arry[existing.index] = extend(existing.element, object);
} else {
arry.push(object);
}
}
function appendNonExistingObjects(a1, a2, propertyname, propertyprocessor) {
a2.forEach(checkerForPropertyName.bind(null, propertyname, propertyprocessor, a1));
}
function unionObjects(a1, a2, propertyname, propertyprocessor) {
var ret = a1.slice();
appendNonExistingObjects(ret, a2, propertyname, propertyprocessor);
return ret;
}
function execute_eqf (what, eqf, item){
if (eqf(item, what)) {
return true;
}
}
function contains (arr, what, eqf) {
if (!isFunction (eqf)) {
return arr.indexOf(what) > -1;
}
return arr.some(execute_eqf.bind(null, what, eqf));
}
function notcontains (arr, what, eqf){
return !contains(arr, what, eqf);
}
function _filter_notcontains (arr, eqf, what){
return notcontains(arr, what, eqf);
};
function difference (arr1, arr2, eqf) {
return arr1.filter(_filter_notcontains.bind(null, arr2, eqf));
}
function isConsistent (arr1, arr2) { ///means arr2 has to have starting elements equal to elements of arr1
if (arr2.length < arr1.length) return false;
for (var i = 0 ; i < arr1.length; i++) {
if (arr2[i] !== arr1[i]) return false;
}
return true;
}
function _intersect_check (ret, arr2, eqf, item) {
if (notcontains(arr2, item, eqf)) { return; }
if (contains(ret, item, eqf)) { return; }
ret.push (item);
}
function intersect (arr1, arr2, eqf) {
if (!(arr1 && arr1.length)) return [];
if (!(arr2 && arr2.length)) return [];
var ret = [];
arr1.forEach(_intersect_check.bind(null, ret, arr2, eqf));
return ret;
}
function pivot (source, options) {
var p = new Pivoter(options);
return p.pivot(source);
}
function unpivot (source, options) {
var p = new Pivoter(options);
return p.unpivot(source);
}
/* options:
x_field : this field is used for x axis ...
y_field : this field is used for y axis ...
value_field : this field is used for value ...
x_fields_list : list of fields accross x axis ...
init_empty_rows : should empty rows be inited,
to_y : converting function to y ...
from_y : convert back y value to original value ...
pivot_init_value : what should we put as initial value ...
*/
function Pivoter (options) {
this.options = extend ({}, Pivoter.DEFAULT_OPTIONS, options);
if (!this.options.x_field) throw new Error('No x_field config');
if (!this.options.y_field) throw new Error('No y_field config');
if (!this.options.value_field) throw new Error('No value_field config');
if (!this.options.x_fields_list) throw new Error('No x_fields_list config');
}
Pivoter.prototype.pivot = function (source) {
var ret = [];
source.forEach (this._processPivotSourceItem.bind(this, ret));
if (!this.options.init_empty_rows) return ret;
for (var i = 0; i < ret.length; i++) {
if (ret[i]) continue;
ret[i] = this.initializeEmptyPivotRecord();
}
return ret;
};
Pivoter.prototype._processPivotSourceItem = function (ret, item) {
var y = this.options.to_y(item[this.options.y_field], item);
if (!ret[y]) {
ret[y] = this.initializeEmptyPivotRecord();
}
var x = item[this.options.x_field];
if (!(x in ret[y])) throw new Error(x+' is not in filed list ...');
//console.log('PROCESSING PIVOT SOURCE ITEM', y, ret[y], item);
ret[y][x] = item[this.options.value_field];
};
Pivoter.prototype.initializeEmptyPivotRecord = function () {
var ret = {};
this.options.x_fields_list.forEach (this._createEmptyPivotField.bind(this, ret));
return ret;
};
Pivoter.prototype._createEmptyPivotField = function (ret, name) {
return ret[name] = 'pivot_init_value' in this.options ? this.options.pivot_init_value : null;
};
Pivoter.prototype.unpivot = function (source, removeNonExistingValueFromUnpivot) {
var ret = [];
source.forEach (this._processPivotedItem.bind(this, removeNonExistingValueFromUnpivot, ret));
return ret;
};
Pivoter.prototype._processPivotedItem = function (removeNonExistingValueFromUnpivot, ret, item, index) {
this.options.x_fields_list.forEach (this._fromPivoted.bind(this, removeNonExistingValueFromUnpivot, ret, index, item));
};
Pivoter.prototype._fromPivoted = function (removeNonExistingValueFromUnpivot, ret, y, item, field){
var o = {};
o[this.options.value_field] = item[field];
o[this.options.y_field] = this.options.from_y(y, item);
o[this.options.x_field] = field;
if (this._shouldAccountUnpivot(o, removeNonExistingValueFromUnpivot)) {
ret.push (this._processUnpivotRecord(o));
}
};
Pivoter.prototype._shouldAccountUnpivot = function (o, removeNonExistingValueFromUnpivot) {
if (removeNonExistingValueFromUnpivot) {
if (o[this.options.value_field] === this.options.nonexisting_value) {
return false;
}
}
var f = this.options.shouldAccountUnpivot;
return isFunction(f) ? f(o) : true;
};
Pivoter.prototype._processUnpivotRecord = function (rec) {
var f = this.options.processUnpivotRecord;
return isFunction(f) ? f(rec) : rec;
};
Pivoter.DEFAULT_OPTIONS = {
nonexisting_value : null,
init_empty_rows : false,
to_y: function (s) {return parseInt(s);},
from_y : function (s) {return s+'';}
};
function toRet (ret, val, name) {
ret.push (name);
}
function unique (arr) {
var map = new Map ();
for (var i = 0; i < arr.length; i++) {
if (!map.get(arr[i])) map.add(arr[i], true);
}
var ret = [];
map.traverse (toRet.bind(null, ret));
return ret;
}
function randomizeArray(array) {
var length = array.length;
var last = length - 1;
for (var index = 0; index < length; index++) {
var rand = Math.floor ((index+1)*Math.random());
var temp = array[index];
array[index] = array[rand];
array[rand] = temp;
}
return array;
}
var ret = {
intersect : intersect,
isConsistent : isConsistent,
contains : contains,
notcontains : notcontains,
difference : difference,
union: union,
appendNonExistingItems: appendNonExistingItems,
findElementWithProperty: findElementWithProperty,
findLastElementWithProperty: findLastElementWithProperty,
findElementAndIndexWithProperty: findElementAndIndexWithProperty,
findElementIndexAndInsertIndexWithProperty: findElementIndexAndInsertIndexWithProperty,
pivot : pivot,
unpivot : unpivot,
Pivoter : Pivoter,
findToMatchFilter : findToMatchFilter,
findFirstToMatchFilter : findFirstToMatchFilter,
unique : unique,
randomizeArray : randomizeArray,
findWithProperty : findWithProperty,
appendNonExistingObjects: appendNonExistingObjects,
unionObjects: unionObjects
};
return ret;
};
},{"./helpers":2}],5:[function(require,module,exports){
function Node(content){
this.left = null;
this.right = null;
this.leftCount = 0;
this.rightCount = 0;
this.content = content;
}
Node.prototype.destroy = function(){
this.content = null;
this.leftCount = null;
this.rightCount = null;
this.right = null;
this.left = null;
};
Node.prototype.returnOnRemove = function(){
return this.content;
};
Node.prototype.apply = function(func,depth){
return func(this.content,this,depth);
};
Node.prototype.advance = function(val){
if (val === -1){
return this.left;
}
if (val === 1){
return this.right;
}
throw new Error('Invalid value' + val + '. -1 for left, 1 for right.');
};
Node.prototype.higherSubtreeRootLeft = function(){
return (this.leftCount >= this.rightCount) ? this.left : this.right;
/*
if (this.leftCount >= this.rightCount){
return this.left;
}else{
return this.right;
}
*/
}
Node.prototype.higherSubtreeRootRight = function(){
return (this.rightCount >= this.leftCount) ? this.right : this.left;
/*
if (this.rightCount >= this.leftCount){
return this.right;
}else{
return this.left;
}
*/
}
Node.prototype.higherSubtree = function(){
return (this.leftCount >= this.rightCount ? this.leftCount : this.rightCount) + 1;
};
Node.prototype.findMax = function(stack){
var curr = this;
stack.addToFront(curr);
while (curr.right){
curr = curr.right;
stack.addToFront(curr);
}
return curr;
};
Node.prototype.findMin = function(stack){
var curr = this;
stack.addToFront(curr);
while (curr.left){
curr = curr.left;
stack.addToFront(curr);
}
return curr;
};
Node.prototype.absHeightDiff = function(){
return Math.abs(this.leftCount - this.rightCount);
};
Node.prototype.rotateLeftLeft = function(prnt,leaf){
this.left = leaf.right;
if (this.left !== null){
this.leftCount = this.left.higherSubtree();
}else{
this.leftCount = 0;
}
if (leaf.right !== null){
//leaf.right.up = this;
}
leaf.right = this;
//leaf.up = prnt;
//this.up = leaf;
leaf.rightCount = leaf.right.higherSubtree();
if (prnt !== null){
if (prnt.left === this){
prnt.left = leaf;
prnt.leftCount = prnt.left.higherSubtree();
}else{
prnt.right = leaf;
prnt.rightCount = prnt.right.higherSubtree();
}
}
};
Node.prototype.rotateLeftRight = function(prnt,leaf,bottom){
leaf.right = bottom.left;
if (leaf.right !== null){
leaf.rightCount = leaf.right.higherSubtree();
}else{
leaf.rightCount = 0;
}
if (bottom.left !== null){
//bottom.left.up = leaf;
}
bottom.left = leaf;
bottom.leftCount = bottom.left.higherSubtree();
this.left = bottom;
this.leftCount = this.left.higherSubtree();
//bottom.up = this;
//leaf.up = bottom;
this.rotateLeftLeft(prnt,bottom);
};
Node.prototype.rotateRightRight = function(prnt,leaf){
this.right = leaf.left;
if (this.right !== null){
this.rightCount = this.right.higherSubtree();
}else{
this.rightCount = 0;
}
if (leaf.left !== null){
//leaf.left.up = this;
}
leaf.left = this;
//leaf.up = prnt;
//this.up = leaf;
leaf.leftCount = leaf.left.higherSubtree();
if (prnt !== null){
if (prnt.left === this){
prnt.left = leaf;
prnt.leftCount = prnt.left.higherSubtree();
}else{
prnt.right = leaf;
prnt.rightCount = prnt.right.higherSubtree();
}
}
};
Node.prototype.rotateRightLeft = function(prnt,leaf,bottom){
leaf.left = bottom.right;
if (leaf.left !== null){
leaf.leftCount = leaf.left.higherSubtree();
}else{
leaf.leftCount = 0;
}
if (bottom.right !== null){
//bottom.right.up = leaf;
}
bottom.right = leaf;
bottom.rightCount = bottom.right.higherSubtree();
this.right = bottom;
this.rightCount = this.right.higherSubtree();
//bottom.up = this;
//leaf.up = bottom;
this.rotateRightRight(prnt,bottom);
};
Node.prototype.contentToString = function(){
return this.content.toString();
};
module.exports = Node;
},{}],6:[function(require,module,exports){
function createStack(doublelinkedlistbase, inherit) {
'use strict';
var ListItemCtor = doublelinkedlistbase.Item,
ListMixin = doublelinkedlistbase.Mixin;
function TreeBranchItem (content) {
ListItemCtor.call(this, content);
}
inherit(TreeBranchItem, ListItemCtor);
function TreeBranchStack(){
ListMixin.call(this);
}
ListMixin.addMethods(TreeBranchStack);
TreeBranchStack.prototype.addToFront = function(content){
if (!checkForTreeNode(content)) {
return;
}
var newItem = new TreeBranchItem(content);
this.assureForController();
this.controller.addToFront(newItem);
};
TreeBranchStack.prototype.addToBack = function(content){
var newItem;
if (!checkForTreeNode(content)) {
return;
}
if (!this.assureForController()) {
return;
}
newItem = new TreeBranchItem(content);
this.controller.addToBack(newItem);
};
TreeBranchStack.prototype.push = TreeBranchStack.prototype.addToBack;
TreeBranchStack.prototype.shift = function(){
var ret, head;
if (!this.head) {
return;
}
if (!this.assureForController()) {
return;
}
ret = this.head.content;
if (!checkForTreeNode(ret)) {
return;
}
head = this.head;
this.controller.remove(this.head);
head.destroy();
return ret;
};
TreeBranchStack.prototype.addAsPrevTo = function (content, prevtarget) {
if (!this.assureForController()) {
return;
}
this.controller.addAsPrevTo(new TreeBranchItem(content), prevtarget);
};
TreeBranchStack.prototype.findOne = function(criterionfunction){
var item = this.firstItemToSatisfy(criterionfunction);
if(item){
return item.content;
}else{
return;
}
};
function checkForTreeNode(ret) {
if (!(ret && ret.hasOwnProperty('left'))) {
console.trace();
console.error(ret);
return false;
}
return true;
}
return TreeBranchStack;
}
module.exports = createStack;
},{}],7:[function(require,module,exports){
(function (process){(function (){
function createAvlTreeControllerFactory(Stack) {
'use strict';
return function createAvlTreeController(compare){
//TODO check if compare is a function??
function AvlTreeController(myTree){
this.tree = myTree;
}
AvlTreeController.prototype.destroy = function(){
this.tree = null;
};
AvlTreeController.prototype.remove = function(content){
if (typeof content !== 'number' && !content){
return false;
}
var prevStack = this.prevStackToEqual(content);
if(!prevStack){
return false;
}
var leaf = prevStack.shift()||null;
var oldHeight = 0;
var higher = null;
var newHeight = 0;
var high,middle,low;
var balanceInd = false;
var ret;
//1. case - No children
if (leaf.left === null && leaf.right === null){
higher = prevStack.shift()||null;
if (higher === null){
this.tree.root = null;
this.tree.decCount();
ret = leaf.returnOnRemove();
leaf.destroy();
prevStack.destroy();
return ret;
}else{
oldHeight = higher.higherSubtree();
if (higher.left === leaf){
higher.left = null;
higher.leftCount--;
high = higher;
middle = higher.right;
if (!!middle){
low = middle.higherSubtreeRootLeft();
}else{
low = null;
}
}else{
higher.right = null;
higher.rightCount--;
high = higher;
middle = higher.left;
if (!!middle){
low = middle.higherSubtreeRootRight();
}else{
low = null;
}
}
newHeight = higher.higherSubtree();
balanceInd = balanceInd || (higher.absHeightDiff() === 2);
}
}else{
if (leaf.left === null || leaf.right === null){
higher = prevStack.shift()||null;
if (higher !== null){
oldHeight = higher.higherSubtree();
}
//2.1 case - 1 child - Left
if (leaf.left !== null && leaf.right === null){
if (higher !== null){
if (higher.left === leaf){
higher.left = leaf.left;
higher.leftCount--;
high = higher;
middle = higher.right;
if (!!middle){
low = middle.higherSubtreeRootLeft();
}else{
low = null;
}
}else{
higher.right = leaf.left;
higher.rightCount--;
high = higher;
middle = higher.left;
if (!!middle){
low = middle.higherSubtreeRootRight();
}else{
low = null;
}
}
newHeight = higher.higherSubtree();
balanceInd = balanceInd || (higher.absHeightDiff() === 2);
}else{
this.tree.root = leaf.left;
newHeight = 0;
}
}else{
//2.2 case - 1 child - Right
if (leaf.left === null && leaf.right !== null){
if (higher !== null){
if (higher.left === leaf){
higher.left = leaf.right;
higher.leftCount--;
high = higher;
middle = higher.right;
if (!!middle){
low = middle.higherSubtreeRootLeft();
}else{
low = null;
}
}else{
higher.right = leaf.right;
higher.rightCount--;
high = higher;
middle = higher.left;
if (!!middle){
low = middle.higherSubtreeRootRight();
}else{
low = null;
}
}
newHeight = higher.higherSubtree();
balanceInd = balanceInd || (higher.absHeightDiff() === 2);
}else{
this.tree.root = leaf.right;
newHeight = 0;
}
}
}
}else{
//3 case - 2 children
var leafParent = prevStack.head;
leaf.right.findMin(prevStack);
var max = prevStack.shift()||null;
var maxParent = prevStack.shift()||null;
if (maxParent === null){
oldHeight = leaf.higherSubtree();
max.left = leaf.left;
max.leftCount = max.left.higherSubtree();
high = max;
middle = max.left;
low = middle.higherSubtreeRootRight();
balanceInd = balanceInd || (max.absHeightDiff() === 2);
newHeight = leaf.higherSubtree();
}else{
oldHeight = maxParent.higherSubtree();
if (maxParent.left === max){
maxParent.left = max.right;
maxParent.leftCount--;
max.left = leaf.left;
max.leftCount = max.left.higherSubtree();
if (leaf.right !== max){
max.right = leaf.right;
max.rightCount = max.right.higherSubtree();
}
high = maxParent;
middle = maxParent.right;
if (!!middle){
low = middle.higherSubtreeRootLeft();
}else{
low = null;
}
if (leafParent !== null){
prevStack.addAsPrevTo(max, leafParent);
//leafParent.insertBefore(max,prevStack);
higher = leafParent.content;
if (higher.left === leaf){
higher.left = max;
}else{
higher.right = max;
}
}else{
prevStack.addToBack(max);
}
balanceInd = balanceInd || (maxParent.absHeightDiff() === 2);
}else{
max.left = leaf.left;
max.leftCount = max.left.higherSubtree();
if (leaf.right !== max){
max.right = leaf.right;
max.rightCount = max.right.higherSubtree();
}
if (maxParent.left === leaf){
maxParent.left = max;
maxParent.leftCount = maxParent.left.higherSubtree();
}else{
maxParent.right = max;
maxParent.rightCount = maxParent.right.higherSubtree();
}
high = max;
middle = max.left;
if (!!middle){
low = middle.higherSubtreeRootRight();
}else{
low = null;
}
prevStack.addToFront(maxParent);
balanceInd = balanceInd || (max.absHeightDiff() === 2) || (maxParent.absHeightDiff() === 2);
}
newHeight = maxParent.higherSubtree();
}
if (leaf === this.tree.root){
this.tree.root = max;
}
}
}
this.tree.decCount();
if (oldHeight !== newHeight || !!balanceInd){
this.doBalanceRemove(high,middle,low,prevStack);
}
ret = leaf.returnOnRemove();
leaf.destroy();
prevStack.destroy();
return ret;
};
AvlTreeController.prototype.add = function(newItem){
if (!newItem){
return;
}
var prevStack = this.prevStackToLeaf(newItem.content);
var leaf = prevStack.shift()||null;
if (leaf === null){
this.tree.root = newItem;
prevStack.destroy();
return;
}else{
var res = compare(leaf.content,newItem.content);
//newItem.up = leaf;
if (res===0){
console.trace();
prevStack.destroy();
console.error(leaf.content, 'is not unique');
throw new Error('Items must have unique content');
}
if (res===-1){
leaf.left = newItem;
leaf.leftCount++;
}else{
leaf.right = newItem;
leaf.rightCount++;
}
}
var higher = prevStack.shift()||null;
var bottom = newItem;
if (leaf.leftCount !== leaf.rightCount){
this.doBalanceAdd(higher,leaf,bottom,prevStack);
}
prevStack.destroy();
};
AvlTreeController.prototype.doBalanceAdd = function(higher,leaf,bottom,prevStack){
var tmp;
while (higher){
var prnt = prevStack.shift()||null;
if (higher.left === leaf){
higher.leftCount = leaf.higherSubtree();
if (higher.leftCount === higher.rightCount){
break;
}
if (higher.leftCount - higher.rightCount === 2){
if (leaf.leftCount - leaf.rightCount >= 0){
higher.rotateLeftLeft(prnt,leaf);
if (prnt === null){
this.tree.root = leaf;
}
tmp = higher;
higher = leaf;
leaf = bottom;
bottom = tmp;
}else{
higher.rotateLeftRight(prnt,leaf,bottom);
if (prnt === null){
this.tree.root = bottom;
}
tmp = higher;
higher = bottom;
leaf = bottom;
bottom = tmp;
}
}
}else{
higher.rightCount = leaf.higherSubtree();
if (higher.leftCount === higher.rightCount){
break;
}
if (higher.leftCount - higher.rightCount === -2){
if (leaf.leftCount - leaf.rightCount <= 0){
higher.rotateRightRight(prnt,leaf);
if (prnt === null){
this.tree.root = leaf;
}
tmp = higher;
higher = leaf;
leaf = bottom;
bottom = tmp;
}else{
higher.rotateRightLeft(prnt,leaf,bottom);
if (prnt === null){
this.tree.root = bottom;
}
tmp = higher;
higher = bottom;
leaf = bottom;
bottom = tmp;
}
}
}
bottom = leaf;
leaf = higher;
higher = prnt;
}
};
AvlTreeController.prototype.doBalanceRemove = function(higher,leaf,bottom,prevStack){
var tmp;
while (higher){
var prnt = prevStack.shift()||null;
if (!!leaf){
if (higher.right === leaf){
higher.leftCount = !!higher.left ? higher.left.higherSubtree() : 0;
if (higher.leftCount + 1 === higher.rightCount){
break;
}
if (higher.leftCount - higher.rightCount === -2){
if (leaf.leftCount - leaf.rightCount <= 0){
higher.rotateRightRight(prnt,leaf);
if (prnt === null){
this.tree.root = leaf;
}
tmp = higher;
higher = leaf;
leaf = bottom;
bottom = tmp;
}else{
higher.rotateRightLeft(prnt,leaf,bottom);
if (prnt === null){
this.tree.root = bottom;
}
tmp = higher;
higher = bottom;
leaf = bottom;
bottom = tmp;
}
}
}else{
higher.rightCount = !!higher.right ? higher.right.higherSubtree() : 0;
if (higher.leftCount === higher.rightCount + 1){
break;
}
if (higher.leftCount - higher.rightCount === 2){
if (leaf.leftCount - leaf.rightCount >= 0){
higher.rotateLeftLeft(prnt,leaf);
if (prnt === null){
this.tree.root = leaf;
}
tmp = higher;
higher = leaf;
leaf = bottom;
bottom = tmp;
}else{
higher.rotateLeftRight(prnt,leaf,bottom);
if (prnt === null){
this.tree.root = bottom;
}
tmp = higher;
higher = bottom;
leaf = bottom;
bottom = tmp;
}
}
}
}
if (!!prnt){
if (prnt.left === higher){
leaf = prnt.right;
bottom = leaf.higherSubtreeRootLeft();
}else{
leaf = prnt.left;
if (!(leaf && leaf.higherSubtreeRootRight)) {
console.trace();
console.log(prnt);
process.exit(0);
}
bottom = leaf.higherSubtreeRootRight();
}
}
higher = prnt;
}
};
AvlTreeController.prototype.prevStackToLeaf = function(content){
var curr = this.tree.root;
var prevStack = new Stack();
var res;
while (curr !== null){
res = compare(curr.content,content);
if (res === 0){
console.trace();
prevStack.destroy();
console.error(content, 'is not unique');
throw new Error('Items must have unique content');
}
prevStack.addToFront(curr);
curr = curr.advance(res);
}
return prevStack;
};
AvlTreeController.prototype.prevStackToEqual = function(content){
var curr = this.tree.root;
var prevStack = new Stack();
var res;
while (curr !== null){
prevStack.addToFront(curr);
res = compare(curr.content,content);
if (res === 0){
return prevStack;
}
curr = curr.advance(res);
}
prevStack.destroy();
/*
console.trace();
throw Error('Item with content ' + JSON.stringify(content) + ' does not exist.');
*/
return;
}
AvlTreeController.prototype.find = function(content){
var curr = this.tree.root;
var res;
while (curr){
res = compare(curr.content,content);
if (res === 0){
return curr;
}
curr = curr.advance(res);
}
return null;
};
function nodeApplier (node, thingy, errorcaption) {
if (!errorcaption) {
return node.apply(thingy);
}
if (!(typeof errorcaption == 'string')) {
console.error('what is errorcaption?', errorcaption);
process.exit(1);
}
try {
return node.apply(thingy);
} catch (e) {
console.log(errorcaption+' :', e);
return;
}
}
function nodeApplier2 (node, thingy1, thingy2, errorcaption) {
if (!errorcaption) {
return node.apply(thingy1, thingy2);
}
try {
return node.apply(thingy1, thingy2);
} catch (e) {
console.log(errorcaption+' :', e);
return;
}
}
AvlTreeController.prototype.firstItemToSatisfyPreOrder = function(func, node, errorcaption){
if (!node) return null;
var check = nodeApplier(node, func, errorcaption);
if ('boolean' !== typeof check){
throw Error('func needs to return a boolean value');
}
if (!!check){
return node.content;
}
var ret = this.firstItemToSatisfyPreOrder(func,node.left, errorcaption);
if (!!ret) return ret;
ret = this.firstItemToSatisfyPreOrder(func,node.right, errorcaption);
if (!!ret) return ret;
};
AvlTreeController.prototype.firstItemToSatisfyInOrder = function(func, node, errorcaption){
if (!node) return null;
ret = this.firstItemToSatisfyInOrder(func,node.left, errorcaption);
if (!!ret) return ret;
var check = nodeApplier(node, func, errorcaption);
if ('boolean' !== typeof check){
throw Error('func needs to return a boolean value');
}
if (!!check){
return node.content;
}
ret = this.firstItemToSatisfyInOrder(func,node.right, errorcaption);
if (!!ret) return ret;
};
AvlTreeController.prototype.firstItemToSatisfyPostOrder = function(func, node, errorcaption){
if (!node) return null;
var ret = this.firstItemToSatisfyPostOrder(func,node.left, errorcaption);
if (!!ret) return ret;
ret = this.firstItemToSatisfyPostOrder(func,node.right, errorcaption);
if (!!ret) return ret;
var check = nodeApplier(node, func, errorcaption);
if ('boolean' !== typeof check){
throw Error('func needs to return a boolean value');
}
if (!!check){
return node.content;
}
};
AvlTreeController.prototype.lastItemToSatisfyPreOrder = function(func,node,prev, errorcaption){
if (!node) return null;
var check = nodeApplier(node, func, errorcaption);
if ('boolean' !== typeof check){
throw Error('func needs to return a boolean value');
}
if (!check){
return !!prev ? prev.content : null;
}
var ret = this.lastItemToSatisfyPreOrder(func,node.left,node, errorcaption);
if (!!ret) return ret;
ret = this.lastItemToSatisfyPreOrder(func,node.right,node, errorcaption);
if (!!ret) return ret;
return null;
};
AvlTreeController.prototype.lastItemToSatisfyInOrder = function(func,node,prev, errorcaption){
if (!node) return null;
var ret = this.lastItemToSatisfyInOrder(func,node.left,node, errorcaption);
if (!!ret) return ret;
var check = nodeApplier(node, func, errorcaption);
if ('boolean' !== typeof check){
throw Error('func needs to return a boolean value');
}
if (!check){
return !!prev ? prev.content : null;
}
ret = this.lastItemToSatisfyInOrder(func,node.right,node, errorcaption);
if (!!ret) return ret;
return null;
};
AvlTreeController.prototype.lastItemToSatisfyPostOrder = function(func,node,prev, errorcaption){
if (!node) return null;
var ret = this.lastItemToSatisfyPostOrder(func,node.left,node, errorcaption);
if (!!ret) return ret;
ret = this.lastItemToSatisfyPostOrder(func,node.right,node, errorcaption);
if (!!ret) return ret;
var check = nodeApplier(node, func, errorcaption);
if ('boolean' !== typeof check){
throw Error('func needs to return a boolean value');
}
if (!check){
return !!prev ? prev.content : null;
}
return null;
};
AvlTreeController.prototype.traversePreOrder = function(func, node, depth, errorcaption){
if (!node) return;
nodeApplier2(node,func,depth, errorcaption);
this.traversePreOrder(func,node.left,depth+1, errorcaption);
this.traversePreOrder(func,node.right,depth+1, errorcaption);
};
AvlTreeController.prototype.traversePreOrderConditionally = function(func, node, depth, errorcaption){
if (!node) return;
var ret = nodeApplier2(node,func,depth, errorcaption);
if(typeof ret !== 'undefined'){
return ret;
}
ret = this.traversePreOrderConditionally(func,node.left,depth+1, errorcaption);
if(typeof ret !== 'undefined'){
return ret;
}
return this.traversePreOrderConditionally(func,node.right,depth+1, errorcaption);
};
AvlTreeController.prototype.traverseInOrder = function(func, node, depth, errorcaption){
if (!node) return;
this.traverseInOrder(func,node.left,depth+1, errorcaption);
nodeApplier2(node,func,depth, errorcaption);
this.traverseInOrder(func,node.right,depth+1, errorcaption);
};
AvlTreeController.prototype.traverseInOrderConditionally = function(func, node, depth, errorcaption){
if (!node) return;
var ret = this.traverseInOrderConditionally(func,node.left,depth+1, errorcaption);
if(typeof ret !== 'undefined'){
return ret;
}
ret = nodeApplier2(node,func,depth, errorcaption);
if(typeof ret !== 'undefined'){
return ret;
}
return this.traverseInOrderConditionally(func,node.right,depth+1, errorcaption);
};
AvlTreeController.prototype.traversePostOrder = function(func, node, depth, errorcaption){
if (!node) return;
this.traversePostOrder(func,node.left,depth+1, errorcaption);
this.traversePostOrder(func,node.right,depth+1, errorcaption);
nodeApplier2(node,func,depth, errorcaption);
};
AvlTreeController.prototype.traversePostOrderConditionally = function(func, node, depth, errorcaption){
if (!node) return;
var ret = this.traversePostOrderConditionally(func,node.left,depth+1, errorcaption);
if(typeof ret !== 'undefined'){
return ret;
}
ret = this.traversePostOrderConditionally(func,node.right,depth+1, errorcaption);
if(typeof ret !== 'undefined'){
return ret;
}
return nodeApplier2(node,func,depth, errorcaption);
};
return AvlTreeController;
}
}
module.exports = createAvlTreeControllerFactory;
}).call(this)}).call(this,require('_process'))
},{"_process":378}],8:[function(require,module,exports){
function createAvlTree (dlistbase, inherit) {
return {
treeFactory: require('./treefactorycreator')(dlistbase, inherit),
Node: require('./Node')
}
}
module.exports = createAvlTree;
},{"./Node":5,"./treefactorycreator":9}],9:[function(require,module,exports){
function createTreeFactory(dlistbase, inherit) {
var controllerFactory = require('./controllerfactorycreator')(require('./Stack.js')(dlistbase, inherit));
return function createTreeKlass(compare,nodefactory){
var controllerctor = controllerFactory(compare);
function AvlTree(){
this.root = null;
this.count = 0;
this.controller = new controllerctor(this);
}
AvlTree.prototype.destroy = function(){
this.purge();
this.count = null;
this.root = null;
if (this.controller) {
this.controller.destroy();
}
this.controller = null;
};
function contentGetter(content,node){
return content;
}
function destroyer (node) {
node.destroy();
}
AvlTree.prototype.purge = function(){
var nodes = [], _ns = nodes;
this.controller.traverseInOrder(function (n) {_ns.push(n);});
_ns = null;
nodes.forEach(destroyer);
nodes = null;
this.root = null;
this.count = 0;
};
AvlTree.prototype.count = function(){
return this.count;
}
AvlTree.prototype.empty = function(){
return this.count === 0;
};
AvlTree.prototype.add = function(){ //arguments are to be fed into nodefactory
if (!this.controller) {
return null;
}
var newItem = nodefactory.apply(null,arguments);//new nodector(content);
this.controller.add(newItem);
this.count++;
return newItem;
};
//TODO private?
AvlTree.prototype.decCount = function(){
this.count--;
};
AvlTree.prototype.remove = function(content){
if (!this.controller) {
return null;
}
return this.controller.remove(content);
};
AvlTree.prototype.find = function(content){
if (!this.controller) {
return null;
}
return this.controller.find(content);
};
AvlTree.prototype.findOne = function(criterionfunction){
if ('function' !== typeof criterionfunction){
throw new Error('First parameter \'criterionfunction\' is not a function');
}
return this.firstItemToSatisfy(criterionfunction);
};
AvlTree.prototype.firstItemToSatisfyPreOrder = function(func){
if (!this.controller) {
return null;
}
return this.controller.firstItemToSatisfyPreOrder(func,this.root);
};
AvlTree.prototype.firstItemToSatisfy = function(func){
if (!this.controller) {
return null;
}
return this.controller.firstItemToSatisfyInOrder(func,this.root);
};
AvlTree.prototype.firstItemToSatisfyPostOrder = function(func){
if (!this.controller) {
return null;
}
return this.controller.firstItemToSatisfyPostOrder(func,this.root);
};
AvlTree.prototype.lastItemToSatisfyPreOrder = function(func){
if (!this.controller) {
return null;
}
return this.controller.lastItemToSatisfyPreOrder(func,this.root,null);
};
AvlTree.prototype.lastItemToSatisfy = function(func){
if (!this.controller) {
return null;
}
return this.controller.lastItemToSatisfyInOrder(func,this.root,null);
};
AvlTree.prototype.lastItemToSatisfyPostOrder = function(func){
if (!this.controller) {
return null;
}
return this.controller.lastItemToSatisfyPostOrder(func,this.root,null);
};
AvlTree.prototype.traverseInOrder = function(func){
if (!this.controller) {
return;
}
this.controller.traverseInOrder(func,this.root,0);
};
AvlTree.prototype.traversePreOrder= function(func){
if (!this.controller) {
return;
}
this.controller.traversePreOrder(func,this.root,0);
}
AvlTree.prototype.traversePostOrder= function(func){
if (!this.controller) {
return;
}
this.controller.traversePostOrder(func,this.root,0);
}
AvlTree.prototype.traverseInOrderConditionally = function(func){
if (!this.controller) {
return;
}
return this.controller.traverseInOrderConditionally(func,this.root,0);
}
AvlTree.prototype.traversePreOrderConditionally= function(func){
if (!this.controller) {
return;
}
return this.controller.traversePreOrderConditionally(func,this.root,0);
}
AvlTree.prototype.traversePostOrderConditionally= function(func){
if (!this.controller) {
return;
}
return this.controller.traversePostOrderConditionally(func,this.root,0);
}
AvlTree.prototype.dumpToConsole = function(func){
console.log('\n-----------------------------------------------------------------\n');
this.traverseInOrder(func||consoleTree);
};
function consoleTree(content,item,level){
var s = '';
for(var i=0; i<level; i++){
s += '\t';
}
console.log(s+item.contentToString()+' ('+level+')');
}
/*
function drainer(arry,countobj,content){
arry[countobj.count] = content;
countobj.count++;
}
AvlTree.prototype.drain = function(){
var ret = new Array(this.length),countobj={count:0},_ret = ret;
this.traverse(drainer.bind(null,_ret,countobj));
_ret = null;
this.purge();
return ret;
};
*/
return AvlTree;
}
}
module.exports = createTreeFactory;
},{"./Stack.js":6,"./controllerfactorycreator":7}],10:[function(require,module,exports){
(function (process){(function (){
module.exports = function (lib) {
'use strict';
var q = lib.q,
jsonschema = lib.jsonschema,
validator = new (jsonschema.Validator)();
//TODO: load some prefefined schemas into validator for common data types like email and so on ...
function extractValidationMessages(title, error) {
return (title ? (title + ': ') : '') + error.path.join('.') + ' ' + error.message;
}
function validateSingleParam(errors, complete_schema, param_value, param_index) {
var schema = complete_schema[param_index], ret, result;
if( lib.isUndef(schema) ){
console.error('no schema for',param_index,'in',complete_schema);
return undefined;
}
//if schema === true just let it pass ...
if (schema === true) {
return undefined;
}
if ((null === param_value || lib.isUndef(param_value)) && schema.required===false) {
ret = schema.required ? 'Missing param: ' + schema.title : undefined;
//console.log('Param value is', param_value, 'and ', schema.required, ret);
return ret;
}
result = validator.validate(param_value, schema);
if (!result.errors.length) {
return;
}
Array.prototype.push.apply(errors, result.errors.map(extractValidationMessages.bind(null, schema.title)));
}
var __id=0;
function Callable() {
//this.__id = ++__id;
this._activeDefers = new lib.DeferMap();
}
Callable.prototype.destroy = function () {
//console.trace();
//console.log(this.__id, 'destroying');
var ad = this._activeDefers;
this._activeDefers = null;
if (ad) {
ad.destroy();
}
};
Callable.prototype.executeStep = function (stepspec) {
//console.log('stepspec', stepspec);
var ret = this._activeDefers.defer(lib.uid()),
methodname = stepspec[0],
method = this[methodname],
ml,
params,
trailing,
vp,
cleaner;
if (!ret.resolve) {
console.trace();
console.error('this has to be a defer:', ret);
process.exit(0);
}
if ('function' !== typeof method) {
console.trace();
console.log('In', this.__methodDescriptors, 'Method ' + methodname + ' does not exist');
ret.reject(new lib.Error('METHOD_DOES_NOT_EXIST', 'Method ' + methodname + ' does not exist'));
return ret.promise;
}
if (this.__methodDescriptors && !this.__methodDescriptors[methodname]) {
console.log(this.__methodDescriptors, methodname, '?');
ret.reject(new lib.Error('METHOD_NOT_EXECUTABLE