Operating Systems Course Project
This project is an Operating System Scheduling Simulator that implements Enhanced Priority Scheduling (EPS) — classical Preemptive Priority Scheduling improved with Aging to eliminate starvation.
Each support ticket is treated as a process in the ready queue:
| OS Concept | EPS Equivalent |
|---|---|
| Process | Support Ticket |
| CPU Core | Support Agent |
| Ready Queue | Tier Queue (Tier1–Tier4, by priority) |
| Context Switch | CPU handed to a different process |
| Starvation | A low-priority process repeatedly overtaken |
| Aging | Effective priority improving while waiting |
Lower priority number = higher priority (Priority 1 > Priority 2 > Priority 3 > Priority 4).
Severity maps to priority as: CRITICAL = 1, HIGH = 2, MEDIUM = 3, LOW = 4.
Each process carries:
PID Process id
Arrival Time (AT) When it enters the ready queue
Burst Time (BT) Total CPU time required
Priority Static priority (1 = highest)
Effective Priority Priority after aging (used for scheduling)
Starting Time (ST) First time it executes
Completion Time (CT)
Waiting Time (WT)
Turnaround Time (TAT)
Remaining Time (RT)
Response Time
At every time unit, among all arrived, not-yet-finished processes, the CPU runs the one with the best effective priority. If a higher-priority process arrives, the running process is preempted (its remaining burst is saved and it resumes later).
Tie-breaking: Priority → Smaller Remaining Burst → Earlier Arrival → lower PID.
Aging (starvation prevention): for every agingInterval time units a process
spends waiting (ready but not running), its effective priority improves:
effectivePriority = max(1, effectivePriority − agingBoost)
So a long-ignored low-priority process steadily climbs until it eventually runs — guaranteeing no process waits forever.
The aging parameters live in
settings.json:agingInterval(default 5),agingBoost(default 1),starvationThreshold(default 12).
The same formulas are used regardless of mode, anchored to each process's first start time:
Starting Time ST = first execution start
Waiting Time WT = ST − AT
Turnaround Time TAT = WT + BT
Completion Time CT = ST + BT
Response Time = ST − AT
Average WT = ΣWT / n
Average TAT = ΣTAT / n
Note: WT/TAT/CT are computed from the first start time (not a completion-based formula). The preemptive simulation determines execution order, context switches, CPU utilisation and throughput.
| Metric | How it's computed |
|---|---|
| Average Waiting Time | ΣWT / n |
| Average Turnaround Time | ΣTAT / n |
| Average Response Time | Σ(ST − AT) / n |
| CPU Utilization | total burst ÷ makespan × 100 |
| Throughput | n ÷ makespan |
| Context Switches | times the CPU switched to a different process |
| Starvation Count | processes whose WT exceeded starvationThreshold |
The Analytics page also runs the same workload with plain priority (no aging) as a baseline, so you can see Enhanced (with aging) vs Basic (no aging) side by side.
Controller → Service → EPSEngine (simulation) → JSON Repository → DTO
↓
WebSocket Layer (live updates)
controller— REST API endpointsservice— Business logic (TicketService, MetricsService, AgentService)scheduler— EPSEngine (preemptive priority + aging) + TierQueueManagerrepository— JSON-backed repositories (Ticket, Agent, Metrics, Settings)model— Data models (Ticket/Process, Agent, Metrics, Settings)dto— Request/response DTOsconfig— CORS + WebSocket configurationwebsocket— Real-time broadcast handlerstorage— Generic JSON flat-file storeutils— Severity → priority/tier mapping helpers
- Backend: Java 17, Spring Boot 3, Maven, REST APIs, WebSocket
- Frontend: HTML5, CSS3, Vanilla JavaScript (no frameworks)
- Storage: JSON flat files (
tickets.json,agents.json,metrics.json,settings.json) - Realtime: WebSocket (
/ws/queue) broadcasts queue/ticket/metric updates
- Java 17+ (JDK)
- Maven 3.8+
- A modern browser
- (Optional) VS Code with "Extension Pack for Java" and "Live Server"
cd ehps/backend
mvn spring-boot:runThe server starts at http://localhost:8080. It reads/writes the JSON files
in ehps/backend/data/.
API base: http://localhost:8080/api
WebSocket: ws://localhost:8080/ws/queue
No build step. Open ehps/frontend/index.html, or serve it with VS Code's
Live Server (recommended). A .vscode/settings.json is included that tells
Live Server to ignore the backend/ data files, so backend writes don't cause
the page to reload in a loop.
The frontend expects the backend at http://localhost:8080 (configured in
js/main.js via API_BASE and WS_URL).
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/tickets/create |
Create a process (AT/BT optional; priority from severity) |
| GET | /api/tickets/waiting |
Waiting processes, ordered by effective priority |
| GET | /api/tickets/next |
Dispatch the highest effective-priority process |
| PUT | /api/tickets/{id}/resolve |
Mark a process resolved |
| GET | /api/tickets |
All processes (with computed ST/CT/WT/TAT/RT) |
| GET | /api/tickets/{id} |
Single process with its EPS schedule metrics |
| GET | /api/metrics |
Aggregate metrics (EPS vs no-aging baseline) |
| GET | /api/queues |
4-tier queue snapshots for visualization |
| GET | /api/dashboard |
Aggregated dashboard payload |
| GET | /api/agents |
List all agents |
| PUT | /api/agents/{id}/assign |
Assign agent to a process |
| PUT | /api/agents/{id}/status |
Update agent status |
Read endpoints (
/api/tickets,/api/tickets/{id},/api/dashboard) compute the schedule in memory and do not write to disk.
| Event Type | Triggered When |
|---|---|
QUEUE_UPDATE |
Queue contents/order changed (create, dispatch, resolve) |
TICKET_PROCESSED |
A process was dispatched or resolved |
PRIORITY_UPDATED |
A new process was scheduled |
DASHBOARD_REFRESH |
Aggregate metrics changed |
- Landing (
index.html) — Hero with live queue preview and statistics. - Dashboard (
dashboard.html) — KPI cards, per-tier queue load, recent and waiting process lists, "Process Next" button. - Create Ticket (
create-ticket.html) — Create a new process from a form. - Queue Visualization (
queues.html) — 4 priority-tier columns; processes that have been aged show an "↑ aging" boost tag. - Ticket Detail (
ticket-detail.html) — Per-process view: Process Attributes (PID, AT, BT, Priority, RT), Schedule Metrics (ST, CT, WT, TAT, Response Time with their formulas), a time-ordered timeline (Arrived → First Started → Completed), and an Aging panel showing how many boosts the process received. - Analytics (
analytics.html) — Charts comparing Enhanced (with aging) vs Basic (no aging) across the performance metrics. - Admin (
admin.html) — Agent list, queue control, and the full process table.
backend/data/tickets.json ships with 7 sample processes (varied arrival times,
burst times and priorities) so the scheduler produces meaningful Gantt order,
metrics, and at least one aging promotion immediately on first run.
- Each time unit, every waiting (ready-but-not-running) process accrues wait time.
- After every
agingIntervalunits of waiting, its effective priority improves byagingBoost(the priority number decreases, toward 1). - Eventually even a Priority-4 process climbs high enough to preempt and run, so no process can wait indefinitely.
- A process whose total waiting exceeds
starvationThresholdis reported in the Starvation Count metric.
- The scheduler uses pure priority + aging only — there is no customer-value, queue-load, or weighted scoring in the scheduling decision. Ticket-theme fields (customer, severity label, issue type) are for presentation only.
- Tiers are a visualization of priority:
Tier1= priority 1 (top) …Tier4= priority 4. Aging that lowers a process's priority number visually promotes it to a higher tier.