--- a
+++ b/backend/smartRuleSystem.js
@@ -0,0 +1,250 @@
+/*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);
+			}
+		}
+	})
+}