const fs = require('fs'); const commands = module.exports = {}; const msgRegex = /^!([a-zA-Z0-9]+) ([a-zA-Z0-9]+) ([a-zA-Z0-9]+) ?(.*)$/; // Compute the edit distance between the two given strings function getEditDistance(sourceString, targetString) { if (sourceString.length === 0) return targetString.length; if (targetString.length === 0) return sourceString.length; let matrix = []; // increment along the first column of each row for (let i = 0; i <= targetString.length; i++) { matrix[i] = [i]; } // increment each column in the first row for (let j = 0; j <= sourceString.length; j++) { matrix[0][j] = j; } // Fill in the rest of the matrix for (let i = 1; i <= targetString.length; i++) { for (let j = 1; j <= sourceString.length; j++) { let cost = 1; if (targetString.charAt(i-1) === sourceString.charAt(j-1)) { cost = 0; } matrix[i][j] = Math.min(matrix[i-1][j-1] + cost, // substitution matrix[i][j-1] + 1, // insertion matrix[i-1][j] + 1 // deletion ); } } return matrix[targetString.length][sourceString.length]; } function getSuggestions(input, list, threshhold){ let candidates = {}; let bestDistance = null; for(let key in list){ let distance = getEditDistance(input, key); console.log("new it. key: "+key+" dist:"+distance); if(distance >= threshhold) continue; if(bestDistance === distance){ //another candidate candidates[candidates.length] = key; console.log("other candidate"); } else if(bestDistance > distance || bestDistance === null){ //new best candidate candidates = [key]; bestDistance = distance; console.log("new best candidate"); } } return candidates; } function suggestFix(msg, projects){ const shortcuts = msg.match(msgRegex); const expansion = {}; if(shortcuts === null){ return null; } expansion.project = findShortcut(shortcuts[1], projects); if(expansion.project) { expansion.project = expansion.project.toLowerCase(); } else { return getSuggestions(shortcuts[1], projects); } expansion.service = findShortcut(shortcuts[2], projects[expansion.project]); if(expansion.service) { expansion.service = expansion.service.toLowerCase(); } else { return getSuggestions(shortcuts[2], projects[expansion.project]); } expansion.subcommand = findShortcut(shortcuts[3], projects[expansion.project][expansion.service]); if(expansion.subcommand) { return null; } else { return getSuggestions(shortcuts[3], projects[expansion.project][expansion.service]); } } commands.suggestFix = suggestFix; commands.getEditDistance = getEditDistance; const findShortcut = (shortcut, objects) => { const regex = new RegExp('^' + shortcut + '.*'); let expansionCount = 0; let expansion = false; for(let key in objects) { if(regex.test(key)) { expansionCount++; if(expansionCount > 1) { return false; }; expansion = key; }; }; return expansion; }; commands.expandCommand = (msg, projects) => { return new Promise((resolve, reject) => { const shortcuts = msg.match(msgRegex); const expansion = {}; if(shortcuts === null){ reject('No regex match.'); return; } expansion.project = findShortcut(shortcuts[1], projects); if(expansion.project) { expansion.project = expansion.project.toLowerCase(); } else { reject('could not resolve project: ' + shortcuts[1]); return; } expansion.service = findShortcut(shortcuts[2], projects[expansion.project]); if(expansion.service) { expansion.service = expansion.service.toLowerCase(); } else { reject('could not resolve service: ' + shortcuts[2]); return; } expansion.subcommand = findShortcut(shortcuts[3], projects[expansion.project][expansion.service]); if(expansion.subcommand) { expansion.subcommand = expansion.subcommand.toLowerCase(); } else { reject('could not resolve subcommand: ' + shortcuts[4]); return; } // if args are given, write them in command if(shortcuts[4]) expansion.args = shortcuts[4]; resolve(expansion); return; }); }; commands.projects = {}; fs.readdirSync('./projects').forEach((file) => { let project = file.match(/^([a-z]*)\.js$/); if(!project) { //skip current forEach pass return; } project = project[1]; commands.projects[project] = require('./projects/' + file); }); /* //Test code const commands = {}; commands['homeserver'] = {}; commands['homeserver']['register'] = {}; commands['homeserver']['register'].regex = /([a-zA-Z0-9])/; commands['homeserver']['register'].usage = ''; commands['homeserver']['register'].exec = (args) => { //args is a .match with .regex }; commands['imninja'] = {}; commands['imninja']['register'] = {}; commands['imninja']['register'].regex = /([a-zA-Z0-9])/; commands['imninja']['register'].usage = ''; commands['imninja']['register'].exec = (args) => { //args is a .match with .regex }; console.log(getSuggestions("inminja", commands)); // -> imninja console.log(getSuggestions("34C21", commands, 4)); // -> {}*/ //console.log(getEditDistance("saturday", "sunday")); //should be 3 /* expandCommand('!lubi infra reb saeifsaef', commands.projects) .then((success) => { console.log(success); }, (fail) => { console.log(fail); }); */