openct-tasks/_common/modules/pemFioi/beav-1.0.js

521 lines
12 KiB
JavaScript

var Beav = new Object();
/**********************************************************************************/
/* Object */
Beav.Object = new Object();
Beav.Object.eq = function eq(x, y) {
// assumes arguments to be of same type, except if one of the two arguments is null,
// in which case the comparison returns true if the other argument is also null.
if (x == null || y == null) {
return (x == null && y == null);
}
var tx = typeof(x);
var ty = typeof(y);
if (tx != ty) {
throw "Beav.Object.eq incompatible types";
}
if (tx == "boolean" || tx == "number" || tx == "string" || tx == "undefined") {
return x == y;
}
if ($.isArray(x)) {
if (! $.isArray(y))
throw "Beav.Object.eq incompatible types";
if (x.length != y.length)
return false;
for (var i = 0; i < x.length; i++)
if (! eq(x[i], y[i]))
return false;
return true;
}
if (tx == "object") {
var kx = [];
for (var key in x) {
kx.push(key);
}
var ky = [];
for (var key in y) {
ky.push(key);
}
var sort_keys = function(n1,n2) { return (n1 < n2) ? -1 : ((n1 > n2) ? 1 : 0); };
kx.sort(sort_keys);
ky.sort(sort_keys);
if (kx.length != ky.length)
return false;
for (var i = 0; i < kx.length; i++) {
var ex = kx[i];
var ey = ky[i];
if (ex != ey)
return false;
if (! eq(x[ex], y[ex]))
return false;
}
return true;
}
throw "Beav.Object.eq unsupported types";
};
Beav.Object.clone = function(obj) {
return JSON.parse(JSON.stringify(obj))
};
/**********************************************************************************/
/* Array */
Beav.Array = new Object();
Beav.Array.make = function(nb, initValue) {
var t = [];
for (var i = 0; i < nb; i++)
t[i] = initValue;
return t;
};
Beav.Array.init = function(nb, initFct) {
var t = [];
for (var i = 0; i < nb; i++)
t.push(initFct(i));
return t;
};
Beav.Array.indexOf = function(t, v, eq) {
if (eq === undefined)
eq = Beav.Object.eq;
for (var i = 0; i < t.length; i++)
if (eq(t[i], v))
return i;
return -1;
};
Beav.Array.has = function(t, v, eq) {
return Beav.Array.indexOf(t, v, eq) != -1;
};
Beav.Array.filterCount = function(t, filterFct) {
var count = 0;
for (var i = 0; i < t.length; i++)
if (filterFct(t[i], i))
count++;
return count;
};
Beav.Array.stableSort = function(t, compFct) {
var swap = function(a, b) {
var v = t[a];
t[a] = t[b];
t[b] = v;
};
var insert = function (i, j, v) {
while(i+1 < j && compFct(t[i+1], v) < 0) {
swap(i, i+1);
i++;
}
t[i] = v;
};
var merge = function(i, k, j) {
for ( ; i<k; i++) {
if (compFct(t[k], t[i]) < 0) {
var v = t[i];
t[i] = t[k];
insert(k, j, v);
}
}
};
var msort = function msort(i, j) {
var size = j - i;
if (size < 2)
return;
var k = i + Math.floor(size/2);
msort(i, k);
msort(k, j);
merge(i, k, j);
};
msort(0, t.length);
};
Beav.Array.shuffle = function(t, randomSeed) {
var nbValues = t.length;
for (var iValue = 0; iValue < nbValues; iValue++) {
// TODO: we should pick the next random number at every step
// by calling, e.g., randomSeed = RandomGenerator.next(randomSeed);
var randomShift = randomSeed % (nbValues - iValue);
var pos = iValue + randomShift;
var tmp = t[iValue];
t[iValue] = t[pos];
t[pos] = tmp;
}
};
/**********************************************************************************/
/* Matrix */
Beav.Matrix = new Object();
Beav.Matrix.init = function(nbRows, nbCols, initFct) {
var m = [];
for (var x = 0; x < nbRows; x++) {
var t = [];
for (var y = 0; y < nbCols; y++) {
t.push(initFct(x, y));
}
m.push(t);
}
return m;
};
Beav.Matrix.map = function(m, mapFct) {
var r = [];
for (var x = 0; x < m.length; x++) {
r[x] = [];
for (var y = 0; y < m[x].length; y++) {
r[x][y] = mapFct(m[x][y], x, y, m);
}
}
return r;
};
Beav.Matrix.copy = function(m) {
return Beav.Matrix.map(m, function(v) { return v; });
};
Beav.Matrix.make = function(nbRows, nbCols, v) {
return Beav.Matrix.init(nbRows, nbCols, function() { return v; });
};
Beav.Matrix.forEach = function(m, iterFct) {
for (var x = 0; x < m.length; x++) {
for (var y = 0; y < m[x].length; y++) {
iterFct(m[x][y], x, y, m);
}
}
};
Beav.Matrix.filterCount = function(m, selectFct) {
var count = 0;
for (var x = 0; x < m.length; x++) {
for (var y = 0; y < m[x].length; y++) {
if (selectFct(m[x][y], x, y)) {
count++;
}
}
}
return count;
};
/**********************************************************************************/
/* Matrix3D */
Beav.Matrix3D = new Object();
Beav.Matrix3D.init = function(nbX, nbY, nbZ, initFct) {
var m = [];
for (var x = 0; x < nbX; x++) {
var t = [];
for (var y = 0; y < nbY; y++) {
var r = [];
for (var z = 0; z < nbZ; z++) {
r.push(initFct(x, y, z));
}
t.push(r);
}
m.push(t);
}
return m;
};
Beav.Matrix3D.map = function(m, mapFct) {
var r = [];
for (var x = 0; x < m.length; x++) {
r[x] = [];
for (var y = 0; y < m[x].length; y++) {
r[x][y] = [];
for (var z = 0; z < m[x][y].length; z++) {
r[x][y][z] = mapFct(m[x][y][z], x, y, z, m);
}
}
}
return r;
};
Beav.Matrix3D.copy = function(m) {
return Beav.Matrix3D.map(m, function(v) { return v; });
};
Beav.Matrix3D.make = function(nbX, nbY, nbZ, v) {
return Beav.Matrix3D.init(nbX, nbY, nbZ, function() { return v; });
};
Beav.Matrix3D.forEach = function(m, iterFct) {
for (var x = 0; x < m.length; x++) {
for (var y = 0; y < m[x].length; y++) {
for (var z = 0; z < m[x][y].length; z++) {
iterFct(m[x][y][z], x, y, z, m);
}
}
}
};
Beav.Matrix3D.filterCount = function(m, selectFct) {
var count = 0;
for (var x = 0; x < m.length; x++) {
for (var y = 0; y < m[x].length; y++) {
for (var z = 0; z < m[x][y].length; z++) {
if (selectFct(m[x][y][z], x, y, z)) {
count++;
}
}
}
}
return count;
};
/**********************************************************************************/
/* Exception */
/* Mechanism for having user exceptions that cannot be confused
with JavaScript builtin exceptions.
To throw the exception myExn, do:
Beav.Exception.throw(myExn);
To catch only user exceptions, do:
try {
...
} catch (exn) {
var myExn = Beav.Exception.extract(exn);
...
}
In this case, the exception is automatically re-thrown
if it is not a user exception.
*/
/*
Beav.Exception = {};
Beav.Exception.constructor = function(arg) {
this.contents = arg;
};
Beav.Exception.throw = function(arg) {
throw new Beav.Exception.constructor(arg);
};
Beav.Exception.extract = function(exn) {
if (exn instanceof Beav.Exception.constructor) {
return exn.contents;
} else {
throw exn;
}
};
*/
/**********************************************************************************/
/* Navigator */
Beav.Navigator = new Object();
Beav.Navigator.isIE8 = function() {
return navigator.appVersion.indexOf("MSIE 8.") != -1;
}
/**********************************************************************************/
/* Dom */
Beav.Dom = new Object();
Beav.Dom.showOrHide = function(e, visible) {
if (visible)
e.show();
else
e.hide();
};
/**********************************************************************************/
/* HTML */
Beav.Html = new Object();
// Escape the html characters in a string
Beav.Html.escape = function(stringToEncode) {
var entityMap = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': '&quot;',
"'": '&#39;',
"/": '&#x2F;' };
return String(stringToEncode).replace(/[&<>"'\/]/g, function (s) {
return entityMap[s];
});
};
/**********************************************************************************/
/* Raphael */
Beav.Raphael = new Object();
Beav.Raphael.line = function(paper, x1, y1, x2, y2) {
return paper.path([ "M", x1, y1, "L", x2, y2 ]);
};
Beav.Raphael.lineRelative = function(paper, x1, y1, dx, dy) {
return Beav.Raphael.line(paper, x1, y1, x1+dx, y1+dy);
};
Beav.Raphael.loadTextExtensions = function(paper) {
paper.text_prebeav = paper.text;
var valign = function(dir) { // dir = 'center', or 'top', or 'bottom'
var b = this.getBBox();
var h = b.height;
var d = 0;
if (dir == 'center') {
d = 0;
} else if (dir == 'top') {
d = h/2;
} else if (dir == 'top') {
d = - h/2; // TODO: maybe remove one pixel in case h is odd number?
}
try {
// this.translate(0, d); // not supported by IE8
// this.attr({'y': b.y + d}); // does not seem to work
this.transform("t0," + d); // workaround?
} catch(e) {}
return this;
};
paper.text = function(x, y, text, fontSize) {
if(!window.enableRtl || !text || typeof text == "string" || !text.length) {
var txt = paper.text_prebeav(x, y, text);
txt.valign = valign;
return txt;
}
var set = paper.set();
if(!fontSize) { fontSize = 16; }
var lineHeight = fontSize * 1.2; // Raphael's line-height
var startY = y - ((text.length - 1) / 2) * lineHeight
for(var i = 0; i < text.length; i++) {
var txt = paper.text_prebeav(x, startY + i * lineHeight, text[i]);
txt.valign = valign;
set.push(txt);
}
return set;
}
var setproto = paper.set().__proto__;
try {
setproto.valign = function(dir) {
this.forEach(function(item) {
item.valign(dir);
});
return this;
};
} catch(err) {
}
};
/**********************************************************************************/
/* Random */
Beav.Random = new Object();
Beav.Random.bit = function(randomSeed, idBit) {
return (randomSeed & (1 << idBit)) ? 1 : 0;
};
/**********************************************************************************/
/* Task */
Beav.Task = new Object();
Beav.Task.scoreInterpolate = function(minScore, maxScore, minResult, maxResult, result) {
// requires minResult <= result <= maxResult and minScore <= maxScore
return Math.round(minScore + (maxScore - minScore) * (result - minResult) / (maxResult - minResult));
};
/**********************************************************************************/
/* Geometry */
Beav.Geometry = new Object();
Beav.Geometry.distance = function(x1,y1,x2,y2) {
return Math.sqrt(Math.pow(x2 - x1,2) + Math.pow(y2 - y1,2));
};
/*
This is used to handle drag on devices that have both a touch screen and a mouse.
Can be tested on chrome by loading a task in desktop mode, then switching to tablet mode.
To call instead of element.drag(onMove, onStart, onEnd);
*/
Beav.dragWithTouch = function(element, onMove, onStart, onEnd) {
var touchingX = 0;
var touchingY = 0;
var disabled = false;
function onTouchStart(evt) {
if (disabled) {
return;
}
var touches = evt.changedTouches;
touchingX = touches[0].pageX;
touchingY = touches[0].pageY;
onStart(touches[0].pageX, touches[0].pageY, evt);
}
function onTouchEnd(evt) {
if (disabled) {
return;
}
onEnd(null);
}
function onTouchMove(evt) {
if (disabled) {
return;
}
var touches = evt.changedTouches;
var dx = touches[0].pageX - touchingX;
var dy = touches[0].pageY - touchingY;
onMove(dx, dy, touches[0].pageX, touches[0].pageY, evt);
}
function callOnStart(x,y,event) {
disabled = true;
onStart(x,y,event);
}
function callOnMove(dx,dy,x,y,event) {
disabled = true;
onMove(dx,dy,x,y,event);
}
function callOnEnd(event) {
disabled = false;
onEnd(event);
}
// element.undrag();
element.drag(callOnMove,callOnStart,callOnEnd);
if (element.touchstart) {
element.touchstart(onTouchStart);
element.touchend(onTouchEnd);
element.touchcancel(onTouchEnd);
element.touchmove(onTouchMove);
}
}