Dynamically-changing variables random intergers - javascript

The numbers themselves aren't relevant. I have a list of variables that are used to track a moving vehicle.
UTC Time:, Latitude:, Longitude:, Speed:, Heading:, Steering:, Odometer:(PPM), GPS Status:, STWS Status:
Like i said the numbers aren't relevant, and neither is the math. I just need to simulate dynamically changing integers for each variable. For instance, Speed:25. then the 25 become a 26, then a 28, then a 15 and so on. I will implement this code, and then set the min and max for each variable.
I just need to show customers that the vehicle tracking system monitor can display changing values for each variable.
Thank you.

$("#the_span_id").text(n); and hook it up to a JavaScript timer event.

It sounds like what you need is a jQuery countdown. Take a look at this link:
http://www.tripwiremagazine.com/2011/04/9-cool-jquery-countdown-scripts.html

You could do something along the following lines:
var DynVar = {
variables: [],
timer: 0,
numIntervals: 0,
counter: 0,
updateVar: function(v) {
v.value = Math.random() * (v.max - v.min) + v.min;
},
createVar: function(name, min, max) {
var v = {"name": name, "min": min, "max": max};
DynVar.updateVar(v);
DynVar.variables.push(v);
return v;
},
update: function() {
for (i = 0; i < DynVar.variables.length; ++i) {
var v = DynVar.variables[i];
DynVar.updateVar(v);
console.log(DynVar.counter + ": " + v.name + ": " + v.value);
}
if (DynVar.counter++ >= DynVar.numIntervals) {
clearInterval(DynVar.timer);
}
},
start: function(interval, numIntervals) {
DynVar.counter = 0;
DynVar.numIntervals = numIntervals;
DynVar.timer = setInterval(DynVar.update, interval);
}
};
DynVar.createVar("speed", 10, 30);
DynVar.createVar("latitude", 20, 22);
DynVar.start(1000, 3);

Related

Optimise Round Up/Down Function

So one of our clients (an auctioneer) has a set of weird increments (also know as London increments), where essentially they don't conform to any divisible number, so using something like: Math.round(number / increment) * increment will not work.
The increments
From: 100, To: 299, Increment: 10
From: 300, To: 319, Increment: 20
From: 320, To: 379, Increment: 30
From: 380, To: 419, Increment: 20
And this kind of thing goes on.
So taking a number like: 311 should round up to 320. Now I have this code and it works fine, it also rounds up/down 321 => 350 and 363 => 380 as expected.
My concern is that it is not fast and/or sustainable and with large numbers that need to be rounded it will get slower. This function needs to be as fast as the Math.round() obviously knowing that it won't but as fast as possible. Now as much as I got it working, the way I have done it is essentially looping X amount of times (x being any number, so I have set it to 9999999, and I am hoping someone knows a better way of doing this.
// Get increment amount
window.getIncrement = (num) => {
var num = parseInt(num);
for (var i = 0; i < window.increments.length; i++) {
if (num >= parseInt(window.increments[i].from) && num <= parseInt(window.increments[i].to)) {
return parseInt(window.increments[i].increment);
}
}
}
// Get increment start value
window.getIncrementStartValue = (num) => {
var num = parseInt(num);
for (var i = 0; i < window.increments.length; i++) {
if (num >= parseInt(window.increments[i].from) && num <= parseInt(window.increments[i].to)) {
return parseInt(window.increments[i].from);
}
}
};
// Custom round up function
const roundToNearestIncrement = (increment, number, roundDown) => {
var incrementStart = parseInt(window.getIncrementStartValue(number));
var increment = parseInt(increment), number = parseInt(number);
console.log(incrementStart, increment, number);
// So now we have a start value, check the direction of flow
var lastBelow = false, firstAbove = false;
for (var i = 0; i < 9999999; i++) {
var incrementRounder = incrementStart + (increment * i);
if (incrementRounder === number) { return number; }
if (incrementRounder < number) { lastBelow = incrementRounder; }
if (incrementRounder > number) { firstAbove = incrementRounder; }
if (lastBelow !== false && firstAbove !== false) { break; }
console.log('Loop #' + i + ', Below: ' + lastBelow + ', Above: ' + firstAbove);
}
return !roundDown ? firstAbove : lastBelow;
}
Then you use it like so:
// Example usage
var num = 329;
var inc = getIncrement(num);
console.log('Rounded: ' + roundToNearestIncrement(inc, num) + ', Expected: 350');
Now as I said it works great, but my concern is that it will slow down a Node process if the number uses something large like 1,234,567, or just the highest number of that increment set, because the code will loop until it finds the above and below number, so if anyone has a better idea on how to do this that it will work but not loop?
See screenshot of the one I did before:
You can see it had to loop 1865 times before it found the above and below amounts.
Anyway, any ideas you have would be appreciated.
There are a couple of ways of making this faster
1.You can store a very big hash will all the possible values and the rounding result. This will use a lot of scape, but will be the fastest. This means that you'll a hash similar to this
rounded = []; rounded[0]=0 ... rounded[100] = rounded[101] = ... = rounded[109] = 110 ... and so on.
Of course this solution depends on the size of the table.
2.Build a binary search tree, based on the breakout points and search that tree. If the tree is balanced it will take O(log(n)) for a search.
If I understand the problem correctly:
Pre-build the array of all the thresholds, in ascending order. I imagine it'll look something like [0, 1, 2,..., 320, 350, 380, 400, 420,...];
Then the lookup will be simple:
const findNearestThreshold = (number) => thresholdsArray
.find(threshold => (threshold >= number));
A solution basing just on the increments array.
const steps = [
{ from: 100, increment: 10}, // I don't need 'to' property here
{ from: 300, increment: 20},
{ from: 320, increment: 30},
{ from: 380, increment: 20},
]
const roundUp = x => {
const tooLargeIndex = steps.findIndex(({from}) => from > x);
const { from, increment } = steps[tooLargeIndex - 1];
const difference = x - from;
return from + Math.ceil(difference / increment) * increment;
}
console.log(300, roundUp(300));
console.log(311, roundUp(311));
console.log(321, roundUp(321));

Is it possible to pass a parameter name as an argument in string form to use as parameter name in function? [duplicate]

This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 3 years ago.
I have a number of calls to the same function where I am passing objects as well as specific object parameters as arguments. I've had no issue passing the object alone or passing an object parameter in the form object.param. However, I would also like to pass the object name and the parameter name as separate arguments so that I can combine them freely in the function. However, I can't figure out the syntax (or if my idea is supported).
The primary question is is my syntax correct: foo(param) and this[objectName].param?
My simple example below seems to work on playcode.io, but the same principle isn't working in my primary code.
Here is the simple version of the code:
var options = {
bar: 0
};
foo('bar'); // parameter name as string
function foo(param) {
var objectName = "options";
this[objectName].param = 2; // assembling object name with parameter name as string here
console.log('param = ' + this[objectName].param)
}
UPDATE: Here is an example of the working code using #CertainPerformance suggesting of not using .this.
const optionNames = {
optionsA: {
startMin: 3
},
// other option names
};
const constObjectNames = {
optionsConstA: {
maxVolume: 1
// etc
}
// other const object names
};
var objectName = "optionsA";
var constObjectName = "optionsConstA";
function callCalculateNewValue(optionName, constOptionName) {
var param = optionName;
return param;
}
foo('startMin');
function foo(param) {
optionNames[objectName][param] = callCalculateNewValue(optionNames[objectName][param], constObjectNames[constObjectName]);
console.log('= ' + optionNames[objectName][param]);
}
Here is my actual code for context The ridiculously named function callCallCalculateNewValue is the one in question:
function getRandom(min, max) { // returns a random number between min and max (both included)
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function valBetween(v, min, max) { // current value, min/max that I want to make sure v doesn't go under/over
return (Math.min(max, Math.max(min, v)));
}
var optionsConstA = {
// not recalculating each stage
soundFileName: 'audio/60.wav',
maxVolume: 1,
startMinSeparation: 1000, // the minimum distance appart the min/max values can be
slaveStatusMin: 'master',
minSeparation: 1000,
// recalculating each stage
startMin: 1050, // min time function waits before a sound is played
startMax: 8000, // max time function waits before a sound is played
playDurationMin: 15000, // min play time for each sound
playDurationMax: 20000, // max play time for each sound
fadeInMin: 10, // for individual sounds
fadeInMax: 8000, // for individual sounds
fadeOutMin: 8000, // for individual sounds
fadeOutMax: 8000, // for individual sounds
chanceRandomMin: 90, // values below the result won't be random, so for less chance variables are random, make min/max high
chanceRandomMax: 99, // values below the result won't be random
rampMin: 0,
rampMax: 4,
rampVolumeMin: 0, // number of stages the sounds will be faded in (total volume at each stage will be reduced by a percentage)
rampVolumeMax: 4,
volatilityMin: 1, // result is multiplied by CalculatedChange. ## This should possibly be unique for each parameter pair, though it is now calculating randomly within these values.
volatilityMax: 1 // result is multiplied by CalculatedChange
};
var optionsA = {
startMin: 0,
startMax: 0
};
function calculateNewValue(oldValue, min, max, volatilityMin, volatilityMax, slaveStatus, chanceRandomMin, chanceRandomMax, minSeparation, newMasterValue) {
var randomThreshold = getRandom(chanceRandomMin, chanceRandomMax);
var randomValue = getRandom(0, 100); // random number used against the threshold to see if the paramater should be reandomly determined
console.log("random value: " + randomValue) // the random number between 0-100 that if > the threshold value, it will use the random function
if (randomValue > randomThreshold || oldValue == 0) { // if random = yes OR if the oldValue is 0 (which would mean that it's the very first tiem the function is being called and this will keep it from getting stuck near the Min value to start) parameter is determined randomly
newValue = getRandom(min, max); // yes, it's random, so move randomly not incrementally from old value
console.log('Was random: ' + newValue)
}
else { // if not random, determine its move from oldValue
var changeLimit = (max - min) * .1; // ## I'm setting the max possible incremental move at a pecentage (e.g., 10%) of difference betten max and min value. I can make this more detailed per parameter later. Maybe send a percentage artument along.
var calculatedChange = getRandom(-changeLimit, changeLimit); // determines base value for parameter change (aka, change from oldValue)
console.log('Calculated change: ' + calculatedChange)
var volatility = getRandom(volatilityMin, volatilityMax); // # I should refine volatility's relationship with calculatedChange
newValue = valBetween(oldValue + (calculatedChange * volatility), min, max); // make sure calculatedChange can be negative
}
if (slaveStatus == 'master') {
newValue = valBetween(newValue, min, max - minSeparation); // if master (aka Min value), make sure Min is not so large that it doesn't have room for minSeparation (if it is added to Max)
}
if (slaveStatus !== 'master') { // now that the the value is determined, if you are a slave (aka a Max value which goes second), make sure you are >= to your master
if (newValue < newMasterValue) { // if newValue is less than the calculated value of its min/max counterpart...
newValue = newMasterValue;
}
if (newValue - newMasterValue < minSeparation) { // i.e, there isn't enough separation between the Max value and the newly defined Min Value
newValue = newValue + (minSeparation - (newValue - newMasterValue)); // adds needed separation value
console.log('Max: Separation added')
}
}
return newValue;
}
function callCalculateNewValue(objectName, constObjectName) {
objectName = calculateNewValue(constObjectName.startMin, constObjectName.startMin, constObjectName.startMax, constObjectName.volatilityMin, constObjectName.volatilityMax, constObjectName.slaveStatusMin, constObjectName.chanceRandomMin, constObjectName.chanceRandomMax, constObjectName.minSeparation);
return objectName;
}
var masterLoopStage = 0;
var calc = (function masterLoop(i) {
setTimeout(function () {
++i;
masterLoopStage = i;
console.log('masterLoopStage is: ' + i);
callCallCalculateNewValue('startMin');
function callCallCalculateNewValue(param) {
var objectName = "optionsA";
var constObjectName = "optionsConstA";
this[objectName].param = callCalculateNewValue(this[objectName].param, this[constObjectName]);
console.log('optionsA.startMin: ' + this[objectName].param)
}
optionsA.startMax = calculateNewValue(optionsA.startMax, optionsConstA.startMin, optionsConstA.startMax, optionsConstA.volatilityMin, optionsConstA.volatilityMax, optionsConstA.startMin, optionsConstA.chanceRandomMin, optionsConstA.chanceRandomMax, optionsConstA.minSeparation, optionsA.startMin);
console.log('Min: ' + optionsA.startMin);
console.log('Max: ' + optionsA.startMax);
console.log('______________');
/////////////////
masterLoop(i);
}, 3000) // time between increments
})(1);
console.log('____________');
console.log('Min: ' + optionsA.startMin);
console.log('Max: ' + optionsA.startMax);
With your current setup, it's not possible without eval, which should not be used - however, if you change around the data structure so that everything that can be an objectName is a property of a larger object, rather than a standalone variable (and do the same for the dynamic constObjectName), it would be doable. For example:
const optionNames = {
optionsA: {
startMin: 0,
startMax: 0
},
// other option names
};
const constObjectNames = {
optionsConstA: {
soundFileName: 'audio/60.wav',
maxVolume: 1,
// etc
}
// other const object names
};
Then, you can use ordinary bracket notation, just like your foo function in the first snippet is doing. Your param also contains a string which is the property name you want to access, so you need to use bracket notation when using param too, eg [param] rather than .param. In full:
const optionNames = {
optionsA: {
startMin: 1,
},
// other option names
};
const constObjectNames = {
optionsConstA: {
startMinB: 1,
}
// other const object names
};
function calculate(optionName, constOptionName) {
var value = optionName + constOptionName.startMinB;
return value;
}
foo('startMin'); // I'm still not sure what the syntax is for passing parameter name, or if I can
function foo(param) {
var objectName = "optionsA";
var constObjectName = "optionsConstA";
optionNames[objectName][param] = calculate(optionNames[objectName][param], constObjectNames[constObjectName]);
console.log('= ' + optionNames[objectName][param])
}
Your use of this will only work if the code in question is operating on the top level, which is not a good idea to depend on (you'd be polluting the global scope unnecessarily).

Whats wrong with my javascript Object?

I have a javascript "object." Im using the word object to make things easier. Which is here:
var character = {
name: "",
myClass: "",
health: 20,
maxHealth: 20,
};
Say i have a game, and the game has fights, and after each fight you gain a health point. which is done with:
character.maxHealth += 1;
However... When i tried to do this, i ended up getting 201 as the maxHealth or 2032 or 203232 or whatever number i wanted to add to the max health was just adding as if it was a string. through my eyes in looks like an integer to me but i must be mistaken. if anyone can give me a hand it would be really appreciated. That is an example of what i have. the actual code is:
var character = {
name: "",
myClass: "",
health: 20,
maxHealth: 20,
stamina: 10,
maxStamina: 10,
mana: 5,
maxMana: 5,
physStrength: 3,
minAttack: 0,
mentStrength: 3,
physDefense: 3,
mentDefense: 3,
exp: 0,
punch: function() {
toggleAttackButtons(0);
this.minAttack = this.physStrength/3;
var damage = Math.floor(Math.random() * this.physStrength) + this.minAttack;
addString("You punched and did " + damage + " damage.");
myEnemy.health -= damage;
updateStats();
setTimeout(function(){
myEnemy.attack();
toggleAttackButtons(1);
updateStats();
}, 1000);
},
kick: function(){
toggleAttackButtons(0);
this.minAttack = this.physStrength/3;
var damage = Math.floor(Math.random() * this.physStrength) + this.minAttack;
addString("You kicked and did " + damage + " damage.");
myEnemy.health -= damage
updateStats();
setTimeout(function(){
myEnemy.attack();
toggleAttackButtons(1);
updateStats();
}, 1000);
},
};
and this is where im incrementing the number:
var updateStats = function() {
document.getElementById("charHealth").innerHTML = "Health: " + character.health + " / " + character.maxHealth;
document.getElementById("enemHealth").innerHTML = "Health: " + myEnemy.health + " / " + myEnemy.maxHealth;
if(myEnemy.health <= 0){
myEnemy.health = 0;
character.maxHealth += 1;
removeFightScreen(1);
}
if(character.health <= 0){
removeFightScreen(2);
}
};
I understand the object is messy i plan on rewriting it in the future to be a lot more efficient. im just roughing it up right now.
I found myself the answer. Im sorry for my lack of code evidence, however it contains cookies, so when i write the cookies using the character stats like health and maxHealth, they end up being converted into strings to fit the cookie. Therefore i need to convert them back to integers. thank you guys for your help. Next time i will add in all the code i just felt that being there was several hundred lines of code i didnt want to go through it all.

How to calculate interest javascript

I'm trying to create a function that returns the money I have after x years of interest.
var calculateInterest = function(total, year, rate) {
(var interest = rate / 100 + 1;
return parseFloat((total * Math.pow(interest, year)).toFixed(4))
}
console.log(calculateInterest(915, 13, 2));
I'm not getting it to work and I'm stuck!
Any advice?
You were close. You don't need parentheses around var interest:
var calculateInterest = function(total, year, rate) {
var interest = rate / 100 + 1;
return parseFloat((total * Math.pow(interest, year)).toFixed(4));
}
var answer = calculateInterest(915, 13, 2);
console.log(answer);
I'd recommend cleaning it up a little to:
var calculateInterest = function(total, years, ratePercent, roundToPlaces) {
var interestRate = ((ratePercent / 100) + 1);
return (total * Math.pow(interestRate, years)).toFixed(roundToPlaces);
}
var answer = calculateInterest(915, 13, 2, 2);
console.log(answer);
You don't need parseFloat() if the variable is already a number (it's needed when you're parsing from a string, which is not the case here). I am adding a parameter to specify how many decimal places to round to is useful so you can control the output of the function.
Updated fiddle

Adding color to the max value in a dynamically generated chart?

The jsfiddle link is here http://jsfiddle.net/MzQE8/110/
The problem here I feel is in my JavaScript.
I input values to the series object in a HighChart from an array. On the array I am trying to find index and the value of the maximum element and then I am saving the maximum array element back with this modification
yArr[index] = {
y: value,
color: '#aaff99'
};
So that It appears as a diferent color from the rest of the points on the graph which is a dynamic one. That is its sliding one.
Here is my code
$(function () {
$(document).ready(function () {
Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart;
$('#container').highcharts({
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
//As this graph is generated due to random values. I am creating an Array with random values.
var yArr = [];
yArr[0] = Math.random();
yArr[1] = Math.random();
yArr[2] = Math.random();
yArr[3] = Math.random();
setInterval(function () {
console.log(yArr.length);
var x = (new Date()).getTime(), // current time
y = Math.random();
var index = findIndexOfGreatest(yArr);
var value = yArr[index];
yArr[index] = {
y: value,
color: '#aaff99'
};
series.addPoint([x, yArr.shift()], true, true);
yArr.push(Math.random());
}, 1000);
}
}
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 450
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
plotOptions: {
series: {
lineWidth: 1
}
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' + Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' + Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Random Data',
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i++) {
data.push({
x: time + i * 1000,
y: yArr.shift()
});
}
return data;
})(),
color: 'red'
}]
});
});
function findIndexOfGreatest(array) {
var greatest;
var indexOfGreatest;
for (var i = 0; i < array.length; i++) {
if (!greatest || array[i] > greatest) {
greatest = array[i];
indexOfGreatest = i;
}
}
return indexOfGreatest;
}
});
I feel my idea is correct but there are big holes in my implementation. I guess.
Thanks
See demo: http://jsfiddle.net/MzQE8/350/
All y-values are stored in series.yData, so you don't have to create another array for that. Now just update point which is the highest one, and add new points. Something like above demo, code:
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0],
index = series.yData.indexOf(series.yData.max());
// mark first max points
this.series[0].prevMax = this.series[0].data[index];
this.series[0].prevMax.update({
color: '#aaff99'
});
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.random(),
color = null,
index, max;
if (series.prevMax && series.prevMax.update) {
// remove previously colored point
if (y > series.prevMax.y) {
series.prevMax.update({
color: null
}, false);
color = '#aaff99';
// store max, which is last point
series.prevMax = series.data[series.yData.length];
}
} else {
max = series.yData.max();
index = series.yData.indexOf(max);
if(y > max) {
color = '#aaff99';
series.prevMax = series.data[series.yData.length];
} else {
series.prevMax = series.data[index];
series.prevMax.update({
color: '#aaff99'
}, false)
}
}
// add new point
series.addPoint({
x: x,
y: y,
color: color
}, true, true);
}, 1000);
}
}
im not to sure what your seeking but if i understand correctly you want the bullet marks to be a different color to differentiate from the others. i wont include source code because what you have included in your js fiddle is pretty advanced stuff and you will be able to figure this out no problem.
calculate (all total values added together / 256 + i) * 255 (or something similar)
the i represents the bullet increment in a loop. please for give the algorithm i haven't slept in 32 hours and i know its def. suggested you check it.
Oh.. kay here is the updated solution working out on paper
http://i966.photobucket.com/albums/ae147/Richard_Grant/Untitled-1_zps7766a939.png
I PUT A LOT OF WORK INTO THIS! so please!!! use it well -.-'
What is happening here is i drew out a graph with values going from 0 - 200 and i labeled the graph results 1 - 4, i also made this the x coordinates cause im lazy.
In the workflow RES = means results or X, Val = Value or Y
These are used to calculate RGB values and i solved the first 3 results. the first result tangent should always be 0 because any number divisible by 0 is 0, and any number multiplied by 0 is 0.
When i say tangent i mean the angle of the point by the 200, 0 value (invisible point). in this formula the angle would not be perfected because the x and y on the graph are not equal, one is 200 max and the other is 4 max. if i wanted this to be accurate i would have turned the tangent into a percent and multiplied it by 255. but i didn't.
I feel i have given you the necessary tools to complete your request on your own now :) if you do not understand how i did this or found this algorithm, just fall back to random colors.
Thanks John doe, your question helped me. This is the function i used to change the color of the maximum value of my y axis:
function () {
var maximum = chart.yAxis[0].dataMax;
var index = series.yData.indexOf(maximum);
chart.series[0].data[index].update({ color: '#aaff99' });
}
It may help other people too.

Categories