For loop where each value is distributed correctly - javascript

I have a for loop where I want to distribute a certain number of words with the same length across a timeline.
I have variables that give me the duration for each text, the start of where the words will spawn, and the end.
var wordArray = [];
for (t = 0; t < words.length; t++) {
//This generates the textbox
wordArray[wordArray.length] = currentComp.layers.addText(words[t]);
if (t == 0) {
//This makes the first textbox appear in the start
wordArray[wordArray.length - 1].inPoint = start;
//This makes the first textbox have the length with the value that divides it by the number of words
wordArray[wordArray.length - 1].outPoint = wordArray[wordArray.length - 1].inPoint + textTime;
//Here I am trying to make them all evenly distributed by multiplying the divided duration for the number of words that are already existing
} else if (t < words.length - 2) {
wordArray[wordArray.length - 1].inPoint = start + textTime * (wordArray.length - 1);
wordArray[wordArray.length - 1].outPoint = end - textTime * (wordArray.length - 1);
} else {
//This is here to make the last word stop at the end of the text duration.
wordArray[wordArray.length - 1].inPoint = start + textTime * (wordArray.length - 1);
wordArray[wordArray.length - 1].outPoint = wordArray[wordArray.length - 1].inPoint + textTime;
}
}
The error comes in the end, as seen in the image.The word in the end (highlighted in white) has less length than the previous, and the second to last word has more length than all the other words.
I'm aware this isn't a syntax issue, rather a maths issue that I can't seem to figure out. Thanks in advance
EDIT: Found the answer and updated the syntax to match it.

I updated the syntax to match the correct code.
Turns out that The issue was that the gap for each word wasn't being calculated correctly.
I got it to work by calculating the start and the end of each section by doing this :
var startDurationString = timeCalc[0].split(":");
var finalStartDurationString = startDurationString[1] + ":" + startDurationString[2] + ":" + startDurationString[3];
var startDuration = currentFormatToTime(finalStartDurationString, currentComp.frameRate);
var endDurationString = timeCalc[1].split(":");
var finalEndDurationString = endDurationString[1] + ":" + endDurationString[2] + ":" + endDurationString[3];
var endDuration = currentFormatToTime(finalEndDurationString, currentComp.frameRate);
Then, I used the difference of the start and the end and divided by the length of the words.
durationForEachText = (endDuration-startDuration) / numberOfWords.length;
Hope it helps anyone out there.

Related

Milliseconds in Lap Time Average dropping the Zero in Tenths place

I am using code I found on this site to average lap times in MM:SS.mmm (Averaging Times using Javascript)
It works great until the result has a zero in the tenths place. For example, the result should be 01:00.096 however, the zero is dropped and the answer is 01:00.96
I have simplified the input of 'times' to highlight the problem.
I have looked at different formatting issues, tried converting the strings to numbers and I've looked at the offsetify function thinking it was somehow interpreting the milliseconds incorrectly.
I am a novice at JavaScript with no formal training but enjoy hobby-programming. I have learned a lot from the examples on this site for use in my own little apps.
var times = ['01:00.096'];
var date = 0
var result = '';
function offsetify(t)
{
return t < 10 ? '0' + t : t;
}
for(var x = 0; x < times.length; x++ ) {
var tarr = times[x].split(':');
date += new Date(0, 0, 0, 0, tarr[0], tarr[1].split('.')[0], tarr[1].split('.')[1]).getTime();
}
var avg = new Date(date/times.length);
result = offsetify(avg.getMinutes()) + ':' + offsetify(avg.getSeconds()) + '.' + offsetify(avg.getMilliseconds());
The reason you see the 0 dropping is because in the offsetify function you have
return t < 10 ? '0' + t : t;
and you are passing it the value 96, which is not less than 10, so the function returns 96.
If you are able to find a datetime-formatting library like date-fns or moment, and you should use one, then great! Let the library do the work for you.
If you would like the practice, which is great for learning, use
s.padStart(3, '0')
for milliseconds, and
s.padStart(2, '0')
for minutes. For example, for your milliseconds:
> "5".padStart(3, "0")
'005'
> "55".padStart(3, "0")
'055'
> "383".padStart(3, "0")
'383'
Your function offsetify(t) appends a 0 in case your minutes/seconds is only single-digit - however milliseconds should be 3 digits!
You could create a new function that appends 0 if it is already 2 digits (less than 100), and 00 if it is only single-digit (less than 10) and just returns the result if it is already 3 digits.
function offsetifyMilliseconds(t)
{
return t < 10 ? '00' + t : t < 100 ? '0' + t : t;
}
and then do
result = offsetify(avg.getMinutes()) + ':' + offsetify(avg.getSeconds()) + '.' + offsetifyMilliseconds(avg.getMilliseconds());
However recent versions of Javascript (from ES2017) has access to the .padStart() function on any string:
The padStart() method pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length. The padding is applied from the start (left) of the current string.
-- String.prototype.padStart() - MDN
Using this would make your code much more readable (although you'd have to convert the numeric result to a string first). You could even change your offsetify function to use this method, and prevent code duplication!
In the example below I have defined 2 as the default padding length for the method, but you can pass an additional parameter to the function when you want to use it for milliseconds:
var times = ['01:00.096'];
var date = 0
var result = '';
function offsetify(t, len = 2)
{
return t.toString().padStart(len, '0');
}
for(var x = 0; x < times.length; x++ ) {
var tarr = times[x].split(':');
date += new Date(0, 0, 0, 0, tarr[0], tarr[1].split('.')[0], tarr[1].split('.')[1]).getTime();
}
var avg = new Date(date/times.length);
var minutes = offsetify(avg.getMinutes());
var seconds = offsetify(avg.getSeconds());
var milliseconds = offsetify(avg.getMilliseconds(), 3);
result = minutes + ':' + seconds + ':' + milliseconds;
console.log(result);

Generating Two Numbers With a Specific Sum

I'm trying to generate two numbers with a specific sum. Here is my proposed method:
Edited: http://jsfiddle.net/KDmwn/274/
$(document).ready(function () {
function GenerateRandomNumber() {
var min = -13, max = 13;
var random = Math.floor(Math.random() * (max - min + 1)) + min;
return random;
}
var x = GenerateRandomNumber();
function GenerateRandomNumber2() {
var min2 = -13, max2 = 13;
var random2 = Math.floor(Math.random() * (max2 - min2 + 1)) + min2;
if ((random2 + x) == 0){
return random2};
}
var xx = GenerateRandomNumber2();
There's something wrong with the if ((random2 + x) = 0) line, as the code runs perfectly fine when it's removed. How can I modify this line so that the sum of the two numbers is 0? It would be most helpful if someone could modify the Jsfiddle that I've included. Thanks!
This is invalid:
if ((random2 + x) = 0){
You cannot assign something to an expression.
You probably meant to use the comparison operator (==), like this:
if ((random2 + x) == 0){
Are you trying to make it only output a second number that, when added to the first, equals 0? Because it actually already does that - but only if it gets it on the first try (try hitting refresh at least 30 times.) You need to tell it to keep re-choosing (looping) the second random number while the sum isn't 0:
function GenerateRandomNumber2() {
var min2 = -13,
max2 = 13;
var random2;
while ((random2 + x) !== 0) {
random2 = Math.floor(Math.random() * (max2 - min2 + 1)) + min2;
}
return random2;
}
http://jsfiddle.net/vL77hjp0/
To take this one step further, if I'm reading this right (if not ignore this) it looks like you might want to eventually choose a random sum and have it determine the required second number to be added. To do this, we would replace the 0 in our "while" loop with 'sum'. And 'sum' would have to be defined as a random number with a "max=x+13" and "min=x-13" (otherwise the random number may be too high/low for random2 to ever reach, causing the browser to crash.) [Or just remove the limits from random2.]
http://jsfiddle.net/fkuo54hc/
First, your GenerateRandomNumbers2 function returns undefined value other than in your if statement. So you need to return a value. I updated your fiddle and refactor some of your code.

Applying Fibonacci, working with large numbers

I am trying to successfully complete this challenge on the Rosalind page. The challenge is:
Given: Positive integers n≤40 and k≤5.
Return: The total number of rabbit pairs that will be present after n months if we begin with 1 pair and in each generation, every pair of reproduction-age rabbits produces a litter of k rabbit pairs (instead of only 1 pair).
The exercise gives a text file of two numbers, the n and k mentioned above.
My code, which attempts to implement Fibonacci, works as expected for lower numbers of months. However, the result begins to become extremely large for higher numbers of months, and in each case I am given, my answer is Infinity.
Is my formula applied incorrectly? Or is Javascript a bad choice of language to use for such an exercise?
My code:
function fibonacciRabbits(months, pairs){
var months = months;
var numberOfPairs = pairs;
var result = 0;
// Declare parent & child arrays with constants
var parentArr = [1, numberOfPairs + 1]
var childArr = [numberOfPairs, numberOfPairs]
var total = []
// Loop from the point after constants set above
for(var i = 2; i < months - 2 ; i++){
parentArr.push(parentArr[i-1] + childArr[i-1])
childArr.push(parentArr[i-1] * childArr[i-2])
total.push(parentArr[i-1] + childArr[i-1])
}
result = childArr[childArr.length - 1] + parentArr[parentArr.length - 1]
console.log(months + ' months and ' + numberOfPairs + ' pairs:\n')
console.log('parentArr:\n', parentArr)
console.log('childArr:\n', childArr)
console.log('total\n', total)
console.log('result:', result)
console.log('\n\n\n')
}
fibonacciRabbits(5, 3)
fibonacciRabbits(11, 3)
fibonacciRabbits(21, 3)
fibonacciRabbits(31, 2)
And here is a REPL
Here is a more brief solution that doesn't produce such large numbers, and handles the maximum case without hitting infinity in Javascript. I think your solution was getting too big too fast.
function fibonacciRabbits(months, reproAmount){
var existingAdults = 0;
var adultPairs = 0;
var childPairs = 1;
for(var i = 2; i <= months; i++){
adultPairs = childPairs; //children mature
childPairs = (existingAdults * reproAmount); //last month's adults reproduce
existingAdults += adultPairs; //new adults added to the reproduction pool
}
console.log(existingAdults + childPairs);
}
To make sure you are on the right track, test your function with:
fibonacciRabbits(1, 1);
fibonacciRabbits(2, 1);
Which from the website says: f(1)=f(2)=1. So these should both produce "1" no matter what. Your code produces "3" for both of these.

Calculate in Javascript not working

I want to calculate in Javascript but having Strange Problems.
It just adds an 1 to my String but it should calculate it. I am converting my Strings to Int with the parseInt() Function and a am calculating like this: sec = sec + 1;
var calc= parseInt($(this).find("input[name=calc]").val());
calc = calc + 1;
Your string must not be empty if don't want NaN. First check if you get an empty string:
var cal = null;
if ( $(this).find("input[name=calc]").val() ) {
cal = parseInt( $(this).find("input[name=calc]").val(), 10 );
cal++;
}
if(!!sec){
sec = parseInt(sec, 10) + 1;
alert(sec);
}
Or, in your scenario:
var fieldvalue = $(this).find("input[name=calc]").val(), calc;
if(!!fieldvalue){
calc = parseInt(fieldvalue, 10);
calc += 1;
alert(calc);
}
Do you have more code to express. It may just be coming out to 1, because sec is not set as a number
In javascript, the + operator is used for addition and concatenation of strings.
As javascript is weakly typed, you have to add information about the type. Here are two solutions:
Substract 0 from the string
sec = (sec-0) + 1;
Add unary + operator to the string
sec = (+sec) + 1;

Time validations (Javascript)

I have a form (Using JavaScript) in which users are supposed to enter information like their work start time, break start time, break end time and work end time. I have 4 textboxes for this purpose. Time entered into the textbox is in hhmm format (24-hour only).
Requirements:
1. The break times (start and end) must be within the work start and end time.
2. Break start must be before break end time.
3. Users can take up work shifts during the day or even overnight.
4. Work time(excluding breaks) should be less than 8 hours and greater than 4 hours.
So some typical valid entries would be:
User1-
Start time: 0900
Break start time:1300
Break end time:1400
End time:1600
User2-
Start time:2200
Break start time:2300
Break end time:2330
End time:0400
Some invalid entries would be:
Case1 - Break start before break end
Start time:2200
Break start time: 2330
Break end time: 2300
End time:0400
Case 2 -Breaks outside work time
Start time:2200
Break start time:1830
Break end time: 1900
End time:0400
I'm having trouble writing the validation code (JavaScript) for requirements 1,2 & 3. Please help me out.
Here's what I've got so far. (Please note: I cannot use DATE objects.)
var wrkSt = getElement('TB1').value;
var wrkSt_hr = parseFloat(wrkSt.substr(0,2));
var wrkSt_mn= parseFloat(wrkEd.substr(2,2));
var brkSt = getElement('TB2').value;
var brkSt_hr = parseFloat(brkSt.substr(0,2));
var brkSt_mn= parseFloat(brkEd.substr(2,2));
var brkEd = getElement('TB3').value;
var brkEd_hr = parseFloat(brkSt.substr(0,2));
var brkEd_mn= parseFloat(brkEd.substr(2,2));
var wrkEd = getElement('TB4').value;
var wrkEd_hr = parseFloat(wrkEd.substr(0,2));
var wrkEd_mn= parseFloat(wrkEd.substr(2,2));
var msg='';
if ((wrkSt_hr > wrkEd_hr) || ((wrkSt_hr == wrkEd_hr) && (wrkSt_mn >= wrkEd_mn)) )
{
msg+='shift overnight selected';
}
if (wrkEd_hr>12){wrkEd_hr-=12;}
if (wrkSt_hr >12){wrkSt_hr -=12;}
if (brkSt_hr>12){brkSt_hr-=12;}
if (brkEd_hr>12){brkEd_hr-=12;}
var Breakdiff = ((brkEd_hr - brkSt_hr)*60) + (brkEd_mn - brkSt_mn);
var Workdiff_tot = ((wrkEd_hr- wrkSt_hr)*60) + (wrkEd_mn -wrkSt_mn);
var Shiftdiff = Workdiff_tot - Breakdiff;
if (Shiftdiff > 480) //8hours = 8*60 = 480 min
{
msg+='Time greater than 8 hrs';
}
if (Shiftdiff < 240) //4 hours = 4*60 = 240 min
{
msg+='Time less than 4 hrs';
}
Please help me with the logic for checking breaks and work time. Thx for any help in advance!
function validate(start, breakStart, breakEnd, end) {
var minutes = [];
for (var i = 0; i < 4; ++i) {
var time = arguments[i];
if (!/^(?:[01]\d|2[0-3])[0-5]\d$/.test(time)) {
throw new Error("Invalid time " + time);
}
var minute = minutes[i] = time.substring(0, 2) * 60 + +time.substring(2);
if (i && minute < minutes[i - 1]) { // Take into account times that cross midnight.
minutes[i] = (minute += 24*60);
}
if (i && minute <= minutes[i - 1]) {
throw new Error("Out of order " + arguments[i - 1] + " and " + time);
}
}
if (minutes[3] - minutes[0] > 8*60) { throw new Error("Shift too long"); }
if (minutes[3] - minutes[0] > 4*60) { throw new Error("Shift too short"); }
}

Categories

Resources