fix: theme switching issue (#776)#779
Conversation
✅ Deploy Preview for astounding-nougat-da0f6a ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
@dhawneetgcode is attempting to deploy a commit to the adityapaul2603-gmailcom's projects Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughAlgoScope 1.13.0 adds multiple algorithm visualizers and operating-system pages, expands routing and discovery, introduces favorites, notes, onboarding, and difficulty metadata, tightens API middleware, updates visualizer interactions, and adds release, security, SEO, and documentation content. ChangesPlatform and release infrastructure
Application features
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 2 | ❌ 5❌ Failed checks (5 warnings)
✅ Passed checks (2 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/sortingAlgo/Visualizer.jsx (1)
648-650: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winStale tooltip: no more shuffling.
The button is now "Reset" and
handleResetrestores a fixedINITIAL_ARRAY— it doesn't shuffle or randomize anything. The tooltip still promises "Shuffle and generate a new array", which will confuse users.✏️ Align the copy
<Tooltip - content="Shuffle and generate a new array" + content="Reset to the default array" position="top" >🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/sortingAlgo/Visualizer.jsx` around lines 648 - 650, Update the Tooltip content associated with the reset button in Visualizer to describe resetting the array to its initial fixed values, replacing the outdated shuffle-and-generate wording while leaving its position and reset behavior unchanged.src/components/Footer.jsx (1)
201-215: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winFix the Array Search complexity label.
src/components/Footer.jsx:38-41describes “Linear and Binary search visualization,” butO(log N)only matches binary search. If this card covers both, use a combined label likeO(N) / O(log N)or narrow the copy to binary search.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/Footer.jsx` around lines 201 - 215, The Array Search card’s complexity label is inaccurate for copy describing both linear and binary search. Update the corresponding algorithm metadata near the Array Search entry in Footer.jsx to use a combined complexity label such as O(N) / O(log N), or revise the description to cover binary search only while retaining O(log N).
🟡 Minor comments (19)
src/data/difficultyMap.js-1-15 (1)
1-15: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winAdd missing
/practiceand/challengeroutes toROUTE_DIFFICULTIES.
NEXT_TOPICS_MAP.Advancedsuggests/practiceand/challenge(lines 46, 49) with difficulty'Intermediate', but neither route exists inROUTE_DIFFICULTIES. When users navigate to those pages,DifficultyBadgeandLearningPathSuggestionswill both returnnull— no badge, no suggestions. Adding them ensures consistent UX across all pages that appear in the suggestion graph.🛠️ Proposed fix
export const ROUTE_DIFFICULTIES = { '/sort': 'Beginner', '/search': 'Beginner', '/spath': 'Intermediate', '/ldssearch': 'Beginner', '/adt': 'Intermediate', '/kadane': 'Intermediate', '/moore-voting': 'Beginner', '/math-theory': 'Intermediate', '/string-algorithms': 'Advanced', '/dynamic-programming': 'Intermediate', '/dp-journey': 'Advanced', '/backtracking': 'Advanced', '/monotonic-stack': 'Advanced', + '/practice': 'Intermediate', + '/challenge': 'Intermediate', }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/data/difficultyMap.js` around lines 1 - 15, Add the missing /practice and /challenge entries to ROUTE_DIFFICULTIES, assigning each the Intermediate difficulty so DifficultyBadge and LearningPathSuggestions resolve them consistently with NEXT_TOPICS_MAP.Advanced.src/components/LearningPathSuggestions.jsx-12-13 (1)
12-13: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winFilter out the current route from suggestions.
NEXT_TOPICS_MAP.Beginnerincludes{ name: "Moore's Voting", href: '/moore-voting' }. When a user is already on/moore-voting, the component suggests the current page as a "next step," which is confusing. Filter out suggestions matching the current pathname so users only see genuinely new topics.🛠️ Proposed fix
- const suggestions = NEXT_TOPICS_MAP[activeDifficulty] || [] + const suggestions = (NEXT_TOPICS_MAP[activeDifficulty] || []).filter( + (topic) => topic.href !== location.pathname + )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/LearningPathSuggestions.jsx` around lines 12 - 13, Update the suggestions logic in LearningPathSuggestions to filter out any item whose href matches the current pathname before checking for an empty list. Preserve all non-matching suggestions and the existing null return when no suggestions remain.src/components/concepts/ConceptsOverview.jsx-53-56 (1)
53-56: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winSmall copy nit: there's a stray space before the comma ("algorithms , data structures"). Tiny, but it's on a visible headline.
✏️ Fix
- {total} algorithms , data structures and system concepts, all in one - place. + {total} algorithms, data structures, and system concepts, all in + one place.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/concepts/ConceptsOverview.jsx` around lines 53 - 56, Update the text in the ConceptsOverview descriptive paragraph to remove the space before the comma in “algorithms, data structures,” while preserving the rest of the copy unchanged.src/components/AppLayout.jsx-10-14 (1)
10-14: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winDrop the conflicting position utility on
Background.
absoluteandfixedboth setposition, so one of them is redundant here. Keep the one that matches the intended behavior (fixed inset-0for a viewport background, orabsolute inset-0if it should stay within the layout).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/AppLayout.jsx` around lines 10 - 14, Remove the conflicting position utility from the Background component’s outer div, keeping only the positioning that matches its intended scope: use fixed with inset-0 for a viewport-wide background or absolute with inset-0 for a layout-contained background.Source: Path instructions
src/components/monotonicStack/StackVisualizer.jsx-346-347 (1)
346-347: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
ComplexityGraphis being fed a "mode", not a sort algorithm.
ComplexityGraphwas built for sorting: it titles itself"{algorithm} Sort Performance", picks its curve from a fixed sort list, and colors the line viaalgorithmColors[algorithm]. Passingmode('histogram'/'matrix') means it renders "Histogram Sort Performance", falls into the linearelsebranch ofgenerateData, andalgorithmColors['histogram']isundefined, so the line loses its color.Consider a stack-specific complexity card/label here, or extend
ComplexityGraphto accept a title + a color/curve that actually describe the monotonic-stack O(n) behavior. Want me to sketch a smalltitle/colorprop addition toComplexityGraph?🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/monotonicStack/StackVisualizer.jsx` around lines 346 - 347, Replace the ComplexityGraph usage in the monotonic-stack visualizer with stack-specific complexity presentation: either use a dedicated card/label or extend ComplexityGraph with explicit title, color, and O(n) curve inputs. Ensure it no longer receives mode as algorithm, and that the rendered title and line color accurately describe monotonic-stack behavior.Source: Path instructions
src/algorithms/monotonicStack/maximalRectangleSteps.js-28-39 (1)
28-39: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winThe JavaScript
lineMapis off by one. 🐛Nice edge-case coverage in the generator, but the JS map drifted. Counting the JS snippet,
rowLoopis line 7 (line 6 is blank), yet the map says6, and every key after it is one line too low as well. All the other languages (Python/Java/C++/…) correctly startrowLoopat 7. The result: the code panel will highlight the wrong line for the JS view only.🔧 Proposed fix (align with the other languages)
lineMap: { setup: 2, - rowLoop: 6, - updateHeights: 8, - stackSetup: 11, - stackLoop: 12, - whileLoop: 13, - popAndCalc: 14, - updateMax: 16, - push: 18, - complete: 21, + rowLoop: 7, + updateHeights: 9, + stackSetup: 12, + stackLoop: 13, + whileLoop: 14, + popAndCalc: 15, + updateMax: 17, + push: 19, + complete: 22, },As per path instructions:
src/algorithms/**— "Ensure algorithmic correctness ... Check for edge cases."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/algorithms/monotonicStack/maximalRectangleSteps.js` around lines 28 - 39, Correct the JavaScript lineMap entries in maximalRectangleSteps so rowLoop is 7 and every subsequent mapped key is incremented by one, while preserving setup and complete according to their actual JavaScript snippet lines. Keep the mappings for the other languages unchanged.Source: Path instructions
src/components/AlgoCard.jsx-60-86 (1)
60-86: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winRoute favorite writes through the shared helper. This handler duplicates the storage logic and does a raw
JSON.parse, so a corruptedlocalStorageentry can still break the click path. UsingtoggleFavorite()(oraddFavorite/removeFavorite) keeps the storage/event contract and error handling in one place.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/AlgoCard.jsx` around lines 60 - 86, Update handleFavoriteClick to use the shared toggleFavorite helper instead of directly reading, parsing, modifying, and writing localStorage. Preserve the existing favorite state update and click behavior, relying on toggleFavorite for storage, event dispatching, and corrupted-entry error handling.Source: Path instructions
src/components/operatingSystems/cpuSchedulingAlgorithms.js-141-145 (1)
141-145: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winSort statistics by
originalIndex, notpidtext.This comparator assumes every PID is
P<number>. The page lets users editpidfreely, so a custom label likeTaskmakesparseInt(a.pid.substring(1))returnNaN, and the final ordering stops being meaningful. Use the trackedoriginalIndexfor the five stats-sort blocks instead.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/operatingSystems/cpuSchedulingAlgorithms.js` around lines 141 - 145, Update all five statistics-sorting blocks to order entries by their tracked originalIndex rather than parsing pid text; remove the parseInt-based comparator logic and preserve the existing statistics sorting flow.Source: Path instructions
src/algorithms/backtracking/backtrackingSources.js-720-726 (1)
720-726: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRemove the stray Rust brace
is_safealready closes before the standalone}here, so the extra brace makes the sample invalid Rust and breaks copy-paste compilation for learners.Fix
true } -} fn solve(graph: &[Vec<usize>], colors: &mut Vec<usize>, node: usize, k: usize) -> bool {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/algorithms/backtracking/backtrackingSources.js` around lines 720 - 726, Remove the standalone closing brace immediately after the is_safe function in the generated Rust sample, leaving the function’s existing closing brace intact so the snippet remains valid Rust.src/components/operatingSystems/OperatingSystemsPage.jsx-88-99 (1)
88-99: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winMake the clickable card keyboard-accessible. ⌨️
The CPU Scheduling card navigates on
onClick, but a<motion.div>isn't focusable or operable by keyboard — so keyboard/screen-reader users can't open the visualizer. Addrole="button",tabIndex={0}, and anonKeyDown(Enter/Space) whenisCpuScheduling, or better, wrap the content in a real<button>/router<Link>.<motion.div key={module.title} variants={itemVariants} + role={isCpuScheduling ? 'button' : undefined} + tabIndex={isCpuScheduling ? 0 : undefined} onClick={() => { if (isCpuScheduling) { navigate('/operating-systems/cpu-scheduling') } }} + onKeyDown={(e) => { + if (isCpuScheduling && (e.key === 'Enter' || e.key === ' ')) { + e.preventDefault() + navigate('/operating-systems/cpu-scheduling') + } + }}(Side note: the static-analysis "missing key" warnings on the inner spans/headings are false positives — the mapped element already has
key={module.title}.)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/operatingSystems/OperatingSystemsPage.jsx` around lines 88 - 99, Update the CPU Scheduling card’s motion.div in the operating-systems card rendering to be keyboard-accessible: when isCpuScheduling, add button semantics, make it focusable, and handle Enter and Space in onKeyDown by triggering the same navigation as onClick. Preserve non-clickable behavior for other cards and the existing module.title key.src/components/shortestPathAlgo/GridVisualizer.jsx-529-545 (1)
529-545: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winAvoid re-running the solver on every endpoint drag frame.
startPos/endPosare in the solve effect’s deps, so dragging an endpoint after a run re-computes the algorithm on every cell enter. BecausehandleMouseEnteralso callsclearPath()first, the grid can flicker and do extra work while you drag. If live re-solve isn’t intended, make the effect depend onrunKeyonly; otherwise debounce the drag updates or clear on drop.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/shortestPathAlgo/GridVisualizer.jsx` around lines 529 - 545, Update the solve effect containing the algorithm dispatch and animate callback so endpoint dragging does not trigger a solver run on every cell-enter event: remove startPos and endPos from its dependency list and make it rerun based on runKey only, preserving the existing endpoint values for the run.Source: Linters/SAST tools
README.md-104-106 (1)
104-106: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winBlank line splits the Features table in two.
The empty line after the Algorithm Coverage row terminates the table, so the rows below (Comparison Mode … Secure & Modern UI) render as a separate, header-less block. Remove the blank line to keep one continuous table:
📄 Fix
| **Algorithm Coverage** | Support for Sorting (Quick, Merge, Shell), Searching (Linear, Binary), Graph (BFS, DFS, Dijkstra), Abstract Data Types (Stacks, Queues, Binary Trees, Binary Heaps, Linked Lists, and Priority Queues), and Dynamic Programming (Kadane's, Moore's). | - | **Comparison Mode** | Side-by-side visualization of multiple algorithms to compare their efficiency and execution patterns in real-time. |🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` around lines 104 - 106, Remove the blank line between the “Algorithm Coverage” row and the “Comparison Mode” row in the Features table in README.md, keeping all feature rows contiguous so they render as one table.README.md-36-38 (1)
36-38: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winBackticks break these Table-of-Contents anchor links.
The backticks are inside the link destination, so Markdown treats
`#-tech-stack`as a literal target and the links won't jump to the sections. Drop the backticks:🔗 Fix
-- [Tech Stack](`#-tech-stack`) -- [Quick Start](`#-quick-start`) -- [Architecture](`#-architecture`) +- [Tech Stack](`#-tech-stack`) +- [Quick Start](`#-quick-start`) +- [Architecture](`#-architecture`)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` around lines 36 - 38, Update the README table-of-contents links for Tech Stack, Quick Start, and Architecture by removing the backticks from each link destination, leaving the anchor targets as plain fragment identifiers.src/input.css-115-118 (1)
115-118: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winKeep
--theme-text-mutedlighter than body text
--theme-text-muted:#111111is darker than `--theme-text: `#1b1b1b, so the “muted” tier reads stronger than normal copy. Since this token also drivestext-slate-500/600, it should stay below the base text color; a mid-gray would preserve the intended hierarchy while keeping descriptions legible.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/input.css` around lines 115 - 118, Update the --theme-text-muted CSS variable in the theme token definitions to use a mid-gray lighter than the --theme-text base value, preserving the intended muted hierarchy and legibility for text-slate-500/600 consumers.src/components/SearchBar.jsx-487-496 (1)
487-496: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winInclude
categoryin the post-filter.fuse.search()already matchescategory, but this filter only keepsname/keywordshits, so queries like “Shortest Path” can get filtered out as “No results”. Addresult.item.categoryhere.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/SearchBar.jsx` around lines 487 - 496, Update the post-filter inside the SearchBar searchResults flow to also match result.item.category case-insensitively against searchText. Preserve the existing name and optional keywords checks so category-only Fuse matches, such as “Shortest Path,” remain in the results.src/components/challenge/ChallengeVisualizer.jsx-528-549 (1)
528-549: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winTop-up can repeat a question within the same 10-question round.
Nice picker design overall! But watch the boundary case: when
remaininghas fewer thanMAX_QUESTIONSleft, you keep those leftovers inbatchand then top up from a freshly reshuffled full bank. That fresh copy can contain the very questions already sitting inbatch, so one round can show the same question twice — the opposite of the "never repeat until all seen" goal. Filtering the top-up against what's already inbatchcloses the gap.🐛 Suggested fix
const batch = remaining.splice(0, MAX_QUESTIONS) if (batch.length < MAX_QUESTIONS) { const fresh = [...QUESTION_BANK] for (let i = fresh.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)) ;[fresh[i], fresh[j]] = [fresh[j], fresh[i]] } - remaining = fresh - batch.push(...remaining.splice(0, MAX_QUESTIONS - batch.length)) + const used = new Set(batch.map((q) => q.id)) + remaining = fresh.filter((q) => !used.has(q.id)) + batch.push(...remaining.splice(0, MAX_QUESTIONS - batch.length))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/challenge/ChallengeVisualizer.jsx` around lines 528 - 549, Update the top-up logic in pick so the freshly reshuffled QUESTION_BANK excludes every question already present in batch before filling the remaining MAX_QUESTIONS slots. Preserve the existing leftover questions and reshuffling behavior, while ensuring no question appears more than once in a single returned batch.src/components/Footer.jsx-38-41 (1)
38-41: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winComplexity label vs. description mismatch.
The description mentions "Linear and Binary search" but the badge shows only
O(log N). Linear search isO(N)— on a learning tool this can mislead. ConsiderO(N) / O(log N)or a neutral label.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/Footer.jsx` around lines 38 - 41, Update the Array Search entry’s complexity value to represent both algorithms described by desc, using a label such as O(N) / O(log N) rather than only O(log N).src/components/dataStructures/adtSources.js-1183-1219 (1)
1183-1219: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winComment describes union-by-size, code does union-by-rank.
The lead comment talks about "Union by Size tracks subtree sizes instead of ranks," but the class below uses
this.rank[...]union-by-rank. For a teaching snippet this mismatch is confusing — either drop the comment or make it clearly an alternative note separate from the shown implementation.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/dataStructures/adtSources.js` around lines 1183 - 1219, Update the introductory comment for DisjointSetUnion so it clearly presents union-by-size as an alternative optimization, separate from the shown union-by-rank implementation using this.rank. Keep the existing class behavior and rank-based logic unchanged.src/components/dynamicProgramming/DPOptimizationJourney.jsx-1612-1618 (1)
1612-1618: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winOperator-precedence bug leaks "O(1) total" into every approach.
&&binds tighter than?:, so this reads as(ap === 'space' && pk === 'coin') ? 'O(n) array only' : 'O(1) total'. Forrecursion/memo/tab, the condition is false and it falls through to'O(1) total'— which then renders in addition to the correct line just above (e.g. recursion shows both "O(n) call stack" and "O(1) total"). Only thespaceapproach should produce this text.🐛 Proposed fix
{ap === 'recursion' && 'O(n) call stack'} {ap === 'memo' && 'O(n) call stack + O(n) array'} {ap === 'tab' && 'O(1) call stack + O(n) array'} - {ap === 'space' && pk === 'coin' - ? 'O(n) array only' - : 'O(1) total'} + {ap === 'space' && + (pk === 'coin' ? 'O(n) array only' : 'O(1) total')}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/dynamicProgramming/DPOptimizationJourney.jsx` around lines 1612 - 1618, Fix the conditional rendering in the approach-summary block so the `ap === 'space'` check gates both space-specific outcomes, preventing `O(1) total` from rendering for `recursion`, `memo`, or `tab`. Preserve the existing coin-specific `O(n) array only` text for the `space` approach with `pk === 'coin'`.
🧹 Nitpick comments (11)
src/components/PracticePage.jsx (1)
481-492: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDeduplicate the "JavaScript-only" guard across the four run/compare handlers. The same
if (language !== 'javascript') { append error; return }block (with an almost-identical hardcoded message) is copy-pasted four times, and the compare message has already drifted from the run message. Extract a tiny helper so the message lives in one place and future languages are enabled by editing a single guard. Behavior is fine today — this is purely maintainability.
src/components/PracticePage.jsx#L481-L492: replace the inline guard inhandleRunCodewith a shared helper (e.g.if (!ensureJsSupported(setLogs)) return).src/components/PracticePage.jsx#L520-L531: same helper againstsetLogsAinhandleRunCodeA.src/components/PracticePage.jsx#L559-L570: same helper againstsetLogsBinhandleRunCodeB.src/components/PracticePage.jsx#L598-L617: reuse the helper for bothsetLogsAandsetLogsBinhandleCompareBenchmark(parameterize the "execution"/"compare" wording).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/PracticePage.jsx` around lines 481 - 492, Extract the duplicated JavaScript-language guard into a shared helper in PracticePage.jsx that accepts the relevant log setter and supports execution/compare wording. Replace the inline guards in handleRunCode (src/components/PracticePage.jsx:481-492), handleRunCodeA (src/components/PracticePage.jsx:520-531), and handleRunCodeB (src/components/PracticePage.jsx:559-570); reuse the helper for both log setters in handleCompareBenchmark (src/components/PracticePage.jsx:598-617), preserving the existing error behavior while keeping the message centralized.src/components/GuidedTour.jsx (1)
263-273: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd Escape-to-close and focus management for the tour dialog.
You've labelled the popover
role="dialog" aria-modal="true", but there's noEscapekey handler and focus is never moved into the dialog (nor trapped). Keyboard/screen-reader users can't dismiss the tour withEscand can tab into the blocked content behind the overlay — which contradicts thearia-modalcontract.A small
keydowneffect wiringEscape → handleCompleteand moving focus to the dialog on open covers the common cases.♿ Suggested minimal Escape handler
// Auto-start tour on first visit useEffect(() => {useEffect(() => { if (!isOpen) return const onKeyDown = (e) => { if (e.key === 'Escape') handleComplete() } window.addEventListener('keydown', onKeyDown) return () => window.removeEventListener('keydown', onKeyDown) }, [isOpen])🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/GuidedTour.jsx` around lines 263 - 273, Add Escape-key handling and focus management to the tour dialog rendered by the motion.div: when the tour opens, move focus into the dialog, and register a keydown listener that invokes handleComplete on Escape, cleaning it up when closed or dependencies change. Preserve the existing role="dialog" and aria-modal behavior, and ensure focus remains within the dialog rather than reaching content behind the overlay.Source: Path instructions
src/components/sortingAlgo/Visualizer.jsx (1)
208-215: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueHoist
INITIAL_ARRAYto module scope.It's redefined on every render and duplicates the literal already used for
baseArray's initial state (line 157). Lifting it to a module-level constant and reusing it in both places removes the drift risk between the two copies:♻️ Single source of truth
+// module scope (near DEFAULT_ARRAY_SIZE) +const INITIAL_ARRAY = [50, 120, 70, 30, 200, 90, 160]- const INITIAL_ARRAY = [50, 120, 70, 30, 200, 90, 160] const handleReset = () => {And initialize state with it:
useState(INITIAL_ARRAY)(line 157).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/sortingAlgo/Visualizer.jsx` around lines 208 - 215, Move INITIAL_ARRAY out of the component to module scope, then reuse it when initializing baseArray with useState(INITIAL_ARRAY) and in handleReset. Remove the duplicate array literal so both initial and reset behavior share one source of truth.src/components/backtrackingAlgo/CanvasGraphColoring.jsx (1)
414-424: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueStale comment in
handleSvgClick. The comment says "add node if under limit", but the handler only deselects the current node — no add logic here. Update the comment (adding is handled by the+ Nodebutton) to avoid confusing future readers.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/backtrackingAlgo/CanvasGraphColoring.jsx` around lines 414 - 424, Update the comment inside handleSvgClick to describe only the actual behavior: clicks on the SVG background or a line deselect the current node. Remove the inaccurate reference to adding nodes, noting that node creation is handled by the “+ Node” button if appropriate.src/components/backtrackingAlgo/MenuSetAlgoBacktracking.jsx (1)
188-188: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueHeads-up on speed range consistency.
SpeedSliderhere uses its defaultmin={0.5}, but the keyboard shortcuts inVisualizerPage(SoloMode) clampspeeddown to0.25. If a user presses-past 0.5, the slider can't reflect that value. Consider passing matchingmin/step(or clamping the shortcut to 0.5) so the two controls agree.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/backtrackingAlgo/MenuSetAlgoBacktracking.jsx` at line 188, Align the SpeedSlider configuration in MenuSetAlgoBacktracking with the speed bounds used by VisualizerPage/SoloMode keyboard shortcuts: either pass matching min and step values to support 0.25, or update the shortcut clamping to the slider’s 0.5 minimum. Ensure keyboard changes can always be represented by the slider.src/components/MathTheory/MathSoloVisualizer.jsx (2)
113-120: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMinor: parameter
nextAlgoshadows the outer derivednextAlgo.Inside
handleAlgoChange, the argument reuses the name of the URL-derivednextAlgoconstant defined at the top of the component. It works, but shadowing makes the flow harder to follow for readers tracing where the value comes from — considernextKeyoralgoKey.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/MathTheory/MathSoloVisualizer.jsx` around lines 113 - 120, Rename the handleAlgoChange parameter nextAlgo to a distinct name such as nextKey or algoKey, and update its uses in setAlgo and URLSearchParams.set while preserving the outer URL-derived nextAlgo constant.
107-111: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAvoid running the
clear()side effect during render.The
setAlgo/setPrevAlgo"adjust state while rendering" pattern is a legitimate React idiom, butclear()isn't pure — it callswindow.clearTimeout(...)(and cancels playback) as a side effect. Running that in the render body violates render purity and can misbehave under React 19's concurrent/StrictMode double-invocation. Better to keep the pure state sync here and move the playback reset into an effect (or fold the whole reset intohandleAlgoChange+ a URL-drivenuseEffect).♻️ One option: sync in render, reset in effect
if (nextAlgo !== prevAlgo) { setAlgo(nextAlgo) setPrevAlgo(nextAlgo) - clear() } + + useEffect(() => { + clear() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [algo])Worth confirming
clear's identity is stable (it is in the provideduseStepPlayback) before wiring it into an effect dependency.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/MathTheory/MathSoloVisualizer.jsx` around lines 107 - 111, Remove the clear() call from the render-time nextAlgo !== prevAlgo state synchronization in MathSoloVisualizer, leaving only the pure setAlgo and setPrevAlgo updates there. Add an effect that observes the algorithm change and invokes the stable clear callback to reset playback, including the appropriate dependencies so URL-driven changes and user changes preserve the existing reset behavior.Sources: Path instructions, Linters/SAST tools
src/components/MathTheory/CanvasFFT.jsx (1)
264-267: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueIdle preview reshuffles on every render (esp.
noise).
idleSignalis recomputed on every render, and forfftType === 'noise'generateSignalcallsMath.random(), so the idle bars/nodes jump around whenever the component re-renders (e.g. toggling the Butterfly/Spectrum tab) even though nothing changed. Wrapping it inuseMemokeyed on[validN, fftType]keeps the idle view stable and avoids the throwaway work.♻️ Suggested memoization
- const idleSignal = generateSignal(validN, fftType) - const nodes = - currentStep?.nodes ?? - idleSignal.map((v, i) => ({ index: i, re: v, im: 0, state: 'idle' })) + const idleSignal = useMemo( + () => generateSignal(validN, fftType), + [validN, fftType] + ) + const nodes = + currentStep?.nodes ?? + idleSignal.map((v, i) => ({ index: i, re: v, im: 0, state: 'idle' }))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/MathTheory/CanvasFFT.jsx` around lines 264 - 267, Memoize the idle signal used by the node fallback in the MathTheory canvas component, using validN and fftType as dependencies so generateSignal runs only when either input changes. Keep the currentStep?.nodes precedence and idle node mapping unchanged.Source: Linters/SAST tools
README.md (1)
199-199: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueNit: add a language to this fenced block. The project-tree block has no language hint (markdownlint MD040); tagging it
text(orplaintext) silences the warning and avoids accidental syntax highlighting.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` at line 199, Tag the README project-tree fenced code block with the `text` or `plaintext` language identifier so markdownlint MD040 recognizes its language and avoids syntax highlighting.Source: Linters/SAST tools
src/components/slidingwindow/SlidingWindowVisualizer.jsx (1)
908-926: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffOptional: this component styles everything with inline style objects + a raw
<style>block rather than Tailwind. It's correct and mirrors the existing DP Journey visualizer, so no change is required — but per the components convention (Tailwind patterns), migrating the static styling to utility classes would improve consistency and keep theme tokens centralized. Fine to defer given the size of the rewrite. As per path instructions: "Ensure styles follow Tailwind CSS patterns."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/slidingwindow/SlidingWindowVisualizer.jsx` around lines 908 - 926, Leave the existing inline styles and raw style block in SlidingWindowVisualizer unchanged; the review identifies Tailwind migration as optional and does not require a code change.Source: Path instructions
src/components/ScrollToTopButton.jsx (1)
7-20: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueOptional: recompute on resize and mark the scroll listener passive.
onScrollonly fires on scroll, so if the document height changes (async content, orientation/viewport resize) while the user hasn't scrolled,showBottom/showTopstay stale until the next scroll. Listening toresizetoo keeps the buttons honest, and{ passive: true }avoids blocking the scroll thread.♻️ Suggested tweak
- window.addEventListener('scroll', onScroll) - onScroll() - return () => window.removeEventListener('scroll', onScroll) + window.addEventListener('scroll', onScroll, { passive: true }) + window.addEventListener('resize', onScroll) + onScroll() + return () => { + window.removeEventListener('scroll', onScroll) + window.removeEventListener('resize', onScroll) + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/ScrollToTopButton.jsx` around lines 7 - 20, Update the useEffect listener setup around onScroll to also recompute state on window resize and register the scroll listener with the passive option. Invoke the existing onScroll handler for the initial state, add matching cleanup for both listeners, and preserve the current button visibility calculations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@index.html`:
- Line 99: Restore the vis-network dependency used by CanvasShortestPath.jsx by
either reintroducing the CDN bootstrap in index.html so window.vis is available,
or updating CanvasShortestPath.jsx to import and use vis-network/standalone
instead of the global. Keep the shortest-path canvas initialization behavior
unchanged.
In `@src/components/backtrackingAlgo/CanvasGraphColoring.jsx`:
- Around line 263-268: Update the frame-generation logic in the useMemo block
around streamGraphColoringFrames so custom graphs cannot synchronously
materialize unbounded frames. Enforce a reasonable frame limit while collecting
frames, stop generation once the limit is reached, and expose a “too complex to
visualize” state for the UI to render instead of attempting to display truncated
results as complete.
In `@src/components/dynamicProgramming/DPVisualizer.jsx`:
- Around line 238-260: Add a configurable maximum bound to parseIntegerValue and
enforce it for capacity, amount, and list-length inputs through
parseIntegerList. Preserve the existing integer, safe-integer, and minimum
validations, but reject values above the bound before DP visualizations allocate
or clone large arrays; use the appropriate error message consistently.
In `@src/components/Home.jsx`:
- Around line 39-49: Update the filteredAlgos and filteredOS expressions so the
filter === 'All' branches copy ALGORITHMS and OPERATING_SYSTEMS before sortItems
runs, preventing mutation of the imported arrays; keep the filter branches
unchanged. Also harden sortItems by using a zero fallback for missing
difficultyWeight entries so its comparator never returns NaN.
In `@src/components/operatingSystems/CPUSchedulingPage.jsx`:
- Around line 54-65: Update addProcess to derive the next PID number from the
maximum numeric suffix among existing processes’ pid values, then use the next
available number instead of processes.length + 1. Preserve the existing process
creation and state updates while ensuring deleted PIDs are not reused and new
PIDs remain unique for process-keyed maps and views.
---
Outside diff comments:
In `@src/components/Footer.jsx`:
- Around line 201-215: The Array Search card’s complexity label is inaccurate
for copy describing both linear and binary search. Update the corresponding
algorithm metadata near the Array Search entry in Footer.jsx to use a combined
complexity label such as O(N) / O(log N), or revise the description to cover
binary search only while retaining O(log N).
In `@src/components/sortingAlgo/Visualizer.jsx`:
- Around line 648-650: Update the Tooltip content associated with the reset
button in Visualizer to describe resetting the array to its initial fixed
values, replacing the outdated shuffle-and-generate wording while leaving its
position and reset behavior unchanged.
---
Minor comments:
In `@README.md`:
- Around line 104-106: Remove the blank line between the “Algorithm Coverage”
row and the “Comparison Mode” row in the Features table in README.md, keeping
all feature rows contiguous so they render as one table.
- Around line 36-38: Update the README table-of-contents links for Tech Stack,
Quick Start, and Architecture by removing the backticks from each link
destination, leaving the anchor targets as plain fragment identifiers.
In `@src/algorithms/backtracking/backtrackingSources.js`:
- Around line 720-726: Remove the standalone closing brace immediately after the
is_safe function in the generated Rust sample, leaving the function’s existing
closing brace intact so the snippet remains valid Rust.
In `@src/algorithms/monotonicStack/maximalRectangleSteps.js`:
- Around line 28-39: Correct the JavaScript lineMap entries in
maximalRectangleSteps so rowLoop is 7 and every subsequent mapped key is
incremented by one, while preserving setup and complete according to their
actual JavaScript snippet lines. Keep the mappings for the other languages
unchanged.
In `@src/components/AlgoCard.jsx`:
- Around line 60-86: Update handleFavoriteClick to use the shared toggleFavorite
helper instead of directly reading, parsing, modifying, and writing
localStorage. Preserve the existing favorite state update and click behavior,
relying on toggleFavorite for storage, event dispatching, and corrupted-entry
error handling.
In `@src/components/AppLayout.jsx`:
- Around line 10-14: Remove the conflicting position utility from the Background
component’s outer div, keeping only the positioning that matches its intended
scope: use fixed with inset-0 for a viewport-wide background or absolute with
inset-0 for a layout-contained background.
In `@src/components/challenge/ChallengeVisualizer.jsx`:
- Around line 528-549: Update the top-up logic in pick so the freshly reshuffled
QUESTION_BANK excludes every question already present in batch before filling
the remaining MAX_QUESTIONS slots. Preserve the existing leftover questions and
reshuffling behavior, while ensuring no question appears more than once in a
single returned batch.
In `@src/components/concepts/ConceptsOverview.jsx`:
- Around line 53-56: Update the text in the ConceptsOverview descriptive
paragraph to remove the space before the comma in “algorithms, data structures,”
while preserving the rest of the copy unchanged.
In `@src/components/dataStructures/adtSources.js`:
- Around line 1183-1219: Update the introductory comment for DisjointSetUnion so
it clearly presents union-by-size as an alternative optimization, separate from
the shown union-by-rank implementation using this.rank. Keep the existing class
behavior and rank-based logic unchanged.
In `@src/components/dynamicProgramming/DPOptimizationJourney.jsx`:
- Around line 1612-1618: Fix the conditional rendering in the approach-summary
block so the `ap === 'space'` check gates both space-specific outcomes,
preventing `O(1) total` from rendering for `recursion`, `memo`, or `tab`.
Preserve the existing coin-specific `O(n) array only` text for the `space`
approach with `pk === 'coin'`.
In `@src/components/Footer.jsx`:
- Around line 38-41: Update the Array Search entry’s complexity value to
represent both algorithms described by desc, using a label such as O(N) / O(log
N) rather than only O(log N).
In `@src/components/LearningPathSuggestions.jsx`:
- Around line 12-13: Update the suggestions logic in LearningPathSuggestions to
filter out any item whose href matches the current pathname before checking for
an empty list. Preserve all non-matching suggestions and the existing null
return when no suggestions remain.
In `@src/components/monotonicStack/StackVisualizer.jsx`:
- Around line 346-347: Replace the ComplexityGraph usage in the monotonic-stack
visualizer with stack-specific complexity presentation: either use a dedicated
card/label or extend ComplexityGraph with explicit title, color, and O(n) curve
inputs. Ensure it no longer receives mode as algorithm, and that the rendered
title and line color accurately describe monotonic-stack behavior.
In `@src/components/operatingSystems/cpuSchedulingAlgorithms.js`:
- Around line 141-145: Update all five statistics-sorting blocks to order
entries by their tracked originalIndex rather than parsing pid text; remove the
parseInt-based comparator logic and preserve the existing statistics sorting
flow.
In `@src/components/operatingSystems/OperatingSystemsPage.jsx`:
- Around line 88-99: Update the CPU Scheduling card’s motion.div in the
operating-systems card rendering to be keyboard-accessible: when
isCpuScheduling, add button semantics, make it focusable, and handle Enter and
Space in onKeyDown by triggering the same navigation as onClick. Preserve
non-clickable behavior for other cards and the existing module.title key.
In `@src/components/SearchBar.jsx`:
- Around line 487-496: Update the post-filter inside the SearchBar searchResults
flow to also match result.item.category case-insensitively against searchText.
Preserve the existing name and optional keywords checks so category-only Fuse
matches, such as “Shortest Path,” remain in the results.
In `@src/components/shortestPathAlgo/GridVisualizer.jsx`:
- Around line 529-545: Update the solve effect containing the algorithm dispatch
and animate callback so endpoint dragging does not trigger a solver run on every
cell-enter event: remove startPos and endPos from its dependency list and make
it rerun based on runKey only, preserving the existing endpoint values for the
run.
In `@src/data/difficultyMap.js`:
- Around line 1-15: Add the missing /practice and /challenge entries to
ROUTE_DIFFICULTIES, assigning each the Intermediate difficulty so
DifficultyBadge and LearningPathSuggestions resolve them consistently with
NEXT_TOPICS_MAP.Advanced.
In `@src/input.css`:
- Around line 115-118: Update the --theme-text-muted CSS variable in the theme
token definitions to use a mid-gray lighter than the --theme-text base value,
preserving the intended muted hierarchy and legibility for text-slate-500/600
consumers.
---
Nitpick comments:
In `@README.md`:
- Line 199: Tag the README project-tree fenced code block with the `text` or
`plaintext` language identifier so markdownlint MD040 recognizes its language
and avoids syntax highlighting.
In `@src/components/backtrackingAlgo/CanvasGraphColoring.jsx`:
- Around line 414-424: Update the comment inside handleSvgClick to describe only
the actual behavior: clicks on the SVG background or a line deselect the current
node. Remove the inaccurate reference to adding nodes, noting that node creation
is handled by the “+ Node” button if appropriate.
In `@src/components/backtrackingAlgo/MenuSetAlgoBacktracking.jsx`:
- Line 188: Align the SpeedSlider configuration in MenuSetAlgoBacktracking with
the speed bounds used by VisualizerPage/SoloMode keyboard shortcuts: either pass
matching min and step values to support 0.25, or update the shortcut clamping to
the slider’s 0.5 minimum. Ensure keyboard changes can always be represented by
the slider.
In `@src/components/GuidedTour.jsx`:
- Around line 263-273: Add Escape-key handling and focus management to the tour
dialog rendered by the motion.div: when the tour opens, move focus into the
dialog, and register a keydown listener that invokes handleComplete on Escape,
cleaning it up when closed or dependencies change. Preserve the existing
role="dialog" and aria-modal behavior, and ensure focus remains within the
dialog rather than reaching content behind the overlay.
In `@src/components/MathTheory/CanvasFFT.jsx`:
- Around line 264-267: Memoize the idle signal used by the node fallback in the
MathTheory canvas component, using validN and fftType as dependencies so
generateSignal runs only when either input changes. Keep the currentStep?.nodes
precedence and idle node mapping unchanged.
In `@src/components/MathTheory/MathSoloVisualizer.jsx`:
- Around line 113-120: Rename the handleAlgoChange parameter nextAlgo to a
distinct name such as nextKey or algoKey, and update its uses in setAlgo and
URLSearchParams.set while preserving the outer URL-derived nextAlgo constant.
- Around line 107-111: Remove the clear() call from the render-time nextAlgo !==
prevAlgo state synchronization in MathSoloVisualizer, leaving only the pure
setAlgo and setPrevAlgo updates there. Add an effect that observes the algorithm
change and invokes the stable clear callback to reset playback, including the
appropriate dependencies so URL-driven changes and user changes preserve the
existing reset behavior.
In `@src/components/PracticePage.jsx`:
- Around line 481-492: Extract the duplicated JavaScript-language guard into a
shared helper in PracticePage.jsx that accepts the relevant log setter and
supports execution/compare wording. Replace the inline guards in handleRunCode
(src/components/PracticePage.jsx:481-492), handleRunCodeA
(src/components/PracticePage.jsx:520-531), and handleRunCodeB
(src/components/PracticePage.jsx:559-570); reuse the helper for both log setters
in handleCompareBenchmark (src/components/PracticePage.jsx:598-617), preserving
the existing error behavior while keeping the message centralized.
In `@src/components/ScrollToTopButton.jsx`:
- Around line 7-20: Update the useEffect listener setup around onScroll to also
recompute state on window resize and register the scroll listener with the
passive option. Invoke the existing onScroll handler for the initial state, add
matching cleanup for both listeners, and preserve the current button visibility
calculations.
In `@src/components/slidingwindow/SlidingWindowVisualizer.jsx`:
- Around line 908-926: Leave the existing inline styles and raw style block in
SlidingWindowVisualizer unchanged; the review identifies Tailwind migration as
optional and does not require a code change.
In `@src/components/sortingAlgo/Visualizer.jsx`:
- Around line 208-215: Move INITIAL_ARRAY out of the component to module scope,
then reuse it when initializing baseArray with useState(INITIAL_ARRAY) and in
handleReset. Remove the duplicate array literal so both initial and reset
behavior share one source of truth.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro Plus
Run ID: 97c01b75-1959-4245-9087-48b0f17feec1
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/preview.pngis excluded by!**/*.png
📒 Files selected for processing (85)
.env.example.github/ISSUE_TEMPLATE/config.ymlCHANGELOG.mdREADME.mdSECURITY.mdapi/index.jsindex.htmlpackage.jsonpublic/sitemap.xmlsrc/App.jsxsrc/algorithms/backtracking/backtrackingSources.jssrc/algorithms/mathTheory/mathTheorySources.jsxsrc/algorithms/mathTheory/mathTheorySteps.jsxsrc/algorithms/monotonicStack/largestRectangleSteps.jssrc/algorithms/monotonicStack/maximalRectangleSteps.jssrc/components/AlgoCard.jsxsrc/components/AppLayout.jsxsrc/components/CodeEditor.jsxsrc/components/ComplexityGraph.jsxsrc/components/DifficultyBadge.jsxsrc/components/Favorites.jsxsrc/components/Footer.jsxsrc/components/GuidedTour.jsxsrc/components/Home.jsxsrc/components/LearningPathSuggestions.jsxsrc/components/MathTheory/CanvasFFT.jsxsrc/components/MathTheory/MathSoloVisualizer.jsxsrc/components/Navbar.jsxsrc/components/PracticePage.jsxsrc/components/ScrollToTopButton.jsxsrc/components/SearchBar.jsxsrc/components/SeoHead.jsxsrc/components/SpeedSlider.jsxsrc/components/about/About.jsxsrc/components/arraySearch/ComparisonMode.jsxsrc/components/arraySearch/Visualizer.jsxsrc/components/arraySearch/VisualizerPage.jsxsrc/components/backtrackingAlgo/CanvasGraphColoring.jsxsrc/components/backtrackingAlgo/MenuSetAlgoBacktracking.jsxsrc/components/backtrackingAlgo/VisualizerPage.jsxsrc/components/challenge/ChallengeVisualizer.jsxsrc/components/concepts/ConceptsOverview.jsxsrc/components/dataStructures/DSLayout.jsxsrc/components/dataStructures/LinkedListIV.jsxsrc/components/dataStructures/adtSources.jssrc/components/dataStructures/dsuIV.jsxsrc/components/difficultyColors.jssrc/components/dynamicProgramming/DPOptimizationJourney.jsxsrc/components/dynamicProgramming/DPVisualizer.jsxsrc/components/hero/Hero.jsxsrc/components/hero/HeroProductPreview.jsxsrc/components/kadaneAlgo/CanvasKadane.jsxsrc/components/kadaneAlgo/VisualizerPage.jsxsrc/components/monotonicStack/StackVisualizer.jsxsrc/components/monotonicStack/StackVisualizerPage.jsxsrc/components/mooreVotingAlgo/CanvasMooreVoting.jsxsrc/components/mooreVotingAlgo/VisualizerPage.jsxsrc/components/notes/AlgorithmNotes.jsxsrc/components/operatingSystems/CPUSchedulingPage.jsxsrc/components/operatingSystems/DiskSchedulingPage.jsxsrc/components/operatingSystems/OperatingSystemsPage.jsxsrc/components/operatingSystems/PageReplacementPage.jsxsrc/components/operatingSystems/cpuSchedulingAlgorithms.jssrc/components/operatingSystems/cpuSchedulingData.jssrc/components/searchAlgo/CanvasSearching.jsxsrc/components/shortestPathAlgo/CanvasShortestPath.jsxsrc/components/shortestPathAlgo/GridVisualizer.jsxsrc/components/shortestPathAlgo/ShortestPathPage.jsxsrc/components/slidingwindow/SlidingWindowVisualizer.jsxsrc/components/sortingAlgo/Visualizer.jsxsrc/components/sortingAlgo/VisualizerPage.jsxsrc/components/testCaseManager/TestCaseManager.jsxsrc/components/twoPointer/TwoPointerVisualizer.jsxsrc/components/visualizer/CodePanel.jsxsrc/data/complexityMap.jssrc/data/difficultyMap.jssrc/data/tourSteps.jssrc/data/visualizerData.jssrc/input.csssrc/lib/favorites.jssrc/lib/testCaseStore.jssrc/lib/testCaseStore.test.jssrc/lib/utils.jssrc/lib/version.jssrc/main.jsx
| })() | ||
| </script> | ||
| <script src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script> | ||
|
|
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm how window.vis is provided after removing the CDN script.
echo "== window.vis usages =="
rg -nP 'window\.vis' -g '*.jsx' -g '*.js' -C1
echo "== any vis-network import / script tag =="
rg -nP "vis-network|from ['\"]vis" -g '!node_modules' -C1
echo "== package.json dependency =="
rg -nP '"vis-network"' package.jsonRepository: algoscope-hq/AlgoScope
Length of output: 184
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== relevant files =="
git ls-files | rg '(^|/)(index\.html|CanvasShortestPath\.(jsx|tsx|js|ts)|package\.json|vite\.config\.(js|ts)|src/.*vis.*\.(jsx|tsx|js|ts))$'
echo
echo "== index.html excerpt =="
nl -ba index.html | sed -n '1,160p'
echo
echo "== search for vis-network / vis imports =="
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' \
'vis-network|window\.vis|from ["'"'"']vis|from ["'"'"']vis-network|require\(["'"'"']vis|require\(["'"'"']vis-network' .
echo
echo "== CanvasShortestPath references =="
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' 'CanvasShortestPath' .Repository: algoscope-hq/AlgoScope
Length of output: 520
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== index.html lines 1-160 =="
cat -n index.html | sed -n '1,160p'
echo
echo "== CanvasShortestPath.jsx lines 1-220 =="
cat -n src/components/shortestPathAlgo/CanvasShortestPath.jsx | sed -n '1,220p'
echo
echo "== vis-related references =="
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' \
'window\.vis|vis-network|from ["'"'"']vis|from ["'"'"']vis-network|require\(["'"'"']vis|require\(["'"'"']vis-network' \
index.html src package.json api -C 2Repository: algoscope-hq/AlgoScope
Length of output: 18652
🌐 Web query:
vis-network/standalone window.vis global export UMD ESM
💡 Result:
The vis-network package provides a standalone build that is designed for easy inclusion, featuring bundled dependencies and automatically injected CSS [1]. For UMD usage (typically via a <script> tag in browsers), you can use the standalone UMD bundle [2][3]. This build makes the library available as a global variable, typically accessed as vis.Network [4]. The recommended path for this file is: https://unpkg.com/vis-network/standalone/umd/vis-network.min.js [5][3] For ESM (ECMAScript Modules) usage in modern projects, the package provides a standalone ESM build [2][5]. You can import it using: import * as vis from "vis-network/standalone"; or explicitly: import * as vis from "vis-network/standalone/esm/vis-network"; [5] Key characteristics of the standalone build include: - Simplification: It is a single file where CSS is bundled and injected automatically, meaning you do not need to include a separate CSS file [1][3]. - Scope: It contains all necessary dependencies [1]. - Limitations: It does not work well with other packages from the Vis family (e.g., Timeline); for cross-package functionality, the "Peer" build is recommended instead [1][6]. For bundlers (Webpack, Rollup, etc.) that support tree-shaking, the standalone build might include more code than necessary. In those environments, the Peer or ESNext builds are often preferred to reduce bundle size [3][7][6].
Citations:
- 1: https://visjs.github.io/vis-network/docs/network/
- 2: https://visjs.github.io/vis-network/examples/network/basic_usage/standalone.html
- 3: navigationButtons not displayed visjs/vis-network#217
- 4: https://visjs.github.io/vis-network/examples/network/basic_usage/legacy.html
- 5: feat(build): add index files to bundles visjs/vis-network#223
- 6: https://visjs.github.io/vis-network/examples/network/basic_usage/peer.html
- 7: https://visjs.github.io/vis-network/examples/network/basic_usage/esnext.html
Restore the vis-network bootstrap for Shortest Path CanvasShortestPath.jsx still depends on window.vis, but index.html no longer loads the CDN script, and the other vis usage imports vis-network/standalone as a module instead of assigning a global. As-is, the shortest-path canvas will stay blank. Either expose vis on window again or switch this component to the module import.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@index.html` at line 99, Restore the vis-network dependency used by
CanvasShortestPath.jsx by either reintroducing the CDN bootstrap in index.html
so window.vis is available, or updating CanvasShortestPath.jsx to import and use
vis-network/standalone instead of the global. Keep the shortest-path canvas
initialization behavior unchanged.
| const frames = useMemo(() => { | ||
| if (trigger === 0) return [] | ||
| const f = [] | ||
| streamGraphColoringFrames(graph, K, (fr) => f.push(fr)) | ||
| return f | ||
| }, [trigger, K, graph]) |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the target file and nearby symbols.
git ls-files 'src/components/backtrackingAlgo/*' | sed -n '1,20p'
ast-grep outline src/components/backtrackingAlgo/CanvasGraphColoring.jsx --view expanded || true
# Read the relevant section around the reported lines.
wc -l src/components/backtrackingAlgo/CanvasGraphColoring.jsx
sed -n '1,360p' src/components/backtrackingAlgo/CanvasGraphColoring.jsx
# Find related helpers and constants referenced by the comment.
rg -n "streamGraphColoringFrames|MAX_NODES|logEntries|useMemo|trigger|step forward|auto-play|handleSvgClick|handle[A-Za-z]*Click" src/components/backtrackingAlgo/CanvasGraphColoring.jsxRepository: algoscope-hq/AlgoScope
Length of output: 11888
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the frame generator implementation if it's in the same repo.
rg -n "function streamGraphColoringFrames|const streamGraphColoringFrames|export .*streamGraphColoringFrames|streamGraphColoringFrames" srcRepository: algoscope-hq/AlgoScope
Length of output: 396
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the frame generator implementation if it's in the repo.
rg -n "streamGraphColoringFrames" srcRepository: algoscope-hq/AlgoScope
Length of output: 396
🏁 Script executed:
python3 - <<'PY'
from math import pow
for k in (2, 3, 4):
n = 12
leaves = k ** n
internal = (k ** n - 1) // (k - 1) if k > 1 else n
# Upper bound if every node emits try+place+backtrack for each color choice.
frames_upper = 3 * (k * internal)
print(f"k={k}, n={n}: assignments={leaves:,}, tree_nodes={internal:,}, rough_frames_upper={frames_upper:,}")
PYRepository: algoscope-hq/AlgoScope
Length of output: 402
🏁 Script executed:
python3 - <<'PY'
from math import pow
for k in (2, 3, 4):
n = 12
leaves = k ** n
internal = (k ** n - 1) // (k - 1) if k > 1 else n
frames_upper = 3 * (k * internal)
print(f"k={k}, n={n}: assignments={leaves:,}, tree_nodes={internal:,}, rough_frames_upper={frames_upper:,}")
PYRepository: algoscope-hq/AlgoScope
Length of output: 402
Cap frame generation for custom graphs
streamGraphColoringFrames still runs synchronously inside useMemo and materializes every step into frames. With custom graphs allowed up to 12 nodes, low-K inputs can explode into millions of frames, blocking the main thread and blowing up memory. Stream lazily or stop after a frame limit and surface a “too complex to visualize” state.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/backtrackingAlgo/CanvasGraphColoring.jsx` around lines 263 -
268, Update the frame-generation logic in the useMemo block around
streamGraphColoringFrames so custom graphs cannot synchronously materialize
unbounded frames. Enforce a reasonable frame limit while collecting frames, stop
generation once the limit is reached, and expose a “too complex to visualize”
state for the UI to render instead of attempting to display truncated results as
complete.
Source: Path instructions
| function parseIntegerValue(value, label, { min } = {}) { | ||
| const trimmed = String(value).trim() | ||
|
|
||
| if (!trimmed) { | ||
| return { error: `${label} cannot be empty.` } | ||
| } | ||
|
|
||
| if (!/^-?\d+$/.test(trimmed)) { | ||
| return { error: `${label} must be an integer.` } | ||
| } | ||
|
|
||
| const parsed = Number(trimmed) | ||
|
|
||
| if (!Number.isSafeInteger(parsed)) { | ||
| return { error: `${label} is too large.` } | ||
| } | ||
|
|
||
| if (min !== undefined && parsed < min) { | ||
| return { error: `${label} must be at least ${min}.` } | ||
| } | ||
|
|
||
| return { value: parsed } | ||
| } |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the relevant file structure first
ast-grep outline src/components/dynamicProgramming/DPVisualizer.jsx --view expanded || true
echo '--- parseIntegerValue / parseIntegerList / input usage ---'
rg -n "parseIntegerValue|parseIntegerList|capacity|amount|coins|weights|arr|Amount|Capacity|parse.*List" src/components/dynamicProgramming/DPVisualizer.jsx
echo '--- file excerpt around validators ---'
sed -n '200,340p' src/components/dynamicProgramming/DPVisualizer.jsxRepository: algoscope-hq/AlgoScope
Length of output: 9500
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- generator implementations ---'
sed -n '1,200p' src/components/dynamicProgramming/DPVisualizer.jsx | sed -n '1,200p'
echo '--- search for generateCoinChangeSteps / generateKnapsackSteps ---'
rg -n "function generateCoinChangeSteps|function generateKnapsackSteps|generateCoinChangeSteps|generateKnapsackSteps|Array\\(amount\\+1\\)|\\[\\.\\.\\.dp\\]|Array.from\\(\\{ length: \\(capacity" src/components/dynamicProgramming/DPVisualizer.jsx
echo '--- input fields around capacity/amount ---'
sed -n '580,675p' src/components/dynamicProgramming/DPVisualizer.jsxRepository: algoscope-hq/AlgoScope
Length of output: 9340
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- generator file candidates ---'
fd -a "dpStepGenerators" src/algorithms src || true
echo '--- outline candidate file(s) ---'
for f in $(fd -a "dpStepGenerators" src/algorithms src 2>/dev/null); do
[ -f "$f" ] || continue
echo "FILE: $f"
ast-grep outline "$f" --view expanded || true
done
echo '--- search for array growth / step snapshots ---'
rg -n "Array\\(|\\[\\.\\.\\.dp\\]|steps\\.push|push\\(|generateCoinChangeSteps|generateKnapsackSteps|steps =" src/algorithms -g '*dpStepGenerators*' -g '*.js' -g '*.jsx' -g '*.ts' -g '*.tsx'
echo '--- read relevant sections if file exists ---'
for f in $(fd -a "dpStepGenerators" src/algorithms src 2>/dev/null); do
[ -f "$f" ] || continue
wc -l "$f"
sed -n '1,260p' "$f"
doneRepository: algoscope-hq/AlgoScope
Length of output: 27687
Add a max bound for capacity/amount and list lengths. Number.isSafeInteger still allows inputs that make the DP visualizations allocate and clone huge arrays: coin change snapshots dp/usedCoin on every step, and knapsack copies the whole table per cell. A small upper bound in parseIntegerValue/parseIntegerList would prevent the UI from freezing on oversized inputs.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/dynamicProgramming/DPVisualizer.jsx` around lines 238 - 260,
Add a configurable maximum bound to parseIntegerValue and enforce it for
capacity, amount, and list-length inputs through parseIntegerList. Preserve the
existing integer, safe-integer, and minimum validations, but reject values above
the bound before DP visualizations allocate or clone large arrays; use the
appropriate error message consistently.
| const filteredAlgos = ( | ||
| filter === 'All' | ||
| ? ALGORITHMS | ||
| : ALGORITHMS.filter((algo) => algo.difficulty === filter) | ||
| ).sort(sortItems) | ||
|
|
||
| const filteredOS = ( | ||
| filter === 'All' | ||
| ? OPERATING_SYSTEMS | ||
| : OPERATING_SYSTEMS.filter((os) => os.difficulty === filter) | ||
| ).sort(sortItems) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Avoid mutating the imported arrays — .sort() mutates in place.
When filter === 'All', the ternary hands back the same ALGORITHMS (and OPERATING_SYSTEMS) reference imported from visualizerData, and Array.prototype.sort sorts it in place. That permanently reorders the shared module-level arrays, so other consumers (e.g. ConceptsOverview) will render in the mutated order too — a spooky-action-at-a-distance bug. The .filter(...) branch is safe because it already returns a fresh array; only the 'All' branch leaks.
Copy before sorting:
🛠️ Fix
const filteredAlgos = (
filter === 'All'
- ? ALGORITHMS
+ ? [...ALGORITHMS]
: ALGORITHMS.filter((algo) => algo.difficulty === filter)
).sort(sortItems)
const filteredOS = (
filter === 'All'
- ? OPERATING_SYSTEMS
+ ? [...OPERATING_SYSTEMS]
: OPERATING_SYSTEMS.filter((os) => os.difficulty === filter)
).sort(sortItems)Minor follow-on: sortItems returns NaN if any item's difficulty isn't in difficultyWeight (undefined - undefined), which yields an unstable sort. Today all items set difficulty, but a ?? 0 fallback on the weights would harden it.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const filteredAlgos = ( | |
| filter === 'All' | |
| ? ALGORITHMS | |
| : ALGORITHMS.filter((algo) => algo.difficulty === filter) | |
| ).sort(sortItems) | |
| const filteredOS = ( | |
| filter === 'All' | |
| ? OPERATING_SYSTEMS | |
| : OPERATING_SYSTEMS.filter((os) => os.difficulty === filter) | |
| ).sort(sortItems) | |
| const filteredAlgos = ( | |
| filter === 'All' | |
| ? [...ALGORITHMS] | |
| : ALGORITHMS.filter((algo) => algo.difficulty === filter) | |
| ).sort(sortItems) | |
| const filteredOS = ( | |
| filter === 'All' | |
| ? [...OPERATING_SYSTEMS] | |
| : OPERATING_SYSTEMS.filter((os) => os.difficulty === filter) | |
| ).sort(sortItems) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/Home.jsx` around lines 39 - 49, Update the filteredAlgos and
filteredOS expressions so the filter === 'All' branches copy ALGORITHMS and
OPERATING_SYSTEMS before sortItems runs, preventing mutation of the imported
arrays; keep the filter branches unchanged. Also harden sortItems by using a
zero fallback for missing difficultyWeight entries so its comparator never
returns NaN.
| const addProcess = () => { | ||
| const newId = | ||
| typeof crypto !== 'undefined' && crypto.randomUUID | ||
| ? crypto.randomUUID() | ||
| : `p${Date.now()}-${Math.random()}` | ||
| const newPid = `P${processes.length + 1}` | ||
| setProcesses((prev) => [ | ||
| ...prev, | ||
| { id: newId, pid: newPid, arrivalTime: 0, burstTime: 1, priority: 1 }, | ||
| ]) | ||
| setStep2Completed(true) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
addProcess can generate duplicate PIDs after a delete.
P${processes.length + 1} derives the label from the current count, not from the max existing PID. Start with P1/P2/P3, delete P2 → list is [P1, P3] (length 2), then Add → P${2 + 1} = "P3", a duplicate. Since the flow columns, statistics rows, and the remainingTimeRef/completedSetRef Maps are all keyed by pid, duplicates collide — the animation and stats will misbehave.
Derive the next number from the existing PIDs instead:
🛠️ Collision-free PID
- const newPid = `P${processes.length + 1}`
+ const maxNum = processes.reduce((max, p) => {
+ const n = parseInt(String(p.pid).replace(/\D/g, ''), 10)
+ return Number.isNaN(n) ? max : Math.max(max, n)
+ }, 0)
+ const newPid = `P${maxNum + 1}`📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const addProcess = () => { | |
| const newId = | |
| typeof crypto !== 'undefined' && crypto.randomUUID | |
| ? crypto.randomUUID() | |
| : `p${Date.now()}-${Math.random()}` | |
| const newPid = `P${processes.length + 1}` | |
| setProcesses((prev) => [ | |
| ...prev, | |
| { id: newId, pid: newPid, arrivalTime: 0, burstTime: 1, priority: 1 }, | |
| ]) | |
| setStep2Completed(true) | |
| } | |
| const addProcess = () => { | |
| const newId = | |
| typeof crypto !== 'undefined' && crypto.randomUUID | |
| ? crypto.randomUUID() | |
| : `p${Date.now()}-${Math.random()}` | |
| const maxNum = processes.reduce((max, p) => { | |
| const n = parseInt(String(p.pid).replace(/\D/g, ''), 10) | |
| return Number.isNaN(n) ? max : Math.max(max, n) | |
| }, 0) | |
| const newPid = `P${maxNum + 1}` | |
| setProcesses((prev) => [ | |
| ...prev, | |
| { id: newId, pid: newPid, arrivalTime: 0, burstTime: 1, priority: 1 }, | |
| ]) | |
| setStep2Completed(true) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/operatingSystems/CPUSchedulingPage.jsx` around lines 54 - 65,
Update addProcess to derive the next PID number from the maximum numeric suffix
among existing processes’ pid values, then use the next available number instead
of processes.length + 1. Preserve the existing process creation and state
updates while ensuring deleted PIDs are not reused and new PIDs remain unique
for process-keyed maps and views.
Pull Request Summary
What changed?
solvedthe bugs related to issues
Why is this needed?
Because it makes the site good
Closes #776
Type of Change
feat- New user-facing feature or algorithm capabilityfix- Bug fix or regression fixdocs- Documentation-only changestyle- Formatting or styling change with no behavior changerefactor- Code restructuring with no feature or bug-fix behavior changeperf- Performance improvementtest- Test coverage or test infrastructure changebuild- Build system, dependency, or packaging changeci- GitHub Actions, Docker, Vercel, or release automation changechore- Maintenance change that does not affect usersrevert- Reverts a previous changeRelease Notes
Release note category:
Release note entry:
Testing and Verification
npm ciornpm installnpm run format:checknpm run lintnpm run buildhttp://localhost:5173Skipped or additional testing notes:
UI Evidence
Before:
After:
CI/CD and Deployment Impact
Deployment notes:
Reviewer Checklist
Summary by CodeRabbit