Skip to content
Snippets Groups Projects
Commit f15cef80 authored by Daniel's avatar Daniel
Browse files

BubbleSort finished

parents
No related branches found
No related tags found
No related merge requests found
Pipeline #223084 passed
# The Docker image that will be used to build your app
image: node
# Functions that should be executed before the build script is run
before_script:
- npm install
pages:
script:
- npm run build
artifacts:
paths:
# The folder that contains the files to be exposed at the Page URL
- public
rules:
# This ensures that only pushes to the default branch will trigger
# a pages deploy
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
FROM node:18-alpine
WORKDIR /app
RUN npm create vite@latest sorting-visualizer -- --template react &&\
apk update && apk add --no-cache bash findutils &&\
rm -rf /var/cache/apk/*
WORKDIR /app/sorting-visualizer
RUN rm -rf src/App.css src/App.jsx src/assets src/index.css
COPY package-lock.json .
COPY package.json .
RUN npm install
COPY src src/
COPY index.html .
COPY vite.config.js .
# port 5173
EXPOSE 5173
#Start
CMD ["npm", "run", "dev", "--", "--host"]
# Sorting Visualizer
Sorting Visualizer demonstrates how Bubble Sort works through an interactive graphical interface.
---
![unsorted](unsorted.png)
![sorted](sorted.png)
[Check it out]()
services:
app:
image: sorting-visualizer
container_name: Sorting-Visualizer
ports:
- 127.0.0.1:5173:5173
volumes:
- ./src/:/app/sorting-visualizer/src/
- ./package-lock.json:/app/sorting-visualizer/package-lock.json
- ./package.json:/app/sorting-visualizer/package.json
networks:
- my-network
networks:
my-network:
driver: bridge
import js from '@eslint/js'
import globals from 'globals'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📊</text></svg>">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sorting-Visualizer</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
This diff is collapsed.
{
"name": "sorting-visualizer",
"homepage": "https://stdarunte.h-da.io/sorting-visualizer",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.3.1",
"react-bootstrap-range-slider": "^3.0.8",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@eslint/js": "^9.9.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"eslint": "^9.9.0",
"eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0",
"vite": "^5.4.1"
}
}
sorted.png

61.2 KiB

async function BubbleSort(EingangsArray, updateBars, setColor){
const len = EingangsArray.length;
for(let i = 0; i< len -1; ++i){
for(let k=0; k< len -1-i; k++){
let tmp;
if (k == len -2-i){
setColor([(len-1-i)]);
}
if(EingangsArray[k] > EingangsArray[k+1]){
tmp = EingangsArray[k];
EingangsArray[k] = EingangsArray[k+1];
EingangsArray[k+1] = tmp;
}
updateBars([...EingangsArray]);
await new Promise(resolve => setTimeout(resolve, 40)); // Pause für Animation
}
}
setColor([(len-len)]);
console.log(EingangsArray);
return EingangsArray;
}
export default BubbleSort;
\ No newline at end of file
body{
margin: 0;
}
.Container {
display: flex;
flex-direction: column;
align-items: center;
}
.bar {
background-color: blue;
display: inline-block;
height: 100px;
flex: 1 1 20px;
min-width: 2px;
}
.sorted {
background-color: deeppink;
animation: ScaleAnimation 0.5s ease-in-out;
}
.finished {
background-color: lawngreen;
flex: 1 1 20px;
min-width: 2px;
margin: 2px;
display: inline-block;
animation: GreenScaleAnimation 1s ease-in;
}
.range-slider {
margin-top: -4px;
padding: 0 px;
}
.ToolBar {
height: 50px;
width: 100%;
background: aquamarine;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.DivArray{
transform: rotate(180deg);
transform: scaleY(-1);
display: flex;
flex-wrap: nowrap;
justify-content: center;
gap: 2px;
width: 90%;
margin-top: 5px;
}
@keyframes ScaleAnimation {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
}
}
@keyframes GreenScaleAnimation {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
import React, {useState, useEffect, useRef} from 'react';
import './SortingVisualizer.css'
import BubbleSort from "./BubbleSort";
import RangeSlider from 'react-bootstrap-range-slider';
import 'react-bootstrap-range-slider/dist/react-bootstrap-range-slider.css';
function SortingVisualizer() {
const moduloFive = ((window.innerWidth / 22)).toFixed(0) % 5;
const monitorSize = (window.innerWidth / 22).toFixed(0) - moduloFive;
const [BarNumber, setBarNumber] = useState(monitorSize);
const [bars, setbars] = useState(() => generateArray(BarNumber));
const [sorting, setSorting] = useState(false);
const [alreadySorted, setAlreadySorted] = useState();
const [isSorted, setIsSorted] = useState(false);
console.log((window.innerWidth / 23).toFixed(0) - moduloFive);
const SliderWithInputFormControl = () => {
const [sliderValue_intern, setSliderValue_intern] = useState(BarNumber);
return (
<RangeSlider
value={sliderValue_intern}
step={5}
max={100}
min={5}
disabled={sorting}
onChange={changeEvent => setSliderValue_intern(Number(changeEvent.target.value))}
onAfterChange={() => setBarNumber(sliderValue_intern)}
/>
);
};
useEffect(() => {
resetBars();
}, [BarNumber]);
function getRandomArbitrary(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function generateArray(numberBars) {
return Array.from({length: numberBars}, () => getRandomArbitrary(50, 300));
console.log('bar length' + bars.length);
let ColoredBars = document.getElementsByClassName('sorted');
console.log(ColoredBars);
while (ColoredBars.length > 0) {
ColoredBars[0].className = 'bar';
}
}
async function handleSorting() {
if (sorting) return;
setSorting(true);
await BubbleSort(bars, setbars, setAlreadySorted);
setSorting(false);
}
function resetBars() {
setAlreadySorted(1000);
setbars(generateArray(BarNumber));
let ColoredBars = document.getElementsByClassName('sorted');
document.getElementById('startButton').innerText = 'Sort';
while (ColoredBars.length > 0) {
ColoredBars[0].className = 'bar';
}
setIsSorted(false);
}
function finishAnimation() {
let ColoredBars = document.getElementsByClassName('sorted');
while (ColoredBars.length > 0) {
ColoredBars[0].className = 'finished';
}
}
function handleButton() {
if (!sorting && !isSorted) {
setAlreadySorted(1000);
handleSorting();
} else if (isSorted) {
resetBars();
}
}
useEffect(() => {
if (alreadySorted == 0) {
setIsSorted(true);
finishAnimation();
document.getElementById('startButton').innerText = 'Generate new Bars';
}
}, [alreadySorted]);
return (
<>
<div className='Container'>
<div className='ToolBar'>
<SliderWithInputFormControl style={{className: 'range-slider'}}/>
<input type='number' max={100} min={0}
onChange={changeEvent => {
let value = Number(changeEvent.target.value);
if (value > 100) value = 100;
if (value < 5) value = 5;
setBarNumber(value);
}} defaultValue={BarNumber}
value={BarNumber} style={{width: '50px', margin: '10px'}}/>
<button id='startButton' style={{margin: '20px'}} disabled={sorting} onClick={() => {
handleButton()
}}>{sorting ? 'Sorting...' : 'Sort'}</button>
</div>
<div className='DivArray'>
{bars.map((height, index) => (<div key={index} data-key={index}
className={`bar + ${alreadySorted <= index ? 'sorted' : ''}`}
style={{height: `${height}px`}}></div>))}
</div>
</div>
</>
)
};
export default SortingVisualizer;
\ No newline at end of file
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import SortingVisualizer from './SortingVisualizer.jsx'
createRoot(document.getElementById('root')).render(
<StrictMode>
<SortingVisualizer />
</StrictMode>,
)
unsorted.png

61.5 KiB

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
base: '/',
plugins: [react()],
build: {
outDir: 'public',
assetsDir: 'assets',
},
})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment