/**
* @file constantArrayParsing.js
* @module constantArrayParsing
* @description Contains all system defined business rules for parsing arrays specific to constants.
* @requires module:ruleParsing
* @requires module:configurator
* @requires module:loggers
* @requires {@link https://www.npmjs.com/package/@haystacks/constants|@haystacks/constants}
* @requires {@link https://mathjs.org/index.html|math}
* @requires {@link https://www.npmjs.com/package/chalk|chalk}
* @requires {@link https://www.npmjs.com/package/path|path}
* @author Seth Hollingsead
* @date 2022/04/26
* @copyright Copyright © 2022-… by Seth Hollingsead. All rights reserved
*/
// Internal imports
import ruleParsing from '../ruleParsing.js';
import configurator from '../../../executrix/configurator.js';
import loggers from '../../../executrix/loggers.js';
// External imports
import hayConst from '@haystacks/constants';
import * as math from 'mathjs';
import chalk from 'chalk';
import path from 'path';
const {bas, biz, cfg, msg, sys, wrd} = hayConst;
const baseFileName = path.basename(import.meta.url, path.extname(import.meta.url));
// businessRules.rules.arrayParsing.constantArrayParsing.
const namespacePrefix = sys.cbusinessRules + bas.cDot + wrd.crules + bas.cDot + wrd.carray + wrd.cParsing + bas.cDot + baseFileName + bas.cDot;
/**
* @function getLengthOfLongestStringInArray
* @description Determines what the longest string is in an array of strings.
* @param {array<string>} inputData The array for which we should find the longest length string in.
* @param {string} inputMetaData Not used for this business rule.
* @return {integer} The length of the longest string in the array.
* @author Seth Hollingsead
* @date 2022/01/19
* @NOTE https://stackoverflow.com/questions/6521245/finding-longest-string-in-array
*/
function getLengthOfLongestStringInArray(inputData, inputMetaData) {
let functionName = getLengthOfLongestStringInArray.name;
loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataIs + JSON.stringify(inputData));
loggers.consoleLog(namespacePrefix + functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = 0;
if (inputData) {
returnData = math.max(...(inputData.map(el => el.length)));
}
loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + returnData);
loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return returnData;
}
/**
* @function searchForPatternsInStringArray
* @description Walks through sub-strings of each string in the input array of strings searching or common patterns using a brute-force sequential array search.
* Maximum string length to search is the maximum string length - 1 (basically the longest string in the array minus 1 character).
* Minimum string length to search is 3 characters.
* @param {array<string>} inputData The array of strings that should be searched for matching patterns.
* @param {string} inputMetaData Not used for this business rule.
* @return {array<string>} A string array of common string values found in more than 1 element of the array and 3 or more characters long.
* @author Seth Hollingsead
* @date 2022/01/19
*/
function searchForPatternsInStringArray(inputData, inputMetaData) {
let functionName = searchForPatternsInStringArray.name;
loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataIs + JSON.stringify(inputData));
loggers.consoleLog(namespacePrefix + functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = false;
if (inputData && inputData.length > 0) {
returnData = []; // Reset it to an empty array, the input data has something n it so we should be able to process it.
let maxStringLength = getLengthOfLongestStringInArray(inputData, '') - 1;
// maxStringLength is:
loggers.consoleLog(namespacePrefix + functionName, msg.cmaxStringLengthIs + maxStringLength);
let minStringLength = 3;
// minStringLength is:
loggers.consoleLog(namespacePrefix + functionName, msg.cminStringLengthIs + minStringLength);
for (let a = 0; a < inputData.length; a++) { // Initial high-level loop over each of the array elements. (This is the source string for the comparison)
let currentMasterStringArrayElement = inputData[a];
// currentMasterStringArrayElement is:
loggers.consoleLog(namespacePrefix + functionName, msg.ccurrentMasterStringArrayElementIs + currentMasterStringArrayElement);
if (currentMasterStringArrayElement.includes(bas.cSpace) === false) {
// currentMasterStringArrayElement does not contain a space character
loggers.consoleLog(namespacePrefix + functionName, msg.cSearchForPatternsInStringArrayMessage1);
// NOTE: All of the other loggers.consoleLog below this are not actually getting called for some reason.
// That is why I have added the hard-coded console logs, but really they only need to be enabled if this function needs to be debugged.
// It's difficult to debug these because they really dump a LOT of data to the output.
// The only real way to debug larger data sets would be to force the output to a log file.
// A small data-set might be possible to debug.
// Loop over the length of the string we need to compare.
for (let b = minStringLength; b <= maxStringLength; b++) { // b will now hold the length of the string we are using to compare.
// loggers.consoleLog(namespacePrefix + functionName, 'length of string to compare is: ' + toString(b));
// console.log('Length of string to compare is: ' + b);
// First make sure that the length of our master string is less than or equal to the length of j, otherwise we will just skip to the next.
if (currentMasterStringArrayElement.length <= b) {
// loggers.consoleLog(namespacePrefix + functionName, 'currentMasterStringArrayElement.length is less than b');
// console.log('currentMasterStringArrayElement.length is less than b');
// Loop again for the length of the current string - 3 (minStringLength)
// Each loop will determine our currentComparisonString (which will be used when we actually iterate over the array in ur search)
for (let c = 0; c <= currentMasterStringArrayElement.length - minStringLength; c++) { // Loop through each set of strings in the master comparison string.
// loggers.consoleLog(namespacePrefix + functionName, 'c value is: ' + c);
// console.log('c value is: ' + c);
// Now here we should be able to finally compute the beginning and ending of the indexes for the string we want to use for comparison.
let beginningIndex = c;
// loggers.consoleLog(namespacePrefix + functionName, 'beginningIndex is: ' + beginningIndex);
// console.log('beginningIndex is: ' + beginningIndex);
let endingIndex = c + b;
// loggers.consoleLog(namespacePrefix + functionName, 'endingIndex is: ' + endingIndex);
// console.log('ending index is: ' + endingIndex);
let stringToCompare = currentMasterStringArrayElement.substring(beginningIndex, endingIndex);
// loggers.consoleLog(namespacePrefix + functionName, 'stringToCompare is: ' + stringToCompare);
// console.log('stringToCompare is: ' + stringToCompare);
// Now we need another loop to go over all of the array elements, make sure we always ignore the current array element.
for (let d = 0; d < inputData.length; d++) {
// loggers.consoleLog(namespacePrefix + functionName, 'd value is: ' + d);
// console.log('d value is: ' + d);
if (d != a) {
// loggers.consoleLog(namespacePrefix + functionName, 'd != a');
// console.log('d != a');
let otherStringToCompare = inputData[d];
// loggers.consoleLog(namespacePrefix + functionName, 'otherStringToCompare is: ' + otherStringToCompare);
// console.log('otherStringToCompare is: ' + otherStringToCompare);
if (otherStringToCompare.includes(stringToCompare)) {
// loggers.consoleLog(namespacePrefix + functionName, 'FOUND A MATCH!!!! ' + stringToCompare);
// console.log('FOUND A MATCH!!!! ' + stringToCompare);
// Here we have found a match among brothers. We need to see if this stringToCompare has already been added to the returnData array.
if (ruleParsing.processRulesInternal([[returnData, stringToCompare], ruleParsing.getRule(biz.cascertainMatchingElements)], [biz.cdoesArrayContainValue]) === false) {
returnData.push(stringToCompare);
} // End-if (ruleParsing.processRulesInternal([[returnData, stringToCompare], ruleParsing.getRule(biz.cascertainMatchingElements)], [biz.cdoesArrayContainValue]) === false)
} // End-if (otherStringToCompare.includes(stringToCompare))
} // End-if (d != a)
} // End-for (let d = 0; d < inputData.length; d++)
} // End-for (let c = 0; c <= currentMasterStringArrayElement.length - minStringLength; c++)
} // End-if (currentMasterStringArrayElement.length <= b)
} // End-for (let b = minStringLength; b <= maxStringLength; b++)
} else { // Else-clause if (currentMaserStringArrayElement.includes(bas.cSpace) === false)
// WARNING: Teh current string being searched contains a space character, we are going to skip comparison.
loggers.consoleLog(namespacePrefix + functionName, msg.cSearchForPatternsInSringArrayMessage2 + msg.cSearchForPatternsInStringArrayMessage3);
}
} // End-for (let a = 0; a < inputData.length; a++)
} else { // Else-clause if (inputData && inputData.length > 0)
// WARNING: InputData was not an array or had an empty array.
loggers.consoleLog(namespacePrefix + functionName, msg.cSearchForPatternsInSringArrayMessage4);
}
loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + JSON.stringify(returnData));
loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return returnData;
}
/**
* @function validatePatternsThatNeedImplementation
* @description Scans through an array of strings and determines which ones are not yet implemented in the constants system.
* @param {array<string>} inputData The array of strings that should be checked if they are already implemented in the constants system or not.
* @param {string} inputMetaData Not used for this business rule.
* @return {string} A coma separated list of constants that are not yet implemented.
* @author Seth Hollingsead
* @date 2022/01/20
*/
function validatePatternsThatNeedImplementation(inputData, inputMetaData) {
let functionName = validatePatternsThatNeedImplementation.name;
loggers.consoleLog(namespacePrefix + functionName, msg.cBEGIN_Function);
loggers.consoleLog(namespacePrefix + functionName, msg.cinputDataIs + JSON.stringify(inputData));
loggers.consoleLog(namespacePrefix + functionName, msg.cinputMetaDataIs + inputMetaData);
let returnData = '';
if (inputData) {
let passMessage = '';
let colorizeLogsEnabled = configurator.getConfigurationSetting(wrd.csystem, cfg.cenableColorizedConsoleLogs);
let j = 0; // We will use this as an iterator to count the number of times we add a string to the returnData coma-seperated list.
for (const element of inputData) {
let currentString = element;
if (ruleParsing.processRulesInternal([currentString, ''], [biz.cdoesConstantExist]) === false) {
// Constant does NOT exist:
passMessage = msg.cConstantDoesNotExist + currentString;
if (colorizeLogsEnabled === true) {
passMessage = chalk.rgb(0,0,0)(passMessage);
passMessage = chalk.bgRgb(0,255,0)(passMessage);
} // End-if (colorizeLogsEnabled === true)
console.log(passMessage);
// constant does NOT exist:
loggers.consoleLog(namespacePrefix + functionName, msg.cConstantDoesNotExist + currentString);
// Make sure we add all the strings that do not exist to a coma-separated list,
// so we can enqueue it to the constantsGeneratorList command and generate actual new constants lines of code.
if (j === 0) {
returnData = currentString;
} else {
returnData = returnData + bas.cComa + currentString;
}
j++;
} else { // Else-clause for if (ruleParsing.processRulesInternal([currentString, ''], [biz.cdoesConstantExist]) === false)
// Constant does exist:
passMessage = msg.cConstantDoesExist + currentString;
if (colorizeLogsEnabled === true) {
passMessage = chalk.rgb(0,0,0)(passMessage);
passMessage = chalk.bgRgb(255,0,0)(passMessage);
} // End-if colorizeLogsEnabled === true
console.log(passMessage);
// constant does exist:
loggers.consoleLog(namespacePrefix + functionName, msg.cConstantDoesExist + currentString);
}
} // End-for (const element of inputData)
} // End-if (inputData)
loggers.consoleLog(namespacePrefix + functionName, msg.creturnDataIs + returnData);
loggers.consoleLog(namespacePrefix + functionName, msg.cEND_Function);
return returnData;
}
export default {
getLengthOfLongestStringInArray,
searchForPatternsInStringArray,
validatePatternsThatNeedImplementation,
};