diff --git a/Sprint-3/1-key-errors/0.js b/Sprint-3/1-key-errors/0.js index 653d6f5a0..29ce9f80c 100644 --- a/Sprint-3/1-key-errors/0.js +++ b/Sprint-3/1-key-errors/0.js @@ -1,13 +1,29 @@ // Predict and explain first... // =============> write your prediction here +// Prediction +// A SyntaxError is thrown with message: Identifier 'str' has already been declared // call the function capitalise with a string input // interpret the error message and figure out why an error is occurring +// Error message interpreted ====> The error message simply means the name 'str' was declared twice in the same scope -function capitalise(str) { - let str = `${str[0].toUpperCase()}${str.slice(1)}`; - return str; -} - +// function capitalise(str) { +// let str = `${str[0].toUpperCase()}${str.slice(1)}`; +// return str; +// } +// capitalise("moses"); // =============> write your explanation here +// The error here is because the parameter 'str' and the variable 'let str' share the same name in he same scope, thus the SyntaxError. +// To fix this error, I could either give the variable a different name or reassign the parameter 'str' without 'let', since no new declaration is made + // =============> write your new code here +// function capitalise(str) { +// let capitalised = `${str[0].toUpperCase()}${str.slice(1)}`; +// return capitalised; +// } +// console.log(capitalise("moses")); +// | +function capitalise(str) { + return `${str[0].toUpperCase()}${str.slice(1)}`; +} +console.log(capitalise("moses")); \ No newline at end of file diff --git a/Sprint-3/1-key-errors/1.js b/Sprint-3/1-key-errors/1.js index f2d56151f..454384a8c 100644 --- a/Sprint-3/1-key-errors/1.js +++ b/Sprint-3/1-key-errors/1.js @@ -1,20 +1,32 @@ // Predict and explain first... +// My prediction is the program would throw a SyntaxError, because 'decimalNumber' has already been declared as a parameter and also has been declared as a new variable in the same scope // Why will an error occur when this program runs? // =============> write your prediction here +//An error will occur because 'const decimalNumber = 0.5' clashes with the parameter of the same name. // Try playing computer with the example to work out what is going on -function convertToPercentage(decimalNumber) { - const decimalNumber = 0.5; - const percentage = `${decimalNumber * 100}%`; +// function convertToPercentage(decimalNumber) { +// // The parameter 'decimalNumber' is created as a variable inside the function's scope. +// const decimalNumber = 0.5; +// // tries to declare new variable called 'decimalNumber' in the same scope, where one already exists as a parameter +// // cannot declare same name twice in one scope with 'const' +// const percentage = `${decimalNumber * 100}%`; - return percentage; -} - -console.log(decimalNumber); +// return percentage; +// } +// // As a result of the conflict nothing runs. +// console.log(decimalNumber); +// // This line is outside the function and would not parse, as 'decimalNumber' only exists inside 'convertToPercentage' as a parameter. // =============> write your explanation here +// Parameters and variables declared inside a function cannot be accessed outside it. // Finally, correct the code to fix the problem // =============> write your new code here +function convertToPercentage(decimalNumber){ + return `${decimalNumber * 100}%`; + +} +console.log(convertToPercentage(0.5)); \ No newline at end of file diff --git a/Sprint-3/1-key-errors/2.js b/Sprint-3/1-key-errors/2.js index aad57f7cf..4e0a059c3 100644 --- a/Sprint-3/1-key-errors/2.js +++ b/Sprint-3/1-key-errors/2.js @@ -1,20 +1,28 @@ // Predict and explain first BEFORE you run any code... - +// The parameter is written as a value instead of a variable name // this function should square any number but instead we're going to get an error // =============> write your prediction of the error here +// The program will throw a SyntaxError -function square(3) { - return num * num; -} +// function square(3) { +// return num * num; +// } // =============> write the error message here +// SyntaxError: Unexpected number // =============> explain this error message here +// In the 'function square(3)' JavaScript parser expected a valid parameter name it could use as a variable +// Since '3' is a number literal, not a valid identifier, the parser cannot understand it and throws a syntax error. // Finally, correct the code to fix the problem // =============> write your new code here +function square(number){ + return number * number; +} +console.log(square(77)); diff --git a/Sprint-3/2-mandatory-debug/0.js b/Sprint-3/2-mandatory-debug/0.js index b27511b41..91cc921ba 100644 --- a/Sprint-3/2-mandatory-debug/0.js +++ b/Sprint-3/2-mandatory-debug/0.js @@ -1,14 +1,26 @@ // Predict and explain first... // =============> write your prediction here +// My prediction is '320' would be printed first followed by "The result of multiplying 10 and 32 is undefined" +// This occurs because 'multiply()' does not return anything -function multiply(a, b) { - console.log(a * b); -} +// function multiply(a, b) { +// console.log(a * b); +// } -console.log(`The result of multiplying 10 and 32 is ${multiply(10, 32)}`); +// console.log(`The result of multiplying 10 and 32 is ${multiply(10, 32)}`); // =============> write your explanation here +// The template literal calls 'multiply(10, 32) to build the string +// Inside multiply, 'console.log(a * b)' runs immediately, printing '320' +// This happens before the outer 'console.log' line finishes, because JavaScript has to evaluate 'multiply(10, 32)' first to know what to put in the template +// 'multiply's' function body only contains a 'console.log' statement without a 'return' keyword +// A function with no explicit return statement returns 'undefined' by default. // Finally, correct the code to fix the problem // =============> write your new code here +function multiply(a, b){ + return a * b; +} + +console.log(`The result of multiplying 10 and 32 is ${multiply(10, 32)}`); diff --git a/Sprint-3/2-mandatory-debug/1.js b/Sprint-3/2-mandatory-debug/1.js index 37cedfbcf..38429c167 100644 --- a/Sprint-3/2-mandatory-debug/1.js +++ b/Sprint-3/2-mandatory-debug/1.js @@ -1,13 +1,23 @@ // Predict and explain first... // =============> write your prediction here +// The code seems like it would log 'The sum of 10 and 32 is 42' since function 'sum(10, 32)' seems to add two numbers -function sum(a, b) { - return; - a + b; -} -console.log(`The sum of 10 and 32 is ${sum(10, 32)}`); +// function sum(a, b) { +// return; +// a + b; +// } + +// console.log(`The sum of 10 and 32 is ${sum(10, 32)}`); // =============> write your explanation here +// When the code was run it logged 'The sum of 10 and 32 is undefined' +// The bug is in line 7 +// 'return' is automatically assigned a semi-colon if it is followed by a line break, making line 8 unreachable + // Finally, correct the code to fix the problem // =============> write your new code here +function sum(a, b){ + return a + b; +} +console.log (`The sum of 10 and 32 is ${sum(10, 32)}`); diff --git a/Sprint-3/2-mandatory-debug/2.js b/Sprint-3/2-mandatory-debug/2.js index 57d3f5dc3..32508566c 100644 --- a/Sprint-3/2-mandatory-debug/2.js +++ b/Sprint-3/2-mandatory-debug/2.js @@ -2,23 +2,39 @@ // Predict the output of the following code: // =============> Write your prediction here +// I predict the output would print the last digits of '42', '105', and '806' because the function name is 'getLastDigit' and it's been called by the input values as arguments -const num = 103; +// const num = 103; -function getLastDigit() { - return num.toString().slice(-1); -} +// function getLastDigit() { +// return num.toString().slice(-1); +// } -console.log(`The last digit of 42 is ${getLastDigit(42)}`); -console.log(`The last digit of 105 is ${getLastDigit(105)}`); -console.log(`The last digit of 806 is ${getLastDigit(806)}`); +// console.log(`The last digit of 42 is ${getLastDigit(42)}`); +// console.log(`The last digit of 105 is ${getLastDigit(105)}`); +// console.log(`The last digit of 806 is ${getLastDigit(806)}`); // Now run the code and compare the output to your prediction // =============> write the output here +// The last digit of 42 is 3 +// The last digit of 105 is 3 +// The last digit of 806 is 3 + // Explain why the output is the way it is // =============> write your explanation here +// The bug is in line 9, where 'getLastDigit()' is declared with no parameters +// Instead the function body reaches out to 'const num = 103' and disregards the values passed because the function does not declare any parameter + // Finally, correct the code to fix the problem // =============> write your new code here +// const num = 103 ---- becomes irrelevant +function getLastDigit(n){ + return n.toString().slice(-1) +} +console.log(`The last digit of 42 is ${getLastDigit(42)}`); +console.log(`The last digit of 105 is ${getLastDigit(105)}`); +console.log(`The last digit of 806 is ${getLastDigit(806)}`); + // This program should tell the user the last digit of each number. // Explain why getLastDigit is not working properly - correct the problem diff --git a/Sprint-3/3-mandatory-implement/1-bmi.js b/Sprint-3/3-mandatory-implement/1-bmi.js index 58b1085f1..2fff81b87 100644 --- a/Sprint-3/3-mandatory-implement/1-bmi.js +++ b/Sprint-3/3-mandatory-implement/1-bmi.js @@ -15,5 +15,17 @@ // It should return a string of their Body Mass Index to 1 decimal place function calculateBMI(weight, height) { + if (!height || height <= 0){ // to catch cases of undefined and null + throw new Error('Height must be greater than 0'); + } + const heightSquared = height ** 2; + return weight / heightSquared; + } +function formatBMI(bmi){ + return bmi.toFixed(1); // rounds 'bmi' to 1 decimal place and converts to a string // return the BMI of someone based off their weight and height -} + } + +const bmiFurMath = calculateBMI(70, 1.73) + 7; +const displayBMI = formatBMI(bmiFurMath); +console.log(`The Body Mass Index is: ${displayBMI}`); diff --git a/Sprint-3/3-mandatory-implement/2-cases.js b/Sprint-3/3-mandatory-implement/2-cases.js index 5b0ef77ad..9be764f82 100644 --- a/Sprint-3/3-mandatory-implement/2-cases.js +++ b/Sprint-3/3-mandatory-implement/2-cases.js @@ -14,3 +14,11 @@ // You will need to come up with an appropriate name for the function // Use the MDN string documentation to help you find a solution // This might help https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase + +function toUpperSnakeCase(input){ + if (typeof input !== "string"){ + throw new Error("Input must be a string") + } + return input.trim().replaceAll(/\s+/g, "_").toUpperCase(); +} +console.log (toUpperSnakeCase("lord of the rings season 1 episode 1")); diff --git a/Sprint-3/3-mandatory-implement/3-to-pounds.js b/Sprint-3/3-mandatory-implement/3-to-pounds.js index 10754da73..80681a68b 100644 --- a/Sprint-3/3-mandatory-implement/3-to-pounds.js +++ b/Sprint-3/3-mandatory-implement/3-to-pounds.js @@ -4,3 +4,24 @@ // You will need to declare a function called toPounds with an appropriately named parameter. // You should call this function a number of times to check it works for different inputs + +function toPounds(penceString){ + let cleanNum = penceString.trim(); + if (cleanNum.toLowerCase().endsWith("p")){ + cleanNum = cleanNum.substring(0, cleanNum.length - 1); + } + const paddedPenceNumberString = cleanNum.padStart(3, "0"); + const pounds = paddedPenceNumberString.substring(0, paddedPenceNumberString.length - 2); + const pence = paddedPenceNumberString.substring(paddedPenceNumberString.length - 2).padEnd(2, "0"); + + return `£${pounds}.${pence}`; +} + +console.log(toPounds("77770p")); +console.log(toPounds("2570p")); +console.log(toPounds("399p")); +console.log(toPounds("77p")); +console.log(toPounds("0p")); +console.log(toPounds(" 50p ")); +console.log(toPounds("777")); +console.log(toPounds("")); diff --git a/Sprint-3/4-mandatory-interpret/time-format.js b/Sprint-3/4-mandatory-interpret/time-format.js index c0dd9c9a5..593439cb3 100644 --- a/Sprint-3/4-mandatory-interpret/time-format.js +++ b/Sprint-3/4-mandatory-interpret/time-format.js @@ -1,8 +1,24 @@ +// let padCalls = 0; +// let padCallCount = 0; +// let firstNum; +// let lastNum; +let lastReturn; + function pad(num) { + // padCalls++; + // padCallCount++; + // if (padCallCount === 1){ + // firstNum = num; + // } + // lastNum = num; let numString = num.toString(); while (numString.length < 2) { numString = "0" + numString; } + // if (padCallCount === 1){ + // firstReturn = numString; + // } + lastReturn = numString; return numString; } @@ -14,6 +30,13 @@ function formatTimeDisplay(seconds) { return `${pad(totalHours)}:${pad(remainingMinutes)}:${pad(remainingSeconds)}`; } +// for (const s of [8784, 77, 77777]){ +// padCalls = 0; +// const result = formatTimeDisplay(s); +// console.log(`formatTimeDisplay(${s})==> ${result}| pad called ${padCalls} times `); +// } +formatTimeDisplay(61); +console.log("The return value of pad when it is called for the last time is:", lastReturn); // You will need to play computer with this example - use the Python Visualiser https://pythontutor.com/visualize.html#mode=edit // to help you answer these questions @@ -22,17 +45,28 @@ function formatTimeDisplay(seconds) { // a) When formatTimeDisplay is called how many times will pad be called? // =============> write your answer here +// The 'pad' function is called "three times" within the 'formatTimeDisplay' function +// The count will always be three because the 'return' statement contains three 'pad()' calls // Call formatTimeDisplay with an input of 61, now answer the following: // b) What is the value assigned to num when pad is called for the first time? // =============> write your answer here +// for the first call to pad, num is assigned the value of 'totalHours', which is '0' +// Since the template literal is evaluated from left to right, calling 'formatTimeDisplay(61)', the calls occur in this order: +// totalHours, remainingMinutes, and remainingSeconds // c) What is the return value of pad when it is called for the first time? // =============> write your answer here +// For the first call to 'pad', 'num' is '0' +// The pad function will return '00' because it pads single-digit numbers with a leading zero // d) What is the value assigned to num when pad is called for the last time in this program? Explain your answer // =============> write your answer here +// The last call is 'pad(remainingSeconds)' which is '61 % 60' +// since 61 divided by 60 leaves a remainder of 1, it means the value '1' is assigned to 'num' in the last call of pad // e) What is the return value of pad when it is called for the last time in this program? Explain your answer // =============> write your answer here +// The return value of pad when called for the last time is '01' +// since '1.toString()' is '1', the 'while' loop runs once and adds a '0' to the front, giving '01' diff --git a/Sprint-3/5-stretch-extend/format-time.js b/Sprint-3/5-stretch-extend/format-time.js index 32a32e66b..62ba5f547 100644 --- a/Sprint-3/5-stretch-extend/format-time.js +++ b/Sprint-3/5-stretch-extend/format-time.js @@ -2,7 +2,7 @@ // Make sure to do the prep before you do the coursework // Your task is to write tests for as many different groups of input data or edge cases as you can, and fix any bugs you find. -function formatAs12HourClock(time) { +/*function formatAs12HourClock(time) { const hours = Number(time.slice(0, 2)); if (hours > 12) { return `${hours - 12}:00 pm`; @@ -22,4 +22,74 @@ const targetOutput2 = "11:00 pm"; console.assert( currentOutput2 === targetOutput2, `current output: ${currentOutput2}, target output: ${targetOutput2}` -); +);*/ + +function formatAs12HourClock(time){ + if (typeof time != "string"){ + throw new Error (`Expected a string in "HH:MM" format, got ${typeof time}`); + } + const match = /^([01]\d|2[0-3]):([0-5]\d)$/.exec(time); + if(!match){ + throw new RangeError(`Invalid time "${time}": expected 24-hour "HH:MM" (00:00 to 23:59)`); + } + + const hours = Number(match[1]); + const minutes = match[2]; + const period = hours < 12 ? "am" : "pm"; + const hours12 = hours % 12 === 0 ? 12 : hours % 12; + + return `${String(hours12).padStart(2, "0")}:${minutes} ${period}`; +} +console.log(formatAs12HourClock("23:00")) + +function check(input, targetOutput){ + const currentOutput = formatAs12HourClock(input); + console.assert(currentOutput === targetOutput, `input: ${input}. current output: ${currentOutput}, target output: ${targetOutput}`); +} + +function checkThrows(input){ + let threw = false; + try{ + formatAs12HourClock(input); + } + catch(error){ + threw = true; + } + console.assert(threw, `input: ${String(input)} should have thrown an error`); +} + +// original tests +check("08:00", "08:00am"); +check("23:00", "11:00pm"); + +// midnight hours +check("00:00", "12:00am"); +check("00:30", "12:30am"); +check("00:59", "12:59am"); + +// mornings +check("01:00", "01:00am"); +check("09:59", "09:59am"); +check("10:05", "10:05am"); +check("11:59", "11:59am"); + +// noon +check("12:00", "12:00pm"); +check("12:01", "12:01pm"); +check("12:30", "12:30pm"); +check("12:59", "12:59pm"); + +// mid-day and evenings +check("13:00", "01:00pm"); +check("17:45", "05:45pm"); +check("22:10", "10:10pm"); +check("23:45", "11:45pm"); +check("23:59", "11:59pm"); + +// invalid times +checkThrows("24:00", "25:00", "12:60", "99:99", undefined, null, 800, ["08:00"]); + +// bad formatting +checkThrows("", "abc", "8:00", "0800", "08:00:00", " 08:00", "08:00 am"); + +console.log("Complete! No errors."); \ No newline at end of file