Why isn't this logging the correct string? Sleep Calculator 7/9


#1

https://www.codecademy.com/courses/learn-javascript-functions/projects/sleep-debt-calculator?course_redirect=introduction-to-javascript

Hey all, so I can’t figure out why when I run this, it doesn’t output the correct string. It should log to the console that I need more sleep, but it doesn’t to return the correct string from my calculateSleepDebt function. Why is this happening?

var getSleepHours = (day) => {
  switch (day) {
    case 'monday':
      return 4;
    case 'tuesday':
      return 5;
    case 'wednesday':
      return 4;
    case 'thursday':
      return 5;
    case 'friday':
      return 7;
    case 'saturday':
      return 7;
    case 'sunday':
      return 5;
  }
}

var getActualSleepHours = () => {
return getSleepHours('monday') + getSleepHours('tuesday') + getSleepHours('wednesday') + getSleepHours('thursday') + getSleepHours('friday') + getSleepHours('saturday') + getSleepHours('sunday');
}

var getIdealSleepHours = () => {
	var idealHours = 7;
  return idealHours * 7;
}

var calculateSleepDebt = () => {
 	var actualSleepHours = getActualSleepHours;
  var idealSleepHours = getIdealSleepHours;
  if (actualSleepHours === idealSleepHours) {
    return 'You are getting the ideal amount of sleep.';
  }else if (actualSleepHours < idealSleepHours) {
    return 'You need to get more sleep.';
  }else {
    return 'You are getting more sleep than needed.';
  }
}
console.log(`The amount of sleep you should be getting each week is ${getIdealSleepHours()} hours.`);
console.log(`The amount of sleep you are getting is ${getActualSleepHours()} hours.`);
console.log(calculateSleepDebt());

#2

Needs to be invoked.

Also needs to be invoked,


#3

Sorry, what do you mean by that?


#4

You are calling two methods so they need to be invoked with ()

getActualSleepHours()

#5

Oh wow I don’t know how I didn’t catch that! Thanks, it works now.

So now, this brings another question to mind. How come I only need to invoke those methods there when defining the variables, but I don’t need to invoke them with () when calling them inside my if/else statement?


#6

Inside your if statement the varables are already assigned the return values of the two methods.

When we assign a function (or method) to a variable without invoking it we are actually making the variable a copy of the function.

const foo = () => "Bar";

console.log(foo());             // -> Bar

const bar = foo;

console.log(bar());             // -> Bar

console.log(bar.toString());    // () => "Bar"

#7

That clears it up, thanks!


#8

Aside

Care to see the above project refactored? It’ll give you something to study now that you have the function working correctly.


#9

Sure, I’d like to take a gander


#10

This is a spoiler so it cannot be copied or indexed.

const days = [
  `Sunday`, `Monday`, `Tuesday`,
  `Wednesday`, `Thursday`,
  `Friday`, `Saturday`
];
const equity = [`more`, `less`];
const hours = [5.5, 6, 6.5, 7, 8, 7.5, 8.5];

const getSleepHours = day => hours[days.indexOf(day)];

const getActualSleepHours = () => hours.reduce((a, b) => a + b);

const getIdealSleepHours = (idealHours = 7.5) => idealHours * 7;

const sleepDebtCalculator = () => {  
  for (let day of days) console.log(day, getSleepHours(day));
  const d = getIdealSleepHours() - getActualSleepHours();
  console.log(
    d < 0 ? `${-d} ${equity[0]} hours sleep than ideal` : 
    d > 0 ? `${d} ${equity[1]} hours sleep than ideal` : 
    `Ideal amount`
  );
};
sleepDebtCalculator();
Sunday 5.5
Monday 6
Tuesday 6.5
Wednesday 7
Thursday 8
Friday 7.5
Saturday 8.5
3.5 less hours sleep than ideal

#11

Thanks, it’s interesting seeing it written this way, I think I understand the majority of it, although I haven’t gotten to the lesson about “for/let”. Also don’t quite understand the const getActualSleepHours…


#12

ES6 introduces block scope that ES5 doesn’t have. If we use var in a for loop the variable is able to leak into the code following it. let and const give block scope to anything with a code block, for, while, etc. When we use let it preserves block scope so the variable cannot leak out of the block in which it is declared.

for (var i = 0; i < 10; i++) {
    console.log(i + 1);
}
console.log(i);
1
2
3
4
5
6
7
8
9
10
10 <- leakage, `i` is still visible to the rest of the program
for (let j = 0; j < 10; j++) {
    console.log(j + 1);
}
console.log(j);
1
2
3
4
5
6
7
8
9
10
ReferenceError: j is not defined
    at eval:19:1

j is no longer visible outside of the loop block.

Notice also that ES6+ introduces the of operator, letting us query element values rather than their index. It applies to arrays the way that for (let key in object) applies to objects.

const getActualSleepHours = () => hours.reduce((a, b) => a + b);

There is an advanced concept in the function, Array.reduce(), which takes a callback (when we use a function as the argument to another function call) with two parameters. Because of implicit returns in ES6+ we effectively minimized this,

hours.reduce(function (a, b) { return a + b; });

What the reduce function allows us to do is apply the inner function to all the elements of the context array (hours) which in this case is addition. We’ve effectively found the sum of the array. This may never come up in the lessons so put it on a back burner for now and read up on it when you finish the track. It’s great practice to come back to the lessons and refactor once you have more tools and understanding under your belt.

const getSleepHours = day => hours[days.indexOf(day)];

The above is almost self-explanatory. We work with data structures rather than a lengthy switch/if-else if-else. The inner code (in the subscript) searches the days array for the day that is passed in. This returns the index which we can then apply to the hours array, having corresponding data points.

I’m pretty sure that at some point the course does cover the ternary expression statement, but that may not have come up yet, either.

let a = condition ? value_if_true : value_if_false;

In the above example I have used a nested ternary…

let a = condition ? value_if_true : other_condition ? value_if_true : value_if_false;

Again, apart from the one lesson that covers this I don’t believe it comes up again. When you get to the concept take a little time out to read up on it.

Couple of things that ES6+ has given us are default parameters such as we see in getIdealSleepHours() The function takes either zero parameters, in which case the default is applied inside the function body, or one parameter, which value will be stored in idealHours and used instead; and, template literals which I believe you understand already.

You will read or find out that arrow functions cannot fully replace ES5 functions, and do not always work as we might expect. I’ll have to dig around for some examples. Unlike function(), () => does not have an arguments object so we must be explicit with our arguments. Not to worry at this time. In due course this will become a subject of your research and practice.


#13

Wow lot’s of great info and examples here! Thanks I’ll definitely read up more on some of this.


#14

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.