how to add a localstorage for my Calculator? - javascript

I have to work on a calculator. I got everything i need. The only thing is, I have to add a LocalStorage under my Result. So the Calculator adds everytime the result, untill i delete the session.
For example:
"1+1=2," 2*2=4, 8/8=1
Localstorage: 2,4,1
function clear()
{
number1.value = "";
number2.value = "";
}
function clearresult()
{
result.innerText = '';
}
function calc()
{
var number1 = parseFloat(document.getElementById('number1').value);
var number2 = parseFloat(document.getElementById('number2').value);
var oper = document.getElementById('operators').value;
if ( !isNaN(number1) && !isNaN(number2) )
{
if ( oper === '+' )
{
result.innerText = document.getElementById('result').value = parseFloat(number1) + parseFloat(number2);
}
if ( oper === '-' )
{
result.innerText = document.getElementById('result').value = parseFloat(number1) - parseFloat(number2);
}
if ( oper === '/' && number1 )
{
result.innerText = document.getElementById('result').value = parseFloat(number1) / parseFloat(number2);
}
if ( oper === '*' )
{
result.innerText = document.getElementById('result').value = parseFloat(number1) * parseFloat(number2);
}
clear();
for (var i = 0; i < localStorage.length; i++)
{
localStorage.setItem('resultstorage', result.innerText);
output.innerText = localStorage.getItem('resultstorage');
}
}
else
{
alert("Es wurden keine Zahlen eingegeben!");
clear();
clearresult();
}
}

*store your result in array and store that array in localstorage as mentioned below
let itemsArray = []
localStorage.setItem('items', JSON.stringify(itemsArray))
const data = JSON.parse(localStorage.getItem('items'))
putting new result in array
itemsArray.push(input.value)
localStorage.setItem('items', JSON.stringify(itemsArray))
remove array from local storage
localStorage.clear()

I think the solution below will go a long way into helping you out
- The use of default variables may make code verbose, remove at wish.
// saves the result and update DOM with it accordingly
const saveResult = function (result, storageName = 'resultstorage') {
let store = []
store.push(result)
localStorage.setItem(storageName, JSON.stringify(store))
// update DOM with value
getResult()
}
// using try-catch statement ensures we did not get an error
// if - say no value is in the localStorage
// And it can enable us to retrieve the last result in memory on page-load
// if peradventure we exited the browser without removing the item from localStorage
// i.e we can call getResult() without error
const getResult = function (storageName = 'resultstorage') {
let result;
try {
result = JSON.parse(localStorage.getItem(storageName))
document.querySelector('#output').innerHTML = result
} catch (err) {}
}
// we use **remove** not **clear** and the storage name
// to avoid removing other values unintended
const removeResult = (storageName = 'resultstorage') => localStorage.removeItem(storageName)
// usage
let value = 23
saveResult(value)

Related

neural network backprop algorithm implementation question

I've been writing a neural network from scratch to learn from.
but since i'm still learning - I want to make sure what I'm writing is actually correct.
I have an array of arrays (a matrix), of cell objects. attached to a 'brain' object which has the following method two methods:
train: function(data)
{
for (let b=0; b< data.length; b++)// for the length of the training data - I.E. we are going assume we are getting many relatively shortly indexed arrays
{
if(data[b].answers.length != data[b].questions.length)
{
console.log("bad data");
return false;
}
for(let c=0;c<data[b].questions.length;c++)
{
brain.attachInputLayer(data[b].questions[c]);
brain.updateForward();
let direction = brain.determinDirection(data[b].answers[c]); //return an array of updateObject with determined weights bias value adjustments, which each cell gets updated order should be from generation by column;
brain.cellMatrix.forEach(cellArray=> cellArray.forEach(cell=> cell.adjust(direction.find(x=> x.ID ===cell.ID))));
brain.updateForward();
brain.displayBrain();
}
}
console.log("all training data done");
alert("win?");
console.log(brain.cellMatrix);
console.log("brain");
}
and
determinDirection:function(answer)
{
// answer is the array of values of each answer cell we want as a result
let arrayOfUpDateObjectsForCell = [];
for(let e=0; e<answer.length; e++)
{
let answerCell = brain.cellMatrix[cellMatrix.length-1][e];
let returnBucket = [];
arrayOfUpDateObjectsForCell.push(answerCell.whatIwant(answer[e], returnBucket));
}
let list = Flat(arrayOfUpDateObjectsForCell);
let realList = Clean(list);
return realList;
}
so each cell of the last generation (the answer output) calls the whatIwant method at brain.train(), this function propagates backwards through the network... but my question really is this:::
:::
does it look like I am calculating the error / direction to move each value correctly?
is averaging the changes between the duplicated updateObjects correct?
(the desiredObjectchange for cell.gen=3,order=0 gets created from each of the next layer cells calling whatIwant. the changes cell.gen=4,order=0 wants cell.gen=3,order=0 to have is averaged with the changes cell.gen=4,order=1 wants for cell.gen=3,order=0).
is averaging the correct operation here?
:::
whatIwant:function(answerValue, returnArray)
{
let desiredWeights = this.weights;
let desiredBias = this.bias;
let desiredActivations = this.activations;
let error = (1/2)*Math.pow(cell.value-answerValue,2);
let desiredObjectChange =
{
ID:this.ID,
weights:this.weights,
bias:this.bias,
activations:this.activations,
value:answerValue,
combine:function(yourCloneFriend)
{
if(yourCloneFriend == false)
{
return;
}
this.bias = (1/2)*(this.bias+yourCloneFriend.bias);
let cWeight = yourCloneFriend.weights[Symbol.iterator]();
let cActivations = yourCloneFriend.activations[Symbol.iterator]();
this.weights.forEach(x=> (1/2)*(x+cWeight.next().value));
this.activations.forEach(y=> (1/2)*(y+cActivations.next().value));
this.recalculateValue();
return this;
},
recalculateValue:function()
{
this.value = Sigmoid(arrayMultiply(this.weights, this.activations)+this.bias);
}
}
for(let k = 0; k< this.weights.length; k++)
{
let lastValue = Sigmoid(arrayMultiply(desiredWeights, desiredActivations)+desiredBias);
let lastError = (1/2)*Math.pow(lastValue-answerValue,2);
for(let l=0;l<3;l++)
{
let currentValue = Sigmoid(arrayMultiply(desiredObjectChange.weights, desiredObjectChange.activations)+desiredObjectChange.bias);
let currentError = (1/2)*Math.pow(currentValue-answerValue,2);
let positiveRange = false;
if(desiredWeights[k] < 0){ positiveRange = true;}
let nudgedWeightArray = NudgeArray(desiredWeights, k, l, positiveRange); //returns a copy array to test, with weight adjusted.
let testWeightChange = Sigmoid(arrayMultiply(nudgedWeightArray,desiredActivations)+desiredBias);
let testWeightError = (1/nudgedWeightArray.length)*Math.pow(testWeightChange - answerValue, 2);
let testWeightResult = compareSmallnumbers('isSmaller', currentError, testWeightError);
if(testWeightResult);
{
desiredWeights = nudgedWeightArray;
currentError = testWeightError;
}
positiveRange=false;
if(desiredBias < 0){positiveRange = true;}
let nudgedBiasVal = this.nudge(desiredBias,l,positiveRange);
let testBiasChange = Sigmoid(nudgedBiasVal+desiredWeights[k]*desiredActivations[k]);
let testBiasError = (1/1)*Math.pow(testBiasChange - answerValue, 2);
let testBiastResult = ('isSmaller', currentError, testBiasError);
if(testBiastResult);
{
desiredBias = nudgedBiasVal;
currentError = testBiasError;
}
positiveRange=!!Math.random(0,1)>5;
let nudgedAcitivationArray = NudgeArray(desiredActivations,k,l,positiveRange);
let testActivationChange = Sigmoid(arrayMultiply(nudgedAcitivationArray,desiredWeights)+desiredBias);
let testActivationError = (1/nudgedAcitivationArray.length)*Math.pow(testActivationChange - answerValue, 2);
let testActivationResult = compareSmallnumbers('isSmaller', currentError, testActivationError);
if(testActivationResult);
{
desiredActivations[k] = nudgedAcitivationArray[k];
currentError = testActivationError;
}
//and the end of the loop, update the error to the new value
let errorResult = compareSmallnumbers('isSmaller',lastError, currentError);
if(errorResult)
{
lastError = currentError;
}
}
desiredObjectChange.weights[k] = desiredWeights[k];
desiredObjectChange.bias = desiredBias;
desiredObjectChange.activations[k] = desiredActivations[k];
desiredObjectChange.value = Sigmoid(arrayMultiply(desiredObjectChange.weights, desiredObjectChange.activations)+desiredObjectChange.bias);
}
let combineObject = returnArray.find(x=>x.ID === desiredObjectChange.ID);
if(!combineObject)
{
returnArray.push(desiredObjectChange);
}
//that was this object - simple stuff, now we need to call this function
if(Array.isArray(cell.lastGenerationTargetKeys) && cell.lastGenerationTargetKeys.length)
{
let nextActivation = desiredObjectChange.activations[Symbol.iterator]();
brain.cellMatrix[cell.generation-1].forEach(x=> x.whatIwant(nextActivation.next().value, returnArray));
return returnArray;
}
else
{
return;
}
},
clean,flat and NudgeArray are these::
function Clean(array)
{
let rArray = [];
array.forEach((x)=>
{
let search = rArray.find(y=>y.ID ===x.ID);
if(search === undefined)
{
rArray.push(x);
}
else
{
rArray[rArray.indexOf(search)].combine(x);
}
});
return rArray;
}
function Flat(array)
{
let holdBucket = [];
let flatten = function(array)
{
for(let i = 0; i<array.length;i++)
{
if(Array.isArray(array[i]))
{
flatten(array[i]);
}
else
{
holdBucket.push(array[i]);
}
}
}
flatten(array);
return holdBucket;
}
function NudgeArray(array ,arrayIndex, Nudgeindex, isPositive)
{//nudge index is designed to act like a variable learning rate modifier, as it tests, jumps decrease in size
let returnArray = [];
array.forEach(x=>returnArray.push(x));
let value = returnArray[arrayIndex];
if(isPositive)
{
value+=(Math.random(0,1)/(Nudgeindex+3));
value = Sigmoid(value);
}
else
{
value+=(Math.random(-1,1)/(Nudgeindex+3));
value = Sigmoid(value);
}
returnArray.splice(arrayIndex,1,value);
return returnArray;
}

I cannot get my map to print is value outside of the function

I am trying to access the values of the map outside of the function getbetlist like do a console.log(bettingPool) outside of that function but whenever I do that it just prints {}. However inside the function getbetlist it prints the correct output.
I have tried changing the varible types, setting the var, creating a new var and resetting it and nothing has worked thus far.
var db = firebase.firestore();
var bettingPool = {}
var marketSplit = {}
var weightedMarketSplit = {}
var msToNextDay = 0;
var test;
async function startNewGame() {
await getBetList();
var now = new Date();
var nextDay = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate() + 1,
7, 59, 59
);
test();
msToNextDay = nextDay.getTime() - now.getTime();
// console.log(msToNextDay)
// bettingPool = {}
// marketSplit = {}
// weightedMarketSplit = {}
// setTimeout(startNewGame(), msToNextDay);
}
startNewGame();
async function getBetList() {
console.log("inside getBetList")
const users = []
const accuracy = []
db.collection('Bets').get().then(
function (querySnapshot) {
querySnapshot.forEach(
function (doc) {
doc.data().userDoc.onSnapshot(docSnapshot => {
/* Betting Pool Split
bettingPool - By Money
marketSplit - By Users
weightedMarketSplit - By users * accuracy
*/
if (!bettingPool[doc.data()['stockId']]) {
bettingPool[doc.data()['stockId']] = {}
marketSplit[doc.data()['stockId']] = {}
weightedMarketSplit[doc.data()['stockId']] = {}
}
if (doc.data()['direction'] == 'Up') {
if (!bettingPool[doc.data()['stockId']].Up) {
bettingPool[doc.data()['stockId']].Up = 0.0
marketSplit[doc.data()['stockId']].Up = 0
weightedMarketSplit[doc.data()['stockId']].Up = 0.0
}
marketSplit[doc.data()['stockId']].Up += 1
bettingPool[doc.data()['stockId']].Up += Number(doc.data()['bet'])
weightedMarketSplit[doc.data()['stockId']].Up += (docSnapshot.data()['accuracy'])
}
else if (doc.data()['direction'] == 'Down') {
if (!bettingPool[doc.data()['stockId']].Down) {
bettingPool[doc.data()['stockId']].Down = 0.0
marketSplit[doc.data()['stockId']].Down = 0
weightedMarketSplit[doc.data()['stockId']].Down = 0.0
}
marketSplit[doc.data()['stockId']].Down += 1
bettingPool[doc.data()['stockId']].Down += Number(doc.data()['bet'])
weightedMarketSplit[doc.data()['stockId']].Down += (docSnapshot.data()['accuracy'])
}
test = bettingPool;
})
}
)
}
)
// for (var user of users) {
// db.collection("Users").doc('' + user).onSnapshot(querySnapshot => {
// // if(querySnapshot.data()['accuracy']) {
// // accuracy.push(querySnapshot.data()['accuracy'])
// // }
// // else {
// // accuracy.push(0.5);
// // }
// // console.log(querySnapshot.data())
// })
// }
}
It's kind of funky code to modify a global object inside a function, for multiple reasons. Especially because the function is called "getBetList" but it doesnt get anything, it just updates a variable somewhere else. Its much cleaner to do something like
const bettingPool = await getBetList()
And have getBetList return the betList.
This should also fix your problem.

Undefined Element displayed with JavaScript

I am able to display the sum value of 6 DOM elements with a "line_cost" tag name- this is displayed as a sub-total(seen as "ST" methods). Unfortunately, while dynamically calculating the delivery-cost using the sub-total values, I consistently get "undefined" as a value being displayed under the delivery-cost tab while sub-total works perfectly.
I thought to believe the problem was occurring due to the DOM not fully loading before the method was called, yet even with the decision if(document.getElementById("sub_total") != null), I still achieve an 'undefined' value. What could be the problem for this 'undefined' value occurring?
function calcST()
{
var i;
var sum = 0; // initialize the sum
let p = document.getElementsByTagName("line_cost");
for (i = 0; i < p.length; i++)
{
if (!isNaN(Number(p[i].innerHTML)))
{
sum = Number(sum + Number(p[i].innerHTML)); // p[i].innerHTML gives you the value
}
}
setST(sum, "sub_total");
}
function setST(sum, item_id)
{
let i = document.getElementById(item_id);
i.innerHTML = sum;
calcDelivCharge();
}
function getST()
{
if (document.getElementById("sub_total") != null)
{
let i = document.getElementById("sub_total");
let v = i.innerHTML;
return v;
}
}
function calcDelivCharge()
{
var delCharge;
var e = getST();
if (e < 100)
{
delcharge = e*0.10
}
else
{
delcharge = 0;
}
setDelivCharge("delivery_charge", delCharge);
}
function setDelivCharge(item_id, delCharge)
{
let i = document.getElementById(item_id);
i.innerHTML = delCharge;
calculateTAX();
}
function getDelivCharge()
{
let i = document.getElementById("delivery_charge");
let v = i.innerHTML;
return v;
}

How to pass an array from one function to another as reference in Cloud Function

I have one function getUsers where I have one array jsonResponse. I am passing that array to computeData function. I want computeData function should be able to add items in jsonResponse array itself.
But below code is not adding in same array, as it always return empty array in response.send function.
index.js
exports.getUsers = functions.https.onRequest((request, response) => {
var x = [];
var xLocation,
yLocation = [],
jsonResponse = [];
// print algorithm name
console.log(request.query.algo);
let geoFire = new GeoFire(db.ref("/users/" + request.query.userId));
geoFire.get("location").then(function(location) {
xLocation = location;
});
db
.ref("/users/" + request.query.userId)
.once("value")
.then(function(snapshot) {
var jsonObject = snapshot.val();
var basicProfileJsonObject = jsonObject.basicProfile;
for (var key in basicProfileJsonObject) {
if (utils.isNumber(basicProfileJsonObject[key])) {
x.push(basicProfileJsonObject[key]);
}
}
db.ref("/users/").once("value").then(function(snapshot) {
var y = [];
snapshot.forEach(function(item) {
var user = item.val();
let userId = user.basicProfile.userId;
if (userId !== request.query.userId) {
if (xLocation == null) {
computeData(x, user, request.query.algo, jsonResponse);
} else {
let geoFire = new GeoFire(db.ref("/users/" + userId));
geoFire.get("location").then(function(location) {
if (location === null) {
console.log(
"Provided key is not in GeoFire, will ignore profile"
);
computeData(x, user, request.query.algo, jsonResponse);
} else {
console.log("Provided key has a location of " + location);
var distance = GeoFire.distance(xLocation, location); // in km
console.log("Distance: " + distance);
if (distance < 15) {
computeData(x, user, request.query.algo, jsonResponse);
}
}
});
}
}
});
response.send(jsonResponse);
});
});
});
function computeData(x, user, algo, jsonResponse) {
var similarityCount,
y = [];
var basicProfileJsonObject = user.basicProfile;
for (var key in basicProfileJsonObject) {
if (utils.isNumber(basicProfileJsonObject[key])) {
y.push(basicProfileJsonObject[key]);
}
}
if (algo === "cosine") {
// compute cosine value
similarityCount = cosineUtils.cosineSimilarity(x, y);
} else if (algo == "euclidean") {
// compute euclidean distance value
similarityCount = 1 / (1 + euclidean(x, y));
} else if (algo === "pearson-correlation") {
// compute pearson correlation coefficents
similarityCount = pcorr.pearsonCorrelation(x, y);
}
console.log(x);
console.log(y);
console.log(similarityCount);
jsonResponse.push(user);
}
Does anyone know how to pass array as reference and add items into it in Cloud Function for Firebase ?
Your else statement is a promise which means your loop would have finished and called response.send(jsonResponse); by the time it gets to computeData() in your else statement.
Try something like this, it doesn't touch all your variables but the main idea is to use Promise.all with computed values as resolved -
exports.getUsers = functions.https.onRequest((request, response) => {
// blah blah
var y = []; // store promises that resolves your computed value
snapshot.forEach(function(item) {
// blah blah
if (xLocation == null) {
y.push(Promise.resolve(computeData());
} else {
y.push(computeAnotherData(userId));
}
});
Promise.all(y)
.then(values => {
response.send(values);
});
});
function computeAnotherData(userId) {
let geoFire = new GeoFire(db.ref("/users/" + userId));
return geoFire.get("location").then(function(location) {
return computeData();
});
}
Hope it makes sense.

Extend Javascript Syntax to Add Typing

I'd like to extend javascript to add custom type checking.
e.g.
function test(welcome:string, num:integer:non-zero) {
console.log(welcome + num)
}
which would compile into:
function test(welcome, num) {
if(Object.prototype.toString.call(welcome) !== "[object String]") {
throw new Error('welcome must be a string')
}
if (!Number.isInteger(num)) {
throw new Error('num must be an integer')
}
console.log(welcome + num)
}
What's the most straightforward way of doing this?
So far i've looked at:
sweet.js (online documentation looks out of date as I think it's going through some sort of internal rewrite)
esprima and escodegen (not sure where to start)
manually parsing using regular expressons
After evaluating all the various options, using sweet.js appears to be the best solution. It's still fairly difficult to get working (and I am probably doing stuff the wrong way) but just in case someone want's to do something similar this here was my solution.
'use strict'
syntax function = function(ctx) {
let funcName = ctx.next().value;
let funcParams = ctx.next().value;
let funcBody = ctx.next().value;
//produce the normal params array
var normalParams = produceNormalParams(funcParams)
//produce the checks
var paramChecks = produceParamChecks(funcParams)
//produce the original funcBody code
//put them together as the final result
var params = ctx.contextify(funcParams)
var paramsArray = []
for (let stx of params) {
paramsArray.push(stx)
}
var inner = #``
var innerStuff = ctx.contextify(funcBody)
for (let item of innerStuff) {
inner = inner.concat(#`${item}`)
}
var result = #`function ${funcName} ${normalParams} {
${paramChecks}
${inner}
}`
return result
function extractParamsAndParamChecks(paramsToken) {
var paramsContext = ctx.contextify(paramsToken)
//extracts the actual parameters
var paramsArray = []
var i = 0;
var firstItembyComma = true
for (let paramItem of paramsContext) {
if (firstItembyComma) {
paramsArray.push({
param: paramItem,
checks: []
})
firstItembyComma = false
}
if (paramItem.value.token.value === ',') {
firstItembyComma = true
i++
} else {
paramsArray[i].checks.push(paramItem.value.token.value)
}
}
for (var i = 0; i < paramsArray.length; i++) {
var checks = paramsArray[i].checks.join('').split(':')
checks.splice(0, 1)
paramsArray[i].checks = checks
}
return paramsArray
}
function produceNormalParams(paramsToken) {
var paramsArray = extractParamsAndParamChecks(paramsToken)
//Produces the final params #string
var inner = #``
var first = true
for (let item of paramsArray) {
if (first === true) {
inner = inner.concat(#`${item.param}`)
} else {
inner = inner.concat(#`,${item.param}`)
}
}
return #`(${inner})`
}
function produceParamChecks(paramsToken) {
var paramsArray = extractParamsAndParamChecks(paramsToken)
var result = #``
for (let paramObject of paramsArray) {
var tests = produceChecks(paramObject)
result = result.concat(#`${tests}`)
}
return result
}
function produceChecks(paramObject) {
var paramToken = paramObject.param
var itemType = paramObject.checks[0]
var checks = paramObject.checks
if (itemType === undefined) return #``
if (itemType === 'array') {
return #`if (Object.prototype.toString.call(${paramToken}) !== "[object Array]") throw new Error('Must be array:' + ${paramToken})`
else {
throw new Error('item type not recognised: ' + itemType)
}
}
}

Categories