From 039289c632f1e2e78fe363a3eb31eb44e8e03302 Mon Sep 17 00:00:00 2001 From: Soumava Das Date: Sat, 16 May 2026 20:51:30 +0530 Subject: [PATCH 1/3] feat: Implement complete lift simulator with interactive UI - Add HTML structure with input form for floors and lifts configuration - Create responsive CSS styling for lift doors, floors, and controls - Implement JavaScript logic for lift movement, door animations, and call handling - Add lift availability tracking and queue management system - Support multiple lifts with automatic assignment and movement timing - Include visual door opening/closing animations with CSS transforms - Add floor control buttons (up/down) for lift calls - Implement input validation and error handling --- .vscode/settings.json | 3 + src/css/main.css | 133 ++++++++++++++++++++++++++++++ src/index.html | 53 ++++++++++++ src/js/main.js | 182 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 371 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..6f3a2913 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} \ No newline at end of file diff --git a/src/css/main.css b/src/css/main.css index e69de29b..f99334f0 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -0,0 +1,133 @@ +@import url('https://fonts.googleapis.com/css2?family=Khand:wght@300;400;500;600;700&family=Prosto+One&display=swap'); + +:root { + --primary-font: "Cambay", sans-serif; + --bg-color: "#060047"; + --text-color: "#2D2727"; + --upButton-color: "#539165"; + --downButton-color: "#F7C04A"; + --lift-color: "#537FE7"; + --border-color: "#000000"; + --door-color: "#19A7CE"; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: var(--primary-font); + background-color: #f0eeed; + color: var(--text-color); + height: 100vh; +} + +header { + text-align: center; + padding: 2rem 0 2rem 0; +} + +.input__section { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.input__heading { + padding: 0 0 2rem 0; + text-align: center; +} + +.input_labels { + display: inline-block; + width: 15em; +} + +.input_from_user { + padding: 5px; + margin-bottom: 10px; + width: 20em; +} + +.submit__btn { + width: 150px; + height: 35px; + margin-top: 6px; + border-radius: 5px; + border: 2px solid #000000; + font-size: 18px; + padding: 5px; + cursor: pointer; + background-color: #060047; + color: #ffff; +} + +.output__section { + overflow: auto; +} + +.floor { + height: 100px; + display: flex; + flex-direction: row; + align-items: center; + padding-left: 2vw; + gap: 2vw; + border-top: 1px solid #000000; + border-bottom: 1px solid #000000; + margin-top: 2px; + margin-bottom: 2px; +} + +.lift-control { + cursor: pointer; + width: 50px; + height: 25px; + text-transform: capitalize; + padding: 4px; + font-weight: bold; +} + +.lift { + height: 91px; + width: 90px; + background-color: #bce8c4; + display: flex; + flex-direction: row; + overflow: hidden; + margin-right: 20px; + border: 1px solid #000000; +} + +.lift-control .up { + background-color: #bce8c4; +} +.lift-control .down { + background-color: #bce8c4; +} + +.door { + background-color: #19a7ce; + height: 100%; + width: 50%; + transition: all 2.5s; +} + +.left-door { + border-right: 1px solid #f0eeed; +} + +.right-door { + border-left: 1px solid #f0eeed; +} + +.left-move { + transform: translateX(-100%); +} + +.right-move { + transform: translateX(100%); +} \ No newline at end of file diff --git a/src/index.html b/src/index.html index e69de29b..8de8ec66 100644 --- a/src/index.html +++ b/src/index.html @@ -0,0 +1,53 @@ + + + + + + Lift Simulator + + + +
+

welcome to Lift simulator

+
+

+

+
+
+
+
+

Enter Input to start

+
+
+
+ + +
+
+ + +
+ +
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/js/main.js b/src/js/main.js index e69de29b..2f69df4d 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -0,0 +1,182 @@ +const floorInput = document.querySelector(".floor__input"); +const liftInput = document.querySelector(".lift__input"); +const submitBtn = document.querySelector(".submit__btn"); +const outputSection = document.querySelector(".output__section"); + +const floorMaping = new Map(); +const liftMaping = new Map(); +const checkAvailability = new Map(); + +let floorCount = null, + liftCount = null; +let leftLiftcalls = []; + +submitBtn.addEventListener("click", (e) => { + e.preventDefault(); + floorCount = floorInput.value; + liftCount = liftInput.value; + + if (floorCount <= 0 || liftCount <= 0) { + return alert("Invalid Input, Please Try Again!!"); + } + + const inputSection = document.querySelector(".input__section"); + inputSection.style.display = "none"; + + handleFloor(floorCount); + handleLift(liftCount); +}); + +//Making of floor +function handleFloor(totalFloors) { + totalFloors = Number(totalFloors); + const topFloor = document.createElement("section"); + topFloor.className = "floor"; + topFloor.id = `floor-${totalFloors}`; + topFloor.innerHTML = ` +
+ +

Floor-${totalFloors}

+
+ `; + topFloor + .querySelector(".down") + .addEventListener("click", (e) => handleLiftCall(e)); + floorMaping.set(`floor-${totalFloors}`, null); + outputSection.appendChild(topFloor); + + for (let i = totalFloors - 1; i > 0; i--) { + const middleFloors = document.createElement("section"); + middleFloors.className = "floor"; + middleFloors.id = `floor-${i}`; + middleFloors.innerHTML = ` +
+ +

Floor-${i}

+ +
+ `; + + middleFloors + .querySelector(".up") + .addEventListener("click", (e) => handleLiftCall(e)); + middleFloors + .querySelector(".down") + .addEventListener("click", (e) => handleLiftCall(e)); + floorMaping.set(`floor-${i}`, null); + outputSection.appendChild(middleFloors); + } + const groundFloor = document.createElement("section"); + groundFloor.className = "floor"; + groundFloor.id = `floor-${0}`; + groundFloor.innerHTML = ` +
+ +

Floor-${0}

+
+ `; + + groundFloor + .querySelector(".up") + .addEventListener("click", (e) => handleLiftCall(e)); + floorMaping.set(`floor-${0}`, null); + outputSection.appendChild(groundFloor); + + outputSection.style.visibility = "visible"; +} + +//Making of lifts +function handleLift(totalLifts) { + const groundFloor = document.querySelector(".output__section>#floor-0"); + for (let i = 1; i <= totalLifts; i++) { + const currentLift = document.createElement("section"); + currentLift.className = "lift"; + currentLift.id = `lift-${i}`; + currentLift.innerHTML = ` +
+
+ `; + liftMaping.set(`lift-${i}`, 0); + checkAvailability.set(`lift-${i}`, true); + groundFloor.appendChild(currentLift); + } +} + +//handle lift call +function handleLiftCall(event) { + const floorId = event.composedPath()[2].id; + + if (floorMaping.get(floorId) != null) { + const mappedliftId = floorMaping.get(floorId); + if (checkAvailability.get(mappedliftId)) { + checkAvailability.set(mappedliftId, false); + doorOpenClose(floorId, mappedliftId); + } + return; + } + + for (let i = 1; i <= liftCount; i++) { + const liftId = `lift-${i}`; + if (checkAvailability.get(liftId)) { + liftMovement(floorId, liftId); + return; + } + } + leftLiftcalls.push(floorId); +} + +function liftMovement(floorId, liftId) { + if (floorMaping.get(floorId) !== null) { + const mappedLiftId = floorMaping.get(floorId); + if (checkAvailability.get(mappedLiftId)) { + checkAvailability.set(mappedLiftId, false); + doorOpenClose(floorId, mappedLiftId); + } + return; + } + checkAvailability.set(liftId, false); + floorMaping.set(floorId, liftId); + + floorMaping.forEach((value, key) => { + if (key !== floorId && value === liftId) { + floorMaping.set(key, null); + } + }); + + // const floor = document.querySelector(`#${floorId}`); + const lift = document.getElementById(`${liftId}`); + const arr = floorId.split("-"); + const floorNumber = parseInt(arr[arr.length - 1]); + const previousFloor = liftMaping.get(liftId); + const diff = Math.abs(previousFloor - floorNumber); + const transitionDuration = diff * 2; + lift.style.transform = `translateY(-${floorNumber * 100}px)`; + lift.style.transition = `all ${transitionDuration}s`; + + setTimeout(() => { + doorOpenClose(floorId, liftId); + }, transitionDuration * 1000); + + liftMaping.set(liftId, floorNumber); +} + +function doorOpenClose(floorId, liftId) { + const lift = document.querySelector(`#${liftId}`); + const leftDoor = lift.querySelector(".left-door"); + const rightDoor = lift.querySelector(".right-door"); + leftDoor.classList.add("left-move"); + rightDoor.classList.add("right-move"); + setTimeout(() => { + leftDoor.classList.remove("left-move"); + rightDoor.classList.remove("right-move"); + //this lift will be free after 2500ms + setTimeout(() => { + checkAvailability.set(liftId, true); + if (leftLiftcalls.length > 0) { + const floorIdFromRemainingCalls = leftLiftcalls[0]; + leftLiftcalls.shift(); + liftMovement(floorIdFromRemainingCalls, liftId); + } + }, 2500); + }, 2500); +} \ No newline at end of file From db825aecda1eb8b2b23dbbfa57d5500b544687d8 Mon Sep 17 00:00:00 2001 From: Soumava Das Date: Sun, 17 May 2026 19:14:33 +0530 Subject: [PATCH 2/3] fix issues --- src/css/main.css | 18 +++++++++--------- src/index.html | 23 +++++++++++++---------- src/js/main.js | 38 ++++++++++++++++++++++++++------------ 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/src/css/main.css b/src/css/main.css index f99334f0..ccaf2ef5 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -1,14 +1,14 @@ -@import url('https://fonts.googleapis.com/css2?family=Khand:wght@300;400;500;600;700&family=Prosto+One&display=swap'); +@import url("https://fonts.googleapis.com/css2?family=Khand:wght@300;400;500;600;700&family=Prosto+One&display=swap"); :root { --primary-font: "Cambay", sans-serif; - --bg-color: "#060047"; - --text-color: "#2D2727"; - --upButton-color: "#539165"; - --downButton-color: "#F7C04A"; - --lift-color: "#537FE7"; - --border-color: "#000000"; - --door-color: "#19A7CE"; + --bg-color: #060047; + --text-color: #2d2727; + --upButton-color: #539165; + --downButton-color: #f7c04a; + --lift-color: #537fe7; + --border-color: #000000; + --door-color: #19a7ce; } * { @@ -130,4 +130,4 @@ header { .right-move { transform: translateX(100%); -} \ No newline at end of file +} diff --git a/src/index.html b/src/index.html index 8de8ec66..783f9226 100644 --- a/src/index.html +++ b/src/index.html @@ -1,17 +1,18 @@ - + - - - + + + Lift Simulator - - - + + +
-

welcome to Lift simulator

+

welcome to Lift simulator

+
@@ -25,6 +26,7 @@

Enter Input to start

> Enter Input to start > Enter Input to start
- - \ No newline at end of file + + diff --git a/src/js/main.js b/src/js/main.js index 2f69df4d..bc2ba283 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -13,10 +13,15 @@ let leftLiftcalls = []; submitBtn.addEventListener("click", (e) => { e.preventDefault(); - floorCount = floorInput.value; - liftCount = liftInput.value; - - if (floorCount <= 0 || liftCount <= 0) { + floorCount = parseInt(floorInput.value, 10); + liftCount = parseInt(liftInput.value, 10); + + if ( + isNaN(floorCount) || + isNaN(liftCount) || + floorCount <= 0 || + liftCount <= 0 + ) { return alert("Invalid Input, Please Try Again!!"); } @@ -33,12 +38,19 @@ function handleFloor(totalFloors) { const topFloor = document.createElement("section"); topFloor.className = "floor"; topFloor.id = `floor-${totalFloors}`; - topFloor.innerHTML = ` -
- -

Floor-${totalFloors}

-
- `; + const floorDetails = document.createElement("section"); + floorDetails.className = "floor-details"; + + const downBtn = document.createElement("button"); + downBtn.className = "lift-control down"; + downBtn.textContent = "↓"; + + const floorLabel = document.createElement("p"); + floorLabel.className = "floor-number"; + floorLabel.textContent = `Floor-${totalFloors}`; + + floorDetails.append(downBtn, floorLabel); + topFloor.appendChild(floorDetails); topFloor .querySelector(".down") .addEventListener("click", (e) => handleLiftCall(e)); @@ -104,7 +116,9 @@ function handleLift(totalLifts) { //handle lift call function handleLiftCall(event) { - const floorId = event.composedPath()[2].id; + const floorElement = event.target.closest(".floor"); + if (!floorElement) return; + const floorId = floorElement.id; if (floorMaping.get(floorId) != null) { const mappedliftId = floorMaping.get(floorId); @@ -179,4 +193,4 @@ function doorOpenClose(floorId, liftId) { } }, 2500); }, 2500); -} \ No newline at end of file +} From b64f0188bc4c9fd6645cf225b23c18a5714d8f5a Mon Sep 17 00:00:00 2001 From: Soumava Das Date: Sun, 17 May 2026 19:18:16 +0530 Subject: [PATCH 3/3] resolved --- src/index.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/index.html b/src/index.html index 783f9226..076753a0 100644 --- a/src/index.html +++ b/src/index.html @@ -9,10 +9,6 @@

welcome to Lift simulator

-
-

-

-