Files
disk-scheduling/script.js
T
2024-11-27 20:19:46 +08:00

246 lines
7.4 KiB
JavaScript

let head;
let requests = [];
let currentIndex = 0;
let seekTime = 0;
let direction = 1; // 1 for right, -1 for left
let animationInterval;
let buttons;
function initialize() {
head = document.getElementById("head");
const diskTrack = document.getElementById("diskTrack");
buttons = document.querySelectorAll("button");
updateTrackElements(diskTrack);
}
function updateTrackElements(diskTrack) {
const trackWidth = diskTrack.offsetWidth;
const initialHead = parseInt(document.getElementById("initialHead").value);
const requestInput = document.getElementById("requestQueue").value;
requests = requestInput.split(",").map((x) => parseInt(x.trim()));
const headPosition = (initialHead / 199) * trackWidth;
head.style.left = headPosition + "px";
const existingRequests = document.querySelectorAll(".request");
existingRequests.forEach((req) => req.remove());
requests.forEach((pos) => {
const request = document.createElement("div");
request.className = "request";
request.style.left = (pos / 199) * trackWidth + "px";
diskTrack.appendChild(request);
});
seekTime = 0;
currentIndex = 0;
direction = 1;
updateStats(initialHead);
}
function updateStats(position) {
document.getElementById("seekTime").textContent = seekTime;
document.getElementById("currentPos").textContent = position;
}
function disableButtons(activeButton = null) {
buttons.forEach((button) => {
if (button.textContent === "重置") return;
button.disabled = true;
if (activeButton && button === activeButton) {
button.classList.add("active");
}
});
}
function enableButtons() {
buttons.forEach((button) => {
button.disabled = false;
button.classList.remove("active");
});
}
function startFCFS() {
reset();
disableButtons(event.target);
const diskTrack = document.getElementById("diskTrack");
let currentPosition = parseInt(
document.getElementById("initialHead").value
);
let currentRequestIndex = 0;
animationInterval = setInterval(() => {
if (currentRequestIndex >= requests.length) {
clearInterval(animationInterval);
enableButtons();
return;
}
const trackWidth = diskTrack.offsetWidth;
const targetPosition = requests[currentRequestIndex];
const targetPixel = (targetPosition / 199) * trackWidth;
seekTime += Math.abs(targetPosition - currentPosition);
currentPosition = targetPosition;
head.style.left = targetPixel + "px";
setTimeout(() => {
const requestElements = document.querySelectorAll(".request");
requestElements.forEach((req) => {
const reqPos = Math.round(
(parseFloat(req.style.left) / trackWidth) * 199
);
if (reqPos === targetPosition) {
req.classList.add("served");
}
});
}, 400);
direction = currentPosition > targetPosition ? -1 : 1;
updateStats(targetPosition);
currentRequestIndex++;
}, 1000);
}
function startSSTF() {
reset();
disableButtons(event.target);
const diskTrack = document.getElementById("diskTrack");
const trackWidth = diskTrack.offsetWidth;
const initialHead = parseInt(document.getElementById("initialHead").value);
let currentPosition = initialHead;
let remainingRequests = [...requests];
animationInterval = setInterval(() => {
if (remainingRequests.length === 0) {
clearInterval(animationInterval);
enableButtons();
return;
}
let closestRequest = remainingRequests.reduce((closest, current) => {
let closestDistance = Math.abs(closest - currentPosition);
let currentDistance = Math.abs(current - currentPosition);
return currentDistance < closestDistance ? current : closest;
});
remainingRequests = remainingRequests.filter(
(req) => req !== closestRequest
);
const targetPixel = (closestRequest / 199) * trackWidth;
seekTime += Math.abs(closestRequest - currentPosition);
currentPosition = closestRequest;
head.style.left = targetPixel + "px";
setTimeout(() => {
const requests = document.querySelectorAll(".request");
requests.forEach((req) => {
const reqPos = Math.round(
(parseFloat(req.style.left) / trackWidth) * 199
);
if (reqPos === closestRequest) {
req.classList.add("served");
}
});
}, 400);
direction = currentPosition > closestRequest ? -1 : 1;
updateStats(closestRequest);
}, 1000);
}
function startSCAN() {
reset();
disableButtons(event.target);
const diskTrack = document.getElementById("diskTrack");
const trackWidth = diskTrack.offsetWidth;
const initialHead = parseInt(document.getElementById("initialHead").value);
const initialDirection = document.getElementById("scanDirection").value;
let currentPosition = initialHead;
let sortedRequests = [...requests].sort((a, b) => a - b);
let headIndex = sortedRequests.findIndex((x) => x >= initialHead);
if (headIndex === -1) headIndex = sortedRequests.length;
let scanOrder;
if (initialDirection === "right") {
scanOrder = [
...sortedRequests.slice(headIndex),
...sortedRequests.slice(0, headIndex).reverse(),
];
direction = 1;
} else {
scanOrder = [
...sortedRequests.slice(0, headIndex).reverse(),
...sortedRequests.slice(headIndex),
];
direction = -1;
}
let currentRequestIndex = 0;
animationInterval = setInterval(() => {
if (currentRequestIndex >= scanOrder.length) {
clearInterval(animationInterval);
enableButtons();
return;
}
const targetPosition = scanOrder[currentRequestIndex];
const targetPixel = (targetPosition / 199) * trackWidth;
seekTime += Math.abs(targetPosition - currentPosition);
currentPosition = targetPosition;
head.style.left = targetPixel + "px";
setTimeout(() => {
const requests = document.querySelectorAll(".request");
requests.forEach((req) => {
const reqPos = Math.round(
(parseFloat(req.style.left) / trackWidth) * 199
);
if (reqPos === targetPosition) {
req.classList.add("served");
}
});
}, 400);
updateStats(targetPosition);
currentRequestIndex++;
}, 1000);
}
function reset() {
if (animationInterval) {
clearInterval(animationInterval);
enableButtons();
}
const diskTrack = document.getElementById("diskTrack");
updateTrackElements(diskTrack);
}
function markRequestAsServed(request) {
request.classList.add("served");
request.style.animation = "pulse 0.3s ease";
}
function handleResize() {
const diskTrack = document.getElementById("diskTrack");
updateTrackElements(diskTrack);
}
window.onload = function () {
initialize();
let resizeTimeout;
window.addEventListener("resize", function () {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(handleResize, 100);
});
};