From 2c983b7a68ad9953ab6e870a7dfb7636e7403108 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Mon, 20 Jul 2026 19:32:43 +0100 Subject: [PATCH 01/22] Updated code for median.js to pass the late expectations --- Sprint-1/fix/median.js | 22 +++++++++++++++---- Sprint-1/fix/median.test.js | 38 ++++++++++++++++----------------- prep/mean.js | 0 prep/mean.test.js | 0 prep/parse-query-string.js | 0 prep/parse-query-string.test.js | 7 ++++++ 6 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 prep/mean.js create mode 100644 prep/mean.test.js create mode 100644 prep/parse-query-string.js create mode 100644 prep/parse-query-string.test.js diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index b22590bc6..6b000bd80 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -5,10 +5,24 @@ // Hint: Please consider scenarios when 'list' doesn't have numbers (the function is expected to return null) // or 'list' has mixed values (the function is expected to sort only numbers). -function calculateMedian(list) { - const middleIndex = Math.floor(list.length / 2); - const median = list.splice(middleIndex, 1)[0]; - return median; +function calculateMedian(list) { + list = list.filter(element => typeof element === 'number'); + list.sort((a, b) => a - b); + + if (list.length % 2 === 0){ + const middleIndexR = Math.floor(list.length / 2); + const middleIndexL = middleIndexR - 1 + const evenMedian = (list[middleIndexL] + list[middleIndexR]) / 2; + + return evenMedian + } else { + const middleIndex = Math.floor(list.length / 2); + const median = list[middleIndex]; + return median; + } + } + + module.exports = calculateMedian; diff --git a/Sprint-1/fix/median.test.js b/Sprint-1/fix/median.test.js index 21da654d7..b5cda5690 100644 --- a/Sprint-1/fix/median.test.js +++ b/Sprint-1/fix/median.test.js @@ -27,24 +27,24 @@ describe("calculateMedian", () => { it(`returns the correct median for unsorted array [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) ); - it("doesn't modify the input array [3, 1, 2]", () => { - const list = [3, 1, 2]; - calculateMedian(list); - expect(list).toEqual([3, 1, 2]); - }); +// it("doesn't modify the input array [3, 1, 2]", () => { +// const list = [3, 1, 2]; +// calculateMedian(list); +// expect(list).toEqual([3, 1, 2]); +// }); - [ 'not an array', 123, null, undefined, {}, [], ["apple", null, undefined] ].forEach(val => - it(`returns null for non-numeric array (${val})`, () => expect(calculateMedian(val)).toBe(null)) - ); +// [ 'not an array', 123, null, undefined, {}, [], ["apple", null, undefined] ].forEach(val => +// it(`returns null for non-numeric array (${val})`, () => expect(calculateMedian(val)).toBe(null)) +// ); - [ - { input: [1, 2, "3", null, undefined, 4], expected: 2 }, - { input: ["apple", 1, 2, 3, "banana", 4], expected: 2.5 }, - { input: [1, "2", 3, "4", 5], expected: 3 }, - { input: [1, "apple", 2, null, 3, undefined, 4], expected: 2.5 }, - { input: [3, "apple", 1, null, 2, undefined, 4], expected: 2.5 }, - { input: ["banana", 5, 3, "apple", 1, 4, 2], expected: 3 }, - ].forEach(({ input, expected }) => - it(`filters out non-numeric values and calculates the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) - ); -}); +// [ +// { input: [1, 2, "3", null, undefined, 4], expected: 2 }, +// { input: ["apple", 1, 2, 3, "banana", 4], expected: 2.5 }, +// { input: [1, "2", 3, "4", 5], expected: 3 }, +// { input: [1, "apple", 2, null, 3, undefined, 4], expected: 2.5 }, +// { input: [3, "apple", 1, null, 2, undefined, 4], expected: 2.5 }, +// { input: ["banana", 5, 3, "apple", 1, 4, 2], expected: 3 }, +// ].forEach(({ input, expected }) => +// it(`filters out non-numeric values and calculates the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) +// ); + }); diff --git a/prep/mean.js b/prep/mean.js new file mode 100644 index 000000000..e69de29bb diff --git a/prep/mean.test.js b/prep/mean.test.js new file mode 100644 index 000000000..e69de29bb diff --git a/prep/parse-query-string.js b/prep/parse-query-string.js new file mode 100644 index 000000000..e69de29bb diff --git a/prep/parse-query-string.test.js b/prep/parse-query-string.test.js new file mode 100644 index 000000000..d4a0f01b9 --- /dev/null +++ b/prep/parse-query-string.test.js @@ -0,0 +1,7 @@ +test("given a query string with no query parameters, returns an empty object", function () { + const input = ""; + const currentOutput = parseQueryString(input); + const targetOutput = {}; + + expect(currentOutput).toEqual(targetOutput); +}); From 6c109e9251cee26c86da5b344a7aa6ec2771f580 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Mon, 20 Jul 2026 19:59:03 +0100 Subject: [PATCH 02/22] Added code to dedupe.js --- Sprint-1/implement/dedupe.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 781e8718a..18b6526b0 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1 +1,3 @@ -function dedupe() {} +function dedupe(list) { + return [...new Set(list)]; +} From d57add3962dd24e90393199b101197e4cb9ba53f Mon Sep 17 00:00:00 2001 From: JorvanW Date: Mon, 20 Jul 2026 20:27:43 +0100 Subject: [PATCH 03/22] added code for max.js --- Sprint-1/implement/max.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 6dd76378e..e1b256bce 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,4 +1,8 @@ function findMax(elements) { + elements = elements.filter(element => typeof element === 'number'); + if (elements.length === 0){ + return -Infinity; + } + return Math.max(...elements); } - module.exports = findMax; From e3befbbc298fe45abd00e85daaf92ed20577f06d Mon Sep 17 00:00:00 2001 From: JorvanW Date: Mon, 20 Jul 2026 20:48:37 +0100 Subject: [PATCH 04/22] Added code to sum.js --- Sprint-1/implement/sum.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index 9062aafe3..ae3530cf5 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,4 +1,14 @@ function sum(elements) { + elements = elements.filter(element => typeof element === 'number'); + let total = 0; + + for (let element of elements) { + total += element; + // += means to add to the current value and assign as result + // elements are individual items inside a collection (not just string) + } + + return total; } module.exports = sum; From 872ddf0cacc7385d8682ab46cc0fcfe2b375c301 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Tue, 21 Jul 2026 11:01:13 +0100 Subject: [PATCH 05/22] modified code on includes.js to use a for...of loop --- Sprint-1/refactor/includes.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sprint-1/refactor/includes.js b/Sprint-1/refactor/includes.js index 29dad81f0..6f2e347ad 100644 --- a/Sprint-1/refactor/includes.js +++ b/Sprint-1/refactor/includes.js @@ -1,8 +1,7 @@ // Refactor the implementation of includes to use a for...of loop function includes(list, target) { - for (let index = 0; index < list.length; index++) { - const element = list[index]; +for (const element of list) { if (element === target) { return true; } @@ -10,4 +9,5 @@ function includes(list, target) { return false; } + module.exports = includes; From 6c28930016f476696af00a70dd6c09ae83fe49dd Mon Sep 17 00:00:00 2001 From: JorvanW Date: Tue, 21 Jul 2026 13:28:00 +0100 Subject: [PATCH 06/22] Changed code in address. js to specify houseNumber --- Sprint-2/debug/address.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..8bd5f6294 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,4 +1,6 @@ // Predict and explain first... +// To specify house number the console.log should use. address.houseNumber. +// without it, It would show as undefined // This code should log out the houseNumber from the address object // but it isn't working... @@ -12,4 +14,4 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +console.log(`My house number is ${address.houseNumber}`); From bbf0a7359fccf76002480e953f76542fb74dbc6b Mon Sep 17 00:00:00 2001 From: JorvanW Date: Tue, 21 Jul 2026 13:52:59 +0100 Subject: [PATCH 07/22] Updated code and added notes for author.js --- Sprint-2/debug/address.js | 4 ++-- Sprint-2/debug/author.js | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 8bd5f6294..66f1b1b32 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,6 +1,6 @@ // Predict and explain first... -// To specify house number the console.log should use. address.houseNumber. -// without it, It would show as undefined +/* To specify house number the console.log should use. address.houseNumber. +without it, It would show as undefined */ // This code should log out the houseNumber from the address object // but it isn't working... diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..461bf36bc 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -3,6 +3,14 @@ // 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 +/* The code wants to log the property value and is using a for...of loop +to make sure it logs everything, however Objects aren't in order and Javascript +doesn't know what you want. Author is an Object and objects are not +iterable which is the error. To fix this change (const value of author) to +(const value of object.values(author)) to specify we want the values (not properties) +in the Object which is 'author'. Using a loop allows up to add information in author +without needing to make changes anywhere else while getting an updated log */ + const author = { firstName: "Zadie", lastName: "Smith", @@ -11,6 +19,6 @@ const author = { alive: true, }; -for (const value of author) { +for (const value of Object.values(author)) { console.log(value); } From 5c2b4b5383e83288138ec53abb5533241e823705 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Tue, 21 Jul 2026 14:15:13 +0100 Subject: [PATCH 08/22] update the code and added notes to recipe.js --- Sprint-2/debug/recipe.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..b2567a6d6 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -1,4 +1,9 @@ // Predict and explain first... +/* In the console.log the {recipe} doesn't specify ingredients so it will +show up as undefined. Changing it to {recipe.ingredients} should fix that issue. +To log each ingredient on a new line you can use (.join("\n")) which +separate the code by line */ + // This program should log out the title, how many it serves and the ingredients. // Each ingredient should be logged on a new line @@ -10,6 +15,7 @@ const recipe = { ingredients: ["olive oil", "tomatoes", "salt", "pepper"], }; -console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); +console.log(`${recipe.title} + serves ${recipe.serves} + ingredients: + ${recipe.ingredients.join("\n")}`); From 663412b427e19d88b0018d4333884b324b20fe76 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Thu, 23 Jul 2026 11:44:05 +0100 Subject: [PATCH 09/22] Added code and tests for contains.js --- Sprint-2/implement/contains.js | 8 +++++++- Sprint-2/implement/contains.test.js | 21 ++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..487d3ecf3 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,9 @@ -function contains() {} +function contains(object, property) { + if (Array.isArray(object)) { + throw new Error("Invalid parameter"); + } + + return property in object; +} module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..d8eb34c36 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -16,20 +16,39 @@ as the object doesn't contains a key of 'c' // Given a contains function // When passed an object and a property name // Then it should return true if the object contains the property, false otherwise +test("contains a passed object should return true, false otherwise",() => { + expect(contains({a: 1, b: 2}, 2)).toEqual(false); + expect(contains({a: 1, b: 2}, 'b')).toEqual(true); +}); // Given an empty object // When passed to contains // Then it should return false -test.todo("contains on empty object returns false"); +test("contains an empty object, returns false",() => { + expect(contains({})).toEqual(false); +}); // Given an object with properties // When passed to contains with an existing property name // Then it should return true +test("contains object with properties, return true when passed with existing property name",() => { + expect(contains({name: 'alice'}, 'name')).toEqual(true); +}); + // Given an object with properties // When passed to contains with a non-existent property name // Then it should return false +test("contains a passed object with non-existent property names return false",() => { + expect(contains({a: 1, b: 2}, 'c')).toEqual(false); + }); + // Given invalid parameters like an array // When passed to contains // Then it should return false or throw an error +test("contains passed invalid parameters like an array to throw error", () => { + expect(() => contains(['horse', 'dog', 'fish'], 'fish')) + .toThrow("Invalid parameter"); +}); + From 4c0d767dad7fe2cd02ae859f2b2e8138f0640d58 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Thu, 23 Jul 2026 14:17:59 +0100 Subject: [PATCH 10/22] added code to lookup.test --- Sprint-2/implement/lookup.js | 19 +++++++++++++++++-- Sprint-2/implement/lookup.test.js | 6 +++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..ada3f0972 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,20 @@ -function createLookup() { - // implementation here +function createLookup(countryCurrencyPairs) { + const lookup = {}; + + countryCurrencyPairs.forEach(pair => { + lookup[pair[0]] = pair[1]; + }); + + return lookup; } +const countryCurrencyPairs = [ + ['US', 'USD'], + ['CA', 'CAD'], + ['EN', 'GBP'] +]; + + + + module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..8e25dc80e 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,8 @@ const createLookup = require("./lookup.js"); -test.todo("creates a country currency code lookup for multiple codes"); +test("creates a country currency code lookup for multiple codes",() => { + expect(createLookup(countryCurrencyPairs)).toEqual([[US, 'USD'], [CA, 'CAD'], [EN, 'GBP']]); +}) /* @@ -33,3 +35,5 @@ It should return: 'CA': 'CAD' } */ + + From 827b0522718f9b23c27aa8a3703a061bc2600395 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Tue, 28 Jul 2026 18:33:49 +0100 Subject: [PATCH 11/22] added code and passed tests for querystring.test.js --- Sprint-2/implement/querystring.js | 23 ++++++++++++++++++++--- Sprint-2/implement/querystring.test.js | 5 +++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..e472002a1 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,16 +1,33 @@ + function parseQueryString(queryString) { const queryParams = {}; if (queryString.length === 0) { return queryParams; } - const keyValuePairs = queryString.split("&"); - + let keyValuePairs = queryString.split("&"); + + for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); + if (!pair) continue; // continue is to skip empty strings + let [key,...values] = pair.split("="); + + key = decodeURIComponent(key.replace(/\+/g, " ")); + const value = decodeURIComponent(values.join("=").replace(/\+/g, " ")); + + + /* decodeURIComponent function decodes percent encoded characters + "replace" swaps one character with another + (/../) means the begining and end of a regex pattern (better for characters) + '\+' is an escaped '+' because it has its own function in coding */ + queryParams[key] = value; + + + console.log(pair) } return queryParams; } + module.exports = parseQueryString; diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 328b8df61..b9d1d20a1 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -31,13 +31,13 @@ test("should decode percent-encoded characters", () => { }); }); -test("should replace '+' by ' '", () => { + test("should replace '+' by ' '", () => { expect(parseQueryString("full+name=John+Doe")).toEqual({ "full name": "John Doe", }); }); -// Stretch exercise: Handling query strings that contain identical keys +/* Stretch exercise: Handling query strings that contain identical keys // Delete this test if you are not working on this optional case test("should store values of a key in an array when the key has 2 or more values", () => { @@ -46,3 +46,4 @@ test("should store values of a key in an array when the key has 2 or more values foo: "bar", }); }); +*/ From 2c0a94ca7613c219815bfccee98208a9eb3432a4 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Tue, 28 Jul 2026 19:47:36 +0100 Subject: [PATCH 12/22] added code and tests for tally.test and js --- Sprint-2/implement/tally.js | 27 ++++++++++++++++++++++++++- Sprint-2/implement/tally.test.js | 14 +++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..925c062da 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,28 @@ -function tally() {} +function tally(array) { //(array) is the input to the function + + if (!Array.isArray(array)){ //checking if array is actually an array + throw new Error("Input must be an array"); + } + + if (array.length === 0){ //if array is empty return a empty array + return [] + } + + + const result = {} //creates result as an empty object which will store the counts + + + for (const item of array){ //'for' loops through every item in the array + if (result[item]){ // checks if the item is already in the result{} + result[item]++} // If it is then '++' tells it to add 1 to the value + + else { + result[item] = 1; // else is saying that if it doesn't exist then we give it a value of 1 + } + +} + + return result; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..5952260a1 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -19,16 +19,28 @@ const tally = require("./tally.js"); // Given a function called tally // When passed an array of items // Then it should return an object containing the count for each unique item +test("tally should return an count of each item passed through an array ",() => { + expect(tally(['a', 'b', 'c'])).toEqual({a: 1, b: 1, c: 1}); +}); // Given an empty array // When passed to tally // Then it should return an empty object -test.todo("tally on an empty array returns an empty object"); +test("tally on an empty array returns an empty object",() => { + expect(tally([])).toEqual([]); +}); // Given an array with duplicate items // When passed to tally // Then it should return counts for each unique item +test("tally on an array with duplicate items return a count for each item ",() => { + expect(tally(['a', 'a', 'b', 'c'])).toEqual({a: 2, b: 1, c: 1}); +}); // Given an invalid input like a string // When passed to tally // Then it should throw an error +test("tally with a invalid string should throw an error",() => { + expect(tally('car')) + .toThrow("Input must be an array"); +}); From f583fd7b40cea5caad43c85d5f008f0f4aedff14 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Wed, 29 Jul 2026 10:32:36 +0100 Subject: [PATCH 13/22] updated tests output for tally.test --- Sprint-2/implement/tally.test.js | 2 +- Sprint-2/interpret/invert.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 5952260a1..4c0bd2e74 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -41,6 +41,6 @@ test("tally on an array with duplicate items return a count for each item ",() // When passed to tally // Then it should throw an error test("tally with a invalid string should throw an error",() => { - expect(tally('car')) + expect(() => tally('car')) .toThrow("Input must be an array"); }); diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..bb9c888fa 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -17,13 +17,20 @@ function invert(obj) { } // a) What is the current return value when invert is called with { a : 1 } +// { key: 1 } // b) What is the current return value when invert is called with { a: 1, b: 2 } +// { key: 2 } // c) What is the target return value when invert is called with {a : 1, b: 2} +// {"1": "a", "2":"b"} + // c) What does Object.entries return? Why is it needed in this program? +// It returns an array of property into the object // d) Explain why the current return value is different from the target output +// The current return value only shows {key: 2}. It doesn't show the first key and value only the second, +// and it doesn't specify the second key. Its just defined as 'key' // e) Fix the implementation of invert (and write tests to prove it's fixed!) From 93df34207c9289f2fe4d6afbf520ed03673646eb Mon Sep 17 00:00:00 2001 From: JorvanW Date: Wed, 29 Jul 2026 10:54:10 +0100 Subject: [PATCH 14/22] added answers to invert.js and added a .test.js page to --- Sprint-2/interpret/invert.js | 16 ++++++++++------ Sprint-2/interpret/invert.test.js | 5 +++++ 2 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 Sprint-2/interpret/invert.test.js diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb9c888fa..48a6607a1 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -6,12 +6,12 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} -function invert(obj) { - const invertedObj = {}; +function invert(obj) { // obj{} is the input of invert function + const invertedObj = {}; // says that invertedObj is a empty object {} - for (const [key, value] of Object.entries(obj)) { - invertedObj.key = value; - } + for (const [key, value] of Object.entries(obj)) { //'for' is looping the key and value of the object + invertedObj[key] = value; // stored. Object.entires(obj) returns an array of array + } // key in a bracket [] lets you use a variable called key return invertedObj; } @@ -31,6 +31,10 @@ function invert(obj) { // d) Explain why the current return value is different from the target output // The current return value only shows {key: 2}. It doesn't show the first key and value only the second, -// and it doesn't specify the second key. Its just defined as 'key' +// and it doesn't specify the second key. Its just defined as 'key'. // e) Fix the implementation of invert (and write tests to prove it's fixed!) + +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..b52cb2a01 --- /dev/null +++ b/Sprint-2/interpret/invert.test.js @@ -0,0 +1,5 @@ +const invert = require("./invert.js"); + +test("When invert is passed, keys and values in the object should be swapped ",() => { + expect({x : 10, y : 20}).toEqual({x : 10, y : 20}); +}); From 5b96abc120e881da43afd9fb04b81ff8a3bf0b60 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Mon, 10 Aug 2026 23:02:23 +0100 Subject: [PATCH 15/22] removed code from sprint 1 and removed prep folder --- Sprint-1/fix/median.js | 22 ++--------- Sprint-1/fix/median.test.js | 38 +++++++++---------- Sprint-1/implement/dedupe.js | 4 +- Sprint-1/implement/max.js | 6 +-- Sprint-1/implement/sum.js | 10 ----- Sprint-1/refactor/includes.js | 4 +- .../Module-Data-Groups.code-workspace | 8 ++++ prep/mean.js | 0 prep/mean.test.js | 0 prep/parse-query-string.js | 0 prep/parse-query-string.test.js | 7 ---- 11 files changed, 35 insertions(+), 64 deletions(-) create mode 100644 Sprint-3/quote-generator/Module-Data-Groups.code-workspace delete mode 100644 prep/mean.js delete mode 100644 prep/mean.test.js delete mode 100644 prep/parse-query-string.js delete mode 100644 prep/parse-query-string.test.js diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index 6b000bd80..b22590bc6 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -5,24 +5,10 @@ // Hint: Please consider scenarios when 'list' doesn't have numbers (the function is expected to return null) // or 'list' has mixed values (the function is expected to sort only numbers). -function calculateMedian(list) { - list = list.filter(element => typeof element === 'number'); - list.sort((a, b) => a - b); - - if (list.length % 2 === 0){ - const middleIndexR = Math.floor(list.length / 2); - const middleIndexL = middleIndexR - 1 - const evenMedian = (list[middleIndexL] + list[middleIndexR]) / 2; - - return evenMedian - } else { - const middleIndex = Math.floor(list.length / 2); - const median = list[middleIndex]; - return median; - } - +function calculateMedian(list) { + const middleIndex = Math.floor(list.length / 2); + const median = list.splice(middleIndex, 1)[0]; + return median; } - - module.exports = calculateMedian; diff --git a/Sprint-1/fix/median.test.js b/Sprint-1/fix/median.test.js index b5cda5690..21da654d7 100644 --- a/Sprint-1/fix/median.test.js +++ b/Sprint-1/fix/median.test.js @@ -27,24 +27,24 @@ describe("calculateMedian", () => { it(`returns the correct median for unsorted array [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) ); -// it("doesn't modify the input array [3, 1, 2]", () => { -// const list = [3, 1, 2]; -// calculateMedian(list); -// expect(list).toEqual([3, 1, 2]); -// }); + it("doesn't modify the input array [3, 1, 2]", () => { + const list = [3, 1, 2]; + calculateMedian(list); + expect(list).toEqual([3, 1, 2]); + }); -// [ 'not an array', 123, null, undefined, {}, [], ["apple", null, undefined] ].forEach(val => -// it(`returns null for non-numeric array (${val})`, () => expect(calculateMedian(val)).toBe(null)) -// ); + [ 'not an array', 123, null, undefined, {}, [], ["apple", null, undefined] ].forEach(val => + it(`returns null for non-numeric array (${val})`, () => expect(calculateMedian(val)).toBe(null)) + ); -// [ -// { input: [1, 2, "3", null, undefined, 4], expected: 2 }, -// { input: ["apple", 1, 2, 3, "banana", 4], expected: 2.5 }, -// { input: [1, "2", 3, "4", 5], expected: 3 }, -// { input: [1, "apple", 2, null, 3, undefined, 4], expected: 2.5 }, -// { input: [3, "apple", 1, null, 2, undefined, 4], expected: 2.5 }, -// { input: ["banana", 5, 3, "apple", 1, 4, 2], expected: 3 }, -// ].forEach(({ input, expected }) => -// it(`filters out non-numeric values and calculates the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) -// ); - }); + [ + { input: [1, 2, "3", null, undefined, 4], expected: 2 }, + { input: ["apple", 1, 2, 3, "banana", 4], expected: 2.5 }, + { input: [1, "2", 3, "4", 5], expected: 3 }, + { input: [1, "apple", 2, null, 3, undefined, 4], expected: 2.5 }, + { input: [3, "apple", 1, null, 2, undefined, 4], expected: 2.5 }, + { input: ["banana", 5, 3, "apple", 1, 4, 2], expected: 3 }, + ].forEach(({ input, expected }) => + it(`filters out non-numeric values and calculates the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) + ); +}); diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 18b6526b0..781e8718a 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1,3 +1 @@ -function dedupe(list) { - return [...new Set(list)]; -} +function dedupe() {} diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index e1b256bce..6dd76378e 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,8 +1,4 @@ function findMax(elements) { - elements = elements.filter(element => typeof element === 'number'); - if (elements.length === 0){ - return -Infinity; - } - return Math.max(...elements); } + module.exports = findMax; diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index ae3530cf5..9062aafe3 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,14 +1,4 @@ function sum(elements) { - elements = elements.filter(element => typeof element === 'number'); - let total = 0; - - for (let element of elements) { - total += element; - // += means to add to the current value and assign as result - // elements are individual items inside a collection (not just string) - } - - return total; } module.exports = sum; diff --git a/Sprint-1/refactor/includes.js b/Sprint-1/refactor/includes.js index 6f2e347ad..29dad81f0 100644 --- a/Sprint-1/refactor/includes.js +++ b/Sprint-1/refactor/includes.js @@ -1,7 +1,8 @@ // Refactor the implementation of includes to use a for...of loop function includes(list, target) { -for (const element of list) { + for (let index = 0; index < list.length; index++) { + const element = list[index]; if (element === target) { return true; } @@ -9,5 +10,4 @@ for (const element of list) { return false; } - module.exports = includes; diff --git a/Sprint-3/quote-generator/Module-Data-Groups.code-workspace b/Sprint-3/quote-generator/Module-Data-Groups.code-workspace new file mode 100644 index 000000000..407c76059 --- /dev/null +++ b/Sprint-3/quote-generator/Module-Data-Groups.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "../.." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/prep/mean.js b/prep/mean.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/prep/mean.test.js b/prep/mean.test.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/prep/parse-query-string.js b/prep/parse-query-string.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/prep/parse-query-string.test.js b/prep/parse-query-string.test.js deleted file mode 100644 index d4a0f01b9..000000000 --- a/prep/parse-query-string.test.js +++ /dev/null @@ -1,7 +0,0 @@ -test("given a query string with no query parameters, returns an empty object", function () { - const input = ""; - const currentOutput = parseQueryString(input); - const targetOutput = {}; - - expect(currentOutput).toEqual(targetOutput); -}); From f6cf1e163f51f7d8def0988b54fe4751c13ee1b5 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Mon, 10 Aug 2026 23:09:45 +0100 Subject: [PATCH 16/22] removed file --- .../quote-generator/Module-Data-Groups.code-workspace | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 Sprint-3/quote-generator/Module-Data-Groups.code-workspace diff --git a/Sprint-3/quote-generator/Module-Data-Groups.code-workspace b/Sprint-3/quote-generator/Module-Data-Groups.code-workspace deleted file mode 100644 index 407c76059..000000000 --- a/Sprint-3/quote-generator/Module-Data-Groups.code-workspace +++ /dev/null @@ -1,8 +0,0 @@ -{ - "folders": [ - { - "path": "../.." - } - ], - "settings": {} -} \ No newline at end of file From fca3dde3693ba34496ca312fb889445500af02b5 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Thu, 13 Aug 2026 09:44:07 +0100 Subject: [PATCH 17/22] removed errors in the lookup.js code and updated the test to function properly --- Sprint-2/implement/lookup.js | 11 +---------- Sprint-2/implement/lookup.test.js | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index ada3f0972..66ccfc568 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,20 +1,11 @@ function createLookup(countryCurrencyPairs) { const lookup = {}; - countryCurrencyPairs.forEach(pair => { + countryCurrencyPairs.forEach((pair) => { lookup[pair[0]] = pair[1]; }); return lookup; } -const countryCurrencyPairs = [ - ['US', 'USD'], - ['CA', 'CAD'], - ['EN', 'GBP'] -]; - - - - module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 8e25dc80e..93a03bd4e 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,8 +1,18 @@ const createLookup = require("./lookup.js"); -test("creates a country currency code lookup for multiple codes",() => { - expect(createLookup(countryCurrencyPairs)).toEqual([[US, 'USD'], [CA, 'CAD'], [EN, 'GBP']]); -}) +test("creates a country currency code lookup for multiple codes", () => { + const countryCurrencyPairs = [ + ["US", "USD"], + ["CA", "CAD"], + ["EN", "GBP"], + ]; + + expect(createLookup(countryCurrencyPairs)).toEqual({ + US: "USD", + CA: "CAD", + EN: "GBP", + }); +}); /* @@ -35,5 +45,3 @@ It should return: 'CA': 'CAD' } */ - - From edb970dbed28d81ccc0a2f8a77c11f90d06a3540 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Thu, 13 Aug 2026 09:46:58 +0100 Subject: [PATCH 18/22] removed console.log in code --- Sprint-2/implement/querystring.js | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index e472002a1..ed62cf529 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,33 +1,26 @@ - function parseQueryString(queryString) { const queryParams = {}; if (queryString.length === 0) { return queryParams; } let keyValuePairs = queryString.split("&"); - - + for (const pair of keyValuePairs) { - if (!pair) continue; // continue is to skip empty strings - let [key,...values] = pair.split("="); - - key = decodeURIComponent(key.replace(/\+/g, " ")); - const value = decodeURIComponent(values.join("=").replace(/\+/g, " ")); + if (!pair) continue; // continue is to skip empty strings + let [key, ...values] = pair.split("="); + + key = decodeURIComponent(key.replace(/\+/g, " ")); + const value = decodeURIComponent(values.join("=").replace(/\+/g, " ")); - - /* decodeURIComponent function decodes percent encoded characters + /* decodeURIComponent function decodes percent encoded characters "replace" swaps one character with another (/../) means the begining and end of a regex pattern (better for characters) - '\+' is an escaped '+' because it has its own function in coding */ - - queryParams[key] = value; + '\+' is an escaped '+' because it has its own function in coding */ - - console.log(pair) + queryParams[key] = value; } return queryParams; } - module.exports = parseQueryString; From d7af84e4d605185b0738b9bd021d709417a8e838 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Thu, 13 Aug 2026 09:51:27 +0100 Subject: [PATCH 19/22] updated tally.js and tally.test to turn and empty array into a empty object as required --- Sprint-2/implement/tally.js | 38 +++++++++++++++++--------------- Sprint-2/implement/tally.test.js | 17 +++++++------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index 925c062da..1376b60e4 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,28 +1,30 @@ -function tally(array) { //(array) is the input to the function +function tally(array) { + //(array) is the input to the function - if (!Array.isArray(array)){ //checking if array is actually an array - throw new Error("Input must be an array"); + if (!Array.isArray(array)) { + //checking if array is actually an array + throw new Error("Input must be an array"); } - - if (array.length === 0){ //if array is empty return a empty array - return [] + + if (array.length === 0) { + //if array is empty return a empty array + return {}; } - - - const result = {} //creates result as an empty object which will store the counts - - for (const item of array){ //'for' loops through every item in the array - if (result[item]){ // checks if the item is already in the result{} - result[item]++} // If it is then '++' tells it to add 1 to the value - + const result = {}; //creates result as an empty object which will store the counts + + for (const item of array) { + //'for' loops through every item in the array + if (result[item]) { + // checks if the item is already in the result{} + result[item]++; + } // If it is then '++' tells it to add 1 to the value else { - result[item] = 1; // else is saying that if it doesn't exist then we give it a value of 1 + result[item] = 1; // else is saying that if it doesn't exist then we give it a value of 1 } - -} + } - return result; + return result; } module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 4c0bd2e74..05b2602ec 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -19,28 +19,27 @@ const tally = require("./tally.js"); // Given a function called tally // When passed an array of items // Then it should return an object containing the count for each unique item -test("tally should return an count of each item passed through an array ",() => { - expect(tally(['a', 'b', 'c'])).toEqual({a: 1, b: 1, c: 1}); +test("tally should return an count of each item passed through an array ", () => { + expect(tally(["a", "b", "c"])).toEqual({ a: 1, b: 1, c: 1 }); }); // Given an empty array // When passed to tally // Then it should return an empty object -test("tally on an empty array returns an empty object",() => { - expect(tally([])).toEqual([]); +test("tally on an empty array returns an empty object", () => { + expect(tally([])).toEqual({}); }); // Given an array with duplicate items // When passed to tally // Then it should return counts for each unique item -test("tally on an array with duplicate items return a count for each item ",() => { - expect(tally(['a', 'a', 'b', 'c'])).toEqual({a: 2, b: 1, c: 1}); +test("tally on an array with duplicate items return a count for each item ", () => { + expect(tally(["a", "a", "b", "c"])).toEqual({ a: 2, b: 1, c: 1 }); }); // Given an invalid input like a string // When passed to tally // Then it should throw an error -test("tally with a invalid string should throw an error",() => { - expect(() => tally('car')) - .toThrow("Input must be an array"); +test("tally with a invalid string should throw an error", () => { + expect(() => tally("car")).toThrow("Input must be an array"); }); From 37deb3c5fca15fc42c1e1cbf51b5a28c740f09ec Mon Sep 17 00:00:00 2001 From: JorvanW Date: Thu, 13 Aug 2026 10:47:10 +0100 Subject: [PATCH 20/22] removed excess comments in invert.js. fixed the code and added more test cases for invert --- Sprint-2/interpret/invert.js | 18 +++++++----------- Sprint-2/interpret/invert.test.js | 12 ++++++++++-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index 48a6607a1..301a543df 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -6,12 +6,11 @@ // E.g. invert({x : 10, y : 20}), target output: {"10": "x", "20": "y"} -function invert(obj) { // obj{} is the input of invert function - const invertedObj = {}; // says that invertedObj is a empty object {} - - for (const [key, value] of Object.entries(obj)) { //'for' is looping the key and value of the object - invertedObj[key] = value; // stored. Object.entires(obj) returns an array of array - } // key in a bracket [] lets you use a variable called key +function invert(obj) { + const invertedObj = {}; + for (const [key, value] of Object.entries(obj)) { + invertedObj[value] = key; + } return invertedObj; } @@ -25,16 +24,13 @@ function invert(obj) { // obj{} is the input of invert funct // c) What is the target return value when invert is called with {a : 1, b: 2} // {"1": "a", "2":"b"} - // c) What does Object.entries return? Why is it needed in this program? // It returns an array of property into the object // d) Explain why the current return value is different from the target output -// The current return value only shows {key: 2}. It doesn't show the first key and value only the second, -// and it doesn't specify the second key. Its just defined as 'key'. +// The current return value only shows {key: 2}. It doesn't show the first key and value only the second, +// and it doesn't specify the second key. Its just defined as 'key'. // e) Fix the implementation of invert (and write tests to prove it's fixed!) module.exports = invert; - - diff --git a/Sprint-2/interpret/invert.test.js b/Sprint-2/interpret/invert.test.js index b52cb2a01..37af999b3 100644 --- a/Sprint-2/interpret/invert.test.js +++ b/Sprint-2/interpret/invert.test.js @@ -1,5 +1,13 @@ const invert = require("./invert.js"); -test("When invert is passed, keys and values in the object should be swapped ",() => { - expect({x : 10, y : 20}).toEqual({x : 10, y : 20}); +test("when passed invert swaps single key-value pair", () => { + expect(invert({ a: 1 })).toEqual({ "1": "a" }); }); + +test("When invert is passed, multiple keys and values in the object should be swapped ", () => { + expect(invert({ x: 10, y: 20 })).toEqual({ "10": "x", "20": "y" }) +}); + +test("when passed invert swaps string values", () => { + expect(invert({ first: "hello",second: "world" })).toEqual({ hello: "first", world: "second" }); +}); \ No newline at end of file From bdcc0fc3c35189b106ad6d3bd6a1f43c97618b67 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Thu, 13 Aug 2026 11:12:59 +0100 Subject: [PATCH 21/22] updated answers for invert.js --- Sprint-2/interpret/invert.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index 301a543df..4c57409f1 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -25,11 +25,11 @@ function invert(obj) { // {"1": "a", "2":"b"} // c) What does Object.entries return? Why is it needed in this program? -// It returns an array of property into the object +// Object Entries return an array of key value pairs and it's needed so the for...of loop goes through each key and value individually // d) Explain why the current return value is different from the target output // The current return value only shows {key: 2}. It doesn't show the first key and value only the second, -// and it doesn't specify the second key. Its just defined as 'key'. +// and it doesn't specify the second key. Its just defined as 'key'. It also doesn't swap the key and value around as intended // e) Fix the implementation of invert (and write tests to prove it's fixed!) From 04d19dde92f1532ae40674389f8f5bad6d829cb9 Mon Sep 17 00:00:00 2001 From: JorvanW Date: Thu, 13 Aug 2026 11:19:26 +0100 Subject: [PATCH 22/22] removed unecessary comment --- Sprint-2/implement/tally.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index 1376b60e4..dccec7039 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,26 +1,19 @@ function tally(array) { - //(array) is the input to the function - if (!Array.isArray(array)) { - //checking if array is actually an array throw new Error("Input must be an array"); } if (array.length === 0) { - //if array is empty return a empty array return {}; } - const result = {}; //creates result as an empty object which will store the counts + const result = {}; for (const item of array) { - //'for' loops through every item in the array if (result[item]) { - // checks if the item is already in the result{} result[item]++; - } // If it is then '++' tells it to add 1 to the value - else { - result[item] = 1; // else is saying that if it doesn't exist then we give it a value of 1 + } else { + result[item] = 1; } }