Transparent getJSON request does not work properly - ajax

I have stuck to make it work: after I put 2 getJSON strings ($.getJSON... ...return false) inside base64 function getjson request runs successfully but the rest of encode function does not return anything then (it must return base64 encoded text). How to fix it? Thanks.
Update: without 'return false;' getjson does not send anything, so that I think there would be a solution replacing 'return false;' to return something else, is not it?
Code:
var Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=|",
// public method for encoding
encode : function (input) {
$.getJSON('http://debug.loc/savedata.php', $("#somedata").serialize(), function(data){});
return false;
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
},

This is expected - actually, it returns value false, not "nothing".
The line return false; below the call to getJSON() effectively returns (exits) from the function. Returning from a function means that the rest of the code does not get executed.
I understand that you want the function to continue executing, encode given value and return it. For this to happen, simply remove the line return false;.

Related

Console.Log and Discord Message displaying different results

I have a relatively basic set of code here that is programmed to roll 3 dice and give me the results whenever I type "/roll" in discord.
However, the results displayed on my command terminal are always different from those in the discord message from the bot.
async execute(interaction)
{
var num = 3;
num = Number(num);
function rollingDice(num) {
// make the dice rolling "num" times.
// return the results.
var diceResults = "";
for (var i = 0; i < num; i++) {
var resultOfEachDice = "";
resultOfEachDice = Math.floor((Math.random() * 6) + 1);
diceResults += resultOfEachDice + ", ";
}
var lastComma = diceResults.lastIndexOf(", ");
diceResults = diceResults.slice(0, lastComma);
return diceResults;
}
var diceResults = rollingDice()
console.log("Rolled " + num + " dice: " + rollingDice(num));
console.log(process.argv);
await interaction.reply('You rolled: ' + rollingDice(num));
So I will type /roll and my terminal will say I rolled "3, 5, 2" while the message would have something entirely different like "1, 6, 4".
This happens every time I run the command and I am not sure what the issue is.

Fastest way to search for a row in a large Google Sheet using/in Google Apps Script

GAS is quite powerful and you could write a full fledged web-app using a Google Sheet as the DB back-end. There are many reasons not to do this but I figure in some cases it is okay.
I think the biggest issue will be performance issues when looking for rows based on some criteria in a sheet with a lot of rows. I know there are many ways to "query" a sheet but I can't find reliable information on which is the fastest.
One of the complexities is that many people can edit a sheet which means there are a variable number of situations you'd have to account for. For the sake of simplicity, I want to assume the sheet:
Is locked down so only one person can see it
The first column has the row number (=row())
The most basic query is finding a row where a specific column equals some value.
Which method would be the fastest?
I have a sheet with ~19k rows and ~38 columns, filled with all sorts of unsorted real-world data. That is almost 700k rows so I figured it would be a good sheet to time a few methods and see which is the fastest.
method 1: get sheet as a 2D array then go through each row
method 2: get sheet as a 2D array, sort it, then using a binary search algorithm to find the row
method 3: make a UrlFetch call to Google visualization query and don't provide last row
method 4: make a UrlFetch call to Google visualization query and provide last row
Here are the my query functions.
function method1(spreadsheetID, sheetName, columnIndex, query)
{
// get the sheet values excluding header,
var rowValues = SpreadsheetApp.openById(spreadsheetID).getSheetByName(sheetName).getSheetValues(2, 1, -1, -1);
// loop through each row
for(var i = 0, numRows = rowValues.length; i < numRows; ++i)
{
// return it if found
if(rowValues[i][columnIndex] == query) return rowValues[i]
}
return false;
}
function method2(spreadsheetID, sheetName, columnIndex, query)
{
// get the sheet values excluding header
var rowValues = SpreadsheetApp.openById(spreadsheetID).getSheetByName(sheetName).getSheetValues(2, 1, -1, -1);
// sort it
rowValues.sort(function(a, b){
if(a[columnIndex] < b[columnIndex]) return -1;
if(a[columnIndex] > b[columnIndex]) return 1;
return 0;
});
// search using binary search
var foundRow = matrixBinarySearch(rowValues, columnIndex, query, 0, rowValues.length - 1);
// return if found
if(foundRow != -1)
{
return rowValues[foundRow];
}
return false;
}
function method3(spreadsheetID, sheetName, queryColumnLetterStart, queryColumnLetterEnd, queryColumnLetterSearch, query)
{
// SQL like query
myQuery = "SELECT * WHERE " + queryColumnLetterSearch + " = '" + query + "'";
// the query URL
// don't provide last row in range selection
var qvizURL = 'https://docs.google.com/spreadsheets/d/' + spreadsheetID + '/gviz/tq?tqx=out:json&headers=1&sheet=' + sheetName + '&range=' + queryColumnLetterStart + ":" + queryColumnLetterEnd + '&tq=' + encodeURIComponent(myQuery);
// fetch the data
var ret = UrlFetchApp.fetch(qvizURL, {headers: {Authorization: 'Bearer ' + ScriptApp.getOAuthToken()}}).getContentText();
// remove some crap from the return string
return JSON.parse(ret.replace("/*O_o*/", "").replace("google.visualization.Query.setResponse(", "").slice(0, -2));
}
function method4(spreadsheetID, sheetName, queryColumnLetterStart, queryColumnLetterEnd, queryColumnLetterSearch, query)
{
// find the last row in the sheet
var lastRow = SpreadsheetApp.openById(spreadsheetID).getSheetByName(sheetName).getLastRow();
// SQL like query
myQuery = "SELECT * WHERE " + queryColumnLetterSearch + " = '" + query + "'";
// the query URL
var qvizURL = 'https://docs.google.com/spreadsheets/d/' + spreadsheetID + '/gviz/tq?tqx=out:json&headers=1&sheet=' + sheetName + '&range=' + queryColumnLetterStart + "1:" + queryColumnLetterEnd + lastRow + '&tq=' + encodeURIComponent(myQuery);
// fetch the data
var ret = UrlFetchApp.fetch(qvizURL, {headers: {Authorization: 'Bearer ' + ScriptApp.getOAuthToken()}}).getContentText();
// remove some crap from the return string
return JSON.parse(ret.replace("/*O_o*/", "").replace("google.visualization.Query.setResponse(", "").slice(0, -2));
}
My binary search algorithm:
function matrixBinarySearch(matrix, columnIndex, query, firstIndex, lastIndex)
{
// find the value using binary search
// https://www.w3resource.com/javascript-exercises/javascript-array-exercise-18.php
// first make sure the query string is valid
// if it is less than the smallest value
// or larger than the largest value
// it is not valid
if(query < matrix[firstIndex][columnIndex] || query > matrix[lastIndex][columnIndex]) return -1;
// if its the first row
if(query == matrix[firstIndex][columnIndex]) return firstIndex;
// if its the last row
if(query == matrix[lastIndex][columnIndex]) return lastIndex;
// now start doing binary search
var middleIndex = Math.floor((lastIndex + firstIndex)/2);
while(matrix[middleIndex][columnIndex] != query && firstIndex < lastIndex)
{
if(query < matrix[middleIndex][columnIndex])
{
lastIndex = middleIndex - 1;
}
else if(query > matrix[middleIndex][columnIndex])
{
firstIndex = middleIndex + 1;
}
middleIndex = Math.floor((lastIndex + firstIndex)/2);
}
return matrix[middleIndex][columnIndex] == query ? middleIndex : -1;
}
This is the function I used to test them all:
// each time this function is called it will try one method
// the first time it is called it will try method1
// then method2, then method3, then method4
// after it does method4 it will start back at method1
// we will use script properties to save which method is next
// we also want to use the same query string for each batch so we'll save that in script properties too
function testIt()
{
// get the sheet where we're staving run times
var runTimesSheet = SpreadsheetApp.openById("...").getSheetByName("times");
// we want to see true speed tests and don't want server side caching so we a copy of our data sheet
// make a copy of our data sheet and get its ID
var tempSheetID = SpreadsheetApp.openById("...").copy("temp sheet").getId();
// get script properties
var scriptProperties = PropertiesService.getScriptProperties();
// the counter
var searchCounter = Number(scriptProperties.getProperty("searchCounter"));
// index of search list we want to query for
var searchListIndex = Number(scriptProperties.getProperty("searchListIndex"));
// if we're at 0 then we need to get the index of the query string
if(searchCounter == 0)
{
searchListIndex = Math.floor(Math.random() * searchList.length);
scriptProperties.setProperty("searchListIndex", searchListIndex);
}
// query string
var query = searchList[searchListIndex];
// save relevant data
var timerRow = ["method" + (searchCounter + 1), searchListIndex, query, 0, "", "", "", ""];
// run the appropriate method
switch(searchCounter)
{
case 0:
// start time
var start = (new Date()).getTime();
// run the query
var ret = method1(tempSheetID, "Extract", 1, query);
// end time
timerRow[3] = ((new Date()).getTime() - start) / 1000;
// if we found the row save its values in the timer output so we can confirm it was found
if(ret)
{
timerRow[4] = ret[0];
timerRow[5] = ret[1];
timerRow[6] = ret[2];
timerRow[7] = ret[3];
}
break;
case 1:
var start = (new Date()).getTime();
var ret = method2(tempSheetID, "Extract", 1, query);
timerRow[3] = ((new Date()).getTime() - start) / 1000;
if(ret)
{
timerRow[4] = ret[0];
timerRow[5] = ret[1];
timerRow[6] = ret[2];
timerRow[7] = ret[3];
}
break;
case 2:
var start = (new Date()).getTime();
var ret = method3(tempSheetID, "Extract", "A", "AL", "B", query);
timerRow[3] = ((new Date()).getTime() - start) / 1000;
if(ret.table.rows.length)
{
timerRow[4] = ret.table.rows[0].c[0].v;
timerRow[5] = ret.table.rows[0].c[1].v;
timerRow[6] = ret.table.rows[0].c[2].v;
timerRow[7] = ret.table.rows[0].c[3].v;
}
break;
case 3:
var start = (new Date()).getTime();
var ret = method3(tempSheetID, "Extract", "A", "AL", "B", query);
timerRow[3] = ((new Date()).getTime() - start) / 1000;
if(ret.table.rows.length)
{
timerRow[4] = ret.table.rows[0].c[0].v;
timerRow[5] = ret.table.rows[0].c[1].v;
timerRow[6] = ret.table.rows[0].c[2].v;
timerRow[7] = ret.table.rows[0].c[3].v;
}
break;
}
// delete the temp file
DriveApp.getFileById(tempSheetID).setTrashed(true);
// save run times
runTimesSheet.appendRow(timerRow);
// start back at 0 if we're the end
if(++searchCounter == 4) searchCounter = 0;
// save the search counter
scriptProperties.setProperty("searchCounter", searchCounter);
}
I have a global variable searchList that is an array of various query strings -- some are in the sheet, some are not.
I ran testit on a trigger to run every minute. After 152 iterations I had 38 batches. Looking at the result, this is what I see for each method:
| Method | Minimum Seconds | Maximum Seconds | Average Seconds |
|---------|-----------------|-----------------|-----------------|
| method1 | 8.24 | 36.94 | 11.86 |
| method2 | 9.93 | 23.38 | 14.09 |
| method3 | 1.92 | 5.48 | 3.06 |
| method4 | 2.20 | 11.14 | 3.36 |
So it appears that, at least for my data-set, is using Google visualization query is the fastest.

VBScript division decimal by integer returns extra remainder

I'm trying to validate my VBScript function that divides an input value by 1440. When I pass 43.56 as input parameter, it returns me the following result:
0.030250000000000002
while the correct answer is
0.03025
What should I do to make it work correctly both with evenly divided integers, like 1440 / 1440 = 1, and when one value is a decimal.
Currently my function looks like so:
Function convertMinutesToDays(value)
If IsNumeric(value) And TypeName(value) <> "Boolean" Then
convertMinutesToDays = value / 1440
Else
convertMinutesToDays = 0
End If
End Function
Actually, if you simply put Response.Write convertMinutesToDays(43.56), it will show 0.03025, but we are using it within an assert javascript method, like so:
Call AssertAreEqual(convertMinutesToDays(43.56), 0.03025, "convertMinutesToDays: pass 43.56 should return 0.03025")
The javascript code:
<script language="JavaScript" runat="server">
function AssertAreEqual(val1, val2, message)
{
var retVal = false;
var divAttributes = "";
var equality = "";
if (val1 === val2)
{
divAttributes = "class=\"unittest assertareequal pass\"";
equality = "=";
retVal = true;
}
else
{
divAttributes = "class=\"unittest assertareequal fail\"";
equality = "!=";
retVal = false;
}
Response.Write("<div " + divAttributes + ">Actual:" + val1 + " " + equality + " " + val2 + ":Expected | " + message + "</div>");
return retVal;
}
</script>
The output:
Actual:0.030250000000000002 != 0.03025:Expected | convertMinutesToDays: pass 43.56 should return 0.03025
Any ideas?
This is due to the way floating point math works in VBScript(well most any language really). For your code, the Round function should suffice because you are always dividing by a single number so rounding errors won't add up on you the way they can in other types of functions. I chose 5 decimal places because it fixes your example. If you find others that still are off then you may need to up that but for representing partial days 5 is probably enough.
Function convertMinutesToDays(value)
If IsNumeric(value) And TypeName(value) <> "Boolean" Then
convertMinutesToDays = Round(value / 1440, 5)
Else
convertMinutesToDays = 0
End If
End Function

How to change the custom option price using jQuery?

I have created the three text type custom options and one dropdown type custom option. If i changed the select box value
"height * width" after this calculation, I want to set the calculated result in one input box
this all done in jQuery but now i want to set that value as custom option price
Magento.
Can you please help??
jQuery("#paper_size").on( "change", '#drop', function(){
var reg = jQuery('#paper_size').find("#drop").val();
var str = jQuery('#options_3_text').val();
var str1 = jQuery('#options_2_text').val();
var total = (str * str1 * 11) + 7;
var totalmts = (str * str1 * 3.53) + 7;
if (reg == '2') {
jQuery('#options_4_text').val(total);
}
else{
jQuery('#options_4_text').val(totalmts);
});
}
});
I guess this will work cause there was a Bracket mismatch in your code I found out after I copied the code to VS Code
jQuery("#paper_size").on("change", '#drop', function () {
var reg = jQuery('#paper_size').find("#drop").val();
var str = jQuery('#options_3_text').val();
var str1 = jQuery('#options_2_text').val();
var total = (str * str1 * 11) + 7;
var totalmts = (str * str1 * 3.53) + 7;
if (reg == '2') {
jQuery('#options_4_text').val(total);
}
else {
jQuery('#options_4_text').val(totalmts);
}});

jQuery Can't work with data from $.ajax correctly

I get data from a $.ajax call but cant work correctly with the data of it. Here is my code.
function OnSuccessResultSet(data, status) {
var output;
for (var i in data.recordset) {
output += "<li><a href='#'>";
for (var j = 0; j < metaName.length; j++) {
var testVar = metaName[j];
output += " <h2>" + data.recordset[i].testVar+ "</h2>";
alert(data.recordset[i].testVar);
alert(testVar);
alert(data.recordset[i].LABEL);
};
output += "</a></li>";
}
$(output).appendTo("#content1");
$('#content1').listview('refresh');
}
The first alert gives me an undefined back. Second alert gives me LABEL back and third one gives me the value of LABEL. My metaName has all attribute values for my element from recordset. I fill also my metaName array with a $.ajax call.
I dont find my mistake. :/
I think you need to use bracket notation instead of dot notation as the member operator here as the key you are looking for is stored in the variable testVar
alert(data.recordset[i][testVar]);
Ex
function OnSuccessResultSet(data, status) {
var output, testVar;
for (var i in data.recordset) {
output += "<li><a href='#'>";
for (var j = 0; j < metaName.length; j++) {
testVar = metaName[j];
output += " <h2>" + data.recordset[i][testVar]+ "</h2>";
};
output += "</a></li>";
}
$(output).appendTo("#content1");
$('#content1').listview('refresh');
}

Resources