Time based javascript, creating a blank response for approx 30 minutes - javascript

First - thanks in advance for your help.
I have a image based slide show, that calls #photo1, 2, 3. Using javascript to change the image (actually the image folder, all images have the same name, so just changing root folder) based on various time blocks throughout the day. (9am-11am, 11am-3pm, 3-6pm, 6pm-9am). In case it matters, I am storing the images on dropbox (so my buddy can change them at will, the links provided are old and not currently working).
It all seems to be working, accept for approx the first 30 minutes after the change time, it goes blank. Then works fine again.
Thoughts? I am not great with javascript, so if I am going about this all wrong, I am open to new approaches.
Javascript code:
$(document).ready(function(){
var d = new Date();
var n = d.getHours();
// If time is after 9AM or before 11AM
if (n > 9 && n < 11) {
$("img#photo1").attr("src","https://dl.dropboxusercontent.com/s/324....67l/ad1.jpg?dl=0");
$("img#photo2").attr("src","https://dl.dropboxusercontent.com/s/5i9f....m10z/ad2.jpg?dl=0");
$("img#photo3").attr("src","https://dl.dropboxusercontent.com/s/n7....66/ad3.jpg?dl=0");
}
else if (n > 11 && n < 15) {
$("img#photo1").attr("src","https://dl.dropboxusercontent.com/s/31p....rw3r/ad1.jpg?dl=0");
$("img#photo2").attr("src","https://dl.dropboxusercontent.com/s/h3m....tsqy/ad2.jpg?dl=0");
$("img#photo3").attr("src","https://dl.dropboxusercontent.com/s/zr9....kzja/ad3.jpg?dl=0");
}
else if (n > 15 && n < 18) {
$("img#photo1").attr("src","https://dl.dropboxusercontent.com/s/5li....y2w/ad1.jpg?dl=0");
$("img#photo2").attr("src","https://dl.dropboxusercontent.com/s/no....twr2/ad2.jpg?dl=0");
$("img#photo3").attr("src","https://dl.dropboxusercontent.com/s/ojjn....i1g/ad3.jpg?dl=0");
}
else if (n > 18 || n < 9) {
$("img#photo1").attr("src","https://dl.dropboxusercontent.com/s/kn3ch....s7g0/ad1.jpg?dl=0");
$("img#photo2").attr("src","https://dl.dropboxusercontent.com/s/dhxi5....04/ad2.jpg?dl=0");
$("img#photo3").attr("src","https://dl.dropboxusercontent.com/s/mb51....336/ad3.jpg?dl=0");
}
// runs the code every hour, probably there is a much better way to do this
setTimeout(function(){window.location.reload();}, 3600000)
});

When the hour is 9, 11, 15 or 18, none of your conditions will match, and nothing will be displayed. Change the conditions to:
if (n >= 9 && n < 11) {
// ...
}
else if (n >= 11 && n < 15) {
// ...
}
else if (n >= 15 && n < 18) {
// ...
}
else if (n >= 18 || n < 9) {
// ...
}

You've excluded 9, 11, 15 and 18; the if statements selects for greater than or less than. You'll get undefined for any of those numbers.

Related

Multiple and different conditions in Javascript

I have a problem with logic.
If the number is higher than 0 and less than 10 AND the number is 11 AND the number is 22 do something. (1, 2, 3, 4, 5, 6, 7, 8, 9, 11 or 22).
And ELSE IF the number is higher than 10 BUT is NOT 11 or is NOT 22, do something else. (10, 12, 13 ....20, 21, 23, 24...)
I got to do only with 11, but I have no clue how to insert another condition with 22.
if (n >= 0 && n < 10) || (n == 11 && n == 22) {
do something
} else if (n >= 10 && n != 11) && (n != 22) {
do something else
}
Try (n >= 1 && n <= 9) || n == 11 || n == 22 which will check if the number is between 1 and 9 inclusive (1 to 9) OR it's 11 OR it's 22.
Then, in your else if, just check for >= 10 - numbers less than 1 e.g. 0, won't trigger the else either.
if ((n >=1 0 && n <= 9) || n == 11 || n == 22) {
do something
} else if (n >= 10) {
do something else
}
Use >= and <= to make it clearer what values you're looking for otherwise it takes a little extra mental load to realise that n > 0 && n < 10 really means values 1 to 9.
Also, it's JavaScript and numbers can either be integral or floating point, so greater than zero could be 0.1 etc.
In your if statement, you say:
n is larger or equal to 0 AND n is smaller than 10
OR
n is equal to 11 AND n is equal to 22
Which means, the if block will run for numbers that are between 0 and 9 (inclusive) OR for the numbers 11 AND 22. So the number can either be between 0 and 9 or it can be BOTH 11 and 22, which is impossible.
My take on the if statement:
if (n >= 1 && n <= 9 || n == 11 || n == 22) {
do something;
}
That way, you don't get confused with the inclusive and exclusive numbering and make sure that either 11 or 22 is allowed.
The second block will run for numbers that are greater or equal to 10 AND not 11 AND not 22. Which is just fine.
else if (n >= 10 && n != 11 && n != 22) {
do something else;
}
In this answer, I assume you don't want to entirely skip the 10. If you do, then in the second statement, you would check for n > 10.
Logically, this is sound. However, I don't think that you need to check for 11 and 22 in the second one, as the if block will run first and if the number is 11 or 22, the first if block will run. So the second one doesn't need to account for them.
Based on your example of (1, 2, 3, 4, 5, 6, 7, 8, 9, 11 or 22) it sounds like this is what you're going for?
if ((n > 0 && n < 10) || n == 11 || n == 22) {
// do something
} else if (n >= 10) {
// do something else
}
Edit: Added else if (n >= 10) that I overlooked
Just take the comparison and because of the higher precedence of logical AND && over logical OR ||, you need no parenthesis.
if (n >= 0 && n < 10 || n === 11 || n === 22) {
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 11 or 22
// do something
} else {
// 10, 12, 13 ... 21, 23 ...
// do something
}
Your first condition will never succeed because you can't have a number higher than 0 and less than 10 AND this same number is equal to 11 AND also being equal to 22 (in both case, it'll be more than 10).
if ((n > 0 && n < 10) || n == 11 || n == 22) {
// my number is 1, 2, 3, 4, 5, 6, 7, 8, 9, 11 or 22
} else {
// my number is almost everything except the values from above
}
You were almost there.
To test for 1, 2, 3, 4, 5, 6, 7, 8, 9, 11 or 22:
if (n >= 0 && n < 10) || (n == 11 && n == 22) {
Can minimally be changed to:
if ((n > 0 && n < 10) || (n == 11 || n == 22)) {
The three important changes are:
balance parentheses to make a proper if( ) construct.
>= 0 becomes > 0 to achieve the higher than zero requirement.
The last && becomes ||.
This also changes the order of operations such that we don't actually need any extra parentheses at all in this case. This also happens to be correct, and is simpler:
if (n > 0 && n < 10 || n == 11 || n == 22) {
...because && has higher precedence than || and the comparators (>, < and ==) have higher precedence than the conditionals (&& and ||).
At this point you don't need an else if condition. Just else will suffice. 11 and 22 are handled by the affirmative case of the if and therefore n will be neither of those things in the else case.
Final product:
if (n > 0 && n < 10 || n == 11 || n == 22) {
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 11 or 22
} else {
// Something else. :)
}
Take a look at the documentation, don't confuse logicial AND (&&) and logical OR (||).
function check(n) {
if((n >= 1 && n <= 9) || (n == 11 || n == 22)) {
console.log(n, true);
} else if(n >= 10) {
console.log(n, false);
}
}
check(1) // true
check(11) // true
check(22) // true
check(0)
check(10) // false
check(12) // false
check(21) // false
check(23) // false

Grading Students in JS with recursion - Range Error

I was trying to work on this hackerrank problem.
Every student receives a grade in the inclusive range from
0-100 to .
Any less than 38 is a failing grade.
Sam is a professor at the university and likes to round each student's according to these rules:
If the difference between grade the and the next multiple of
5 is less than 3, round up to the next multiple of 5. If the value of grade is less than 38, no rounding occurs as the
result will still be a failing grade.
Given the initial value of for each of Sam's students, write code to
automate the rounding process.
My code is:
function gradingStudents(grades) {
const roundup = y => y + 1;
{
if ( grades < 38 || grades % 5 === 0) return grades;
else if ( grades % 5 < 4 && grades % 5 !== 0) return roundup(grades);
}
{
if (roundup % 5 === 0) return roundup;
else { gradingStudents(roundup + 1) }
}
}
gradingStudents(38) // -> 39
I tried to use Math.ceil(grades) inside the variable roundup but output didnt change. So, when you invoke the function with a number that is not before a multiple of 5 (e.g. 43) it returns the proceeding number. However, if it is the number before a multiple of 5 it gives a range error. "maximum call stack size reached."
As far as I got, the code doesnt proceed to the second part. Even if it did, I am not sure if it would fetch the current value of the function roundup when dealing with if statements in the second block.
What do I dont get in here?
Also, this is actually meant for an array output but since I am a beginner I am pretty much okay with this one for the start as well :D .
Javascript solution:
function gradingStudents(grades) {
return grades.map((grade) => {
if (grade > 37) {
const offset = 5 - (grade % 5);
if (offset < 3) {
grade += offset;
}
}
return grade;
});
}
Try this:
function gradingStudents(grades) { //input: 43
var finalGrade;
if(grade < 38)
return grades;
else{
var gradeDif = grades % 5; //3
if(gradeDif > 3){
return grades;
}
else {
return grades + (5 - gradeDif); //Output: 45
}
}
}
One solution calculates the next multiple of 5 no bigger than the grade and uses that value to test whether or not to round up (next5 - grade < 3).
We write a simple function to round an individual grade and then for a list of grades use .map with that function.
const roundGrade = (grade) => {
const next5 = 5 * Math.ceil (grade / 5)
return (grade < 38) ? grade : (next5 - grade < 3) ? next5 : grade
}
const gradingStudents = (grades) =>
grades .map (roundGrade)
console .log (gradingStudents ([73, 67, 38, 33]))
Note that, like most solutions to this problem, no recursion is needed.
1-Use the Array.prototypt.map according to the question logic.
const gradingStudents = (grades) => grades
.map(n => (n >= 38 && n % 5 >= 3)?(n + ( 5 - ( n % 5 ) )):n )
let result = gradingStudents([0,25,38,56,89,77,78,57,58])
console.log(result)
My solution is this
function gradingStudents(grades) {
grades.map((grade,i)=>{
if(grade >= 38){
let fg = (grade/5).toString().split('.');
if(fg[1]>5){
grades[i]=((parseInt(fg[0],10)+1) * 5);
};
}
});
return grades;
}
console.log(gradingStudents([73,67,38,33]));
my solution:
function gradingStudents(grades) {
return grades.map(function(grade) {
return (grade >= 38 && grade % 5 >= 3) ? grade + 5 - (grade % 5) : grade;
});
}

How can I convert these 'if' statements to an algorithm

I'm trying to convert these 'if' statements to an algorithm, so that I can have many more stages instead of being limited to 10. How would I go about converting it? I just can't wrap my head around the logic!
function getStage(km) {
if (km > 2 && km < 4){
return 1;
}
else if (km > 4 && km < 6){
return 2;
}
else if (km > 6 && km < 8){
return 3;
}
else if (km > 8 && km < 10){
return 4;
}
else if (km > 10 && km < 12){
return 5;
}
else if (km > 12 && km < 14){
return 6;
}
else if (km > 14 && km < 16){
return 7;
}
else if (km > 16 && km < 18){
return 8;
}
else if (km > 18 && km < 20){
return 9;
}
else if (km > 20 && km < 22){
return 10;
}
}
I have tried this:
function getStage(km) {
var tempStage = 0;
for (var i = 0; i < stages; i++) {
var stage = i + 1;
var tempKm = stage * 2;
var nextKm = stage + 2;
if (km > tempKm && km < nextKm) {
tempStage = stage;
}
}
return tempStage;
}
Perhaps I shouldn't be using a for loop? Is there a better way of doing this?
Maybe you are looking for Math.floor
function getStage(km) {
return Math.floor(km / 2)
}
console.log(getStage(2));
// 1
console.log(getStage(10));
// 5
console.log(getStage(11));
// 5
You can just use math to do this. No loops or conditionals necessary.
Notice that your input intervals increase in "steps" of 2, and your outputs increase in "steps" of 1. This makes me think maybe we should divide km by 2.
Since we always want an integer answer, we can use the Math.floor function.
Some examples:
Math.floor(3/2) = 1
Math.floor(4.1/2) = 2
etc.
Depending on what you want to return for edge cases (what if km = 2 or km = 4, or any multiple of 2?) we might be done here. If you wish to return 1 when k=4, 2 when k=6, etc., you'll need to do a little more work.
*** In general: *** if you are working with numbers and you find yourself writing a lot of cases, you can usually use some combination of simple mathematical operators to calculate the result. For problems like these, try thinking about your input/output pairs, and what the relationship is between them.
You could take the floored value of km divided by two plus one.
10 is the upper limit.
function getStage(km) {
return Math.min((km >> 1) + 1, 10);
}
console.log(getStage(2.1)); // 2
console.log(getStage(3)); // 2
console.log(getStage(4)); // 4
Try something like this. This is general solution which applies not only to 2*n series.
const stages = [2, 4, 6, 8, 10, 13, 15, 16, 20]; //should be ordered. Else sort it first.
const getStage = km => stages.indexOf(stages.find(i => km < i));
console.log(getStage(5)); //2
console.log(getStage(1.5)); //0
console.log(getStage(8.1)); //4
console.log(getStage(15)); //7
console.log(getStage(22)); //-1 out of index

Greater than X but less than Y javascript

I am new here, but i'm simply trying to figure out why this javascript is not working in my math program.
For the last two IF statements, i'm comparing numbers. Greater than X but less than Y...
(function(){
if(fieldname4-fieldname3 < 30) return (1));
if ((fieldname4-fieldname3 > 31) && (fieldname4-fieldname3 < 60)) return
(2);
if ((fieldname4-fieldname3 > 60) && (fieldname4-fieldname3 < 90)) return
(3);
})();
Thanks for any help you can give me.
EDIT: I'm going to post the full script when i'm back to my compuer. Sorry for being so vague. It wasn't intentional. I'm still learning.
You can try to write a better code. For example:
(function(){
if(fieldname4-fieldname3 < 30){
return 1; //returns 1 for every number smaller then 30
}
if(fieldname4-fieldname3 >= 30 && fieldname4-fieldname3 <= 60){
return 2; // returns 2 for every number smaller then 60(includes 60) and greater then 30(includes 30)
}
if(fieldname4-fieldname3 > 60 && fieldname4-fieldname3 < 90){
return 3; // returns 3 for number smaller then 90 and greater then 60
}
})();
I hope that this will help you
Just shooting at it in the dark without seeing the script but how about this??
function test (fieldname4, fieldname3) {
var fieldResult = fieldname4 - fieldname3;
if(fieldResult < 30) {
return 1;
} else if ((fieldResult > 31) && (fieldResult < 60)) {
return 2;
} else if ((fieldResult > 60) && (fieldResult < 90)) {
return 3;
}
};

Inserting an event in an array of events with specific rules

I have a list of events on a given day. (events time is a moment object)
[
{ id: 1, start: '2017-05-01 05:00'},
{ id: 2, start: '2017-05-01 08:00'},
{ id: 3, start: '2017-05-01 14:00'},
{ id: 4, start: '2017-05-01 17:00'}
]
I need to add one event in this array so that the new event time is not less than 5am, is at least 3 hours after the previous event (if there is one) and 3h before the next event (if there is one). The new event should be planned on the same day.
In this case, it would insert the new event just after id = 2 and at 11am.
I started something but it ended up with a dozen of ifs and I got lost after a few hours thinking:
// for each event, check if there's time before or after (not less than 5am, not more than 11:59pm)
for(var i = 0; i < events.length; i++) {
var eventTime = events[i].start.clone();
var before = eventTime.clone();
var after = eventTime.clone();
before.subtract('hours', 3);
after.add('hours', 3);
if(i == 0 && !before.hour() < 5 && !before.isBefore(date, 'day')) {
// first event of the day, new time cannot be before 5am and cannot be on the previous day
hour = before.hour();
} else if(i == 0 && !after.isAfter(date, 'day')) {
// same as above but we test time + 3h
} else if(i == events.length - 1 && !after.isAfter(date, 'day')) {
// last event of the day, new time cannot be the next day (after 11:59pm)
hour = after.hour();
} else if (i > 0 && i < events.length - 1) {
// middle events
// new time should be at least 3H after previous event and 3H before next event
// ex: 5h, 8h, 12h ok but 5h, 8h, 10h not ok or 5h, 6h, 9h not ok
var previousEventTime = events[i-1].start.clone();
var nextEventTime = events[i+1].start.clone();
if(before.hour() >= previousEventTime.hour() && after.hour() <= nextEventTime.hour()) {
}
//
}
}
Here is a snippet that can be used:
var events = [
{ id: 1, start: 'Mon, 01 May 2017 05:00:00 +0200'},
{ id: 2, start: 'Mon, 01 May 2017 08:00:00 +0200'},
{ id: 3, start: 'Mon, 01 May 2017 14:00:00 +0200'},
{ id: 4, start: 'Mon, 01 May 2017 17:00:00 +0200'}
];
for(var i = 0; i < events.length; i++) {
var eventTime = moment(events[i].start).clone();
var before = moment(eventTime).clone();
var after = moment(eventTime).clone();
before.subtract(3, 'hours');
after.add(3, 'hours');
console.log(eventTime, before, after);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
After spending a day on this I came up with a "mathematical" solution.
In my array I want to insert an event y between an event x and an event z. (x being the previous event and z the next one)
Since I need 3 hours minimum between each event I figured:
x+3 <= y-3 || y+3 <= z-3
The one I implemented is a little bit different. I figured I needed at least 6 hours between 2 events to be able to insert a new event in the middle.
y-x > =6 || z-y >= 6
Since my brain is not far from burning out the code looks like this...
for(var i = 0; i < events.length; i++) {
var x = null;
var y = events[i].start.clone().hour();
var z = null;
if(i > 0) {
x = events[i-1].start.clone().hour();
}
if(i < events.length -1) {
z = events[i+1].start.clone().hour();
}
// first event or only event
if(i == 0) {
// check if removing 3h00 doesn't cross the 5am limit
if(y - 3 >= 5) {
hour = y - 3;
} else if(z-y >= 6) {
// check if there's enough time before next event
hour = y + 3;
}
}
// middle event
if(x && z) {
if (y-x >= 6) {
hour = y - 3;
} else if (z-y >= 6) {
hour = y + 3;
}
}
// last event (can also be first if only 1 element)
// with !hour we make sure that a "middle" event hour is not overriden if found above
if(!hour && i == events.length - 1 && i != 0) {
// check if adding 3h00 doesn't change day (23h00)
if(y + 3 <= 23) {
hour = y + 3;
} else if(y-x >= 6) {
// check if there's enough time after previous event
hour = y - 3;
}
}
}
return hour;
I'd be glad to accept an answer that improves on this algorithm.

Categories

Resources