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

BubbleSort finished

parents
Branches
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