Skip to content
This repository was archived by the owner on Dec 18, 2024. It is now read-only.

Migracode|Afere Onome Precious|Module Js-2|Sprint 2|Week 2 #239

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
1,051 changes: 943 additions & 108 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/user-event": "^13.5.0",
"jest": "^29.2.2",
"jest-environment-jsdom": "^29.2.2"
"jest-environment-jsdom": "^29.2.2",
"test": "^3.3.0"
},
"jest": {
"setupFilesAfterEnv": [
Expand Down
4 changes: 3 additions & 1 deletion week-2/debug/address.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// Predict and explain first...
//Answer:We can not access object with index instead we access them with the key, that is why we mutilate it by using the ".",
//and then the key to get access to the house number.

// This code should log out the houseNumber from the address object
// but it isn't working...
Expand All @@ -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}`);
7 changes: 5 additions & 2 deletions week-2/debug/author.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Predict and explain first...

/**Answer:
* Javascript doesn't allow you to iterate over object value,
* objects don't have the natural sequence that arrays do
*/
// 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

Expand All @@ -11,6 +14,6 @@ const author = {
alive: true,
};

for (const value of author) {
for (const value of Object.values(author)) {
console.log(value);
}
2 changes: 1 addition & 1 deletion week-2/debug/recipe.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ const recipe = {
};

console.log(`${recipe.title} serves ${recipe.serves}
ingredients:
ingredients:\n${recipe.ingredients.join("\n")}
${recipe}`);
10 changes: 9 additions & 1 deletion week-2/implement/contains.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
function contains() {}
function contains(object, key) {
if (typeof object !== "object" || object === null) {
throw new TypeError("Invalid input: object must be a non-null object.");
}
return object.hasOwnProperty(key);
}
console.log(contains({ a: 1, b: 2 }, "a"));
console.log(contains({ a: 1, b: 2 }, "c"));
console.log(contains({}, "a"));

module.exports = contains;
26 changes: 26 additions & 0 deletions week-2/implement/contains.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,29 @@ as the object doesn't contains a key of 'c'
// Given invalid parameters like arrays
// When passed to contains
// Then it should return false or throw an error

describe("contains()", () => {
test("Given an object with the property, it should return true", () => {
expect(contains({ a: 1, b: 2 }, "a")).toBe(true);
});

test("Given an object without the property, it should return false", () => {
expect(contains({ a: 1, b: 2 }, "c")).toBe(false);
});

test("Given an empty object, it should return false", () => {
expect(contains({}, "a")).toBe(false);
});

test("Given null, it should throw an error", () => {
expect(() => contains(null, "a")).toThrow(
"Invalid input: object must be a non-null object."
);
});

test("Given a non-object input, it should throw an error", () => {
expect(() => contains(42, "a")).toThrow(
"Invalid input: object must be a non-null object."
);
});
});
15 changes: 14 additions & 1 deletion week-2/implement/lookup.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
function createLookup() {
function createLookup(countryCurrencyPairs) {
// implementation here
const lookup = {};
for (const pair of countryCurrencyPairs) {
const [countryCodes, currencyCodes] = pair;
lookup[countryCodes] = currencyCodes;
}
return lookup;
}
const countryCurrencyPairs = [
["US", "USD"],
["CA", "CAD"],
];
console.log(createLookup(countryCurrencyPairs));

module.exports = createLookup;
1 change: 1 addition & 0 deletions week-2/implement/lookup.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// ======= Test suite is provided below... =======
const createLookup = require("./lookup");

test("converts a single pair of currency codes", () => {
expect(createLookup([["GB", "GBP"]])).toEqual({
Expand Down
20 changes: 20 additions & 0 deletions week-2/implement/tally.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
function tally(items) {
if (!Array.isArray(items)) {
throw new Error("Invalid input,input must be an array");
}
const result = {};
for (const item of items) {
if (result[item]) {
result[item]++;
} else {
result[item] = 1;
}
}
return result;
}
console.log(tally(["a"]));
console.log(tally(["a", "a", "a"]));
console.log(tally(["a", "a", "b", "c"]));
console.log(tally([]));

module.exports = tally;
19 changes: 19 additions & 0 deletions week-2/implement/tally.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,22 @@
// Given an invalid input like a string
// When passed to tally
// Then it should throw an error

const tally = require("./tally");

test("tallies a single item in an array", () => {
expect(tally(["a"])).toEqual({ a: 1 });
});
test("tallies an array with duplicate items", () => {
expect(tally(["a", "a", "a"])).toEqual({ a: 3 });
});
test("Given an empty array,it should return an empty object", () => {
expect(tally([])).toEqual({});
});
test("Given an invalid input,it should throw an error", () => {
expect(() => tally("invalid")).toThrow(
"Invalid input,input must be an array"
);
expect(() => tally(123)).toThrow("Invalid input,input must be an array");
expect(() => tally(null)).toThrow("Invalid input,input must be an array");
});
15 changes: 14 additions & 1 deletion week-2/interpret/invert.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,31 @@ function invert(obj) {
const invertedObj = {};

for (const [key, value] of Object.entries(obj)) {
invertedObj.key = value;
invertedObj[value] = key;
}

return invertedObj;
}
const obj = { a: 1, b: 2 };
const entries = Object.entries(obj);
console.log(invert({ a: 1 }));

console.log(invert({ a: 1, b: 2 }));

console.log(invert({ x: 10, y: 20 }));
console.log(entries);

// a) What is the current return value when invert is called with { a : 1 }
//Answer :key:1

// b) What is the current return value when invert is called with { a: 1, b: 2 }
//Answer : key:2

// c) What is the target return value when invert is called with {a : 1, b: 2}
//Answer :{ '1': 'a' }

// c) What does Object.entries return? Why is it needed in this program?
//Answer:It returns an array of the keys and values, when it is needed

// d) Explain why the current return value is different from the target output
//Answer:It is different because invertedObj.key = value; this doesn't create a property with the actual value of key from the object. Instead, it literally sets a property named "key" in invertedObj.
15 changes: 15 additions & 0 deletions week-2/stretch/count-words.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
function countWords(str) {
const wordCount = {};
const words = str.split("");

for (const word of words) {
if (wordCount[word]) {
wordCount[word]++;
} else {
wordCount[word] = 1;
}
}
return wordCount;
}
console.log(countWords("you and me and you"));

/*
Count the number of times a word appears in a given string.

Expand Down
14 changes: 9 additions & 5 deletions week-2/stretch/mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// refactor calculateMode by splitting up the code
// into smaller functions using the stages above

function calculateMode(list) {
function trackFrequency(list) {
// track frequency of each value
let freqs = new Map();

Expand All @@ -17,8 +17,10 @@ function calculateMode(list) {

freqs.set(num, (freqs.get(num) || 0) + 1);
}

// Find the value with the highest frequency
return freqs;
}
// Find the value with the highest frequency
function findMode(freqs) {
let maxFreq = 0;
let mode;
for (let [num, freq] of freqs) {
Expand All @@ -27,8 +29,10 @@ function calculateMode(list) {
maxFreq = freq;
}
}

return maxFreq === 0 ? NaN : mode;
}

function calculateMode(list) {
const freqs = trackFrequency(list);
return findMode(freqs);
}
module.exports = calculateMode;
16 changes: 12 additions & 4 deletions week-2/stretch/till.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,33 @@ function totalTill(till) {
let total = 0;

for (const [coin, quantity] of Object.entries(till)) {
console.log(coin * quantity);
total += coin * quantity;
const coinValue = parseInt(coin.replace("p", ""), 10);

if (isNaN(coinValue)) {
continue;
}
total += coinValue * quantity;
}

return `£${total / 100}`;
return `£${(total / 100).toFixed(2)}`;
}

const till = {
"1p": 10,
"5p": 6,
"50p": 4,
"20p": 10,
};

const totalAmount = totalTill(till);
module.exports = totalTill;

// a) What is the target output when totalTill is called with the till object
//Answer:NaN

// b) Why do we need to use Object.entries inside the for...of loop in this function?
//Answer:it allows us to iterate over the key and value pairs of an object in a structured way.

// c) What does coin * quantity evaluate to inside the for...of loop?
//Answer: its evaluating the product of two value coin and quantity.

// d) Write a test for this function to check it works and then fix the implementation of totalTill
39 changes: 39 additions & 0 deletions week-2/stretch/till.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const totalTill = require("./till");

describe("totalTill function", () => {
test("should correctly calculate the total value of coins", () => {
const till = {
"1p": 10,
"5p": 6,
"50p": 4,
"20p": 10,
};

// Expected total to be: 10 * 1p + 6 * 5p + 4 * 50p + 10 * 20p = 10 + 30 + 200 + 200 = 440p = £4.40
const result = totalTill(till);
expect(result).toBe("£4.40");
});

test("should return £0.00 when no coins are present", () => {
const till = {};
const result = totalTill(till);
expect(result).toBe("£0.00");
});

test("should correctly calculate when only one coin type is present", () => {
const till = {
"2p": 5, // Expected to be:5 * 2p = 10p = £0.10
};
const result = totalTill(till);
expect(result).toBe("£0.10");
});

test("should handle coins with higher denominations correctly", () => {
const till = {
"1p": 100, // Expected to be:100 * 1p = 100p = £1.00
"50p": 2, // Expected to be:2 * 50p = 100p = £1.00
};
const result = totalTill(till);
expect(result).toBe("£2.00");
});
});