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,13 @@
'use strict';
let x = () => {
a = 3;
};
let y = () => (a = 5);
let z = () => {
console.log(a);
};
x();
y();
z();

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
@@ -40,6 +40,24 @@
</main>
<script>
'use strict';
const outputEl = document.querySelector('.output');
const isPalindrom = (toCheckString) => {
const reverseString = toCheckString
.replace(/[$%!.,]/g, '')
.split('')
.reverse()
.join('');
return toCheckString.trim().toLowerCase() === reverseString.trim().toLowerCase() ? true : false;
};
const toTest = ` Lagerregal`;
const result = isPalindrom(toTest);
console.log(toTest, result);
outputEl.textContent = `${toTest} ist ${result ? 'ein' : 'KEIN'} Palindrom`;
</script>
</body>
</html>

View File

@@ -1,47 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 46: Richtige Gewinner</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h1>Übung 46: Richtige Gewinner</h1>
<p>
Die Ausgabe der Gewinner aus dem letzten Beispiel (Codebeispiel 324) ist immer noch nicht ideal. Am Besten
wäre das folgende Ergebnis-Array:
</p>
<pre>
<code>
[
'1st place: Heribert',
'2nd place: Friedlinde',
'3rd place: Tusnelda',
'Oswine',
'Ladislaus',
]
</code>
</pre>
</div>
<div class="output alert alert-secondary"></div>
</div>
</main>
<script>
'use strict';
const outputEl = document.querySelector('.output');
const winners = ['Heribert', 'Friedlinde', 'Tusnelda', 'Oswine', 'Ladislaus'];
// Beispiel
const getWinners = (winners) => {};
console.log(getWinners(winners));
outputEl.innerHTML = `<ul><li>${getWinners(winners).join('</li><li>')}</li></ul>`;
</script>
</body>
</html>

View File

@@ -1,79 +0,0 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 47: Lückentext zu Higher-Order-Funktionen</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<h1>Übung 47: Lückentext zu Higher-Order-Funktionen</h1>
<p>
Das ist garantiert der letzte Lückentext für diese Lektion. Ersetzen Sie wieder die Kommentare
<strong>/* ??? */</strong> durch den richtigen Code, um das angegebene Ergebnis zu erzielen.
</p>
</div>
</main>
<script>
'use strict';
let result;
let results;
let inputs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let text = 'Hi this is a short text';
let names = ['Heribert', 'Friedlinde', 'Tusnelda', 'Oswine', 'Ladislaus'];
//odd numbers
//results = inputs
console.log(results); // => [ 1, 3, 5, 7, 9 ]
//sum
//result = inputs
console.log(result); // => 55
//product
//result = inputs
console.log(result); // => 3628800
//longest word length
result = text.split(' '); //=> ['Hi', 'this', 'is', 'a', 'short', 'text'];
//
console.log(result); // => 5
//longest word
result = text.split(' '); //=> ['Hi', 'this', 'is', 'a', 'short', 'text'];
//
console.log(result); // =>'short'
//avg word length =========================
// result =
console.log(result); // => 3
//sort by 3rd letter
// ['Heribert', 'Friedlinde', 'Tusnelda', 'Oswine', 'Ladislaus'];
const names2 = [...names];
// results =
console.log(results); // => [ 'Ladislaus', 'Friedlinde', 'Heribert', 'Tusnelda', 'Oswine' ]
// Are there names with more than 8 letters?
// ['Heribert', 'Friedlinde', 'Tusnelda', 'Oswine', 'Ladislaus'];
// result = names
// Has every name at least 8 letters?
// result = names
console.log(result); // false
// What is the lowest value from the inputs?
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// result = inputs
console.log(result);
</script>
</body>
</html>

View File

@@ -0,0 +1,100 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 46: Richtige Gewinner</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h1>Übung 46: Richtige Gewinner</h1>
<p>
Die Ausgabe der Gewinner aus dem letzten Beispiel (Codebeispiel 324) ist immer noch nicht ideal. Am Besten
wäre das folgende Ergebnis-Array:
</p>
<pre>
<code>
[
'1st place: Heribert',
'2nd place: Friedlinde',
'3rd place: Tusnelda',
'Oswine',
'Ladislaus',
]
</code>
</pre>
</div>
<div class="output alert alert-secondary"></div>
</div>
</main>
<script>
'use strict';
const outputEl = document.querySelector('.output');
const winners = ['Heribert', 'Friedlinde', 'Tusnelda', 'Oswine', 'Ladislaus'];
// const PlaceWinner = () => {
// console.log(winners());
// };
// Beispiel
const getWinners = (winners) => {
const results = [];
const restAr = [];
for (let i = 0; i < winners.length; i++) {
if (i === 0) {
results.push(`1st Place: ${winners[i]}`);
} else if (i === 1) {
results.push(`2nd Place: ${winners[i]}`);
} else if (i === 2) {
results.push(`3rd Place: ${winners[i]}`);
} else {
restAr.push(winners[i]);
}
}
//return [results, restAr];
return results.concat(rest);
};
// Beispiel
const getWinners2 = (names = []) => {
const results = names.map((name, idx) => {
if (idx === 0) {
return `1st place: ${name}`;
}
if (idx === 1) {
return `2nd place: ${name}`;
}
if (idx === 2) {
return `3rd place: ${name}`;
}
return name;
});
return results;
};
const labels = ['1st', '2nd', '3rd'];
// Beispiel
const getWinners3 = (names = []) => {
const results = names.map((name, idx) => {
// if (idx < 3) {
// return `${labels[idx]} place: ${name}`;
// } else {
// return name;
// }
return idx < labels.length ? `${labels[idx]} place: ${name}` : name;
});
return results;
};
console.log(getWinners3(winners));
outputEl.innerHTML = `<ul><li>${getWinners3(winners).join('</li><li>')}</li></ul>`;
</script>
</body>
</html>

View File

@@ -0,0 +1,173 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 47: Lückentext zu Higher-Order-Funktionen</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<main>
<div class="container py-5">
<h1>Übung 47: Lückentext zu Higher-Order-Funktionen</h1>
<p>
Das ist garantiert der letzte Lückentext für diese Lektion. Ersetzen Sie wieder die Kommentare
<strong>/* ??? */</strong> durch den richtigen Code, um das angegebene Ergebnis zu erzielen.
</p>
</div>
</main>
<script>
'use strict';
let result;
let results;
let inputs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let text = 'Hi this is a short text';
let names = ['Heribert', 'Friedlinde', 'Tusnelda', 'Oswine', 'Ladislaus'];
//odd numbers
//results = inputs
//let inputs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
results = inputs.filter((n) => n % 2 !== 0);
const ungeradeZahlen = [];
for (let i = 0; i < inputs.length; i++) {
if (inputs[i] % 2 !== 0) {
ungeradeZahlen.push(inputs[i]);
}
}
console.log(ungeradeZahlen); // => [ 1, 3, 5, 7, 9 ]
console.log(results); // => [ 1, 3, 5, 7, 9 ]
// ==================================================================
// sum
inputs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// a und b wrd addiert (1+2 = 3) speichert in a und ( a + b ( 3 +3 = 6))
const sum = inputs.reduce((a, b) => a + b, 0);
console.log('sum: ', sum); // => 55
// ======================================================================
//product
//result = inputs
const gesamtsumme = inputs.reduce((a, b) => a * b, 1);
console.log(gesamtsumme); // => 3628800
// ========================================================================
//longest word length
// let text = 'Hi this is a short text';
const longestWordLength = text.split(' ').reduce((a, b) => {
if (a.length > b.length) {
return a;
} else {
return b;
}
}).length;
console.log(longestWordLength); //=> 5
// longest word length
results = text.split(' '); //=> ['Hi', 'this', 'is', 'a', 'short', 'text'];
const getWordLength = (word) => {
return word.length;
};
const wordLength = results.map(getWordLength); // => [2,4,2,1,5,4]
result = wordLength.sort((n1, n2) => {
return n2 - n1;
});
result = result[0];
console.log(result); // => 5
result = text
.split(' ') //=> ['Hi', 'this', 'is', 'a', 'short', 'text'];
.map((a) => a.length) // => [2,4,2,1,5,4]
.reduce((a, b) => Math.max(a, b)); // => 5
// .reduce((a, b) => (a < b ? b : a)); // => 5
console.log('Max word length: ', result);
//longest word length
result = text.split(' ').sort((a, b) => b.length - a.length)[0].length;
//=> ['Hi', 'this', 'is', 'a', 'short', 'text'];
console.log(`Länge des längsten Wortes: ${result}`); // => 5
// ======================================================
//longest word
//result = text.split(' '); //=> ['Hi', 'this', 'is', 'a', 'short', 'text'];
const longestword = text.split(' ').reduce((a, b) => {
if (a.length > b.length) return a;
else return b;
});
result = text.split(' ').sort((a, b) => b.length - a.length)[0];
console.log('longestword: ', result); // =>'short'
console.log(longestword); // =>'short'
// =========================================================
//avg word length =========================// => 3
const avgword = text.split(' ');
const AnzahlSum = avgword.length; // 6
const AvgSum = AnzahlSum / 2;
console.log(AvgSum); // 3
result =
text
.split(' ') //=> ['Hi', 'this', 'is', 'a', 'short', 'text'];
.map((a) => a.length) // => [2,4,2,1,5,4]
.reduce((a, b) => a + b, 0) / text.split(' ').length;
console.log(`Avg word length: ${result}`); // => 3
result =
text
.split(' ')
.map((text) => text.length)
.reduce((n1, n2) => n1 + n2, 0) / text.split(' ').length;
console.log(`Durchschnittliche Wortlänge: ${result}`); // => 3
result = text.replaceAll(' ', '').length / text.split(' ').length;
console.log(`Durchschnittliche Wortlänge: ${result}`); // => 3
// ============================================================
//sort by 3rd letter
// ['Heribert', 'Friedlinde', 'Tusnelda', 'Oswine', 'Ladislaus'];
const names2 = [...names];
const sortedByThirdLetterAr = names2.sort((a, b) => a.charAt(2).localeCompare(b.charAt(2)));
results = [...names].sort((a, b) => (a.charAt(2) < b.charAt(2) ? -1 : 1));
console.log(`sort by 3rd letter: ${results}`); // => [ 'Ladislaus', 'Friedlinde', 'Heribert', 'Tusnelda', 'Oswine' ]
console.log(sortedByThirdLetterAr); // => [ 'Ladislaus', 'Friedlinde', 'Heribert', 'Tusnelda', 'Oswine' ]
// ========================================================================
// Are there names with more than 8 letters?
// ['Heribert', 'Friedlinde', 'Tusnelda', 'Oswine', 'Ladislaus'];
const names3 = [...names];
const moreThenEightLetters = names3.filter((name) => name.length > 8);
result = names.some((name) => name.length > 8);
console.log(moreThenEightLetters.length > 0); // => true
console.log(result); // => true
//===================================================================
// Has every name at least 8 letters?
result = [...names].every((name) => name.length <= 8);
console.log('Has every name at least 8 letters?: ', result);
//====================================================
// What is the lowest value from the inputs?
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// result = inputs
result = Math.min(...inputs);
console.log(result);
</script>
</body>
</html>

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
@@ -28,7 +28,13 @@
<script>
'use strict';
const honoluluFlip = ['Maracuja Juice', 'Pineapple Juice', 'Lemon Juice', 'Grapefruit Juice', 'Crushed Ice'];
const honoluluFlip = [
'Maracuja Juice', //
'Pineapple Juice',
'Lemon Juice',
'Grapefruit Juice',
'Crushed Ice',
];
const ingredientsFromMyBar = [
'Pineapple',
@@ -49,14 +55,16 @@
// 1. Schreibe eine Funktion, `hasIngredient`, die `true` zurückgibt, wenn eine angegebene Zutat in einer Rezeptliste vorhanden ist. Rufe deine Funktion mit Maracujsasaft und Honolulu Flip auf.
const hasIngredient = (listOfIngredients, searchedIngredient) => {
/* ??? */
const hasIngredient = (cocktailAr = [], searchStr) => {
return cocktailAr.includes(searchStr);
};
//alert(hasIngredient(honoluluFlip, 'Maracuja Juice'));
// 2. So richtig sinnvoll ist unsere Funktion noch nicht. Viel hilfreicher wäre es, wenn wir eine Funktion hätten, die anhand unserer vorhandenen Zutaten herausfindet, ob wir den Cocktail auch tatsächlich machen können. Dafür benötigst du die komplette Liste aller bei dir vorhandenen Zutaten (ingredientsFromMyBar). Du möchtest wissen, ob du alle Zutaten vorrätig hast, die du zum Mixen des Cocktails benötigst.
const isMixableWith = (cocktailRecipe, availableIngredients) => {
/* ??? */
const isMixableWith = (cocktailAr, allAr = []) => {
return cocktailAr.every((str) => hasIngredient(allAr, str));
};
//honoluluFlip isMixableWith ingredientsFromMyBar?

View File

@@ -19,6 +19,10 @@
const transform = (fullName) => {
const nameParts = fullName.split(' '); // => ['Ladislaus', 'Coolio', 'Barry', 'Crazy', 'Jones'];
const lastName = nameParts.slice(nameParts.length - 1); // => 'Jones'
// nameParts = nameParts.slice(0, nameParts.length - 1); // => ['Ladislaus', 'Coolio', 'Barry', 'Crazy']
// Wenn Variable mit "let" deklarariert wäre, könnten wir die Variable neu befüllen. Bezeichner wäre aber dann nicht mehr sinnvoll.
const firstNames = nameParts.slice(0, nameParts.length - 1); // => ['Ladislaus', 'Coolio', 'Barry', 'Crazy']
return firstNames.map((firstName) => firstName.charAt(0) + '.').join(' ') + ' ' + lastName;

15
02_advanced/.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,15 @@
{
"recommendations": [
"kamikillerto.vscode-colorize",
"sleistner.vscode-fileutils",
"bierner.github-markdown-preview",
"bradgashler.htmltagwrap",
"zhuangtongfa.material-theme",
"techer.open-in-browser",
"esbenp.prettier-vscode",
"pdconsec.vscode-print",
"vscode-icons-team.vscode-icons",
"formulahendry.auto-rename-tag",
"tomoki1207.pdf"
]
}

332
02_advanced/.vscode/marp-theme.css vendored Normal file
View File

@@ -0,0 +1,332 @@
/* @theme marp-theme */
@charset "UTF-8";
/*!
* Marp Dracula theme.
* @theme marp-theme
* @author Daniel Nicolas Gisolfi & modified by Philippe Botzek
*
* @auto-scaling true
* @size 4:3 960px 720px
* @size 16:9 1280px 720px
*/
@import url('https://fonts.googleapis.com/css?family=Lato:400,900|IBM+Plex+Sans:400,700');
:root {
--dracula-background: #282a36;
--dracula-current-line: #44475a;
--dracula-foreground: #f8f8f2;
--dracula-comment: #6272a4;
--dracula-cyan: #8be9fd;
--dracula-green: #50fa7b;
--dracula-orange: #ffb86c;
--dracula-pink: #ff79c6;
--dracula-purple: #bd93f9;
--dracula-red: #ff5555;
--dracula-yellow: #f1fa8c;
}
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
background: var(--dracula-background);
}
/* Dracula Foreground */
.hljs,
.hljs-subst,
.hljs-typing,
.hljs-variable,
.hljs-template-variable {
color: var(--dracula-foreground);
}
/* Dracula Comment */
.hljs-comment,
.hljs-quote,
.hljs-deletion {
color: var(--dracula-comment);
}
/* Dracula Cyan */
.hljs-meta .hljs-doctag,
.hljs-built_in,
.hljs-selector-tag,
.hljs-section,
.hljs-link,
.hljs-class {
color: var(--dracula-cyan);
}
/* Dracula Green */
.hljs-title {
color: var(--dracula-green);
}
/* Dracula Orange */
.hljs-params {
color: var(--dracula-orange);
}
/* Dracula Pink */
.hljs-keyword {
color: var(--dracula-pink);
}
/* Dracula Purple */
.hljs-literal,
.hljs-number {
color: var(--dracula-purple);
}
/* Dracula Red */
.hljs-regexp {
color: var(--dracula-red);
}
/* Dracula Yellow */
.hljs-string,
.hljs-name,
.hljs-type,
.hljs-attr,
.hljs-symbol,
.hljs-bullet,
.hljs-addition,
.hljs-template-tag {
color: var(--dracula-yellow);
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-literal,
.hljs-title,
.hljs-section,
.hljs-doctag,
.hljs-type,
.hljs-name,
.hljs-strong {
font-weight: bold;
}
.hljs-params,
.hljs-emphasis {
font-style: italic;
}
svg[data-marp-fitting='svg'] {
max-height: 580px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0.5em 0 0 0;
color: var(--dracula-pink);
}
h1 strong,
h2 strong,
h3 strong,
h4 strong,
h5 strong,
h6 strong {
font-weight: inherit;
}
h1 {
font-size: 1.8em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.3em;
}
h4 {
font-size: 1.1em;
}
h5 {
font-size: 1em;
}
h6 {
font-size: 0.9em;
}
p,
blockquote {
margin: 1em 0 0 0;
}
ul > li,
ol > li {
margin: 0.3em 0 0 0;
color: var(--dracula-cyan);
}
ul > li > p,
ol > li > p {
margin: 0.6em 0 0 0;
}
code {
display: inline-block;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.8em;
letter-spacing: 0;
margin: -0.1em 0.15em;
padding: 0.1em 0.2em;
vertical-align: baseline;
color: var(--dracula-green);
}
pre {
display: block;
margin: 1em 0 0 0;
min-height: 1em;
overflow: visible;
}
pre code {
box-sizing: border-box;
margin: 0;
min-width: 100%;
padding: 0.5em;
font-size: 0.7em;
}
pre code svg[data-marp-fitting='svg'] {
max-height: calc(580px - 1em);
}
blockquote {
margin: 1em 0 0 0;
padding: 0 1em;
position: relative;
color: var(--dracula-orange);
}
blockquote::after,
blockquote::before {
content: '“';
display: block;
font-family: 'Times New Roman', serif;
font-weight: bold;
position: absolute;
color: var(--dracula-green);
}
blockquote::before {
top: 0;
left: 0;
}
blockquote::after {
right: 0;
bottom: 0;
transform: rotate(180deg);
}
blockquote > *:first-child {
margin-top: 0;
}
mark {
background: transparent;
}
table {
border-spacing: 0;
border-collapse: collapse;
margin: 1em 0 0 0;
}
table th,
table td {
padding: 0.2em 0.4em;
border-width: 1px;
border-style: solid;
}
section {
font-size: 35px;
font-family: 'IBM Plex Sans';
line-height: 1.35;
letter-spacing: 1.25px;
padding: 70px;
color: var(--dracula-foreground);
background-color: var(--dracula-background);
}
section > *:first-child,
section > header:first-child + * {
margin-top: 0;
}
section a,
section mark {
color: var(--dracula-red);
}
section code {
background: var(--dracula-current-line);
color: var(--dracula-current-green);
}
section h1 strong,
section h2 strong,
section h3 strong,
section h4 strong,
section h5 strong,
section h6 strong {
color: var(--dracula-current-line);
}
section pre > code {
background: var(--dracula-current-line);
}
section header,
section footer,
section section::after,
section blockquote::before,
section blockquote::after {
color: var(--dracula-comment);
}
section table th,
section table td {
border-color: var(--dracula-current-line);
}
section table thead th {
background: var(--dracula-current-line);
color: var(--dracula-yellow);
}
section table tbody > tr:nth-child(even) td,
section table tbody > tr:nth-child(even) th {
background: var(--dracula-current-line);
}
header,
footer,
section::after {
box-sizing: border-box;
font-size: 66%;
height: 70px;
line-height: 50px;
overflow: hidden;
padding: 10px 25px;
position: absolute;
color: var(--dracula-comment);
}
header {
left: 0;
right: 0;
top: 0;
}
footer {
left: 0;
right: 0;
bottom: 0;
}
section::after {
right: 0;
bottom: 0;
font-size: 80%;
}

30
02_advanced/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,30 @@
{
"workbench.iconTheme": "vscode-icons",
"workbench.colorTheme": "One Dark Pro",
"prettier.printWidth": 120,
"prettier.singleQuote": true,
"editor.hover.enabled": "on",
"editor.wordWrap": "on",
"explorer.confirmDelete": false,
"explorer.confirmDragAndDrop": false,
"editor.quickSuggestionsDelay": 600,
"editor.tabSize": 2,
"editor.formatOnSave": true,
"emmet.includeLanguages": {
"javascript": "javascriptreact",
"ejs": "html"
},
"html.format.unformatted": "wbr,%",
"files.associations": {
"*.ejs": "html"
},
"editor.fontFamily": "'MesloLGS NF', Hack, Consolas, 'Courier New', monospace",
"oneDarkPro.markdownStyle": false,
"explorer.compactFolders": false,
"workbench.editor.labelFormat": "short",
"editor.hover.delay": 800,
"editor.bracketPairColorization.enabled": true,
"editor.guides.bracketPairs": "active",
"markdown.marp.themes": ["./.vscode/marp-theme.css"],
"markdown-preview-github-styles.colorTheme": "light"
}

View File

@@ -0,0 +1,73 @@
{
"Output HTML Element": {
"scope": "html",
"prefix": "output",
"body": ["<div class=\"output alert alert-secondary my-3\"></div>"],
"description": "generate a div Element with output alert and alert secondary class"
},
"Bootstrap html": {
"scope": "html",
"prefix": "!bs",
"body": [
"<!DOCTYPE html>",
"<html lang=\"de\">",
"\t<head>",
"\t\t<meta charset=\"UTF-8\" />",
"\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />",
"\t\t<title>$0</title>",
"\t\t<link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css\" rel=\"stylesheet\" />",
"\t</head>",
"\t<body>",
"\t\t<main>",
"\t\t\t<div class=\"container py-5\">",
"\t\t\t\t<h1>$0</h1>",
"\t\t\t</div>",
"\t\t</main>",
"\t\t<script>",
"\t\t\t'use strict';",
"\t\t\t",
"\t\t</script>",
"\t</body>",
"</html>"
],
"description": "Generate HTML with Bootstrap CDN and script-tag"
},
"$ und $$ helper function": {
"scope": "javascript,typescript",
"prefix": "$$$",
"body": [
"const $ = (qs) => document.querySelector(qs);",
"const $$ = (qs) => Array.from(document.querySelectorAll(qs));"
],
"description": "$ and $$ shorthand helper function"
},
"JavaScript Dateivorlage": {
"scope": "javascript,typescript",
"prefix": "vjs",
"body": [
"'use strict';",
"",
"(() => {",
"",
"\t// === DOM & VARS =======",
"\tconst DOM = {};",
"",
"\t// === INIT =============",
"\tconst init = () => {",
"",
"\t}",
"",
"\t// === EVENTHANDLER =====",
"",
"\t// === XHR/FETCH ========",
"",
"\t// === FUNCTIONS ========",
"",
"\tinit();",
"",
"})();"
],
"description": "JavaScript Dateivorlage"
}
}

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));
});

Some files were not shown because too many files have changed in this diff Show More