feature/sortingAlgorithm #8

Merged
lobo merged 5 commits from feature/sortingAlgorithm into main 2026-02-04 14:20:00 +01:00
8 changed files with 160 additions and 125 deletions
Showing only changes of commit a10f62f2dd - Show all commits

View File

@@ -1,87 +1,89 @@
<div class="container">
<h1>{{ 'PATHFINDING.TITLE' | translate }}</h1>
<mat-card class="container">
<mat-card-header>
<mat-card-title>{{ 'PATHFINDING.TITLE' | translate }}</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="algo-info">
<h3>{{ 'PATHFINDING.EXPLANATION.TITLE' | translate }}</h3>
<div class="algo-info">
<h3>{{ 'PATHFINDING.EXPLANATION.TITLE' | translate }}</h3>
<p>
<strong>Dijkstra</strong> {{ 'PATHFINDING.EXPLANATION.DIJKSTRA_EXPLANATION' | translate }}
<a href="{{UrlConstants.DIJKSTRA_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
</p>
<p>
<strong>Dijkstra</strong> {{ 'PATHFINDING.EXPLANATION.DIJKSTRA_EXPLANATION' | translate }}
<a href="{{UrlConstants.DIJKSTRA_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
</p>
<p>
<strong>A*</strong> {{ 'PATHFINDING.EXPLANATION.ASTAR_EXPLANATION' | translate}}
<a href="{{UrlConstants.ASTAR_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
</p>
<p>
<strong>A*</strong> {{ 'PATHFINDING.EXPLANATION.ASTAR_EXPLANATION' | translate}}
<a href="{{UrlConstants.ASTAR_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
</p>
<p>
<strong>{{ 'PATHFINDING.EXPLANATION.NOTE' | translate}}</strong> {{ 'PATHFINDING.EXPLANATION.DISCLAIMER' | translate}}
</p>
</div>
<div class="controls-container">
<div class="controls">
<button matButton="filled" (click)="visualizeDijkstra()">{{ 'PATHFINDING.DIJKSTRA' | translate }}</button>
<button matButton="filled" (click)="visualizeAStar()">{{ 'PATHFINDING.ASTAR' | translate }}</button>
</div>
<div class="controls">
<button matButton="filled" (click)="normalCase()">{{ 'PATHFINDING.NORMAL_CASE' | translate }}</button>
<button matButton="filled" (click)="edgeCase()">{{ 'PATHFINDING.EDGE_CASE' | translate }}</button>
<button matButton="filled" (click)="clearBoard()">{{ 'PATHFINDING.CLEAR_BOARD' | translate }}</button>
<p>
<strong>{{ 'PATHFINDING.EXPLANATION.NOTE' | translate}}</strong> {{ 'PATHFINDING.EXPLANATION.DISCLAIMER' | translate}}
</p>
</div>
<div class="controls">
<mat-button-toggle-group [(ngModel)]="selectedNodeType" aria-label="Node Type Selection">
<mat-button-toggle [value]="NodeType.Start">{{ 'PATHFINDING.START_NODE' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.End">{{ 'PATHFINDING.END_NODE' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.Wall">{{ 'PATHFINDING.WALL' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.None">{{ 'PATHFINDING.CLEAR_NODE' | translate }}</mat-button-toggle>
</mat-button-toggle-group>
</div>
<div class="controls-container">
<div class="controls">
<button matButton="filled" (click)="visualizeDijkstra()">{{ 'PATHFINDING.DIJKSTRA' | translate }}</button>
<button matButton="filled" (click)="visualizeAStar()">{{ 'PATHFINDING.ASTAR' | translate }}</button>
</div>
<div class="controls">
<button matButton="filled" (click)="normalCase()">{{ 'PATHFINDING.NORMAL_CASE' | translate }}</button>
<button matButton="filled" (click)="edgeCase()">{{ 'PATHFINDING.EDGE_CASE' | translate }}</button>
<button matButton="filled" (click)="clearBoard()">{{ 'PATHFINDING.CLEAR_BOARD' | translate }}</button>
</div>
<div class="controls">
<div class="grid-size">
<mat-form-field appearance="outline" class="grid-field">
<mat-label>{{ 'ALGORITHM.PATHFINDING.GRID_HEIGHT' | translate }}</mat-label>
<input
matInput
type="number"
[min]="MIN_GRID_SIZE"
[max]="MAX_GRID_SIZE"
[(ngModel)]="gridRows"
(blur)="applyGridSize()"
(keyup.enter)="applyGridSize()"
/>
</mat-form-field>
<div class="controls">
<mat-button-toggle-group [(ngModel)]="selectedNodeType" aria-label="Node Type Selection">
<mat-button-toggle [value]="NodeType.Start">{{ 'PATHFINDING.START_NODE' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.End">{{ 'PATHFINDING.END_NODE' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.Wall">{{ 'PATHFINDING.WALL' | translate }}</mat-button-toggle>
<mat-button-toggle [value]="NodeType.None">{{ 'PATHFINDING.CLEAR_NODE' | translate }}</mat-button-toggle>
</mat-button-toggle-group>
</div>
<mat-form-field appearance="outline" class="grid-field">
<mat-label>{{ 'ALGORITHM.PATHFINDING.GRID_WIDTH' | translate }}</mat-label>
<input
matInput
type="number"
[min]="MIN_GRID_SIZE"
[max]="MAX_GRID_SIZE"
[(ngModel)]="gridCols"
(blur)="applyGridSize()"
(keyup.enter)="applyGridSize()"
/>
</mat-form-field>
<div class="controls">
<div class="grid-size">
<mat-form-field appearance="outline" class="grid-field">
<mat-label>{{ 'PATHFINDING.GRID_HEIGHT' | translate }}</mat-label>
<input
matInput
type="number"
[min]="MIN_GRID_SIZE"
[max]="MAX_GRID_SIZE"
[(ngModel)]="gridRows"
(blur)="applyGridSize()"
(keyup.enter)="applyGridSize()"
/>
</mat-form-field>
<mat-form-field appearance="outline" class="grid-field">
<mat-label>{{ 'PATHFINDING.GRID_WIDTH' | translate }}</mat-label>
<input
matInput
type="number"
[min]="MIN_GRID_SIZE"
[max]="MAX_GRID_SIZE"
[(ngModel)]="gridCols"
(blur)="applyGridSize()"
(keyup.enter)="applyGridSize()"
/>
</mat-form-field>
</div>
</div>
<div class="legend">
<span><span class="legend-color start"></span> {{ 'PATHFINDING.START_NODE' | translate }}</span>
<span><span class="legend-color end"></span> {{ 'PATHFINDING.END_NODE' | translate }}</span>
<span><span class="legend-color wall"></span> {{ 'PATHFINDING.WALL' | translate }}</span>
<span><span class="legend-color visited"></span> {{ 'PATHFINDING.VISITED' | translate }}</span>
<span><span class="legend-color path"></span> {{ 'PATHFINDING.PATH' | translate }}</span>
</div>
</div>
<div class="legend">
<span><span class="legend-color start"></span> {{ 'PATHFINDING.START_NODE' | translate }}</span>
<span><span class="legend-color end"></span> {{ 'PATHFINDING.END_NODE' | translate }}</span>
<span><span class="legend-color wall"></span> {{ 'PATHFINDING.WALL' | translate }}</span>
<span><span class="legend-color visited"></span> {{ 'PATHFINDING.VISITED' | translate }}</span>
<span><span class="legend-color path"></span> {{ 'PATHFINDING.PATH' | translate }}</span>
<div class="results-container">
<p>{{ 'PATHFINDING.PATH_LENGTH' | translate }}: {{ pathLength }}</p>
<p>{{ 'PATHFINDING.EXECUTION_TIME' | translate }}: {{ executionTime | number:'1.2-2' }} ms</p>
</div>
</div>
<div class="results-container">
<p>{{ 'PATHFINDING.PATH_LENGTH' | translate }}: {{ pathLength }}</p>
<p>{{ 'PATHFINDING.EXECUTION_TIME' | translate }}: {{ executionTime | number:'1.2-2' }} ms</p>
</div>
<canvas #gridCanvas></canvas>
</div>
<canvas #gridCanvas></canvas>
</mat-card-content>

View File

@@ -2,25 +2,6 @@
padding: 2rem;
}
.algo-info {
margin: 0 0 1rem 0;
padding: 0.75rem 1rem;
border: 1px solid #ddd;
border-radius: 8px;
h3 {
margin: 0 0 0.5rem 0;
}
p {
margin: 0.5rem 0;
}
a {
margin-left: 0.25rem;
}
}
.controls-container {
display: flex;
flex-direction: column;

View File

@@ -12,6 +12,7 @@ import {TranslateModule, TranslateService} from '@ngx-translate/core';
import {DEFAULT_GRID_COLS, DEFAULT_GRID_ROWS, MAX_GRID_PX, MAX_GRID_SIZE, MIN_GRID_SIZE, Node} from './pathfinding.models';
import {PathfindingService} from './service/pathfinding.service';
import {UrlConstants} from '../../../constants/UrlConstants';
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from '@angular/material/card';
enum NodeType {
Start = 'start',
@@ -32,7 +33,11 @@ interface GridPos { row: number; col: number }
MatButtonToggleModule,
MatFormFieldModule,
MatInputModule,
TranslateModule
TranslateModule,
MatCard,
MatCardHeader,
MatCardTitle,
MatCardContent
],
templateUrl: './pathfinding.component.html',
styleUrls: ['./pathfinding.component.scss']

View File

@@ -1,12 +1,29 @@
<div class="sorting-container">
<mat-card class="sorting-card">
<mat-card-header>
<mat-card-title>{{ 'ALGORITHM.SORTING.TITLE' | translate }}</mat-card-title>
<mat-card-title>{{ 'SORTING.TITLE' | translate }}</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="algo-info">
<h3>{{ 'SORTING.EXPLANATION.TITLE' | translate }}</h3>
<p>
<strong>Dijkstra</strong> {{ 'SORTING.EXPLANATION.DIJKSTRA_EXPLANATION' | translate }}
<a href="{{UrlConstants.DIJKSTRA_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
</p>
<p>
<strong>A*</strong> {{ 'SORTING.EXPLANATION.ASTAR_EXPLANATION' | translate}}
<a href="{{UrlConstants.ASTAR_WIKI}}" target="_blank" rel="noopener noreferrer">Wikipedia</a>
</p>
<p>
<strong>{{ 'SORTING.EXPLANATION.NOTE' | translate}}</strong> {{ 'SORTING.EXPLANATION.DISCLAIMER' | translate}}
</p>
</div>
<div class="controls-panel">
<mat-form-field appearance="fill">
<mat-label>{{ 'ALGORITHM.SORTING.ALGORITHM' | translate }}</mat-label>
<mat-label>{{ 'SORTING.ALGORITHM' | translate }}</mat-label>
<mat-select [(ngModel)]="selectedAlgorithm">
@for (algo of availableAlgorithms; track algo.value) {
<mat-option [value]="algo.value">{{ algo.name }}</mat-option>
@@ -15,7 +32,7 @@
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>{{ 'ALGORITHM.SORTING.ARRAY_SIZE' | translate }}</mat-label>
<mat-label>{{ 'SORTING.ARRAY_SIZE' | translate }}</mat-label>
<input
matInput
type="number"
@@ -29,18 +46,18 @@
</div>
<div class="controls-panel">
<button mat-raised-button color="primary" (click)="startSorting()">
<mat-icon>play_arrow</mat-icon> {{ 'ALGORITHM.SORTING.START' | translate }}
<mat-icon>play_arrow</mat-icon> {{ 'SORTING.START' | translate }}
</button>
<button mat-raised-button color="warn" (click)="resetSorting()">
<mat-icon>refresh</mat-icon> {{ 'ALGORITHM.SORTING.RESET' | translate }}
<mat-icon>refresh</mat-icon> {{ 'SORTING.RESET' | translate }}
</button>
<button mat-raised-button (click)="generateNewArray()">
<mat-icon>add_box</mat-icon> {{ 'ALGORITHM.SORTING.GENERATE_NEW_ARRAY' | translate }}
<mat-icon>add_box</mat-icon> {{ 'SORTING.GENERATE_NEW_ARRAY' | translate }}
</button>
</div>
<div class="info-panel">
<p>{{ 'ALGORITHM.SORTING.EXECUTION_TIME' | translate }}: {{ executionTime }} ms</p>
<p>{{ 'SORTING.EXECUTION_TIME' | translate }}: {{ executionTime }} ms</p>
</div>
<div class="visualization-area">
@for (item of sortArray; track $index) {

View File

@@ -10,6 +10,7 @@ import { SortingService } from './service/sorting.service';
import {SortData, SortSnapshot} from './sorting.models';
import { FormsModule } from '@angular/forms';
import {MatInput} from '@angular/material/input';
import {UrlConstants} from '../../../constants/UrlConstants';
@Component({
selector: 'app-sorting',
standalone: true,
@@ -137,4 +138,6 @@ export class SortingComponent implements OnInit {
this.stopAnimations();
this.resetSortState();
}
protected readonly UrlConstants = UrlConstants;
}

View File

@@ -317,25 +317,29 @@
},
"ALERT": {
"START_END_NODES": "Bitte wählen Sie einen Start- und Endknoten aus, bevor Sie den Algorithmus starten."
}
},
"GRID_HEIGHT": "Höhe",
"GRID_WIDTH": "Beite"
},
"SORTING": {
"TITLE": "Sortieralgorithmen",
"ALGORITHM": "Algorithmen",
"START": "Sortierung starten",
"RESET": "Zurücksetzen",
"GENERATE_NEW_ARRAY": "Neues Array generieren",
"EXECUTION_TIME": "Ausführungszeit",
"ARRAY_SIZE": "Anzahl der Balken"
},
"ALGORITHM": {
"TITLE": "Algorithmen",
"PATHFINDING": {
"TITLE": "Wegfindung",
"DESCRIPTION": "Vergleich von Dijkstra vs. A*.",
"GRID_HEIGHT": "Höhe",
"GRID_WIDTH": "Beite"
"DESCRIPTION": "Vergleich von Dijkstra vs. A*."
},
"SORTING": {
"TITLE": "Sortieralgorithmen",
"DESCRIPTION": "Visualisierung verschiedener Sortieralgorithmen.",
"ALGORITHM": "Algorithmus",
"START": "Sortierung starten",
"RESET": "Zurücksetzen",
"GENERATE_NEW_ARRAY": "Neues Array generieren",
"EXECUTION_TIME": "Ausführungszeit",
"ARRAY_SIZE": "Anzahl der Balken"
"TITLE": "Sortierung",
"DESCRIPTION": "Visualisierung verschiedener Sortieralgorithmen."
}
}
}

View File

@@ -317,25 +317,28 @@
},
"ALERT": {
"START_END_NODES": "Please select a start and end node before running the algorithm."
}
},
"GRID_HEIGHT": "Height",
"GRID_WIDTH": "Width"
},
"SORTING": {
"TITLE": "Sorting Algorithms",
"ALGORITHM": "Algorithm",
"START": "Start Sorting",
"RESET": "Reset",
"GENERATE_NEW_ARRAY": "Generate New Array",
"EXECUTION_TIME": "Execution Time",
"ARRAY_SIZE": "Number of Bars"
},
"ALGORITHM": {
"TITLE": "Algorithms",
"PATHFINDING": {
"TITLE": "Pathfinding",
"DESCRIPTION": "Comparing of Dijkstra vs. A*.",
"GRID_HEIGHT": "Height",
"GRID_WIDTH": "Width"
"DESCRIPTION": "Comparing of Dijkstra vs. A*."
},
"SORTING": {
"TITLE": "Sorting Algorithms",
"TITLE": "Sorting",
"DESCRIPTION": "Visualizing various sorting algorithms.",
"ALGORITHM": "Algorithm",
"START": "Start Sorting",
"RESET": "Reset",
"GENERATE_NEW_ARRAY": "Generate New Array",
"EXECUTION_TIME": "Execution Time",
"ARRAY_SIZE": "Number of Bars"
}
}
}

View File

@@ -211,3 +211,23 @@ a {
height: 18px;
width: 18px;
}
// algos
.algo-info {
margin: 0 0 1rem 0;
padding: 0.75rem 1rem;
border: 1px solid #ddd;
border-radius: 8px;
h3 {
margin: 0 0 0.5rem 0;
}
p {
margin: 0.5rem 0;
}
a {
margin-left: 0.25rem;
}
}