FAQ: Code Challenges: JavaScript Fundamentals - finalGrade()

OK. Another concept I need to study up on. I’m beginning to think me and javascript just aren’t copacetic. I’m having such a hard time with it.

1 Like

Think of confusion as the fuel of learning. If you are confused, you’re got fuel in the tank. Never give up. If anything, go back over all the lessons from the beginning and see if you discover any holes that can be addressed. It’s not a race. Better to go slowly, and don’t jump ahead if you are unsure of what you have learned so far.

2 Likes

Hello Everyone,

Can anyone tell me where did I go wrong with my code below? Codecademy keeps giving me an X but when I check my work, I get the results I need. What am I missing? I look forward to hearing from you!

const finalGrade = (grade1, grade2, grade3) => {
let average = (grade1 + grade2 + grade3) /3

if ((grade1 < 0 || grade1 > 100) || (grade2 < 0 || grade2 > 100) || (grade3 < 0 || grade3 > 100)) {
console.log(‘You have entered an invalid grade.’)
} else if (average < 59) {
return ‘F’
} else if (average < 69) {
return ‘D’
} else if (average < 79) {
return ‘C’
} else if (average < 89) {
return ‘B’
} else {
return ‘A’
}
}

Perhaps add 1 to each of the conditional values; i.e. 59 => 60, 69 => 70, &c.

} else if (average < 60) {

Hello Guys, well very simple, I did the exercise with my resources of what I have been learning on the course but the exercise solution is totally different, I feel they both accomplish the same, they both work. Now… important. I want to make sure I’m not committing any mistake, thanks for the help.

let finalGrade = (average1, average2, average3) => {
finalGrade = (average1 + average2 + average3) / 3;

if (finalGrade < 0 || finalGrade > 100) {
    return 'You have entered an invalid grade'
} else if (finalGrade < 60) {
    return 'F';
} else if (finalGrade < 70) {
    return 'D';
} else if (finalGrade < 80) {
    return 'C';
} else if (finalGrade < 90) {
    return 'B';
} else {
    return 'A';
}

};

The only thing I would change is where the average is computed… After the validation.

if (...) {
    return ...
}
average = ...
if (...) {

Thank you Roy !

and how about using a variable instead of using the same function as a variable, does that make it easier or change something? Let’s said something like this -->

let finalGrade = (average1, average2, average3) => {
const totalAverage = (average1 + average2 + average3) / 3;

It doesn’t change anything since the variable is in a different scope; however, it is less confusing to the reader if the variable is not the same as the name of the function.

I would suggest declaring functions with const. They never change and are better protected that way.

I’m only able to successfully complete this exercise with my argument as an if/else statement but not when I use a Switch statement.

code with a switch statement:

const finalGrade = (midterm,final,homework) => {
   if ((midterm < 0 || midterm > 100) || (final < 0 || final > 100) || (homework < 0 || homework > 100 )) {
     return 'You have entered an invalid grade.'
   }
   let averageGrade = (midterm + final + homework) /3;

switch (averageGrade) 
 case averageGrade < 60:
 return 'F';
 break;
 case averageGrade < 70:
 return 'D';
 break;
 case averageGrade < 80:
 return 'C';
 break;
 case averageGrade < 90:
 return 'B';
 default :
 return 'A'

  };   
  
console.log(finalGrade(100,50,100));

However, replacing the switch statement with an if/else statement instead, it successfully runs:

const finalGrade = (midterm,final,homework) => {
  if ((midterm < 0 || midterm > 100) || (final < 0 || final > 100) || (homework < 0 || homework > 100 )) {
    return 'You have entered an invalid grade.'
  }
  let averageGrade = (midterm + final + homework) /3



if (averageGrade < 60) {
return 'F'
} else if (averageGrade < 70) {
return 'D'
} else if (averageGrade < 80) {
return 'C'
} else if (averageGrade < 90) {
return 'B'
} else  
return 'A'

 };

 console.log(finalGrade(100,50,100));

For reference, this is a screenshot of the error

Can someone please help me spot the error?
Thanks in advance.

switch (expression) { case block }
                    ^
                 missing

Thanks for your reply Roy.

Now the error seems to be the < as you can see below.

Still can’t figure it out.

const finalGrade = (midterm,final,homework) => {
    if ((midterm < 0 || midterm > 100) || (final < 0 || final > 100) || (homework < 0 || homework > 100 )) {
      return 'You have entered an invalid grade.'
    }
    let averageGrade = (midterm + final + homework) /3;
 
switch (averageGrade) {
case < 60 :
return 'F';
break;
case < 70 :
return 'D';
break;
case < 80 :
return 'C';
break;
case < 90 :
return 'B';
break;
case <= 100 :
return 'A';
break;
}
   };   
   
console.log(finalGrade(100,80,100));

`case is a keyword, not a variable. What your code is attempting is to do is match the case expression to a variable in the switch argument. The only thing a comparison expression can match is a boolean.

averageGrade < 60  => true, or false

As we go down the case list, the first comparison to be true would be the match. So what goes into the argument, then?

Hello everyone

I have tried to extend this lesson by adding some code that checks to make sure that the numbers entered are actually numbers. I’ve used Number.isInteger to do this and it seems to work if I enter one of the grades as a string (‘A’ gives the error ‘you have entered an invalid grade.’).

It does not work if I enter A without any quote marks, and gives the error ‘A is not defined’. I understand why this is, but my question is whether there is a way to return an error ‘you have entered an invalid grade’ no matter what I enter in as one of the variables, so long as it’s not a number?

I suspect the answer is something like: ‘The use will never be able to enter an undefined var, so this won’t ever be a problem’, but I just want to make sure.

function finalGrade(num1, num2, num3) {
  if (num1 > 100 || num2 > 100 || num3 > 100 || num1 < 0 || num2 < 0 || num3 < 0 || Number.isInteger(num1) != true || Number.isInteger(num2) != true || Number.isInteger(num3) != true) {
    return 'You have entered an invalid grade.';
  } else if (((num1+num2+num3) / 3) >= 90) {
    return 'A';
  } else if (((num1+num2+num3) / 3) >= 80) {
    return 'B';
  } else if (((num1+num2+num3) / 3) >= 70) {
    return 'C';
  } else if (((num1+num2+num3) / 3) >= 60) {
    return 'D';
  } else {
    return 'F';
  }
} 
console.log(finalGrade(A, 92, 80)) // returns error A is not defined

Thanks :smiley:
Ib

The first step would be to validate the inputs. Your code does that. We need numeric input or our math will fail. For now that should be allowed to throw fatal errors. This is an important signal that we can benefit from by fail-safing against that type of error in the future. Test Driven Development is built upon this principle. Tackle the potential errors from the bottom up. First one to occur is the first one that gets mitigated.

All of the branches contain the same math pattern. That tells us we can perform it in one step before the conditional.

Once the inputs are validated,

const x = (num1 + num2 + num3) / 3

if (x < 60) { return 'F' } else
if (x < 70) { return 'D' } else
if (x < 80) { return 'C' ) else
if (x < 90) { return 'B' } else
return 'A'

Is using Number.isInteger() justified in this setting? It follows we should be able to take any number, float or integer. The above if statement will produce correct results for either.

const isNumber = n => typeof n === 'number';

The above is a predicate function. The name says what it returns.

Now we just need to give it a companion function to test the range.

const inRange = n => 0 <= n && n <= 100;

The syntax your function is written in supports an arguments object which allows us to iterate through the argument list without referencing the parameters.

x = Array.from(arguments)
for (y of x) {
    if (isNumber(y) && inRange(y)) {
        continue
    }
    return 'You have entered an invalid grade.'
}

Demo

 > function finalGrade(num1, num2, num3) {
       x = Array.from(arguments)
       for (y of x) {
           if (isNumber(y) && inRange(y)) {
               continue
           }
           return 'You have entered an invalid grade.'
       }
   }
<- undefined
 > finalGrade(50,60,70)
<- undefined
 > finalGrade(-50,60,170)
<- "You have entered an invalid grade."
 > finalGrade(a, b, c)
x > Uncaught ReferenceError: c is not defined

After, finalGrade(50,60,70) we get undefined as the response. This is what we want at that point, and tested here for that reason. Our logic can proceed from this point knowing the inputs are valid.

I don’t know what I’m missing here… the code works fine. but i still get error from codecademy

code begins

finalGrade = (num1, num2, num3)=>{

let avarage = (num1 + num2 + num3)/3

if(avarage <= 59 && avarage >=0){

return 'F'

} else if(avarage >= 60 && avarage <=69){

return 'D'

} else if(avarage >=70 && avarage <=79){

return 'C'

} else if(avarage >=80 && avarage <= 89){

return 'B'

} else if(avarage >=90 && avarage <=100){

return 'A'

} else {

return 'You have entered an invalid grade'

}

}

code ends

I can’t for the life of me figure out what I’m doing wrong. :confounded:
I’ve tried changing it several times based on tips I’ve read here and whatever I could think of myself after checking the cheatsheets, but no matter what I do it always ends up like this. It feels like I’m missing something super obvious but I just don’t see it.
If someone could please tell me where I’ve messed up and how I’m supposed to do it in the future, it’d be very much appreciated. :bowing_woman:t2:

Edit: I’ve figured out another way to do it by reading the replies here so I could technically just delete it and redo it by copying that, but I’d still like to know why my version fails so I know what to avoid in the future because in my eyes this should work just as well (though clearly it doesn’t…).

1 Like

With all that logic implemented one must have had good reason for it. So what was it? I ask you to ask yourself. Explain away…

Were any of the solutions you found, or the one you found, any simpler? Can you compare the logic you used to that logic and see where yours might have been weaker?

1 Like

After thinking about it, I’d say there was no good reason for it at all. I just kind of expected it to be really hard and complicated and so it didn’t even occur to me that less could be more. :thinking:
Even after simplifying my if/else if’s it still wouldn’t run, but I got it to work after changing my function-within-the-function averageScore to a regular variable. I have no idea why I made it a function in the first place… Is it ever necessary (or even possible) to create functions within functions?

A lot of the solutions I found were simpler, shorter and easier to read in general than mine, yet produced the same result that I wanted, so I’d say mine was weaker simply because it was overly complicated (to the point where it wouldn’t even work) when it really didn’t have to be.
Thank you for your reply, I’ll try not to make things harder than they have to be moving forward! :smile:

Yes it is possible and at times the way to write a dedicated function that only the parent function will ever need or use. We won’t be facing any of that in exercises so no stress.

My example above uses two helper functions to abstract away the value testing. Both of them could easily be written within the finalGrade function, at the top.

Hi @tomoecchi!
Your intention to understand the origin of the error message seems very valuable to me. It has also happened to me, and when I understand the origin of an error I feel that I learn better. :nerd_face:

Regarding your original code, beyond that maybe there is no need to use a function expression (a regular variable serves the same purpose in this case), the source of the error message is not there.

Your “finalGrade” function should work perfectly even if you had kept the declaration of your averageScore variable using a function expression.

But remember that when you declare a variable using a function expression, you cannot call that variable as you call a regular variable …

The error occurred because in the conditions of your if statements you call the variable averageScore as if you were calling a regular variable… when you should call it as if you were calling a function: averageScore() .

Cheers and happy coding! :heart: :keyboard:

1 Like