Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions projects_registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -618,5 +618,22 @@
"harmonics"
],
"path": "math/Fourier-Series-Visualizer/Fourier-Series-Visualizer.py"
},
{
"name": "Pathfinding Visualizer",
"emoji": "🗺️",
"category": "utilities",
"difficulty": "advanced",
"description": "Visualize Dijkstra's and A* Search algorithms on an interactive grid.",
"keywords": [
"pathfinding",
"visualizer",
"algorithm",
"dijkstra",
"astar",
"grid",
"search"
],
"path": "utilities/Pathfinding-Visualizer/Pathfinding-Visualizer.py"
}
]
92 changes: 92 additions & 0 deletions utilities/Pathfinding-Visualizer/Pathfinding-Visualizer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import os
import time

def clear_screen():
os.system('cls' if os.name == 'nt' else 'clear')

def print_grid(grid):
for row in grid:
print(" ".join(row))
print()

def get_neighbors(node, rows, cols):
r, c = node
neighbors = []
if r > 0: neighbors.append((r - 1, c))
if r < rows - 1: neighbors.append((r + 1, c))
if c > 0: neighbors.append((r, c - 1))
if c < cols - 1: neighbors.append((r, c + 1))
return neighbors

def run_dijkstra(grid, start, end):
rows, cols = len(grid), len(grid[0])
distances = { (r, c): float('inf') for r in range(rows) for c in range(cols) }
distances[start] = 0
previous = { (r, c): None for r in range(rows) for c in range(cols) }
unvisited = [(r, c) for r in range(rows) for c in range(cols)]

while unvisited:
unvisited.sort(key=lambda node: distances[node])
current = unvisited.pop(0)

if distances[current] == float('inf'):
break

if grid[current[0]][current[1]] == '█':
continue

if current == end:
break

for neighbor in get_neighbors(current, rows, cols):
if neighbor in unvisited and grid[neighbor[0]][neighbor[1]] != '█':
alt = distances[current] + 1
if alt < distances[neighbor]:
distances[neighbor] = alt
previous[neighbor] = current

if neighbor != end and neighbor != start:
grid[neighbor[0]][neighbor[1]] = '.'
clear_screen()
print_grid(grid)
time.sleep(0.05)

# Reconstruct path
path = []
curr = end
while previous[curr] is not None:
path.append(curr)
curr = previous[curr]

for p in reversed(path):
if p != end and p != start:
grid[p[0]][p[1]] = '*'
clear_screen()
print_grid(grid)
time.sleep(0.05)

def main():
rows, cols = 10, 20
grid = [[' ' for _ in range(cols)] for _ in range(rows)]

start = (1, 1)
end = (8, 18)

grid[start[0]][start[1]] = 'S'
grid[end[0]][end[1]] = 'E'

# Add some walls
for i in range(2, 8):
grid[i][6] = '█'
for i in range(1, 7):
grid[i][12] = '█'

print("🗺️ Pathfinding Visualizer (Terminal Edition)")
print("S = Start, E = End, █ = Wall, . = Visited, * = Path")
input("Press Enter to run Dijkstra's Algorithm...")

run_dijkstra(grid, start, end)
print("Finished Pathfinding!")

if __name__ == "__main__":
main()
Binary file modified web-app/assets/banners/2048-game.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/armstrong.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/binary-search.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/blackjack21.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/bubble-sort.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/budget-tracker.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/caesar-cipher.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/calculator.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/chess.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/coin-flip.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/collatz.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/color-palette.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/coordinate-polar-transform.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/derivative-calculator.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/dice-rolling.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/dots-boxes.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/emoji-memory-game.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/fibonacci.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/flames.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/flappy-game.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/fourier-series.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/hangman.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/math-quiz.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/matrix-calculator.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/morse-code.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web-app/assets/banners/number-converter.webp
Binary file modified web-app/assets/banners/number-guessing.webp
Binary file modified web-app/assets/banners/number-sliding-puzzle.webp
Binary file modified web-app/assets/banners/pascal-triangle.webp
Binary file modified web-app/assets/banners/password-forge.webp
Binary file modified web-app/assets/banners/prime-analyzer.webp
Binary file modified web-app/assets/banners/productive-pet.webp
Binary file modified web-app/assets/banners/progress-tracker.webp
Binary file modified web-app/assets/banners/progression-recognizer.webp
Binary file modified web-app/assets/banners/projectile-motion.webp
Binary file modified web-app/assets/banners/resume-analyzer.webp
Binary file modified web-app/assets/banners/reverse-hangman.webp
Binary file modified web-app/assets/banners/rock-paper-scissor.webp
Binary file modified web-app/assets/banners/simon-says.webp
Binary file modified web-app/assets/banners/snake.webp
Binary file modified web-app/assets/banners/spot-the-difference.webp
Binary file modified web-app/assets/banners/tic-tac-toe.webp
Binary file modified web-app/assets/banners/tower-of-hanoi.webp
Binary file modified web-app/assets/banners/typing-speed-tester.webp
Binary file modified web-app/assets/banners/unit-converter.webp
Binary file modified web-app/assets/banners/war-card-game.webp
Binary file modified web-app/assets/banners/whack-a-mole.webp
Binary file modified web-app/assets/banners/word-scramble.webp
34 changes: 34 additions & 0 deletions web-app/debug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const { chromium } = require('@playwright/test');

(async () => {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();

page.on('console', msg => console.log('BROWSER CONSOLE:', msg.type(), msg.text()));
page.on('pageerror', err => console.log('BROWSER ERROR:', err.message));

console.log("Navigating...");
await page.goto('http://localhost:8080');

console.log("Waiting for search bar...");
await page.waitForSelector('#searchBar');
await page.fill('#searchBar', 'pathfinding visualizer');

console.log("Waiting for project card...");
await page.waitForSelector('.project-card:has-text("Pathfinding Visualizer")');
await page.click('.project-card:has-text("Pathfinding Visualizer")');

console.log("Waiting for modal...");
await page.waitForSelector('#pfGrid');

const html = await page.locator('#pfGrid').innerHTML();
console.log("GRID HTML:", html.substring(0, 500));

const count = await page.locator('#pfGrid td').count();
console.log("CELL COUNT:", count);

const box = await page.locator('#pfGrid').boundingBox();
console.log("GRID BOUNDING BOX:", box);

await browser.close();
})();
18 changes: 18 additions & 0 deletions web-app/generate_banners.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,23 @@ def draw_o(ox, oy):
for i, h in enumerate(bar_heights):
x = 230 + i * 50
v_draw.rectangle([x, 320 - h, x + 30, 320], fill=color_accent)
elif "pathfinding" in n_lower or "visualizer" in n_lower:
# A grid with a path being found
cx, cy = 400, 225
# draw grid base
for r in range(5):
for c in range(8):
x = cx - 160 + c * 40
y = cy - 100 + r * 40
v_draw.rectangle([x, y, x + 35, y + 35], fill=(255,255,255,10), outline=color_accent_dim, width=1)
# draw start and end
v_draw.ellipse([cx - 150, cy - 90, cx - 135, cy - 75], fill=(16, 185, 129)) # Start
v_draw.ellipse([cx + 130, cy + 70, cx + 145, cy + 85], fill=(239, 68, 68)) # End
# draw a path
pts = [(cx - 142, cy - 82), (cx - 102, cy - 82), (cx - 102, cy - 42), (cx - 62, cy - 42), (cx - 62, cy - 2), (cx + 18, cy - 2), (cx + 18, cy + 38), (cx + 58, cy + 38), (cx + 58, cy + 78), (cx + 138, cy + 78)]
v_draw.line(pts, fill=color_accent, width=4, joint="round")
# draw a wall
v_draw.rectangle([cx - 20, cy - 100, cx + 15, cy + 15], fill=color_accent)
else:
# Default nice abstract waves
points = []
Expand Down Expand Up @@ -633,6 +650,7 @@ def draw_o(ox, oy):
("Caesar Cipher", "utilities", "caesar-cipher.webp"),
("Unit Converter", "utilities", "unit-converter.webp"),
("Budget Tracker", "utilities", "budget-tracker.webp"),
("Pathfinding Visualizer", "utilities", "pathfinding-visualizer.webp"),
]

# Run generation
Expand Down
138 changes: 9 additions & 129 deletions web-app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,8 @@ <h3>Legal</h3>
<script src="js/projects/reverse-hangman.js"></script>
<script defer src="js/projects/unit-converter.js"></script>
<script defer src="js/projects/fourier-series.js"></script>
<script defer src="js/projects.js"></script>
<script defer src="js/projects/pathfinding-visualizer.js?v=2"></script>
<script defer src="js/projects.js?v=2"></script>
<script defer src="js/cm-editor.js"></script>
<script defer src="js/playground.js"></script>
<script defer type="module" src="js/main.js"></script>
Expand Down Expand Up @@ -1138,6 +1139,13 @@ <h3>Legal</h3>
},

// UTILITIES (10+)
{
project: "pathfinding-visualizer",
title: "Pathfinding Visualizer",
category: "utilities",
desc: "Interactive visualizer for Dijkstra and A* algorithms",
tags: "utility,algorithm,visualizer,pathfinding"
},
{
project: "budget-tracker",
title: "Budget Tracker",
Expand Down Expand Up @@ -1421,135 +1429,7 @@ <h3>${proj.title}</h3>
})();
</script>

<!-- MODAL FIX - Load projects properly -->
<script>
(function () {
const modal = document.getElementById("projectModal");
const modalBody = document.getElementById("modalBody");
const modalClose = document.getElementById("modalClose");

if (!modal || !modalBody) {
console.error("Modal elements not found!");
return;
}

// Function to close modal
function closeModal() {
modal.classList.remove("active");
modal.setAttribute("aria-hidden", "true");
document.body.style.overflow = "";
document.body.style.paddingRight = "";

// Clear modal body
modalBody.innerHTML = "";

console.log("Modal closed");
}

// Function to open modal with project
window.openProjectModal = function (projectName, triggerElement) {
console.log("Opening project:", projectName);

// Clear previous content
modalBody.innerHTML =
'<div style="text-align: center; padding: 2rem;">Loading project...</div>';

// Show modal
modal.classList.add("active");
modal.setAttribute("aria-hidden", "false");
document.body.style.overflow = "hidden";

// Get project HTML
let projectHTML = "";

// Try to get HTML from the project's function
const functionName =
"get" +
projectName
.split("-")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join("") +
"HTML";

if (typeof window[functionName] === "function") {
try {
projectHTML = window[functionName]();
console.log("Loaded via", functionName);
} catch (e) {
console.error("Error loading project:", e);
projectHTML = `<div style="text-align: center; padding: 2rem; color: red;">
<h3>Error loading project</h3>
<p>${e.message}</p>
</div>`;
}
} else {
// Fallback: Try to find by looking at loaded scripts
console.warn("No loader found for:", projectName);
projectHTML = `<div style="text-align: center; padding: 2rem;">
<h3>${projectName.replace(/-/g, " ").toUpperCase()}</h3>
<p>Project content will be available soon.</p>
<p style="color: var(--accent);">Check back later!</p>
</div>`;
}

modalBody.innerHTML = `
<div class="modal-project-container">
<div class="modal-project-header">
<h2>${projectName.replace(/-/g, " ").toUpperCase()}</h2>
</div>
<div class="modal-project-content">
${projectHTML}
</div>
</div>
`;

// Try to initialize project if function exists
const initName =
"init" +
projectName
.split("-")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join("");

if (typeof window[initName] === "function") {
setTimeout(() => {
try {
window[initName]();
console.log("Initialized:", projectName);
} catch (e) {
console.error("Init error:", e);
}
}, 100);
}
};

// Close button handler
if (modalClose) {
modalClose.addEventListener("click", closeModal);
}

// Click outside to close
modal.addEventListener("click", (e) => {
if (e.target === modal) {
closeModal();
}
});

// Escape key to close
document.addEventListener("keydown", (e) => {
if (e.key === "Escape" && modal.classList.contains("active")) {
closeModal();
}
});

// Override the existing openProjectSafe if needed
if (typeof window.openProjectSafe !== "function") {
window.openProjectSafe = window.openProjectModal;
}

console.log('✅ Modal fix loaded');
})();
</script>

<script>
// FIX 1: Add missing toPascalCase function
Expand Down
Loading
Loading