/*made by Miguel Rodrigues @ KBZ miguel.rodrigues@knowledgebiz.pt*/
//smartRuleSystem is to automatically and intelligently create new rules
var mysql = require('../controllers/mysql');
var email = require('../controllers/emailer');
var logger = require('../config/logger.js');
var predict = require('predict');
//Handle the rules system and creates Automatically New Rules
module.exports.smartRulesHandler = function(){
var handler = "backend.controllers.mysql.getRulesList";
logger.info("Starting: ",handler);
//Get All Rules on Specific Rule
mysql.getRulesList(function(isOK, rules){
if(isOK){
logger.info("GetRulesList Success");
rules.forEach(function(eachRule, ruleIndex){
var handler = "backend.controllers.mysql.retrieveStatisticsList";
logger.info("Starting: ",handler);
//Get Statistics on Specific Rule
mysql.retrieveStatisticsList(eachRule.rulesID, function(isOK, rows, total){
if(isOK){
if(total.totalNotifications > 0){
switch (eachRule.conditionValue){
case ">":
case ">=":
if(eachRule.description.search("System Create Automatically New rule") > -1){
if(total.averageValue < parseFloat(eachRule.threshold / 100)*parseFloat(eachRule.controlValue)){
updateRule(eachRule, 0);
}else if(total.averageValue < parseFloat(eachRule.controlValue)){
checkLastFalseNotifications(eachRule, function(isOK, newValue){
if(isOK) {
updateRule(eachRule, newValue);
}
})
}else{
deleteRule(eachRule.rulesID);
}
}else{
checkIfExists(eachRule, function(OK, callback){
if(!OK) {
if(total.averageValue < parseFloat(eachRule.threshold / 100)*parseFloat(eachRule.controlValue)){
createNewRule(eachRule, 0);
}else if(total.averageValue < parseFloat(eachRule.controlValue)){
checkLastFalseNotifications(eachRule, function(isOK, newValue){
if(isOK) {
createNewRule(eachRule, newValue);
}
})
}
}
})
}
break;
case "<":
case "<=":
if(eachRule.description.search("System Create Automatically New rule") > -1){
if(total.averageValue > parseFloat(eachRule.threshold / 100)*parseFloat(eachRule.controlValue)){
updateRule(eachRule, 0);
}else if(total.averageValue > parseFloat(eachRule.controlValue)){
checkLastFalseNotifications(eachRule, function(isOK, newValue){
if(isOK) {
updateRule(eachRule, newValue);
}
})
}else{
deleteRule(eachRule.rulesID);
}
}else{
checkIfExists(eachRule, function(OK, callback){
if(!OK) {
if(total.averageValue > parseFloat(eachRule.threshold / 100)*parseFloat(eachRule.controlValue)){
createNewRule(eachRule, 0);
}else if(total.averageValue > parseFloat(eachRule.controlValue)){
checkLastFalseNotifications(eachRule, function(isOK, newValue){
if(isOK) {
createNewRule(eachRule, newValue);
}
})
}
}
})
}
break;
default:
}
}
}
else{
logger.error("retrieveStatisticsList Failed: ", rows);
}
})
})
}else{
logger.error("GetRulesList Failed: ", rules);
}
})
}
//Function for Update Data on Specific Rule
/*
input: rule (Specific Rule), newConditionValue
*/
function updateRule (rule, newConditionValue){
var handler = "backend.controllers.mysql.updateRule";
if(newConditionValue == 0){
var data = {
description: "System Create Automatically New rule: " + rule.description,
parameter: rule.parameter,
conditionValue: rule.conditionValue,
controlValue: parseFloat(rule.threshold / 100)*parseFloat(rule.controlValue),
threshold: rule.threshold,
notificationType: rule.notificationType,
token: rule.token
};
}else if(newConditionValue > 0){
var data = {
description: "System Create Automatically New rule: " + rule.description,
parameter: rule.parameter,
conditionValue: rule.conditionValue,
controlValue: newConditionValue,
threshold: rule.threshold,
notificationType: rule.notificationType,
token: rule.token
};
}
mysql.updateRule(data, function(isOK, callback){
if(!isOK) {
logger.error(handler,"Fail");
}else{
logger.info(handler,"Success");
}
});
}
//Function for Delete Specific Rule
/*
input: rulesID (Specific Rule)
*/
function deleteRule (rulesID){
var handler = "backend.controllers.mysql.deleteRule";
mysql.deleteRule(rulesID, function(isOK, callback){
if(!isOK) {
logger.error(handler,"Fail");
}else{
logger.info(handler,"Success");
}
})
}
//Function for Create New Rule (Automatically New Rule by System)
/*
input: rule (Specific Rule), newConditionValue
*/
function createNewRule (rule, newConditionValue){
if(newConditionValue == 0){
var data = {
description: "System Create Automatically New rule: " + rule.description,
parameter: rule.parameter,
conditionValue: rule.conditionValue,
controlValue: parseFloat(rule.threshold / 100)*parseFloat(rule.controlValue),
threshold: rule.threshold,
notificationType: rule.notificationType,
token: rule.token
};
}else if(newConditionValue > 0){
var data = {
description: "System Create Automatically New rule: " + rule.description,
parameter: rule.parameter,
conditionValue: rule.conditionValue,
controlValue: newConditionValue,
threshold: rule.threshold,
notificationType: rule.notificationType,
token: rule.token
};
}
var handler = "backend.controllers.mysql.insertNotificationRules";
logger.info("Starting: ",handler);
mysql.insertNotificationRules(data, function(isOK, callback){
if(!isOK) {
logger.error("Create Automatically New Rule: Fail");
}
else{
logger.info("Create Automatically New Rule: Sucess");
var handler = "backend.controllers.mysql.getEmailTovAppByToken";
logger.info("Starting: ",handler);
mysql.getEmailTovAppByToken(rule.token, function(isOK, emailTo){
if(!isOK) {
logger.error("Error Get Email by Token");
}
else{
logger.info("Success Get Email by Token");
email.sendEmailNewRule(emailTo[0].developerID, "System Create Automatically New rule: " + rule.description);
}
})
}
})
}
//Function for Check if that Specific Automatically Rule Created by System Exists
/*
input: rule (Specific Rule)
output: true/false
*/
function checkIfExists (rule, cb){
mysql.checkIfRuleAutomaticExists(rule, function(isOK, callback){
if(!isOK) {
logger.info("There is no Rule Created Automatically");
cb(false);
}
else{
logger.info("Rule already Created");
cb(true);
}
})
}
//Function for get Last 5 False Notifications
/*
input: rule (Specific Rule)
output: true/false
*/
function checkLastFalseNotifications (rule, cb){
var prediction = predict.movingAverage(5);
var aux = 0;
mysql.retrieveStatisticsList(rule.rulesID, function(isOK, rows){
if(!isOK) {
cb(false);
}
else{
if(rows.length > 0){
rows.slice(-5).forEach(function(eachRow, index){
if(eachRow.result == "false"){
prediction.pushValues([parseFloat(eachRow.subjectValue)]);
aux++;
}
})
if(aux == 5){
cb(true, prediction.predictNextValue().toFixed(2));
}else{
cb(false);
}
}else{
cb(false);
}
}
})
}