Meal Maker

I am trying to figure out why the following source code does not run. Any help and explanation are appreciated. Here is the hyperlink of the exercise.

  • Thanks in advance
Tasks -->
// 1.0 Start by creating an empty menu object. [DONE]
// 2.0 Add a _courses property to your menu object and set its value to an empty object. This property will ultimately contain a mapping between each course and the dishes available to order in that course. [DONE]
// 3.0 Create three properties inside the _courses object called appetizers, mains, and desserts. Each one of these should initialize to an empty array. [DONE]
// 4.0 Create getter and setter methods for the appetizers, mains, and desserts properties. [DONE]
// 5.0 Inside your menu object, create an empty getter method for the _courses property. [DONE]
// 6.0 Inside the courses getter method, return an object that contains key/value pairs for appetizers, mains, and desserts. [DONE]
// 7.0 Inside the menu object, we are going to create a method called .addDishToCourse() which will be used to add a new dish to the specified course on the menu. The method should take in three parameters: the courseName, the dishName , and the dishPrice. [DONE]
// 8.0 The .addDishToCourse() method should create an object called dish which has a name and price which it gets from the parameters. The method should then push this dish object into the appropriate array in your menu‘s _courses object based on what courseName was passed in. [DONE]
// 9.0 Now, we’re going to need another function which will allow us to get a random dish from a course on the menu, which will be necessary for generating a random meal. Create a method inside the menu object called .getRandomDishFromCourse(). It will take in one parameter which is the courseName. [DONE]
// 10.0 There are a few steps in getting the .getRandomDishFromCourse() to work. Retrieve the array of the given course’s dishes from the menu‘s _courses object and store in a variable called dishes. Generate a random index by multiplying Math.random() by the length of the dishes array (This will guarantee that the random number will be between 0 and the length of the array) Round that generated number to a whole number by using Math.floor() on the result. Return the dish located at that index in dishes. [DONE]
// 11.0 Now that we have a way to get a random dish from a course, we can create a .generateRandomMeal() function which will automatically generate a three-course meal for us. The function doesn’t need to take any parameters. The function should create an appetizer variable which should be the result of calling the .getRandomDishFromCourse() method when we pass in an appetizers string to it. Create a main variable and dessert variable the same way you created the appetizer variable, but make sure to pass in the right course type. Calculates the total price and returns a string that contains the name of each of the dishes and the total price of the meal, formatted as you like.
// 12.0 Now that we’ve finished our menu, object, let’s use it to create a menu by adding some appetizers, mains, and desserts with the .addDishToCourse() function. Add at least 3 dishes to each course (or more if you like!). [DONE]
Source Code -->

let menu = {
	_courses : {
		appetizers : [],
		mains : [],
		desserts : [],
		get appetizers() {
			return this._courses.appetizers;
		},
		set appetizers(inputOne) {
			this._courses.appetizers.push(appetizer);
		},
		get mains() {
			return this._courses.mains;
		},
		set mains(inputTwo) {
			this._courses.mains.push(main);
		},
		get desserts() {
			return this._courses.desserts;
		},
		set desserts(inputThree) {
			this._courses.desserts.push(dessert);
		}
	},
		get _courses() {
				return {
					appetizers: this.appetizers,
					mains: this.mains,
					desserts: this.desserts
				}
			},
		addDishToCourse(courseName, dishName, dishPrice) {
			const dish = {
				name : this.dishName,
				price: this.dishPrice
			};
			this._courses[courseName] = dish;
		},
		getRandomDishFromCourse(courseName) {
			let dishes = this._courses[courseName];
			let randomIndex = Math.floor(Math.random() * dishes.length);
			return dishes[randomIndex]; // Attention
		},
		generateRandomMeal() {
			let appetizer = this.getRandomDishFromCourse('appetizers');
			let main = this.getRandomDishFromCourse('mains');
			let dessert = this.getRandomDishFromCourse('desserts');
			let totalPrice = appetizer.price + main.price + dessert.price;
			return `${appetizer.name} "," ${main.name} "," ${dessert.name} "," ${totalPrice}`;
		}
	};
	
	menu.addDishToCourse('appetizers', 'Easy Beer Bread', 10);
	menu.addDishToCourse('mains', 'Chicken Soup', 15);
	menu.addDishToCourse('desserts', 'Banana Split', 5);

	menu.addDishToCourse('appetizers', 'Pizza Rolls', 7);
	menu.addDishToCourse('mains', 'Fried Chicken', 17);
	menu.addDishToCourse('desserts', 'Brownie', 6);

	menu.addDishToCourse('appetizers', 'Reuben Roll Ups', 12);
	menu.addDishToCourse('mains', 'Pizza', 20);
	menu.addDishToCourse('desserts', 'Cake', 7);

	let meal = menu.generateRandomMeal();
	console.log(meal);
	
Error Output -->
TypeError: Cannot read property 'length' of undefined
    at Object.getRandomDishFromCourse (/script.js:56:56)
    at Object.generateRandomMeal (/script.js:60:25)
    at /script.js:80:18

well, we could inspect our code by logging some relevant information:

		getRandomDishFromCourse(courseName) {
			let dishes = this._courses[courseName];
                        console.log(dishes, this._courses, courseName);
			let randomIndex = Math.floor(Math.random() * dishes.length);
			return dishes[randomIndex]; // Attention
		},

simply insert the .log() within your code, run it, to see the output.

Well, that is slightly problematic.

Given we start of with an array, undefined must come from somewhere. What gives undefined? Accessing a property (or getter) that doesn’t exist, so maybe here:

		get _courses() {
				return {
					appetizers: this.appetizers,
					mains: this.mains,
					desserts: this.desserts
				}
			},

_courses object doesn’t have a appetizers property or getter, so this.appetizers will result in undefined.

Putting asides that JS should give an error for trying to access property which doesn’t exist on an Object, but that is a whole different story.

That describes a situation for which execution cannot continue. Do you agree that this situation doesn’t have a sane way to continue?

It also says where you have that situation

and then you’d compare to what you meant should happen there and adjust accordingly