Difference between revisions of "User:Abel/WbProcessor.js"
Jump to navigation
Jump to search
m (Abel moved page MediaWiki:Gadget-Wbprocessor.js to MediaWiki:Gadget-WbProcessor.js) |
m |
||
(43 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
// License: GPL | // License: GPL | ||
− | // Wikibase | + | // Wikibase Processor |
− | console.log(' | + | console.log('wbprocessor loading'); |
+ | |||
+ | function WikibaseProcessorContainer(universe, location) { | ||
+ | |||
+ | Debug_switch = false; | ||
+ | |||
+ | this.main = interjson(checkdive(universe, location)); | ||
+ | var the = this.main; | ||
+ | |||
+ | /* The following is the main exposed function of the current Wb Processing class | ||
+ | usage cases | ||
+ | |||
+ | to check the last value in a location given by a preceding array of internal paths to find, with the possibility of array layers between elements of array of paths: | ||
+ | wbproc.checkentity( [ wbEStruct['instanceOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], 96 ] ); | ||
+ | |||
+ | to return for example content of default value given by array of location paths, or check for existence of | ||
+ | wbproc.checkentity( { default_value: [ wbEStruct['defaultValRelation'], wbEStruct['IDPropLoc'] ] } ) | ||
+ | |||
+ | |||
+ | */ | ||
+ | |||
+ | this.checkentity = function(paths) { | ||
+ | if ((the !== undefined) && (paths !== undefined)) { | ||
+ | return proceed(the, paths); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Exposed general wrapper for proceed for object other than what the class is originally instanced on, currently unused | ||
+ | // Could be used to create a further function to cross check current object with another object 'universe' with another for example | ||
+ | |||
+ | this.xcontains = function(unv, angle) { | ||
+ | if ((unv !== undefined) && (angle !== undefined)) { | ||
+ | return proceed(unv, angle); | ||
+ | }; | ||
+ | } | ||
+ | |||
+ | /* Exposed helper function to get Entity object of alien entity, if ever needed */ | ||
+ | |||
+ | this.EnqueueWB = async function(idk) { | ||
+ | var k = await wbqueue(idk); | ||
+ | return k; | ||
+ | } | ||
+ | |||
+ | /* Private part of wb Entity getter */ | ||
+ | |||
+ | async function wbqueue(id) { | ||
+ | return new Promise( | ||
+ | function(resolve, reject) { | ||
+ | $.getJSON('/w/api.php?action=wbgetentities&format=json&ids=' + id, function(json) { | ||
+ | var h = json.entities; | ||
+ | resolve(h); | ||
+ | }) | ||
+ | }).then(function(result) { | ||
+ | debuglog(result); | ||
+ | return result; | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | |||
+ | // the list of private helper functions, could not be accessed from outside | ||
+ | // helper function for descend into an object if key exists, otherwise stay at current level of object | ||
+ | function indexinterpolate(obj, i) { | ||
+ | return (obj[i] !== undefined) ? obj[i] : obj | ||
+ | }; | ||
+ | |||
+ | // helper function for checking a part of an array exists, if it doesn't, go undefined | ||
+ | function indexcheck(obj, i) { | ||
+ | if (obj !== undefined) { | ||
+ | return (obj[i] !== undefined) ? obj[i] : undefined | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | // dive selects matrix.a.b.c.d from the array called matrix and 'a.b.c.d' as string | ||
+ | // if a.b.c.d does not exists, it returns the substructure until the substructure exists, if d does not exist, it returns matrix.a.b.c e.g. | ||
+ | function dive(array, read) { | ||
+ | if (array !== undefined) { | ||
+ | return (read + '').split('.').reduce(indexinterpolate, array); | ||
+ | } | ||
+ | } | ||
+ | // Check returns matrix.a.b.c.d from 'array' ~ 'matrix' and 'read' ~ 'a.b.c.d' only if it exists all the way, otherwise go undefined | ||
+ | function check(array, read) { | ||
+ | if (array !== undefined) { | ||
+ | return (read + '').split('.').reduce(indexcheck, array); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Main object / array processing instrument | ||
+ | // Array can be a composition of objects and arrays | ||
+ | // Read is the instructions, could be an array, or a single path, but for now it should be an object based on our inner convention, example: | ||
+ | /* | ||
+ | relational_id_list = { | ||
+ | controller_id: [ wbEStructure['instanceOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 96 ], | ||
+ | personal_data_id: [ wbEStructure['subclassOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 421 ], | ||
+ | interface_button_id: [ wbEStructure ['instanceOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 487 ] | ||
+ | } | ||
+ | */ | ||
+ | |||
+ | function proceed(array, read) { | ||
+ | var ret_obj = {}, | ||
+ | temp_obj = array, | ||
+ | |||
+ | // If we encounter something seriously wrong we will just raise a red flag by setting this false, will check before returning this. | ||
+ | success_o_meter = true, | ||
+ | |||
+ | // If all goes well, for each path checked, we will have a member in this | ||
+ | future_instructional_return = []; | ||
+ | |||
+ | //|||||||||||||||||||||||||||||||||||||||||||||||||||||[ I N S T R U C T I O N S C O N T R O L ]|||||||||||||||||||||||||||||||||||||||||||||||||||||| | ||
+ | |||
+ | // Init program, check if instructions are an object (not an array but has multiple keys) : | ||
+ | // This is the main path of the function. Could be improved to have it for simple array of instructions | ||
+ | if ((!Array.isArray(read)) && (Object.keys(read).length > 0)) { | ||
+ | |||
+ | Object.keys(read).forEach(function(path) { | ||
+ | debuglog("instructions are an object, in path " + path); | ||
+ | |||
+ | //||||||||||||||||||||||||||[ Check if elements of instruction object are arrays themselves ]|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | ||
+ | |||
+ | if (Array.isArray(read[path])) { | ||
+ | |||
+ | // for each path, future_instructional_return will be filled with the future_return_partition after proceeding through that path | ||
+ | var future_return_partition = temp_obj; | ||
+ | |||
+ | Object.keys(read[path]).forEach(function(path2) { | ||
+ | |||
+ | debuglog("instructions are an array of arrays, going through " + read[path][path2]); | ||
+ | // for each step, see if it led anywhere other than where we were. | ||
+ | if (data_function(future_return_partition, read[path][path2]) != future_return_partition) { | ||
+ | // if it did, proceed; | ||
+ | future_return_partition = data_function(future_return_partition, read[path][path2]); | ||
+ | } else { | ||
+ | // if it didn, raise flag | ||
+ | success_o_meter = false; | ||
+ | } | ||
+ | |||
+ | //|||||||||||||||||||||||||||||||||||||||||||||||||||[ I N S T R U C T I O N S C O N T R O L ||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | ||
+ | |||
+ | }); | ||
+ | //Now that we went through the path, lets see if everything was ok. | ||
+ | if (success_o_meter === true) { | ||
+ | // If yes, put the result of the travel 'future_return_partition' into 'future_instructional_return' | ||
+ | |||
+ | debuglog("arrived at") | ||
+ | debuglog(future_return_partition); | ||
+ | future_instructional_return[path] = future_return_partition; | ||
+ | } else { | ||
+ | |||
+ | // Otherwise let's put an undefined in there | ||
+ | debuglog("seeking derailed"); | ||
+ | success_o_meter = true; | ||
+ | future_instructional_return[path] = undefined; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | //|||||||||||||||||| If instruction object element is not an array, lets just try to do that one step |||||||||||||||||||||||||||||||||||||||||||||||||||||||| | ||
+ | // Unused | ||
+ | else { | ||
+ | |||
+ | // INCLUDE step block with read[path] | ||
+ | if (data_function(temp_obj, read[path]) !== temp_obj) { | ||
+ | future_instructional_return[path] = data_function(temp_obj, read[path]); | ||
+ | } else { | ||
+ | // future_instructional_return.push( undefined ); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | }); | ||
+ | |||
+ | // Now that we have gone through all paths, make future return object into what we got | ||
+ | temp_obj = future_instructional_return; | ||
+ | } | ||
+ | |||
+ | //||||||||||||[ If we are not in instruction object, let's see if we have an instruction array ]|||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | ||
+ | //Unused, this part could be improved | ||
+ | else if (Array.isArray(read)) { | ||
+ | // If so let's follow the array of instructions | ||
+ | Object.keys(read).forEach(function(ect) { | ||
+ | if (data_function(temp_obj, read[ect]) !== temp_obj) { | ||
+ | |||
+ | temp_obj = data_function(temp_obj, read[ect]); | ||
+ | |||
+ | } else { | ||
+ | |||
+ | success_o_meter = false; | ||
+ | |||
+ | } | ||
+ | }); | ||
+ | } | ||
+ | |||
+ | //||||||||||||[ If we have a single instruction, let's try following that ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | ||
+ | //Unused, this part could be improved | ||
+ | else { | ||
+ | |||
+ | if (data_function(temp_obj, read) !== temp_obj) { | ||
+ | |||
+ | temp_obj = data_function(temp_obj, read); | ||
+ | |||
+ | } else { | ||
+ | |||
+ | success_o_meter = false; | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | // If we haven't got a not found signal along the way, let's try returning the object | ||
+ | |||
+ | if (success_o_meter === true) { | ||
+ | return temp_obj; | ||
+ | } else { | ||
+ | return undefined; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //|||||||||||||||||||||||||||||||||||||||||||||||||||||[ S T E P B L O C K ]|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | ||
+ | |||
+ | // Function that takes 1 step. Proceed (along a path) uses this for each step. | ||
+ | |||
+ | function data_function(temp_obj, moving) { | ||
+ | |||
+ | // we will return an array | ||
+ | var future_temp_obj = []; | ||
+ | |||
+ | // Check if we are on an array level, | ||
+ | if (Array.isArray(temp_obj)) { | ||
+ | debuglog("data is on an array level"); | ||
+ | Object.keys(temp_obj).forEach(function(ect) { | ||
+ | |||
+ | // if so, try proceeding in all directions. | ||
+ | debuglog("Within partition: " + ect); | ||
+ | if (checkdive(temp_obj[ect], moving) !== undefined) { | ||
+ | future_temp_obj.push(checkdive(temp_obj[ect], moving)); | ||
+ | } | ||
+ | // Put an element into the return array for each direction we could move into | ||
+ | |||
+ | }); | ||
+ | |||
+ | temp_obj = future_temp_obj; | ||
+ | |||
+ | } else { | ||
+ | |||
+ | // if we are not on an array level, proceed with the path | ||
+ | |||
+ | debuglog("data is on an objective level"); | ||
+ | |||
+ | if (checkdive(temp_obj, moving) !== temp_obj) { | ||
+ | future_temp_obj = checkdive(temp_obj, moving); | ||
+ | } | ||
+ | |||
+ | if (future_temp_obj !== undefined) { | ||
+ | temp_obj = future_temp_obj; | ||
+ | } else { | ||
+ | debuglog('nothing to see here') | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // NOTE this function works now but shows syntactic variance between the else branches | ||
+ | // Rigorous testing recommended | ||
+ | |||
+ | return temp_obj; | ||
+ | } | ||
+ | |||
+ | //|||||||||||||||||||||||||||||||||||||||||||||||||||||[ E N D O F S T E P B L O C K ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| | ||
+ | |||
+ | // This function substitutes a bunch of try catches and also tries to dive into 'array' in different ways | ||
+ | |||
+ | function checkdive(array, read) { | ||
+ | |||
+ | // simple case, array is an object containing property 'read' | ||
+ | |||
+ | if (check(array, read) !== undefined) { | ||
+ | return dive(array, read); | ||
+ | } | ||
+ | |||
+ | // array case, 'array' is an actual array, lets return an array of successful trials to dive into each direction | ||
+ | |||
+ | if (Array.isArray(array)) { | ||
+ | var potential_return = []; | ||
+ | Object.keys(array).forEach(function(item) { | ||
+ | if (check(array[item], read) !== undefined) { | ||
+ | potential_return.push(dive(array[item], read)); | ||
+ | } | ||
+ | }); | ||
+ | return potential_return; | ||
+ | } | ||
+ | |||
+ | // mystical case, 'what you have been seeking you had it all along... or at least you have it now' | ||
+ | // This is for when you already at a value level, and are looking for that value. | ||
+ | // Or when on an object level, and looking for that object | ||
+ | // or when on an array level, and looking for that array :O | ||
+ | |||
+ | if (array === read) { | ||
+ | return read; | ||
+ | } | ||
+ | |||
+ | /* If we did this, it would probably open up a wormhole or a segfault, or that strange error message browsers give when they are maxed out | ||
+ | |||
+ | if (Object.keys( array ).length > 0 ){ | ||
+ | Object.keys( array ).forEach( function ( piece ) { | ||
+ | if ( array[ piece ] === read ) { return read }; | ||
+ | }); | ||
+ | } | ||
+ | */ | ||
+ | } | ||
+ | |||
+ | // Try parsing json. If not a json, go void. | ||
+ | this.rxjson = function(rx) { | ||
+ | return interjson(rx); | ||
+ | } | ||
+ | |||
+ | function interjson(obj) { | ||
+ | try { | ||
+ | return JSON.parse(obj) | ||
+ | } catch (e) { | ||
+ | // if not JSON, do silly things | ||
+ | debuglog('not a json ¯\_(ツ)_/¯'); | ||
+ | }; | ||
+ | } | ||
+ | |||
+ | // Heavyweight solution to suppress error messages. | ||
+ | |||
+ | function debuglog(l0g) { | ||
+ | if (Debug_switch) { | ||
+ | console.log(l0g); | ||
+ | } | ||
+ | } | ||
+ | } |
Latest revision as of 12:07, 4 June 2019
// License: GPL
// Wikibase Processor
console.log('wbprocessor loading');
function WikibaseProcessorContainer(universe, location) {
Debug_switch = false;
this.main = interjson(checkdive(universe, location));
var the = this.main;
/* The following is the main exposed function of the current Wb Processing class
usage cases
to check the last value in a location given by a preceding array of internal paths to find, with the possibility of array layers between elements of array of paths:
wbproc.checkentity( [ wbEStruct['instanceOfRelations'], wbEStruct['IDPropLoc'], wbEStruct['IDName'], 96 ] );
to return for example content of default value given by array of location paths, or check for existence of
wbproc.checkentity( { default_value: [ wbEStruct['defaultValRelation'], wbEStruct['IDPropLoc'] ] } )
*/
this.checkentity = function(paths) {
if ((the !== undefined) && (paths !== undefined)) {
return proceed(the, paths);
}
}
// Exposed general wrapper for proceed for object other than what the class is originally instanced on, currently unused
// Could be used to create a further function to cross check current object with another object 'universe' with another for example
this.xcontains = function(unv, angle) {
if ((unv !== undefined) && (angle !== undefined)) {
return proceed(unv, angle);
};
}
/* Exposed helper function to get Entity object of alien entity, if ever needed */
this.EnqueueWB = async function(idk) {
var k = await wbqueue(idk);
return k;
}
/* Private part of wb Entity getter */
async function wbqueue(id) {
return new Promise(
function(resolve, reject) {
$.getJSON('/w/api.php?action=wbgetentities&format=json&ids=' + id, function(json) {
var h = json.entities;
resolve(h);
})
}).then(function(result) {
debuglog(result);
return result;
});
}
// the list of private helper functions, could not be accessed from outside
// helper function for descend into an object if key exists, otherwise stay at current level of object
function indexinterpolate(obj, i) {
return (obj[i] !== undefined) ? obj[i] : obj
};
// helper function for checking a part of an array exists, if it doesn't, go undefined
function indexcheck(obj, i) {
if (obj !== undefined) {
return (obj[i] !== undefined) ? obj[i] : undefined
}
};
// dive selects matrix.a.b.c.d from the array called matrix and 'a.b.c.d' as string
// if a.b.c.d does not exists, it returns the substructure until the substructure exists, if d does not exist, it returns matrix.a.b.c e.g.
function dive(array, read) {
if (array !== undefined) {
return (read + '').split('.').reduce(indexinterpolate, array);
}
}
// Check returns matrix.a.b.c.d from 'array' ~ 'matrix' and 'read' ~ 'a.b.c.d' only if it exists all the way, otherwise go undefined
function check(array, read) {
if (array !== undefined) {
return (read + '').split('.').reduce(indexcheck, array);
}
}
// Main object / array processing instrument
// Array can be a composition of objects and arrays
// Read is the instructions, could be an array, or a single path, but for now it should be an object based on our inner convention, example:
/*
relational_id_list = {
controller_id: [ wbEStructure['instanceOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 96 ],
personal_data_id: [ wbEStructure['subclassOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 421 ],
interface_button_id: [ wbEStructure ['instanceOfRelations'], wbEStructure['IDPropLoc'], wbEStructure['IDName'], 487 ]
}
*/
function proceed(array, read) {
var ret_obj = {},
temp_obj = array,
// If we encounter something seriously wrong we will just raise a red flag by setting this false, will check before returning this.
success_o_meter = true,
// If all goes well, for each path checked, we will have a member in this
future_instructional_return = [];
//|||||||||||||||||||||||||||||||||||||||||||||||||||||[ I N S T R U C T I O N S C O N T R O L ]||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Init program, check if instructions are an object (not an array but has multiple keys) :
// This is the main path of the function. Could be improved to have it for simple array of instructions
if ((!Array.isArray(read)) && (Object.keys(read).length > 0)) {
Object.keys(read).forEach(function(path) {
debuglog("instructions are an object, in path " + path);
//||||||||||||||||||||||||||[ Check if elements of instruction object are arrays themselves ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (Array.isArray(read[path])) {
// for each path, future_instructional_return will be filled with the future_return_partition after proceeding through that path
var future_return_partition = temp_obj;
Object.keys(read[path]).forEach(function(path2) {
debuglog("instructions are an array of arrays, going through " + read[path][path2]);
// for each step, see if it led anywhere other than where we were.
if (data_function(future_return_partition, read[path][path2]) != future_return_partition) {
// if it did, proceed;
future_return_partition = data_function(future_return_partition, read[path][path2]);
} else {
// if it didn, raise flag
success_o_meter = false;
}
//|||||||||||||||||||||||||||||||||||||||||||||||||||[ I N S T R U C T I O N S C O N T R O L |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
});
//Now that we went through the path, lets see if everything was ok.
if (success_o_meter === true) {
// If yes, put the result of the travel 'future_return_partition' into 'future_instructional_return'
debuglog("arrived at")
debuglog(future_return_partition);
future_instructional_return[path] = future_return_partition;
} else {
// Otherwise let's put an undefined in there
debuglog("seeking derailed");
success_o_meter = true;
future_instructional_return[path] = undefined;
}
}
//|||||||||||||||||| If instruction object element is not an array, lets just try to do that one step ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Unused
else {
// INCLUDE step block with read[path]
if (data_function(temp_obj, read[path]) !== temp_obj) {
future_instructional_return[path] = data_function(temp_obj, read[path]);
} else {
// future_instructional_return.push( undefined );
}
}
});
// Now that we have gone through all paths, make future return object into what we got
temp_obj = future_instructional_return;
}
//||||||||||||[ If we are not in instruction object, let's see if we have an instruction array ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//Unused, this part could be improved
else if (Array.isArray(read)) {
// If so let's follow the array of instructions
Object.keys(read).forEach(function(ect) {
if (data_function(temp_obj, read[ect]) !== temp_obj) {
temp_obj = data_function(temp_obj, read[ect]);
} else {
success_o_meter = false;
}
});
}
//||||||||||||[ If we have a single instruction, let's try following that |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//Unused, this part could be improved
else {
if (data_function(temp_obj, read) !== temp_obj) {
temp_obj = data_function(temp_obj, read);
} else {
success_o_meter = false;
}
}
// If we haven't got a not found signal along the way, let's try returning the object
if (success_o_meter === true) {
return temp_obj;
} else {
return undefined;
}
}
//|||||||||||||||||||||||||||||||||||||||||||||||||||||[ S T E P B L O C K ]||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Function that takes 1 step. Proceed (along a path) uses this for each step.
function data_function(temp_obj, moving) {
// we will return an array
var future_temp_obj = [];
// Check if we are on an array level,
if (Array.isArray(temp_obj)) {
debuglog("data is on an array level");
Object.keys(temp_obj).forEach(function(ect) {
// if so, try proceeding in all directions.
debuglog("Within partition: " + ect);
if (checkdive(temp_obj[ect], moving) !== undefined) {
future_temp_obj.push(checkdive(temp_obj[ect], moving));
}
// Put an element into the return array for each direction we could move into
});
temp_obj = future_temp_obj;
} else {
// if we are not on an array level, proceed with the path
debuglog("data is on an objective level");
if (checkdive(temp_obj, moving) !== temp_obj) {
future_temp_obj = checkdive(temp_obj, moving);
}
if (future_temp_obj !== undefined) {
temp_obj = future_temp_obj;
} else {
debuglog('nothing to see here')
}
}
// NOTE this function works now but shows syntactic variance between the else branches
// Rigorous testing recommended
return temp_obj;
}
//|||||||||||||||||||||||||||||||||||||||||||||||||||||[ E N D O F S T E P B L O C K ]|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// This function substitutes a bunch of try catches and also tries to dive into 'array' in different ways
function checkdive(array, read) {
// simple case, array is an object containing property 'read'
if (check(array, read) !== undefined) {
return dive(array, read);
}
// array case, 'array' is an actual array, lets return an array of successful trials to dive into each direction
if (Array.isArray(array)) {
var potential_return = [];
Object.keys(array).forEach(function(item) {
if (check(array[item], read) !== undefined) {
potential_return.push(dive(array[item], read));
}
});
return potential_return;
}
// mystical case, 'what you have been seeking you had it all along... or at least you have it now'
// This is for when you already at a value level, and are looking for that value.
// Or when on an object level, and looking for that object
// or when on an array level, and looking for that array :O
if (array === read) {
return read;
}
/* If we did this, it would probably open up a wormhole or a segfault, or that strange error message browsers give when they are maxed out
if (Object.keys( array ).length > 0 ){
Object.keys( array ).forEach( function ( piece ) {
if ( array[ piece ] === read ) { return read };
});
}
*/
}
// Try parsing json. If not a json, go void.
this.rxjson = function(rx) {
return interjson(rx);
}
function interjson(obj) {
try {
return JSON.parse(obj)
} catch (e) {
// if not JSON, do silly things
debuglog('not a json ¯\_(ツ)_/¯');
};
}
// Heavyweight solution to suppress error messages.
function debuglog(l0g) {
if (Debug_switch) {
console.log(l0g);
}
}
}