-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
222 lines (189 loc) · 10 KB
/
Copy pathscript.js
File metadata and controls
222 lines (189 loc) · 10 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
document.addEventListener('DOMContentLoaded', () => {
const MAX_WAITING_CHAIRS = 5;
const HAIRCUT_DURATION_MS = 3500;
const CUSTOMER_ARRIVAL_INTERVAL_MS = 1500; // Auto-add customer interval (optional)
// --- State Variables ---
let barberStatus = 'Sleeping';
let waitingCustomers = [];
let customerInChair = null;
let nextCustomerId = 1;
let barberTimeoutId = null; // To manage the setTimeout for haircut completion
let autoAddCustomerIntervalId = null; // For optional auto-customer adding
// --- DOM References ---
const barberStatusIconSpan = document.getElementById('barber-status-icon');
const barberStatusTextSpan = document.getElementById('barber-status-text');
const barberChairDiv = document.getElementById('barber-chair');
const barberChairCustomerIdSpan = barberChairDiv.querySelector('.customer-id');
const waitingChairsDiv = document.getElementById('waiting-chairs');
const waitingCountSpan = document.getElementById('waiting-count');
const maxChairsSpan = document.getElementById('max-chairs');
const addCustomerBtn = document.getElementById('addCustomerBtn');
const resetSimBtn = document.getElementById('resetSimBtn'); // Reference for reset button
const logList = document.getElementById('logList');
const logContainer = document.getElementById('logContainer');
const clearLogBtn = document.getElementById('clearLogBtn');
// --- Constants for Icons & Classes ---
const ICON_SLEEPING = 'fas fa-bed';
const ICON_CUTTING = 'fas fa-cut'; // Using scissors icon now
const ICON_INFO = 'fas fa-info-circle';
const ICON_ACTION = 'fas fa-running'; // Customer action
const ICON_LEAVE = 'fas fa-door-open';
const ICON_SUCCESS = 'fas fa-check-circle';
const ICON_SPECIAL = 'fas fa-star'; // Waking up barber / Reset
const ICON_WAIT = 'fas fa-hourglass-start';
// --- Core Functions ---
function logMessage(message, type = 'info') { // Types: info, action, leave, success, special, wait
const li = document.createElement('li');
const timestamp = new Date().toLocaleTimeString();
let iconClass = ICON_INFO;
let liClass = 'log-info';
switch (type) {
case 'action': iconClass = ICON_ACTION; liClass = 'log-action'; break;
case 'leave': iconClass = ICON_LEAVE; liClass = 'log-leave'; break;
case 'success': iconClass = ICON_SUCCESS; liClass = 'log-success'; break;
case 'special': iconClass = ICON_SPECIAL; liClass = 'log-special'; break;
case 'wait': iconClass = ICON_WAIT; liClass = 'log-wait'; break;
}
li.classList.add(liClass);
li.innerHTML = `<span class="log-time">[${timestamp}]</span> <i class="${iconClass} log-icon"></i> ${message}`;
logList.appendChild(li);
// Auto-scroll to bottom
logContainer.scrollTop = logContainer.scrollHeight;
}
function updateUI() {
// Update Barber Status & Icon & Animation
barberStatusTextSpan.textContent = barberStatus;
barberStatusIconSpan.classList.remove('cutting-animation'); // Remove animation first
if (barberStatus === 'Sleeping') {
barberStatusIconSpan.innerHTML = `<i class="${ICON_SLEEPING}"></i>`;
} else { // Cutting
barberStatusIconSpan.innerHTML = `<i class="${ICON_CUTTING}"></i>`;
barberStatusIconSpan.classList.add('cutting-animation'); // Add animation only when cutting
}
// Update Barber Chair
if (customerInChair !== null) {
barberChairDiv.classList.remove('empty');
barberChairDiv.classList.add('occupied');
barberChairCustomerIdSpan.textContent = `C${customerInChair}`;
} else {
barberChairDiv.classList.remove('occupied');
barberChairDiv.classList.add('empty');
barberChairCustomerIdSpan.textContent = '';
}
// Update Waiting Room Count
waitingCountSpan.textContent = waitingCustomers.length;
maxChairsSpan.textContent = MAX_WAITING_CHAIRS;
// Update Waiting Chairs visuals
waitingChairsDiv.innerHTML = ''; // Clear existing chairs
for (let i = 0; i < MAX_WAITING_CHAIRS; i++) {
const chairDiv = document.createElement('div');
chairDiv.classList.add('chair-icon');
const icon = document.createElement('i');
icon.className = 'fas fa-chair';
const customerIdSpan = document.createElement('span');
customerIdSpan.className = 'customer-id';
if (i < waitingCustomers.length) {
chairDiv.classList.add('occupied');
customerIdSpan.textContent = `C${waitingCustomers[i]}`;
} else {
chairDiv.classList.add('empty');
}
chairDiv.appendChild(icon);
chairDiv.appendChild(customerIdSpan);
waitingChairsDiv.appendChild(chairDiv);
}
}
function barberWork() {
if (customerInChair === null) {
// This case handles if the customer somehow disappears during the transition
// or if reset happens exactly between states.
if (barberStatus === 'Cutting') { // Only log unexpected wake if we thought we were cutting
logMessage("Barber woke up unexpectedly or customer left during transition.", 'leave');
barberStatus = 'Sleeping'; // Go back to sleep if work vanished
updateUI();
}
return;
}
logMessage(`Barber starts cutting hair for Customer ${customerInChair}.`, 'action');
// barberStatus = 'Cutting'; // Already set before calling barberWork usually
updateUI(); // Update UI immediately to show cutting state & animation
// Clear any previous timeout just in case (might happen on rapid adds/resets)
if (barberTimeoutId) clearTimeout(barberTimeoutId);
// Simulate haircut duration
barberTimeoutId = setTimeout(() => {
logMessage(`Barber finished with Customer ${customerInChair}.`, 'success');
const finishedCustomer = customerInChair;
customerInChair = null; // Customer leaves the chair
// Update UI to show empty barber chair BEFORE checking waiting room
updateUI();
// Check waiting room *after* current customer leaves chair and UI updates
if (waitingCustomers.length > 0) {
const nextCustomer = waitingCustomers.shift(); // Get next customer
customerInChair = nextCustomer; // Move to barber chair state
logMessage(`Customer ${nextCustomer} moves from waiting room to barber chair.`, 'action');
logMessage(`Barber calls next customer (${nextCustomer}).`, 'special');
// barberStatus = 'Cutting'; // Status remains 'Cutting' implicitly
barberWork(); // Recursively call barberWork for the next customer
} else {
// No customers waiting, barber goes to sleep
logMessage("Waiting room empty. Barber goes back to sleep.", 'info');
barberStatus = 'Sleeping';
barberTimeoutId = null; // Clear the timeout ID as it's finished
updateUI(); // Update UI to show sleeping state
}
// No extra UI update needed here, handled in branches or next barberWork call.
}, HAIRCUT_DURATION_MS);
}
function addCustomer() {
const customerId = nextCustomerId++;
logMessage(`Customer ${customerId} arrives at the shop.`, 'info');
if (barberStatus === 'Sleeping') {
// Barber is free, wake him up!
logMessage(`Barber is sleeping. Customer ${customerId} wakes the barber!`, 'special');
customerInChair = customerId; // Assign customer to chair first
barberStatus = 'Cutting'; // Update status BEFORE starting work
logMessage(`Customer ${customerId} sits directly in the barber chair.`, 'action');
// updateUI() will be called inside barberWork()
barberWork(); // Start the haircut process
} else if (waitingCustomers.length < MAX_WAITING_CHAIRS) {
// Barber is busy, but there's a free chair
waitingCustomers.push(customerId); // Add to end of queue
logMessage(`Barber busy. Customer ${customerId} takes waiting chair #${waitingCustomers.length}.`, 'wait');
updateUI(); // Update UI to show new waiting customer
} else {
// Barber is busy and waiting room is full
logMessage(`Waiting room full! Customer ${customerId} leaves the shop.`, 'leave');
// No UI update needed unless you want to show 'balking' temporarily
}
}
function clearLog() {
logList.innerHTML = '';
logMessage("Log cleared.", "info"); // Add a message indicating clearance
}
function resetSimulation() {
// 1. Stop any ongoing processes
if (barberTimeoutId) {
clearTimeout(barberTimeoutId);
barberTimeoutId = null;
}
// Optional: Stop auto-add if it's running
// stopAutoAdd(); // If you implement start/stopAutoAdd
// 2. Reset state variables to initial values
barberStatus = 'Sleeping';
waitingCustomers = [];
customerInChair = null;
nextCustomerId = 1;
// 3. Log the reset event
logMessage("--- Simulation Reset ---", "special");
// 4. Update the UI to reflect the reset state
updateUI();
console.log("Simulation reset to initial state."); // For debugging
}
// --- Initialization ---
logMessage("Barber shop simulation initialized.", "info");
logMessage(`Waiting room capacity: ${MAX_WAITING_CHAIRS} chairs. Haircut time: ${HAIRCUT_DURATION_MS / 1000}s.`, "info");
addCustomerBtn.addEventListener('click', addCustomer);
clearLogBtn.addEventListener('click', clearLog);
resetSimBtn.addEventListener('click', resetSimulation); // Add listener for reset button
updateUI(); // Initial UI setup
});