diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..e151e973c 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,9 +1,13 @@ // Predict and explain first... + // undefind is expect. because index access is for arrays not for object. + // for object you mention the key to get the value. + // This code should log out the houseNumber from the address object // but it isn't working... // Fix anything that isn't working + const address = { houseNumber: 42, street: "Imaginary Road", @@ -11,5 +15,7 @@ const address = { country: "England", postcode: "XYZ 123", }; - -console.log(`My house number is ${address[0]}`); +// either access via (.) properties +console.log(`My house number is ${address.houseNumber}`); +//OR prakets notation +console.log(`My house number is ${address['houseNumber']}`); diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..8975abef2 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -3,6 +3,9 @@ // This program attempts to log out all the property values in the object. // But it isn't working. Explain why first and then fix the problem + // i know it will not work because we cant access these values this way. + // what i learned new is the 3 properties + const author = { firstName: "Zadie", lastName: "Smith", @@ -11,6 +14,18 @@ const author = { alive: true, }; -for (const value of author) { +//for (const value of author) { + //console.log(value);} + +for (const key in author) { + console.log(author[key]); +} +for (const value of Object.values(author)) { console.log(value); } +for (const key of Object.keys(author)) { + console.log(author[key]); +} +for (const [key, value] of Object.entries(author)) { + console.log(value); // or console.log(`${key}: ${value}`) +} \ No newline at end of file diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..e0e365c22 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -3,6 +3,8 @@ // This program should log out the title, how many it serves and the ingredients. // Each ingredient should be logged on a new line // How can you fix it? + //i tried to use map but could not write the code itself i checked it online. AI help me with another solution. + //.join const recipe = { title: "bruschetta", @@ -11,5 +13,9 @@ const recipe = { }; console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); +ingredients: + ${recipe.ingredients.join("\n")}`); + +console.log(`${recipe.title} serves ${recipe.serves} +ingredients: +${recipe.ingredients.map((ingredient) => ` ${ingredient}`).join("\n")}`); \ No newline at end of file diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..ff9ecef40 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,11 @@ -function contains() {} +function contains(obj, propertyName) { + // Check if obj is a valid plain object (not array, not null, not other object types) + if (obj === null || typeof obj !== "object" || Array.isArray(obj)) { + return false; + } + + // Use hasOwnProperty to check if the property exists directly on the object + return Object.prototype.hasOwnProperty.call(obj, propertyName); +} module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..fd7cc75af 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -33,3 +33,47 @@ test.todo("contains on empty object returns false"); // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +// const contains = require("./contains.js"); + +// Given an empty object +// When passed to contains +// Then it should return false +test("contains on empty object returns false", () => { + expect(contains({}, "a")).toBe(false); +}); + +// Given an object with properties +// When passed to contains with an existing property name +// Then it should return true +test("contains with existing property returns true", () => { + expect(contains({ a: 1, b: 2 }, "a")).toBe(true); + expect(contains({ a: 1, b: 2 }, "b")).toBe(true); +}); + +// Given an object with properties +// When passed to contains with a non-existent property name +// Then it should return false +test("contains with non-existent property returns false", () => { + expect(contains({ a: 1, b: 2 }, "c")).toBe(false); +}); + +// Given invalid parameters like an array +// When passed to contains +// Then it should return false or throw an error +test("contains with invalid parameters returns false", () => { + // Test with array + expect(contains([1, 2, 3], "0")).toBe(false); // arrays are objects but we treat them as invalid for this use case + expect(contains([1, 2, 3], "length")).toBe(false); + + // Test with null + expect(contains(null, "a")).toBe(false); + + // Test with undefined + expect(contains(undefined, "a")).toBe(false); + + // Test with string + expect(contains("hello", "0")).toBe(false); + + // Test with number + expect(contains(123, "toString")).toBe(false); +}); diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..985523d18 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,13 @@ -function createLookup() { - // implementation here +function createLookup(countryCurrencyPairs) { + const lookup = {}; + + for (const pair of countryCurrencyPairs) { + const countryCode = pair[0]; + const currencyCode = pair[1]; + lookup[countryCode] = currencyCode; + } + + return lookup; } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..7b6bcaa9c 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -33,3 +33,16 @@ It should return: 'CA': 'CAD' } */ + +test("creates a country currency code lookup for multiple codes", () => { + const countryCurrencyPairs = [ + ["US", "USD"], + ["CA", "CAD"], + ]; + const result = createLookup(countryCurrencyPairs); + + expect(result).toEqual({ + US: "USD", + CA: "CAD", + }); +}); \ No newline at end of file diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..65695b6b4 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -6,8 +6,14 @@ function parseQueryString(queryString) { const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + // Split only on the first '=' to handle values containing '=' + const equalsIndex = pair.indexOf("="); + if (equalsIndex !== -1) { + const key = pair.substring(0, equalsIndex); + const value = pair.substring(equalsIndex + 1); + queryParams[key] = value; + } + // If there's no '=', treat the whole string as key with undefined value } return queryParams; diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..26e176d94 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -3,10 +3,24 @@ // Below is one test case for an edge case the implementation doesn't handle well. // Fix the implementation for this test, and try to think of as many other edge cases as possible - write tests and fix those too. -const parseQueryString = require("./querystring.js") + + +const parseQueryString = require("./querystring.js"); test("parses querystring values containing =", () => { expect(parseQueryString("equation=x=y+1")).toEqual({ - "equation": "x=y+1", + equation: "x=y+1", + }); +}); + +test("handles multiple parameters with special characters", () => { + expect(parseQueryString("a=1&b=2&equation=x=y+1")).toEqual({ + a: "1", + b: "2", + equation: "x=y+1", }); }); + +test("handles empty query string", () => { + expect(parseQueryString("")).toEqual({}); +}); \ No newline at end of file diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..67fbeea5f 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,15 @@ -function tally() {} +function tally(items) { + const counts = {}; + + for (const item of items) { + if (counts[item] === undefined) { + counts[item] = 1; + } else { + counts[item]++; + } + } + + return counts; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..bfc1f828b 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -1,4 +1,4 @@ -const tally = require("./tally.js"); +//const tally = require("./tally.js"); /** * tally array @@ -32,3 +32,16 @@ test.todo("tally on an empty array returns an empty object"); // Given an invalid input like a string // When passed to tally // Then it should throw an error +const tally = require("./tally.js"); + +test("tally on an empty array returns an empty object", () => { + expect(tally([])).toEqual({}); +}); + +test("tally counts duplicate items correctly", () => { + expect(tally(["a", "a", "a"])).toEqual({ a: 3 }); +}); + +test("tally counts multiple unique items", () => { + expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 }); +}); \ No newline at end of file diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..8762012bb 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -6,15 +6,15 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} -function invert(obj) { - const invertedObj = {}; +// function invert(obj) { +// const invertedObj = {}; - for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; - } +// for (const [key, value] of Object.entries(obj)) { +// invertedObj.key = value; +// } - return invertedObj; -} +// return invertedObj; +// } // a) What is the current return value when invert is called with { a : 1 } @@ -27,3 +27,16 @@ function invert(obj) { // d) Explain why the current return value is different from the target output // e) Fix the implementation of invert (and write tests to prove it's fixed!) + + +function invert(obj) { + const invertedObj = {}; + + for (const [key, value] of Object.entries(obj)) { + invertedObj[value] = key; // Use value as key, original key as value + } + + return invertedObj; +} + +module.exports = invert; diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js new file mode 100644 index 000000000..536809825 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,13 @@ +const invert = require("./invert.js"); + +test("inverts object with single key-value pair", () => { + expect(invert({ a: 1 })).toEqual({ 1: "a" }); +}); + +test("inverts object with multiple key-value pairs", () => { + expect(invert({ a: 1, b: 2 })).toEqual({ 1: "a", 2: "b" }); +}); + +test("inverts object with string values", () => { + expect(invert({ x: 10, y: 20 })).toEqual({ 10: "x", 20: "y" }); +}); diff --git a/package.json b/package.json new file mode 100644 index 000000000..d15e6373b --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "module-data-groups", + "version": "1.0.0", + "scripts": { + "test": "jest" + }, + "devDependencies": { + "jest": "^30.2.0" + } +} diff --git a/prep/100.js b/prep/100.js new file mode 100644 index 000000000..86666f0fc --- /dev/null +++ b/prep/100.js @@ -0,0 +1,19 @@ +const ingredients = ["olive oil", "tomatoes", "garlic", "onion", "carrot"]; +let ingredientsCopy = ingredients; +ingredientsCopy.push("pasta", "salt", "pepper"); +const otherRecipe = [ + "olive oil", + "tomatoes", + "garlic", + "onion", + "carrot", + "pasta", + "salt", + "pepper", +]; + +console.log(ingredients === ingredientsCopy); +console.log(ingredients === otherRecipe); +console.log(otherRecipe === ingredientsCopy); +console.log(otherRecipe.length === ingredients.length); + diff --git a/prep/600.js b/prep/600.js new file mode 100644 index 000000000..1119186e8 --- /dev/null +++ b/prep/600.js @@ -0,0 +1,26 @@ +function collectNumbers(list) { + const numbersOnly = []; + for (const item of list) { + if (item === "string") { + numbersOnly.push(item); + } + } + return numbersOnly; +} + +test("only collects numbers in the array", () => { + const currentOutput = collectNumbers([ + 10.1, + "hello", + 6.1, + 8.0, + 9.7, + 10.1, + "hi", + 3.5, + "oops", + ]); + const targetOutput = [10.1, 6.1, 8.0, 9.7, 10.1, 3.5]; + + expect(currentOutput).toEqual(targetOutput); +}); diff --git a/prep/600.test.js b/prep/600.test.js new file mode 100644 index 000000000..637438307 --- /dev/null +++ b/prep/600.test.js @@ -0,0 +1,26 @@ +function collectNumbers(list) { + const numbersOnly = []; + for (const item of list) { + if (typeof item === "number") { + numbersOnly.push(item); + } + } + return numbersOnly; +} + +test("only collects numbers in the array", () => { + const currentOutput = collectNumbers([ + 10.1, + "hello", + 6.1, + 8.0, + 9.7, + 10.1, + "hi", + 3.5, + "oops", + ]); + const targetOutput = [10.1, 6.1, 8.0, 9.7, 10.1, 3.5]; + + expect(currentOutput).toEqual(targetOutput); +}); diff --git a/prep/Stair.js b/prep/Stair.js new file mode 100644 index 000000000..a3f1a3612 --- /dev/null +++ b/prep/Stair.js @@ -0,0 +1,32 @@ +function drawStairs(n) { + let result = ""; + + for (let i = 0; i < n; i++) { + // Add spaces BEFORE the "I" + result += writeSpace(i); + + // Then add the "I" + result += "I"; + + // Add newline if not the last line + if (i < n - 1) { + result += "\n"; + } + } + + return result; +} + +function writeSpace(n) { + let result = ""; + for (let i = 0; i < n; i++) { + result += "*"; // Use spaces, not asterisks + } + return result; +} + + +console.log(drawStairs(16)); +console.log(drawStairs(1)); +console.log(drawStairs(1)); +console.log ("^^^^") diff --git a/prep/can-eat-icecream.js b/prep/can-eat-icecream.js new file mode 100644 index 000000000..b2e76897e --- /dev/null +++ b/prep/can-eat-icecream.js @@ -0,0 +1,45 @@ +// Write a function that returns true if I can eat the ice cream +// The function has 1 parameter representing an ice cream object +// I can eat the ice cream if it is lactose-free and contains less than 10 grams of sugar + +function canEat(iceCream) { + return ( + iceCream.lactoseFree === true && iceCream.gramsOfSugarPerScoop < 10 + ); +} + +const iceCream1 = { + flavour: "Vanilla", + lactoseFree: false, + gramsOfSugarPerScoop: 12, +}; + +const iceCream2 = { + flavour: "Mango Sorbet", + lactoseFree: true, + gramsOfSugarPerScoop: 10, +}; + +const iceCream3 = { + flavour: "Coconut", + lactoseFree: true, + gramsOfSugarPerScoop: 8, +}; + +const iceCream4 = { + flavour: "Strawberry", + lactoseFree: false, + gramsOfSugarPerScoop: 8, +}; + +const iceCream5 = { + flavour: "Lemon Sorbet", + lactoseFree: true, + gramsOfSugarPerScoop: 7, +}; + +console.log(canEat(iceCream1)); // what should this output? +console.log(canEat(iceCream2)); // what should this output? +console.log(canEat(iceCream3)); // what should this output? +console.log(canEat(iceCream4)); // what should this output? +console.log(canEat(iceCream5)); // what should this output? diff --git a/prep/cheap-book.js b/prep/cheap-book.js new file mode 100644 index 000000000..f4d31526f --- /dev/null +++ b/prep/cheap-book.js @@ -0,0 +1,49 @@ +function getCheapest(book1, book2) { + const cost1 = book1.cost; + const cost2 = book2.cost; + + if (cost1 < cost2) { + return book1.title; // book1 is cheaper + } else { + return book2.title; // book2 is cheaper (or equal) + } +} +// Write a function called `getCheapest` that will take 2 book objects as parameters +// and return the name of the cheaper book + +const fictionBook = { + title: "1984", + author: "George Orwell", + category: "Dystopian Fiction", + subcategory: "Political", + cost: 9.99, +}; + +const productivityBook = { + title: "Atomic Habits", + author: "James Clear", + category: "Self-Help", + subcategory: "Productivity", + cost: 16.2, +}; + +// this should output 1984 +console.log(getCheapest(fictionBook, productivityBook)); + + + + +// this is for plural +function getCheapest(books) { + if (books.length === 0) return null; // Handle empty array case + + let cheapestBook = books[0]; // Start with the first book as the cheapest + + for (let i = 1; i < books.length; i++) { + if (books[i].cost < cheapestBook.cost) { + cheapestBook = books[i]; // Update if we find a cheaper book + } + } + + return cheapestBook.title; +} \ No newline at end of file diff --git a/prep/doubleNnumber.test.js b/prep/doubleNnumber.test.js new file mode 100644 index 000000000..0a2907123 --- /dev/null +++ b/prep/doubleNnumber.test.js @@ -0,0 +1,16 @@ +const doubleAllNumbers = require("./doubleNumber.js"); + +test("doubles [10, 20, 30] to [20, 40, 60]", () => { + const input = [10, 20, 30]; + const result = doubleAllNumbers(input); + const expected = [20, 40, 60]; + + expect(result).toEqual(expected); +}); + +test("works with negative numbers", () => { + const input = [-5, -10, 15]; // ← This is ONLY for the test + const result = doubleAllNumbers(input); + const expected = [-10, -20, 30]; + expect(result).toEqual(expected); +}); diff --git a/prep/doubleNumber.js b/prep/doubleNumber.js new file mode 100644 index 000000000..2ab928597 --- /dev/null +++ b/prep/doubleNumber.js @@ -0,0 +1,24 @@ +// Can you fix this code? +// function doubleAllNumbers(numbers) { +// let doubledNumbers= [] + +// for (let n of numbers) { +// doubledNumbers.push(n * 2); +// } + +// return doubledNumbers; +// } + +// const myNums = [10, 20, 30]; +// console.log(doubleAllNumbers(myNums)); + +// make it better code + +function doubleAllNumbers(numbers) { + let doubledNumbers = []; + for (let n of numbers) { + doubledNumbers.push(n * 2); + } + return doubledNumbers; +} +module.exports = doubleAllNumbers; diff --git a/prep/lesson-plan/100.js b/prep/lesson-plan/100.js new file mode 100644 index 000000000..d7f33fea2 --- /dev/null +++ b/prep/lesson-plan/100.js @@ -0,0 +1,28 @@ +// Predict and explain... +// What will be logged by this code? +// Check your prediction and explanation by running the code. + +const person1 = { + name: "Abdi", + location: "London", + id_number: 17, +}; + +const person2 = { + name: "Shadi", + job: "Software Engineer", + location: "London", + id_number: 28, +}; + +const person3 = person2; + +person3.location = "Manchester"; + +console.log(person1.name); +console.log(person2["name"]); +console.log(person1.id_number > person2["id_number"]); +console.log(person1.job); +console.log(person1.location === person2.location); +console.log(person1.location === person3.location); +console.log(person2.location === person3.location); diff --git a/prep/lesson-plan/200.js b/prep/lesson-plan/200.js new file mode 100644 index 000000000..2822c3304 --- /dev/null +++ b/prep/lesson-plan/200.js @@ -0,0 +1,15 @@ +// Predict and explain... +// What will happen when this program is run? +// Check your prediction and explanation by running the program. +// Fix anything that needs fixing. + +const person = { + "name": "Jemima", + "location": "Glasgow", + "id_number" : 9, +}; + +console.assert(person.name === "Jemima"); +console.assert(person.location === "Glasgow"); +console.assert(person.id_number === 9); +console.log(person.id_number); \ No newline at end of file diff --git a/prep/lesson-plan/300.js b/prep/lesson-plan/300.js new file mode 100644 index 000000000..b35a1badf --- /dev/null +++ b/prep/lesson-plan/300.js @@ -0,0 +1,25 @@ +function checkLivesNearCYF(person) { + const cyfLocations = [ + "Birmingham", + "Cape Town", + "Glasgow", + "London", + "Manchester", + ]; + return cyfLocations.includes(person.city); // Changed from .location to .city +} + +const mo = { + name: "Mo", + city: "Glasgow", // Uses city + focus: "React", +}; + +const sayed = { + name: "Sayed", + city: "Edinburgh", // Uses city + focus: "SQL", +}; + +console.assert(checkLivesNearCYF(mo)); // true - Glasgow is in CYF locations +console.assert(!checkLivesNearCYF(sayed)); // true - Edinburgh is NOT in CYF locations diff --git a/prep/lesson-plan/400.js b/prep/lesson-plan/400.js new file mode 100644 index 000000000..e41ed322e --- /dev/null +++ b/prep/lesson-plan/400.js @@ -0,0 +1,47 @@ +// Predict and explain... +// What will happen when this program is run? +// Check your prediction and explanation by running the program. +// Fix anything that needs fixing. + +function printSaladRecipe(forPerson) { + const saladRecipe = { + name: "salad", + ingredients: ["lettuce", "corn", "carrots", "cucumber"], + rating_out_of_10: 8, + steps: [ + "Shred the lettuce", + "Cut the carrots into small pieces", + "Slice the cucumber", + "Mix all the vegetables together in a bowl", + ], + }; + + if (forPerson.eatsMeat) { + saladRecipe.ingredients.push("chicken"); // FIXED: .push works only with arrays; not with objects. + // therefore we added it to ingredients array. + saladRecipe.steps.push("Mix in the chicken"); // this one is good because it is added to array already. + } + + console.log(`For ${forPerson.name} to make ${saladRecipe.name}:`); + console.log("Get:"); + for (const ingredient of saladRecipe.ingredients) { + console.log(` * ${ingredient}`); + } + for (const step of saladRecipe.steps) { + console.log(step); + } +} + +const person1 = { + name: "Ola", + eatsMeat: true, +}; + +const person2 = { + name: "Steve", + eatsMeat: false, +}; + +printSaladRecipe(person1); +console.log(""); +printSaladRecipe(person2); diff --git a/prep/lesson-plan/500.js b/prep/lesson-plan/500.js new file mode 100644 index 000000000..870891d51 --- /dev/null +++ b/prep/lesson-plan/500.js @@ -0,0 +1,36 @@ +// Fill in the code below so that the tests pass. + +const people = []; + +people.push({ + name: "Saqib", + favourite_food: "salad", +}); + +people.push({ + name: "Shadi", + favourite_food: "mango", +}); + +people.push({ + name: "Navid", + favourite_food: "macarons", +}); + +const favouriteFoods = []; + +// +//option one +for (const person of people) { + favouriteFoods.push(person.favourite_food); +} +// Option 2: for loop with index +// for (let i = 0; i < people.length; i++) { +// favouriteFoods.push(people[i].favourite_food); +// TODO: Fill the array favouriteFoods with the favourite foods of each person. +// You must not type the strings (i.e. your solution should not involve you typing the word "salad"). + +console.assert(favouriteFoods.length === 3); +console.assert(favouriteFoods.includes("salad")); +console.assert(favouriteFoods.includes("mango")); +console.assert(favouriteFoods.includes("macarons")); diff --git a/prep/lesson-plan/600.js b/prep/lesson-plan/600.js new file mode 100644 index 000000000..cfb1f109f --- /dev/null +++ b/prep/lesson-plan/600.js @@ -0,0 +1,16 @@ +// Predict and explain... +// What will happen when this program is run? +// Check your prediction and explanation by running the program. +// Fix anything that needs fixing. + +const person = { + name: "Manu", + favourite_ice_cream: "vanilla", + favourite_topping: "marshmallows", +}; + +function assertFieldEquals(object, field, targetValue) { + console.assert(object[field] === targetValue); +} + +assertFieldEquals(person, "favourite_ice_cream", "vanilla"); diff --git a/prep/mean.js b/prep/mean.js new file mode 100644 index 000000000..8a3c20906 --- /dev/null +++ b/prep/mean.js @@ -0,0 +1,30 @@ +// function calculateMean(list) { +// let total = 0; +// for (const item of list) { +// total += item; +// } +// } +// calculateMean([10, 20, 30, 40, 50]) +// DEbugger shift ctrl P +//debug: toggle auto attach +//only auto attach when the inspect flag is given +// node --inspect file.js +// This function calculates the average of numbers in an array +function calculateMean(list) { + // If the list is empty, return 0---- that is another test level + if (list.length === 0) { + return 0; + } + + // Add up all the numbers + let total = 0; + for (const item of list) { + total += item; + } + + // Divide by how many numbers there are + return total / list.length; +} + +// This makes the function available to other files +module.exports = calculateMean; \ No newline at end of file diff --git a/prep/mean.test.js b/prep/mean.test.js new file mode 100644 index 000000000..8e9e35e01 --- /dev/null +++ b/prep/mean.test.js @@ -0,0 +1,17 @@ +const calculateMean = require("./mean.js"); + +test("calculates the mean of a list of numbers", () => { + const list = [3, 50, 7]; + const currentOutput = calculateMean(list); + const targetOutput = 20; + + expect(currentOutput).toEqual(targetOutput); // 20 is (3 + 50 + 7) / 3 +}); + +test("calculates the mean of a list of numbers", () => { + const list = [0]; + const currentOutput = calculateMean(list); + const targetOutput = 0; + + expect(currentOutput).toEqual(targetOutput); 0 +}); diff --git a/prep/median.js b/prep/median.js new file mode 100644 index 000000000..10fceee97 --- /dev/null +++ b/prep/median.js @@ -0,0 +1,7 @@ +function calculateMedian(list) { + const middleIndex = Math.floor(list.length / 2); + const median = list.splice(middleIndex, 1)[0]; + + return median; +} +module.exports = calculateMedian \ No newline at end of file diff --git a/prep/median.test.js b/prep/median.test.js new file mode 100644 index 000000000..3e9127ba4 --- /dev/null +++ b/prep/median.test.js @@ -0,0 +1,7 @@ +test("calculates the median of a list of odd length", () => { + const list = [10, 20, 30, 50, 60]; + const currentOutput = calculateMedian(list); + const targetOutput = 30; + expect(currentOutput).toEqual(targetOutput); +}); +const calculateMedian = require("./median.js"); diff --git a/prep/names-icecream.js b/prep/names-icecream.js new file mode 100644 index 000000000..8e05689bc --- /dev/null +++ b/prep/names-icecream.js @@ -0,0 +1,69 @@ +// function whichIceCreamsCanIEat(iceCreams) { +// return iceCreams +// .filter( +// (iceCream) => +// iceCream.lactoseFree === true && iceCream.gramsOfSugarPerScoop < 10 +// ) +// .map((iceCream) => iceCream.flavour); +// } + +//OR +function whichIceCreamsCanIEat(iceCreams) { + const edibleFlavours = []; + + for (let i = 0; i < iceCreams.length; i++) { + if ( + iceCreams[i].lactoseFree === true && + iceCreams[i].gramsOfSugarPerScoop < 10 + ) { + edibleFlavours.push(iceCreams[i].flavour); + } + } + + return edibleFlavours; +} +test("given one edible ice cream, returns its flavour", () => { + const input = [ + { flavour: "Coconut", lactoseFree: true, gramsOfSugarPerScoop: 8 }, + ]; + + const currentOutput = whichIceCreamsCanIEat(input); + const targetOutput = ["Coconut"]; + + expect(currentOutput).toEqual(targetOutput); +}); + +const iceCream1 = { + flavour: "Vanilla", + lactoseFree: false, + gramsOfSugarPerScoop: 12, +}; + +const iceCream2 = { + flavour: "Mango Sorbet", + lactoseFree: true, + gramsOfSugarPerScoop: 10, +}; + +const iceCream3 = { + flavour: "Coconut", + lactoseFree: true, + gramsOfSugarPerScoop: 8, +}; + +const iceCream4 = { + flavour: "Strawberry", + lactoseFree: false, + gramsOfSugarPerScoop: 8, +}; + +const iceCream5 = { + flavour: "Lemon Sorbet", + lactoseFree: true, + gramsOfSugarPerScoop: 7, +}; + +const allIceCreams = [iceCream1, iceCream2, iceCream3, iceCream4, iceCream5]; + +const iceCreamsICanEat = whichIceCreamsCanIEat(allIceCreams); +console.log(iceCreamsICanEat); // what should this output? \ No newline at end of file diff --git a/prep/parse-query-string.js b/prep/parse-query-string.js new file mode 100644 index 000000000..178cdba98 --- /dev/null +++ b/prep/parse-query-string.js @@ -0,0 +1,61 @@ +//function parseQueryString(queryString) { + ///We first need to separate out the "fruit=banana" string so we can access "fruit" and "banana" separately. + // We can do this by splitting up the string by the = character. + // We can split the string into an array consisting of ['fruit', 'banana']. + // Then we can grab the array's contents and assign the elements meaningful names: +// const queryParams = {}; + +// const keyValuePair = queryString.split("="); +// const key = keyValuePair[0]; +// const value = keyValuePair[1]; // value will hold 'banana' + + ///const [key, value] = queryString.split("="); // key will hold 'fruit', value will hold 'banana' + + + +// queryParams[key] = value; // Fixed: use bracket notation to use the variable as key +// return queryParams; +// } + + +// // in case of multible pairs we are missing one step - breaking up the string of multiple key-value pairs +// // into an array where each element is a single key-value pair. If we do this, +// // then we can iterate over the array, and do what we already know how to do on each key-value pair. +// function parseQueryString(queryString) { +// // assume queryString has a value of "sort=lowest&colour=yellow" +// const queryParams = {}; +// const keyValuePairs = queryString.split("&"); // keyValuePairs will point to ["sort=lowest", "colour=yellow"] + +// for (const pair of keyValuePairs) { +// const [key, value] = pair.split("="); +// queryParams[key] = value; +// } + +// return queryParams; +// } +// module.exports = parseQueryString; + +//Now that we’ve worked out how to solve this problem in the case of multiple query parameters, +// let’s integrate that solution into our previous implementation, to make sure it works for all cases. + +//We can keep our if (queryString.length === 0) +// { check from before. We still need it because split on an empty string still returns an empty string. +// If we don’t have this special case, we’ll try to parse the empty string, probably incorrectly. + +//We don’t need to do anything special for the one-value case, +// as an array containing one element gets iterated the same as an array of multiple elements: +function parseQueryString(queryString) { + const queryParams = {}; + if (queryString.length === 0) { + return queryParams; + } + const keyValuePairs = queryString.split("&"); + + for (const pair of keyValuePairs) { + const [key, value] = pair.split("="); + queryParams[key] = value; + } + + return queryParams; +} + module.exports = parseQueryString; diff --git a/prep/parse-query-string.test.js b/prep/parse-query-string.test.js new file mode 100644 index 000000000..319158c88 --- /dev/null +++ b/prep/parse-query-string.test.js @@ -0,0 +1,20 @@ +test("given a query string with no query parameters, returns an empty object", () => { + const input= ""; + const currentOutput = parseQueryString(input); + const targetOutput = {}; + expect(currentOutput).toEqual(targetOutput); +}); +const parseQueryString = require("./parse-query-string.js"); +test("given a query string with one pair of query params, returns them in object", () => { + const input = "fruit=banana"; + const currentOutput = parseQueryString(input); + const targetOutput = { fruit: "banana" }; + + expect(currentOutput).toEqual(targetOutput); +}); +test("given a query string with multiple key-value pairs, returns them in object", () => { + const input = "sort=lowest&colour=yellow"; + const currentOutput = parseQueryString(input); + const targetOutput = { sort: "lowest", colour: "yellow" }; + expect(currentOutput).toEqual(targetOutput); +}); \ No newline at end of file diff --git a/prep/swapFirstAndLast.js b/prep/swapFirstAndLast.js new file mode 100644 index 000000000..003cc8265 --- /dev/null +++ b/prep/swapFirstAndLast.js @@ -0,0 +1,19 @@ +// Write a function which takes an array as a parameter +// and swaps the first element with the last element + +// function swapFirstAndLast(arr) {} + +// const myArray = [5, 2, 3, 4, 1]; +// swapFirstAndLast(myArray); +// console.log(myArray); +// what output should we expect? +// Write a function which takes an array as a parameter +// and swaps the first element with the last element + +function swapFirstAndLast(arr) { + let temp = arr[0]; + arr[0] = arr[arr.length - 1]; + arr[arr.length - 1] = temp; +} + +module.exports = swapFirstAndLast; \ No newline at end of file diff --git a/prep/swapFirstAndLast.test.js b/prep/swapFirstAndLast.test.js new file mode 100644 index 000000000..7d9f9c6a1 --- /dev/null +++ b/prep/swapFirstAndLast.test.js @@ -0,0 +1,7 @@ +const swapFirstAndLast = require("./swapFirstAndLast.js"); + +test("swaps first and last elements of [5, 2, 3, 4, 1]", () => { + const myArray = [5, 2, 3, 4, 1]; + swapFirstAndLast(myArray); + expect(myArray).toEqual([1, 2, 3, 4, 5]); +}); diff --git a/prep/week9-prep/index.html b/prep/week9-prep/index.html new file mode 100644 index 000000000..91c15145e --- /dev/null +++ b/prep/week9-prep/index.html @@ -0,0 +1,24 @@ + + + + + + Document + + + +
+

Example character limit comment component!

+ + +

You have 200 characters remaining

+
+ + \ No newline at end of file diff --git a/prep/week9-prep/script.js b/prep/week9-prep/script.js new file mode 100644 index 000000000..5242f1fb7 --- /dev/null +++ b/prep/week9-prep/script.js @@ -0,0 +1,26 @@ +// const textarea = document.querySelector("textarea"); +// const remainingCharacters = textarea.maxLength - textarea.value.length; + +// const charactersLeftP = document.querySelector("#character-limit-info"); +// charactersLeftP.innerText = `You have ${remainingCharacters} characters remaining`; + +// function updateCharacterLimit() { +// const remainingCharacters = textarea.maxLength - textarea.value.length; +// const charactersLeftP = document.querySelector("#character-limit-info"); +// charactersLeftP.innerText = `You have ${remainingCharacters} characters remaining`; +// } + +// textarea.addEventListener("keyup", updateCharacterLimit); + +// refactor version +const textarea = document.querySelector("textarea"); + +updateCharacterLimit(); + +function updateCharacterLimit() { + const remainingCharacters = textarea.maxLength - textarea.value.length; + const charactersLeftP = document.querySelector("#character-limit-info"); + charactersLeftP.innerText = `You have ${remainingCharacters} characters remaining`; +} + +textarea.addEventListener("keyup", updateCharacterLimit); \ No newline at end of file diff --git a/prep/week9-prep/style.css b/prep/week9-prep/style.css new file mode 100644 index 000000000..e69de29bb