Skip to content

deeep-exe/Robins-bakery

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

🥖 Bakery OS Simulator — MERN Edition

A Banker's Algorithm visualizer, rebuilt on the MERN stack (MongoDB · Express · React · Node). The original single-file vanilla-JS app has been split into a React frontend and an Express API, with the algorithm and simulation state living on the server and persisted in MongoDB.


Architecture overview

┌────────────────────┐        HTTP/JSON        ┌────────────────────┐
│   React (Vite)     │  ───────────────────▶   │  Express API       │
│                    │                         │                    │
│  components/       │   GET  /api/simulation  │  routes/           │
│  hooks/useSimulation│  POST /api/.../tick    │  controllers/      │
│   - tick loop      │   POST /api/.../start   │  services/         │
│   - renders state  │   ... etc               │   - banker.js      │
│                    │  ◀───────────────────   │   - simulation.js  │
└────────────────────┘   { state, analysis }   └─────────┬──────────┘
                                                          │ Mongoose
                                                          ▼
                                                  ┌────────────────┐
                                                  │   MongoDB      │
                                                  │  Simulation    │
                                                  │  (singleton)   │
                                                  └────────────────┘

Key design decisions

  • The server owns the truth. The Banker's Algorithm (safety check, deadlock detection, recovery) and the full simulation state live in Express + MongoDB — not the browser. The React client never runs the algorithm itself.
  • The client drives the animation. Because the simulation animates on a timer, the React useSimulation hook calls POST /api/simulation/tick on an interval while the sim is running, and re-renders whatever state comes back. Speed and the running flag come from the server, so the loop stops itself on deadlock or completion.
  • One simulation document. State is stored as a single "singleton" document (key: "default"), so it survives server restarts.
  • Uniform responses. Every endpoint returns { state, analysis, message }:
    • state — persisted data (cakes, totals, flags, speed)
    • analysis — freshly computed { safe, sequence, blocked, available }
    • message — optional toast text (e.g. "C1 baked successfully! 🎉")

Folder structure

bakery-mern/
├── server/                     # Express + MongoDB API
│   ├── .env.example
│   ├── package.json
│   └── src/
│       ├── server.js           # entrypoint: connect DB + listen
│       ├── app.js              # express app, middleware, routes
│       ├── config/
│       │   ├── db.js           # mongoose connection
│       │   └── constants.js    # RES_META + CAKE_EMOJIS
│       ├── models/
│       │   └── Simulation.js   # Mongoose schema (singleton)
│       ├── services/
│       │   ├── banker.js       # pure Banker's Algorithm
│       │   ├── factory.js      # initial state + makeCake
│       │   └── simulationService.js  # tick + all control logic
│       ├── controllers/
│       │   └── simulationController.js
│       └── routes/
│           └── simulationRoutes.js
│
└── client/                     # React (Vite)
    ├── index.html
    ├── vite.config.js          # dev proxy /api -> :5000
    ├── package.json
    └── src/
        ├── main.jsx
        ├── App.jsx
        ├── styles.css          # original stylesheet (unchanged)
        ├── api/simulation.js   # fetch wrapper
        ├── hooks/useSimulation.js   # state + tick loop + actions
        └── components/
            ├── Header.jsx
            ├── ResourcesPanel.jsx
            ├── Conveyor.jsx
            ├── SafeSequence.jsx
            ├── ProcessTable.jsx
            ├── Controls.jsx
            ├── Legend.jsx
            ├── AddCakeModal.jsx
            └── Toast.jsx

API routes

Method Path Purpose
GET /api/meta Resource metadata (icons, labels, emojis)
GET /api/simulation Current state + analysis
POST /api/simulation/tick Advance one simulation tick
POST /api/simulation/start Begin running (clears blocked → waiting)
POST /api/simulation/pause Stop running
POST /api/simulation/reset Rebuild the default world
POST /api/simulation/detect Detect deadlock
POST /api/simulation/resolve Recover (abort cheapest victim)
POST /api/simulation/cakes Add a cake — body { "max": [o,b,f,s] }
DELETE /api/simulation/cakes/:id Remove a cake
PATCH /api/simulation/speed Set speed — body { "speed": 1..10 }
GET /api/scenarios List stored scenario presets
POST /api/simulation/load Load a preset — body { "key": "..." }
POST /api/scenarios/save Save current world — body { "name" }

MongoDB schema

A single Simulation document holds the whole world:

Simulation {
  key: "default",            // singleton marker (unique)
  total: [5, 3, 10, 10],     // [Ovens, Bakers, Flour, Sugar]
  cakes: [
    {
      id: "C1",
      emoji: "🍰",
      max:       [1, 3, 2, 1],
      allocated: [1, 1, 2, 1],
      status: "running",     // running | waiting | blocked | completed
      progress: 0            // 0..100
    }
  ],
  deadlock: false,
  running: false,
  speed: 5,
  cakeCounter: 4,
  timestamps: true
}

Scenario library

Beyond the one live simulation, the database also stores a library of named configurations in a separate scenarios collection. Built-in scenarios are seeded into MongoDB on server startup (idempotent upsert), and the dropdown bar above the grid lets you load any of them — or save your current world as a new one.

Key Category Demonstrates
sandbox safe The default playground; bakes to completion
safe-sequence safe Safe only in one order (C2 → C3 → C1)
circular-wait deadlock 4-cake cycle, one resource per edge; recoverable
hold-and-wait deadlock Oven exhaustion — two cakes hold 2 ovens each and wait

Loading a scenario overwrites the singleton simulation's total and cakes (statuses reset to waiting, progress to 0). Deadlock scenarios surface as soon as you press ▶ Start or 🔍 Detect, and ♻ Resolve aborts the cheapest victim to recover. Saved scenarios get category custom and a generated unique key, so they survive restarts alongside the built-ins.


Setup instructions

Requires Node.js 18+ and a MongoDB database (local mongod or a free MongoDB Atlas cluster).

1. Backend

cd server
npm install
cp .env.example .env
# open .env and paste your real MONGO_URI
npm run dev          # starts http://localhost:5000  (npm start for prod)

.env example:

PORT=5000
MONGO_URI="mongourlxxxxxx"

2. Frontend

In a second terminal:

cd client
npm install
npm run dev          # starts http://localhost:5173

Open http://localhost:5173. The Vite dev server proxies /api/* to the backend on port 5000, so no CORS setup is needed in development.

Reset the database

Just hit ↺ Reset in the UI, or delete the simulations collection in MongoDB — the server recreates the default world automatically.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors