diff --git a/gabau.github.io/src/components/games/SortVisualizer.tsx b/gabau.github.io/src/components/games/SortVisualizer.tsx new file mode 100644 index 0000000..9741797 --- /dev/null +++ b/gabau.github.io/src/components/games/SortVisualizer.tsx @@ -0,0 +1,59 @@ +import { Stage } from "@pixi/react"; +import { Graphics as GraphicComponent } from "@pixi/react"; +import { Color, Graphics } from "pixi.js"; +import { useCallback, useContext } from "react"; +import ThemeContext from "../../context/ThemeContext"; + +const sortingColor = { + dark: { + bgColor: new Color("black"), + barColor: new Color("green"), + selectedColor: new Color("white") + }, + light: { + bgColor: new Color("white"), + barColor: new Color("black"), + selectedColor: new Color("grey") + } +} + +const SortVisualizer: React.FC<{ + values: number[], + currentPosition: number, + width: number, + height: number, + base_offset?: number, + gap?: number +}> = ({ gap, values, width, height, currentPosition, base_offset }) => { + const {theme} = useContext(ThemeContext); + const currColors = theme === "dark" ? sortingColor.dark : sortingColor.light; + const m = base_offset ? base_offset : 100; + const draw = useCallback((g: Graphics) => { + g.clear(); + g.beginFill(currColors.bgColor); + g.drawRect(0, 0, width, height); + // render each of the values in the item + let max_val = values[0]; + let min_val = values[0]; + for (const v of values) { + max_val = Math.max(v, max_val); + min_val = Math.min(v, min_val); + } + const w = width / values.length; + + const gapWrapper = gap ? gap : 0.5 * w; + for (let i = 0; i < values.length; ++i) { + const perc = Math.round( (values[i] - min_val) / (max_val - min_val) * (height - m)) + m; + g.beginFill(currColors.barColor); + if (currentPosition === i) { + g.beginFill(currColors.selectedColor); + } + g.drawRect(i*w, height - perc, w - gapWrapper, perc); + } + }, [currColors.bgColor, currColors.barColor, currColors.selectedColor, width, height, values, gap, m, currentPosition]); + return + + +} + +export default SortVisualizer; \ No newline at end of file diff --git a/gabau.github.io/src/components/layouts/CenteredDivLayout.tsx b/gabau.github.io/src/components/layouts/CenteredDivLayout.tsx new file mode 100644 index 0000000..51f645a --- /dev/null +++ b/gabau.github.io/src/components/layouts/CenteredDivLayout.tsx @@ -0,0 +1,11 @@ + + +export default function CenteredDivLayout({ children }: { + children: JSX.Element | string +}) { + return
+
+ {children} +
+
+} diff --git a/gabau.github.io/src/pages/Playground.tsx b/gabau.github.io/src/pages/Playground.tsx index 2a93f1c..9d67359 100644 --- a/gabau.github.io/src/pages/Playground.tsx +++ b/gabau.github.io/src/pages/Playground.tsx @@ -1,5 +1,6 @@ import { Link } from "react-router-dom"; import TypeWriterHeader from "../components/TypeWriterHeader"; +import { playgroundRoutes } from "../routes/playground"; const PlayGroundCard = ({ title, @@ -29,33 +30,6 @@ const PlayGroundCard = ({ // }; // } -const playgrounds = [ - { - title: "Terminal", - description: "Simple terminal that runs in the browser", - link: "/play/terminal", - }, - { - title: "A Page", - description: "Just a page", - link: "/play/apage", - }, - { - title: "Repeating text", - description: "Simple repeating animation", - link: "/play/rotating", - }, - { - title: "Animated Sand", - description: "Simple sand falling in pixi.js", - link: "/play/sand", - }, - { - title: "Pong", - description: "Pong game", - link: "/play/pong", - }, -]; export default function PlayGround() { return ( @@ -63,13 +37,13 @@ export default function PlayGround() {

For the miscellaneous stuff

- {playgrounds.map((v) => { + {playgroundRoutes.map((v) => { return ( ); })} diff --git a/gabau.github.io/src/pages/fun/SortVisPage.tsx b/gabau.github.io/src/pages/fun/SortVisPage.tsx new file mode 100644 index 0000000..734028e --- /dev/null +++ b/gabau.github.io/src/pages/fun/SortVisPage.tsx @@ -0,0 +1,193 @@ +import { useEffect, useState } from "react"; +import SortVisualizer from "../../components/games/SortVisualizer"; +import CenteredDivLayout from "../../components/layouts/CenteredDivLayout"; + +// stores the states for partition sort +class PartitionSortState { + partitions: { start: number; end: number }[]; + currPos: number; + frontPointer: number; + start: number; + end: number; + constructor() { + this.partitions = []; + this.currPos = 0; + this.frontPointer = 0; + this.start = 0; + this.end = 0; + } + + swap(values: number[], i: number, j: number) { + if (i >= values.length || j >= values.length) return; + const tmp = values[i]; + values[i] = values[j]; + values[j] = tmp; + } + + getNextStep(values: number[]) { + if ( + this.currPos >= this.end || + this.frontPointer >= this.end || + this.start >= this.end + ) { + // push the current partitions onto the stack + if (this.start < this.end) { + if (this.frontPointer !== this.end) { + this.partitions.push({ + start: this.start, + end: this.frontPointer, + }); + } + if (this.start !== this.frontPointer + 1) { + this.partitions.push({ + start: this.frontPointer + 1, + end: this.end, + }); + } + } + + // console.log(values); + // return "finished" + // reset the position to the partitions + // Finshed sorting + if (this.partitions.length === 0) { + return "finished"; + } + this.currPos = this.partitions[0].start + 1; + this.frontPointer = this.partitions[0].start; + this.end = this.partitions[0].end; + this.start = this.frontPointer; + this.partitions = this.partitions.slice(1); + } + + // if (values[this.frontPointer] > values[this.frontPointer + 1]) { + // this.swap(values, this.frontPointer, this.frontPointer + 1); + // this.frontPointer += 1; + // this.currPos = Math.max(this.frontPointer + 1, this.currPos); + // return values; + // } + if (values[this.currPos] <= values[this.frontPointer]) { + this.swap(values, this.currPos, this.frontPointer + 1); + this.swap(values, this.frontPointer, this.frontPointer + 1); + this.frontPointer += 1; + } + this.currPos += 1; + return values; + } +} + +export default function SortVisPage() { + const [values, setValues] = useState([4, 0]); + const [partSort] = useState(new PartitionSortState()); + const [startAnim, setStartAnim] = useState(false); + const [currPosition, setCurrPosition] = useState(0); + const [arraySize, setArraySize] = useState(40); + const [animating, setAnimating] = useState(false); + const [intervalTime, setIntervalTime] = useState(10); + const [currTimeout, setCurrTimeout] = useState(null); + useEffect(() => { + setValues(Array.from({ length: 40 }, () => Math.floor(Math.random() * 40))); + }, []); + + useEffect(() => { + if (!startAnim) return; + partSort.start = 0; + partSort.end = values.length; + partSort.frontPointer = 0; + partSort.currPos = 1; + const f = () => { + if (!animating) return; + const r = partSort.getNextStep(values); + if (r === "finished") { + setAnimating(false); + return; + } + setCurrPosition(partSort.currPos); + setCurrTimeout(setTimeout(f, intervalTime)); + }; + const t = setTimeout(f, intervalTime); + return () => clearTimeout(t); + }, [partSort, startAnim, values, animating, intervalTime]); + + return ( + +
+
+
+ + + +
+ + setArraySize(e.target.value as unknown as number)} + className="rounded-lg bg-slate-200 dark:bg-slate-600 p-3 shadow my-5" + /> + setArraySize(e.target.value as unknown as number)} + className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" + /> + + + setIntervalTime(e.target.value as unknown as number)} + className="rounded-lg bg-slate-200 dark:bg-slate-600 p-3 shadow my-5" + /> + setIntervalTime(e.target.value as unknown as number)} + className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" + /> +
+ +
+
+ ); +} diff --git a/gabau.github.io/src/routes.tsx b/gabau.github.io/src/routes.tsx index 7284dbd..00e9f11 100644 --- a/gabau.github.io/src/routes.tsx +++ b/gabau.github.io/src/routes.tsx @@ -6,12 +6,7 @@ import About from "./pages/About"; import Chess from "./components/games/Chess"; import PlayGround from "./pages/Playground"; import NavBarWrapper from "./components/NavBarWrapper"; -import Terminal from "./components/Terminal"; -import TypeWriterHeader from "./components/TypeWriterHeader"; -import APage from "./pages/fun/APage"; -import RepeatingBannerPage from "./pages/fun/RepeatingBannerPage"; -import AnimatedSandPage from "./pages/fun/AnimatedSandPage"; -import PongPage from "./pages/fun/PongPage"; +import { playgroundRoutes } from "./routes/playground"; const routes = [ { @@ -45,60 +40,7 @@ const routes = [ }, { path: "/play", - children: [ - { - path: "terminal", - element: ( -
- -

Basic unix-like terminal. No persistant storage

- -
- ), - }, - { - path: "apage", - element: ( - - ), - }, - { - path: "rotating", - element: , - }, - { - path: "sand", - element: , - }, - { - path: "pong", - element: - }, - ], + children: playgroundRoutes, }, ], }, diff --git a/gabau.github.io/src/routes/playground.tsx b/gabau.github.io/src/routes/playground.tsx new file mode 100644 index 0000000..5db6b98 --- /dev/null +++ b/gabau.github.io/src/routes/playground.tsx @@ -0,0 +1,76 @@ +import Terminal from "../components/Terminal"; +import TypeWriterHeader from "../components/TypeWriterHeader"; +import AnimatedSandPage from "../pages/fun/AnimatedSandPage"; +import APage from "../pages/fun/APage"; +import PongPage from "../pages/fun/PongPage"; +import RepeatingBannerPage from "../pages/fun/RepeatingBannerPage"; +import SortVisPage from "../pages/fun/SortVisPage"; + +export const playgroundRoutes = [ + { + path: "terminal", + title: "Terminal", + description: "Simple terminal that runs in the browser", + element: ( +
+ +

Basic unix-like terminal. No persistant storage

+ +
+ ), + }, + { + path: "apage", + title: "A page", + description: "Just a page", + element: ( + + ), + }, + { + path: "rotating", + title: "Repeating Text", + description: "Simple repeating Text", + element: , + }, + { + path: "sand", + title: "Sand", + description: "Simple sand falling in pixi.js", + element: , + }, + { + path: "pong", + title: "Pong", + description: "Pong game", + element: , + }, + { + path: "sort", + title: "Sort visualisation", + description: "Simple sorting visualisation of quick sort. It is pure quick sort which makes it slow on sorted array", + element: + } +]; + + diff --git a/gabau.github.io/tsconfig.app.tsbuildinfo b/gabau.github.io/tsconfig.app.tsbuildinfo index 89df9d6..5b96dbd 100644 --- a/gabau.github.io/tsconfig.app.tsbuildinfo +++ b/gabau.github.io/tsconfig.app.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/app.tsx","./src/errorpage.tsx","./src/main.tsx","./src/routes.tsx","./src/vite-env.d.ts","./src/components/codeblock.tsx","./src/components/modalmanager.tsx","./src/components/moonsuntoggle.tsx","./src/components/navbar.tsx","./src/components/navbarwrapper.tsx","./src/components/terminal.tsx","./src/components/typewriterheader.tsx","./src/components/animated/fuzzytext.tsx","./src/components/animated/repeatingbanner.tsx","./src/components/games/animatedsand.tsx","./src/components/games/chess.tsx","./src/components/games/pong.tsx","./src/context/modalcontext.ts","./src/context/themecontext.ts","./src/hooks/usemodals.ts","./src/pages/about.tsx","./src/pages/contact.tsx","./src/pages/playground.tsx","./src/pages/projects.tsx","./src/pages/root.tsx","./src/pages/fun/apage.tsx","./src/pages/fun/animatedsandpage.tsx","./src/pages/fun/pongpage.tsx","./src/pages/fun/repeatingbannerpage.tsx","./src/types/modals.d.ts","./src/types/themes.d.ts","./src/types/virtfile.d.ts"],"version":"5.6.2"} \ No newline at end of file +{"root":["./src/app.tsx","./src/errorpage.tsx","./src/main.tsx","./src/routes.tsx","./src/vite-env.d.ts","./src/components/codeblock.tsx","./src/components/modalmanager.tsx","./src/components/moonsuntoggle.tsx","./src/components/navbar.tsx","./src/components/navbarwrapper.tsx","./src/components/terminal.tsx","./src/components/typewriterheader.tsx","./src/components/animated/fuzzytext.tsx","./src/components/animated/repeatingbanner.tsx","./src/components/games/animatedsand.tsx","./src/components/games/chess.tsx","./src/components/games/pong.tsx","./src/components/games/sortvisualizer.tsx","./src/components/layouts/centereddivlayout.tsx","./src/context/modalcontext.ts","./src/context/themecontext.ts","./src/hooks/usemodals.ts","./src/pages/about.tsx","./src/pages/contact.tsx","./src/pages/playground.tsx","./src/pages/projects.tsx","./src/pages/root.tsx","./src/pages/fun/apage.tsx","./src/pages/fun/animatedsandpage.tsx","./src/pages/fun/pongpage.tsx","./src/pages/fun/repeatingbannerpage.tsx","./src/pages/fun/sortvispage.tsx","./src/routes/playground.tsx","./src/types/modals.d.ts","./src/types/themes.d.ts","./src/types/virtfile.d.ts"],"version":"5.6.2"} \ No newline at end of file