diff --git a/mandatory/1-writers.js b/mandatory/1-writers.js index f815c156..15bb9a2e 100644 --- a/mandatory/1-writers.js +++ b/mandatory/1-writers.js @@ -19,7 +19,10 @@ use values inside Objects. */ + + // We've created an array of objects for you here: + let writers = [ { firstName: "Virginia", @@ -55,9 +58,11 @@ let writers = [ occupation: "writer", age: 49, alive: true, - } + }, ]; + + /* Exercise 1: @@ -66,9 +71,23 @@ Exercise 1: "Hi, my name is {firstName} {lastName}. I am {age} years old, and work as a {occupation}." */ + + + function logAllWriters() { - // write your code to log all writers here -}; + writers.forEach((writer) => { + console.log( + `Hi, my name is ${writer.firstName} ${writer.lastName}. I am ${writer.age} years old, and work as a ${writer.occupation}.` + ); + }); +} + +// Because we have an ***array of objects***, I have used .forEach to iterate over each array object. +// Inside the forEach there is a call back function that takes the array as a parameter (writers) +// and console.logs a concatenated string that prints the desired properties of the objects. + + + /* Exercise 2: @@ -79,10 +98,44 @@ Exercise 2: "Writer {firstName} {lastName} died at {age} years old." */ + function logDeadWritersInTheirForties() { - // write your code here + return writers.forEach((writer) => { + if (writer.age >= 40 && writer.age <= 49 && writer.alive === false) { + console.log( + `Writer ${writer.firstName} ${writer.lastName} died at ${writer.age} years old.` + ); + } + }); } +// Here .forEach has been used again to iterate over each array object. A callback function taking the array +// a parameter has been used but this time uses an if-statement to console.log selected objects (writers) +// if they meet a certain condition. In this case we are checking the writers age and the value of one of +// the property "alive". + +/* ALTERNATIVE SOLUTION >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +writers.forEach(function ({ firstName, lastName, age, alive }) { + const isIn40s = 40 <= age && age <= 49; + + if (!alive && isIn40s) console.log(`Writer ${firstName} ${lastName} died at ${age} years old.`); +}); + +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +In this solution, notice that we've stored the expression 40 <= age && age <= 49 +in a variable called isIn40s. Sometimes well named variables will help improve the +readability and maintenance of your code base. + +We also use the ! operator, called the logical NOT operator. +This will invert the value of a boolean, for example: + +*/ + + + + /* Exercise 3: @@ -92,38 +145,69 @@ Exercise 3: */ function logAliveWritersInTheirForties() { - // write your code here + return writers.forEach((writer) => { + if (writer.age >= 40 && writer.age <= 49 && writer.alive === true) { + console.log( + `Hi, my name is ${writer.firstName} ${writer.lastName}. I am ${writer.age} years old.` + ); + } + }); } -/* ======= TESTS - DO NOT MODIFY ===== +/* + +ALTERNATIVE SOLUTION >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>. + +writers.forEach(function ({ firstName, lastName, age, alive }) { + const isIn40s = 40 <= age && age <= 49; + + if (alive && isIn40s) + console.log(`Hi, my name is ${firstName} ${lastName}. I am ${age} years old.`); +}); + + +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + + + + + + + + +======= TESTS - DO NOT MODIFY ===== - To run the tests for this exercise, run `npm test -- --testPathPattern 1-writers.js` - To run all exercises/tests in the mandatory folder, run `npm test` - (Reminder: You must have run `npm install` one time before this will work!) */ -test("exercise 1", () => expectFunctionToLog(logAllWriters, [ - "Hi, my name is Virginia Woolf. I am 59 years old, and work as a writer.", - "Hi, my name is Zadie Smith. I am 40 years old, and work as a writer.", - "Hi, my name is Jane Austen. I am 41 years old, and work as a writer.", - "Hi, my name is Bell Hooks. I am 63 years old, and work as a writer.", - "Hi, my name is Yukiko Motoya. I am 49 years old, and work as a writer." -])); - -test("exercise 2", () => expectFunctionToLog(logDeadWritersInTheirForties, [ - "Writer Jane Austen died at 41 years old." -])); - -test("exercise 3", () => expectFunctionToLog(logAliveWritersInTheirForties, [ - "Hi, my name is Zadie Smith. I am 40 years old.", - "Hi, my name is Yukiko Motoya. I am 49 years old." -])); +test("exercise 1", () => + expectFunctionToLog(logAllWriters, [ + "Hi, my name is Virginia Woolf. I am 59 years old, and work as a writer.", + "Hi, my name is Zadie Smith. I am 40 years old, and work as a writer.", + "Hi, my name is Jane Austen. I am 41 years old, and work as a writer.", + "Hi, my name is Bell Hooks. I am 63 years old, and work as a writer.", + "Hi, my name is Yukiko Motoya. I am 49 years old, and work as a writer.", + ])); + +test("exercise 2", () => + expectFunctionToLog(logDeadWritersInTheirForties, [ + "Writer Jane Austen died at 41 years old.", + ])); + +test("exercise 3", () => + expectFunctionToLog(logAliveWritersInTheirForties, [ + "Hi, my name is Zadie Smith. I am 40 years old.", + "Hi, my name is Yukiko Motoya. I am 49 years old.", + ])); function expectFunctionToLog(f, values) { - const consoleLogSpy = jest.spyOn(console, 'log'); - f(); - expect(consoleLogSpy).toBeCalledTimes(values.length); - values.forEach((value, i) => { - expect(consoleLogSpy).nthCalledWith(i+1, value); - }); - consoleLogSpy.mockRestore(); -}; \ No newline at end of file + const consoleLogSpy = jest.spyOn(console, "log"); + f(); + expect(consoleLogSpy).toBeCalledTimes(values.length); + values.forEach((value, i) => { + expect(consoleLogSpy).nthCalledWith(i + 1, value); + }); + consoleLogSpy.mockRestore(); +} diff --git a/mandatory/10-cheap-diner.js b/mandatory/10-cheap-diner.js index 302dfbb9..a67cbca8 100644 --- a/mandatory/10-cheap-diner.js +++ b/mandatory/10-cheap-diner.js @@ -2,20 +2,23 @@ The Frugal Gentleman -Atticus has been invited to a dinner party, and he decides to purchase a meal to share with he party -Being a very frugal gentleman (yet disliking looking like a cheapskate), he decides to use a very simple rule. +Atticus has been invited to a dinner party, and he decides to purchase a meal +to share with he party. Being a very frugal gentleman (yet disliking looking +like a cheapskate), he decides to use a very simple rule. In any selection of two or more meals, he will always buy the second-cheapest. If there is no choice, then he will buy the only meal given to him. If there are no meals available, then he will return null -Given an array of Meal objects, write a function that returns the name of the Meal he will buy for the party. If given an array of only one, Atticus will buy that Meal. +Given an array of Meal objects, write a function that returns the name of the +Meal he will buy for the party. If given an array of only one, Atticus will buy that Meal. let setOne = [ { name: "Turkey", price: 8.99 }, { name: "Chicken", price: 13.99 }, { name: "Lobster", price: 10.99 } ] + chosenMeal(setOne) Should give the answer "Lobster" @@ -27,6 +30,30 @@ chosenMeal(emptyArray) Should give the answer "Nothing :(" +SOLUTION >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + +function chooseMeal(mealArray) { + mealArray.sort((mealA, mealB) => mealA.price - mealB.price); + + const secondCheapestMeal = mealArray[1]; + const cheapestMeal = mealArray[0]; + const nothingAvailableMessage = 'Nothing :('; + + if (secondCheapestMeal) return secondCheapestMeal.name; + else if (cheapestMeal) return cheapestMeal.name; + else return nothingAvailableMessage; +} + +We can break down this solution into several parts: + +Sort the array of meals into ascending order by price +Access the first and second positions in the array +(which should be the cheapest and second cheapest, respectively ) +Check these elements and then return the names depending on whether the elements exist or not +Notice in our solution that we are passing a callback function to sort in order to specify +that we want to sort by the price property on each meal object. + **/ function chooseMeal(mealArray) { diff --git a/mandatory/11-choose-your-own-adventure.js b/mandatory/11-choose-your-own-adventure.js index 60e49d43..26a14e6d 100644 --- a/mandatory/11-choose-your-own-adventure.js +++ b/mandatory/11-choose-your-own-adventure.js @@ -45,7 +45,62 @@ room doesn't allow? For example if you are in the Classroom and you try to move east? If there is a bug in your code, try to fix it. To enable the tests for the stretch goals, remove the ".skip" on the appropriate tests below. -*/ + +******************************************************************************************/ +//SOLUTION COPIED + +let game = { + currentRoom: null, + start: function (roomName) { + // This function is called with the name of the room that the player wants + // to start in. + // Finish the function so that the currentRoom property is set to the room + // object for the correct room. + // Hint: the only valid rooms are "hall", "classroom" and "library". + if (roomName === "hall") { + this.currentRoom = rooms.hall; + } else if (roomName === "classroom") { + this.currentRoom = rooms.classroom; + } else if (roomName === "library") { + this.currentRoom = rooms.library; + } + }, + + move: function (direction) { + // This function is called with the direction that the player wants to move. + // Finish the function so that the currentRoom property is updated with new + // room in the direction that the player wants to move in. + // + // Hint: the room objects have north/east/south/west methods which return + // a new room object that is in the relevant direction. + + if (direction === "north") { + this.currentRoom = this.currentRoom.north(); + } else if (direction === "east") { + this.currentRoom = this.currentRoom.east(); + } else if (direction === "south") { + this.currentRoom = this.currentRoom.south(); + } else if (direction === "west") { + this.currentRoom = this.currentRoom.west(); + } + }, +}; + +/*************************************************************************************** + +The basic solution is to check the roomName to determine which room +object within the rooms object should be assigned to this.currentRoom. +So for example, if the player types "hall", it is passed to the start method +as the roomName parameter. We can then check whether it is "hall", "classroom" +or "library" and set this.currentRoom to be the appropriate object inside rooms. + +The basic solution is to check the direction to determine which method to call on the +this.currentRoom object. When the player types in a direction, it is passed to the move +method as the direction parameter. We can then check if it is "north", "east", "south" or "west" +and call the appropriate method in the this.currentRoom object. +This returns the new room object and so we change this.currentRoom to be assigned to the new room object. + +******************************************************************************************/ let game = { currentRoom: null, diff --git a/mandatory/2-eligible-students.js b/mandatory/2-eligible-students.js index cb472063..a3d2ba68 100644 --- a/mandatory/2-eligible-students.js +++ b/mandatory/2-eligible-students.js @@ -9,20 +9,41 @@ After you complete the exercise, compare your solution to your previous one. Can you see how using objects leads to more clear code? - ------------------------------------------------------------------------- + **LAST WEEKS SOLUTION** + const getEligibleStudents = + arr => arr.filter((item => item[1] >= 8)).map(item => item[0]); + + ****************************************************************************************** Only students who have attended enough classes are eligible to sit an exam. Create a function which: + - Accepts an array which contains all the students' names and their attendance counts (see tests to confirm how this data will be structured) - Returns an array containing only the names of the who have attended AT LEAST 8 classes - */ + + ******************************************************************************************/ function eligibleStudents(attendances) { - + return attendances + .filter((student) => student.attendance >= 8) + .map((student) => student.name); } +/****************************************************************************************** + +As we have an *array of objects* we can use the array method .filter +to filter out only the array values to return. The .filter method filters +the values but it does not return an array so we can chain the method .map to +return a new array containing only the student names of the filtered results. + +My code is almost the same as last weeks, except rather than filtering nested +array values we are filtering object values. I'm unsure if this is any easier or +what the specific benefits are. + +*******************************************************************************************/ + /* ======= TESTS - DO NOT MODIFY ===== - To run the tests for this exercise, run `npm test -- --testPathPattern 2-eligible-students.js` - To run all exercises/tests in the mandatory folder, run `npm test` @@ -30,15 +51,19 @@ function eligibleStudents(attendances) { */ const attendances = [ - {name: "Ahmed", attendance: 8}, - {name: "Clement", attendance: 10}, - {name: "Elamin", attendance: 6}, - {name: "Adam", attendance: 7}, - {name: "Tayoa", attendance: 11}, - {name: "Nina", attendance: 10}, + { name: "Ahmed", attendance: 8 }, + { name: "Clement", attendance: 10 }, + { name: "Elamin", attendance: 6 }, + { name: "Adam", attendance: 7 }, + { name: "Tayoa", attendance: 11 }, + { name: "Nina", attendance: 10 }, ]; - + test("eligibleStudents function works", () => { - expect(eligibleStudents(attendances)).toEqual(["Ahmed", "Clement", "Tayoa", "Nina"]); + expect(eligibleStudents(attendances)).toEqual([ + "Ahmed", + "Clement", + "Tayoa", + "Nina", + ]); }); - \ No newline at end of file diff --git a/mandatory/3-journey-planner.js b/mandatory/3-journey-planner.js index 2a96b8a2..9683a4e0 100644 --- a/mandatory/3-journey-planner.js +++ b/mandatory/3-journey-planner.js @@ -7,16 +7,7 @@ Write a function journeyPlanner that: - - Accepts two paramters: - 1) An object where the keys are locations and the values are arrays of the transportation modes you can use to get there. - e.g. - { - Angel: ["tube", "bus"], - "London Bridge": ["tube", "river boat"], - } - - 2) A string containing a transport mode - e.g. "bus" + - Accepts two parameters, the object and a string value for mode of transport: - Returns an array of where I can go if I only want to use a specific mode of transport. @@ -24,12 +15,19 @@ When you finish the exercise, think about how this solution is different to your last solution. What's better about each approach? + */ -function journeyPlanner(locations, transportMode) { - + +function journeyPlanner(locationsObj, transportStr) { + const placesInLondon = Object.keys(locationsObj); //returns array of locations (keys) in the object + const hasTransportMode = placesInLondon.filter((values) => // filter locations array + locationsObj[values].includes(transportStr) //how does locationsArr[values] access the values? + ); + return hasTransportMode; } + /* ======= TESTS - DO NOT MODIFY ===== - To run the tests for this exercise, run `npm test -- --testPathPattern 3-journey-planner.js` - To run all exercises/tests in the mandatory folder, run `npm test` diff --git a/mandatory/4-water-bottle.js b/mandatory/4-water-bottle.js index 4e914d11..ae9c6799 100644 --- a/mandatory/4-water-bottle.js +++ b/mandatory/4-water-bottle.js @@ -1,9 +1,8 @@ -/* -Create an object that acts a water bottle. +/**************************************************************************************** -It will need a volume property to store how full or empty the bottle is. - -Volume will be 100 when bottle is full and 0 when empty. +Create an object that acts a water bottle. It will need a volume property +to store how full or empty the bottle is. Volume will be 100 when bottle +is full and 0 when empty. Give your water bottle methods for - filling it up @@ -15,48 +14,48 @@ Give your water bottle methods for - and telling if the bottle is empty We made a start on this here by giving you the skeleton of our object. - You have to implement the missing features according to the specification. -*/ -// Here is your starting point: +****************************************************************************************/ + let bottle = { volume: 0, + fullCapacity: 100, fillUp: function () { - // calling this function should completely fill your bottle (volume = 100); + if (!this.isFull()) this.volume = this.fullCapacity; }, pour: function () { - // calling this function should increase your bottle volume by 10 units; + const tenDrinkingUnits = 10; + if (!this.isFull()) this.volume += tenDrinkingUnits; }, drink: function () { - // calling this function should decrease your bottle volume by 10 units; + const tenDrinkingUnits = 10; + if (!this.isEmpty()) this.volume -= tenDrinkingUnits; }, isFull: function () { - // this function should return true if your bottle is full; + return this.volume === this.fullCapacity; }, isEmpty: function () { - // this function should return true if your bottle is empty; + return this.volume === 0; }, }; -/* + +/**************************************************************************************** TIP: - Remember that for changing properties on the current object inside one of its - methods you can refer to it by its variable name: `bottle` or by using the keyword `this`. -*/ + Remember that for changing properties on the current object inside + one of its methods you can refer to it by its variable + name: `bottle` or by using the keyword `this`. +*****************************************************************************************/ -/* +/**************************************************************************************** Extra question: - Why do you think it is preferred to use `this` inside the object rather than its variable name, in our case `bottle`? - Leave your answer below: -*/ + Why do you think it is preferred to use `this` inside the object rather + than its variable name, in our case `bottle`? + Leave your answer below: -// Write you answer to the question here - -/* -Once you have completed your object run the following -and see if your answer matches the expected result at the bottom :) -*/ + Answer: Is it more specific? +*****************************************************************************************/ /* ======= TESTS - DO NOT MODIFY ===== - To run the tests for this exercise, run `npm test -- --testPathPattern 4-water-bottle.js` diff --git a/mandatory/5-groceries.js b/mandatory/5-groceries.js index 2855fdcb..30b90eba 100644 --- a/mandatory/5-groceries.js +++ b/mandatory/5-groceries.js @@ -1,48 +1,116 @@ -/* -As you you can have an Array of Objects, you can also store Arrays in Objects. +/**************************************************************************************** In this exercise, you'll practice: - How to loop through the properties (keys) of an Object and read its values. - How to access an Array stored inside an Object. - How to access a specific property of an object and set it. -You're going shopping, and you need a shopping list. You've already created your weekly meal plan -that contains the missing ingredients for your menus. It is stored in the "weeklyMealPlan" object. -Complete the exercises below. -*/ +You're going shopping and you need a shopping list. +You've already created your weekly meal plan which +contains the missing ingredients for your menu. +This is stored in the "weeklyMealPlan" object. + +*****************************************************************************************/ -// Here is your let weeklyMealPlan = { monday: ["Cheese", "Eggs", "Tomato", "Paprika", "Leek"], tuesday: ["Wrap", "Tuna", "Canned beans", "Cheese", "Carrot", "Aubergine"], - wednesday: ["Orange Juice", "Apple", "Ananas", "Black tea"], + wednesday: ["Orange Juice", "Apple", "Bananas", "Black tea"], thursday: ["Lamb", "Salt", "Bulgur", "Potato"], friday: ["Rice milk", "Blueberries", "Porridge", "Banana", "Cinnamon"], saturday: ["Olive oil", "Potato", "Salmon", "Asparagus"], sunday: [], }; -/* +/************************************************************************************** Exercise 1: - Loop through the weekly meal plan object to gather weekly ingredients into the weeklyGroceriesToBuy array. - The weeklyGroceriesToBuy array shouldn't contain any repeating items. -*/ -// Gather all week item names into this array + +Loop through the weekly meal plan object to gather weekly ingredients +into the weeklyGroceriesToBuy array. The weekly GroceriesToBuy array +shouldn't contain any repeating items. + +****************************************************************************************/ + let weeklyGroceriesToBuy = []; -/* +//return array of values (nested array) +Object.values(weeklyMealPlan).forEach((ingredientsForADay) => { //for each value set + ingredientsForADay.forEach((ingredient) => { //for each ingredient + if (!weeklyGroceriesToBuy.includes(ingredient)) weeklyGroceriesToBuy.push(ingredient); + }); //if it doesn't include ingredient (already) push it to new array. +}); +console.log('weeklyGroceriesToBuy: ', weeklyGroceriesToBuy); + + +/**************************************************************************************** Exercise 2: - Loop through your list again, but now only collect the weekend items into the weekendGroceriesToBuy array. -*/ -// Gather weekend item names into this array + +Loop through your list again, but now only collect the +weekend items into the weekendGroceriesToBuy array. + +******************************************************************************************/ + let weekendGroceriesToBuy = []; -/* +//turn keys & values into array +Object.entries(weeklyMealPlan).forEach((keyValuePair) => { + const day = keyValuePair[0]; //grab day + const ingredientsForADay = keyValuePair[1]; //grab ingredients + if (day === "saturday" || day === "sunday") { + weekendGroceriesToBuy = weekendGroceriesToBuy.concat(ingredientsForADay); + } +}); + +console.log("weekendGroceriesToBuy: ", weekendGroceriesToBuy); + +/*************************************************************************************** +//REFERENCE + +Object.entries will evaluate each property of the object as an array of entries: +const person = { name: 'Barny', age: 22 }; +Object.entries(person) = + +[ + ['name', 'Barny'], + ['age', 22], +]; + +Each inner array stores a key-value pair from the original object. +Object.entries(weeklyMealPlan); +will evaluate to + +[ + ['monday', ['Cheese', 'Eggs', 'Tomato', 'Paprika', 'Leek']], + ['tuesday', ['Wrap', 'Tuna', 'Canned beans', 'Cheese', 'Carrot', 'Aubergine']], + ['wednesday', ['Orange Juice', 'Apple', 'Bananas', 'Black tea']], + ['thursday', ['Lamb', 'Salt', 'Bulgur', 'Potato']], + ['friday', ['Rice milk', 'Blueberries', 'Porridge', 'Banana', 'Cinnamon']], + ['saturday', ['Olive oil', 'Potato', 'Salmon', 'Asparagus']], + ['sunday', []], +]; + +We can then use forEach over this array of arrays and access the day of week and +the ingredients for a given day: + +Object.entries(weeklyMealPlan).forEach((keyValuePair) => { + const day = keyValuePair[0]; + const ingredientsForADay = keyValuePair[1]; +}); + +keyValuePair will be assigned to +['monday', ['Cheese', 'Eggs', 'Tomato', 'Paprika', 'Leek']]; + +*****************************************************************************************/ + +/**************************************************************************************** Exercise 3: - Loop through your weekly meal plan: - - count how many ingredients you should buy each day - - and update the corresponding properties of numberOfItemsPerWeek object. -*/ + +Loop through your weekly meal plan: + - count how many ingredients you should buy each day + - and update the corresponding properties of numberOfItemsPerWeek object. + +*****************************************************************************************/ + // Gather daily item counts into this object let numberOfItemsPerWeek = { monday: 0, @@ -54,6 +122,17 @@ let numberOfItemsPerWeek = { sunday: 0, }; +Object.entries(weeklyMealPlan).forEach(([day, ingredientsForADay]) => { + numberOfItemsPerWeek[day] = ingredientsForADay.length; +}); + +/**************************************************************************************** +NOTES: + +Is [day] accessing and updating the objects values? I don't get how this part is working. + +*****************************************************************************************/ + /* ======= TESTS - DO NOT MODIFY ===== - To run the tests for this exercise, run `npm test -- --testPathPattern 5-groceries.js` - To run all exercises/tests in the mandatory folder, run `npm test` @@ -62,26 +141,48 @@ let numberOfItemsPerWeek = { test("Exercise 1 - Weekly groceries to buy contains correct items", () => { const expectedWeeklyGroceriesToBuy = [ - 'Cheese', 'Eggs', - 'Tomato', 'Paprika', - 'Leek', 'Wrap', - 'Tuna', 'Canned beans', - 'Carrot', 'Aubergine', - 'Orange Juice', 'Apple', - 'Ananas', 'Black tea', - 'Lamb', 'Salt', - 'Bulgur', 'Potato', - 'Rice milk', 'Blueberries', - 'Porridge', 'Banana', - 'Cinnamon', 'Olive oil', - 'Salmon', 'Asparagus' + "Cheese", + "Eggs", + "Tomato", + "Paprika", + "Leek", + "Wrap", + "Tuna", + "Canned beans", + "Carrot", + "Aubergine", + "Orange Juice", + "Apple", + "Ananas", + "Black tea", + "Lamb", + "Salt", + "Bulgur", + "Potato", + "Rice milk", + "Blueberries", + "Porridge", + "Banana", + "Cinnamon", + "Olive oil", + "Salmon", + "Asparagus", ]; - expect(weeklyGroceriesToBuy).toIncludeSameMembers(expectedWeeklyGroceriesToBuy); + expect(weeklyGroceriesToBuy).toIncludeSameMembers( + expectedWeeklyGroceriesToBuy + ); }); test("Exercise 2 - Weekend groceries to buy contains correct items", () => { - const expectedWeekendGroceriesToBuy = ["Olive oil", "Potato", "Salmon", "Asparagus"]; - expect(weekendGroceriesToBuy).toIncludeSameMembers(expectedWeekendGroceriesToBuy); + const expectedWeekendGroceriesToBuy = [ + "Olive oil", + "Potato", + "Salmon", + "Asparagus", + ]; + expect(weekendGroceriesToBuy).toIncludeSameMembers( + expectedWeekendGroceriesToBuy + ); }); test("Exercise 3 - Numer of items per week contains the correct counts", () => { @@ -95,4 +196,4 @@ test("Exercise 3 - Numer of items per week contains the correct counts", () => { sunday: 0, }; expect(numberOfItemsPerWeek).toEqual(expectedNumberOfItemsPerWeek); -}); \ No newline at end of file +}); diff --git a/mandatory/6-people-I-know.js b/mandatory/6-people-I-know.js index 39cea6d0..7ca7e179 100644 --- a/mandatory/6-people-I-know.js +++ b/mandatory/6-people-I-know.js @@ -1,14 +1,11 @@ -/* -Below you will find a list of people that I know. -*/ - -/* +/***************************************************************************************** 1) Reading -Before you start, you should read through the object below so that you understand the structure of it. +Before you start, you should read through the object below so +that you understand the structure of it. When you've finished +continue to the exercises below. -When you've finished. Continue to the exercises below. -*/ +******************************************************************************************/ const friends = [ { @@ -373,53 +370,83 @@ const friends = [ }, ]; -/* +/**************************************************************************************** + 2) Aged 35 or Older In the above object you can see my friends and the colleagues of my friends. - First, I want you to find all of my friends who are 35 or older. -*/ +*****************************************************************************************/ -let thirtyFiveOrOlder = []; +let thirtyFiveOrOlder = friends.filter(function (friend) {//filter friends array + const lowerAgeLimit = 35; //store number in variable (best practice) + return friend.age >= lowerAgeLimit; //return friend.ages greater than 35 +}); -/* +/**************************************************************************************** + 3) Find the email address -Next, I want you to find all of my friends who work for "POWERNET" and then store their emails in the array below +Next, I want you to find all of my friends who work for "POWERNET" +and then store their emails in the array below -*/ +*****************************************************************************************/ -let powerNetEmails = []; +let powerNetEmails = friends + .filter(function (friend) { + // filter friends company by search term + const companySearchTerm = "POWERNET"; + return friend.company === companySearchTerm; + }) + .map(function (friend) { + return friend.email; //return array of emails of filtered friends + }); -/* +/***************************************************************************************** 4) colleagues with "Stacie Villarreal" Next, I want you to find all of my friends who are colleagues of Stacie Villarreal. +You can see who people's colleagues are by seeing the "colleagues" array in each +of my friends objects. This time, I only want the full names +(" ") of my friends who are colleagues of hers. -You can see who people's colleagues are by seeing the "colleagues" array in each of my friends objects. +*******************************************************************************************/ -This time, I only want the full names (" ") of my friends who are colleagues of hers. +let friendsWhoAreColleaguesOfStacie = []; -*/ +friends.forEach((friend) => { //for each friend + friend.colleagues.forEach((colleague) => { //for each friend colleague + if (colleague.name === "Stacie Villarreal") //check if colleague name = stacie + friendsWhoAreColleaguesOfStacie.push( + //if true, push name into new arr + `${friend.name.first} ${friend.name.last}` + ); + }); +}); -let friendsWhoAreColleaguesOfStacie = []; -/* +/**************************************************************************************** 5) Find "Multi-tasking" colleagues Next, I want you to find all of the colleagues of my friends who are good at "Multi-tasking" - You can tell if they are good at "Multi-tasking" because they will have it listed in their skills +This time, I only want the full names of the people who can multitask. -This time, I only want the full names of the people who can multitask - -*/ +/*************************************************************************************** */ let colleaguesWhoCanMultitask = []; +friends.forEach((friend) => { //for each friend + friend.colleagues.forEach((colleague) => { //for each of their colleagues + colleague.skills.forEach((skill) => { //for each colleague skill + if (skill === "Multi-tasking") //push ones matching multi-tasking + colleaguesWhoCanMultitask.push(colleague.name); + }); + }); +}); + /* ======= TESTS - DO NOT MODIFY ===== - To run the tests for this exercise, run `npm test -- --testPathPattern 6-people-I-know.js` - To run all exercises/tests in the mandatory folder, run `npm test` @@ -427,8 +454,12 @@ let colleaguesWhoCanMultitask = []; */ test("2 - friends that are over 35", () => { - expect(thirtyFiveOrOlder.map(({name}) => name.first)).toIncludeSameMembers([ - "Vilma", "Aisha", "Mitchell", "Sutton", "Jana" + expect(thirtyFiveOrOlder.map(({ name }) => name.first)).toIncludeSameMembers([ + "Vilma", + "Aisha", + "Mitchell", + "Sutton", + "Jana", ]); }); @@ -449,10 +480,10 @@ test("4 - friends with Stacie Villarreal as a colleague", () => { test("5 - colleagues who can multitask", () => { expect(colleaguesWhoCanMultitask).toIncludeSameMembers([ - "Rush May", - "Gena Good", - "Cunningham Shelton", - "Castro Castaneda", - "Luz Newton", + "Rush May", + "Gena Good", + "Cunningham Shelton", + "Castro Castaneda", + "Luz Newton", ]); }); diff --git a/mandatory/7-recipes.js b/mandatory/7-recipes.js index da790642..1e97e3c8 100644 --- a/mandatory/7-recipes.js +++ b/mandatory/7-recipes.js @@ -1,17 +1,15 @@ -/** - -The Recipe Card -Never forget another recipe! +/**************************************************************************************** +The Recipe Card - Never forget another recipe! Create an object to hold information on your favorite recipe. - It should have properties for - title (a string), - servings (a number), and - ingredients (an array of strings) -On separate lines (one console.log statement for each), log the recipe information so it looks like: +On separate lines (one console.log statement for each), +log the recipe information so it looks like: Mole Serves: 2 @@ -20,9 +18,45 @@ cinnamon cumin cocoa -You should write and log at least 5 recipes - -**/ - -let recipes = {}; - +You should write and log at least 5 recipes */ + +let recipes = { + yorkshirePudding: { + title: "Yorkshire Pudding", + serves: 2, + ingredients: ["flour", "eggs", "milk"], + }, + BaconSarnie: { + title: "Bacon Sarnie", + serves: 1, + ingredients: ["bacon", "bread", "butter", "brown sauce"], + }, + Cupcakes: { + title: "Cupcakes", + serves: 5, + ingredients: ["chocolate", "butter", "flour", "sugar", "eggs"], + }, + Pancake: { + title: "Pancake", + serves: 3, + ingredients: ["milk", "eggs", "flour", "sugar"], + }, + eggSarnie: { + title: "Egg Sarnie", + serves: 1, + ingredients: ["egg", "bread", "butter", "oil"], + }, +}; + +for (recipe in recipes) { //for every nested object in outer object + console.log(recipe); + let keys = Object.keys(recipes[recipe]); + let values = Object.values(recipes[recipe]); + console.log(keys[1] + " : " + values[1]); + console.log(keys[2] + ":"); + let ingredientsValues = values[2]; + ingredientsValues = ingredientsValues.forEach((element) => { + console.log(element); + }); + console.log('\n'); //break between recipes +} diff --git a/mandatory/8-reading-list.js b/mandatory/8-reading-list.js index 6d22df00..1687c979 100644 --- a/mandatory/8-reading-list.js +++ b/mandatory/8-reading-list.js @@ -1,18 +1,13 @@ -/** - -The Reading List -Keep track of which books you've read and which books you want to read! - -===== +/*************************************************************************************** Exercise 1 -===== Create an array of objects, where each object describes a book and has properties for: - The title (a string) - Author (a string) - and alreadyRead (a boolean indicating if you read it yet) -Write a funciton that loops through the array of books. For each book, log the book title and book author like so: +Write a function which loops through the array of books. For each book, +log the book title and book author like so: "The Hobbit by J.R.R. Tolkien" @@ -22,27 +17,57 @@ You should modify the tests so that they contain the values that correspond to y In this style of testing it is typical to write out as strings exactly what you expect your output to be, without using any variables or any logic like loops, template strings or if statements. -*/ +*****************************************************************************************/ + +const books = [ + { + title: "The Lord of the Rings", + author: "J.R.R Tolkien", + alreadyRead: true, + }, + { + title: "Millennium Series", + author: "Stieg Larsson", + alreadyRead: false, + }, + { + title: "Harry Potter", + author: "J.K Rowling", + alreadyRead: true, + }, + { + title: "Dracula", + author: "Bram Stoker", + alreadyRead: true, + }, + { + title: "The Vampire Diaries", + author: "Lisa J Smith", + alreadyRead: true, + }, +]; -const books = []; - -// exercise 1 function logBooks() { + books.forEach(function (book) { + console.log(`${book.title} by ${book.author}`); + }); } - -/* +logBooks(); + +/************************************************************************************** +Exercise -===== -Exercise 2 -===== -Now modify the function, using an if/else statement to change the output depending on whether you have read it yet or not. +Now modify the function, using an if/else statement to change the output depending on +whether you have read it yet or not. If you've read it, log a string like 'You've already read "The Hobbit" by J.R.R. Tolkien', and if not, log a string like 'You still need to read "The Lord of the Rings" by J.R.R. Tolkien.' -You will need to modify the tests to check the correct output. If you have already learnt about red-green refactoring, -remember to practice: +***************** ADDITIONAL REQUIREMENTS ******************** + +You will need to modify the tests to check the correct output. If you have already learnt +about red-green refactoring, remember to practice: - first change the test to the value that should be output, - run the test to check that your test goes red - now change your code to make the test pass @@ -59,7 +84,17 @@ As an example for this exercise, you might do the following steps - Modify the books so that they have the correct alreadyRead value - All tests should turn green!! -**/ +******************************************************************************************/ + +function logBooks() { + books.forEach(function (book) { + if (book.alreadyRead) { + console.log(`You've already read ${book.title} by ${book.author}`); + } else { + console.log(`You still need to read ${book.title} by ${book.author}`); + } + }); +} /* ======= TESTS - DO MODIFY (!!!) ===== - To run the tests for this exercise, run `npm test -- --testPathPattern 8-reading-list.js` @@ -67,31 +102,31 @@ As an example for this exercise, you might do the following steps - (Reminder: You must have run `npm install` one time before this will work!) */ -test("books are logged", function() { - expectLogBooksToLog([ - "The Hobbit by J.R.R. Tolkien", - "The Map of Salt and Stars by Jennifer Zeynab Joukhadar", - "Dietland by Sarai Walker", - "A Place for Us by Fatima Farheen Mirza", - "The House of Impossible Beauties by Joseph Cassara" - ]); +test("books are logged", function () { + expectLogBooksToLog([ + "The Hobbit by J.R.R. Tolkien", + "The Map of Salt and Stars by Jennifer Zeynab Joukhadar", + "Dietland by Sarai Walker", + "A Place for Us by Fatima Farheen Mirza", + "The House of Impossible Beauties by Joseph Cassara", + ]); }); /* ======= TESTS - DO NOT MODIFY ===== */ /* -* Assert that when the function logBooks is called, the values in the expectedValues array are logged in order via console.log. -* -* - If the number of calls to console.log does not match the number of elements in the array, the test will fail -* - If the calls to console.log do not contain the strings in the expectedValue array, the test will fail -* -* You do not need to understand how this function works to successfully complete the exercise. -*/ + * Assert that when the function logBooks is called, the values in the expectedValues array are logged in order via console.log. + * + * - If the number of calls to console.log does not match the number of elements in the array, the test will fail + * - If the calls to console.log do not contain the strings in the expectedValue array, the test will fail + * + * You do not need to understand how this function works to successfully complete the exercise. + */ function expectLogBooksToLog(expectedValues) { - const consoleLogSpy = jest.spyOn(console, 'log'); - logBooks(); - expect(consoleLogSpy).toBeCalledTimes(expectedValues.length); - expectedValues.forEach((value, i) => { - expect(consoleLogSpy).nthCalledWith(i+1, value); - }); - consoleLogSpy.mockRestore(); -}; \ No newline at end of file + const consoleLogSpy = jest.spyOn(console, "log"); + logBooks(); + expect(consoleLogSpy).toBeCalledTimes(expectedValues.length); + expectedValues.forEach((value, i) => { + expect(consoleLogSpy).nthCalledWith(i + 1, value); + }); + consoleLogSpy.mockRestore(); +} diff --git a/mandatory/9-budgets.js b/mandatory/9-budgets.js index 2c05a4b5..6c146cab 100644 --- a/mandatory/9-budgets.js +++ b/mandatory/9-budgets.js @@ -1,9 +1,7 @@ /** - Get Sum of People's Budget Create the function that takes an array with objects and returns the sum of people's budgets. - For example: getBudgets([ @@ -14,11 +12,17 @@ getBudgets([ Should give return the answer of 62600. -**/ +******************************************************************************************/ function getBudgets(peopleArray) { + let total = 0; + for (const person of peopleArray) { + total += person.budget; + } + return total; } + /* ======= TESTS - DO MODIFY (!!!) ===== - To run the tests for this exercise, run `npm test -- --testPathPattern 9-budgets.js` - To run all exercises/tests in the mandatory folder, run `npm test` diff --git a/package.json b/package.json index f792ad1e..387fbae8 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "description": "Exercises for JS2 Week 1", "scripts": { - "test": "jest --testRegex='mandatory[/\\\\].*\\.js$' --testPathIgnorePatterns='choose-your-own|recipes|water-bottle'" + "test": "jest --testRegex='mandatory[/\\\\].*\\.js$'" }, "repository": { "type": "git", @@ -16,6 +16,11 @@ "setupFilesAfterEnv": [ "jest-extended", "./.setup/jest.setup.js" + ], + "testPathIgnorePatterns": [ + "adventure", + "recipes", + "water" ] }, "homepage": "https://github.com/CodeYourFuture/JavaScript-Core-2-Coursework-Week1#readme",