Average and Lowest and Highest Temperature - JavaScript - javascript

This calculator is designed to accept user input for the purpose of calculating and reporting average temperatures. I've got the it completed for the most part but I'm running into an issue where low temps that have a different amount of digits than the high, example: 9 and 10 or 95 and 110, the script is valuing the low temp higher than the high temp. Under neath is the javascript I'm using. Unfortunately I can't add a screenshot yet but the output response on entering a low of 9 and a high of 10 is:
Please enter a low temperature less than the high temperature.
(function(){
var temperatures = [];
var lowest = 150;
var highest = 0;
var lowestDate;
var highestDate;
var lAverage = 0;
var hAverage = 0;
var table = $('table');
function addTemps() {
'use strict';
var table = "<table><tr><th style='width:110px'>Date</th><th>Low Temperature</th><th>High Temperature</th></tr>";
var lTemp = $('lTemp').value;
var hTemp = $('hTemp').value;
if (((parseFloat(lTemp) != parseInt(lTemp, 10)) || isNaN(lTemp) ||
(parseFloat(hTemp) != parseInt(hTemp, 10)) || isNaN(hTemp)) ||
(lTemp > 150) || (hTemp < 0) || (lTemp>hTemp)) {
if ((parseFloat(lTemp) != parseInt(lTemp, 10)) || isNaN(lTemp)){
table += '<tr><td colspan="3">Please enter a number for low temperature.</td></tr></table>';
}
if ((parseFloat(hTemp) != parseInt(hTemp, 10)) || isNaN(hTemp)){
table += '<tr><td colspan="3">Please enter a number for high temperature.</td></tr></table>';
}
if ((lTemp > 150) || (hTemp < 0)) {
table += '<tr><td colspan="3">Please enter a number below 150 for low, or a number greater than 0 for high temperature.</td></tr></table>';
}
if (lTemp>hTemp) {
table += '<tr><td colspan="3">Please enter a low temperature less than the high temperature.</td></tr></table>';
}
$('output').innerHTML = table;
}
else {
lTemp = parseInt(lTemp);
hTemp = parseInt(hTemp);
var newDate = new Date((new Date().getTime())-(temperatures.length * 86400000));
temperatures.push([newDate,lTemp,hTemp]);
table = createTable(table);
$('output').innerHTML = table;
}
return false;
}
function init() {
'use strict';
$('theForm').onsubmit = addTemps;
}
function createTable(tbl){
lAverage=0; hAverage=0;
for (var i = 0; i<temperatures.length; i++) {
var date = ''+(temperatures[i][0].getMonth()+1)+"/"+temperatures[i][0].getDate()+"/"+temperatures[i][0].getFullYear();
var low = temperatures[i][1];
var high = temperatures[i][2];
tbl += '<tr><td>'+date+'</td><td style="text-align: right">'+low+'</td><td style="text-align: right">'+high+'</td></tr>';
if (low < lowest){
lowest = low;
lowestDate = date;
}
if (high > highest){
highest = high;
highestDate = date;
}
lAverage+=temperatures[i][1];
hAverage+=temperatures[i][2];
}
lAverage=(lAverage/temperatures.length).toFixed(1);
hAverage=(hAverage/temperatures.length).toFixed(1);
tbl+='<tr class="summaryRow"><td>Averages</td><td style="text-align: right">'+lAverage+'</td><td style="text-align: right">'+hAverage+'</td></tr>';
tbl+='<tr class="summaryRow"><td colspan="3">The lowest temperature of '+lowest+' occured on '+lowestDate+'.</tr>';
tbl+='<tr class="summaryRow"><td colspan="3">The highest temperature of '+highest+' occured on '+highestDate+'.</tr>';
tbl+='</table>';
return tbl;
}
function $(elementID){
if (typeof(elementID) == 'string') {
return document.getElementById(elementID);
}
}
window.onload = init;
})();
I'm assuming this is an error in the addTemps function with parseFloat or parseInt but I'm stuck on what to actually modify to avoid this issue.

Here are some thoughts. I could not test this code in repl.it, so it might have some rough edges.
If I correctly understand what this code is supposed to do..
Two main issues were:
You were comparing strings to numbers in several locations.
Your addTemps() function always returned false -- is this correct?
I actually don't remember how onSubmit works as I've not used JQuery or forms in ages.
Adjust the return value from addTemps appropriately, if I got that part mixed up.
Not technically wrong, but you can use "convenience variables" to cache calculations/conversions. They are essentially "free" in JS. This can make Code easier to read, and compiler doesn't have to keep re-doing the same calc.
(function(){
// could avoid "magic numbers" in code with:
var min_valid_hiTemp = 0;
var max_valid_loTemp = 150;
// initialize vars
var temperatures = [];
var lowest = 150; // max_valid_loTemp;
var highest = 0; // min_valid_hiTemp;
var lowestDate = '';
var highestDate = '';
var lAverage = 0;
var hAverage = 0;
var table = $('table');
function addTemps() {
'use strict';
var table = "<table><tr><th style='width:110px'>Date</th><th>Low Temperature</th><th>High Temperature</th></tr>";
var lTemp = $('lTemp').value;
var hTemp = $('hTemp').value;
// convenience variables
loTemp_float = parseFloat(lTemp);
loTemp_int = parseInt(lTemp, 10);
hiTemp_float = parseFloat(hTemp);
hiTemp_int = parseInt(hTemp, 10);
loTemp_isNAN = isNaN(lTemp);
hiTemp_isNAN = isNaN(hTemp);
// print error message if input was invalid
if ( (loTemp_float != loTemp_int) ||
(hiTemp_float != hiTemp_int) ||
loTemp_inNaN || hiTemp_isNan ||
(loTemp_int > hiTemp_int) ||
(loTemp_int > 150) ||
(hiTemp_int < 0)
){
if ((loTemp_float != loTemp_int) || loTemp_isNAN){
table += '<tr><td colspan="3">Please enter a number for low temperature.</td></tr></table>';
}
if ((hiTemp_float != hiTemp_int) || hiTemp_isNAN){
table += '<tr><td colspan="3">Please enter a number for high temperature.</td></tr></table>';
}
// uses "magic numbers"
if ((loTemp_int > 150) || (hiTemp_int < 0)) {
table += '<tr><td colspan="3">Please enter a number below 150 for low, or a number greater than 0 for high temperature.</td></tr></table>';
}
if (loTemp_int > hiTemp_int) {
table += '<tr><td colspan="3">Please enter a low temperature less than the high temperature.</td></tr></table>';
}
// don't call createTable() ?
$('output').innerHTML = table;
// shouldn't this block return false? - To not submit the form
return false
}
// input is valid: store the temperature data
else {
// not necessary now - we already have variables with this info: loTemp_int, hiTemp_int
// lTemp = parseInt(lTemp);
// hTemp = parseInt(hTemp);
// curious how the number of stored temps is related to the date..?
var newDate = new Date((new Date().getTime())-(temperatures.length * 86400000));
// just use the variables we already have
//temperatures.push([newDate, lTemp, hTemp]);
temperatures.push([newDate, loTemp_int, hiTemp_int]);
table = createTable(table);
$('output').innerHTML = table;
// shouldn't this block return true? - To submit the form
return true
}
// ?? No matter what, return false?
// I suspect you want to return false if input was invalid, and true if it was valid.
// if so, the return values should be inside the "if" and the "else" blocks.
// Not outside both blocks, as it is here.
//return false;
}
function init() {
'use strict';
$('theForm').onsubmit = addTemps;
}
function createTable(tbl){
lAverage=0;
hAverage=0;
for (var i = 0; i<temperatures.length; i++) {
var date = ''+(temperatures[i][0].getMonth()+1)+"/"+temperatures[i][0].getDate()+"/"+temperatures[i][0].getFullYear();
var low = temperatures[i][1];
var high = temperatures[i][2];
tbl += '<tr><td>'+date+'</td><td style="text-align: right">'+low+'</td><td style="text-align: right">'+high+'</td></tr>';
if (low < lowest){
lowest = low;
lowestDate = date;
}
if (high > highest){
highest = high;
highestDate = date;
}
// you already have variables "low" and "high" - may as well use them
// lAverage+=temperatures[i][1];
// hAverage+=temperatures[i][2];
lAverage += low;
hAverage += high;
}
lAverage=(lAverage/temperatures.length).toFixed(1);
hAverage=(hAverage/temperatures.length).toFixed(1);
tbl+='<tr class="summaryRow"><td>Averages</td><td style="text-align: right">'+lAverage+'</td><td style="text-align: right">'+hAverage+'</td></tr>';
tbl+='<tr class="summaryRow"><td colspan="3">The lowest temperature of '+lowest+' occured on '+lowestDate+'.</tr>';
tbl+='<tr class="summaryRow"><td colspan="3">The highest temperature of '+highest+' occured on '+highestDate+'.</tr>';
tbl+='</table>';
return tbl;
}
function $(elementID){
if (typeof(elementID) == 'string') {
return document.getElementById(elementID);
}
}
window.onload = init;
})();
I actually don't remember how onSubmit works as I've not used JQuery or forms in ages.
Adjust the return value from addTemps appropriately, if I got that part mixed up.
Here is a repl version, that also corrects a couple typos that exist in the above code.
note: none of the "print" statements will appear until you reply to the "add another temp" prompt with something other than y. So that part of the functionality is not perfect, but you can see that the main sticky points of the logic have been correctly addressed.
// could avoid "magic numbers" in code with:
var min_valid_hiTemp = 0;
var max_valid_loTemp = 150;
// initialize vars
var temperatures = [];
var lowest = 150; // max_valid_loTemp;
var highest = 0; // min_valid_hiTemp;
var lowestDate = '';
var highestDate = '';
var lAverage = 0;
var hAverage = 0;
// var table = $('table');
// non html version
var table = 'table\n';
function addTemps() {
'use strict';
var table = 'Date' + ' ' + 'Low Temperature' + ' ' + 'High Temperature' + '\n';
// var lTemp = $('lTemp').value;
// var hTemp = $('hTemp').value;
// non html version:
var lTemp = prompt('enter low temp');
var hTemp = prompt('enter high temp');
// convenience variables
var loTemp_float = parseFloat(lTemp);
var loTemp_int = parseInt(lTemp, 10);
var hiTemp_float = parseFloat(hTemp);
var hiTemp_int = parseInt(hTemp, 10);
var loTemp_isNAN = isNaN(lTemp);
var hiTemp_isNAN = isNaN(hTemp);
// print error message if input was invalid
if ( (loTemp_float != loTemp_int) ||
(hiTemp_float != hiTemp_int) ||
loTemp_isNAN || hiTemp_isNAN ||
(loTemp_int > hiTemp_int) ||
(loTemp_int > 150) ||
(hiTemp_int < 0)
){
if ((loTemp_float != loTemp_int) || loTemp_isNAN){
table += 'Please enter a number for low temperature.' + '\n';
}
if ((hiTemp_float != hiTemp_int) || hiTemp_isNAN){
table += 'Please enter a number for high temperature.' + '\n';
}
// uses "magic numbers"
if ((loTemp_int > 150) || (hiTemp_int < 0)) {
table += 'Please enter a number below 150 for low, or a number greater than 0 for high temperature.' + '\n';
}
if (loTemp_int > hiTemp_int) {
table += 'Please enter a low temperature less than the high temperature.' + '\n';
}
// does't call createTable() ?
// $('output').innerHTML = table;
// without html:
console.log(table);
console.log();
// shouldn't this block return false? - To not submit the form
return false
}
// input is valid: store the temperature data
else {
// curious how the number of stored temps is related to the date..?
var newDate = new Date((new Date().getTime()) - (temperatures.length * 86400000));
temperatures.push([newDate, loTemp_int, hiTemp_int]);
table = createTable(table);
//$('output').innerHTML = table;
// non html version
console.log(table);
console.log();
// shouldn't this block return true? - To submit the form
return true
}
// ?? No matter what, return false?
// I suspect you want to return false if input was invalid, and true if it was valid.
// if so, the return values should be inside the "if" and the "else" blocks.
// Not outside both blocks, as it is here.
//return false;
}
function init() {
'use strict';
//$('theForm').onsubmit = addTemps;
// non html / jquery version
if (addTemps()){
console.log("submitted");
}
else {
console.log('not submitted');
}
}
function createTable(tbl){
lAverage=0;
hAverage=0;
for (var i = 0; i< temperatures.length; i++) {
var date = '' + (temperatures[i][0].getMonth()+1) +
"/" + temperatures[i][0].getDate() +
"/" + temperatures[i][0].getFullYear();
var low = temperatures[i][1];
var high = temperatures[i][2];
tbl += date + '\t' + low + '\t\t\t' + high + '\n';
if (low < lowest){
lowest = low;
lowestDate = date;
}
if (high > highest){
highest = high;
highestDate = date;
}
lAverage += low;
hAverage += high;
}
lAverage = (lAverage/temperatures.length).toFixed(1);
hAverage = (hAverage/temperatures.length).toFixed(1);
tbl += 'Averages' + '\t' + lAverage + ' low, ' + '\t\t' + hAverage + ' high' + '\n';
tbl += 'The lowest temperature of ' + lowest + ' occured on ' + lowestDate +'.\n';
tbl += 'The highest temperature of ' + highest + ' occured on ' + highestDate+'.\n';
tbl += '\n';
return tbl;
}
// window.onload = init;
var addAnother = 'y'
while (addAnother == 'y') {
init();
addAnother = prompt('press "y" to add another');
}

Related

JavaScript infinity loop in calculator

I'm developing a small calculator that allows you to input a string. So it has to recognize which sign has to be executed in first place.
My problem is that somewhere and by some reason it creates a stackoverflow. I was expecting if you could help me to find out.
The first for is to give each operator a precedence, so * is more important than +. Second loop is destinated to find the sign into the string, so if input.indexOf(signos[i]) is lower or than 0 it jumps off the operator. if its dalse it goes in and put the number in left side and right side into two aux values and in the end it solves the sign and replace it into the string so at the end it shows you the result.
Thanks.
var input;
var signos = ['*', '/', '+', '-'];
var cursor = 0;
var aux1 = "";
var aux2 = "";
var auxSigno = "";
var resuelto = 0;
var encontrado = false;
function lectura(){
input = document.getElementById("ans").value;
console.log(input);
for(i = 0; i < signos.length; i++){
cursor = input.indexOf(signos[i]);
//console.log(cursor);
if (cursor > -1){
auxSigno = input.charAt(cursor);
//console.log(auxSigno);
for(j = 0; j < input.length; i++){
for(k = cursor-1; comparar(k); k--){
aux1+=input[k];
}
for(l = cursor+1; comparar(l); l++){
aux2+=input[l];
}
operar();
var cadena = aux1+auxSigno+aux2;
var auxCadena = input.replace(cadena, resuelto);
input = auxCadena;
}
}
}
console.log(input);
}
function comparar(caracter){
for(m = 0; m < signos.length; m++){
if (caracter === signos[m]){
return true;
}
}
return false;
}
function operar(){
console.log(auxSigno);
console.log(aux1);
console.log(aux2);
if (signos.indexOf(auxSigno) == 0){
resuelto = parseFloat(aux1) * parseFloat(aux2);
console.log(resuelto + " opc1");
} else if (signos.indexOf(auxSigno) == 1) {
resuelto = parseFloat(aux1) / parseFloat(aux2);
console.log(resuelto + " opc2");
} else if (signos.indexOf(auxSigno) == 2) {
resuelto = parseFloat(aux1) + parseFloat(aux2);
console.log(resuelto + " opc3")
} else if (signos.indexOf(auxSigno) == 3){
resuelto = parseFloat(aux1) - parseFloat(aux2);
console.log(resuelto + " opc4")
} else {
console.log("opc no implementada");
}
}
if the input is "6+6*8", the result should be "54", but it doesn't show anything, just keep doing the for.

function that adds and subtracts values from vars setting some of them to NaN

I apologize for the length, but all of it's necessary, and I removed unimportant parts. The function:
function fight()
{
var cellsLost, mitoLost, chloroLost = 0;
var cellsGained, mitoGained, chloroGained = 0;
var w = cells;
var x = chloros;
var z = mitos;
if((difficulty == "easy")&&(lysos<=10))
{
cellsLost = randomInt(1,10-lysos); //-9 to 9
mitoLost = Math.round(randomInt(0,4-((1/5)*lysos))); //-2 to 4
chloroLost = Math.round(randomInt(0,8-((1/3)*lysos))); // -3 to 8
}
else if((difficulty == "easy")&&(lysos>10))
{
cellsGained = Math.abs((randomInt(1,10-lysos))); //
mitoGained = Math.round(((1/5)*lysos) - randomInt(0,2));
chloroGained = Math.round(((1/3)*lysos) - randomInt(0,3));
}
else if((difficulty == "average")&&(lysos<=20))
{
cellsLost = randomInt(0,20-lysos); //0 to 19
mitoLost = Math.round(randomInt(0,10-((1/2)*lysos))); // -10 to 10
chloroLost = Math.round(randomInt(0,15-((1/3)*lysos))); //-7 to 15
}
else if((difficulty == "average")&&(lysos>20))
{
cellsGained = Math.abs((randomInt(1,20-lysos)));
mitoGained = Math.round(((1/5)*lysos)-randomInt(0,4));
chloroGained = Math.round(((1/3)*lysos)-randomInt(0,7));
}
else if((difficulty == "challenging")&&(lysos<=30))
{
cellsLost = randomInt(0,30-lysos); //0 to 29
mitoLost = Math.abs(Math.round(randomInt(0,15-((1/2)*lysos)))); //-15 to 15 ie 0-15 with double chances
chloroLost = Math.round(randomInt(0,25-((1/3)*lysos))); //-10 to 25 ie 0 to 25 with double chances upto 10
}
else if((difficulty == "challenging")&&(lysos>30))
{
cellsGained = Math.abs((randomInt(1,30-lysos)));
mitoGained = Math.round(((1/5)*lysos)-randomInt(0,6));
chloroGained = Math.round(((1/3)*lysos)-randomInt(0,10));
}
mitoLost = negtozero(mitoLost);
chloroLost = negtozero(chloroLost);
cellsLost = negtozero(cellsLost);
mitoGained = negtozero(mitoGained);
chloroGained = negtozero(chloroGained);
cellsGained = negtozero(cellsGained);
cells = cells - cellsLost;
mitos = mitos - mitoLost;
chloros = chloros - chloroLost;
mitos += mitoGained;
chloros += chloroGained;
cells += cellsGained;
mitos = negtozero(mitos);
cells = negtozero(cells);
chloros = negtozero(chloros);
divideCost = Math.round((15*(Math.pow(1.15,cells))));
chloroCost = Math.round((100*(Math.pow(1.15,chloros))));
mitoCost = (Math.round(150*(Math.pow(1.15,mitos))));
display('The battle was long and hard.');
if((w-cells)>0)
{
display('You lost ' + (w-cells) + ' cells.');
}
if((cells-w)>0)
{
display('You gained ' + (cells-w) + ' cells.');
}
if((x-chloros)>0)
{
display('You lost ' + (x-chloros) + ' chloroplasts.');
}
if((chloros-x)>0)
{
display('You gained ' + (chloros-x) + ' cells.');
}
if((z-mitos)>0)
{
display('You lost ' + (z-mitos) + ' chloroplasts.');
}
if((mitos-z)>0)
{
display('You lost ' + (mitos-z) + ' chloroplasts.');
}
attackCheck = setInterval(function() { cellAttack(); },1000);
document.getElementById('fightbtn').style.display = "none";
document.getElementById('fleebtn').style.display = "none";
}
}
mitos, chloros and cells are all global vars previously initialized with values >0 or =0. Function negtozero() accepts an int argument and either returns the number if positive or 0 if it's negative.
All the function does is provide a value to cellslost, chlorolost, mitolost and to cellsgained, mitogained, chlorogained based on certain conditions, and adds/subtracts themselves to cells, mitos and chloros respectively. I don't know why/how mitos and cells are being assigned NaN values, whereas chloros is being assigned the proper values.

Add Campaign Selector in Adwords Script

I have a bid-to-position script that targets keywords that have a label associated with them. The label contains the desired position and the script adjusts the keyword's bid in order to reach that position. Right now the script targets any keyword with the label. I'm trying to edit the script so it will look for labeled keywords in campaigns that I choose. I tried adding .withCondition(CampaignName = ' My Campaign Name'") to the labelIterator variable but had no luck. Can anyone point me in the right direction?
/**
*
* Average Position Bidding Tool
*
* This script changes keyword bids so that they target specified positions,
* based on recent performance.
*
* Version: 1.2
* Updated 2015-09-28 to correct for report column name changes
* Updated 2016-02-05 to correct label reading, add extra checks and
* be able to adjust maximum bid increases and decreases separately
* Google AdWords Script maintained on brainlabsdigital.com
*
**/
// Options
var maxBid = 5.00;
// Bids will not be increased past this maximum.
var minBid = 0.10;
// Bids will not be decreased below this minimum.
var firstPageMaxBid = 1.00;
// The script avoids reducing a keyword's bid below its first page bid estimate. If you think
// Google's first page bid estimates are too high then use this to overrule them.
var dataFile = "AveragePositionData.txt";
// This name is used to create a file in your Google Drive to store today's performance so far,
// for reference the next time the script is run.
var useFirstPageBidsOnKeywordsWithNoImpressions = false;
// If this is true, then if a keyword has had no impressions since the last time the script was run
// its bid will be increased to the first page bid estimate (or the firsPageMaxBid if that is smaller).
// If this is false, keywords with no recent impressions will be left alone.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Advanced Options
var bidIncreaseProportion = 0.2;
var bidDecreaseProportion = 0.4;
var targetPositionTolerance = 0.2;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function main() {
var fieldJoin = ",";
var lineJoin = "$";
var idJoin = "#";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
var files = DriveApp.getFilesByName(dataFile);
if (!files.hasNext()) {
var file = DriveApp.createFile(dataFile,"");
Logger.log("File '" + dataFile + "' has been created.");
} else {
var file = files.next();
if (files.hasNext()) {
Logger.log("Error - more than one file named '" + dataFile + "'");
return;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
var labelIds = [];
var labelIterator = AdWordsApp.labels()
.withCondition("CampaignName CONTAINS_IGNORE_CASE 'MY CAMPAIGN NAME' ")
.withCondition("KeywordsCount > 0")
.withCondition("LabelName CONTAINS_IGNORE_CASE 'Position '")
.get();
while (labelIterator.hasNext()) {
var label = labelIterator.next();
if (label.getName().substr(0,"position ".length).toLowerCase() == "position ") {
labelIds.push(label.getId());
}
}
if (labelIds.length == 0) {
Logger.log("No position labels found.");
return;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
var keywordData = {
//UniqueId1: {LastHour: {Impressions: , AveragePosition: }, ThisHour: {Impressions: , AveragePosition: },
//CpcBid: , FirstPageCpc: , MaxBid, MinBid, FirstPageMaxBid, PositionTarget: , CurrentAveragePosition:,
//Criteria: }
}
var ids = [];
var uniqueIds = [];
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
var report = AdWordsApp.report(
'SELECT Id, Criteria, AdGroupId, AdGroupName, CampaignName, Impressions, AveragePosition, CpcBid, FirstPageCpc, Labels, BiddingStrategyType ' +
'FROM KEYWORDS_PERFORMANCE_REPORT ' +
'WHERE Status = ENABLED AND AdGroupStatus = ENABLED AND CampaignStatus = ENABLED ' +
'AND LabelIds CONTAINS_ANY [' + labelIds.join(",") + '] ' +
'AND AdNetworkType2 = SEARCH ' +
'AND Device NOT_IN ["HIGH_END_MOBILE"] ' +
'DURING TODAY'
);
var rows = report.rows();
while(rows.hasNext()){
var row = rows.next();
if (row["BiddingStrategyType"] != "cpc") {
if (row["BiddingStrategyType"] == "Enhanced CPC"
|| row["BiddingStrategyType"] == "Target search page location"
|| row["BiddingStrategyType"] == "Target Outranking Share"
|| row["BiddingStrategyType"] == "None"
|| row["BiddingStrategyType"] == "unknown") {
Logger.log("Warning: keyword " + row["Criteria"] + "' in campaign '" + row["CampaignName"] +
"' uses '" + row["BiddingStrategyType"] + "' rather than manual CPC. This may overrule keyword bids and interfere with the script working.");
} else {
Logger.log("Warning: keyword " + row["Criteria"] + "' in campaign '" + row["CampaignName"] +
"' uses the bidding strategy '" + row["BiddingStrategyType"] + "' rather than manual CPC. This keyword will be skipped.");
continue;
}
}
var positionTarget = "";
var labels = row["Labels"].toLowerCase().split("; ")
for (var i=0; i<labels.length; i++) {
if (labels[i].substr(0,"position ".length) == "position ") {
var positionTarget = parseFloat(labels[i].substr("position ".length-1).replace(/,/g,"."),10);
break;
}
}
if (positionTarget == "") {
continue;
}
if (integrityCheck(positionTarget) == -1) {
Logger.log("Invalid position target '" + positionTarget + "' for keyword '" + row["Criteria"] + "' in campaign '" + row["CampaignName"] + "'");
continue;
}
ids.push(parseFloat(row['Id'],10));
var uniqueId = row['AdGroupId'] + idJoin + row['Id'];
uniqueIds.push(uniqueId);
keywordData[uniqueId] = {};
keywordData[uniqueId]['Criteria'] = row['Criteria'];
keywordData[uniqueId]['ThisHour'] = {};
keywordData[uniqueId]['ThisHour']['Impressions'] = parseFloat(row['Impressions'].replace(/,/g,""),10);
keywordData[uniqueId]['ThisHour']['AveragePosition'] = parseFloat(row['AveragePosition'].replace(/,/g,""),10);
keywordData[uniqueId]['CpcBid'] = parseFloat(row['CpcBid'].replace(/,/g,""),10);
keywordData[uniqueId]['FirstPageCpc'] = parseFloat(row['FirstPageCpc'].replace(/,/g,""),10);
setPositionTargets(uniqueId, positionTarget);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
setBidChange();
setMinMaxBids();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
var currentHour = parseInt(Utilities.formatDate(new Date(), AdWordsApp.currentAccount().getTimeZone(), "HH"), 10);
if (currentHour != 0) {
var data = file.getBlob().getDataAsString();
var data = data.split(lineJoin);
for(var i = 0; i < data.length; i++){
data[i] = data[i].split(fieldJoin);
var uniqueId = data[i][0];
if(keywordData.hasOwnProperty(uniqueId)){
keywordData[uniqueId]['LastHour'] = {};
keywordData[uniqueId]['LastHour']['Impressions'] = parseFloat(data[i][1],10);
keywordData[uniqueId]['LastHour']['AveragePosition'] = parseFloat(data[i][2],10);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
findCurrentAveragePosition();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
try {
updateKeywords();
} catch (e) {
Logger.log("Error updating keywords: " + e);
Logger.log("Retrying after one minute.");
Utilities.sleep(60000);
updateKeywords();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
var content = resultsString();
file.setContent(content);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Functions
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function integrityCheck(target){
var n = parseFloat(target, 10);
if(!isNaN(n) && n >= 1){
return n;
}
else{
return -1;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function setPositionTargets(uniqueId, target){
if(target !== -1){
keywordData[uniqueId]['HigherPositionTarget'] = Math.max(target-targetPositionTolerance, 1);
keywordData[uniqueId]['LowerPositionTarget'] = target+targetPositionTolerance;
}
else{
keywordData[uniqueId]['HigherPositionTarget'] = -1;
keywordData[uniqueId]['LowerPositionTarget'] = -1;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function bidChange(uniqueId){
var newBid = -1;
if(keywordData[uniqueId]['HigherPositionTarget'] === -1){
return newBid;
}
var cpcBid = keywordData[uniqueId]['CpcBid'];
var minBid = keywordData[uniqueId]['MinBid'];
var maxBid = keywordData[uniqueId]['MaxBid'];
if (isNaN(keywordData[uniqueId]['FirstPageCpc'])) {
Logger.log("Warning: first page CPC estimate is not a number for keyword '" + keywordData[uniqueId]['Criteria'] + "'. This keyword will be skipped");
return -1;
}
var firstPageBid = Math.min(keywordData[uniqueId]['FirstPageCpc'], keywordData[uniqueId]['FirstPageMaxBid'], maxBid);
var currentPosition = keywordData[uniqueId]['CurrentAveragePosition'];
var higherPositionTarget = keywordData[uniqueId]['HigherPositionTarget'];
var lowerPositionTarget = keywordData[uniqueId]['LowerPositionTarget'];
var bidIncrease = keywordData[uniqueId]['BidIncrease'];
var bidDecrease = keywordData[uniqueId]['BidDecrease'];
if((currentPosition > lowerPositionTarget) && (currentPosition !== 0)){
var linearBidModel = Math.min(2*bidIncrease,(2*bidIncrease/lowerPositionTarget)*(currentPosition-lowerPositionTarget));
var newBid = Math.min((cpcBid + linearBidModel), maxBid);
}
if((currentPosition < higherPositionTarget) && (currentPosition !== 0)) {
var linearBidModel = Math.min(2*bidDecrease,((-4)*bidDecrease/higherPositionTarget)*(currentPosition-higherPositionTarget));
var newBid = Math.max((cpcBid-linearBidModel),minBid);
if (cpcBid > firstPageBid) {
var newBid = Math.max(firstPageBid,newBid);
}
}
if((currentPosition === 0) && useFirstPageBidsOnKeywordsWithNoImpressions && (cpcBid < firstPageBid)){
var newBid = firstPageBid;
}
if (isNaN(newBid)) {
Logger.log("Warning: new bid is not a number for keyword '" + keywordData[uniqueId]['Criteria'] + "'. This keyword will be skipped");
return -1;
}
return newBid;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function findCurrentAveragePosition(){
for(var x in keywordData){
if(keywordData[x].hasOwnProperty('LastHour')){
keywordData[x]['CurrentAveragePosition'] = calculateAveragePosition(keywordData[x]);
} else {
keywordData[x]['CurrentAveragePosition'] = keywordData[x]['ThisHour']['AveragePosition'];
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function calculateAveragePosition(keywordDataElement){
var lastHourImpressions = keywordDataElement['LastHour']['Impressions'];
var lastHourAveragePosition = keywordDataElement['LastHour']['AveragePosition'];
var thisHourImpressions = keywordDataElement['ThisHour']['Impressions'];
var thisHourAveragePosition = keywordDataElement['ThisHour']['AveragePosition'];
if(thisHourImpressions == lastHourImpressions){
return 0;
}
else{
var currentPosition = (thisHourImpressions*thisHourAveragePosition-lastHourImpressions*lastHourAveragePosition)/(thisHourImpressions-lastHourImpressions);
if (currentPosition < 1) {
return 0;
} else {
return currentPosition;
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function keywordUniqueId(keyword){
var id = keyword.getId();
var idsIndex = ids.indexOf(id);
if(idsIndex === ids.lastIndexOf(id)){
return uniqueIds[idsIndex];
}
else{
var adGroupId = keyword.getAdGroup().getId();
return adGroupId + idJoin + id;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function setMinMaxBids(){
for(var x in keywordData){
keywordData[x]['MinBid'] = minBid;
keywordData[x]['MaxBid'] = maxBid;
keywordData[x]['FirstPageMaxBid'] = firstPageMaxBid;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function setBidChange(){
for(var x in keywordData){
keywordData[x]['BidIncrease'] = keywordData[x]['CpcBid'] * bidIncreaseProportion/2;
keywordData[x]['BidDecrease'] = keywordData[x]['CpcBid'] * bidDecreaseProportion/2;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function updateKeywords() {
var keywordIterator = AdWordsApp.keywords()
.withIds(uniqueIds.map(function(str){return str.split(idJoin);}))
.get();
while(keywordIterator.hasNext()){
var keyword = keywordIterator.next();
var uniqueId = keywordUniqueId(keyword);
var newBid = bidChange(uniqueId);
if(newBid !== -1){
keyword.setMaxCpc(newBid);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
function resultsString(){
var results = [];
for(var uniqueId in keywordData){
var resultsRow = [uniqueId, keywordData[uniqueId]['ThisHour']['Impressions'], keywordData[uniqueId]['ThisHour']['AveragePosition']];
results.push(resultsRow.join(fieldJoin));
}
return results.join(lineJoin);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
}
so CampaignName isn't a valid with condition for the label selector. What you need to do instead is have a Campaign Selector in a while look before you come to your Label selector, which then feeds from the campaign iteration. I've done a quick and dirty example below, but of course, you'd have to take a look to see if doing this will require other changes later on (or earlier on) in your code.
var labelIds = [];
var campaignIterator = AdWordsApp.campaigns()
.withCondition("CampaignName CONTAINS_IGNORE_CASE 'MY CAMPAIGN NAME' ")
.get()
while (campaignIterator.hasNext())
{
var campaign = campaignIterator.next()
var labelIterator = campaign.labels()
.withCondition("CampaignName CONTAINS_IGNORE_CASE 'MY CAMPAIGN NAME' ")
.withCondition("KeywordsCount > 0")
.withCondition("LabelName CONTAINS_IGNORE_CASE 'Position '")
.get();
while (labelIterator.hasNext()) {
var label = labelIterator.next();
if (label.getName().substr(0,"position ".length).toLowerCase() == "position ") {
labelIds.push(label.getId());
}
}
if (labelIds.length == 0) {
Logger.log("No position labels found.");
return;
}
}
var labelIterator = AdWordsApp.labels()

Multiplying variables and showing result in a box

I'm having a problem when trying to multiply the totalPallets by the price-per-pallet ($25) and then showing that in the productSubTotal box. With the code as it is right now, the quatity total shows but when I try to get the price result, it doesn't show the operation. Also, if I try changing anythung from the code, the whole thing breaks down. I'll be thankful if anyone could help me. Thanks
// UTILITY FUNCTIONS
function IsNumeric(n) {
return !isNaN(n);
}
function calcTotalPallets() {
var totalPallets = 0;
$(".num-pallets-input").each(function() {
var thisValue = parseInt($(this).val());
if ( (IsNumeric(thisValue)) && (thisValue != '') ) {
totalPallets += parseInt(thisValue);
};
});
$("#quantitytotal").val(totalPallets);
}
function calcProdSubTotal() {
var prodSubTotal = 0;
$(".totalprice").each(function() {
var valString = parseInt(totalPallets) * multiplier;
prodSubTotal += parseInt(valString);
});
$("#product-subtotal").val(CommaFormatted(prodSubTotal));
};
// "The Math" is performed pretty much whenever anything happens in the quanity inputs
$('.num-pallets-input').bind("focus blur change keyup", function(){
// Caching the selector for efficiency
var $el = $(this);
// Grab the new quantity the user entered
var numPallets = CleanNumber($el.val());
var totalPallets = CleanNumber($el.val());
var prodSubTotal = CleanNumber($el.val());
// Find the pricing
var multiplier = $el
.parent().parent()
.find("td.price-per-pallet span")
.text();
};
// Calcuate the overal totals
calcProdSubTotal();
calcTotalPallets();
});
function CommaFormatted(amount) {
var delimiter = ",";
var i = parseInt(amount);
if(isNaN(i)) { return ''; }
i = Math.abs(i);
var minus = '';
if (i < 0) { minus = '-'; }
var n = new String(i);
var a = [];
while(n.length > 3)
{
var nn = n.substr(n.length-3);
a.unshift(nn);
n = n.substr(0,n.length-3);
}
if (n.length > 0) { a.unshift(n); }
n = a.join(delimiter);
amount = "$" + minus + n;
return amount;
}
});

Javascript Functions, Uncaught syntax error, Unexpected token?

The following code is giving me an error in the chrome developer tools:
"uncaught syntax error- unexpected token"
Specifically, the Errors come up in the populate header function at
var notraw = JSON.parse(arrayraw)
and in the first if statement, at
parsed = JSON.parse(retrieved); //var test is now re-loaded!
These errors haven't come up in previous iterations. Does anyone know why?
// This statement should be ran on load, to populate the table
// if Statement to see whether to retrieve or create new
if (localStorage.getItem("Recipe") === null) { // if there was no array found
console.log("There was no array found. Setting new array...");
//Blank Unpopulated array
var blank = [
["Untitled Recipe", 0, 0]
];
// Insert Array into local storage
localStorage.setItem("Recipe", JSON.stringify(blank));
console.log(blank[0]);
} else {
console.log("The Item was retrieved from local storage.");
var retrieved = localStorage.getItem("Recipe"); // Retrieve the item from storage
// test is the storage entry name
parsed = JSON.parse(retrieved); //var test is now re-loaded!
// we had to parse it from json
console.log(parsed)
}
// delete from array and update
function deletefromarray(id) {
var arrayraw = localStorage.getItem("Recipe")
var notraw = JSON.parse(arrayraw)
console.log(notraw[id])
notraw.splice(id, 1);
localStorage.setItem("Recipe", JSON.stringify(notraw));
}
// This adds to local array, and then updates that array.
function addtoarray(ingredient, amount, unit) {
var arrayraw = localStorage.getItem("Recipe")
var notraw = JSON.parse(arrayraw)
notraw.push([ingredient, amount, unit]);
localStorage.setItem("Recipe", JSON.stringify(notraw));
var recipeid = notraw.length - 1
console.log("recipe id:" + recipeid)
}
//The calculation function, that gets the ingredients from the array, and calculates what ingredients are needed
function calculate(multiplier) {
alert("Calculate function was called")
var length = recipearray.length - 1;
console.log("There are " + length + " ingredients.");
for (i = 0; i < length; i++) {
console.log("raw = " + recipearray[i + 1][1] + recipearray[i + 1][2]);
console.log("multiplied = " + recipearray[i + 1][1] / recipearray[0][2] * multiplier + recipearray[i + 1][2]);
}
}
// The save function, This asks the user to input the name and how many people the recipe serves. This information is later passed onto the array.
function save() {
var verified = true;
while (verified) {
var name = prompt("What's the name of the recipe?")
var serves = prompt("How many people does it serve?")
if (serves === "" || name === "" || isNaN(serves) === true || serves === "null") {
alert("You have to enter a name, followed by the number of people it serves. Try again.")
verified = false;
} else {
alert("sucess!");
var element = document.getElementById("header");
element.innerHTML = name;
var header2 = document.getElementById("details");
header2.innerHTML = "Serves " + serves + " people"
calculate(serves)
var arrayraw = localStorage.getItem("Recipe")
var notraw = JSON.parse(arrayraw)
notraw.splice(0, 1, [name, serves, notraw.length])
localStorage.setItem("Recipe", JSON.stringify(notraw))
return;
}
}
}
// the recipe function processes the inputs for the different ingredients and amounts.
function recipe() {
// Declare all variables
var ingredient = document.getElementById("ingredient").value;
var amount = document.getElementById("number").value;
var unit = document.getElementById("unit").value;
var count = "Nothing";
console.log("Processing");
if (isNaN(amount)) {
alert("You have to enter a number in the amount field")
} else if (ingredient === "" || amount === "" || unit === "Select Unit") {
alert("You must fill in all fields.")
} else if (isNaN(ingredient) === false) {
alert("You must enter an ingredient NAME.")
} else {
console.log("hey!")
// console.log(recipearray[1][2] + recipearray[1][1])
var totalamount = amount + unit
edit(ingredient, amount, unit, false)
insRow(ingredient, totalamount) // post(0,*123456*,"Fish")
}
}
function deleteRow(specified) {
// Get the row that the delete button was clicked in, and delete it.
var inside = specified.parentNode.parentNode.rowIndex;
document.getElementById('table').deleteRow(inside);
var rowid = inside + 1 // account for the first one being 0
console.log("An ingredient was deleted by the user: " + rowid);
// Remove this from the array.
deletefromarray(-rowid);
}
function insRow(first, second) {
//var first = document.getElementById('string1').value;
//var second = document.getElementById('string2').value;
// This console.log("insRow: " + first)
// Thisconsole.log("insRow: " + second)
var x = document.getElementById('table').insertRow(0);
var y = x.insertCell(0);
var z = x.insertCell(1);
var a = x.insertCell(2);
y.innerHTML = first;
z.innerHTML = second;
a.innerHTML = '<input type="button" onclick="deleteRow(this)" value="Delete">';
}
function populateheader() {
// Populate the top fields with the name and how many it serves
var arrayraw = localStorage.getItem("Recipe")
var notraw = JSON.parse(arrayraw)
var element = document.getElementById("header");
element.innerHTML = notraw[0][0];
var header2 = document.getElementById("details");
// if statement ensures the header doesn't say '0' people, instead says no people
if (notraw[0][1] === 0) {
header2.innerHTML = "Serves no people"
} else {
header2.innerHTML = "Serves " + notraw[0][1] + " people"
}
console.log("Now populating Header, The Title was: " + notraw[0][0] + " And it served: " + notraw[0][1]);
}
function populatetable() {
console.log("Now populating the table")
// Here we're gonna populate the table with data that was in the loaded array.
var arrayraw = localStorage.getItem("Recipe")
var notraw = JSON.parse(arrayraw)
if (notraw.length === 0 || notraw.length === 1) {
console.log("Array was empty.")
} else {
var count = 1;
while (count < notraw.length) {
amount = notraw[count][1] + " " + notraw[count][2]
insRow(notraw[count][0], amount)
console.log("Inserted Ingredient: " + notraw[count][0] + notraw[count][1])
count++;
}
}
}

Categories

Resources