From b642af56e7fce7ee37166df8df04980316bab30e Mon Sep 17 00:00:00 2001 From: Sohan Rout Date: Tue, 21 Oct 2025 13:05:29 +0530 Subject: [PATCH 1/5] Feat : added circular queue layout update --- app/components/testimonial.jsx | 6 + .../queue/types/circular/animation.jsx | 512 +++++++++--------- .../queue/types/circular/codeBlock.jsx | 4 +- .../queue/types/circular/content.jsx | 118 ++-- app/visualizer/queue/types/circular/page.jsx | 140 ++++- app/visualizer/queue/types/circular/quiz.jsx | 351 ++++-------- lib/modulesMap.js | 1 + 7 files changed, 554 insertions(+), 578 deletions(-) diff --git a/app/components/testimonial.jsx b/app/components/testimonial.jsx index b413625..a8bdfc3 100755 --- a/app/components/testimonial.jsx +++ b/app/components/testimonial.jsx @@ -55,6 +55,12 @@ const TestimonialSection = () => { review: `The breadth of algorithms covered is impressive. From basic sorting to advanced graph algorithms, everything is presented in an accessible way. The only suggestion I have is to add more real-world application examples for each algorithm.`, stars: 4, }, + { + name: 'Kshitija Ghan', + email: '@kshitijaghan24', + review: `I got to know about Data Visualizer just a few days ago , yet i feel i learned a lot already . Great platform !!!`, + stars: 5, + }, ]; const [expandedReviews, setExpandedReviews] = useState({}); diff --git a/app/visualizer/queue/types/circular/animation.jsx b/app/visualizer/queue/types/circular/animation.jsx index 9c35da3..4df120e 100755 --- a/app/visualizer/queue/types/circular/animation.jsx +++ b/app/visualizer/queue/types/circular/animation.jsx @@ -1,323 +1,299 @@ -'use client'; -import React, { useState, useEffect } from 'react'; -import Footer from '@/app/components/footer'; -import CodeBlock from '@/app/visualizer/queue/types/circular/codeBlock'; -import Content from '@/app/visualizer/queue/types/circular/content'; -import ExploreOther from '@/app/components/ui/exploreOther'; -import Quiz from '@/app/visualizer/queue/types/circular/quiz'; -import BackToTop from '@/app/components/ui/backtotop'; -import GoBackButton from "@/app/components/ui/goback"; +"use client"; +import React, { useState } from "react"; const CircularQueueVisualizer = () => { + const [maxSize, setMaxSize] = useState(5); // capacity const [queue, setQueue] = useState(Array(5).fill(null)); - const [front, setFront] = useState(-1); + const [front, setFront] = useState(0); const [rear, setRear] = useState(-1); - const [inputValue, setInputValue] = useState(''); + const [count, setCount] = useState(0); + const [inputValue, setInputValue] = useState(""); const [operation, setOperation] = useState(null); - const [message, setMessage] = useState('Queue is empty'); - const [highlightedIndex, setHighlightedIndex] = useState(null); + const [message, setMessage] = useState("Circular queue is empty"); const [isAnimating, setIsAnimating] = useState(false); - const [size, setSize] = useState(5); // Default size - const isFull = () => { - return (rear + 1) % size === front; - }; + const isEmpty = count === 0; + const isFull = count === maxSize; - const isEmpty = () => { - return front === -1; + /* ---------- helpers ---------- */ + const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); + const showOp = async (txt, ms = 800) => { + setOperation(txt); + await sleep(ms); + setOperation(null); }; + const wrap = (idx) => (idx + maxSize) % maxSize; - // Enqueue - const enqueue = () => { + /* ---------- enqueue rear ---------- */ + const enqueue = async () => { if (!inputValue.trim()) { - setMessage('Please enter a value'); + setMessage("Please enter a value"); return; } - - if (isFull()) { - setMessage('Queue is full!'); + if (isFull) { + setMessage("Circular queue is full!"); return; } - setIsAnimating(true); - setOperation(`Enqueuing "${inputValue}"...`); - - const newRear = (rear + 1) % size; - setHighlightedIndex(newRear); - - setTimeout(() => { - const newQueue = [...queue]; - newQueue[newRear] = inputValue; - setQueue(newQueue); - - if (front === -1) { - setFront(0); - } - setRear(newRear); - - setMessage(`"${inputValue}" added to queue`); - setInputValue(''); - setOperation(null); - setHighlightedIndex(null); - setIsAnimating(false); - }, 600); + await showOp(`Enqueuing "${inputValue}" at rear …`); + const newRear = wrap(rear + 1); + const newQ = [...queue]; + newQ[newRear] = inputValue; + setQueue(newQ); + setRear(newRear); + setCount(count + 1); + setMessage(`"${inputValue}" added`); + setInputValue(""); + setIsAnimating(false); }; - // Dequeue - const dequeue = () => { - if (isEmpty()) { - setMessage('Queue is empty!'); + /* ---------- dequeue front ---------- */ + const dequeue = async () => { + if (isEmpty) { + setMessage("Circular queue is empty!"); return; } - setIsAnimating(true); - setOperation('Dequeuing...'); - setHighlightedIndex(front); - - setTimeout(() => { - const dequeued = queue[front]; - const newQueue = [...queue]; - newQueue[front] = null; - setQueue(newQueue); - - if (front === rear) { - setFront(-1); - setRear(-1); - } else { - setFront((front + 1) % size); - } - - setMessage(`"${dequeued}" removed from queue`); - setOperation(null); - setHighlightedIndex(null); - setIsAnimating(false); - }, 600); + const item = queue[front]; + await showOp(`Dequeuing "${item}" from front …`); + const newQ = [...queue]; + newQ[front] = null; + setQueue(newQ); + setFront(wrap(front + 1)); + setCount(count - 1); + setMessage(`"${item}" removed`); + setIsAnimating(false); }; - // Peek front - const peekFront = () => { - if (isEmpty()) { - setMessage('Queue is empty!'); - return; - } + /* ---------- isEmpty ---------- */ + const checkEmpty = async () => { setIsAnimating(true); - setHighlightedIndex(front); - setMessage(`Front element: "${queue[front]}"`); - setTimeout(() => { - setHighlightedIndex(null); - setIsAnimating(false); - }, 1500); + await showOp("Checking if empty …"); + setMessage( + isEmpty ? "Circular queue is EMPTY" : "Circular queue is NOT empty" + ); + setIsAnimating(false); }; - // Peek rear - const peekRear = () => { - if (isEmpty()) { - setMessage('Queue is empty!'); - return; - } + /* ---------- isFull ---------- */ + const checkFull = async () => { setIsAnimating(true); - setHighlightedIndex(rear); - setMessage(`Rear element: "${queue[rear]}"`); - setTimeout(() => { - setHighlightedIndex(null); - setIsAnimating(false); - }, 1500); + await showOp("Checking if full …"); + setMessage( + isFull ? "Circular queue is FULL" : "Circular queue is NOT full" + ); + setIsAnimating(false); }; - // Reset queue + /* ---------- reset ---------- */ const reset = () => { - setQueue(Array(size).fill(null)); - setFront(-1); + setQueue(Array(maxSize).fill(null)); + setFront(0); setRear(-1); - setMessage('Queue cleared'); + setCount(0); + setInputValue(""); + setOperation(null); + setMessage("Circular queue cleared"); }; - // Change queue size - const changeSize = (newSize) => { - if (isAnimating) return; - setSize(newSize); - setQueue(Array(newSize).fill(null)); - setFront(-1); - setRear(-1); - setMessage(`Queue size changed to ${newSize}`); + /* ---------- change capacity ---------- */ + const resize = (newCap) => { + if (newCap < 1) return; + const newQ = Array(newCap).fill(null); + let idx = 0; + for (let i = 0; i < Math.min(count, newCap); i++) { + newQ[idx++] = queue[wrap(front + i)]; + } + setQueue(newQ); + setMaxSize(newCap); + setFront(0); + setRear(idx - 1); + setCount(idx); + setMessage(`Capacity set to ${newCap}`); }; + /* ---------- UI ---------- */ return ( -
-
- {/* go back block here */} -
- -
+
+

+ Circular Queue Visualiser (Fixed Capacity) +

- {/* main logic here */} -

- Circular Queue -

-
- -

- Visualize Circular Queue Operations -

-
- {/* Queue Size Controls */} -
-
- - - -
-
- - {/* Controls */} -
-
+
+ {/* ----- Controls card ----- */} +
+ {/* Value input + Enqueue */} +
+ setInputValue(e.target.value)} + placeholder="Enter value" + className="flex-1 p-3 border dark:border-gray-700 rounded-lg dark:bg-neutral-900 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" + disabled={isAnimating} + onKeyDown={(e) => e.key === "Enter" && enqueue()} + /> +
+ setInputValue(e.target.value)} - placeholder="Enter value" - className="flex-1 p-2 border rounded dark:bg-gray-700 focus:ring-2 focus:ring-green-500 transition-all" + type="number" + min="1" + max="15" + value={maxSize} + onChange={(e) => resize(Number(e.target.value))} + className="w-20 p-2 border dark:border-gray-700 rounded dark:bg-neutral-900" disabled={isAnimating} /> - -
- -
- - - -
- {/* Operation Status */} - {operation && ( -
- {operation} -
- )} - - {/* Message Display */} - {message && ( -
- {message} -
- )} - - {/* Queue Visualization */} -
-
- - Front: {front === -1 ? 'None' : front} - - - Rear: {rear === -1 ? 'None' : rear} - -
+ {/* Action buttons */} +
+ + + + + +
- {isEmpty() ? ( -
- Queue is empty + {/* Status banners */} +
+ {operation && ( +
+ + + + {operation}
- ) : ( -
- {queue.map((item, index) => ( -
-
- {item === null ? 'Empty' : item} -
- {index} -
- ))} + )} + {message && ( +
+ {message}
)}
-

- Test Your Knowledge before moving forward! -

- + {/* ----- Visualisation card (hidden when empty) ----- */} + {!isEmpty && ( +
+
+ {/* Front pointer */} +
+ Front + + + +
+ + {/* Elements (circular order) */} +
+ {Array.from({ length: maxSize }).map((_, idx) => { + const itemIdx = wrap(front + idx); + const item = queue[itemIdx]; + const isFront = itemIdx === front; + const isRear = itemIdx === rear; + return ( +
+
+ {item ?? "·"} +
+ + #{itemIdx} + +
+ ); + })} +
- - -
-
-
+ {/* Rear pointer */} +
+ Rear + + + +
+
+
+ )} -
- -