diff --git a/src/css/main.css b/src/css/main.css index e69de29b..b02e4afc 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -0,0 +1,169 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; + font-family: sans-serif; +} + +:root { + --gray: #a2aab3; +} + +#home_page { + height: 100vh; + margin: 0 auto; +} + +.form-container { + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.form { + display: flex; + flex-direction: column; + gap: 0.5rem; + font-size: 1rem; + padding: 1rem; + border: 1px solid black; +} + +#lift_page { + padding: 1rem; +} + +.floor { + width: 100%; + height: 100px; + border: 1px solid black; +} + +.floors-container { + display: flex; + flex-direction: column; +} + +.floor { + display: flex; + gap: 1rem; +} + +.floor-title-container { + display: flex; + align-items: center; + justify-content: center; + padding: 1rem; + text-align: center; +} + +.floors-btns { + display: flex; + align-items: center; + justify-content: center; +} + +.floors-btn-container { + display: flex; + flex-direction: column; + gap: 1rem; +} + +#floors-inp, +#lifts-inp { + font-size: 1.25rem; + padding: 4px; +} + +.form-label { + font-size: 1.25rem; + font-weight: 500; +} + +#back-btn { + padding: 0.5rem; + font-size: 1.25rem; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 1rem; +} + +#back-btn:hover { + cursor: pointer; +} + +#submit_btn { + font-size: 1rem; + padding: 10px 16px; + background-color: #4caf50; + color: #fff; + border: none; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.2s ease; +} + +#submit_btn:hover { + background-color: #45a049; +} + +.lift-container { + display: flex; + gap: 1rem; +} + +.lift { + width: 80px; + height: 100px; + border: 1px solid black; + display: flex; + overflow: hidden; +} + +.lift-door, +.right-door { + width: 40px; + height: 100%; + border: 1px solid black; + background-color: #4caf50; + position: relative; + transform-origin: left center; + transition-duration: 2.5s; +} + +.open-left { + transform: translateX(-50px); +} + +.open-right { + transform: translateX(50px); +} + +.up_btn, +.down_btn { + display: flex; + align-items: center; + justify-content: center; + padding: 4px; + border-radius: 50%; +} + +.up_btn:active { + background-color: #4caf50; +} +.down_btn:active { + background-color: #4caf50; +} +.up_btn:hover { + cursor: pointer; +} + +.down_btn:hover { + cursor: pointer; +} + +.hidden { + display: none; +} \ No newline at end of file diff --git a/src/index.html b/src/index.html index e69de29b..75b39efb 100644 --- a/src/index.html +++ b/src/index.html @@ -0,0 +1,40 @@ + + + + + + + + Lift-Simulation + + + + +
+
+
+ + + + + + + +
+
+
+ + + + + + + \ No newline at end of file diff --git a/src/js/main.js b/src/js/main.js index e69de29b..d9d8e85d 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -0,0 +1,237 @@ +// main.js + +const submitBtn = document.getElementById("submit_btn"); +const homePage = document.getElementById("home_page"); +const liftPage = document.getElementById("lift_page"); +const floorsContainer = document.getElementById("floors_container"); +const backBtn = document.getElementById("back-btn"); + +let noOfFloors; +let noOfLifts; +let liftsPositions = new Map(); +let maxLifts = 6; +let screenSize; +let liftQueue = []; + +const upBtnSVG = ``; + +const downBtnSVG = ``; + +window.onload = () => { + screenSize = window.innerWidth; + + if (screenSize < 350) { + maxLifts = 1; + } else if (screenSize < 500) { + maxLifts = 2; + } else if (screenSize < 700) { + maxLifts = 3; + } else if (screenSize < 1000) { + maxLifts = 5; + } else { + maxLifts = 6; + } + + const liftsInp = document.getElementById("lifts-inp"); + liftsInp.placeholder += ` (max ${maxLifts})`; +}; + +window.addEventListener("resize", (event) => { + const changeInWidth = event.currentTarget.innerWidth; + + if ( + (screenSize < 500 && changeInWidth > 500) || + (screenSize > 500 && changeInWidth < 500) || + (screenSize < 700 && changeInWidth > 700) || + (screenSize > 700 && changeInWidth < 700) || + (screenSize < 1000 && changeInWidth > 1000) || + (screenSize > 1000 && changeInWidth < 1000) || + (screenSize < 1400 && changeInWidth > 1400) || + (screenSize > 1400 && changeInWidth < 1400) + ) { + location.reload(); + } +}); + +submitBtn.addEventListener("click", (e) => { + e.preventDefault(); + generateUi(); +}); + +backBtn.addEventListener("click", (e) => { + location.reload(); +}); + +const generateUi = () => { + noOfFloors = parseInt(document.getElementById("floors-inp").value); + noOfLifts = parseInt(document.getElementById("lifts-inp").value); + + if (!noOfFloors) { + alert("No of Floors can't be empty!"); + return; + } else if (!noOfLifts) { + alert("No of Lifts can't be empty"); + return; + } else if (noOfFloors < 1) { + alert("No of Floors can't be less than 1"); + return; + } else if (noOfLifts < 1) { + alert("No of Lifts can't be less than 1"); + return; + } else if (noOfLifts > maxLifts) { + alert(`Number of lifts can't be greater than ${maxLifts}`); + return; + } else { + homePage.classList.add("hidden"); + liftPage.classList.remove("hidden"); + floorsContainer.innerHTML = createFloor(noOfFloors, noOfLifts); + for (let i = 0; i < noOfLifts; i++) { + liftsPositions.set(i + 1, { position: 0, free: true }); + } + } +}; + +// Rest of the code remains unchanged. + +const createFloor = (num) => { + let floorHTML = ""; + for (let i = num; i >= 0; i--) { + floorHTML = + floorHTML + + ` +
+
+

${i === 0 ? "Ground
Floor" : `Floor ${i}`}

+
+
+
+ ${ + i !== num + ? `` + : "" + } + ${ + i !== 0 + ? `` + : "" + } +
+
+
+ ${i === 0 ? createLift(noOfLifts) : ""} +
+
`; + } + + return floorHTML; +}; + +const createLift = (num) => { + let liftHTML = ""; + for (let i = 0; i < num; i++) { + liftHTML = + liftHTML + + `
+
+
+
`; + } + + return liftHTML; +}; + +const moveLift = async (floorNo) => { + liftQueue.push(floorNo); + processLiftOperation(); +}; + +const isLiftAvailable = (map) => { + for (const value of map.values()) { + if (value.free === true) { + return true; + } + } + return false; +}; + +const processLiftOperation = async () => { + const isLiftFree = isLiftAvailable(liftsPositions); + + if (liftQueue.length > 0 && isLiftFree) { + const floorNo = liftQueue.shift(); + const { nearestLift, nearestDistance } = await getNearestAvailableLift( + floorNo + ); + + if (nearestLift !== null) { + const liftObj = liftsPositions.get(nearestLift); + liftsPositions.set(nearestLift, { ...liftObj, free: false }); + + const lift = document.getElementById(`lift-${nearestLift}`); + const height = floorNo * 100; + const transitionDuration = nearestDistance * 2; + + lift.style.transitionDuration = `${transitionDuration}s`; + lift.style.transform = `translateY(${-height}px)`; + + const newliftObj = liftsPositions.get(nearestLift); + liftsPositions.set(nearestLift, { ...newliftObj, position: floorNo }); + + setTimeout(() => { + openDoors(nearestLift); + }, transitionDuration * 1000); + } + + processLiftOperation(); + } +}; + +const getNearestAvailableLift = (currentFloor) => { + let nearestLift = null; + let nearestDistance = noOfFloors + 1; + const lifts = Array.from(liftsPositions.keys()); + + for (let i = 0; i < lifts.length; i++) { + const liftObj = liftsPositions.get(lifts[i]); + + if (liftObj.free) { + const liftFloor = liftObj.position; + + if (liftFloor === currentFloor) { + nearestLift = lifts[i]; + nearestDistance = 0; + break; + } + + const distance = Math.abs(liftFloor - currentFloor); + + if (distance < nearestDistance) { + nearestLift = lifts[i]; + nearestDistance = distance; + } + } + } + + return { nearestLift, nearestDistance }; +}; + +const openDoors = (lift) => { + const leftDoor = document.getElementById(`lift-left-door-${lift}`); + const rightDoor = document.getElementById(`lift-right-door-${lift}`); + + leftDoor.classList.add("open-left"); + rightDoor.classList.add("open-right"); + + const doorOpenTime = 2500; + + setTimeout(() => { + leftDoor.classList.remove("open-left"); + rightDoor.classList.remove("open-right"); + + setTimeout(() => { + const liftObj = liftsPositions.get(lift); + liftsPositions.set(lift, { ...liftObj, free: true }); + processLiftOperation(); + }, doorOpenTime); + }, doorOpenTime); +};