I need some help on an assignment that I need to do. Basically the question is a number guessing game. We're assigned a number in the interval [0,1023] based on our student number and we have 11 guesses to get the right number. I know I have to use a binary search to get the number, my only problem is connecting to the server and getting a result.
We're given this:
A sample request looks as follows:
http://142.132.145.50/A3Server/NumberGuess?snum=1234567&callback=processResult&guess=800
And also given that the request returns the following parameters:
1: A code to determine if your guess is equal, less than or greater than the number
2: Message string
3: Number of guesses made by my application
This is what I've tried so far, just as a test to get the server request working. All I get in return is "object HTMLHeadingElement"
window.onload = function() {
newGuess();
}
function newGuess() {
var url = "http://142.132.145.50/A3Server/NumberGuess?snum=3057267&callback=processResult&guess=600";
var newScriptElement = document.createElement("script");
newScriptElement.setAttribute("src", url);
newScriptElement.setAttribute("id", "jsonp");
var oldScriptElement = document.getElementById("jsonp");
var head=document.getElementsByTagName("head")[0];
if (oldScriptElement == null) {
head.appendChild(newScriptElement);
} else {
head.replaceChild(newScriptElement, oldScriptElement);
}
}
function processResult(code,message,guesses) {
var code = document.getElementById("code");
var message = document.getElementById("message");
var guesses = document.getElementById("guesses");
code.innerHTML = code;
message.innerHTML = message;
guesses.innerHTML = guesses;
}
EDIT: Current state of my code.
window.onload = function() {
min = 0;
max = 1023;
mid = 0;
setInterval(newGuess,1000);
};
function newGuess() {
mid = Math.floor((max-min)/2);
var url = "http://142.132.145.50/A3Server/NumberGuess?snum=3057267&callback=processResult&guess="+mid;
var newScriptElement = document.createElement("script");
newScriptElement.setAttribute("src", url);
newScriptElement.setAttribute("id", "jsonp");
var oldScriptElement = document.getElementById("jsonp");
var head=document.getElementsByTagName("head")[0];
if (oldScriptElement == null) {
head.appendChild(newScriptElement);
} else {
head.replaceChild(newScriptElement, oldScriptElement);
}
}
function processResult(codeJ,messageJ,guessesJ) {
code = document.getElementById("code");
message = document.getElementById("message");
guesses = document.getElementById("guesses");
code.innerHTML = codeJ;
message.innerHTML = messageJ;
guesses.innerHTML = guessesJ;
if(codeJ == 0){
return;
}else if(codeJ == -1){
min = mid + 1;
}else if(codeJ == 1){
max = mid -1;
}
console.log(mid);
}
Check your variable-names. You are overwriting the function-patameters.
Something like
code.innerHTML = code;
message.innerHTML = message;
guesses.innerHTML = guesses;
just CAN'T work, you should see the problem yourself...
Related
I'm supposed to create a functions to test a URL for validity then functions to look for and return parts of the URL string based on location of certain characters (position would be unknown). FYI, I'm very new to programming but have been searching and trying many answers. My latest attempt uses below format (found in an answer) but still can not get anything but an empty string to display when I call the function.
When I run this in Chrome, and enter "http://www.niagaracollege.ca" or "http://lego.ca" even though I am entering a valid URL, I get a return of false.
function validURL(userInput)
{
input = new String(userInput);
if (input.indexOf("://") != -1 && input.lastIndexOf(".") != -1)
return true;
else
return false;
}
function findProtocol(userInput)
{
input = new String(userInput);
var result = input.substring(0, input.indexOf("://"));
return result;
}
function findServer(userInput)
{
input = new String(userInput);
var result = input.substring(input.indexOf("://") + 1 ,input.lastIndexOf("."));
return result;
}
function findDomain(userInput)
{
input = new String(userInput);
var result = input.substring(input.lastIndexOf(".") + 1);
return result;
}
function btnReadURL_onclick()
{
var userInput = document.getElementById("txtURL").value;
var outputBox = document.getElementById("txtOutput");
var URL = validURL(userInput);
if (URL = true)
{
var Part1 = findProtocol(userInput);
var Part2 = findServer(userInput);
var Part3 = findDomain(userInput);
outputBox.value = "Protocol: " + Part1 + "\nServer: " + Part2 +
"\nDomain: " + Part3;
}
else (URL == true)
outputBox.value = "Invalid URL";
}
Use a debugger to find out what you are getting in the userInput. The code is fine. It should work. See sample code below.
test = function() {
var test = "http://Test 2"
alert(test.substring(0, test.indexOf("://")))
}
You need to pass the value to the findProtocol method rather than DOM element
Replace
var userInput = document.getElementById("txtURL");
by
var userInput = document.getElementById("txtURL").value;
and replace
if (URL = true)
with
if( URL == true )
I'm getting HTML from a forum url, and parsing the post count of the user from their profile page. I don't know how to write the parsed number into the Google spreadsheet.
It should go account by account in column B till last row and update the column A with count.
The script doesn't give me any errors, but it doesn't set the retrieved value into the spreadsheet.
function msg(message){
Browser.msgBox(message);
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu("Update")
.addItem('Update Table', 'updatePosts')
.addToUi();
}
function getPostCount(profileUrl){
var html = UrlFetchApp.fetch(profileUrl).getContentText();
var sliced = html.slice(0,html.search('Posts Per Day'));
sliced = sliced.slice(sliced.search('<dt>Total Posts</dt>'),sliced.length);
postCount = sliced.slice(sliced.search("<dd> ")+"<dd> ".length,sliced.search("</dd>"));
return postCount;
}
function updatePosts(){
if(arguments[0]===false){
showAlert = false;
} else {
showAlert=true;
}
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var accountSheet = spreadSheet.getSheetByName("account-stats");
var statsLastCol = statsSheet.getLastColumn();
var accountCount = accountSheet.getLastRow();
var newValue = 0;
var oldValue = 0;
var totalNewPosts = 0;
for (var i=2; i<=accountCount; i++){
newValue = parseInt(getPostCount(accountSheet.getRange(i, 9).getValue()));
oldValue = parseInt(accountSheet.getRange(i, 7).getValue());
totalNewPosts = totalNewPosts + newValue - oldValue;
accountSheet.getRange(i, 7).setValue(newValue);
statsSheet.getRange(i,statsLastCol).setValue(newValue-todaysValue);
}
if(showAlert==false){
return 0;
}
msg(totalNewPosts+" new post found!");
}
function valinar(needle, haystack){
haystack = haystack[0];
for (var i in haystack){
if(haystack[i]==needle){
return true;
}
}
return false;
}
The is the first time I'm doing something like this and working from an example from other site.
I have one more question. In function getPostCount I send the function profileurl. Where do I declare that ?
Here is how you get the URL out of the spreadsheet:
function getPostCount(profileUrl){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var thisSheet = ss.getSheetByName("List1");
var getNumberOfRows = thisSheet.getLastRow();
var urlProfile = "";
var sliced = "";
var A_Column = "";
var arrayIndex = 0;
var rngA2Bx = thisSheet.getRange(2, 2, getNumberOfRows, 1).getValues();
for (var i = 2; i < getNumberOfRows + 1; i++) { //Start getting urls from row 2
//Logger.log('count i: ' + i);
arrayIndex = i-2;
urlProfile = rngA2Bx[arrayIndex][0];
//Logger.log('urlProfile: ' + urlProfile);
var html = UrlFetchApp.fetch(urlProfile).getContentText();
sliced = html.slice(0,html.search('Posts Per Day'));
var postCount = sliced.slice(sliced.search("<dd> ")+"<dd> ".length,sliced.search("</dd>"));
sliced = sliced.slice(sliced.search('<dt>Total Posts</dt>'),sliced.length);
postCount = sliced.slice(sliced.search("<dd> ")+"<dd> ".length,sliced.search("</dd>"));
Logger.log('postCount: ' + postCount);
A_Column = thisSheet.getRange(i, 1);
A_Column.setValue(postCount);
};
}
You're missing var in front of one of your variables:
postCount = sliced.slice(sliced.search("<dd> ")+"<dd> ".length,sliced.search("</dd>"));
That won't work. Need to put var in front. var postCount = ....
In this function:
function updatePosts(){
if(arguments[0]===false){
showAlert = false;
} else {
showAlert=true;
}
There is no array named arguments anywhere in your code. Where is arguments defined and how is it getting any values put into it?
I have this recursive function which is giving me some problems. It needs to be runned like 20.000 times, but when it loops many times the browser crashes. Any help is appreciated
var valid = 0, id = 0;
$(document).ready(function() {
$("#fetch").submit(function(event) {
event.preventDefault();
var selected = $(this).find("#site option:selected");
var pieces = selected.text().split("(");
var sitename = pieces[0];
var numbers = pieces[1].slice(0,-1).split("/");
var fetched = numbers[0]; var total = numbers[1];
var members = $(this).find("#members").val();
var time = $(this).find("#wait").val() * 1000;
wait = (time == 0) ? 800 : time;
$("progress").prop("value", 0).prop("max", members * 2).fadeIn();
valid = 0;
function fetchMember(id) {
id++;
$.post("script.php", $("#fetch").serialize() + "&id=" + id )
.done(function(data) {
console.clear();
isUser = ($(data).text().indexOf("Invalid User") == -1);
if (isUser) valid++;
if(valid < members) setTimeout(function(){ fetchMember(id) }, wait);
if (isUser) {
progress();
fetched++;
selected.text(sitename+"("+fetched+"/"+total+")"); //Updating numbers of fetched profiles on the frontend
username = $(data).find(".normal").text() || $(data).find(".member_username").text() || $(data).find("#username_box h1").text();
$(data).find("dt").each(function() {
var text = $(this).text();
if (text == 'Location') country = $(this).next("dd").text();
});
$.post("save.php", { username: username } )
.done(function(data) {
$("#test").append(id+" "+data + "<br />");
progress();
});
}
});
}
fetchMember(id);
});
});
The function needs to be repeated 20.000 times with a default interval of 800ms or even more like 10 minutes
This function isn't recursing, it's just using setTimeout to call itself again at some point in the future, which isn't the same as true recursion.
However, you're using a global variable passed into a function, this will be causing you scoping issues as it's passed as a copy. By passing the id in to the timed call, you're creating a closure, which at 20,000 times, may be causing you some issues.
That's 20,000 function calls you're pushing onto the stack. That is very memory-intensive.
Try if it is a memory issue but I don't see that looking at the code.
var valid = 0, id = 0;
$(document).ready(function() {
$("#fetch").submit(function(event) {
event.preventDefault();
var selected = $(this).find("#site option:selected");
var pieces = selected.text().split("(");
var sitename = pieces[0];
var numbers = pieces[1].slice(0,-1).split("/");
var fetched = numbers[0]; var total = numbers[1];
var members = $(this).find("#members").val();
var time = $(this).find("#wait").val() * 1000;
wait = (time == 0) ? 800 : time;
$("progress").prop("value", 0).prop("max", members * 2).fadeIn();
valid = 0;
fetchMember(id,selected,pieces,sitename,numbers,fetched,members,time,wait);
});
});
function fetchMember(id,selected,pieces,sitename,numbers,fetched,members,time,wait) {
id++;
$.post("script.php", $("#fetch").serialize() + "&id=" + id )
.done(function(data) {
console.clear();
isUser = ($(data).text().indexOf("Invalid User") == -1);
if (isUser) valid++;
if (isUser) {
progress();
fetched++;
selected.text(sitename+"("+fetched+"/"+total+")"); //Updating numbers of fetched profiles on the frontend
username = $(data).find(".normal").text() || $(data).find(".member_username").text() || $(data).find("#username_box h1").text();
$(data).find("dt").each(function() {
var text = $(this).text();
if (text == 'Location') country = $(this).next("dd").text();
});
$.post("save.php", { username: username } )
.done(function(data) {
$("#test").append(id+" "+data + "<br />");
progress();
if(valid < members) setTimeout(function(){ fetchMember(id,selected,pieces,sitename,numbers,fetched,members,time,wait) }, wait);
});
}
});
}
Memory leak references http://javascript.crockford.com/memory/leak.html ... jquery does not leak.
[Exhibit 4 - Leak test with a closure]
<html>
<head>
<script type="text/javascript">
function LeakMemory(){
var parentDiv = document.createElement("div");
parentDiv.onclick=function(){
foo();
};
parentDiv.bigString =
new Array(1000).join(new Array(2000).join("XXXXX"));
}
</script>
</head>
<body>
<input type="button"
value="Memory Leaking Insert" onclick="LeakMemory()" />
</body>
</html>
I want to create a array containing objects, and I'm using Parse to query all the data.
However, the for loop which loops over the results doesn't does that in the correct order but randomly loops over the data. If I log i each iteration, the logs show different results every time.
Here is my code:
for (var i = 0; i < results.length; i++)
{
Parse.Cloud.useMasterKey();
// retrieve params
var objectid = results[i];
var self = request.params.userid;
// start query
var Payment = Parse.Object.extend("Payments");
var query = new Parse.Query(Payment);
query.get(objectid, {
success: function (payment) {
// get all the correct variables
var from_user_id = payment.get("from_user_id");
var to_user_id = payment.get("to_user_id");
var amount = payment.get("amount");
var createdAt = payment.updatedAt;
var note = payment.get("note");
var img = payment.get("photo");
var location = payment.get("location");
var status = payment.get("status");
var fromquery = new Parse.Query(Parse.User);
fromquery.get(from_user_id, {
success: function(userObject) {
var fromusername = userObject.get("name");
var currency = userObject.get("currency");
var toquery = new Parse.Query(Parse.User);
toquery.get(to_user_id, {
success: function(touser)
{
var tousername = touser.get("name");
if(tousername !== null || tousername !== "")
{
sendArray(tousername);
}
},
error: function(touser, error)
{
var tousername = to_user_id;
if(tousername !== null || tousername !== "")
{
sendArray(tousername);
}
}
});
function sendArray(tousername) {
var array = new Array();
// create the time and date
var day = createdAt.getDate();
var year = createdAt.getFullYear();
var month = createdAt.getMonth();
var hour = createdAt.getHours();
var minutes = createdAt.getMinutes();
// create the timestamp
var time = "" + hour + ":" + minutes;
var date = "" + day + " " + month + " " + year;
var associativeArray = {};
if(self == from_user_id)
{
fromusername = "self";
}
if(self == to_user_id)
{
tousername = "self";
}
associativeArray["from"] = fromusername;
associativeArray["to"] = tousername;
associativeArray["amount"] = amount;
associativeArray["currency"] = currency;
associativeArray["date"] = date;
associativeArray["time"] = time;
associativeArray["status"] = status;
if(note == "" || note == null)
{
associativeArray["note"] = null;
}
else
{
associativeArray["note"] = note;
}
if(img == "" || img == null)
{
associativeArray["img"] = null;
}
else
{
associativeArray["img"] = img;
}
if(location == "" || location == null)
{
associativeArray["location"] = null;
}
else
{
associativeArray["location"] = location;
}
array[i] = associativeArray;
if((i + 1) == results.length)
{
response.success(array);
}
},
error: function(userObject, error)
{
response.error(106);
}
});
},
error: function(payment, error) {
response.error(125);
}
});
}
But the i var is always set to seven, so the associative arrays are appended at array[7] instead of the correct i (like 1,2,3,4,5)
The reason that this is so important is because I want to order the payment chronologically (which I have done in the query providing the results).
What can I do to solve this issue?
Success is a callback that happens at a later point in time. So what happens is, the for loop runs 7 times and calls parse 7 times. Then after it has run each of parse success calls will be executed, they look at i which is now at 7.
A simple way to fix this is to wrap the whole thing in an immediate function and create a new closure for i. Something like this
for(var i = 0; i < results.length; i++){
function(iClosure) {
//rest of code goes here, replace i's with iClosure
}(i);
}
Now what will happen is that each success function will have access to it's own iClosure variable and they will be set to the value of i at the point they were created in the loop.
I am having an issue with my cookies and I can't figure it out.
Basically I have it set up so it checks for the cookie to see if the
user is logged in, and then displays either a welcome message or a
login link.
It works - except that instead of returning the persons name in the
welcome message it just is blank where the name should be.
The cookie is there, with all the appropriate info.. not sure what I
am doing wrong.
var itm = new Array();
itm[0] = findCookie("ui");
if (itm[0] == null) {
document.write("<h2><a href='logreg.html'>Log In or Sign Up</a></h2>");
}
else {
var c1 = itm[0].indexOf(",");
var c2 = itm[0].indexOf(",",c1);
var c3 = itm[0].indexOf(",",c2);
var gname = itm[0].substring(c2,c3);
document.write("<h2>Welcome "+gname+"!</h2>");
}
The findCookie function is..
function findCookie(val){
var cookie = null;
var findVal = val + "=";
var dc = document.cookie;
if (dc.length > 0)
{
var start = dc.indexOf(findVal);
if (start >= 0)
{
start += findVal.length;
lastVal = dc.indexOf(";", start);
if (lastVal == -1)
{
lastVal = dc.length;
}
cookie = (dc.substring(start, lastVal));
}
else
{
return cookie;
}
}
return cookie;
}
Never mind - I forgot to add the +1 after it finds the index of the comma or else it just reads the index number for each being the same...