let's say I have two values: 600 & 470
What I'm trying to do is specify a set of time, let's say 0 and 100 (4 seconds if 25fps) and then get the 'tween' values for each 'frame'.
var base = 600;
var target = 470;
var start = 0;
var end = 100;
var values = [];
for (var i = start; i < end; i++) {
// not sure where to begin with the math here
// so i'll just asssign it to i, but obviously it's wrong
var value = i;
values.push(value);
}
// Once complete, id expect:
// values[0] === 600;
// values[99] === 470;
How can I achieve this?
Calculate the increment (between each item in the array), and then you can create the array all at once by mapping each i to base + increment * i:
const base = 600;
const target = 470;
const start = 0;
const end = 100;
const increment = (target - base) / (end - start - 1);
const values = Array.from(
{ length: end - start },
(_, i) => base + increment * i
);
console.log(values[0]);
console.log(values[99]);
console.log(values);
I made an easy solution to this question.
Two variable added:
difference
rate
The base value minus rated differences to get step values.
var base = 600;
var target = 470;
var start = 0;
var end = 100;
var values = [];
var difference = base-target;
for (var i = start; i < end; i++) {
var rate = (i/(end-1));
var value = base - (difference*rate);
values.push(value);
}
// Once complete, id expect:
// values[0] === 600;
// values[99] === 470;
console.log(values);
Related
I have the following code:
function test1() {
var app = SpreadsheetApp;
var activesheet = app.getActiveSpreadsheet().getActiveSheet();
for (var j = 2; j<= 3; j++) {
activesheet.getRange(j,2).setValue("C");
}
}
This code will add the character "C" to the cell B2 and B3 which is great.
I am looking to get my code to add two "C" characters to 2 random cells from the first 30 cells of the B column.
Any help is much appreciated. Thank you.
This code may help you
function test1() {
var app = SpreadsheetApp;
var activesheet = app.getActiveSpreadsheet().getActiveSheet();
let randomCellIndex;
let usedCell = [];
for (var i = 0; i < 2; i++) {
// make sure not to use same index twice
do
randomCellIndex = Math.floor(Math.random() * 30) + 1;
while (usedCell.indexOf(randomCellIndex) !== -1);
usedCell.push(randomCellIndex);
activesheet.getRange(randomCellIndex,2).setValue("CC");
}
}
I assume that you don't want duplicate values so i would grab two values from shuffled array. To avoid going into the rabbit hole with shuffling array exsample uses underscore
_.shuffle([...Array(30)].map((value, index) => index+1))
Adds character string to range n times making a unique selection each time.
function addCharsRandom(chr = "AB", a1rg = "", n = 3) {
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
const rg = (a1rg.length < 2) ? sh.getActiveRange() : sh.getRange(a1rg);
if (rg.getDisplayValues().flat().length >= n) {
rg.setBackground("yellow")
const w = rg.getWidth();
const h = rg.getHeight();
const r = rg.getRow();
const c = rg.getColumn();
let rA = [];
let cA = [];
[...Array.from(new Array(n).keys())].forEach(i => {
let row, col;
do {
row = r + Math.floor(Math.random() * h);
col = c + Math.floor(Math.random() * w);
} while (rA.indexOf(row)>-1 && cA.indexOf(col)>-1);
rA.push(row);
cA.push(col);
sh.getRange(row, col).setValue(sh.getRange(row, col).getDisplayValue() + chr).setBackground("white");
});
} else {
SpreadsheetApp.getUi().alert("Range is to small for number of unique selections");
}
}
if a1rg equals "" then it will select the active range.
Demo:
I'm a beginning JavaScript user. I'd like to calculate a score of 15 questions from a program.
What I need:
I put the value I received to JSq1, JSq2, etc. then I add them up and divided by total question and round up a score. I can lay everything in many lines but that does not look efficient. I'm trying to figure out a way to use loop to get all the same result.
Please help.
THANKS
<script language = "JavaScript">
// the following may work
var JSq1 =Varq1score.getValue();
var JSq2 =Varq2score.getValue();
var JSq3 =Varq3score.getValue();
var JSq4 =Varq4score.getValue();
var JSq5 =Varq5score.getValue();
var JSq6 =Varq6score.getValue();
var JSq7 =Varq7score.getValue();
var JSq8 =Varq8score.getValue();
var JSq9 =Varq9score.getValue();
var JSq10 =Varq10score.getValue();
var JSq11 =Varq11score.getValue();
var JSq12 =Varq12score.getValue();
var JSq13 =Varq13score.getValue();
var JSq14 =Varq14score.getValue();
var JSq15 =Varq15score.getValue();
var totalScore = JSq1 + JSq2 + JSq3 + ...
var totalQuestion = 15
var finalScore = parseFloat(totalScore/totalQuestion*100).toFixed(0);
// I'd like to do the following but don't know how to specify JSq1, JSq2, etc in a loop so I don't have to repeat the lines so many times.
var totalQ = 15;
for (i = 0; i <= totalQ ; i++) {
var JSq+[i] = "Varq"+ i + "score.getValue()";
}
for (i = 0; i <= totalQ ; i++) {
var totalScore = totalScore + JSq + [i];
}
...
</script>
1) Build an object all_vars with all the variable. (Here with object shorthand property, { JSq1 } will be equivalent to { JSq1: Varq1score.getValue() }
2) Use Object.values to get values of above object in an array.
3) Use any loop (in this case we are using reduce) to build total score dynamically.
With these slight changes to your current code, you can achieve the result. Check the following sample code.
var JSq1 = 3;
var JSq2 = 3;
var JSq3 = 3;
var JSq4 = 3;
var JSq5 = 3;
var JSq6 = 3;
var JSq7 = 3;
var JSq8 = 3;
var JSq9 = 3;
var JSq10 = 3;
var JSq11 = 3;
var JSq12 = 3;
var JSq13 = 3;
var JSq14 = 3;
var JSq15 = 3;
var all_vars = {
JSq1,
JSq2,
JSq3,
JSq4,
JSq5,
JSq6,
JSq7,
JSq8,
JSq9,
JSq10,
JSq11,
JSq12,
JSq13,
JSq14,
JSq15
};
var totalScore = Object.values(all_vars).reduce((sum, jsq) => sum + jsq, 0);
var totalQuestion = 15;
var finalScore = parseFloat((totalScore / totalQuestion) * 100).toFixed(0);
console.log(finalScore)
I'm trying to figure out how to handle calendar event overlapping the way Google calendar does it.
I have an array of events with start and end dates.
Currently I sort the entire array to be in order from earliest to latest then find out how many times an event is overlapped and how many times it is overlapping another. I'm not sure where to go from here, I feel like I could use those values to calculate proper css width % and left %. Am I even on the right track?? I'm doing this as a school project. Thank you in advance!
EDIT: I took a look at the similar question that Markus Jarderot has answered before and found the answer I was looking for. Thank you so much!
function getOverlappingEvents(eventArray) {
var result = [];
eventArray.sort(function(a, b) {
return a.eventStart - b.eventStart;
});
for (var i = 0; i < eventArray.length; i++) {
var overapped = 0;
var overlaps = 0;
var isdate = new Date(eventArray[i].eventStart);
var iedate = new Date(eventArray[i].eventEnd);
for (var x = 0; x < eventArray.length; x++) {
var xsdate = new Date(eventArray[x].eventStart);
var xedate = new Date(eventArray[x].eventEnd);
if(isdate <= xsdate && iedate > xsdate){
overapped++;
}else if(isdate >= xsdate && isdate < xedate){
overlaps++;
}
}
result.push([eventArray[i].calEventID, overapped, overlaps]);
}
return result;
}
function toDom(events, ids){
var domEvents = [];
for (var i = 0; i < events.length; i++) {
var id = events[i].calEventID;
var width = 0;
var left = 0;
var sDate = new Date(events[i].eventStart);
var eDate = new Date(events[i].eventEnd);
var time = sDate.format("htt") + " - " + eDate.format("htt");
var duration = (eDate.getHours() * 60 + eDate.getMinutes()) - (sDate.getHours() * 60 + sDate.getMinutes());
var height = Math.round((duration * 0.75));
var topOffSet = (sDate.getHours() - 6) * 45 + Math.round(sDate.getMinutes() * 0.75);
var status = events[i].calStatus;
var desc = events[i].description;
var json = {id: id, sDate: sDate, eDate: eDate, status: status, height: height+"px", top: topOffSet+"px", width: width+"%", left: left+"%", desc: desc, time: time};
console.log(json);
domEvents.push(json);
}
return domEvents;
}
I am using the below code to assign a random class (out of five) to each individual image on my page.
$(this).addClass('color-' + (Math.floor(Math.random() * 5) + 1));
It's working great but I want to make it so that there are never two of the same class in a row.
Even better would be if there were never two of the same in a row, and it also did not use any class more than once until all 5 had been used... As in, remove each used class from the array until all of them have been used, then start again, not allowing the last of the previous 5 and the first of the next 5 to be the same color.
Hope that makes sense, and thanks in advance for any help.
You need to create an array of the possible values and each time you retrieve a random index from the array to use one of the values, you remove it from the array.
Here's a general purpose random function that will not repeat until all values have been used. You can call this and then just add this index onto the end of your class name.
var uniqueRandoms = [];
var numRandoms = 5;
function makeUniqueRandom() {
// refill the array if needed
if (!uniqueRandoms.length) {
for (var i = 0; i < numRandoms; i++) {
uniqueRandoms.push(i);
}
}
var index = Math.floor(Math.random() * uniqueRandoms.length);
var val = uniqueRandoms[index];
// now remove that value from the array
uniqueRandoms.splice(index, 1);
return val;
}
Working demo: http://jsfiddle.net/jfriend00/H9bLH/
So, your code would just be this:
$(this).addClass('color-' + (makeUniqueRandom() + 1));
Here's an object oriented form that will allow more than one of these to be used in different places in your app:
// if only one argument is passed, it will assume that is the high
// limit and the low limit will be set to zero
// so you can use either r = new randomeGenerator(9);
// or r = new randomGenerator(0, 9);
function randomGenerator(low, high) {
if (arguments.length < 2) {
high = low;
low = 0;
}
this.low = low;
this.high = high;
this.reset();
}
randomGenerator.prototype = {
reset: function() {
this.remaining = [];
for (var i = this.low; i <= this.high; i++) {
this.remaining.push(i);
}
},
get: function() {
if (!this.remaining.length) {
this.reset();
}
var index = Math.floor(Math.random() * this.remaining.length);
var val = this.remaining[index];
this.remaining.splice(index, 1);
return val;
}
}
Sample Usage:
var r = new randomGenerator(1, 9);
var rand1 = r.get();
var rand2 = r.get();
Working demo: http://jsfiddle.net/jfriend00/q36Lk4hk/
You can do something like this using an array and the splice method:
var classes = ["color-1", "color-2", "color-3", "color-4", "color-5"];
for(i = 0;i < 5; i++){
var randomPosition = Math.floor(Math.random() * classes.length);
var selected = classes.splice(randomPosition,1);
console.log(selected);
alert(selected);
}
var used = [];
var range = [0, 5];
var generateColors = (function() {
var current;
for ( var i = range[0]; i < range[5]; i++ ) {
while ( used.indexOf(current = (Math.floor(Math.random() * 5) + 1)) != -1 ) ;
used.push(current);
$(" SELECTOR ").addClass('color-' + current);
}
});
Just to explain my comment to jfriend00's excellent answer, you can have a function that returns the members of a set in random order until all have been returned, then starts again, e.g.:
function RandomList(list) {
var original = list;
this.getOriginal = function() {
return original;
}
}
RandomList.prototype.getRandom = function() {
if (!(this.remainder && this.remainder.length)) {
this.remainder = this.getOriginal().slice();
}
return this.remainder.splice(Math.random() * this.remainder.length | 0,1);
}
var list = new RandomList([1,2,3]);
list.getRandom(); // returns a random member of list without repeating until all
// members have been returned.
If the list can be hard coded, you can keep the original in a closure, e.g.
var randomItem = (function() {
var original = [1,2,3];
var remainder;
return function() {
if (!(remainder && remainder.length)) {
remainder = original.slice();
}
return remainder.splice(Math.random() * remainder.length | 0, 1);
};
}());
Here, sums[i].value is getting right values but when I want to keep a grand total of all Sum, it is failing.
function calc() {
var amounts = document.getElementsByName("Amount");
var prices = document.getElementsByName("Price");
var sums = document.getElementsByName('Sum');
var tax = document.getElementsByName('Tax');
var total = document.getElementsByName('Total');
for (var i = 0; i < amounts.length; i++) {
sums[i].value = amounts[i].value * prices[i].value;
total[0].value = total[0].value + sums[i].value;
// only this line is not working
}
}
Plain HTML is strings, all the way down, and var amounts = document.getElementsByName("Amount"); followed by amounts.value means you now have string values. Since + is also a string operator, JavaScript will happily turn "2"+"4" into "24", which looks like it did maths, but wrong, when in fact it didn't do math at all.
Convert all values that need to be numbers into numbers, first:
var amounts = document.getElementsByName("Amount");
....
var amount = parseFloat(amounts.value); // NOW it's a number
...
Replace your code with :
for (var i = 0; i < amounts.length; i++) {
sums[i].value = parseFloat(amounts[i].value) * parseFloat(prices[i].value);
total[0].value = parseFloat(total[0].value) + parseFloat(sums[i].value);
// only this line is not working
}
sums[i].value = parseFloat(amounts[i].value) * parseFloat(prices[i].value);
total[0].value = parseFloat(total[0].value) + parseFloat(sums[i].value);
This should help you.
Remove the .value while adding and multiplying
function test()
{
var amounts = new Array();
amounts[0] = "4";
amounts[1] = "6";
amounts[2] = "10";
var prices = new Array();
prices[0] = "4";
prices[1] = "6";
prices[2] = "10";
var sums = new Array();
var total = 0;
for (var i = 0; i < amounts.length; i++) {
sums[i] = parseInt(amounts[i]) * parseInt(prices[i]);
total= parseInt(total) + parseInt(sums[i]);
// only this line is not working
//alert(total); is 152
}
}