import React, { useState, useEffect, useCallback } from 'react';
import { Camera } from 'lucide-react';
// A* Pathfinding Algorithm
class AStar {
constructor(grid) {
this.grid = grid;
}
// Manhattan distance heuristic
heuristic(a, b) {
return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
}
// Check if a cell is walkable
isWalkable(x, y) {
return x >= 0 && x < this.grid.length &&
y >= 0 && y < this.grid[0].length &&
this.grid[x][y] !== 1;
}
findPath(start, end, occupiedCells) {
const openSet = [];
const closedSet = new Set();
const cameFrom = new Map();
const gScore = new Map();
const fScore = new Map();
const startKey = "" + start.x + "," + start.y;
const endKey = "" + end.x + "," + end.y;
gScore.set(startKey, 0);
fScore.set(startKey, this.heuristic(start, end));
openSet.push(start);
while (openSet.length > 0) {
// Get node with lowest fScore
const current = openSet.reduce((lowest, node) =>
(fScore.get("" + node.x + "," + node.y) < fScore.get("" + lowest.x + "," + lowest.y) ? node : lowest)
);
// Check if reached goal
if (current.x === end.x && current.y === end.y) {
const path = [];
let curr = current;
while (curr) {
path.unshift(curr);
curr = cameFrom.get("" + curr.x + "," + curr.y);
}
return path;
}
// Remove current from openSet and add to closedSet
openSet.splice(openSet.indexOf(current), 1);
closedSet.add("" + current.x + "," + current.y);
// Check neighbors
const neighbors = [
{x: current.x+1, y: current.y},
{x: current.x-1, y: current.y},
{x: current.x, y: current.y+1},
{x: current.x, y: current.y-1}
];
for (const neighbor of neighbors) {
const neighborKey = "" + neighbor.x + "," + neighbor.y;
// Skip if not walkable or in closed set or occupied
if (!this.isWalkable(neighbor.x, neighbor.y) ||
closedSet.has(neighborKey) ||
occupiedCells.has(neighborKey)) {
continue;
}
const tentativeGScore = gScore.get("" + current.x + "," + current.y) + 1;
if (!openSet.some(n => n.x === neighbor.x && n.y === neighbor.y)) {
openSet.push(neighbor);
} else if (tentativeGScore >= gScore.get(neighborKey)) {
continue;
}
// This path is the best until now
cameFrom.set(neighborKey, current);
gScore.set(neighborKey, tentativeGScore);
fScore.set(neighborKey, gScore.get(neighborKey) + this.heuristic(neighbor, end));
}
}
return null; // No path found
}
}
// Rest of the code remains the same as in the previous artifact
const TrafficSimulation = () => {
// ... [full previous implementation]
};
export default TrafficSimulation;