Meal Maker output issue

Hi!

I am stuck with the project Meal Maker
I have a problem with the output of my code:

let menu = {
  _courses: {
    appetizers: [],
    mains: [],
    desserts: [],
  },
  get courses() {
    return Object.entries(this.courses);
  },
	addDishToCourse (courseName, dishName, dishPrice) {
    let dish = {
      name: dishName,
      price: dishPrice
    };
    if (courseName === 'appetizers') {
    this._courses['appetizers'].push(dishName);
    }
    if (courseName === 'mains') {
    this._courses['mains'].push(dishName);
    }
    if (courseName === 'desserts') {
    this._courses['desserts'].push(dishName);
    }
  },
  getRandomDishFromCourse(courseName) {
    let dishes = this._courses[courseName];
    let randomNum = Math.floor(Math.random() * dishes.length);
    return dishes[randomNum];
  },
  generateRandomMeal: function() {
    let appetizer =  this.getRandomDishFromCourse('appetizers');
    let main =  this.getRandomDishFromCourse('mains');
    let dessert =  this.getRandomDishFromCourse('desserts');
    let totalPrice = appetizer.price + main.price + dessert.price;
    return `Your meal is ${appetizer.price}, ${main.price}, ${dessert.price}. The total price is ${totalPrice}.`;
  }
};
menu.addDishToCourse('appetizers', 'Caesar Salad', 4.25);
menu.addDishToCourse('appetizers', 'Mimosa Salad', 5);
menu.addDishToCourse('appetizers', 'Holloumi', 3);
menu.addDishToCourse('mains', 'Meat', 12);
menu.addDishToCourse('mains', 'Poultry', 14);
menu.addDishToCourse('mains', 'Fish', 16);
menu.addDishToCourse('desserts', 'Lava cake', 5);
menu.addDishToCourse('desserts', 'Icecream', 2);
menu.addDishToCourse('desserts', 'Bachlava', 3);

let meal = menu.generateRandomMeal();
console.log(meal);

The output in console looks like this:
Your meal is undefined, undefined, undefined. The total price is NaN.

What am I doing wrong?

You’ll want to work your way backwards from your output until you find the place(s) where you lost the actual values.

You can also test the individual functions, and if it’s too much code to handle then you may be able to remove some of it temporarily while debugging so that you have less to look at/consider.

Or start looking somewhere in the middle of the whole process to see if things are okay at that point to determine if the problem is later or earlier in time.

I have done that and I can successfully produce random dishes, but random meal fails to produce the result and I cannot figure out what’s wrong.

Then you would look at what’s being done after obtaining random dishes right? During some operation you’ll drop the ball. Which?

You don’t need to look at the code as a whole and see only whether the whole thing works. You can inspect parts of it.

The difference in how fast you and I will find the cause is mostly in how quick we both are to dig into the code and find out what happens as it happens. But there’s no difference in ability to do it, all you really need is to stick in some calls to console.log before and after doing things to find out whether it made the desired change, and to keep doing that for all the things that need to happen to be an overall working series of events.

Your output comes from here

let meal = menu.generateRandomMeal();
console.log(meal);

since that gets its data from menu.generateRandomMeal, you would continue by looking there.

    generateRandomMeal() {
        let appetizer =  this.getRandomDishFromCourse('appetizers');
        let main =  this.getRandomDishFromCourse('mains');
        let dessert =  this.getRandomDishFromCourse('desserts');
        let totalPrice = appetizer.price + main.price + dessert.price;
        console.log(appetizer, main, dessert)
        return `Your meal is ${appetizer.price}, ${main.price}, ${dessert.price}. The total price is ${totalPrice}.`;
    }

You’re using appetizer/main/dessert’s price properties. So maybe it would be a good idea to look at what those are, yeah? Print them out, like above. What do you see, and are there price properties of that?

Things don’t add up there, but how should it be instead? Well, as the programmer you better know, can’t write code when you don’t know what it’s supposed to say. Maybe you do know, and can now see the difference and think about what needs to change and where that change needs to happen, or if you don’t, then see what the instructions have to say about the things involved in the situation.

1 Like

@ionatan is giving some good advise. You may want to look into the properties of your meals :wink: .

@janneslohmeijer, @ionatan
I am still not getting what is wrong with the code. I get that within this function these properties don’t exist, but this what is done in the example in the course itself.
I tried the following code to fix it, but it doesn’t return the correct total price.

let menu = {
  _courses: {
    appetizers: [],
    mains: [],
    desserts: []
  },
  _coursesPrices:{
    appetizers: [],
    mains: [],
    desserts: []
  },
  get courses() {
    return Object.entries(this.courses);
  },
	addDishToCourse (courseName, dishName, dishPrice) {
    const dish = {
      name: dishName,
      price: dishPrice
    };
    if (courseName === 'appetizers') {
    this._courses['appetizers'].push(dishName);
    this._coursesPrices['appetizers'].push(dishPrice);
    }
    if (courseName === 'mains') {
    this._courses['mains'].push(dishName);
    this._coursesPrices['mains'].push(dishPrice);
    }
    if (courseName === 'desserts') {
    this._courses['desserts'].push(dishName);
    this._coursesPrices['desserts'].push(dishPrice);
    }
  },
  getRandomDishFromCourse(courseName) {
    const dishes = this._courses[courseName];
    const dishesP = this._coursesPrices[courseName];
    const randomNum = Math.floor(Math.random() * dishes.length);
    return [dishes[randomNum], dishesP[randomNum]];
  },
  generateRandomMeal() {
    const appetizer =  this.getRandomDishFromCourse('appetizers')[0];
    const main =  this.getRandomDishFromCourse('mains')[0];
    const dessert =  this.getRandomDishFromCourse('desserts')[0];
     const appetizerP =  this.getRandomDishFromCourse('appetizers')[1];
    const mainP =  this.getRandomDishFromCourse('mains')[1];
    const dessertP =  this.getRandomDishFromCourse('desserts')[1];
    const totalPrice = appetizerP + mainP + dessertP;
    return `Your meal is ${appetizer}, ${main}, ${dessert}. The total price is ${totalPrice}.`;
  }
};
menu.addDishToCourse('appetizers', 'Caesar Salad', 4.25);
menu.addDishToCourse('appetizers', 'Mimosa Salad', 5);
menu.addDishToCourse('appetizers', 'Holloumi', 3);
menu.addDishToCourse('mains', 'Meat', 12);
menu.addDishToCourse('mains', 'Poultry', 14);
menu.addDishToCourse('mains', 'Fish', 16);
menu.addDishToCourse('desserts', 'Lava cake', 5);
menu.addDishToCourse('desserts', 'Icecream', 2);
menu.addDishToCourse('desserts', 'Bachlava', 3);

let meal = menu.generateRandomMeal();
console.log(meal);

If they don’t exist, should you use them? If not, is there something else you should use instead?
Or if you should use them and they should exist but don’t, then where should they come from?

Think of it like legos or domino bricks to be lined up. Though, don’t connect it in the first way you see, better if you think about how you mean for it to be connected, and then change the part that isn’t so.

A big part of this all is to maintain very tight control, to know what everything should be. Codecademy tends to ask you to “hey copy paste this” but that won’t work at all when you need to fix something, then you need to firmly know what it is you’re writing and you’ll need to take a few steps back and obtain an understanding of how things are supposed to fit together and that may seem like a harsh change of pace but that’s the difference between writing code and copying text, isn’t it.

Hint: your dish is an object. Hope this helps.

@ionatan, @janneslohmeijer
I tried accessing dish object in generateRandomMeal function, but it returns error and furthermore it is not randomized.

Consider what information generateRandomMeal needs to have to do what it should be doing.
Write it down or something.
Does it have access to all those things?
If any of it is missing, where should it come from.

^ It’s probably about the fourth time I’m saying nearly this same thing, I’m aware that I’m repeating myself. You keep moving the target and I keep adjusting this same thing for the new target. But that’s all you need to be doing, if there’s another situation popping up, then this is still the same thing to be doing. Observe the situation and compare to what it should be, which part is different, change that part.

The thing is, nobody has any magical sight for finding problems, it’s going to be something along these lines to methodically figure out what’s up.

@micro3227863613, things are randomized, but the problem is that you are randomly choosing a dish name, and then randomly choosing a dish price. You’re not getting the price that corresponds to the randomly chosen dish name (unless you just happen to randomly choose the name and price at the same index).

Get rid of the separate _coursePrices property and instead of pushing only the dishName onto the courses for a given course name, push the entire dish object. That way, when you randomly choose a dish, you get its name and its price at the same time. Then make the requisite code changes to correspond to this new way of holding your information.

1 Like

The exercise is quite a mess, and its main benefit is probably entirely incidental – it’s difficult to follow so there’s going to be a mistake, and suddenly there’s a need to figure out what’s actually happening in the code, something that I imagine is often avoided when following codecademy’s instructions.

You’ll always make mistakes, and this demonstrates that there’s a need for control over what you’re writing and ability/willingness to fully dig into it as needed. You could consider the point to have been made, and move on without necessarily finishing, the project itself isn’t what matters.

Though if you do stick with it, I suggest spending some time with the instructions to figure out in full what should be happening. Looking at other parts of the code may also say quite a lot about how things are supposed to connect together.

Lets get back to your code from your first post since you are tracking further and further away from the solution. Now look at what defines a ‘dish’ and where it should be stored.

@chuckwondo
Thanks! It works now like this:

let menu = {
  _courses: {
    appetizers: [],
    mains: [],
    desserts: []
  },
  get courses() {
    return Object.entries(this.courses);
  },
	addDishToCourse (courseName, dishName, dishPrice) {
    const dish = {
      name: dishName,
      price: dishPrice
    };
    if (courseName === 'appetizers') {
    this._courses['appetizers'].push(dish);
    }
    if (courseName === 'mains') {
    this._courses['mains'].push(dish);
    }
    if (courseName === 'desserts') {
    this._courses['desserts'].push(dish);
    }
  },
  getRandomDishFromCourse(courseName) {
    const dishes = this._courses[courseName];
    const randomNum = Math.floor(Math.random() * dishes.length);
    return dishes[randomNum];
  },
  generateRandomMeal() {
    const appetizer =  this.getRandomDishFromCourse('appetizers');
    const main =  this.getRandomDishFromCourse('mains');
    const dessert =  this.getRandomDishFromCourse('desserts');
    const totalPrice = appetizer.price + main.price + dessert.price;
    return `Your meal is ${appetizer.name}, ${main.name}, ${dessert.name}. The total price is ${totalPrice}.`;
  }
};
menu.addDishToCourse('appetizers', 'Caesar Salad', 4.25);
menu.addDishToCourse('appetizers', 'Mimosa Salad', 5);
menu.addDishToCourse('appetizers', 'Holloumi', 3);
menu.addDishToCourse('mains', 'Meat', 12);
menu.addDishToCourse('mains', 'Poultry', 14);
menu.addDishToCourse('mains', 'Fish', 16);
menu.addDishToCourse('desserts', 'Lava cake', 5);
menu.addDishToCourse('desserts', 'Icecream', 2);
menu.addDishToCourse('desserts', 'Bachlava', 3);

let meal = menu.generateRandomMeal();
console.log(meal);

Now that @chuckwondo has presented you the solution on a silver plate. I am wondering how far you were from solving this yourself.

Also, your addDishToCourse method can be written with a lot less code and using no if statements or specific location pushers.

return this._courses[courseName].push(dish);

If you do insist on using if statements (only plus side is that it has a build in error handling, since you can provide a message if a meal entered is not an appetizer, main or dessert :wink: ). I suggest not using 3 consecutive if statements but use an if ... else if .... else statement like so and build in the error message.

if (courseName === 'appetizers') {
    return this._courses['appetizers'].push(dishName);
} else if (courseName === 'mains') {
    return this._courses['mains'].push(dishName);
} else if (courseName === 'desserts') {
    return this._courses['desserts'].push(dishName);
} else {
    return console.log('Course is not valid, only options are appetizers, mains and desserts.'); 
}

@janneslohmeijer
This code:

was not working for some reason so I switched to if statements