@for (entry of xpKeys; track entry.key) {
diff --git a/src/app/pages/algorithms/algorithms.component.html b/src/app/pages/algorithms/algorithms.component.html
new file mode 100644
index 0000000..a4b1827
--- /dev/null
+++ b/src/app/pages/algorithms/algorithms.component.html
@@ -0,0 +1,13 @@
+
+
Algorithmen
+
+
+
+ {{ category.title }}
+
+
+ {{ category.description }}
+
+
+
+
diff --git a/src/app/pages/algorithms/algorithms.component.scss b/src/app/pages/algorithms/algorithms.component.scss
new file mode 100644
index 0000000..d6d57ce
--- /dev/null
+++ b/src/app/pages/algorithms/algorithms.component.scss
@@ -0,0 +1,19 @@
+.container {
+ padding: 2rem;
+}
+
+.category-cards {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+ margin-top: 2rem;
+
+ mat-card {
+ cursor: pointer;
+ max-width: 300px;
+
+ &:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+ }
+ }
+}
diff --git a/src/app/pages/algorithms/algorithms.component.ts b/src/app/pages/algorithms/algorithms.component.ts
new file mode 100644
index 0000000..7c8535f
--- /dev/null
+++ b/src/app/pages/algorithms/algorithms.component.ts
@@ -0,0 +1,26 @@
+import { Component, OnInit } from '@angular/core';
+import { AlgorithmsService } from './service/algorithms.service';
+import { AlgorithmCategory } from './models/algorithm-category';
+import { Observable } from 'rxjs';
+import { CommonModule } from '@angular/common';
+import { RouterLink } from '@angular/router';
+import { MatCardModule } from '@angular/material/card';
+
+@Component({
+ selector: 'app-algorithms',
+ templateUrl: './algorithms.component.html',
+ styleUrls: ['./algorithms.component.scss'],
+ standalone: true,
+ imports: [CommonModule, RouterLink, MatCardModule],
+})
+export class AlgorithmsComponent implements OnInit {
+
+ categories$: Observable
| undefined;
+
+ constructor(private algorithmsService: AlgorithmsService) {
+ }
+
+ ngOnInit(): void {
+ this.categories$ = this.algorithmsService.getCategories();
+ }
+}
diff --git a/src/app/pages/algorithms/models/algorithm-category.ts b/src/app/pages/algorithms/models/algorithm-category.ts
new file mode 100644
index 0000000..15971f6
--- /dev/null
+++ b/src/app/pages/algorithms/models/algorithm-category.ts
@@ -0,0 +1,6 @@
+export interface AlgorithmCategory {
+ id: string;
+ title: string;
+ description: string;
+ routerLink: string;
+}
diff --git a/src/app/pages/algorithms/pathfinding/pathfinding.component.html b/src/app/pages/algorithms/pathfinding/pathfinding.component.html
new file mode 100644
index 0000000..db95196
--- /dev/null
+++ b/src/app/pages/algorithms/pathfinding/pathfinding.component.html
@@ -0,0 +1,29 @@
+
+
{{ 'PATHFINDING.TITLE' | translate }}
+
+
+
+
+ {{ 'PATHFINDING.START_NODE' | translate }}
+ {{ 'PATHFINDING.END_NODE' | translate }}
+ {{ 'PATHFINDING.WALL' | translate }}
+ {{ 'PATHFINDING.CLEAR_NODE' | translate }}
+
+
+
+
+
+
+
+
+
+ {{ 'PATHFINDING.START_NODE' | translate }}
+ {{ 'PATHFINDING.END_NODE' | translate }}
+ {{ 'PATHFINDING.WALL' | translate }}
+ {{ 'PATHFINDING.VISITED' | translate }}
+ {{ 'PATHFINDING.PATH' | translate }}
+
+
+
+
+
diff --git a/src/app/pages/algorithms/pathfinding/pathfinding.component.scss b/src/app/pages/algorithms/pathfinding/pathfinding.component.scss
new file mode 100644
index 0000000..94346e3
--- /dev/null
+++ b/src/app/pages/algorithms/pathfinding/pathfinding.component.scss
@@ -0,0 +1,49 @@
+.container {
+ padding: 2rem;
+}
+
+.controls-container {
+ display: flex;
+ flex-direction: column;
+ margin-bottom: 1rem;
+}
+
+.controls {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+ margin-bottom: 1rem;
+
+ mat-button-toggle-group {
+ border-radius: 4px;
+ overflow: hidden;
+ }
+}
+
+.legend {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+ align-items: center;
+ font-size: 0.9em;
+
+ .legend-color {
+ display: inline-block;
+ width: 15px;
+ height: 15px;
+ border: 1px solid #ccc;
+ vertical-align: middle;
+ margin-right: 5px;
+
+ &.start { background-color: green; }
+ &.end { background-color: red; }
+ &.wall { background-color: black; }
+ &.visited { background-color: skyblue; }
+ &.path { background-color: gold; }
+ }
+}
+
+canvas {
+ border: 1px solid #ccc;
+ display: block;
+}
\ No newline at end of file
diff --git a/src/app/pages/algorithms/pathfinding/pathfinding.component.ts b/src/app/pages/algorithms/pathfinding/pathfinding.component.ts
new file mode 100644
index 0000000..8ea27ae
--- /dev/null
+++ b/src/app/pages/algorithms/pathfinding/pathfinding.component.ts
@@ -0,0 +1,284 @@
+import {AfterViewInit, Component, ElementRef, HostListener, ViewChild} from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { MatButtonModule } from '@angular/material/button';
+import {GRID_COLS, GRID_ROWS, NODE_SIZE, Node} from './pathfinding.models';
+import {MatButtonToggleModule} from '@angular/material/button-toggle';
+import {FormsModule} from '@angular/forms';
+import {NgIf} from '@angular/common';
+import { PathfindingService } from './service/pathfinding.service';
+import { TranslateModule, TranslateService } from '@ngx-translate/core';
+
+// Define an enum for node types that can be placed by the user
+enum NodeType {
+ Start = 'start',
+ End = 'end',
+ Wall = 'wall',
+ None = 'none'
+}
+
+@Component({
+ selector: 'app-pathfinding',
+ standalone: true,
+ imports: [CommonModule, MatButtonModule, MatButtonToggleModule, FormsModule, NgIf, TranslateModule],
+ templateUrl: './pathfinding.component.html',
+ styleUrls: ['./pathfinding.component.scss']
+})
+export class PathfindingComponent implements AfterViewInit {
+
+ @ViewChild('gridCanvas', { static: true })
+ canvas!: ElementRef;
+ ctx!: CanvasRenderingContext2D;
+
+ grid: Node[][] = [];
+ startNode: Node | null = null;
+ endNode: Node | null = null;
+
+ isDrawing: boolean = false;
+ selectedNodeType: NodeType = NodeType.None; // Default to no selection
+ animationSpeed: number = 10; // milliseconds
+
+ readonly NodeType = NodeType; // Expose enum to template
+
+ constructor(private pathfindingService: PathfindingService,
+ private translate: TranslateService) {
+ }
+
+ ngAfterViewInit(): void {
+ this.ctx = this.canvas.nativeElement.getContext('2d') as CanvasRenderingContext2D;
+ this.canvas.nativeElement.width = GRID_COLS * NODE_SIZE;
+ this.canvas.nativeElement.height = GRID_ROWS * NODE_SIZE;
+ this.initializeGrid();
+ this.drawGrid();
+
+ // Add event listeners for mouse interactions
+ this.canvas.nativeElement.addEventListener('mousedown', this.onMouseDown.bind(this));
+ this.canvas.nativeElement.addEventListener('mousemove', this.onMouseMove.bind(this));
+ this.canvas.nativeElement.addEventListener('mouseup', this.onMouseUp.bind(this));
+ this.canvas.nativeElement.addEventListener('mouseleave', this.onMouseUp.bind(this)); // Stop drawing if mouse leaves canvas
+ }
+
+ initializeGrid(): void {
+ this.grid = [];
+ for (let row = 0; row < GRID_ROWS; row++) {
+ const currentRow: Node[] = [];
+ for (let col = 0; col < GRID_COLS; col++) {
+ currentRow.push({
+ row,
+ col,
+ isStart: false,
+ isEnd: false,
+ isWall: false,
+ isVisited: false,
+ isPath: false,
+ distance: Infinity,
+ previousNode: null,
+ fScore: 0
+ });
+ }
+ this.grid.push(currentRow);
+ }
+
+ // Set default start and end nodes
+ this.startNode = this.grid[Math.floor(GRID_ROWS / 2)][Math.floor(GRID_COLS / 4)];
+ this.startNode.isStart = true;
+ this.endNode = this.grid[Math.floor(GRID_ROWS / 2)][Math.floor(3 * GRID_COLS / 4)];
+ this.endNode.isEnd = true;
+ }
+
+ drawGrid(): void {
+ if (!this.ctx) {
+ return;
+ }
+
+ this.ctx.clearRect(0, 0, this.canvas.nativeElement.width, this.canvas.nativeElement.height);
+
+ for (let row = 0; row < GRID_ROWS; row++) {
+ for (let col = 0; col < GRID_COLS; col++) {
+ const node = this.grid[row][col];
+ let color = 'lightgray'; // Default color
+
+ if (node.isStart) {
+ color = 'green';
+ } else if (node.isEnd) {
+ color = 'red';
+ } else if (node.isPath) {
+ color = 'gold';
+ } else if (node.isVisited) {
+ color = 'skyblue';
+ } else if (node.isWall) {
+ color = 'black';
+ }
+
+ this.ctx.fillStyle = color;
+ this.ctx.fillRect(col * NODE_SIZE, row * NODE_SIZE, NODE_SIZE, NODE_SIZE);
+ this.ctx.strokeStyle = '#ccc';
+ this.ctx.strokeRect(col * NODE_SIZE, row * NODE_SIZE, NODE_SIZE, NODE_SIZE);
+ }
+ }
+ }
+
+ onMouseDown(event: MouseEvent): void {
+ this.isDrawing = true;
+ this.placeNode(event);
+ }
+
+ onMouseMove(event: MouseEvent): void {
+ if (this.isDrawing) {
+ this.placeNode(event);
+ }
+ }
+
+ onMouseUp(event: MouseEvent): void {
+ this.isDrawing = false;
+ }
+
+ placeNode(event: MouseEvent): void {
+ const rect = this.canvas.nativeElement.getBoundingClientRect();
+ const x = event.clientX - rect.left;
+ const y = event.clientY - rect.top;
+
+ const col = Math.floor(x / NODE_SIZE);
+ const row = Math.floor(y / NODE_SIZE);
+
+ if (row < 0 || row >= GRID_ROWS || col < 0 || col >= GRID_COLS) {
+ return;
+ }
+
+ const node = this.grid[row][col];
+
+ switch (this.selectedNodeType) {
+ case NodeType.Start:
+ if (!node.isEnd && !node.isWall) {
+ if (this.startNode) {
+ this.startNode.isStart = false;
+ }
+ node.isStart = true;
+ this.startNode = node;
+ }
+ break;
+ case NodeType.End:
+ if (!node.isStart && !node.isWall) {
+ if (this.endNode) {
+ this.endNode.isEnd = false;
+ }
+ node.isEnd = true;
+ this.endNode = node;
+ }
+ break;
+ case NodeType.Wall:
+ if (!node.isStart && !node.isEnd) {
+ node.isWall = !node.isWall;
+ }
+ break;
+ case NodeType.None:
+ // Clear a node
+ if (node.isStart) {
+ node.isStart = false;
+ this.startNode = null;
+ } else if (node.isEnd) {
+ node.isEnd = false;
+ this.endNode = null;
+ } else if (node.isWall) {
+ node.isWall = false;
+ }
+ break;
+ }
+ this.drawGrid();
+ }
+
+ visualizeDijkstra(): void {
+ if (!this.startNode || !this.endNode) {
+ alert(this.translate.instant('PATHFINDING.ALERT.START_END_NODES'));
+ return;
+ }
+ this.clearPath();
+ const gridCopy = this.getCleanGrid();
+ const { visitedNodesInOrder, nodesInShortestPathOrder } = this.pathfindingService.dijkstra(gridCopy,
+ gridCopy[this.startNode.row][this.startNode.col],
+ gridCopy[this.endNode.row][this.endNode.col]
+ );
+ this.animateAlgorithm(visitedNodesInOrder, nodesInShortestPathOrder);
+ }
+
+ visualizeAStar(): void {
+ if (!this.startNode || !this.endNode) {
+ alert(this.translate.instant('PATHFINDING.ALERT.START_END_NODES'));
+ return;
+ }
+ this.clearPath();
+ const gridCopy = this.getCleanGrid();
+ const { visitedNodesInOrder, nodesInShortestPathOrder } = this.pathfindingService.aStar(gridCopy,
+ gridCopy[this.startNode.row][this.startNode.col],
+ gridCopy[this.endNode.row][this.endNode.col]
+ );
+ this.animateAlgorithm(visitedNodesInOrder, nodesInShortestPathOrder);
+ }
+
+ animateAlgorithm(visitedNodesInOrder: Node[], nodesInShortestPathOrder: Node[]): void {
+ for (let i = 0; i <= visitedNodesInOrder.length; i++) {
+ if (i === visitedNodesInOrder.length) {
+ setTimeout(() => {
+ this.animateShortestPath(nodesInShortestPathOrder);
+ }, this.animationSpeed * i);
+ return;
+ }
+ const node = visitedNodesInOrder[i];
+ setTimeout(() => {
+ if (!node.isStart && !node.isEnd) {
+ node.isVisited = true;
+ this.drawGrid();
+ }
+ }, this.animationSpeed * i);
+ }
+ }
+
+ animateShortestPath(nodesInShortestPathOrder: Node[]): void {
+ for (let i = 0; i < nodesInShortestPathOrder.length; i++) {
+ const node = nodesInShortestPathOrder[i];
+ setTimeout(() => {
+ if (!node.isStart && !node.isEnd) {
+ node.isPath = true;
+ this.drawGrid();
+ }
+ }, 50 * i); // Speed up path animation
+ }
+ }
+
+ clearBoard(): void {
+ this.initializeGrid();
+ this.drawGrid();
+ }
+
+ clearPath(): void {
+ for (let row = 0; row < GRID_ROWS; row++) {
+ for (let col = 0; col < GRID_COLS; col++) {
+ const node = this.grid[row][col];
+ node.isVisited = false;
+ node.isPath = false;
+ node.distance = Infinity;
+ node.previousNode = null;
+ }
+ }
+ this.drawGrid();
+ }
+
+ // Helper to get a deep copy of the grid for algorithm execution
+ private getCleanGrid(): Node[][] {
+ const newGrid: Node[][] = [];
+ for (let row = 0; row < GRID_ROWS; row++) {
+ const currentRow: Node[] = [];
+ for (let col = 0; col < GRID_COLS; col++) {
+ const node = this.grid[row][col];
+ currentRow.push({
+ ...node,
+ isVisited: false,
+ isPath: false,
+ distance: Infinity,
+ previousNode: null,
+ });
+ }
+ newGrid.push(currentRow);
+ }
+ return newGrid;
+ }
+}
diff --git a/src/app/pages/algorithms/pathfinding/pathfinding.models.ts b/src/app/pages/algorithms/pathfinding/pathfinding.models.ts
new file mode 100644
index 0000000..d55af22
--- /dev/null
+++ b/src/app/pages/algorithms/pathfinding/pathfinding.models.ts
@@ -0,0 +1,16 @@
+export interface Node {
+ row: number;
+ col: number;
+ isStart: boolean;
+ isEnd: boolean;
+ isWall: boolean;
+ isVisited: boolean;
+ isPath: boolean;
+ distance: number;
+ previousNode: Node | null;
+ fScore: number;
+}
+
+export const GRID_ROWS = 25;
+export const GRID_COLS = 50;
+export const NODE_SIZE = 20; // in pixels
diff --git a/src/app/pages/algorithms/pathfinding/service/pathfinding.service.ts b/src/app/pages/algorithms/pathfinding/service/pathfinding.service.ts
new file mode 100644
index 0000000..dd19f39
--- /dev/null
+++ b/src/app/pages/algorithms/pathfinding/service/pathfinding.service.ts
@@ -0,0 +1,146 @@
+import { Injectable } from '@angular/core';
+import { Node, GRID_ROWS, GRID_COLS } from '../pathfinding.models';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class PathfindingService {
+
+ constructor() { }
+
+ // Helper function to get all unvisited neighbors of a given node
+ getUnvisitedNeighbors(node: Node, grid: Node[][]): Node[] {
+ const neighbors: Node[] = [];
+ const { col, row } = node;
+
+ if (row > 0) neighbors.push(grid[row - 1][col]);
+ if (row < GRID_ROWS - 1) neighbors.push(grid[row + 1][col]);
+ if (col > 0) neighbors.push(grid[row][col - 1]);
+ if (col < GRID_COLS - 1) neighbors.push(grid[row][col + 1]);
+
+ return neighbors.filter(neighbor => !neighbor.isVisited && !neighbor.isWall);
+ }
+
+ // Helper function to get the nodes in the shortest path
+ getNodesInShortestPath(endNode: Node): Node[] {
+ const shortestPathNodes: Node[] = [];
+ let currentNode: Node | null = endNode;
+ while (currentNode !== null) {
+ shortestPathNodes.unshift(currentNode);
+ currentNode = currentNode.previousNode;
+ }
+ return shortestPathNodes;
+ }
+
+ // Dijkstra's Algorithm
+ dijkstra(grid: Node[][], startNode: Node, endNode: Node): { visitedNodesInOrder: Node[], nodesInShortestPathOrder: Node[] } {
+ const visitedNodesInOrder: Node[] = [];
+ startNode.distance = 0;
+ const unvisitedNodes: Node[] = this.getAllNodes(grid);
+
+ while (!!unvisitedNodes.length) {
+ this.sortNodesByDistance(unvisitedNodes);
+ const closestNode = unvisitedNodes.shift() as Node;
+
+ // If we encounter a wall, skip it
+ if (closestNode.isWall) continue;
+
+ // If the closest node is at an infinite distance, we're trapped
+ if (closestNode.distance === Infinity) return { visitedNodesInOrder, nodesInShortestPathOrder: [] };
+
+ closestNode.isVisited = true;
+ visitedNodesInOrder.push(closestNode);
+
+ if (closestNode === endNode) return { visitedNodesInOrder, nodesInShortestPathOrder: this.getNodesInShortestPath(endNode) };
+
+ this.updateUnvisitedNeighbors(closestNode, grid);
+ }
+
+ return { visitedNodesInOrder, nodesInShortestPathOrder: [] };
+ }
+
+ private sortNodesByDistance(unvisitedNodes: Node[]): void {
+ unvisitedNodes.sort((nodeA, nodeB) => nodeA.distance - nodeB.distance);
+ }
+
+ private updateUnvisitedNeighbors(node: Node, grid: Node[][]): void {
+ const unvisitedNeighbors = this.getUnvisitedNeighbors(node, grid);
+ for (const neighbor of unvisitedNeighbors) {
+ neighbor.distance = node.distance + 1;
+ neighbor.previousNode = node;
+ }
+ }
+
+ // A* Search Algorithm
+ aStar(grid: Node[][], startNode: Node, endNode: Node): { visitedNodesInOrder: Node[], nodesInShortestPathOrder: Node[] } {
+ const visitedNodesInOrder: Node[] = [];
+ startNode.distance = 0;
+ // hueristic distance
+ startNode['distance'] = this.calculateHeuristic(startNode, endNode);
+ // fScore = gScore + hScore
+ startNode['fScore'] = startNode.distance + startNode['distance'];
+
+ const openSet: Node[] = [startNode];
+ const allNodes = this.getAllNodes(grid);
+
+ // Initialize all nodes' fScore to infinity except for the startNode
+ for (const node of allNodes) {
+ if (node !== startNode) {
+ node['fScore'] = Infinity;
+ node.distance = Infinity; // gScore
+ }
+ }
+
+
+ while (openSet.length > 0) {
+ openSet.sort((nodeA, nodeB) => nodeA['fScore'] - nodeB['fScore']);
+ const currentNode = openSet.shift() as Node;
+
+ if (currentNode.isWall) continue;
+
+ // If the closest node is at an infinite distance, we're trapped
+ if (currentNode.distance === Infinity) return { visitedNodesInOrder, nodesInShortestPathOrder: [] };
+
+
+ currentNode.isVisited = true;
+ visitedNodesInOrder.push(currentNode);
+
+ if (currentNode === endNode) {
+ return { visitedNodesInOrder, nodesInShortestPathOrder: this.getNodesInShortestPath(endNode) };
+ }
+
+ const neighbors = this.getUnvisitedNeighbors(currentNode, grid);
+ for (const neighbor of neighbors) {
+ const tentativeGScore = currentNode.distance + 1; // Distance from start to neighbor
+
+ if (tentativeGScore < neighbor.distance) {
+ neighbor.previousNode = currentNode;
+ neighbor.distance = tentativeGScore;
+ neighbor['distance'] = this.calculateHeuristic(neighbor, endNode);
+ neighbor['fScore'] = neighbor.distance + neighbor['distance'];
+
+ if (!openSet.includes(neighbor)) {
+ openSet.push(neighbor);
+ }
+ }
+ }
+ }
+
+ return { visitedNodesInOrder, nodesInShortestPathOrder: [] };
+ }
+
+ private calculateHeuristic(node: Node, endNode: Node): number {
+ // Manhattan distance heuristic
+ return Math.abs(node.row - endNode.row) + Math.abs(node.col - endNode.col);
+ }
+
+ private getAllNodes(grid: Node[][]): Node[] {
+ const nodes: Node[] = [];
+ for (const row of grid) {
+ for (const node of row) {
+ nodes.push(node);
+ }
+ }
+ return nodes;
+ }
+}
diff --git a/src/app/pages/algorithms/service/algorithms.service.ts b/src/app/pages/algorithms/service/algorithms.service.ts
new file mode 100644
index 0000000..c84b802
--- /dev/null
+++ b/src/app/pages/algorithms/service/algorithms.service.ts
@@ -0,0 +1,28 @@
+import { Injectable } from '@angular/core';
+import { AlgorithmCategory } from '../models/algorithm-category';
+import { Observable, of } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AlgorithmsService {
+
+ private categories: AlgorithmCategory[] = [
+ {
+ id: 'pathfinding',
+ title: 'Pfadfindungsalgorithmen',
+ description: 'Vergleich von Pfadfindungsalgorithmen wie Dijkstra und A*.',
+ routerLink: 'pathfinding'
+ },
+ // {
+ // id: 'sorting',
+ // title: 'Sortieralgorithmen',
+ // description: 'Visualisierung von Sortieralgorithmen wie Bubble Sort, Merge Sort und Quick Sort.',
+ // routerLink: 'sorting'
+ // }
+ ];
+
+ getCategories(): Observable {
+ return of(this.categories);
+ }
+}
diff --git a/src/app/pages/hobbies/hobbies.component.html b/src/app/pages/hobbies/hobbies.component.html
deleted file mode 100644
index 3e705ce..0000000
--- a/src/app/pages/hobbies/hobbies.component.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
- > Work in progress
-
diff --git a/src/app/pages/hobbies/hobbies.component.scss b/src/app/pages/hobbies/hobbies.component.scss
deleted file mode 100644
index 07ff5e5..0000000
--- a/src/app/pages/hobbies/hobbies.component.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-.terminal-loader {
- font-family: monospace;
- font-size: 1.1rem;
- display: inline-flex;
- align-items: center;
-}
-
-.cursor {
- width: 10px;
- height: 1.1rem;
- background: var(--app-fg);
- margin-left: .25rem;
- animation: blink .8s infinite;
-}
-
-@keyframes blink {
- 0%, 50% { opacity: 1; }
- 51%, 100% { opacity: 0; }
-}
diff --git a/src/app/pages/hobbies/hobbies.component.ts b/src/app/pages/hobbies/hobbies.component.ts
deleted file mode 100644
index 8dfb207..0000000
--- a/src/app/pages/hobbies/hobbies.component.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { Component } from '@angular/core';
-
-@Component({
- selector: 'app-hobbies',
- imports: [],
- templateUrl: './hobbies.component.html',
- styleUrl: './hobbies.component.scss',
-})
-export class HobbiesComponent {
-
-}
diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json
index efc920a..0c61726 100644
--- a/src/assets/i18n/de.json
+++ b/src/assets/i18n/de.json
@@ -7,7 +7,7 @@
"ABOUT": "Über mich",
"IMPRINT": "Impressum",
"PROJECTS": "Projekte",
- "HOBBY": "Hobbies",
+ "ALGORITHMS": "Algorithmen",
"SETTINGS": "Einstellungen",
"LANGUAGE": "Sprache",
"APPEARANCE": "Darstellung"
@@ -292,5 +292,21 @@
"PARAGRAPH": "Angaben gemäß § 5 DDG",
"COUNTRY": "Deutschland",
"CONTACT": "Kontakt"
+ },
+ "PATHFINDING": {
+ "TITLE": "Pfadfindungsalgorithmen",
+ "START_NODE": "Startknoten",
+ "END_NODE": "Endknoten",
+ "WALL": "Wand",
+ "CLEAR_NODE": "Löschen",
+ "DIJKSTRA": "Dijkstra",
+ "ASTAR": "A*",
+ "CLEAR_BOARD": "Board leeren",
+ "CLEAR_PATH": "Pfad löschen",
+ "VISITED": "Besucht",
+ "PATH": "Pfad",
+ "ALERT": {
+ "START_END_NODES": "Bitte wählen Sie einen Start- und Endknoten aus, bevor Sie den Algorithmus starten."
+ }
}
}
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 81d2fb2..d8c5241 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -7,7 +7,7 @@
"ABOUT": "About me",
"IMPRINT": "Impressum",
"PROJECTS": "Projects",
- "HOBBY": "Hobby's",
+ "ALGORITHMS": "Algorithms",
"SETTINGS": "Settings",
"LANGUAGE": "Language",
"APPEARANCE": "Appearance"
@@ -292,5 +292,21 @@
"PARAGRAPH": "Information pursuant to Section 5 DDG",
"COUNTRY": "Germany",
"CONTACT": "Contact"
+ },
+ "PATHFINDING": {
+ "TITLE": "Pathfinding Algorithms",
+ "START_NODE": "Start Node",
+ "END_NODE": "End Node",
+ "WALL": "Wall",
+ "CLEAR_NODE": "Clear",
+ "DIJKSTRA": "Dijkstra",
+ "ASTAR": "A*",
+ "CLEAR_BOARD": "Clear Board",
+ "CLEAR_PATH": "Clear Path",
+ "VISITED": "Visited",
+ "PATH": "Path",
+ "ALERT": {
+ "START_END_NODES": "Please select a start and end node before running the algorithm."
+ }
}
}