new class js -advanced

This commit is contained in:
Philippe Torrel
2026-06-29 11:35:03 +02:00
parent ee8a87bf2a
commit 31c13250b0
104 changed files with 2632 additions and 138 deletions

View File

@@ -0,0 +1,7 @@
'use strict';
const foo = ({ a = 1, b = 2 }) => `a: ${a}, b: ${b}`;
console.log(foo({ a: 7 })); // => a: 7, b: 2
console.log(foo({ b: 7 })); // => a: 1, b: 7
console.log(foo({ a: 7, b: 8 })); // => a: 7, b: 8

View File

@@ -0,0 +1,15 @@
'use strict';
const productsFromCSV = (csv) =>
csv
.split('\n')
.slice(1)
.map((str) => str.trim());
const productsCSV = `name, category, price
Klingon Letter Opener, Office Warfare, 19.99
Backpack of Holding, Travel, 29.99
Tardis Alarmclock, Merchandise, 15.99`;
const products = productsFromCSV(productsCSV);
console.log(products);

View File

@@ -0,0 +1,13 @@
'use strict';
const productFromCSV = (productString) => {
const [name, category, price] = productString.split(', ');
return {
name: name,
category: category,
price: price,
};
};
const product = productFromCSV('Backpack of Holding, Travel, 29.99');
console.dir(product);

View File

@@ -0,0 +1,18 @@
'use strict';
const productFromCSV = (productString) => {
const productArray = productString.split(', ');
const name = productArray[0];
const category = productArray[1];
const price = productArray[2];
return {
name: name,
category: category,
price: price,
};
};
const product = productFromCSV('Backpack of Holding, Travel, 29.99');
console.dir(product);

View File

@@ -0,0 +1,25 @@
'use strict';
const trim = (s) => s.match(/\W*(.+)\W*/)[1];
const productFromArray = ([name, category, price]) => ({
name,
category,
price,
});
const productsFromCSV = (csv) =>
csv
.split('\n')
.slice(1)
.map(trim)
.map((s) => s.split(', '))
.map(productFromArray);
const productsCSV = `name, category, price
Klingon Letter Opener, Office Warfare, 19.99
Backpack of Holding, Travel, 29.99
Tardis Alarmclock, Merchandise, 15.99`;
const products = productsFromCSV(productsCSV);
console.log(products);

View File

@@ -0,0 +1,23 @@
'use strict';
const trim = (s) => s.match(/\W*(.+)\W*/)[1];
const productFromCSV = (productString) => {
const [name, category, price] = productString.split(', ');
return {
name,
category,
price,
};
};
const productsFromCSV = (csv) =>
csv.split('\n').slice(1).map(trim).map(productFromCSV);
const productsCSV = `name, category, price
Klingon Letter Opener, Office Warfare, 19.99
Backpack of Holding, Travel, 29.99
Tardis Alarmclock, Merchandise, 15.99`;
const products = productsFromCSV(productsCSV);
console.log(products);

View File

@@ -0,0 +1,12 @@
'use strict';
const formatProduct = ({ name, price }) =>
`* ${name} - buy now for only $${price}`;
const product = {
name: 'Klingon Letter Opener',
category: 'Office Warfare',
price: '19.99',
};
console.log(formatProduct(product));

View File

@@ -0,0 +1,8 @@
'use strict';
const distance = (
{ x: xOrigin, y: yOrigin },
{ x: xDestination, y: yDestination }
) => Math.sqrt((yDestination - yOrigin) ** 2 + (xDestination - xOrigin) ** 2);
console.log(distance({ x: 1, y: 1 }, { x: 5, y: 1 }));

View File

@@ -0,0 +1,6 @@
'use strict';
const logTransformedName = ({ firstName, lastName }) =>
console.log(`${lastName}, ${firstName.charAt(0)}.`);
logTransformedName({ firstName: 'Ladislaus', lastName: 'Jones' });

View File

@@ -0,0 +1,13 @@
function factorial(n) {
// Base case: if n is 0, return 1
if (n === 0) {
return 1;
}
// Recursive case: n * factorial of (n - 1)
return n * factorial(n - 1);
}
// Test cases
console.log(factorial(5)); // => 120
console.log(factorial(3)); // => 6
console.log(factorial(0)); // => 1

View File

@@ -0,0 +1,23 @@
function fibonacci(n) {
// Base cases
if (n === 0) {
return 0;
}
if (n === 1) {
return 1;
}
// Recursive case
return fibonacci(n - 1) + fibonacci(n - 2);
}
// Test cases
console.log(fibonacci(0)); // => 0
console.log(fibonacci(1)); // => 1
console.log(fibonacci(2)); // => 1
console.log(fibonacci(3)); // => 2
console.log(fibonacci(4)); // => 3
console.log(fibonacci(5)); // => 5
console.log(fibonacci(6)); // => 8
console.log(fibonacci(10)); // => 55

View File

@@ -0,0 +1,17 @@
function fibonacciMemo(n, memo = {}) {
// Base Cases
if (n === 0) return 0;
if (n === 1) return 1;
// Test if value already calculated
if (memo[n]) {
return memo[n];
}
// Recursive Case with Memoization
memo[n] = fibonacciMemo(n - 1, memo) + fibonacciMemo(n - 2, memo);
return memo[n];
}
// Test Cases
console.log(fibonacciMemo(50)); // => 12586269025

View File

@@ -0,0 +1,13 @@
function sumArray(arr) {
// Base case: when the array is empty, return 0
if (arr.length === 0) {
return 0;
}
// Recursive case: add the first element to the sum of the rest of the array
return arr[0] + sumArray(arr.slice(1));
}
// Test cases
console.log(sumArray([1, 2, 3, 4, 5])); // => 15
console.log(sumArray([10, -2, 33, 47])); // => 88
console.log(sumArray([])); // => 0

View File

@@ -0,0 +1,13 @@
function sumArrayIndex(arr, index = 0) {
// Base case: when index is greater than or equal to the length of the array return 0
if (index >= arr.length) {
return 0;
}
// Recursive case: add the current element to the sum of the rest of the array
return arr[index] + sumArrayIndex(arr, index + 1);
}
// Test cases
console.log(sumArrayIndex([1, 2, 3, 4, 5])); // => 15
console.log(sumArrayIndex([10, -2, 33, 47])); // => 88
console.log(sumArrayIndex([])); // => 0

View File

@@ -0,0 +1,19 @@
function combinations(n, k) {
// Base Cases
if (k === 0 || k === n) {
return 1;
}
// If k is greater than n, there are no combinations
if (k > n) {
return 0;
}
// Recursive Cases
return combinations(n - 1, k - 1) + combinations(n - 1, k);
}
// Test Cases
console.log(combinations(5, 2)); // => 10
console.log(combinations(6, 3)); // => 20
console.log(combinations(4, 0)); // => 1
console.log(combinations(4, 4)); // => 1
console.log(combinations(5, 6)); // => 0

View File

@@ -0,0 +1,27 @@
function findDeepestLevel(arr, currentLevel = 1) {
// Base case: when the array is empty, return the current level
if (arr.length === 0) {
return currentLevel;
}
let maxLevel = currentLevel;
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
// Recursive case: if the element is an array, call the function recursively
const depth = findDeepestLevel(arr[i], currentLevel + 1);
if (depth > maxLevel) {
maxLevel = depth;
}
}
}
return maxLevel;
}
// Test cases
console.log(findDeepestLevel([1, [2, [3, [4]], 5]])); // => 4
console.log(findDeepestLevel([1, 2, 3, 4, 5])); // => 1
console.log(findDeepestLevel([])); // => 1
console.log(findDeepestLevel([1, [2], [3, [4, [5]]]])); // => 4
console.log(findDeepestLevel([1, [2, [3]], [4, [5, [6]]]])); // => 4

View File

@@ -0,0 +1,19 @@
function findMax(arr) {
// Base case: empty array
if (arr.length === 0) {
return null;
}
// Base case: array with one element
if (arr.length === 1) {
return arr[0];
}
// Recursive case: return the maximum of the first element and the maximum of the rest of the array
const subMax = findMax(arr.slice(1));
return arr[0] > subMax ? arr[0] : subMax;
}
// Test cases
console.log(findMax([1, 5, 3, 9, 2])); // => 9
console.log(findMax([-10, -20, -3, -4])); // => -3
console.log(findMax([42])); // => 42
console.log(findMax([])); // => null

View File

@@ -0,0 +1,14 @@
function reverseString(str) {
// Base case: if the string has only one character, return it
if (str.length <= 1) {
return str;
}
// Recursive case: return the last character of the string and call the function with the rest of the string
return reverseString(str.slice(1)) + str[0];
}
// Test cases
console.log(reverseString('hello')); // => "olleh"
console.log(reverseString('Recursion')); // => "noisruceR"
console.log(reverseString('')); // => ""
console.log(reverseString('A')); // => "A"

View File

@@ -0,0 +1,26 @@
function sumNestedArray(arr) {
// Base case: when the array is empty, return 0
if (arr.length === 0) {
return 0;
}
let sum = 0;
for (let element of arr) {
if (Array.isArray(element)) {
// Recursive case: if the element is an array, sum its elements
sum += sumNestedArray(element);
} else if (typeof element === 'number') {
sum += element;
}
}
return sum;
}
// Test cases
console.log(sumNestedArray([1, [2, [3, 4], 5], 6])); // => 21
console.log(sumNestedArray([[[[1]]], 2, [3, [4, [5]]]])); // => 15
console.log(sumNestedArray([])); // => 0
console.log(sumNestedArray([10, [20, [30, [40]]]])); // => 100
console.log(sumNestedArray([1, 'a', [2, 'b', [3, 4]], 5])); // => 15 (ignores non-numbers)

View File

@@ -0,0 +1,12 @@
function sumRecursive(n) {
if (n === 0) {
return 0;
}
return n + sumRecursive(n - 1);
}
// Test Cases
console.log(sumRecursive(5)); // => 15 (5 + 4 + 3 + 2 + 1)
console.log(sumRecursive(10)); // => 55 (10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1)
console.log(sumRecursive(0)); // => 0

View File

@@ -0,0 +1,15 @@
const tryWork = (resolve, reject) => {
const ergebnis = 21 * 2;
if (Math.random() < 0.5) {
resolve(ergebnis);
} else {
reject('nope');
}
};
const p4 = new Promise(tryWork);
p4.then(
(result) => console.log('OK: ' + result),
(reason) => console.log('KO: ' + reason)
);

View File

@@ -0,0 +1,17 @@
const tryWork = (resolve, reject) => {
const ergebnis = 21 * 2;
if (Math.random() < 0.5) {
resolve(ergebnis);
} else {
reject(new Error('nope'));
}
};
new Promise(tryWork)
.then(() => new Promise(tryWork))
.then(() => new Promise(tryWork))
.then((result) => console.log('OK: ' + result))
.catch((err) => {
console.log('KO: ' + err.message);
console.log(err.stack);
});

View File

@@ -0,0 +1,12 @@
const wait = () => new Promise((resolve) => setTimeout(resolve, 1000));
wait()
.then(() => {
console.log('The');
return wait();
})
.then(() => {
console.log('pyramid');
return wait();
});
// etc...

View File

@@ -0,0 +1,26 @@
// print a phrase, a word at a time:
// the pyramid of doom appears
setTimeout(() => {
console.log('The');
setTimeout(() => {
console.log('pyramid');
setTimeout(() => {
console.log('of');
setTimeout(() => {
console.log('doom');
setTimeout(() => {
console.log('keeps');
setTimeout(() => {
console.log('growing.');
}, 1000);
}, 1000);
}, 1000);
}, 1000);
}, 1000);
}, 1000);

View File

@@ -0,0 +1,17 @@
// print a phrase, a word at a time:
// use promises to avoid the pyramid of doom
const printDelay = (time, str) =>
new Promise((resolve) =>
setTimeout(() => {
console.log(str);
resolve();
}, time)
);
printDelay(1000, 'The')
.then(() => printDelay(1000, 'pyramid'))
.then(() => printDelay(1000, 'of'))
.then(() => printDelay(1000, 'doom'))
.then(() => printDelay(1000, 'is'))
.then(() => printDelay(1000, 'defeated.'));

View File

@@ -0,0 +1,9 @@
const fs = require('fs');
fs.readFile('data/file.txt', 'UTF8', (error, content) => {
if (error) {
console.log('could not read file');
} else {
console.log(content);
}
});

View File

@@ -0,0 +1,17 @@
const fs = require('fs');
const getFileContent = (path, encoding = 'utf-8') => {
return new Promise((resolve, reject) => {
fs.readFile(path, encoding, (error, data) => {
if (error) {
reject(error);
} else {
resolve(data);
}
});
});
};
getFileContent('data/file.txt')
.then((data) => console.log(data))
.catch((err) => console.error(`Something went wrong: ${err}`));

View File

@@ -0,0 +1,9 @@
const fs = require('fs');
const getFileContent = (path, encoding = 'utf-8') => {
return fs.promises.readFile(path, encoding);
};
getFileContent('data/file.txt')
.then((data) => console.log(data))
.catch((err) => console.error(`Something went wrong: ${err}`));

View File

@@ -0,0 +1,8 @@
const fs = require('fs');
const util = require('util');
const getFileContent = util.promisify(fs.readFile);
getFileContent('data/file.txt', 'UTF8')
.then((data) => console.log(data))
.catch((err) => console.error(`Something went wrong: ${err}`));

View File

@@ -0,0 +1,29 @@
const dns = require('dns');
const IP_V = 4; // we use IP protocol version 4
const URL = 'de.webmasters-europe.org';
// Solution 1: Detailed variant with Promise object
const getIp = (url, ip) => {
return new Promise((resolve, reject) => {
dns.lookup(url, ip, (error, data) => {
if (error) {
reject(error);
} else {
resolve({ address: data, family: ip });
}
});
});
};
getIp(URL, IP_V)
.then((data) => console.log(`IP adress = ${data.address}`))
.catch((err) => console.error(err));
// dns.lookup(URL, IP_V, (error, address) => {
// if (error) {
// console.log('error: could not lookup host');
// } else {
// console.log('IP address = ' + address);
// }
// });

View File

@@ -0,0 +1,21 @@
const dns = require('dns');
const IP_V = 4; // we use IP protocol version 4
const URL = 'de.webmasters-europe.org';
// Solution 2: Variant with promises subobject
const getIpPromises = (url, ip) => {
return dns.promises.lookup(url, ip);
};
getIpPromises(URL, IP_V)
.then((data) => console.log(`IP adress = ${data.address}`))
.catch((err) => console.error(err));
// dns.lookup(URL, IP_V, (error, address) => {
// if (error) {
// console.log('error: could not lookup host');
// } else {
// console.log('IP address = ' + address);
// }
// });

View File

@@ -0,0 +1,20 @@
const dns = require('dns');
const util = require('util');
const IP_V = 4; // we use IP protocol version 4
const URL = 'de.webmasters-europe.org';
// Solution 3: Variant with util module
const getIpPromisify = util.promisify(dns.lookup);
getIpPromisify(URL, IP_V)
.then((data) => console.log(`IP adress = ${data.address}`))
.catch((err) => console.error(err));
// dns.lookup(URL, IP_V, (error, address) => {
// if (error) {
// console.log('error: could not lookup host');
// } else {
// console.log('IP address = ' + address);
// }
// });

View File

@@ -0,0 +1 @@
This is the contents of file 01.

View File

@@ -0,0 +1 @@
This is the contents of file 02.

View File

@@ -0,0 +1 @@
This is the contents of file 03.

View File

@@ -0,0 +1 @@
This is the contents of file 04.

View File

@@ -0,0 +1 @@
This is the contents of file 05.

View File

@@ -0,0 +1 @@
This is the contents of file 06.

View File

@@ -0,0 +1,30 @@
const fs = require('fs');
const getFileContent = (name, encoding = 'UTF8') => {
return new Promise((resolve, reject) => {
fs.readFile(name, encoding, (error, content) => {
if (error) {
reject(`could not read file ${name}`);
} else {
resolve(content);
}
});
});
};
Promise.all([
getFileContent('data/file_1.txt'),
getFileContent('data/file_2.txt'),
getFileContent('data/file_3.txt'),
getFileContent('data/file_4.txt'),
getFileContent('data/file_5.txt'),
getFileContent('data/file_6.txt'),
])
.then((contents) =>
contents.forEach((content) => {
console.log(content);
})
)
.catch((error) => {
console.log(error);
});

View File

@@ -0,0 +1,18 @@
// print a phrase, a word at a time:
// workaround to avoid the pyramid of doom
const words = 'The pyramid of doom keeps growing.';
const printWords = (str = '', idx = 0) => {
const words = str.split(/\s/);
// Guard
if (idx >= words.length) return '';
console.log(words[idx]);
setTimeout(() => {
printWords(str, ++idx);
}, 1000);
};
printWords(words);

View File

@@ -0,0 +1,50 @@
'use strict';
const board2string = (board) => board.map((row) => row.join('')).join('\n');
const execMove = (board, move) => {
const originX = fieldToXPosition(originField(move));
const originY = fieldToYPosition(originField(move));
const targetX = fieldToXPosition(targetField(move));
const targetY = fieldToYPosition(targetField(move));
board[targetY][targetX] = board[originY][originX];
board[originY][originX] = emptyBoard()[originY][originX];
return board;
};
const boardInStartPosition = () => [
['♜', '♞', '♝', '♛', '♚', '♝', '♞', '♜'],
['♟', '♟', '♟', '♟', '♟', '♟', '♟', '♟'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['♙', '♙', '♙', '♙', '♙', '♙', '♙', '♙'],
['♖', '♘', '♗', '♕', '♔', '♗', '♘', '♖'],
];
const emptyBoard = () => [
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
];
const originField = (move) => move.substr(0, 2);
const targetField = (move) => move.substr(2);
const fieldToXPosition = (field) => letterToChessIndex(field.charAt(0));
const fieldToYPosition = (field) => numberToChessIndex(field.charAt(1));
const letterToChessIndex = (letter) => 'abcdefgh'.indexOf(letter);
const numberToChessIndex = (num) => 8 - num;
console.log(board2string(boardInStartPosition()));
console.log('\n');
console.log(board2string(execMove(boardInStartPosition(), 'e2e4')));

View File

@@ -0,0 +1,56 @@
'use strict';
const board2string = (board) => board.map((row) => row.join('')).join('\n');
const execMoves = (moves) => moves.reduce(execMove, boardInStartPosition());
const execMove = (board, move) => {
const originX = fieldToXPosition(originField(move));
const originY = fieldToYPosition(originField(move));
const targetX = fieldToXPosition(targetField(move));
const targetY = fieldToYPosition(targetField(move));
board[targetY][targetX] = board[originY][originX];
board[originY][originX] = emptyBoard()[originY][originX];
return board;
};
const boardInStartPosition = () => [
['♜', '♞', '♝', '♛', '♚', '♝', '♞', '♜'],
['♟', '♟', '♟', '♟', '♟', '♟', '♟', '♟'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['♙', '♙', '♙', '♙', '♙', '♙', '♙', '♙'],
['♖', '♘', '♗', '♕', '♔', '♗', '♘', '♖'],
];
const emptyBoard = () => [
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
];
const originField = (move) => move.substr(0, 2);
const targetField = (move) => move.substr(2);
const fieldToXPosition = (field) => letterToChessIndex(field.charAt(0));
const fieldToYPosition = (field) => numberToChessIndex(field.charAt(1));
const letterToChessIndex = (letter) => 'abcdefgh'.indexOf(letter);
const numberToChessIndex = (num) => 8 - num;
console.log(board2string(boardInStartPosition()));
console.log('\n');
console.log(board2string(execMove(boardInStartPosition(), 'e2e4')));
console.log('\n');
console.log(board2string(execMoves(['e2e4', 'e7e5', 'f2f4'])));

View File

@@ -0,0 +1,55 @@
'use strict';
const board2string = (board) => board.map((row) => row.join('')).join('\n');
const positionHistoryForMoves = (moves) =>
moves.map((move, i) => moves.slice(0, i + 1)).map(execMoves);
const execMoves = (moves) => moves.reduce(execMove, boardInStartPosition());
const execMove = (board, move) => {
const originX = fieldToXPosition(originField(move));
const originY = fieldToYPosition(originField(move));
const targetX = fieldToXPosition(targetField(move));
const targetY = fieldToYPosition(targetField(move));
board[targetY][targetX] = board[originY][originX];
board[originY][originX] = emptyBoard()[originY][originX];
return board;
};
const boardInStartPosition = () => [
['♜', '♞', '♝', '♛', '♚', '♝', '♞', '♜'],
['♟', '♟', '♟', '♟', '♟', '♟', '♟', '♟'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['♙', '♙', '♙', '♙', '♙', '♙', '♙', '♙'],
['♖', '♘', '♗', '♕', '♔', '♗', '♘', '♖'],
];
const emptyBoard = () => [
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
['◻', '▦', '◻', '▦', '◻', '▦', '◻', '▦'],
['▦', '◻', '▦', '◻', '▦', '◻', '▦', '◻'],
];
const originField = (move) => move.substr(0, 2);
const targetField = (move) => move.substr(2);
const fieldToXPosition = (field) => letterToChessIndex(field.charAt(0));
const fieldToYPosition = (field) => numberToChessIndex(field.charAt(1));
const letterToChessIndex = (letter) => 'abcdefgh'.indexOf(letter);
const numberToChessIndex = (num) => 8 - num;
const history = positionHistoryForMoves(['e2e4', 'e7e5', 'f2f4']);
console.log(history);
history.forEach((position) => console.log(board2string(position), '\n'));

View File

@@ -0,0 +1,14 @@
const gradesTable = [
['Name', 'Mathematics', 'English', 'Biology'],
['Anna', 85, 92, 78],
['Ben', 90, 88, 84],
['Clara', 76, 95, 89],
];
// Change Anna's math grade to 88
gradesTable[1][1] = 88;
// Add a new row for another student
gradesTable.push(['David', 82, 79, 91]);
console.log(gradesTable);

View File

@@ -0,0 +1,27 @@
'use strict';
const inventory = [
[
// Category: Electronics
['Shelf 1', 'Laptop', 10],
['Shelf 2', 'Smartphone', 25],
],
[
// Category: Clothing
['Shelf 1', 'T-Shirts', 50],
['Shelf 2', 'Jeans', 30],
],
[
// Category: Groceries
['Shelf 1', 'Milk', 100],
['Shelf 2', 'Bread', 80],
],
];
// Increase the number of laptops
inventory[0][0][2] += 5; // New quantity: 15
// Add a new shelf to a category
inventory[1].push(['Shelf 3', 'Pants', 20]);
console.log(inventory);

View File

@@ -0,0 +1,50 @@
'use strict';
const isMixableWithMyIngredients = (cocktailRecipe) =>
isMixableWith(cocktailRecipe, ingredientsFromMyBar);
const isMixableWith = (cocktailRecipe, availableIngredients) =>
cocktailRecipe.every((ingredientFromRecipe) =>
hasIngredient(availableIngredients, ingredientFromRecipe)
);
const hasIngredient = (listOfIngredients, searchedIngredient) =>
listOfIngredients.includes(searchedIngredient);
const honoluluFlip = [
'Maracuja Juice',
'Pineapple Juice',
'Lemon Juice',
'Grapefruit Juice',
'Crushed Ice',
];
const casualFriday = ['Vodka', 'Lime Juice', 'Apple Juice', 'Cucumber'];
const pinkDolly = [
'Vodka',
'Orange Juice',
'Pineapple Juice',
'Grenadine',
'Cream',
'Coco Syrup',
];
const cocktailRecipes = [honoluluFlip, casualFriday, pinkDolly];
const ingredientsFromMyBar = [
'Pineapple',
'Maracuja Juice',
'Cream',
'Grapefruit Juice',
'Crushed Ice',
'Milk',
'Vodka',
'Apple Juice',
'Aperol',
'Pineapple Juice',
'Lime Juice',
'Lemons',
'Cucumber',
];
console.log(cocktailRecipes.find(isMixableWithMyIngredients));
// => [ 'Vodka', 'Lime Juice', 'Apple Juice', 'Cucumber' ]

View File

@@ -0,0 +1,20 @@
'use strict';
const countriesWithCapital = [
['UK', 'London'],
['France', 'Paris'],
['Germany', 'Berlin'],
['Switzerland', 'Bern'],
['Austria', 'Vienna'],
['Russia', 'Moscow'],
];
const capitalOf = (country) => {
const capitalIndex = 1;
const countryIndex = 0;
return countriesWithCapital.find(
(countryWithCapital) => countryWithCapital[countryIndex] === country
)[capitalIndex];
};
console.log(capitalOf('Switzerland'));

View File

@@ -0,0 +1,20 @@
'use strict';
const countriesWithCapital = [
['UK', 'London'],
['France', 'Paris'],
['Germany', 'Berlin'],
['Switzerland', 'Bern'],
['Austria', 'Vienna'],
['Russia', 'Moscow'],
];
const countryForCapital = (capital) => {
const capitalIndex = 1;
const countryIndex = 0;
return countriesWithCapital.find(
(countryWithCapital) => countryWithCapital[capitalIndex] === capital
)[countryIndex];
};
console.log(countryForCapital('Berlin'));

View File

@@ -0,0 +1,46 @@
'use strict';
const gradesTable = [
['Name', 'Mathematics', 'English', 'Biology', 'History'],
['Anna', 85, 92, 78, 88],
['Ben', 90, 88, 84, 79],
['Clara', 76, 95, 89, 91],
['David', 82, 79, 91, 85],
];
// Helper: Calculates average of an array of numbers
const getAverage = (numbers) => {
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
const avg = sum / numbers.length;
return Number(avg.toFixed(2));
};
// 1. Calculate average per student
const calculateAvgGrades = (table) => {
// We take the rows (excluding header), and map each row to a single average value
return table.slice(1).map((row) => {
const grades = row.slice(1); // Remove student name
return getAverage(grades);
});
};
// 2. Calculate average per subject
const calculateAvgSubjects = (table) => {
const headers = table[0].slice(1); // Get subject names ['Mathematics', 'English', ...]
const rows = table.slice(1); // Get data rows
// We map over the headers to create a result for each subject column
return headers.map((_, colIndex) => {
// For the current column, extract the value from every row
// Note: colIndex starts at 0, but in the row data, grades start at index 1
const columnGrades = rows.map((row) => row[colIndex + 1]);
return getAverage(columnGrades);
});
};
// Tests
console.log('Student Averages:', calculateAvgGrades(gradesTable));
// Expected: [85.75, 85.25, 87.75, 84.25]
console.log('Subject Averages:', calculateAvgSubjects(gradesTable));
// Expected: [83.25, 88.50, 85.50, 85.75]

View File

@@ -0,0 +1,41 @@
'use strict';
const image = [
[
// Row 1
[100, 150, 200], // Pixel 1
[50, 100, 150], // Pixel 2
],
[
// Row 2
[25, 75, 125], // Pixel 3
[200, 225, 250], // Pixel 4
],
];
const increaseBrightness = (image, value) => {
// Iterate through each line of the image
return image.map((row) =>
// Iterate through every pixel in the line
row.map((pixel) =>
// Increase each RGB value by 'value' and make sure that it does not exceed 255
pixel.map((component) => Math.min(component + value, 255))
)
);
};
const newImage = increaseBrightness(image, 30);
console.log(newImage);
/*
Expected outcome:
[
[
[130, 180, 230],
[80, 130, 180],
],
[
[55, 105, 155],
[230, 255, 255],
],
]
*/

View File

@@ -0,0 +1,47 @@
'use strict';
const inventory = [
[
// Category: Electronics
['Shelf 1', 'Laptop', 10],
['Shelf 2', 'Smartphone', 25],
],
[
// Category: Clothing
['Shelf 1', 'T-Shirts', 50],
['Shelf 2', 'Jeans', 30],
],
[
// Category: Groceries
['Shelf 1', 'Milk', 100],
['Shelf 2', 'Bread', 80],
],
];
// Add new category “Books"
inventory.push([
['Shelf 1', 'Novels', 40],
['Shelf 2', 'Non-fiction', 35],
]);
console.log(inventory);
/* Expected outcome:
[
[ // Electronics
['Shelf 1', 'Laptop', 10],
['Shelf 2', 'Smartphone', 25],
],
[ // Clothing
['Shelf 1', 'T-Shirts', 50],
['Shelf 2', 'Jeans', 30],
],
[ // Groceries
['Shelf 1', 'Milk', 100],
['Shelf 2', 'Bread', 80],
],
[ // Books
['Shelf 1', 'Novels', 40],
['Shelf 2', 'Non-fiction', 35],
],
]
*/

View File

@@ -0,0 +1,21 @@
'use strict';
const evolutionStages = [
['Pidgey', 'Pidgeotto', 'Pidgeot'],
['Vulpix', 'Ninetales'],
['Dratini', 'Dragonair', 'Dragonite'],
];
const stagesFor = (pokemon) =>
evolutionStages.find((stages) => stages.includes(pokemon));
const stagesAfter = (pokemon) =>
stagesFor(pokemon).slice(stagesFor(pokemon).indexOf(pokemon) + 1);
const stagesBefore = (pokemon) =>
stagesFor(pokemon).slice(0, stagesFor(pokemon).indexOf(pokemon));
console.log(stagesFor('Vulpix')); // => [ 'Vulpix', 'Ninetales' ]
console.log(stagesAfter('Dratini')); // => [ 'Dragonair', 'Dragonite' ]
console.log(stagesBefore('Pidgeot')); // => [ 'Pidgey', 'Pidgeotto' ]
console.log(stagesBefore('Dragonair')); // => [ 'Dratini' ]

View File

@@ -0,0 +1,20 @@
'use strict';
const shoppingList = [
['Fruits', 'Apples', 'Bananas', 'Oranges'],
['Vegetables', 'Carrots', 'Broccoli', 'Spinach'],
['Dairy', 'Milk', 'Cheese', 'Yogurt'],
];
// Your code here
shoppingList[0][2] = 'Grapes'; // Replace 'Bananas' with 'Grapes'
shoppingList[1][2] = 'Tomatoes'; // Replace 'Broccoli' with 'Tomatoes'
shoppingList[2][2] = 'Butter'; // Replace 'Cheese' with 'Butter'
console.log(shoppingList);
// Expected outcome:
// [
// ['Fruits', 'Apples', 'Grapes', 'Oranges'],
// ['Vegetables', 'Carrots', 'Tomatoes', 'Spinach'],
// ['Dairy', 'Milk', 'Butter', 'Yogurt'],
// ]

View File

@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Posts</title>
</head>
<body>
<h1>List of Posts</h1>
<ul id="post-list"></ul>
<script>
'use strict';
async function displayPosts() {
const postList = document.querySelector('#post-list');
try {
const response = await fetch('https://dummyjson.com/posts');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
data.posts.forEach((post) => {
const listItem = document.createElement('li');
listItem.textContent = post.title; // Display the title of each post
postList.appendChild(listItem);
});
} catch (error) {
console.error('Error fetching posts:', error);
const errorItem = document.createElement('li');
errorItem.textContent = 'Error loading posts.';
postList.appendChild(errorItem);
}
}
displayPosts();
</script>
</body>
</html>

View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Display Post Details</title>
</head>
<body>
<h1>List of Posts</h1>
<ul id="post-list"></ul>
<div
id="post-details"
style="
display: none;
border: 1px solid #ccc;
padding: 1em;
margin-top: 1em;
"
>
<h2 id="post-title"></h2>
<p id="post-body"></p>
<button id="close-details">Close Details</button>
</div>
<script>
'use strict';
async function loadAndDisplayPosts() {
const postList = document.getElementById('post-list');
const postDetails = document.getElementById('post-details');
const postTitle = document.getElementById('post-title');
const postBody = document.getElementById('post-body');
const closeDetailsButton = document.getElementById('close-details');
try {
const response = await fetch('https://dummyjson.com/posts');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const posts = await response.json();
posts.forEach((post) => {
const listItem = document.createElement('li');
listItem.textContent = post.title;
listItem.style.cursor = 'pointer';
// Add click event listener to display post details
listItem.addEventListener('click', () => {
postTitle.textContent = post.title;
postBody.textContent = post.body;
postDetails.style.display = 'block';
});
postList.appendChild(listItem);
});
} catch (error) {
console.error('Error fetching posts:', error);
const errorItem = document.createElement('li');
errorItem.textContent = 'Error loading posts.';
postList.appendChild(errorItem);
}
// Close details when the button is clicked
closeDetailsButton.addEventListener('click', () => {
postDetails.style.display = 'none';
});
}
loadAndDisplayPosts();
</script>
</body>
</html>

View File

@@ -0,0 +1,16 @@
'use strict';
async function fetchData() {
try {
const response = await fetch('https://dummyjson.com/posts');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Problem with the fetch operation:', error);
}
}
fetchData();

View File

@@ -0,0 +1,21 @@
'use strict';
const person = {
name: 'John Doe',
age: 30,
profession: 'Web Developer',
};
// Convert JavaScript object to JSON string
const jsonString = JSON.stringify(person);
console.log(jsonString);
// => {"name":"John Doe","age":30,"profession":"Web Developer"}
try {
// Convert JSON string back to JavaScript object
const parsedPerson = JSON.parse(jsonString);
console.log(parsedPerson.name); // => John Doe
console.log(parsedPerson.age); // => 30
} catch (error) {
console.error('Invalid JSON:', error);
}

View File

@@ -0,0 +1,31 @@
'use strict';
async function getData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
// Handle HTTP errors by throwing an exception
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
// Centralized error logging and fallback behavior
console.error('Error fetching data:', error);
// Optionally, return a default value or handle the error gracefully
return null;
}
}
// Usage
getData('https://dummyjson.com/posts')
.then((data) => {
if (data) {
console.log('Data:', data);
} else {
console.log('No data received');
}
})
.catch((error) => {
console.error('Error in getData:', error);
});

View File

@@ -0,0 +1,14 @@
'use strict';
async function fetchUsers() {
try {
const response = await fetch('https://dummyjson.com/users');
const data = await response.json();
console.log(data.users);
} catch (error) {
console.log(error);
}
}
// Call the function
fetchUsers();

View File

@@ -0,0 +1,14 @@
'use strict';
const book = {
title: 'The Great Gatsby',
author: 'F. Scott Fitzgerald',
year: 1925,
};
const jsonString = JSON.stringify(book);
console.log(jsonString);
const jsonObject = JSON.parse(jsonString);
console.log(jsonObject.title);
console.log(jsonObject.author);

View File

@@ -0,0 +1,9 @@
Code,Short Description,Tagline,Quantity,Price
MUG0007,coffee mug with LCD level indicator,never again reach for the empty mug,20,49.90
MUG0013,coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling,put the smart into coffee reading,20,99.90
OFF3145,pen with pre-warmed ink (tested on the South Pole),the pen is mightier than the cold,50,29.90
COM1001,ambidextrous computer mouse,end the dictate of left and right,10,19.90
COM0404,Easter egg themed webcam for your monitor,put an Easter egg on hardware too,20,149.90
COM0001,Vulcan language vi cheatsheet,learn vi and Vulcan at the same time,3,9.90
COM1536,Klingon language emacs cheatsheet,learn emacs and Klingon at the same time,50,9.90
MOB0555,smartphone case with built-in screen,never miss a message,20,39.90
1 Code Short Description Tagline Quantity Price
2 MUG0007 coffee mug with LCD level indicator never again reach for the empty mug 20 49.90
3 MUG0013 coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling put the smart into coffee reading 20 99.90
4 OFF3145 pen with pre-warmed ink (tested on the South Pole) the pen is mightier than the cold 50 29.90
5 COM1001 ambidextrous computer mouse end the dictate of left and right 10 19.90
6 COM0404 Easter egg themed webcam for your monitor put an Easter egg on hardware too 20 149.90
7 COM0001 Vulcan language vi cheatsheet learn vi and Vulcan at the same time 3 9.90
8 COM1536 Klingon language emacs cheatsheet learn emacs and Klingon at the same time 50 9.90
9 MOB0555 smartphone case with built-in screen never miss a message 20 39.90

View File

@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Products</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<ul class="list-group">
<li class="list-group-item">
<h2>coffee mug with LCD level indicator</h2>
<p>never again reach for the empty mug</p>
<p><strong>Price:</strong> EUR 49.90</p>
</li><li class="list-group-item">
<h2>coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling</h2>
<p>put the smart into coffee reading</p>
<p><strong>Price:</strong> EUR 99.90</p>
</li><li class="list-group-item">
<h2>pen with pre-warmed ink (tested on the South Pole)</h2>
<p>the pen is mightier than the cold</p>
<p><strong>Price:</strong> EUR 29.90</p>
</li><li class="list-group-item">
<h2>ambidextrous computer mouse</h2>
<p>end the dictate of left and right</p>
<p><strong>Price:</strong> EUR 19.90</p>
</li><li class="list-group-item">
<h2>Easter egg themed webcam for your monitor</h2>
<p>put an Easter egg on hardware too</p>
<p><strong>Price:</strong> EUR 149.90</p>
</li><li class="list-group-item">
<h2>Vulcan language vi cheatsheet</h2>
<p>learn vi and Vulcan at the same time</p>
<p><strong>Price:</strong> EUR 9.90</p>
<p class="alert alert-warning">Last items in stock!</p>
</li><li class="list-group-item">
<h2>Klingon language emacs cheatsheet</h2>
<p>learn emacs and Klingon at the same time</p>
<p><strong>Price:</strong> EUR 9.90</p>
</li><li class="list-group-item">
<h2>smartphone case with built-in screen</h2>
<p>never miss a message</p>
<p><strong>Price:</strong> EUR 39.90</p>
</li>
</ul></div>
</main>
<script>
'use strict';
</script>
</body>
</html>

View File

@@ -0,0 +1,10 @@
const fs = require('fs');
fs.readFile('data/products.csv', 'UTF8', (error, data) => {
console.log(data); // 2 output
});
for (let i = 0; i < 2000000000; i++) {
// be busy for a few seconds
}
console.log('ready'); // 1 output

View File

@@ -0,0 +1,32 @@
const fs = require('fs');
const data = fs.readFileSync('data/products.csv', 'UTF8');
const STOCK_WARN_AMOUNT = 5;
const products = data.split('\n');
products.shift(); // remove header
const recordToHTML = (record) => {
const fields = record.split(',');
const html = `<li class="list-group-item">
<h2>${fields[1]}</h2>
<p>${fields[2]}</p>
<p><strong>Price:</strong> EUR ${fields[4]}</p>
${
Number(fields[3]) <= STOCK_WARN_AMOUNT
? '<p class="alert alert-warning">Last items in stock!</p>'
: ''
}
</li>`;
return html;
};
const entries = products.filter((row) => row !== '').map(recordToHTML);
console.log('<ul class="list-group">');
entries.forEach((entry) => console.log(entry));
console.log('</ul>');
console.log('ready');

View File

@@ -0,0 +1,39 @@
const fs = require('fs');
const STOCK_WARN_AMOUNT = 5;
// Function to convert a CSV record to HTML
const recordToHTML = (record) => {
const fields = record.split(',');
const html = `<li class="list-group-item">
<h2>${fields[1]}</h2>
<p>${fields[2]}</p>
<p><strong>Price:</strong> EUR ${fields[4]}</p>
${
Number(fields[3]) <= STOCK_WARN_AMOUNT
? '<p class="alert alert-warning">Last items in stock!</p>'
: ''
}
</li>`;
return html;
};
// Asynchronous version
fs.readFile('data/products.csv', 'UTF8', (err, data) => {
if (err) {
console.error(err);
return;
}
const products = data.split('\n');
products.shift(); // remove header
const entries = products.filter((row) => row !== '').map(recordToHTML);
console.log('<ul class="list-group">');
entries.forEach((entry) => console.log(entry));
console.log('</ul>');
console.log('ready');
});

View File

@@ -0,0 +1,5 @@
const fs = require('fs'); // commonjs
const data = fs.readFileSync('data/products.csv', 'utf-8');
console.log(data);

View File

@@ -0,0 +1,34 @@
// some, but not all fields are quoted - solution 1
const mixedCSV =
'"very big, soft computer mouse","the cutest peripheral ever",10,39.90';
let fields = [];
let index = 0;
let state = 'outside';
mixedCSV.split('').forEach((char) => {
if (state === 'quoted') {
fields[index] += char; // => [",v,e,r,y..."]
if (char === '"') {
state = 'outside';
index += 1;
}
} else if (state === 'unquoted') {
if (char === ',') {
state = 'outside';
index += 1;
} else {
fields[index] += char;
}
} else if (state === 'outside') {
fields[index] = char; //=> [",...
if (char === '"') {
state = 'quoted';
} else if (char !== ',') {
state = 'unquoted';
}
}
});
console.log(fields);

View File

@@ -0,0 +1,28 @@
// some, but not all fields are quoted - solution 2/2
const mixedCSV =
'"very big, soft computer mouse",' + '"the cutest peripheral ever",10,39.90';
let fields = [];
const mixedCSVToArray = (s) =>
findCommaPositions(',' + s + ',')
.map((position, i, positions) => s.slice(position, positions[i + 1] - 1))
.slice(0, -1);
const findCommaPositions = (s) =>
s
.split('')
.reduce(
(positions, char, position) =>
char === ',' && isEven(countQuotes(s.slice(0, position)))
? positions.concat(position)
: positions,
[]
);
const countQuotes = (s) => s.split('').filter((c) => c === '"').length;
const isEven = (num) => num % 2 === 0;
console.log(mixedCSVToArray(mixedCSV));

View File

@@ -0,0 +1,7 @@
// all fields are quoted
const quotedCSV =
'"very big, soft computer mouse","the cutest peripheral ever","10","39.90"';
const fields = quotedCSV.split('","');
console.log(fields);

View File

@@ -0,0 +1,5 @@
const fs = require('fs');
const zlib = require('zlib');
const data = fs.readFileSync('data/products.html', 'UTF8');
fs.writeFileSync('data/products.html.gz', zlib.gzipSync(data));

View File

@@ -0,0 +1,9 @@
const fs = require('fs');
const zlib = require('zlib');
const gzipCompressor = zlib.createGzip();
const inputStream = fs.createReadStream('data/products.html');
const outputStream = fs.createWriteStream('data/products.html.gz');
inputStream.pipe(gzipCompressor).pipe(outputStream);

View File

@@ -0,0 +1,6 @@
const crypto = require('crypto');
const data = 'Ich werde verschlüsselt!';
const hash = crypto.createHash('sha256').update(data).digest('hex'); // 256-bit SHA-2 hash algorithm
console.log(hash); // 4803bce8b78d10b6bae3224c041f7c7311dedc056386870e50e6b56a109f4ee8

View File

@@ -0,0 +1 @@
I am a text from a text file with the name file.txt

View File

@@ -0,0 +1 @@
I am a text from a text file with the name file_1.txt

View File

@@ -0,0 +1 @@
I am a text from a text file with the name file_2.txt

View File

@@ -0,0 +1 @@
I am a text from a text file with the name file_3.txt

View File

@@ -0,0 +1,9 @@
Code,Short Description,Tagline,Quantity,Price
MUG0007,coffee mug with LCD level indicator,never again reach for the empty mug,20,49.90
MUG0013,coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling,put the smart into coffee reading,20,99.90
OFF3145,pen with pre-warmed ink (tested on the South Pole),the pen is mightier than the cold,50,29.90
COM1001,ambidextrous computer mouse,end the dictate of left and right,10,19.90
COM0404,Easter egg themed webcam for your monitor,put an Easter egg on hardware too,20,149.90
COM0001,Vulcan language vi cheatsheet,learn vi and Vulcan at the same time,3,9.90
COM1536,Klingon language emacs cheatsheet,learn emacs and Klingon at the same time,50,9.90
MOB0555,smartphone case with built-in screen,never miss a message,20,39.90
1 Code Short Description Tagline Quantity Price
2 MUG0007 coffee mug with LCD level indicator never again reach for the empty mug 20 49.90
3 MUG0013 coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling put the smart into coffee reading 20 99.90
4 OFF3145 pen with pre-warmed ink (tested on the South Pole) the pen is mightier than the cold 50 29.90
5 COM1001 ambidextrous computer mouse end the dictate of left and right 10 19.90
6 COM0404 Easter egg themed webcam for your monitor put an Easter egg on hardware too 20 149.90
7 COM0001 Vulcan language vi cheatsheet learn vi and Vulcan at the same time 3 9.90
8 COM1536 Klingon language emacs cheatsheet learn emacs and Klingon at the same time 50 9.90
9 MOB0555 smartphone case with built-in screen never miss a message 20 39.90

View File

@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Products</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<ul class="list-group">
<li class="list-group-item">
<h2>coffee mug with LCD level indicator</h2>
<p>never again reach for the empty mug</p>
<p><strong>Price:</strong> EUR 49.90</p>
</li><li class="list-group-item">
<h2>coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling</h2>
<p>put the smart into coffee reading</p>
<p><strong>Price:</strong> EUR 99.90</p>
</li><li class="list-group-item">
<h2>pen with pre-warmed ink (tested on the South Pole)</h2>
<p>the pen is mightier than the cold</p>
<p><strong>Price:</strong> EUR 29.90</p>
</li><li class="list-group-item">
<h2>ambidextrous computer mouse</h2>
<p>end the dictate of left and right</p>
<p><strong>Price:</strong> EUR 19.90</p>
</li><li class="list-group-item">
<h2>Easter egg themed webcam for your monitor</h2>
<p>put an Easter egg on hardware too</p>
<p><strong>Price:</strong> EUR 149.90</p>
</li><li class="list-group-item">
<h2>Vulcan language vi cheatsheet</h2>
<p>learn vi and Vulcan at the same time</p>
<p><strong>Price:</strong> EUR 9.90</p>
<p class="alert alert-warning">Last items in stock!</p>
</li><li class="list-group-item">
<h2>Klingon language emacs cheatsheet</h2>
<p>learn emacs and Klingon at the same time</p>
<p><strong>Price:</strong> EUR 9.90</p>
</li><li class="list-group-item">
<h2>smartphone case with built-in screen</h2>
<p>never miss a message</p>
<p><strong>Price:</strong> EUR 39.90</p>
</li>
</ul></div>
</main>
<script>
'use strict';
</script>
</body>
</html>

View File

@@ -0,0 +1,72 @@
const fs = require('fs');
const STOCK_WARN_AMOUNT = 5;
// Function to convert a CSV record to HTML
const recordToHTML = (record) => {
const fields = record.split(',');
const html = `<li class="list-group-item">
<h2>${fields[1]}</h2>
<p>${fields[2]}</p>
<p><strong>Price:</strong> EUR ${fields[4]}</p>
${
Number(fields[3]) <= STOCK_WARN_AMOUNT
? '<p class="alert alert-warning">Last items in stock!</p>'
: ''
}
</li>`;
return html;
};
// Asynchronous version
fs.readFile('data/products.csv', 'UTF8', (err, data) => {
if (err) {
console.error(err);
return;
}
const products = data.split('\n');
products.shift(); // remove header
const entries = products.filter((row) => row !== '').map(recordToHTML);
writeToFile(entries);
});
const writeToFile = (entries) => {
const headerStr = `<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Products</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">`;
const footerStr = `</div>
</main>
<script>
'use strict';
</script>
</body>
</html>`;
const html = `${headerStr}
<ul class="list-group">
${entries.join('')}
</ul>${footerStr}`;
fs.writeFile('data/products.html', html, (err) => {
if (err) {
console.error(err);
return;
}
console.log('File written successfully');
});
console.log('Writing file...');
};

View File

@@ -0,0 +1,9 @@
Code,Short Description,Tagline,Quantity,Price
MUG0007,coffee mug with LCD level indicator,never again reach for the empty mug,20,49.90
MUG0013,coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling,put the smart into coffee reading,20,99.90
OFF3145,pen with pre-warmed ink (tested on the South Pole),the pen is mightier than the cold,50,29.90
COM1001,ambidextrous computer mouse,end the dictate of left and right,10,19.90
COM0404,Easter egg themed webcam for your monitor,put an Easter egg on hardware too,20,149.90
COM0001,Vulcan language vi cheatsheet,learn vi and Vulcan at the same time,3,9.90
COM1536,Klingon language emacs cheatsheet,learn emacs and Klingon at the same time,50,9.90
MOB0555,smartphone case with built-in screen,never miss a message,20,39.90
1 Code Short Description Tagline Quantity Price
2 MUG0007 coffee mug with LCD level indicator never again reach for the empty mug 20 49.90
3 MUG0013 coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling put the smart into coffee reading 20 99.90
4 OFF3145 pen with pre-warmed ink (tested on the South Pole) the pen is mightier than the cold 50 29.90
5 COM1001 ambidextrous computer mouse end the dictate of left and right 10 19.90
6 COM0404 Easter egg themed webcam for your monitor put an Easter egg on hardware too 20 149.90
7 COM0001 Vulcan language vi cheatsheet learn vi and Vulcan at the same time 3 9.90
8 COM1536 Klingon language emacs cheatsheet learn emacs and Klingon at the same time 50 9.90
9 MOB0555 smartphone case with built-in screen never miss a message 20 39.90

View File

@@ -0,0 +1,73 @@
const fs = require('fs');
const zlib = require('zlib');
const STOCK_WARN_AMOUNT = 5;
// Function to convert a CSV record to HTML
const recordToHTML = (record) => {
const fields = record.split(',');
const html = `<li class="list-group-item">
<h2>${fields[1]}</h2>
<p>${fields[2]}</p>
<p><strong>Price:</strong> EUR ${fields[4]}</p>
${
Number(fields[3]) <= STOCK_WARN_AMOUNT
? '<p class="alert alert-warning">Last items in stock!</p>'
: ''
}
</li>`;
return html;
};
// Asynchronous version
fs.readFile('data/products.csv', 'UTF8', (err, data) => {
if (err) {
console.error(err);
return;
}
const products = data.split('\n');
products.shift(); // remove header
const entries = products.filter((row) => row !== '').map(recordToHTML);
writeToFile(entries);
});
const writeToFile = (entries) => {
const headerStr = `<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Products</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">`;
const footerStr = `</div>
</main>
<script>
'use strict';
</script>
</body>
</html>`;
const html = `${headerStr}
<ul class="list-group">
${entries.join('')}
</ul>${footerStr}`;
try {
const compressed = zlib.gzipSync(html);
fs.writeFileSync('data/products.html.gz', compressed);
} catch (err) {
console.error(err);
return;
}
console.log('file written');
};

View File

@@ -0,0 +1,9 @@
Code,Short Description,Tagline,Quantity,Price
MUG0007,coffee mug with LCD level indicator,never again reach for the empty mug,20,49.90
MUG0013,coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling,put the smart into coffee reading,20,99.90
OFF3145,pen with pre-warmed ink (tested on the South Pole),the pen is mightier than the cold,50,29.90
COM1001,ambidextrous computer mouse,end the dictate of left and right,10,19.90
COM0404,Easter egg themed webcam for your monitor,put an Easter egg on hardware too,20,149.90
COM0001,Vulcan language vi cheatsheet,learn vi and Vulcan at the same time,3,9.90
COM1536,Klingon language emacs cheatsheet,learn emacs and Klingon at the same time,50,9.90
MOB0555,smartphone case with built-in screen,never miss a message,20,39.90
1 Code Short Description Tagline Quantity Price
2 MUG0007 coffee mug with LCD level indicator never again reach for the empty mug 20 49.90
3 MUG0013 coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling put the smart into coffee reading 20 99.90
4 OFF3145 pen with pre-warmed ink (tested on the South Pole) the pen is mightier than the cold 50 29.90
5 COM1001 ambidextrous computer mouse end the dictate of left and right 10 19.90
6 COM0404 Easter egg themed webcam for your monitor put an Easter egg on hardware too 20 149.90
7 COM0001 Vulcan language vi cheatsheet learn vi and Vulcan at the same time 3 9.90
8 COM1536 Klingon language emacs cheatsheet learn emacs and Klingon at the same time 50 9.90
9 MOB0555 smartphone case with built-in screen never miss a message 20 39.90

View File

@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Products</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<ul class="list-group">
<li class="list-group-item">
<h2>coffee mug with LCD level indicator</h2>
<p>never again reach for the empty mug</p>
<p><strong>Price:</strong> EUR 49.90</p>
</li><li class="list-group-item">
<h2>coffee mug with bluetooth-connected coffee grounds scanner for automatized fortune telling</h2>
<p>put the smart into coffee reading</p>
<p><strong>Price:</strong> EUR 99.90</p>
</li><li class="list-group-item">
<h2>pen with pre-warmed ink (tested on the South Pole)</h2>
<p>the pen is mightier than the cold</p>
<p><strong>Price:</strong> EUR 29.90</p>
</li><li class="list-group-item">
<h2>ambidextrous computer mouse</h2>
<p>end the dictate of left and right</p>
<p><strong>Price:</strong> EUR 19.90</p>
</li><li class="list-group-item">
<h2>Easter egg themed webcam for your monitor</h2>
<p>put an Easter egg on hardware too</p>
<p><strong>Price:</strong> EUR 149.90</p>
</li><li class="list-group-item">
<h2>Vulcan language vi cheatsheet</h2>
<p>learn vi and Vulcan at the same time</p>
<p><strong>Price:</strong> EUR 9.90</p>
<p class="alert alert-warning">Last items in stock!</p>
</li><li class="list-group-item">
<h2>Klingon language emacs cheatsheet</h2>
<p>learn emacs and Klingon at the same time</p>
<p><strong>Price:</strong> EUR 9.90</p>
</li><li class="list-group-item">
<h2>smartphone case with built-in screen</h2>
<p>never miss a message</p>
<p><strong>Price:</strong> EUR 39.90</p>
</li>
</ul></div>
</main>
<script>
'use strict';
</script>
</body>
</html>

View File

@@ -0,0 +1,9 @@
const fs = require('fs');
const zlib = require('zlib');
const inputStream = fs.createReadStream('data/products.html');
const outputStream = fs.createWriteStream('data/products.html.gz');
inputStream.on('data', (data) => {
outputStream.write(zlib.gzipSync(data));
});

View File

@@ -0,0 +1,17 @@
const crypto = require('crypto');
const PASSWORD_LENGTH = 10;
const s = '23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ!.,;#$%/+*';
const buf = crypto.randomBytes(PASSWORD_LENGTH);
console.log(buf); // gibt ein Buffer Objekt zurück (z.B. <Buffer 90 7f 3d 1d 1f 7d 7d 7d 7d 7d>)
const password = Array.from(buf);
constole.log(password); // gibt ein Array zurück mit Werten zwischen 0 und 255 (z.B. [ 144, 127, 61, 29, 31, 125, 125, 125, 125, 125 ])
password
.map((byte) => s.charAt(byte % s.length)) // gibt ein Array zurück mit den Zeichen aus s (z.B. [ '3', '7', 'h', 'G', 'J', 'z', 'z', 'z', 'z', 'z' ])
.join(''); // wandelt das Array in einen String um.
console.log(password); // gibt das generierte Passwort zurück (z.B. '37hGJzzzzz')

View File

@@ -0,0 +1,12 @@
'use strict';
// Import the 'os' module to access operating system-related utility methods
const os = require('os');
// Get the platform of the operating system (e.g., 'linux', 'win32', 'darwin')
const system = os.platform();
// Get the number of CPU cores available on the machine
const cpus = os.cpus().length;
console.log(`I am running on a machine with ${system} and ${cpus} cores.`);