Javascript Websocket Passing Code to Eval - javascript

I have a javascript object that I am passing through a websocket as raw text to a client. This raw text (for now) is directly passed into an eval statement when received. The issue is, for some reason, Javascript keeps manipulating the data before passing it to the event handler. I am at wits end.
The object that is being passed across the websocket is:
var obj = {
evaluate:function(str) {
digit = parseInt(str,10);
if(isNaN(digit)) {
log.write("Invalid input: "+str);
} else {
log.write(this.spigot(digit));
}
},
spigot:function(digit) {
len = Math.floor(10*digit/3)+1;
A = new Array(len);
for(var i=0;i<len;i++) A[i]=2;
var finalDigit = 0;
var nines = 0;
var predigit = 0;
for(i=1;i<digit+1;i++) {
q = 0;
for(j=len;j>0;j--) {
x = 10*A[j-1] + q*j;
x = Math.floor(x)
A[j-1] = x % ((2*j)-1);
A[j-1] = Math.floor(A[j-1]);
q = x / ((2*j) -1);
q = Math.floor(q);
}
A[0] = Math.floor(q%10);
q = Math.floor(q/10);
if(q==9) {
nines++;
} else if (q==10) {
finalDigit = predigit+1;
for(j=0;j<nines;j++) {
finalDigit = 0;
}
predigit=0;
nines=0;
} else {
finalDigit = predigit;
predigit=q;
for(j=0;j<nines;j++) {
finalDigit = 9;
}
nines=0;
}
}
return finalDigit;
}
}
The client receives the message whole (I checked using both Chrome's developer tools and Firebug). However when I get the message in the following event handler:
function socketMessage(e) {
log.write(e.data); //a log function I have written
}
e.data contains:
obj = {
evaluate:function(str) {
digit = parseInt(str,10);
if(isNaN(digit)) {
log.write('Invalid input: '+str);
} else {
log.write(this.spigot(digit));
}
},
spigot:function(digit) {
len = Math.floor(10*digit/3)+1;
A = new Array(len);
for(var i=0;i<len;i++) A[i]=2;
var finalDigit = 0;
var nines = 0;
var predigit = 0;
for(i=1;i<digit+1;i++) {
q = 0;
for(j=len;j>0;j--) {
x = 10*A[j-1] + q*j;
x = Math.floor(x)
A[j-1] = x %((MISSING)(2*j)-1);
A[j-1] = Math.floor(A[j-1]);
q = x / ((2*j) -1);
q = Math.floor(q);
}
A[0] = Math.floor(q%)(MISSING);
q = Math.floor(q/10);
if(q==9) {
nines++;
} else if (q==10) {
finalDigit = predigit+1;
for(j=0;j<nines;j++) {
finalDigit = 0;
}
predigit=0;
nines=0;
} else {
finalDigit = predigit;
predigit=q;
for(j=0;j<nines;j++) {
finalDigit = 9;
}
nines=0;
}
}
return finalDigit;
}
}
Note how the code has been mutated. There are random (MISSING) strings added throughout it and several of the equations have been truncated.
Why is this happening?
EDIT 1:
After playing around for a while, I have noticed it happens after the % symbol regardless of its placement... So my question is, why significance does the % operator have here that is causing the event listener to slaughter the content of my code?
EDIT 2:
It would appear % is being interpreted as an escape character before being passed to my callback function. I've tried using %25 before sending it across the socket but to no avail.

The % character is being interpreted as an escape character by Javascript. The (MISSING) text you see added is Javascript's way of telling you the escape character wasn't followed by a two digit escape code. The easiest way around this problem is to define a function mod(a,b) that accomplishes the same thing as modulus. I.E.:
....},
mod:function(a,b) {
return (a/b-Math.floor(a/b))*b;
}
Then when you need to use the modulus operator, simply call
Math.floor(this.mod(q,10));

Related

Javascript find the most repetitive character occurrence from the string

Let's say we have this string:
BBBBAAAABBAAAAAACCCCCBDDDDEEEEEEE,FFF
As you can see, here B is occurring 4 times at first but B is also present before DDDD.
Similarly, A is occurring 4 times at the beginning and later 6 times.
I want the expected output if I am searching B it should 4 times as the max occurrence B is 4. However if I am searching A then it should return 6 because the most occurrence for A is 6.
Here is my code I tried:
function checkRepeatativeString(str) {
let hashMap = {};
let seen = new Set();
let counter = 1;
let maxValue = 1;
let isPreviousValueSame = false;
let isNextValueSame = true;
for (let i = 0; i < str.length; i++) {
/**
* is previous value same
*/
if (str[i] == str[i-1]) {
isPreviousValueSame = true;
}
/**
* is next value same
*/
if (str[i] == str[i+1]) {
isNextValueSame = true;
}
if (seen.has(str[i]) && isPreviousValueSame) {
hashMap[str[i]][0]++;
hashMap[str[i]][1]++;
isPreviousValueSame = false;
} else if(seen.has(str[i]) && !isNextValueSame) {
maxValue = Math.max(hashMap[str[i]][1], maxValue);
counter = 0;
hashMap[str[i]] = [counter, maxValue];
} else {
maxValue = Math.max(maxValue, counter);
seen.add(str[i]);
hashMap[str[i]] = [counter, maxValue];
isPreviousValueSame = false;
}
}
return hashMap;
}
let str = "BBBBAAAABBAAAAAACCCCCBDDDDEEEEEEE,FFF";
console.log(checkRepeatativeString(str));
This code is working but if you look for B, I am getting stuck at the beginning of value.
My program returns out for B:
B: [ 1, 1 ]
^ ^
Inside array, 1 is a counter which scans the string and second 1 in array is a max value which should return the output. However my program is returning 1 for B. I am expecting 4 as max value.
Help would be appreciated~
Quick and dirty.
function maxConsecutiveCharacters(check, haystack) {
if(check.length !== 1) return false;
let result = 0;
let buffer = 0;
for(let i = 0; i < haystack.length; i++) {
if(haystack[i] === check) {
buffer++;
}
else {
if(buffer > result) {
result = buffer;
}
buffer = 0;
}
if(buffer > result) {
result = buffer;
}
}
return result;
}
That looks overly complicated. Consider approaching the problem from a different angle - first split up the string into segments of repeating characters, and group them into an object based on the length of the longest substring for a given character.
const checkRepeatativeString = (str) => {
const longestCounts = {};
for (const consecutive of (str.match(/(.)\1*/g) || [])) {
const char = consecutive[0];
longestCounts[char] = Math.max(
longestCounts[char] || 0, // Use the existing value in the object if it exists and is higher
consecutive.length // Otherwise, use the length of the string iterated over
);
}
return longestCounts;
};
let str = "BBBBAAAABBAAAAAACCCCCBDDDDEEEEEEE,FFF";
console.log(checkRepeatativeString(str));
Simpler code often means less surface area for bugs.

issue with `for` loop, causes game to crash when button to run loop is clicked

in trying to get a few numbers (var belief and trinkets) to go up per second (using for loop), i run into the error "expected a conditional expression but instead saw an assignment" when using the analyse function over the following piece of code:
function trinketCount(number) {
if(towers >= 1) {
var trinketCap = 500;
for(; trinkets = trinketCap;) {
trinkets = trinkets + (towers * 2);
}
document.getElementById('trinkets').innerHTML = trinkets;
}
}
and also in the following, very similar, loop:
function beliefCount(number) {
if(towers >= 1) {
var beliefCap = 600;
for(; belief = beliefCap;) {
belief = belief + towers;
document.getElementById('belief').innerHTML = belief;
}
}
}
clicking the button to build a 'tower' also causes the whole thing to crash.
i am fairly new to js so i apologise if the problem is obvious! also check it out for yourself at https://codepen.io/dirtbf/project/full/XjvdMX
"expected a conditional expression but instead saw an assignment"
This is exactly the problem.
for(; trinkets = trinketCap;) {
for(; belief = beliefCap;) {
You're assigning the values in here instead of checking whether they equal each other. Did that error come with a line number?
Fixed function versions:
function trinketCount(number) {
if(towers >= 1) {
var trinketCap = 500;
for(; trinkets == trinketCap;) {
trinkets = trinkets + (towers * 2);
}
document.getElementById('trinkets').innerHTML = trinkets;
}
}
function beliefCount(number) {
if(towers >= 1) {
var beliefCap == 600;
for(; belief = beliefCap;) {
belief = belief + towers;
document.getElementById('belief').innerHTML = belief;
}
}
}

I am making a quiz and I ran js code through shiftedit and got the following error: 'answerValue' used out of scope: lin 15

I am making a quiz and I ran the js code ...
if (isNaN(answerValue)) { answerValue = 0...
through shiftedit and got the following error:
'answerValue' used out of scope: line 15
function answerScore(qName) {
var radiosNo = document.getElementsByName(qName);
for (var i = 0, length = radiosNo.length; i < length; i++) {
if (radiosNo[i].checked) {
// do something with radiosNo
var answerValue = Number(radiosNo[i].value);
}
}
// change NaNs to zero
if (isNaN(answerValue)) {
answerValue = 0;
}
return answerValue;
}
The error clearly says error: 'answerValue' used out of scope: line 15.
You have declared answerValue in if condition and you are trying to access it outside if also. Declaring it in function scope will solve your problem
function answerScore(qName) {
var radiosNo = document.getElementsByName(qName);
var answerValue = null;
for (var i = 0, length = radiosNo.length; i < length; i++) {
if (radiosNo[i].checked) {
// do something with radiosNo
answerValue = Number(radiosNo[i].value);
}
}
// change NaNs to zero
if (isNaN(answerValue)) {
answerValue = 0;
}
return answerValue;
}
You can first define var answerValue = 0, than iterate over the elements using document.querySelectorAll() and instead of checking isNaN(answerValue) you most use do Number.isNaN()
Code:
function answerScore(qName) {
var answerValue = 0;
document
.querySelectorAll(qName)
.forEach(el => {
if (el.checked) {
answerValue = Number(el.value);
}
});
return !Number.isNaN(answerValue) ? answerValue : 0;
}

NodeJS require with asynch functions when synch is wanted

I have the following code
var utils = require(`${__dirname}/../../utils/utils.js`);
...
let object = utils.parse(input);
if (object === undefined){
let helper = utils.recognize(input);
msg.channel.sendMessage("\"" + input + "\" not recognized. Did you mean \"" + helper[0] + "\"?");
object = utils.parse(helper[0]);
}
//code related to object
console.log(object.strLength);
where "parse" tries to match the input to an object in a database, and "recognize" tries to find the best match if the input is spelled incorrectly (Levenshtein) (along with additional info such as how close the match was).
Currently the issue is that the code is ran asynchronously; "object.strLength" returns an undefined before utils.recognize() returns a value. If I copy/paste the recognize() and parse() functions into the file, then the code is run synchronously and I do not run into any issues. However I would rather keep those functions in a separate file as I reuse them in other files.
Is there a way to specify that the functions in utils must be synch? I know that there are libraries that convert asynch into synch but I prefer to use as few libraries as I can help it. I tried to have the recognize functions return a Promise but it ended up as a jumbled mess
edit: here's parse. I did not think it was necessary to answer this question so I did not include it initially:
var db = require(`${__dirname}/../data/database.js`);
...
var parse = (input) => {
let output = db[output];
if (output === null) {
Object.keys(db).forEach((item) => {
if (db[item].num === parseInt(input) || (db[item].color + db[item].type === input)){
output = db[item];
return false;
}
});
}
return output;
}
I solved the issue, thanks everyone. Here's what was wrong, it was with recognize(). It was my mistake to not show the code for it initially.
Original recognize:
var recognize = (item) => {
//iterate through our databases and get a best fit
let bestItem = null;
let bestScore = 99999; //arbitrary large number
//let bestType = null;
//found algorithm online by milot-mirdita
var levenshtein = function(a, b) {
if (a.length == 0) { return b.length; }
if (b.length == 0) { return a.length; }
// swap to save some memory O(min(a,b)) instead of O(a)
if(a.length > b.length) {
let tmp = a;
a = b;
b = tmp;
}
let row = [];
for(let i = 0; i <= a.length; i++) {
row[i] = i;
}
for (let i = 1; i <= b.length; i++) {
let prev = i;
for (let j = 1; j <= a.length; j++) {
let val;
if (b.charAt(i-1) == a.charAt(j-1)) {
val = row[j-1]; // match
} else {
val = Math.min(row[j-1] + 1, // substitution
prev + 1, // insertion
row[j] + 1); // deletion
}
row[j - 1] = prev;
prev = val;
}
row[a.length] = prev;
}
return row[a.length];
}
//putting this here would make the code work
//console.log("hi");
Object.keys(db).forEach((key) => {
if (levenshtein(item, key) < bestScore) {
bestItem = key;
bestScore = levenshtein(item, key);
}
});
return [bestItem, bestScore];
}
My solution was to move the levenshtein function outside of the recognize function, so if I wanted to I can call levenshtein from another function
#user949300 and #Robert Moskal, I changed the forEach loop into a let...in loop. There is no functional difference (as far as I can tell) but the code does look cleaner.
#Thomas, I fixed the let output = db[output]; issue, oops.
Again, thanks for all of your help, I appreciate it. And happy New Year too

Find variable value

I have some inputs in my app: <_input code/> + <_input code/> = <_input code/>.
Let's imagine first input name is a, appropriately second and third inputs' names are b and c. I filled my inputs:
7 + x = 12
Is there any way to calculate x value?
What do I want from my script:
It finds variable in inputs' values.
It checks all fields of my form filled properly.
It finds variable in inputs' values.
From given information script calculates value of variable.
How many inputs will be doesn't matter. I just want to find value of x. Is there any library to do this?
function calculcateA(b,c){
return c-b;
}
if(inputA === 'x'){
alert(calculateA(inputB,inputC));
}
And so on... there is nothing wrong with this functions, but I want to automate this proccess like WolframAplha.
The best thing for you, I guess would be to find some library for solving equations. If you are in need to solve bigger sets of equations then maybe something related to linear algebra.
Can't really tell you an exact solution so you will have to search for yourself.
Here is some code that should solve the problem.
function calculate() {
var varIndex = -1;
//Ensure that at least two three arguements are passed
if (arguments.length < 3) {
throw "You need at least three parameters to make an equation";
}
//Make sure that there is only one variable
for (var i = 0; i < arguments.length; i++) {
if (isNaN(arguments[i])) {
if (varIndex != -1) {
throw "You can't have two variables";
return;
}
varIndex = i;
}
}
//If variable has been found
if (varIndex != -1) {
var answer = 0;
//If variable is at the last position, add all constants
if (varIndex == types.length - 1) {
for (var j = 0; j < arguments.length - 1; j++) {
answer = answer + j;
}
} else {
//Otherwise Deduct all values from the last
answer = arguments[arguments.length - 1];
for (var k = 0; k < arguments.length - 1; k++) {
if (k == varIndex) { continue; }
answer = answer - j;
}
}
//Return Result
return { variable: arguments[varIndex], answer: answer };
}
else {
throw "You need at least one variable";
return;
}
}
You would use the above as follows:
var a = document.querySelector("input[name=a]");
var b = document.querySelector("input[name=b]");
var c = document.querySelector("input[name=c]");
var calcBtn = document.getElementById("calculate");
calcBtn.addEventListener("click", function () {
try {
var result = calculate(a.value, b.value, c.value);
console.log("The value of " + result.variable + " is " + result.answer);
} catch (e) {
console.log(e);
}
});

Categories