From ccb28bbb1c83585813ebbadd590aaf939ea8c8cd Mon Sep 17 00:00:00 2001 From: Salem Ba-rabuod Date: Sat, 28 Mar 2026 12:35:41 +0100 Subject: [PATCH 1/3] solved the assignment --- task-1/Time.js | 66 +++++++++++++++++++++++++++++- task-1/package-lock.json | 30 -------------- task-2/index.js | 88 +++++++++++++++++++++++++++++++++++++++- task-2/package-lock.json | 73 +++++++++++++++++++++++++++++++++ task-2/package.json | 10 ++++- 5 files changed, 232 insertions(+), 35 deletions(-) create mode 100644 task-2/package-lock.json diff --git a/task-1/Time.js b/task-1/Time.js index 97ca7e2..b6c1bb5 100644 --- a/task-1/Time.js +++ b/task-1/Time.js @@ -1,3 +1,65 @@ export class Time { - // Your code here -} \ No newline at end of file + #secondsFromMidnight = 0; + + constructor(hours, minutes, seconds) { + // Avoid Magic Numbers - week 11 - clean code + const SECONDS_IN_HOUR = 3600; + const SECONDS_IN_MINUTE = 60; + const totalSeconds = + hours * SECONDS_IN_HOUR + minutes * SECONDS_IN_MINUTE + seconds; + + if (totalSeconds < 0 || totalSeconds >= 86400) { + throw new Error('Invalid time'); + } + + this.#secondsFromMidnight = totalSeconds; + } + + getHours() { + return Math.floor(this.#secondsFromMidnight / 3600); + } + + getMinutes() { + return Math.floor((this.#secondsFromMidnight % 3600) / 60); + } + + getSeconds() { + return this.#secondsFromMidnight % 60; + } + + addSeconds(seconds) { + const SECONDS_IN_DAY = 86400; // to avoid Magic Numbers + this.#secondsFromMidnight = + (this.#secondsFromMidnight + seconds) % SECONDS_IN_DAY; + if (this.#secondsFromMidnight < 0) { + this.#secondsFromMidnight += SECONDS_IN_DAY; + } + } + + addMinutes(minutes) { + this.addSeconds(minutes * 60); + } + + addHours(hours) { + this.addSeconds(hours * 3600); + } + + toString() { + const HH = String(this.getHours()).padStart(2, '0'); + const mm = String(this.getMinutes()).padStart(2, '0'); + const ss = String(this.getSeconds()).padStart(2, '0'); + return `${HH}:${mm}:${ss}`; + } +} + +const myTime = new Time(12, 35, 0); +console.log(myTime.toString()); // 12:35:00 +myTime.getHours(); // 12 +myTime.getMinutes(); // 35 +myTime.getSeconds(); // 0 + +myTime.addMinutes(25); +console.log(myTime.toString()); // 13:00:00 + +myTime.addHours(12); +console.log(myTime.toString()); // 01:00:00 diff --git a/task-1/package-lock.json b/task-1/package-lock.json index aba2728..26b46fa 100644 --- a/task-1/package-lock.json +++ b/task-1/package-lock.json @@ -161,9 +161,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -180,9 +177,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -199,9 +193,6 @@ "cpu": [ "ppc64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -218,9 +209,6 @@ "cpu": [ "s390x" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -237,9 +225,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -256,9 +241,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -706,9 +688,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -729,9 +708,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -752,9 +728,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -775,9 +748,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ diff --git a/task-2/index.js b/task-2/index.js index 02acffa..f5b23e9 100644 --- a/task-2/index.js +++ b/task-2/index.js @@ -1 +1,87 @@ -// Write your code here. You may create as many files as you like. +import dotenv from 'dotenv'; +import OpenAI from 'openai'; +import readlineSync from 'readline-sync'; +import chalk from 'chalk'; + +dotenv.config(); + +const apiConnection = new OpenAI({ + baseURL: 'https://models.github.io/inference/', + apiKey: process.env.OPENAI_API_KEY, +}); + +async function startQuiz() { + console.log( + chalk.blue.bold('\n=== Welcome to the AI powered quiz game ===\n'), + ); + console.log(chalk.yellow('Generating questions from the AI...')); + + const response = await apiConnection.chat.completions.create({ + model: 'openai/gpt-4o-mini', + messages: [ + { + role: 'user', + content: ` +Generate exactly 10 multiple-choice quiz questions about world geography. + +Rules: +- Each question must have exactly 4 answer options. +- Only one answer is correct. +- Make the questions clear and suitable for a CLI quiz game. +- Return ONLY valid JSON. +- Do not include markdown code fences. +- Do not include any explanation before or after the JSON. + +Use this exact JSON format: +[ + { + "question": "Which country has the city of Kyoto?", + "options": ["China", "Japan", "South Korea", "Thailand"], + "correctAnswer": 2 + } +] + +Important: +- "correctAnswer" must be a number from 1 to 4. +- Return exactly 10 question objects. +`, + }, + ], + }); + + const aiResponseText = response.choices[0].message.content; + const questions = JSON.parse(aiResponseText); + + let score = 0; + + for (let i = 0; i < questions.length; i++) { + const currentQ = questions[i]; + + console.log(chalk.cyan(`\nQuestion ${i + 1}: ${currentQ.question}`)); + + console.log(`1. ${currentQ.options[0]}`); + console.log(`2. ${currentQ.options[1]}`); + console.log(`3. ${currentQ.options[2]}`); + console.log(`4. ${currentQ.options[3]}`); + + const userChoice = readlineSync.question('\n write your answer (1-4): '); + + if (parseInt(userChoice) === currentQ.answer) { + console.log(chalk.green('Your answer is correct! +1 point')); + score++; + } else { + console.log( + chalk.red(`✖ Wrong! The correct answer is: ${currentQ.answer}`), + ); + } + } + + console.log(chalk.magenta.bold('\n============================')); + console.log( + chalk.white(`Quiz finished! Your score is: `) + + chalk.green.bold(`${score}/10`), + ); + console.log(chalk.magenta.bold('============================\n')); +} + +startQuiz(); diff --git a/task-2/package-lock.json b/task-2/package-lock.json new file mode 100644 index 0000000..2dde489 --- /dev/null +++ b/task-2/package-lock.json @@ -0,0 +1,73 @@ +{ + "name": "task-2", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "task-2", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "chalk": "^5.6.2", + "dotenv": "^17.3.1", + "openai": "^6.33.0", + "readline-sync": "^1.4.10" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", + "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/openai": { + "version": "6.33.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-6.33.0.tgz", + "integrity": "sha512-xAYN1W3YsDXJWA5F277135YfkEk6H7D3D6vWwRhJ3OEkzRgcyK8z/P5P9Gyi/wB4N8kK9kM5ZjprfvyHagKmpw==", + "license": "Apache-2.0", + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + } + } +} diff --git a/task-2/package.json b/task-2/package.json index a992f45..4f1cf4b 100644 --- a/task-2/package.json +++ b/task-2/package.json @@ -9,5 +9,11 @@ "keywords": [], "author": "", "license": "ISC", - "type": "module" -} \ No newline at end of file + "type": "module", + "dependencies": { + "chalk": "^5.6.2", + "dotenv": "^17.3.1", + "openai": "^6.33.0", + "readline-sync": "^1.4.10" + } +} From c3e3405a8d8169b061daa450077b0652a60a6591 Mon Sep 17 00:00:00 2001 From: Salem Ba-rabuod Date: Sat, 28 Mar 2026 21:37:34 +0100 Subject: [PATCH 2/3] fixed task 2 --- task-2/index.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/task-2/index.js b/task-2/index.js index f5b23e9..76ebe24 100644 --- a/task-2/index.js +++ b/task-2/index.js @@ -6,8 +6,8 @@ import chalk from 'chalk'; dotenv.config(); const apiConnection = new OpenAI({ - baseURL: 'https://models.github.io/inference/', - apiKey: process.env.OPENAI_API_KEY, + baseURL: 'https://models.inference.ai.azure.com', + apiKey: process.env.AZURE_OPENAI_KEY, }); async function startQuiz() { @@ -17,7 +17,7 @@ async function startQuiz() { console.log(chalk.yellow('Generating questions from the AI...')); const response = await apiConnection.chat.completions.create({ - model: 'openai/gpt-4o-mini', + model: 'gpt-4o-mini', messages: [ { role: 'user', @@ -66,12 +66,12 @@ Important: const userChoice = readlineSync.question('\n write your answer (1-4): '); - if (parseInt(userChoice) === currentQ.answer) { + if (parseInt(userChoice) === currentQ.correctAnswer) { console.log(chalk.green('Your answer is correct! +1 point')); score++; } else { console.log( - chalk.red(`✖ Wrong! The correct answer is: ${currentQ.answer}`), + chalk.red(`✖ Wrong! The correct answer is: ${currentQ.correctAnswer}`), ); } } From 5628791fbbebeebaac8a6cced1bc51d887b57124 Mon Sep 17 00:00:00 2001 From: Salem Ba-rabuod Date: Sun, 29 Mar 2026 13:05:54 +0200 Subject: [PATCH 3/3] applied feadback --- task-1/Time.js | 32 ++++++++++---------------------- task-1/index.js | 13 +++++++++++-- task-2/index.js | 6 +++--- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/task-1/Time.js b/task-1/Time.js index b6c1bb5..f1dd560 100644 --- a/task-1/Time.js +++ b/task-1/Time.js @@ -1,14 +1,15 @@ +const SECONDS_IN_HOUR = 3600; +const SECONDS_IN_MINUTE = 60; +const SECONDS_IN_DAY = 86400; + export class Time { #secondsFromMidnight = 0; constructor(hours, minutes, seconds) { - // Avoid Magic Numbers - week 11 - clean code - const SECONDS_IN_HOUR = 3600; - const SECONDS_IN_MINUTE = 60; const totalSeconds = hours * SECONDS_IN_HOUR + minutes * SECONDS_IN_MINUTE + seconds; - if (totalSeconds < 0 || totalSeconds >= 86400) { + if (totalSeconds < 0 || totalSeconds >= SECONDS_IN_DAY) { throw new Error('Invalid time'); } @@ -16,19 +17,18 @@ export class Time { } getHours() { - return Math.floor(this.#secondsFromMidnight / 3600); + return Math.floor(this.#secondsFromMidnight / SECONDS_IN_HOUR); } getMinutes() { - return Math.floor((this.#secondsFromMidnight % 3600) / 60); + return Math.floor((this.#secondsFromMidnight % SECONDS_IN_HOUR) / SECONDS_IN_MINUTE); } getSeconds() { - return this.#secondsFromMidnight % 60; + return this.#secondsFromMidnight % SECONDS_IN_MINUTE; } addSeconds(seconds) { - const SECONDS_IN_DAY = 86400; // to avoid Magic Numbers this.#secondsFromMidnight = (this.#secondsFromMidnight + seconds) % SECONDS_IN_DAY; if (this.#secondsFromMidnight < 0) { @@ -37,11 +37,11 @@ export class Time { } addMinutes(minutes) { - this.addSeconds(minutes * 60); + this.addSeconds(minutes * SECONDS_IN_MINUTE); } addHours(hours) { - this.addSeconds(hours * 3600); + this.addSeconds(hours * SECONDS_IN_HOUR); } toString() { @@ -51,15 +51,3 @@ export class Time { return `${HH}:${mm}:${ss}`; } } - -const myTime = new Time(12, 35, 0); -console.log(myTime.toString()); // 12:35:00 -myTime.getHours(); // 12 -myTime.getMinutes(); // 35 -myTime.getSeconds(); // 0 - -myTime.addMinutes(25); -console.log(myTime.toString()); // 13:00:00 - -myTime.addHours(12); -console.log(myTime.toString()); // 01:00:00 diff --git a/task-1/index.js b/task-1/index.js index cfa7c93..af59f7e 100644 --- a/task-1/index.js +++ b/task-1/index.js @@ -1,4 +1,13 @@ import { Time } from './Time.js'; -const time = new Time(13, 37, 0); -console.log(time.toString()); // Output: "13:37:00" +const myTime = new Time(12, 35, 0); +console.log(myTime.toString()); // 12:35:00 +console.log(myTime.getHours()); // 12 +console.log(myTime.getMinutes()); // 35 +console.log(myTime.getSeconds()); // 0 + +myTime.addMinutes(25); +console.log(myTime.toString()); // 13:00:00 + +myTime.addHours(12); +console.log(myTime.toString()); // 01:00:00 diff --git a/task-2/index.js b/task-2/index.js index 76ebe24..403fcac 100644 --- a/task-2/index.js +++ b/task-2/index.js @@ -6,8 +6,8 @@ import chalk from 'chalk'; dotenv.config(); const apiConnection = new OpenAI({ - baseURL: 'https://models.inference.ai.azure.com', - apiKey: process.env.AZURE_OPENAI_KEY, + baseURL: 'https://models.github.ai/inference/', + apiKey: process.env.OPENAI_API_KEY, }); async function startQuiz() { @@ -17,7 +17,7 @@ async function startQuiz() { console.log(chalk.yellow('Generating questions from the AI...')); const response = await apiConnection.chat.completions.create({ - model: 'gpt-4o-mini', + model: 'openai/gpt-4o-mini', messages: [ { role: 'user',