An interactive, educational simulation of a 4-road intersection demonstrating core Distributed Systems concepts applied to urban traffic management: centralized control, coordinated timing, phased transitions, deadlock simulation, failover, and state consistency.
Built with React, TypeScript, Vite, Tailwind CSS, and shadcn/ui.
- Realistic signal model: 4 roads (R1–R4) with vehicle and pedestrian signals.
- Modes: Normal cycle, Emergency vehicle priority, VIP priority, Deadlock simulation.
- Controller logic: Pair-wise switching with safe yellow→red→green transitions.
- Clock/DB visualization: Visual indicators for clock sync and shared state.
- Accessible UI: Clear state indicators; keyboard-friendly controls (see A11y section).
-
Install Node.js LTS (v18+ recommended).
-
Install dependencies:
npm i- Start the dev server:
npm run dev- Build for production:
npm run build && npm run previewsrc/
App.tsx # Providers (React Query, Router, Toasts)
main.tsx # App bootstrap
index.css # Theme tokens, components, animations (Tailwind layers)
components/
TrafficIntersection.tsx # Core visualization + auto/pair controller logic
ControlPanel.tsx # Manual controls, modes, transitions
TaskSidebar.tsx # Task navigation
TrafficLight.tsx # Light atom
PedestrianSignal.tsx # Pedestrian atom
Vehicle.tsx # Vehicle badges (normal/emergency/VIP)
ui/… # shadcn/ui primitives
pages/
Index.tsx # Main page composing Sidebar + Intersection + Panel
NotFound.tsx # 404
lib/utils.ts # Tailwind className helper
- Task 1 — Traffic Signals: Single-green policy; pedestrians walk when their road is red.
- Task 2 — Central Controller: Pair-wise switching between (R1,R3) and (R2,R4) with phased transitions (yellow→red→green) for safety.
- Task 3 — Coordination: Multi-signal coordination visualized across the intersection grid.
- Task 4 — Clock Sync: Visual clock indicator suggesting synchronized timing.
- Task 5 — Critical Section: Only one road may be “in the intersection” at a time.
- Task 6 — Deadlock: Simulate and resolve contention.
- Task 7 — Load Balancing: Primary/Backup controllers with a ZooKeeper indicator.
- Task 8 — Consistency: Database icon representing shared state across controllers.
- State is owned by
pages/Index.tsxasintersectionStateandactiveTask. TrafficIntersectionrenders the grid and derives each road’s light state viagetRoadStatus(road), considering current task and modes.- Normal auto-cycle: advances the active road periodically when not in special modes or during transitions.
- Task 2 controller: switches pairs (13 ↔ 24) with a timed sequence:
- Outgoing pair turns yellow
- Then red
- Then opposite pair becomes active
ControlPanelexposes manual road selection with the same safe transition when crossing pairs, plus Emergency/VIP toggles and Deadlock simulation.
npm run dev— Start Vite dev servernpm run build— Production buildnpm run build:dev— Development-mode buildnpm run preview— Preview production buildnpm run lint— Lint the project
- React 18, TypeScript, Vite
- Tailwind CSS, shadcn/ui (Radix UI under the hood)
- React Router, React Query
- UI is split into three main surfaces:
TaskSidebar,TrafficIntersection, andControlPanel. - Styling uses HSL CSS variables for dark/light theming and consistent design tokens.
- Animations (e.g., emergency flash, VIP glow, sync pulse) are declared in Tailwind layers and referenced as utility classes.
- Use descriptive labels for interactive controls (e.g., “Road R1”).
- Consider adding ARIA status text to traffic/pedestrian signals (e.g., “R1: green”).
- Provide motion-reduced fallbacks for flashing/bounce animations using
prefers-reduced-motion.
- Prefer functional state updates when deriving from previous state:
onStateChange(prev => ({ ...prev, activeRoad: 2 }))
- Keep timers and timeouts managed via
useRefand clear them on effect cleanup to avoid overlaps. - Narrow React
useEffectdependencies to only what’s required; avoid re-creating intervals unnecessarily. - Strongly type
intersectionState(create a sharedIntersectionStateinterface) and avoidany.
- Replace nested
setInterval/setTimeoutflows with a small, typed state machine for transitions. - Consolidate duplicate
cnutil (src/pages/lib/utils.ts→ use@/lib/utils). - Remove unused imports and the unused Vite starter
App.cssif not needed. - Add ARIA attributes to signals and buttons; add tests for state transitions.
- Honor
prefers-reduced-motionfor all flashing/animated elements.
- Port already in use: set a new port
vite --port 5174or stop the conflicting process. - Styles not applying: ensure Tailwind content globs include
src/**/*.{ts,tsx}and restart dev server after config changes. - Animations missing: verify the custom keyframes/animations exist in
tailwind.config.tsandindex.css.
This project is provided as an educational/demo resource. Add a license of your choice if you intend to distribute or modify.
- UI components: shadcn/ui + Radix Primitives
- Icons: lucide-react
- Build tooling: Vite