480 lines
24 KiB
JavaScript
480 lines
24 KiB
JavaScript
exports.newConfigReader = function newConfigReader() {
|
|
|
|
let thisObject = {
|
|
loadConfigs: loadConfigs,
|
|
initialize: initialize
|
|
}
|
|
|
|
let storage;
|
|
let storageData;
|
|
let ecosystemObject;
|
|
|
|
return thisObject;
|
|
|
|
function initialize(pEcosystemObject, pStorageData, pStorage, callBackFunction) {
|
|
storage = pStorage;
|
|
storageData = pStorageData;
|
|
ecosystemObject = pEcosystemObject;
|
|
|
|
try {
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> initialize -> Initializing storage."); }
|
|
storage.initialize(storageData, ecosystemObject);
|
|
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
|
} catch (err) {
|
|
console.log("[ERROR] ConfigReader -> initialize -> Error initilizing the storage. Stack:", err.stack);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
|
|
function loadConfigs(callBackFunction) {
|
|
|
|
readHostsConfigs();
|
|
|
|
function readHostsConfigs() {
|
|
|
|
try {
|
|
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> Entering function."); }
|
|
|
|
let requestsSent = 0;
|
|
let responsesReceived = 0;
|
|
|
|
for (let i = 0; i < ecosystemObject.hosts.length; i++) {
|
|
|
|
let host = ecosystemObject.hosts[i];
|
|
|
|
getCompetitions();
|
|
getPlotters();
|
|
|
|
function getCompetitions() {
|
|
|
|
try {
|
|
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> getCompetitions -> Entering function."); }
|
|
|
|
/* In this first section we will load the competitions configurations. */
|
|
|
|
for (let j = 0; j < host.competitions.length; j++) {
|
|
|
|
let competition = host.competitions[j];
|
|
|
|
requestsSent++;
|
|
|
|
storage.readData(host.codeName + "/" + "competitions", competition.repo, competition.configFile, true, onDataArrived);
|
|
|
|
function onDataArrived(err, pData) {
|
|
|
|
try {
|
|
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> getCompetitions -> Cloud -> onDataArrived -> Entering function."); }
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> getCompetitions -> Cloud -> onDataArrived -> host.codeName = " + host.codeName); }
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> getCompetitions -> Cloud -> onDataArrived -> competition.repo = " + competition.repo); }
|
|
if (LOG_FILE_CONTENT === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> getCompetitions -> Cloud -> onDataArrived -> pData = " + pData); }
|
|
|
|
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
|
|
|
console.log("[ERROR] ConfigReader -> readHostsConfigs -> getCompetitions -> Cloud -> onDataArrived -> Could not read a file. ");
|
|
console.log("[ERROR] ConfigReader -> readHostsConfigs -> getCompetitions -> Cloud -> onDataArrived -> err.message = " + err.message);
|
|
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
return;
|
|
}
|
|
|
|
responsesReceived++;
|
|
|
|
pData = pData.toString();
|
|
pData = pData.trim(); // remove first byte with some encoding.
|
|
|
|
let configObj = JSON.parse(pData);
|
|
|
|
/* Since we are going to replace the full bot object and we dont want to lose these two properties, we do this: */
|
|
|
|
configObj.repo = competition.repo;
|
|
configObj.configFile = competition.configFile;
|
|
|
|
host.competitions[j] = configObj;
|
|
|
|
if (requestsSent === responsesReceived) {
|
|
|
|
readDevTeamsConfigs();
|
|
|
|
}
|
|
|
|
}
|
|
catch (err) {
|
|
console.log("[ERROR] ConfigReader -> readHostsConfigs -> getCompetitions -> Cloud -> onDataArrived -> Error = " + err);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (err) {
|
|
console.log("[ERROR] ConfigReader -> readHostsConfigs -> getCompetitions -> getCompetitions -> Error = " + err);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
|
|
function getPlotters() {
|
|
|
|
try {
|
|
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> getPlotters -> getPlotters -> Entering function."); }
|
|
|
|
/* In this second section we will load the competition plotters configurations. */
|
|
|
|
for (let j = 0; j < host.plotters.length; j++) {
|
|
|
|
let plotter = host.plotters[j];
|
|
|
|
requestsSent++;
|
|
|
|
storage.readData(host.codeName + "/" + "plotters", plotter.repo, plotter.configFile, true, onDataArrived);
|
|
|
|
function onDataArrived(err, pData) {
|
|
|
|
try {
|
|
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> getPlotters -> Cloud -> onDataArrived -> Entering function."); }
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> getPlotters -> Cloud -> onDataArrived -> host.codeName = " + host.codeName); }
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> getPlotters -> Cloud -> onDataArrived -> plotter.repo = " + plotter.repo); }
|
|
if (LOG_FILE_CONTENT === true) { console.log("[INFO] ConfigReader -> readHostsConfigs -> getPlotters -> Cloud -> onDataArrived -> pData = " + pData); }
|
|
|
|
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
|
|
|
console.log("[ERROR] ConfigReader -> readHostsConfigs -> getPlotters -> Cloud -> onDataArrived -> Could not read a file. ");
|
|
console.log("[ERROR] ConfigReader -> readHostsConfigs -> getPlotters -> Cloud -> onDataArrived -> err.message = " + err.message);
|
|
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
return;
|
|
}
|
|
|
|
responsesReceived++;
|
|
|
|
pData = pData.toString();
|
|
pData = pData.trim(); // remove first byte with some encoding.
|
|
|
|
let configObj = JSON.parse(pData);
|
|
|
|
/* Since we are going to replace the full bot object and we dont want to lose these two properties, we do this: */
|
|
|
|
configObj.repo = plotter.repo;
|
|
configObj.configFile = plotter.configFile;
|
|
|
|
host.plotters[j] = configObj;
|
|
|
|
if (requestsSent === responsesReceived) {
|
|
|
|
readDevTeamsConfigs();
|
|
|
|
}
|
|
|
|
}
|
|
catch (err) {
|
|
console.log("[ERROR] ConfigReader -> readHostsConfigs -> getPlotters -> Cloud -> onDataArrived -> Error = " + err);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (err) {
|
|
console.log("[ERROR] ConfigReader -> readHostsConfigs -> getPlotters -> getCompetitions -> Error = " + err);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (err) {
|
|
console.log("[ERROR] ConfigReader -> readHostsConfigs -> Error = " + err);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
|
|
function readDevTeamsConfigs() {
|
|
|
|
try {
|
|
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> Entering function."); }
|
|
|
|
/*
|
|
|
|
Each bot has its configuration at its own repo since each team must be able to change it at will.
|
|
So what we do here is to use the master config at the AAPlatform repo that we already have on
|
|
memory and inject into it the config of each bot.
|
|
|
|
Inmediatelly after that, we also load the Plotters configs using the same technique.
|
|
|
|
*/
|
|
|
|
let requestsSent = 0;
|
|
let responsesReceived = 0;
|
|
|
|
for (let i = 0; i < ecosystemObject.devTeams.length; i++) {
|
|
|
|
let devTeam = ecosystemObject.devTeams[i];
|
|
|
|
getBots();
|
|
getPlotters();
|
|
|
|
function getBots() {
|
|
|
|
try {
|
|
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> getBots -> Entering function."); }
|
|
|
|
/* In the next section we are loading the bots configurations. */
|
|
|
|
for (let j = 0; j < devTeam.bots.length; j++) {
|
|
|
|
let bot = devTeam.bots[j];
|
|
|
|
requestsSent++;
|
|
|
|
storage.readData(devTeam.codeName + "/" + "bots", bot.repo, bot.configFile, true, onDataArrived);
|
|
|
|
function onDataArrived(err, pData) {
|
|
|
|
try {
|
|
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> getBots -> Cloud -> onDataArrived -> Entering function."); }
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> getBots -> Cloud -> onDataArrived -> devTeam.codeName = " + devTeam.codeName); }
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> getBots -> Cloud -> onDataArrived -> bot.repo = " + bot.repo); }
|
|
if (LOG_FILE_CONTENT === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> getBots -> Cloud -> onDataArrived -> pData = " + pData); }
|
|
|
|
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
|
|
|
console.log("[ERROR] ConfigReader -> readDevTeamsConfigs -> getBots -> Cloud -> onDataArrived -> Could not read a file. ");
|
|
console.log("[ERROR] ConfigReader -> readDevTeamsConfigs -> getBots -> Cloud -> onDataArrived -> err.message = " + err.message);
|
|
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
return;
|
|
}
|
|
|
|
responsesReceived++;
|
|
|
|
if (pData !== "{}") { // If for any reason we could not tet this config, then we just exclude this bot to improve resiliency.
|
|
|
|
pData = pData.toString();
|
|
pData = pData.trim(); // remove first byte with some encoding.
|
|
|
|
let configObj = JSON.parse(pData);
|
|
|
|
/* Since we are going to replace the full bot object and we dont want to lose these two properties, we do this: */
|
|
|
|
configObj.repo = bot.repo;
|
|
configObj.configFile = bot.configFile;
|
|
|
|
/* Here we will add all the possible Clones of this bot */
|
|
|
|
if (configObj.genes !== undefined) {
|
|
|
|
/* Here, based on the genes we will create one instance for each combination of genes */
|
|
|
|
let valueMatrix = [];
|
|
|
|
for (let i = 0; i < configObj.genes.length; i++) {
|
|
|
|
let gene = configObj.genes[i];
|
|
|
|
let possibleValues = [];
|
|
|
|
for (let j = gene.lowerLimit; j <= gene.upperLimit; j++) {
|
|
|
|
possibleValues.push(j);
|
|
|
|
}
|
|
|
|
valueMatrix.push(possibleValues);
|
|
|
|
}
|
|
|
|
/*
|
|
Now we have all the possible genes values in a multi-dimensional matrix.
|
|
We will go thorugh each of the elements of each dimension and get each combination possible with the other dimmensions.
|
|
*/
|
|
|
|
let combinations = [];
|
|
let combination = [];
|
|
let dimensionIndex = 0;
|
|
|
|
calculateCombinations(dimensionIndex, combination);
|
|
|
|
function calculateCombinations(pDimensionIndex, pCombination) {
|
|
|
|
let dimension = valueMatrix[pDimensionIndex];
|
|
|
|
for (let j = 0; j < dimension.length; j++) {
|
|
|
|
let copy = JSON.parse(JSON.stringify(pCombination));
|
|
|
|
let value = dimension[j];
|
|
copy.push(value);
|
|
|
|
if (pDimensionIndex < valueMatrix.length - 1) {
|
|
|
|
calculateCombinations(pDimensionIndex + 1, copy);
|
|
|
|
} else {
|
|
|
|
combinations.push(copy);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/* We delete the bot definition since it is going to be replaced by one definition for each of its clones. */
|
|
|
|
devTeam.bots.splice(j);
|
|
|
|
/* At this point we have an array with all the possible combinations, we just need to create an instance for each one and set the genes according to that. */
|
|
|
|
for (let i = 0; i < combinations.length; i++) {
|
|
|
|
let botConfig = JSON.parse(JSON.stringify(configObj));
|
|
let combination = combinations[i];
|
|
let genes = {};
|
|
let clonKey = "";
|
|
|
|
for (let j = 0; j < botConfig.genes.length; j++) {
|
|
|
|
genes[botConfig.genes[j].name] = combination[j];
|
|
clonKey = clonKey + "." + combination[j];
|
|
|
|
}
|
|
|
|
let clonName = "Clon" + clonKey;
|
|
let clonConfig = JSON.parse(JSON.stringify(botConfig));
|
|
|
|
/* Lets adapt the bot config so as to tune it for the new clon. */
|
|
|
|
clonConfig.displayName = clonConfig.displayName + " " + clonName;
|
|
clonConfig.codeName = clonConfig.codeName + "-" + clonName;
|
|
|
|
/*
|
|
for (let j = 0; j < clonConfig.products.length; j++) {
|
|
|
|
let product = clonConfig.products[j];
|
|
|
|
for (let k = 0; k < product.dataSets.length; k++) {
|
|
|
|
let dataSet = product.dataSets[k];
|
|
|
|
dataSet.filePath = dataSet.filePath.replace("@Clon", "-" + clonName);
|
|
}
|
|
}
|
|
*/
|
|
|
|
devTeam.bots.push(clonConfig);
|
|
|
|
}
|
|
} else {
|
|
|
|
/* If the bot does not have any genes at all we do what we did before clones existed */
|
|
|
|
devTeam.bots[j] = configObj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (requestsSent === responsesReceived) {
|
|
|
|
callBackFunction(global.DEFAULT_OK_RESPONSE, ecosystemObject);
|
|
|
|
}
|
|
|
|
}
|
|
catch (err) {
|
|
console.log("[ERROR] ConfigReader -> readDevTeamsConfigs -> getBots -> Cloud -> onDataArrived -> Error = " + err);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (err) {
|
|
console.log("[ERROR] ConfigReader -> readDevTeamsConfigs -> getBots -> Error = " + err);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
|
|
function getPlotters() {
|
|
|
|
try {
|
|
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> getPlotters -> Entering Function."); }
|
|
|
|
/* In the next section we are loading the plotters configurations. */
|
|
|
|
for (let j = 0; j < devTeam.plotters.length; j++) {
|
|
|
|
let plotter = devTeam.plotters[j];
|
|
|
|
requestsSent++;
|
|
|
|
storage.readData(devTeam.codeName + "/" + "plotters", plotter.repo, plotter.configFile, true, onDataArrived);
|
|
|
|
function onDataArrived(err, pData) {
|
|
|
|
try {
|
|
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> getPlotters -> Cloud -> onDataArrived -> Entering function."); }
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> getPlotters -> Cloud -> onDataArrived -> devTeam.codeName = " + devTeam.codeName); }
|
|
if (CONSOLE_LOG === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> getPlotters -> Cloud -> onDataArrived -> plotter.repo = " + plotter.repo); }
|
|
if (LOG_FILE_CONTENT === true) { console.log("[INFO] ConfigReader -> readDevTeamsConfigs -> getPlotters -> Cloud -> onDataArrived -> pData = " + pData); }
|
|
|
|
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
|
|
|
console.log("[ERROR] ConfigReader -> readDevTeamsConfigs -> getPlotters -> Cloud -> onDataArrived -> Could not read a file. ");
|
|
console.log("[ERROR] ConfigReader -> readDevTeamsConfigs -> getPlotters -> Cloud -> onDataArrived -> err.message = " + err.message);
|
|
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
return;
|
|
}
|
|
|
|
responsesReceived++;
|
|
|
|
if (pData !== "{}") { // If for any reason we could not tet this config, then we just exclude this bot to improve resiliency.
|
|
|
|
pData = pData.toString();
|
|
pData = pData.trim(); // remove first byte with some encoding.
|
|
|
|
let configObj = JSON.parse(pData);
|
|
|
|
/* Since we are going to replace the full plotter object and we dont want to lose these two properties, we do this: */
|
|
|
|
configObj.repo = plotter.repo;
|
|
configObj.configFile = plotter.configFile;
|
|
|
|
devTeam.plotters[j] = configObj;
|
|
|
|
}
|
|
|
|
if (requestsSent === responsesReceived) {
|
|
|
|
callBackFunction(global.DEFAULT_OK_RESPONSE, ecosystemObject);
|
|
|
|
}
|
|
}
|
|
catch (err) {
|
|
console.log("[ERROR] ConfigReader -> readDevTeamsConfigs -> getPlotters -> Cloud -> onDataArrived -> Error = " + err);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
catch (err) {
|
|
console.log("[ERROR] ConfigReader -> readDevTeamsConfigs -> getPlotters -> Error = " + err);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
catch (err) {
|
|
console.log("[ERROR] ConfigReader -> readDevTeamsConfigs -> Error = " + err);
|
|
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
|
}
|
|
}
|
|
}
|
|
}
|