From e529f771ca63e64d71fadbdbb777cb24fdb0d60a Mon Sep 17 00:00:00 2001 From: Gabriel Vendrame-Piche Date: Mon, 12 Feb 2024 17:53:59 -0500 Subject: [PATCH 1/8] feat: added laundramat hack --- Laundromat/Laundromat.css | 362 +++++++++++++++++++++++++ Laundromat/Laundromat.html | 58 ++++ Laundromat/Laundromat.js | 315 ++++++++++++++++++++++ Laundromat/Laundromat.ts | 385 ++++++++++++++++++++++++++ Laundromat/tsconfig.json | 14 + LockPick/LockPick.ts | 539 ++++++++++++++++++++----------------- index.html | 1 + 7 files changed, 1424 insertions(+), 250 deletions(-) create mode 100644 Laundromat/Laundromat.css create mode 100644 Laundromat/Laundromat.html create mode 100644 Laundromat/Laundromat.js create mode 100644 Laundromat/Laundromat.ts create mode 100644 Laundromat/tsconfig.json diff --git a/Laundromat/Laundromat.css b/Laundromat/Laundromat.css new file mode 100644 index 0000000..ae5c475 --- /dev/null +++ b/Laundromat/Laundromat.css @@ -0,0 +1,362 @@ +body { + font-family: 'Roboto', sans-serif; + overflow: hidden; + position: relative; /* Set position to relative to allow positioning of pseudo-element */ + background: linear-gradient(rgba(21, 27, 48, 0.97), rgba(21, 27, 48, 0.97)), url(https://i.pinimg.com/originals/05/9c/6f/059c6f6f28f86e82367da81344f89206.png); + background-size: cover; +} + +.hack-box-container { + border-radius: 5px; + outline: 2px solid gray; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin: 2% auto; + width: 600px; + height: 800px; +} + +.info-container { + display: flex; + align-items: center; + gap: 15px; + margin-top: -20px; + margin-left: -280px; +} + +.fa-gamepad { + font-size: 35px; + color: rgb(142, 142, 142); +} + +.info-container h2 { + font-size: 25px; + color: rgb(84, 255, 164); + text-shadow: 0 0 2px rgb(127, 255, 191); +} + +.info-container p { + font-size: 15px; + color: rgb(142, 142, 142); +} + +.outer-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + background-color: rgb(15, 27, 33); +} + +.hack-box { + display: flex; + border-radius: 5px; + flex-direction: column; + align-items: center; + justify-content: center; + width: 580px; + height: 580px; + margin-top: 20px; /* Adjusted this line */ + background-color: rgb(22, 40, 52); +} + + + +/* Static lines (Turn line1.... into ts code) */ +.line { + width: 70%; + outline: 1.2px solid rgb(142, 142, 142); +} + + + +/* Lock Circles (turn lock-circle1.... into ts code) */ +.lock-container { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + width: 580px; + height: 580px; +} + +.lock-circle { + outline: 3px solid rgb(173, 173, 173); + border-radius: 50%; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 1; +} + +/* Balls attached to the lock-circles */ +.ball { + width: 17px; + height: 17px; + border-radius: 50%; + background-color: rgb(255, 255, 255); + position: absolute; + z-index: 2; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + transition: transform 0.2s ease-in-out; +} + +/* Only account for 30/60deg and then change the ball's position based on the rotation of the lock-circle */ +/* cos(30deg) = sqrt(3)/2 */ +/* sin(30deg) = 1/2 */ +/* cos(60deg) = 1/2 */ +/* sin(60deg) = sqrt(3)/2 */ + +/* Buttons */ +/* Rotate Buttons */ +.rotate-buttons-container { + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + margin-top: 10px; +} + +.rotate-button { + display: flex; + align-items: center; + justify-content: center; + width: 287px; + height: 50px; + background-color: rgb(49, 37, 76); + color: rgb(147, 62, 171); + border-radius: 5px; + border: none; + font-size: 20px; + font-weight: 500; + cursor: pointer; + gap: 10px; /* Space between arrow and text */ + transition: background-color 0.1s ease-in-out; +} + +.rotate-button:hover { + background-color: rgb(83, 39, 107); +} + +.submit-button-container { + display: flex; + align-items: center; + justify-content: center; + margin-top: 10px; +} + +.submit-button { + display: flex; + align-items: center; + justify-content: center; + width: 579px; + height: 50px; + background-color: rgb(23, 95, 88); + color: rgb(48, 221, 189); + border-radius: 5px; + border: none; + font-size: 20px; + font-weight: 500; + cursor: pointer; + transition: background-color 0.1s ease-in-out; +} + +.submit-button:hover { + background-color: rgb(23, 109, 93); +} + + +/* Timer */ +.timer-container { + background-color: rgb(15, 27, 33); + display: flex; + width: 100%; + height: 10px; +} + +.timer-progress-bar { + background-color: orangered; + width: 100%; + height: 100%; + transition: width 1s linear; +} + +/* The semi-circles that indicate where ball color is supposed to be */ +.position-container{ + display: flex; + align-items: center; + justify-content: center; + position: absolute; + width: 580px; + height: 580px; +} + + +/* r = 55, r = 105, r = 155, r = 205, */ +.position-circle { + fill: none; + stroke-width: 5px; + transform-origin: 50% 50%; +} + +.lose-message { + gap: 10px; + margin-top: -40px; + margin-left: 340px; + display: none; + color: white; + padding: 0px 18px; + border-radius: 5px; + align-items: center; + justify-content: center; + background-color: rgb(56, 13, 23); +} + +.win-message { + gap: 10px; + margin-top: -40px; + margin-left: 340px; + display: none; + color: white; + padding: 0px 10px; + border-radius: 5px; + align-items: center; + justify-content: center; + background-color: rgb(23, 95, 88); +} + +.lose-message p, .win-message p{ + font-size: 12px; + font-weight: 500; +} + +.fa-circle-check { + font-size: 25px; + color: rgb(84, 255, 164); +} + +.fa-circle-xmark { + font-size: 25px; + color: rgb(255, 84, 84); +} + +.overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: transparent; + z-index: 9999; + } +.set-timer-container { + display: flex; + align-items: center; + justify-content: center; + gap: 10px; + margin-top: 10px; +} +.timer { + display: flex; + align-items: center; + justify-content: center; + width: 300px; + height: 50px; + background-color: rgb(23, 95, 88); + color: rgb(48, 221, 189); + border-radius: 5px; + border: none; + font-size: 20px; + font-weight: 500; + cursor: pointer; + transition: background-color 0.1s ease-in-out; +} + +.reset-button { + background-color: #c2fbd7; + border-radius: 100px; + box-shadow: rgba(44, 187, 99, .2) 0 -25px 18px -14px inset,rgba(44, 187, 99, .15) 0 1px 2px,rgba(44, 187, 99, .15) 0 2px 4px,rgba(44, 187, 99, .15) 0 4px 8px,rgba(44, 187, 99, .15) 0 8px 16px,rgba(44, 187, 99, .15) 0 16px 32px; + color: green; + cursor: pointer; + display: inline-block; + font-family: CerebriSans-Regular,-apple-system,system-ui,Roboto,sans-serif; + padding: 7px 20px; + text-align: center; + text-decoration: none; + transition: all 250ms; + border: 0; + font-size: 16px; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; +} + +.reset-button:hover { + box-shadow: rgba(44,187,99,.35) 0 -25px 18px -14px inset,rgba(44,187,99,.25) 0 1px 2px,rgba(44,187,99,.25) 0 2px 4px,rgba(44,187,99,.25) 0 4px 8px,rgba(44,187,99,.25) 0 8px 16px,rgba(44,187,99,.25) 0 16px 32px; + transform: scale(1.05) rotate(-1deg); +} + +.input__group { + position: relative; + padding: 20px 0 0; + width: 100%; + max-width: 180px; + } + + .input__field { + font-family: inherit; + width: 100%; + border: none; + border-bottom: 2px solid #9b9b9b; + outline: 0; + font-size: 17px; + color: #fff; + padding: 7px 0; + background: transparent; + transition: border-color 0.2s; + } + + .input__field::placeholder { + color: transparent; + } + + .input__field:placeholder-shown ~ .input__label { + font-size: 17px; + cursor: text; + top: 20px; + } + + .input__label { + position: absolute; + top: 0; + display: block; + transition: 0.2s; + font-size: 17px; + color: #9b9b9b; + pointer-events: none; + } + + .input__field:focus { + padding-bottom: 6px; + font-weight: 700; + border-width: 3px; + border-image: linear-gradient(to right, #116399, #38caef); + border-image-slice: 1; + } + + .input__field:focus ~ .input__label { + position: absolute; + top: 0; + display: block; + transition: 0.2s; + font-size: 17px; + color: #38caef; + font-weight: 700; + } \ No newline at end of file diff --git a/Laundromat/Laundromat.html b/Laundromat/Laundromat.html new file mode 100644 index 0000000..7f2c24d --- /dev/null +++ b/Laundromat/Laundromat.html @@ -0,0 +1,58 @@ + + + + Laundromat + + + + + + + + +
+
+
+
+

Laundromat

+

Unlock each lock

+
+
+ +

The lockpick bent out of shape.

+
+
+ +

The lock was picked successfully.

+
+
+
+ +
+ + + +
+ +
+
+
+ + +
+
+
+
+
+
+
+
+
0
+
+ + +
+ +
+ + \ No newline at end of file diff --git a/Laundromat/Laundromat.js b/Laundromat/Laundromat.js new file mode 100644 index 0000000..c8427d4 --- /dev/null +++ b/Laundromat/Laundromat.js @@ -0,0 +1,315 @@ +var timerInterval = null; +var timerSeconds = 10; +var secondsRemaining = timerSeconds; +var percentageLeft = 100; +var currentCircle = 1; +var isLocked = false; +function updateTimerDisplay() { + var timerProgress = document.querySelector(".timer-progress-bar"); + var timer = document.querySelector(".timer"); + var currentIncrement = percentageLeft - Math.floor((100 * secondsRemaining) / timerSeconds); + percentageLeft = Math.floor((100 * secondsRemaining) / timerSeconds); + if (percentageLeft - currentIncrement <= 0) { + percentageLeft = 0; + } + if (timerProgress) { + timer.textContent = "".concat(secondsRemaining); + timerProgress.style.width = "".concat(percentageLeft, "%"); + } +} +function runTimer() { + timerInterval = setInterval(function () { + secondsRemaining--; + updateTimerDisplay(); + if (secondsRemaining <= 0) { + resetGame("lose"); + } + }, 1000); +} +function resetGame(status) { + // Remove existing lock circles and SVG elements + var timerProgress = document.querySelector(".timer-progress-bar"); + var timer = document.querySelector(".timer"); + var timerInput = document.querySelector(".input__field"); + var lockContainer = document.querySelector(".lock-container"); + var svgCircle = document.querySelector(".position-container svg"); + var overlay = document.querySelector(".overlay"); + // Block new input from the user when game over + overlay.style.display = "block"; + isLocked = true; + if (status === "init") { + timerSeconds = parseInt(timerInput.value, 10); + timer.textContent = "".concat(timerSeconds); + secondsRemaining = timerSeconds; + } + setTimeout(function () { + lockContainer.innerHTML = ""; + currentCircle = 1; + if (svgCircle) { + svgCircle.innerHTML = ""; + } + overlay.style.display = "none"; + isLocked = false; + removeLines(); + generateLines(); + generateHack(); + shuffleLock(); + runTimer(); + }, 2000); + if (timerInterval) { + clearInterval(timerInterval); + timerProgress.style.display = "none"; + timerProgress.style.width = "100%"; + timer.textContent = "".concat(timerSeconds); + setTimeout(function () { + timerProgress.style.removeProperty("display"); + }, 1000); + secondsRemaining = timerSeconds; + } + if (status === "win") { + var winMsg_1 = document.querySelector(".win-message"); + winMsg_1.style.display = "flex"; + setTimeout(function () { + winMsg_1.style.display = "none"; + }, 2000); + } + else if (status === "lose") { + var loseMsg_1 = document.querySelector(".lose-message"); + loseMsg_1.style.display = "flex"; + indicateFailed(currentCircle); + setTimeout(function () { + loseMsg_1.style.display = "none"; + }, 2000); + } +} +function indicateFailed(circleNum) { + var lockCircle = document.getElementById("lock-circle".concat(circleNum)); + if (lockCircle) { + var balls = lockCircle.querySelectorAll(".ball"); + var svgCircle = document.querySelector(".position-container svg"); + if (svgCircle) { + var semiCircles = svgCircle.querySelectorAll(".position-circle"); + semiCircles.forEach(function (semiCircle) { + if (semiCircle.id.includes("circle".concat(circleNum))) { + var svgElement = semiCircle; + svgElement.style.stroke = "rgb(255, 84, 84)"; + } + }); + } + else { + console.log("SVG element not found in indicateCompleted"); + } + lockCircle.style.outlineColor = "rgb(255, 84, 84)"; + balls.forEach(function (ball) { + ball.style.backgroundColor = "rgb(255, 84, 84)"; + }); + } + else { + console.log("Lock circle ".concat(circleNum, " not found in indicateCompleted")); + } +} +function nextLock() { + var cracked = checkLockStatus(currentCircle); + if (cracked && currentCircle <= 4) { + indicateCompleted(currentCircle); + currentCircle++; + var lockCircle = document.getElementById("lock-circle".concat(currentCircle)); + lockCircle.style.outlineColor = "rgb(239, 181, 17)"; + } + else if (currentCircle === 5 && cracked) { + indicateCompleted(currentCircle); + resetGame("win"); + } + else { + resetGame("lose"); + } +} +function indicateCompleted(circleNum) { + var lockCircle = document.getElementById("lock-circle".concat(circleNum)); + if (lockCircle) { + var balls = lockCircle.querySelectorAll(".ball"); + var svgCircle = document.querySelector(".position-container svg"); + if (svgCircle) { + var semiCircles = svgCircle.querySelectorAll(".position-circle"); + semiCircles.forEach(function (semiCircle) { + if (semiCircle.id.includes("circle".concat(circleNum))) { + var svgElement = semiCircle; + svgElement.style.stroke = "rgba(48, 221, 189, 0.815)"; + } + }); + } + else { + console.log("SVG element not found in indicateCompleted"); + } + lockCircle.style.outlineColor = "rgb(173, 173, 173)"; + balls.forEach(function (ball) { + ball.style.backgroundColor = "rgba(48, 221, 189, 0.815)"; + }); + } + else { + console.log("Lock circle ".concat(circleNum, " not found in indicateCompleted")); + } +} +//Function that runs to randomize the position of the balls compared to their original position +function shuffleLock() { + for (var i = 1; i < 6; i++) { + var shuffleTimes = Math.floor(Math.random() * (12 - 1) + 1); + currentCircle = i; + for (var j = 0; j < shuffleTimes; j++) { + rotateBalls("Right"); + } + } + currentCircle = 1; +} +function checkLockStatus(circleNum) { + var lockCircle = document.getElementById("lock-circle".concat(circleNum)); + var svgCircle = document.querySelector(".position-container svg"); + var semiCircles = svgCircle.querySelectorAll(".position-circle"); + var balls = lockCircle.querySelectorAll("div"); + var allLocks = true; + var currPositionCheck = {}; + balls.forEach(function (ball) { + var position = getRotateZValue(ball.style.transform) % 360; + currPositionCheck[position] = { color: ball.style.backgroundColor }; + }); + semiCircles.forEach(function (semiCircle) { + var _a, _b; + if (semiCircle.id.includes("circle".concat(circleNum))) { + var semiCircleElem = semiCircle; + var semiCirclePos = parseInt(semiCircle.id.split("-")[1], 10); + var semiCircleColor = semiCircleElem.style.stroke; + if (((_a = currPositionCheck[semiCirclePos]) === null || _a === void 0 ? void 0 : _a.color) !== undefined && + ((_b = currPositionCheck[semiCirclePos]) === null || _b === void 0 ? void 0 : _b.color) !== semiCircleColor) { + allLocks = false; + } + } + }); + return allLocks; +} +function shufflePositions(array) { + var _a; + for (var a = array.length - 1; a > 0; a--) { + var b = Math.floor(Math.random() * (a + 1)); + _a = [array[b], array[a]], array[a] = _a[0], array[b] = _a[1]; + } + return array; +} +function removeLines() { + var lines = document.querySelectorAll(".line"); + lines.forEach(function (line) { + line.remove(); + }); +} +function generateLines() { + var hackContainer = document.querySelector(".hack-box"); + for (var i = 1; i < 7; i++) { + var line = document.createElement("div"); + line.className = "line"; + line.id = "line".concat(i); + line.style.transform = "rotateZ(".concat(30 * (i - 1), "deg)"); + hackContainer.appendChild(line); + } +} +function generateCircle(circleNum) { + var lockContainer = document.querySelector(".lock-container"); + var lockCircle = document.createElement("div"); + if (circleNum === 1) { + //Ensure the selector is on the first circle at start + lockCircle.style.outlineColor = "rgb(239, 181, 17)"; + } + lockCircle.id = "lock-circle".concat(circleNum); + lockCircle.className = "lock-circle"; + lockCircle.style.width = "".concat(-20 + 100 * circleNum, "px"); + lockCircle.style.height = "".concat(-20 + 100 * circleNum, "px"); + lockContainer.appendChild(lockCircle); + return lockCircle; +} +function generateSemiCircle(circleNum, position, color) { + var semiCircle = document.createElementNS("http://www.w3.org/2000/svg", "circle"); + var svgCircle = document.querySelector(".position-container svg"); + var r = 5 + circleNum * 50; //The radius needed for the different lockCircles + semiCircle.setAttribute("class", "position-circle"); + semiCircle.setAttribute("id", "circle".concat(circleNum, "-").concat(position)); + semiCircle.setAttribute("cx", "50%"); + semiCircle.setAttribute("cy", "50%"); + semiCircle.setAttribute("r", "".concat(r)); + semiCircle.style.transform = "rotate(".concat(-15 + position, "deg)"); + semiCircle.style.stroke = color; + semiCircle.style.strokeDasharray = "".concat(2 * r * Math.PI); + semiCircle.style.strokeDashoffset = "".concat((11 * (2 * r * Math.PI)) / 12); + svgCircle === null || svgCircle === void 0 ? void 0 : svgCircle.appendChild(semiCircle); +} +function generateHack() { + var positions = [ + 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, + ]; //Available positions (deg) for the balls + var colors = [ + "rgb(202, 39, 97)", + "rgb(239, 181, 17)", + "rgb(46, 134, 213)", + ]; //Available colors for the balls + //Generate between 2-12 balls in different colors for each lock-circle + for (var i = 1; i < 6; i++) { + var positionChecks = Math.floor(Math.random() * (8 - 4) + 4); //The semi-circles that indicate which color needs to be where + var ballAmt = Math.floor(Math.random() * (13 - 5) + 5); + var shuffledPositions = shufflePositions(positions); + var lockCircle = generateCircle(i); + for (var j = 0; j < ballAmt; j++) { + var randomColor = colors[Math.floor(Math.random() * colors.length)]; + var ballElem = document.createElement("div"); + if (j < positionChecks) { + generateSemiCircle(i, shuffledPositions[j], randomColor); + } + ballElem.id = "C".concat(i, "ball").concat(j); + ballElem.className = "ball"; + ballElem.style.transform = "translate(-50%, -50%) rotateZ(".concat(shuffledPositions[j], "deg) translate(").concat(-10 + 50 * i, "px, 0px)"); + ballElem.style.backgroundColor = randomColor; + lockCircle === null || lockCircle === void 0 ? void 0 : lockCircle.appendChild(ballElem); + } + } + currentCircle = 1; +} +function getRotateZValue(transformValue) { + var matches = transformValue.match(/rotateZ\(([^deg)]+)deg\)/); + return matches && matches[1] ? parseFloat(matches[1]) : 0; +} +function rotateBalls(dir) { + var lockCircle = document.getElementById("lock-circle".concat(currentCircle)); + var balls = lockCircle.querySelectorAll("div"); + balls.forEach(function (ball) { + var currentRotateZ = getRotateZValue(ball.style.transform); + var newRotateZ; + if (dir === "Right") { + newRotateZ = currentRotateZ + 30; + } + else { + newRotateZ = currentRotateZ - 30; + } + ball.style.transform = "translate(-50%, -50%) rotateZ(".concat(newRotateZ, "deg) translate(").concat(-10 + 50 * currentCircle, "px, 0px)"); + }); +} +function handleKeyPress(event) { + if (isLocked) + return; //Game is over, key presses are ignored + if (event.key === "ArrowLeft") { + rotateBalls("Left"); + } + else if (event.key === "ArrowRight") { + rotateBalls("Right"); + } + else if (event.key === "Enter") { + nextLock(); + } + else { + return; + } +} +document.addEventListener("DOMContentLoaded", function (event) { + resetGame("init"); +}); +document.addEventListener("click", function (event) { + if (event.target === document.querySelector(".reset-button")) { + resetGame("init"); + } +}); +document.addEventListener("keydown", handleKeyPress); diff --git a/Laundromat/Laundromat.ts b/Laundromat/Laundromat.ts new file mode 100644 index 0000000..9402a50 --- /dev/null +++ b/Laundromat/Laundromat.ts @@ -0,0 +1,385 @@ +let timerInterval: NodeJS.Timeout | null = null; +let timerSeconds = 10; +let secondsRemaining = timerSeconds; +let percentageLeft = 100; +let currentCircle = 1; +let isLocked = false; + +function updateTimerDisplay(): void { + const timerProgress = document.querySelector( + ".timer-progress-bar" + ) as HTMLElement; + const timer = document.querySelector(".timer") as HTMLElement; + const currentIncrement = percentageLeft - Math.floor((100 * secondsRemaining) / timerSeconds); + percentageLeft = Math.floor((100 * secondsRemaining) / timerSeconds); + if (percentageLeft - currentIncrement <= 0) { + percentageLeft = 0; + } + + if (timerProgress) { + timer.textContent = `${secondsRemaining}`; + timerProgress.style.width = `${percentageLeft}%`; + } +} + +function runTimer(): void { + timerInterval = setInterval(() => { + secondsRemaining--; + updateTimerDisplay(); + + if (secondsRemaining <= 0) { + resetGame("lose"); + } + }, 1000); +} + +function resetGame(status: "win" | "lose" | "init"): void { + // Remove existing lock circles and SVG elements + const timerProgress = document.querySelector( + ".timer-progress-bar" + ) as HTMLElement; + const timer = document.querySelector(".timer") as HTMLElement; + const timerInput = document.querySelector(".input__field") as HTMLInputElement; + const lockContainer = document.querySelector( + ".lock-container" + ) as HTMLElement; + const svgCircle = document.querySelector(".position-container svg"); + const overlay = document.querySelector(".overlay") as HTMLElement; + + // Block new input from the user when game over + overlay.style.display = "block"; + isLocked = true; + if (status === "init") { + timerSeconds = parseInt(timerInput.value as string, 10); + timer.textContent = `${timerSeconds}`; + secondsRemaining = timerSeconds; + } + + setTimeout(() => { + lockContainer.innerHTML = ""; + currentCircle = 1; + if (svgCircle) { + svgCircle.innerHTML = ""; + } + overlay.style.display = "none"; + isLocked = false; + removeLines(); + generateLines(); + generateHack(); + shuffleLock(); + runTimer(); + }, 2000); + + if (timerInterval) { + clearInterval(timerInterval); + timerProgress.style.display = "none"; + timerProgress.style.width = "100%"; + timer.textContent = `${timerSeconds}`; + setTimeout(() => { + timerProgress.style.removeProperty("display"); + }, 1000); + secondsRemaining = timerSeconds; + } + + if (status === "win") { + const winMsg = document.querySelector(".win-message") as HTMLElement; + winMsg.style.display = "flex"; + setTimeout(() => { + winMsg.style.display = "none"; + }, 2000); + } else if (status === "lose") { + const loseMsg = document.querySelector(".lose-message") as HTMLElement; + loseMsg.style.display = "flex"; + indicateFailed(currentCircle); + setTimeout(() => { + loseMsg.style.display = "none"; + }, 2000); + } +} + +function indicateFailed(circleNum: number): void { + const lockCircle = document.getElementById( + `lock-circle${circleNum}` + ) as HTMLElement; + + if (lockCircle) { + const balls = lockCircle.querySelectorAll(".ball"); + const svgCircle = document.querySelector(".position-container svg"); + + if (svgCircle) { + const semiCircles = svgCircle.querySelectorAll(".position-circle"); + + semiCircles.forEach((semiCircle) => { + if (semiCircle.id.includes(`circle${circleNum}`)) { + const svgElement = semiCircle as SVGElement; + svgElement.style.stroke = "rgb(255, 84, 84)"; + } + }); + } else { + console.log("SVG element not found in indicateCompleted"); + } + + lockCircle.style.outlineColor = "rgb(255, 84, 84)"; + + balls.forEach((ball) => { + (ball as HTMLElement).style.backgroundColor = "rgb(255, 84, 84)"; + }); + } else { + console.log(`Lock circle ${circleNum} not found in indicateCompleted`); + } +} + +function nextLock(): void { + const cracked = checkLockStatus(currentCircle); + if (cracked && currentCircle <= 4) { + indicateCompleted(currentCircle); + + currentCircle++; + const lockCircle = document.getElementById( + `lock-circle${currentCircle}` + ) as HTMLElement; + lockCircle.style.outlineColor = "rgb(239, 181, 17)"; + } else if (currentCircle === 5 && cracked) { + indicateCompleted(currentCircle); + resetGame("win"); + } else { + resetGame("lose"); + } +} + +function indicateCompleted(circleNum: number): void { + const lockCircle = document.getElementById( + `lock-circle${circleNum}` + ) as HTMLElement; + + if (lockCircle) { + const balls = lockCircle.querySelectorAll(".ball"); + const svgCircle = document.querySelector(".position-container svg"); + + if (svgCircle) { + const semiCircles = svgCircle.querySelectorAll(".position-circle"); + + semiCircles.forEach((semiCircle) => { + if (semiCircle.id.includes(`circle${circleNum}`)) { + const svgElement = semiCircle as SVGElement; + svgElement.style.stroke = "rgba(48, 221, 189, 0.815)"; + } + }); + } else { + console.log("SVG element not found in indicateCompleted"); + } + + lockCircle.style.outlineColor = "rgb(173, 173, 173)"; + + balls.forEach((ball) => { + (ball as HTMLElement).style.backgroundColor = "rgba(48, 221, 189, 0.815)"; + }); + } else { + console.log(`Lock circle ${circleNum} not found in indicateCompleted`); + } +} + +//Function that runs to randomize the position of the balls compared to their original position +function shuffleLock(): void { + for (let i = 1; i < 6; i++) { + const shuffleTimes = Math.floor(Math.random() * (12 - 1) + 1); + currentCircle = i; + for (let j = 0; j < shuffleTimes; j++) { + rotateBalls("Right"); + } + } + currentCircle = 1; +} + +function checkLockStatus(circleNum: number): boolean { + const lockCircle = document.getElementById( + `lock-circle${circleNum}` + ) as HTMLElement; + const svgCircle = document.querySelector( + ".position-container svg" + ) as SVGElement; + const semiCircles = svgCircle.querySelectorAll(".position-circle"); + const balls = lockCircle.querySelectorAll("div"); + let allLocks = true; + + interface positionColor { + color: string; + } + var currPositionCheck: { [id: number]: positionColor } = {}; + balls.forEach((ball) => { + const position = getRotateZValue(ball.style.transform) % 360; + currPositionCheck[position] = { color: ball.style.backgroundColor }; + }); + semiCircles.forEach((semiCircle) => { + if (semiCircle.id.includes(`circle${circleNum}`)) { + const semiCircleElem = semiCircle as SVGElement; + const semiCirclePos = parseInt(semiCircle.id.split("-")[1], 10); + const semiCircleColor = semiCircleElem.style.stroke; + if ( + currPositionCheck[semiCirclePos]?.color !== undefined && + currPositionCheck[semiCirclePos]?.color !== semiCircleColor + ) { + allLocks = false; + } + } + }); + return allLocks; +} + +function shufflePositions(array: number[]): number[] { + for (let a = array.length - 1; a > 0; a--) { + const b = Math.floor(Math.random() * (a + 1)); + [array[a], array[b]] = [array[b], array[a]]; + } + return array; +} + +function removeLines(): void { + const lines = document.querySelectorAll(".line"); + lines.forEach((line) => { + line.remove(); + }); +} + +function generateLines(): void { + const hackContainer = document.querySelector(".hack-box") as HTMLElement; + for (let i = 1; i < 7; i++) { + const line = document.createElement("div") as HTMLElement; + line.className = "line"; + line.id = `line${i}`; + line.style.transform = `rotateZ(${30 * (i - 1)}deg)`; + hackContainer.appendChild(line); + } +} + +function generateCircle(circleNum: number): HTMLElement { + const lockContainer = document.querySelector( + ".lock-container" + ) as HTMLElement; + const lockCircle = document.createElement("div") as HTMLElement; + + if (circleNum === 1) { + //Ensure the selector is on the first circle at start + lockCircle.style.outlineColor = "rgb(239, 181, 17)"; + } + lockCircle.id = `lock-circle${circleNum}`; + lockCircle.className = "lock-circle"; + lockCircle.style.width = `${-20 + 100 * circleNum}px`; + lockCircle.style.height = `${-20 + 100 * circleNum}px`; + lockContainer.appendChild(lockCircle); + return lockCircle; +} + +function generateSemiCircle( + circleNum: number, + position: number, + color: string +): void { + const semiCircle = document.createElementNS( + "http://www.w3.org/2000/svg", + "circle" + ); + const svgCircle = document.querySelector(".position-container svg"); + const r = 5 + circleNum * 50; //The radius needed for the different lockCircles + + semiCircle.setAttribute("class", "position-circle"); + semiCircle.setAttribute("id", `circle${circleNum}-${position}`); + semiCircle.setAttribute("cx", "50%"); + semiCircle.setAttribute("cy", "50%"); + semiCircle.setAttribute("r", `${r}`); + + semiCircle.style.transform = `rotate(${-15 + position}deg)`; + semiCircle.style.stroke = color; + semiCircle.style.strokeDasharray = `${2 * r * Math.PI}`; + semiCircle.style.strokeDashoffset = `${(11 * (2 * r * Math.PI)) / 12}`; + + svgCircle?.appendChild(semiCircle); +} + +function generateHack(): void { + let positions: number[] = [ + 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, + ]; //Available positions (deg) for the balls + let colors: string[] = [ + "rgb(202, 39, 97)", + "rgb(239, 181, 17)", + "rgb(46, 134, 213)", + ]; //Available colors for the balls + + //Generate between 2-12 balls in different colors for each lock-circle + for (let i = 1; i < 6; i++) { + const positionChecks = Math.floor(Math.random() * (8 - 4) + 4); //The semi-circles that indicate which color needs to be where + const ballAmt = Math.floor(Math.random() * (13 - 5) + 5); + const shuffledPositions = shufflePositions(positions); + const lockCircle = generateCircle(i); + + for (let j = 0; j < ballAmt; j++) { + const randomColor = colors[Math.floor(Math.random() * colors.length)]; + const ballElem = document.createElement("div"); + + if (j < positionChecks) { + generateSemiCircle(i, shuffledPositions[j], randomColor); + } + ballElem.id = `C${i}ball${j}`; + ballElem.className = "ball"; + ballElem.style.transform = `translate(-50%, -50%) rotateZ(${ + shuffledPositions[j] + }deg) translate(${-10 + 50 * i}px, 0px)`; + ballElem.style.backgroundColor = randomColor; + lockCircle?.appendChild(ballElem); + } + } + currentCircle = 1; +} + +function getRotateZValue(transformValue: string): number { + const matches = transformValue.match(/rotateZ\(([^deg)]+)deg\)/); + return matches && matches[1] ? parseFloat(matches[1]) : 0; +} + +type Direction = "Left" | "Right"; +function rotateBalls(dir: Direction): void { + const lockCircle = document.getElementById( + `lock-circle${currentCircle}` + ) as HTMLElement; + const balls = lockCircle.querySelectorAll("div"); + + balls.forEach((ball) => { + const currentRotateZ = getRotateZValue(ball.style.transform); + let newRotateZ; + if (dir === "Right") { + newRotateZ = currentRotateZ + 30; + } else { + newRotateZ = currentRotateZ - 30; + } + ball.style.transform = `translate(-50%, -50%) rotateZ(${newRotateZ}deg) translate(${ + -10 + 50 * currentCircle + }px, 0px)`; + }); +} + +function handleKeyPress(event: KeyboardEvent) { + if (isLocked) return; //Game is over, key presses are ignored + + if (event.key === "ArrowLeft") { + rotateBalls("Left"); + } else if (event.key === "ArrowRight") { + rotateBalls("Right"); + } else if (event.key === "Enter") { + nextLock(); + } else { + return; + } +} + +document.addEventListener("DOMContentLoaded", (event) => { + resetGame("init"); +}); + +document.addEventListener("click", (event) => { + if (event.target === document.querySelector(".reset-button")) { + resetGame("init"); + } +}); + +document.addEventListener("keydown", handleKeyPress); diff --git a/Laundromat/tsconfig.json b/Laundromat/tsconfig.json new file mode 100644 index 0000000..956c1ef --- /dev/null +++ b/Laundromat/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es2015", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "outDir": "./" + }, + "include": ["Laundromat.ts"], + "exclude": ["node_modules"] + } + \ No newline at end of file diff --git a/LockPick/LockPick.ts b/LockPick/LockPick.ts index 792719d..1c4f1fd 100644 --- a/LockPick/LockPick.ts +++ b/LockPick/LockPick.ts @@ -4,313 +4,352 @@ let currentCircle = 1; let isLocked = false; function updateTimerDisplay(): void { - const timerProgress = document.querySelector(".timer-progress-bar") as HTMLElement; - const percentageLeft = Math.floor(100*secondsRemaining/20); - - if (timerProgress) { - timerProgress.style.width = `${percentageLeft}%`; - } + const timerProgress = document.querySelector( + ".timer-progress-bar" + ) as HTMLElement; + const percentageLeft = Math.floor((100 * secondsRemaining) / 20); + + if (timerProgress) { + timerProgress.style.width = `${percentageLeft}%`; + } } function runTimer(): void { - timerInterval = setInterval(() => { - secondsRemaining--; - updateTimerDisplay(); + timerInterval = setInterval(() => { + secondsRemaining--; + updateTimerDisplay(); - if (secondsRemaining <= 0) { - resetGame("lose"); - } - }, 1000); + if (secondsRemaining <= 0) { + resetGame("lose"); + } + }, 1000); } function resetGame(status: "win" | "lose" | "init"): void { - // Remove existing lock circles and SVG elements - const timerProgress = document.querySelector(".timer-progress-bar") as HTMLElement; - const lockContainer = document.querySelector('.lock-container') as HTMLElement; - const svgCircle = document.querySelector('.position-container svg'); - const overlay = document.querySelector(".overlay") as HTMLElement; - - // Block new input from the user when game over - overlay.style.display = "block"; - isLocked = true; - - setTimeout(() => { - lockContainer.innerHTML = ''; - currentCircle = 1; - if (svgCircle) { - svgCircle.innerHTML = ''; - } - overlay.style.display = 'none'; - isLocked = false; - generateLines(); - generateHack(); - shuffleLock(); - runTimer(); - }, 2000); - - if (timerInterval) { - clearInterval(timerInterval); - timerProgress.style.display = "none"; - timerProgress.style.width = "100%"; - setTimeout(() => { - timerProgress.style.removeProperty('display'); - }, 1000); - secondsRemaining = 20; - } - - if (status === "win") { - const winMsg = document.querySelector(".win-message") as HTMLElement; - winMsg.style.display = "flex"; - setTimeout (() => { - winMsg.style.display = "none"; - }, 2000); - } else if (status === "lose") { - const loseMsg = document.querySelector(".lose-message") as HTMLElement; - loseMsg.style.display = "flex"; - indicateFailed(currentCircle); - setTimeout (() => { - loseMsg.style.display = "none"; - }, 2000); + // Remove existing lock circles and SVG elements + const timerProgress = document.querySelector( + ".timer-progress-bar" + ) as HTMLElement; + const lockContainer = document.querySelector( + ".lock-container" + ) as HTMLElement; + const svgCircle = document.querySelector(".position-container svg"); + const overlay = document.querySelector(".overlay") as HTMLElement; + + // Block new input from the user when game over + overlay.style.display = "block"; + isLocked = true; + + setTimeout(() => { + lockContainer.innerHTML = ""; + currentCircle = 1; + if (svgCircle) { + svgCircle.innerHTML = ""; } + overlay.style.display = "none"; + isLocked = false; + generateLines(); + generateHack(); + shuffleLock(); + runTimer(); + }, 2000); + + if (timerInterval) { + clearInterval(timerInterval); + timerProgress.style.display = "none"; + timerProgress.style.width = "100%"; + setTimeout(() => { + timerProgress.style.removeProperty("display"); + }, 1000); + secondsRemaining = 20; + } + + if (status === "win") { + const winMsg = document.querySelector(".win-message") as HTMLElement; + winMsg.style.display = "flex"; + setTimeout(() => { + winMsg.style.display = "none"; + }, 2000); + } else if (status === "lose") { + const loseMsg = document.querySelector(".lose-message") as HTMLElement; + loseMsg.style.display = "flex"; + indicateFailed(currentCircle); + setTimeout(() => { + loseMsg.style.display = "none"; + }, 2000); + } } function indicateFailed(circleNum: number): void { - const lockCircle = document.getElementById(`lock-circle${circleNum}`) as HTMLElement; - - if (lockCircle) { - const balls = lockCircle.querySelectorAll('.ball'); - const svgCircle = document.querySelector('.position-container svg'); - - if (svgCircle) { - const semiCircles = svgCircle.querySelectorAll('.position-circle'); - - semiCircles.forEach((semiCircle) => { - if (semiCircle.id.includes(`circle${circleNum}`)) { - const svgElement = semiCircle as SVGElement; - svgElement.style.stroke = 'rgb(255, 84, 84)'; - } - }); - } else { - console.log('SVG element not found in indicateCompleted'); - } + const lockCircle = document.getElementById( + `lock-circle${circleNum}` + ) as HTMLElement; + + if (lockCircle) { + const balls = lockCircle.querySelectorAll(".ball"); + const svgCircle = document.querySelector(".position-container svg"); - lockCircle.style.outlineColor = 'rgb(255, 84, 84)'; + if (svgCircle) { + const semiCircles = svgCircle.querySelectorAll(".position-circle"); - balls.forEach((ball) => { - (ball as HTMLElement).style.backgroundColor = 'rgb(255, 84, 84)'; - }); + semiCircles.forEach((semiCircle) => { + if (semiCircle.id.includes(`circle${circleNum}`)) { + const svgElement = semiCircle as SVGElement; + svgElement.style.stroke = "rgb(255, 84, 84)"; + } + }); } else { - console.log(`Lock circle ${circleNum} not found in indicateCompleted`); + console.log("SVG element not found in indicateCompleted"); } + + lockCircle.style.outlineColor = "rgb(255, 84, 84)"; + + balls.forEach((ball) => { + (ball as HTMLElement).style.backgroundColor = "rgb(255, 84, 84)"; + }); + } else { + console.log(`Lock circle ${circleNum} not found in indicateCompleted`); + } } function nextLock(): void { - const cracked = checkLockStatus(currentCircle); - if (cracked && currentCircle <= 3) { - indicateCompleted(currentCircle); - - currentCircle++; - const lockCircle = document.getElementById(`lock-circle${currentCircle}`) as HTMLElement; - lockCircle.style.outlineColor = 'rgb(239, 181, 17)'; - } else if (currentCircle === 4 && cracked) { - indicateCompleted(currentCircle); - resetGame("win"); - } else { - resetGame("lose"); - } + const cracked = checkLockStatus(currentCircle); + if (cracked && currentCircle <= 3) { + indicateCompleted(currentCircle); + + currentCircle++; + const lockCircle = document.getElementById( + `lock-circle${currentCircle}` + ) as HTMLElement; + lockCircle.style.outlineColor = "rgb(239, 181, 17)"; + } else if (currentCircle === 4 && cracked) { + indicateCompleted(currentCircle); + resetGame("win"); + } else { + resetGame("lose"); + } } function indicateCompleted(circleNum: number): void { - const lockCircle = document.getElementById(`lock-circle${circleNum}`) as HTMLElement; - - if (lockCircle) { - const balls = lockCircle.querySelectorAll('.ball'); - const svgCircle = document.querySelector('.position-container svg'); - - if (svgCircle) { - const semiCircles = svgCircle.querySelectorAll('.position-circle'); - - semiCircles.forEach((semiCircle) => { - if (semiCircle.id.includes(`circle${circleNum}`)) { - const svgElement = semiCircle as SVGElement; - svgElement.style.stroke = 'rgba(48, 221, 189, 0.815)'; - } - }); - } else { - console.log('SVG element not found in indicateCompleted'); - } + const lockCircle = document.getElementById( + `lock-circle${circleNum}` + ) as HTMLElement; + + if (lockCircle) { + const balls = lockCircle.querySelectorAll(".ball"); + const svgCircle = document.querySelector(".position-container svg"); - lockCircle.style.outlineColor = 'rgb(173, 173, 173)'; + if (svgCircle) { + const semiCircles = svgCircle.querySelectorAll(".position-circle"); - balls.forEach((ball) => { - (ball as HTMLElement).style.backgroundColor = 'rgba(48, 221, 189, 0.815)'; - }); + semiCircles.forEach((semiCircle) => { + if (semiCircle.id.includes(`circle${circleNum}`)) { + const svgElement = semiCircle as SVGElement; + svgElement.style.stroke = "rgba(48, 221, 189, 0.815)"; + } + }); } else { - console.log(`Lock circle ${circleNum} not found in indicateCompleted`); + console.log("SVG element not found in indicateCompleted"); } + + lockCircle.style.outlineColor = "rgb(173, 173, 173)"; + + balls.forEach((ball) => { + (ball as HTMLElement).style.backgroundColor = "rgba(48, 221, 189, 0.815)"; + }); + } else { + console.log(`Lock circle ${circleNum} not found in indicateCompleted`); + } } //Function that runs to randomize the position of the balls compared to their original position function shuffleLock(): void { - for (let i = 1; i < 5; i++) { - const shuffleTimes = Math.floor(Math.random() * (12 - 1) + 1); - currentCircle = i; - for (let j = 0; j < shuffleTimes; j++) { - rotateBalls("Right"); - } + for (let i = 1; i < 5; i++) { + const shuffleTimes = Math.floor(Math.random() * (12 - 1) + 1); + currentCircle = i; + for (let j = 0; j < shuffleTimes; j++) { + rotateBalls("Right"); } - currentCircle = 1 + } + currentCircle = 1; } function checkLockStatus(circleNum: number): boolean { - const lockCircle = document.getElementById(`lock-circle${circleNum}`) as HTMLElement; - const svgCircle = document.querySelector('.position-container svg') as SVGElement; - const semiCircles = svgCircle.querySelectorAll('.position-circle'); - const balls = lockCircle.querySelectorAll('div'); - let allLocks = true; - - interface positionColor { - color: string; + const lockCircle = document.getElementById( + `lock-circle${circleNum}` + ) as HTMLElement; + const svgCircle = document.querySelector( + ".position-container svg" + ) as SVGElement; + const semiCircles = svgCircle.querySelectorAll(".position-circle"); + const balls = lockCircle.querySelectorAll("div"); + let allLocks = true; + + interface positionColor { + color: string; + } + var currPositionCheck: { [id: number]: positionColor } = {}; + balls.forEach((ball) => { + const position = getRotateZValue(ball.style.transform) % 360; + currPositionCheck[position] = { color: ball.style.backgroundColor }; + }); + semiCircles.forEach((semiCircle) => { + if (semiCircle.id.includes(`circle${circleNum}`)) { + const semiCircleElem = semiCircle as SVGElement; + const semiCirclePos = parseInt(semiCircle.id.split("-")[1], 10); + const semiCircleColor = semiCircleElem.style.stroke; + if ( + currPositionCheck[semiCirclePos]?.color !== undefined && + currPositionCheck[semiCirclePos]?.color !== semiCircleColor + ) { + allLocks = false; + } } - var currPositionCheck: { [id: number] : positionColor; } = {}; - balls.forEach((ball) => { - const position = getRotateZValue(ball.style.transform)%360; - currPositionCheck[position] = { color: ball.style.backgroundColor }; - }) - semiCircles.forEach((semiCircle) => { - if (semiCircle.id.includes(`circle${circleNum}`)) { - const semiCircleElem = semiCircle as SVGElement; - const semiCirclePos = parseInt(semiCircle.id.split('-')[1], 10); - const semiCircleColor = semiCircleElem.style.stroke; - if (currPositionCheck[semiCirclePos]?.color !== undefined && - currPositionCheck[semiCirclePos]?.color !== semiCircleColor) { - allLocks = false; - } - } - }) - return allLocks + }); + return allLocks; } function shufflePositions(array: number[]): number[] { - for (let a = array.length - 1; a > 0; a--) { - const b = Math.floor(Math.random() * (a + 1)); - [array[a], array[b]] = [array[b], array[a]]; - } - return array; + for (let a = array.length - 1; a > 0; a--) { + const b = Math.floor(Math.random() * (a + 1)); + [array[a], array[b]] = [array[b], array[a]]; + } + return array; } function generateLines(): void { - const hackContainer = document.querySelector('.hack-box') as HTMLElement; - for (let i = 1; i < 7; i++) { - const line = document.createElement('div') as HTMLElement - line.className = 'line'; - line.id = `line${i}`; - line.style.transform = `rotateZ(${30*(i-1)}deg)`; - hackContainer.appendChild(line); - } + const hackContainer = document.querySelector(".hack-box") as HTMLElement; + for (let i = 1; i < 7; i++) { + const line = document.createElement("div") as HTMLElement; + line.className = "line"; + line.id = `line${i}`; + line.style.transform = `rotateZ(${30 * (i - 1)}deg)`; + hackContainer.appendChild(line); + } } function generateCircle(circleNum: number): HTMLElement { - const lockContainer = document.querySelector('.lock-container') as HTMLElement; - const lockCircle = document.createElement('div') as HTMLElement; - - if (circleNum === 1) { //Ensure the selector is on the first circle at start - lockCircle.style.outlineColor = 'rgb(239, 181, 17)' - } - lockCircle.id = `lock-circle${circleNum}`; - lockCircle.className = 'lock-circle'; - lockCircle.style.width = `${-20 + 100*circleNum}px`; - lockCircle.style.height = `${-20 + 100*circleNum}px`; - lockContainer.appendChild(lockCircle); - return lockCircle; + const lockContainer = document.querySelector( + ".lock-container" + ) as HTMLElement; + const lockCircle = document.createElement("div") as HTMLElement; + + if (circleNum === 1) { + //Ensure the selector is on the first circle at start + lockCircle.style.outlineColor = "rgb(239, 181, 17)"; + } + lockCircle.id = `lock-circle${circleNum}`; + lockCircle.className = "lock-circle"; + lockCircle.style.width = `${-20 + 100 * circleNum}px`; + lockCircle.style.height = `${-20 + 100 * circleNum}px`; + lockContainer.appendChild(lockCircle); + return lockCircle; } -function generateSemiCircle(circleNum: number, position: number, color: string): void { - const semiCircle = document.createElementNS("http://www.w3.org/2000/svg", "circle"); - const svgCircle = document.querySelector('.position-container svg'); - const r = 5 + circleNum * 50; //The radius needed for the different lockCircles - - semiCircle.setAttribute("class", "position-circle"); - semiCircle.setAttribute("id", `circle${circleNum}-${position}`); - semiCircle.setAttribute("cx", "50%"); - semiCircle.setAttribute("cy", "50%"); - semiCircle.setAttribute("r", `${r}`); - - semiCircle.style.transform = `rotate(${-15+position}deg)` - semiCircle.style.stroke = color; - semiCircle.style.strokeDasharray = `${2*r*Math.PI}`; - semiCircle.style.strokeDashoffset = `${11*(2*r*Math.PI)/12}`; - - svgCircle?.appendChild(semiCircle); -} +function generateSemiCircle( + circleNum: number, + position: number, + color: string +): void { + const semiCircle = document.createElementNS( + "http://www.w3.org/2000/svg", + "circle" + ); + const svgCircle = document.querySelector(".position-container svg"); + const r = 5 + circleNum * 50; //The radius needed for the different lockCircles + + semiCircle.setAttribute("class", "position-circle"); + semiCircle.setAttribute("id", `circle${circleNum}-${position}`); + semiCircle.setAttribute("cx", "50%"); + semiCircle.setAttribute("cy", "50%"); + semiCircle.setAttribute("r", `${r}`); + + semiCircle.style.transform = `rotate(${-15 + position}deg)`; + semiCircle.style.stroke = color; + semiCircle.style.strokeDasharray = `${2 * r * Math.PI}`; + semiCircle.style.strokeDashoffset = `${(11 * (2 * r * Math.PI)) / 12}`; + + svgCircle?.appendChild(semiCircle); +} function generateHack(): void { - let positions: number[] = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330]; //Available positions (deg) for the balls - let colors: string[] = ['rgb(202, 39, 97)', 'rgb(239, 181, 17)', 'rgb(46, 134, 213)']; //Available colors for the balls - - //Generate between 2-12 balls in different colors for each lock-circle - for (let i = 1; i < 5; i++) { - const positionChecks = Math.floor(Math.random() * (8 - 4) + 4); //The semi-circles that indicate which color needs to be where - const ballAmt = Math.floor(Math.random() * (13 - 5) + 5); - const shuffledPositions = shufflePositions(positions); - const lockCircle = generateCircle(i); - - for (let j = 0; j < ballAmt; j++) { - const randomColor = colors[Math.floor(Math.random() * colors.length)]; - const ballElem = document.createElement('div'); - - if (j < positionChecks) { - generateSemiCircle(i, shuffledPositions[j], randomColor); - } - ballElem.id = `C${i}ball${j}`; - ballElem.className = 'ball'; - ballElem.style.transform = `translate(-50%, -50%) rotateZ(${shuffledPositions[j]}deg) translate(${-10 + 50*i}px, 0px)`; - ballElem.style.backgroundColor = randomColor; - lockCircle?.appendChild(ballElem); - } + let positions: number[] = [ + 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, + ]; //Available positions (deg) for the balls + let colors: string[] = [ + "rgb(202, 39, 97)", + "rgb(239, 181, 17)", + "rgb(46, 134, 213)", + ]; //Available colors for the balls + + //Generate between 2-12 balls in different colors for each lock-circle + for (let i = 1; i < 5; i++) { + const positionChecks = Math.floor(Math.random() * (8 - 4) + 4); //The semi-circles that indicate which color needs to be where + const ballAmt = Math.floor(Math.random() * (13 - 5) + 5); + const shuffledPositions = shufflePositions(positions); + const lockCircle = generateCircle(i); + + for (let j = 0; j < ballAmt; j++) { + const randomColor = colors[Math.floor(Math.random() * colors.length)]; + const ballElem = document.createElement("div"); + + if (j < positionChecks) { + generateSemiCircle(i, shuffledPositions[j], randomColor); + } + ballElem.id = `C${i}ball${j}`; + ballElem.className = "ball"; + ballElem.style.transform = `translate(-50%, -50%) rotateZ(${ + shuffledPositions[j] + }deg) translate(${-10 + 50 * i}px, 0px)`; + ballElem.style.backgroundColor = randomColor; + lockCircle?.appendChild(ballElem); } - currentCircle = 1; + } + currentCircle = 1; } function getRotateZValue(transformValue: string): number { - const matches = transformValue.match(/rotateZ\(([^deg)]+)deg\)/); - return matches && matches[1] ? parseFloat(matches[1]) : 0; + const matches = transformValue.match(/rotateZ\(([^deg)]+)deg\)/); + return matches && matches[1] ? parseFloat(matches[1]) : 0; } -type Direction = 'Left' | 'Right'; +type Direction = "Left" | "Right"; function rotateBalls(dir: Direction): void { - const lockCircle = document.getElementById(`lock-circle${currentCircle}`) as HTMLElement - const balls = lockCircle.querySelectorAll('div') - - balls.forEach((ball) => { - const currentRotateZ = getRotateZValue(ball.style.transform); - let newRotateZ; - if (dir === 'Right') { - newRotateZ = currentRotateZ + 30 - - } else { - newRotateZ = currentRotateZ - 30 - } - ball.style.transform = `translate(-50%, -50%) rotateZ(${newRotateZ}deg) translate(${-10 + 50*currentCircle}px, 0px)`; - }) + const lockCircle = document.getElementById( + `lock-circle${currentCircle}` + ) as HTMLElement; + const balls = lockCircle.querySelectorAll("div"); + + balls.forEach((ball) => { + const currentRotateZ = getRotateZValue(ball.style.transform); + let newRotateZ; + if (dir === "Right") { + newRotateZ = currentRotateZ + 30; + } else { + newRotateZ = currentRotateZ - 30; + } + ball.style.transform = `translate(-50%, -50%) rotateZ(${newRotateZ}deg) translate(${ + -10 + 50 * currentCircle + }px, 0px)`; + }); } function handleKeyPress(event: KeyboardEvent) { - if (isLocked) return; //Game is over, key presses are ignored - - if (event.key === "ArrowLeft") { - rotateBalls('Left'); - } else if (event.key === "ArrowRight") { - rotateBalls('Right'); - } else if (event.key === "Enter") { - nextLock(); - } else { - return; - } + if (isLocked) return; //Game is over, key presses are ignored + + if (event.key === "ArrowLeft") { + rotateBalls("Left"); + } else if (event.key === "ArrowRight") { + rotateBalls("Right"); + } else if (event.key === "Enter") { + nextLock(); + } else { + return; + } } -document.addEventListener('DOMContentLoaded', (event) => { - resetGame("init"); -}) +document.addEventListener("DOMContentLoaded", (event) => { + resetGame("init"); +}); -document.addEventListener('keydown', handleKeyPress); +document.addEventListener("keydown", handleKeyPress); diff --git a/index.html b/index.html index 939fa82..5b49fbd 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,7 @@ From a1978d4ba39b3f1da964888e5ddf00b0db469d84 Mon Sep 17 00:00:00 2001 From: Gabriel Vendrame-Piche Date: Mon, 12 Feb 2024 18:10:22 -0500 Subject: [PATCH 2/8] home-button --- Laundromat/Laundromat.css | 31 +++++++++++++++++++++++++++++++ Laundromat/Laundromat.html | 3 +++ LockPick/LockPick.css | 31 +++++++++++++++++++++++++++++++ LockPick/LockPick.html | 3 +++ RepairKit/RepairKit.css | 31 +++++++++++++++++++++++++++++++ RepairKit/RepairKit.html | 3 +++ RoofRunning/RoofRunning.css | 31 +++++++++++++++++++++++++++++++ RoofRunning/RoofRunning.html | 3 +++ SmokeCrack/SmokeCrack.css | 33 ++++++++++++++++++++++++++++++++- SmokeCrack/SmokeCrack.html | 3 +++ 10 files changed, 171 insertions(+), 1 deletion(-) diff --git a/Laundromat/Laundromat.css b/Laundromat/Laundromat.css index ae5c475..6a447a3 100644 --- a/Laundromat/Laundromat.css +++ b/Laundromat/Laundromat.css @@ -359,4 +359,35 @@ body { font-size: 17px; color: #38caef; font-weight: 700; + } + + .other-container { + display: flex; + align-items: left; + justify-content: left; + gap: 10px; + margin-top: 10px; + } + .home-button { + background-color: #3292ec; + border-radius: 100px; + box-shadow: rgba(37, 138, 227, 0.2) 0 -25px 18px -14px inset,rgba(37, 138, 227, 0.2) 0 1px 2px,rgba(37, 138, 227, 0.2) 0 2px 4px,rgba(37, 138, 227, 0.2) 0 4px 8px,rgba(37, 138, 227, 0.2) 0 8px 16px,rgba(37, 138, 227, 0.2) 0 16px 32px; + color: black; + cursor: pointer; + display: inline-block; + font-family: CerebriSans-Regular,-apple-system,system-ui,Roboto,sans-serif; + padding: 10px 20px; + text-align: center; + text-decoration: none; + transition: all 250ms; + border: 0; + font-size: 16px; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; + } + + .home-button:hover { + box-shadow: rgba(72, 147, 233, 0.35) 0 -25px 18px -14px inset,rgba(72, 147, 233, 0.35) 0 1px 2px,rgba(72, 147, 233, 0.35) 0 2px 4px,rgba(72, 147, 233, 0.35) 0 4px 8px,rgba(72, 147, 233, 0.35) 0 8px 16px,rgba(72, 147, 233, 0.35) 0 16px 32px; + transform: scale(1.05) rotate(-1deg); } \ No newline at end of file diff --git a/Laundromat/Laundromat.html b/Laundromat/Laundromat.html index 7f2c24d..4c8e9d9 100644 --- a/Laundromat/Laundromat.html +++ b/Laundromat/Laundromat.html @@ -10,6 +10,9 @@ +
diff --git a/LockPick/LockPick.css b/LockPick/LockPick.css index 9ff46a7..7ac2c30 100644 --- a/LockPick/LockPick.css +++ b/LockPick/LockPick.css @@ -255,4 +255,35 @@ body { height: 100%; background-color: transparent; z-index: 9999; + } + + .other-container { + display: flex; + align-items: left; + justify-content: left; + gap: 10px; + margin-top: 10px; + } + .home-button { + background-color: #3292ec; + border-radius: 100px; + box-shadow: rgba(37, 138, 227, 0.2) 0 -25px 18px -14px inset,rgba(37, 138, 227, 0.2) 0 1px 2px,rgba(37, 138, 227, 0.2) 0 2px 4px,rgba(37, 138, 227, 0.2) 0 4px 8px,rgba(37, 138, 227, 0.2) 0 8px 16px,rgba(37, 138, 227, 0.2) 0 16px 32px; + color: black; + cursor: pointer; + display: inline-block; + font-family: CerebriSans-Regular,-apple-system,system-ui,Roboto,sans-serif; + padding: 10px 20px; + text-align: center; + text-decoration: none; + transition: all 250ms; + border: 0; + font-size: 16px; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; + } + + .home-button:hover { + box-shadow: rgba(72, 147, 233, 0.35) 0 -25px 18px -14px inset,rgba(72, 147, 233, 0.35) 0 1px 2px,rgba(72, 147, 233, 0.35) 0 2px 4px,rgba(72, 147, 233, 0.35) 0 4px 8px,rgba(72, 147, 233, 0.35) 0 8px 16px,rgba(72, 147, 233, 0.35) 0 16px 32px; + transform: scale(1.05) rotate(-1deg); } \ No newline at end of file diff --git a/LockPick/LockPick.html b/LockPick/LockPick.html index ac7d21f..efa3e2d 100644 --- a/LockPick/LockPick.html +++ b/LockPick/LockPick.html @@ -10,6 +10,9 @@ +
diff --git a/RepairKit/RepairKit.css b/RepairKit/RepairKit.css index 63640cc..3415119 100644 --- a/RepairKit/RepairKit.css +++ b/RepairKit/RepairKit.css @@ -87,4 +87,35 @@ body { .square-slot::after { bottom: -2px; /* Adjust the margin-bottom as needed */ +} + +.other-container { + display: flex; + align-items: left; + justify-content: left; + gap: 10px; + margin-top: 10px; +} +.home-button { + background-color: #3292ec; + border-radius: 100px; + box-shadow: rgba(37, 138, 227, 0.2) 0 -25px 18px -14px inset,rgba(37, 138, 227, 0.2) 0 1px 2px,rgba(37, 138, 227, 0.2) 0 2px 4px,rgba(37, 138, 227, 0.2) 0 4px 8px,rgba(37, 138, 227, 0.2) 0 8px 16px,rgba(37, 138, 227, 0.2) 0 16px 32px; + color: black; + cursor: pointer; + display: inline-block; + font-family: CerebriSans-Regular,-apple-system,system-ui,Roboto,sans-serif; + padding: 10px 20px; + text-align: center; + text-decoration: none; + transition: all 250ms; + border: 0; + font-size: 16px; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; +} + +.home-button:hover { + box-shadow: rgba(72, 147, 233, 0.35) 0 -25px 18px -14px inset,rgba(72, 147, 233, 0.35) 0 1px 2px,rgba(72, 147, 233, 0.35) 0 2px 4px,rgba(72, 147, 233, 0.35) 0 4px 8px,rgba(72, 147, 233, 0.35) 0 8px 16px,rgba(72, 147, 233, 0.35) 0 16px 32px; + transform: scale(1.05) rotate(-1deg); } \ No newline at end of file diff --git a/RepairKit/RepairKit.html b/RepairKit/RepairKit.html index dfc9198..b7a4f24 100644 --- a/RepairKit/RepairKit.html +++ b/RepairKit/RepairKit.html @@ -9,6 +9,9 @@ +
E
diff --git a/RoofRunning/RoofRunning.css b/RoofRunning/RoofRunning.css index 33dc171..ffa1564 100644 --- a/RoofRunning/RoofRunning.css +++ b/RoofRunning/RoofRunning.css @@ -217,4 +217,35 @@ body { #instructions-content.active { display: block; +} + +.other-container { + display: flex; + align-items: left; + justify-content: left; + gap: 10px; + margin-top: 10px; +} +.home-button { + background-color: #3292ec; + border-radius: 100px; + box-shadow: rgba(37, 138, 227, 0.2) 0 -25px 18px -14px inset,rgba(37, 138, 227, 0.2) 0 1px 2px,rgba(37, 138, 227, 0.2) 0 2px 4px,rgba(37, 138, 227, 0.2) 0 4px 8px,rgba(37, 138, 227, 0.2) 0 8px 16px,rgba(37, 138, 227, 0.2) 0 16px 32px; + color: black; + cursor: pointer; + display: inline-block; + font-family: CerebriSans-Regular,-apple-system,system-ui,Roboto,sans-serif; + padding: 10px 20px; + text-align: center; + text-decoration: none; + transition: all 250ms; + border: 0; + font-size: 16px; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; +} + +.home-button:hover { + box-shadow: rgba(72, 147, 233, 0.35) 0 -25px 18px -14px inset,rgba(72, 147, 233, 0.35) 0 1px 2px,rgba(72, 147, 233, 0.35) 0 2px 4px,rgba(72, 147, 233, 0.35) 0 4px 8px,rgba(72, 147, 233, 0.35) 0 8px 16px,rgba(72, 147, 233, 0.35) 0 16px 32px; + transform: scale(1.05) rotate(-1deg); } \ No newline at end of file diff --git a/RoofRunning/RoofRunning.html b/RoofRunning/RoofRunning.html index 5e196ed..2dbf6a3 100644 --- a/RoofRunning/RoofRunning.html +++ b/RoofRunning/RoofRunning.html @@ -13,6 +13,9 @@ +
diff --git a/SmokeCrack/SmokeCrack.css b/SmokeCrack/SmokeCrack.css index f30e251..c1331bf 100644 --- a/SmokeCrack/SmokeCrack.css +++ b/SmokeCrack/SmokeCrack.css @@ -440,4 +440,35 @@ body { .lvl-hard .difficulty-bar { background-color: rgb(255, 84, 84); -} \ No newline at end of file +} + +.other-container { + display: flex; + align-items: left; + justify-content: left; + gap: 10px; + margin-top: 10px; + } + .home-button { + background-color: #3292ec; + border-radius: 100px; + box-shadow: rgba(37, 138, 227, 0.2) 0 -25px 18px -14px inset,rgba(37, 138, 227, 0.2) 0 1px 2px,rgba(37, 138, 227, 0.2) 0 2px 4px,rgba(37, 138, 227, 0.2) 0 4px 8px,rgba(37, 138, 227, 0.2) 0 8px 16px,rgba(37, 138, 227, 0.2) 0 16px 32px; + color: black; + cursor: pointer; + display: inline-block; + font-family: CerebriSans-Regular,-apple-system,system-ui,Roboto,sans-serif; + padding: 10px 20px; + text-align: center; + text-decoration: none; + transition: all 250ms; + border: 0; + font-size: 16px; + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; + } + + .home-button:hover { + box-shadow: rgba(72, 147, 233, 0.35) 0 -25px 18px -14px inset,rgba(72, 147, 233, 0.35) 0 1px 2px,rgba(72, 147, 233, 0.35) 0 2px 4px,rgba(72, 147, 233, 0.35) 0 4px 8px,rgba(72, 147, 233, 0.35) 0 8px 16px,rgba(72, 147, 233, 0.35) 0 16px 32px; + transform: scale(1.05) rotate(-1deg); + } \ No newline at end of file diff --git a/SmokeCrack/SmokeCrack.html b/SmokeCrack/SmokeCrack.html index 51bfdb6..d0c4a60 100644 --- a/SmokeCrack/SmokeCrack.html +++ b/SmokeCrack/SmokeCrack.html @@ -10,6 +10,9 @@ +
From 7599a773b2015a81cb53077bd1b090019a130267 Mon Sep 17 00:00:00 2001 From: Gabriel Vendrame-Piche Date: Mon, 12 Feb 2024 18:36:39 -0500 Subject: [PATCH 3/8] fixed timer display --- Laundromat/Laundromat.js | 9 +++++---- Laundromat/Laundromat.ts | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Laundromat/Laundromat.js b/Laundromat/Laundromat.js index c8427d4..b0fa099 100644 --- a/Laundromat/Laundromat.js +++ b/Laundromat/Laundromat.js @@ -9,15 +9,16 @@ function updateTimerDisplay() { var timer = document.querySelector(".timer"); var currentIncrement = percentageLeft - Math.floor((100 * secondsRemaining) / timerSeconds); percentageLeft = Math.floor((100 * secondsRemaining) / timerSeconds); - if (percentageLeft - currentIncrement <= 0) { - percentageLeft = 0; - } + // if (percentageLeft - currentIncrement <= 0) { + // percentageLeft = 0; + // } if (timerProgress) { timer.textContent = "".concat(secondsRemaining); - timerProgress.style.width = "".concat(percentageLeft, "%"); + timerProgress.style.width = "".concat(percentageLeft - 10, "%"); } } function runTimer() { + updateTimerDisplay(); timerInterval = setInterval(function () { secondsRemaining--; updateTimerDisplay(); diff --git a/Laundromat/Laundromat.ts b/Laundromat/Laundromat.ts index 9402a50..cbe275f 100644 --- a/Laundromat/Laundromat.ts +++ b/Laundromat/Laundromat.ts @@ -12,21 +12,21 @@ function updateTimerDisplay(): void { const timer = document.querySelector(".timer") as HTMLElement; const currentIncrement = percentageLeft - Math.floor((100 * secondsRemaining) / timerSeconds); percentageLeft = Math.floor((100 * secondsRemaining) / timerSeconds); - if (percentageLeft - currentIncrement <= 0) { - percentageLeft = 0; - } + // if (percentageLeft - currentIncrement <= 0) { + // percentageLeft = 0; + // } if (timerProgress) { timer.textContent = `${secondsRemaining}`; - timerProgress.style.width = `${percentageLeft}%`; + timerProgress.style.width = `${percentageLeft-10}%`; } } function runTimer(): void { + updateTimerDisplay(); timerInterval = setInterval(() => { secondsRemaining--; updateTimerDisplay(); - if (secondsRemaining <= 0) { resetGame("lose"); } From 2e6d4d239557b4fb4461388f062da2bc51d8a376 Mon Sep 17 00:00:00 2001 From: Gabriel Vendrame-Piche Date: Mon, 12 Feb 2024 19:04:44 -0500 Subject: [PATCH 4/8] added-key-input A -> Rotate Left D -> Rotate Right Space -> Lock --- Laundromat/Laundromat.js | 10 +++------- Laundromat/Laundromat.ts | 12 ++++-------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/Laundromat/Laundromat.js b/Laundromat/Laundromat.js index b0fa099..b3dfefc 100644 --- a/Laundromat/Laundromat.js +++ b/Laundromat/Laundromat.js @@ -7,11 +7,7 @@ var isLocked = false; function updateTimerDisplay() { var timerProgress = document.querySelector(".timer-progress-bar"); var timer = document.querySelector(".timer"); - var currentIncrement = percentageLeft - Math.floor((100 * secondsRemaining) / timerSeconds); percentageLeft = Math.floor((100 * secondsRemaining) / timerSeconds); - // if (percentageLeft - currentIncrement <= 0) { - // percentageLeft = 0; - // } if (timerProgress) { timer.textContent = "".concat(secondsRemaining); timerProgress.style.width = "".concat(percentageLeft - 10, "%"); @@ -292,13 +288,13 @@ function rotateBalls(dir) { function handleKeyPress(event) { if (isLocked) return; //Game is over, key presses are ignored - if (event.key === "ArrowLeft") { + if (event.key === "ArrowLeft" || event.key === "a") { rotateBalls("Left"); } - else if (event.key === "ArrowRight") { + else if (event.key === "ArrowRight" || event.key === "d") { rotateBalls("Right"); } - else if (event.key === "Enter") { + else if (event.key === "Enter" || event.key === " ") { nextLock(); } else { diff --git a/Laundromat/Laundromat.ts b/Laundromat/Laundromat.ts index cbe275f..6c0071e 100644 --- a/Laundromat/Laundromat.ts +++ b/Laundromat/Laundromat.ts @@ -10,12 +10,8 @@ function updateTimerDisplay(): void { ".timer-progress-bar" ) as HTMLElement; const timer = document.querySelector(".timer") as HTMLElement; - const currentIncrement = percentageLeft - Math.floor((100 * secondsRemaining) / timerSeconds); percentageLeft = Math.floor((100 * secondsRemaining) / timerSeconds); - // if (percentageLeft - currentIncrement <= 0) { - // percentageLeft = 0; - // } - + if (timerProgress) { timer.textContent = `${secondsRemaining}`; timerProgress.style.width = `${percentageLeft-10}%`; @@ -361,11 +357,11 @@ function rotateBalls(dir: Direction): void { function handleKeyPress(event: KeyboardEvent) { if (isLocked) return; //Game is over, key presses are ignored - if (event.key === "ArrowLeft") { + if (event.key === "ArrowLeft" || event.key === "a") { rotateBalls("Left"); - } else if (event.key === "ArrowRight") { + } else if (event.key === "ArrowRight" || event.key === "d") { rotateBalls("Right"); - } else if (event.key === "Enter") { + } else if (event.key === "Enter" || event.key === " ") { nextLock(); } else { return; From 0ca34ed75ec18242e40b75da9ca0a2943b12ebf9 Mon Sep 17 00:00:00 2001 From: Gabriel Vendrame-Piche Date: Mon, 12 Feb 2024 19:25:08 -0500 Subject: [PATCH 5/8] fix css --- Laundromat/Laundromat.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Laundromat/Laundromat.css b/Laundromat/Laundromat.css index 6a447a3..65fedc4 100644 --- a/Laundromat/Laundromat.css +++ b/Laundromat/Laundromat.css @@ -23,7 +23,7 @@ body { align-items: center; gap: 15px; margin-top: -20px; - margin-left: -280px; + margin-left: -250px; } .fa-gamepad { From ae8bd728c50be25be36607a45392776677f2621a Mon Sep 17 00:00:00 2001 From: Gabriel Vendrame-Piche Date: Mon, 12 Feb 2024 19:33:23 -0500 Subject: [PATCH 6/8] fix css --- Laundromat/Laundromat.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Laundromat/Laundromat.css b/Laundromat/Laundromat.css index 65fedc4..cd8ea2d 100644 --- a/Laundromat/Laundromat.css +++ b/Laundromat/Laundromat.css @@ -68,7 +68,7 @@ body { /* Static lines (Turn line1.... into ts code) */ .line { - width: 70%; + width: 83%; outline: 1.2px solid rgb(142, 142, 142); } @@ -79,7 +79,7 @@ body { display: flex; align-items: center; justify-content: center; - position: absolute; + position: absolute; width: 580px; height: 580px; } @@ -194,6 +194,7 @@ body { align-items: center; justify-content: center; position: absolute; + z-index: 50; width: 580px; height: 580px; } From 9b42ba0b323ca98761674bd2a45f9401afdd3f24 Mon Sep 17 00:00:00 2001 From: Gabriel Vendrame-Piche Date: Mon, 12 Feb 2024 19:37:11 -0500 Subject: [PATCH 7/8] fix css for lockpick too --- LockPick/LockPick.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/LockPick/LockPick.css b/LockPick/LockPick.css index 7ac2c30..cbf385c 100644 --- a/LockPick/LockPick.css +++ b/LockPick/LockPick.css @@ -68,7 +68,7 @@ body { /* Static lines (Turn line1.... into ts code) */ .line { - width: 70%; + width: 65%; outline: 1.2px solid rgb(142, 142, 142); } @@ -194,6 +194,7 @@ body { align-items: center; justify-content: center; position: absolute; + z-index: 50; width: 580px; height: 580px; } From ebdb99b70715a34bae13235b9cfe659c7dd86166 Mon Sep 17 00:00:00 2001 From: Gabriel Vendrame-Piche Date: Mon, 12 Feb 2024 20:53:06 -0500 Subject: [PATCH 8/8] fix progress bar for every seconds --- Laundromat/Laundromat.js | 7 ++++++- Laundromat/Laundromat.ts | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Laundromat/Laundromat.js b/Laundromat/Laundromat.js index b3dfefc..22b06fd 100644 --- a/Laundromat/Laundromat.js +++ b/Laundromat/Laundromat.js @@ -10,7 +10,12 @@ function updateTimerDisplay() { percentageLeft = Math.floor((100 * secondsRemaining) / timerSeconds); if (timerProgress) { timer.textContent = "".concat(secondsRemaining); - timerProgress.style.width = "".concat(percentageLeft - 10, "%"); + if (percentageLeft - (100 / timerSeconds) <= 0) { + timerProgress.style.width = "0%"; + } + else { + timerProgress.style.width = "".concat(percentageLeft - (100 / timerSeconds), "%"); + } } } function runTimer() { diff --git a/Laundromat/Laundromat.ts b/Laundromat/Laundromat.ts index 6c0071e..a2a62aa 100644 --- a/Laundromat/Laundromat.ts +++ b/Laundromat/Laundromat.ts @@ -11,10 +11,13 @@ function updateTimerDisplay(): void { ) as HTMLElement; const timer = document.querySelector(".timer") as HTMLElement; percentageLeft = Math.floor((100 * secondsRemaining) / timerSeconds); - if (timerProgress) { timer.textContent = `${secondsRemaining}`; - timerProgress.style.width = `${percentageLeft-10}%`; + if (percentageLeft-(100/timerSeconds) <= 0) { + timerProgress.style.width = "0%"; + } else { + timerProgress.style.width = `${percentageLeft-(100/timerSeconds)}%`; + } } }