From c46f3c0229f5fc7260eb00b03bde19a320af4c50 Mon Sep 17 00:00:00 2001 From: shchengweii Date: Mon, 6 Dec 2021 15:14:06 +0800 Subject: [PATCH 1/3] completed Base timer design --- script.js | 393 +++++++++++++++++++++++++++++++++++++++++++++++++++++ styles.css | 79 ++++++++++- 2 files changed, 471 insertions(+), 1 deletion(-) diff --git a/script.js b/script.js index e2d0297..ec488af 100644 --- a/script.js +++ b/script.js @@ -1 +1,394 @@ // Please implement exercise logic here + +// Notes: +// # to indicate for Base exercises + +// # Base: Match Game Stopwatch +// 1. Use buildBoard function to create the boards first +// 2. Build and test the stopwatch in stages +// 2.1 counts up seconds, minutes and hours +// 2.2 stopwatch can be stopped + +// =================================================== +// Global Variables +// =================================================== + +// boardSize has to be an even number +const boardSize = 4; +const board = []; +// let messageBoard; +let firstCard = null; +let firstCardElement; +let deck; +let secondCard; +let secondCardElement; +let userName = ''; +const boardElement = document.createElement('div'); + +// =================================================== +// Gameplay Logic +// =================================================== + +const squareClick = (messageBoard, cardElement, column, row) => { + console.log(cardElement); + + console.log('FIRST CARD DOM ELEMENT', firstCard); + + console.log('BOARD CLICKED CARD', board[column][row]); + + // console.log to show the column and row + + console.log(column); + console.log(row); + + const clickedCard = board[column][row]; + console.log(userName); + + // create default messages for messageBoard when its a match + // messageBoard.innerText = 'Its a match!'; + // console.log(messageBoard.innerText); + + // the user already clicked on this square + if (cardElement.innerText !== '') { + return; + } + + // first turn + if (firstCard === null) { + console.log('first turn'); + firstCard = clickedCard; + + // turn this card over + // !!! reference codes to add both suitSymbol and displayName details + cardElement.classList.add('card'); + cardElement.innerHTML = `${firstCard.suitSymbol}
${firstCard.displayName}`; + // cardElement.innerText = firstCard.name; + + // hold onto this for later when it may not match + firstCardElement = cardElement; + // !!! display message when user open the first card + messageBoard.innerText = `You opened ${firstCard.displayName} of ${firstCard.suitSymbol}. Click on another card and see if it matches!`; + + // second turn + } else { + console.log('second turn'); + if ( + // clickedCard here refers to the second card clicked + clickedCard.name === firstCard.name && + clickedCard.suit === firstCard.suit + ) { + console.log('match'); + console.log(clickedCard); + console.log(firstCard); + + // !!! reference codes to add cardDisplay details + cardElement.innerHTML = `${clickedCard.suitSymbol}
${clickedCard.displayName}`; + // !!! display message when user open the second card + messageBoard.innerText = `You opened ${clickedCard.displayName} of ${clickedCard.suitSymbol}. Click on another card and see if it matches!`; + + // display match meesage + messageBoard.innerText = 'Congrats! Its a match!'; + + // add setTimeout to display the match message and disappear after 3s + setTimeout(() => { + messageBoard.innerText = ''; + }, 3000); + + // turn this card over + cardElement.innerText = clickedCard.name; + } else { + secondCard = clickedCard; + cardElement.innerText = secondCard.name; + secondCardElement = cardElement; + console.log('NOT a match'); + + // !!! reference codes to add cardDisplay details + cardElement.innerHTML = `${clickedCard.suitSymbol}
${clickedCard.displayName}`; + // display not-match meesage + messageBoard.innerText = 'Sorry! Its not a match!'; + + // add setTimeout function to turn both cards over when they are not a match + setTimeout(() => { + // both functions inside setTimeout are to turn the cards back over + firstCardElement.innerText = ''; + secondCardElement.innerText = ''; + // no-match message to disappear after 3s + messageBoard.innerText = ''; + }, 3000); + // reset the first card + firstCard = null; + } + } +}; + +// =================================================== +// Helper Functions +// =================================================== + +// Get a random index ranging from 0 (inclusive) to max (exclusive). +const getRandomIndex = (max) => Math.floor(Math.random() * max); + +// Shuffle an array of cards +const shuffleCards = (cards) => { + // Loop over the card deck array once + for (let currentIndex = 0; currentIndex < cards.length; currentIndex += 1) { + // Select a random index in the deck + const randomIndex = getRandomIndex(cards.length); + // Select the card that corresponds to randomIndex + const randomCard = cards[randomIndex]; + // Select the card that corresponds to currentIndex + const currentCard = cards[currentIndex]; + // Swap positions of randomCard and currentCard in the deck + cards[currentIndex] = randomCard; + cards[randomIndex] = currentCard; + } + // Return the shuffled deck + return cards; +}; + +// =================================================== +// New Make Deck +// =================================================== + +const makeDeck = () => { + // create the empty deck at the beginning + const newDeck = []; + // Initialise an array of the 4 suits in our deck. We will loop over this array. + const suits = ['hearts', 'diamonds', 'clubs', 'spades']; + const suitSymbols = ['♥', '♦️', '♣', '♠']; + const suitColours = ['red', 'red', 'black', 'black']; + + for (let suitIndex = 0; suitIndex < suits.length; suitIndex += 1) { + // make a variable of the current suit + const currentSuit = suits[suitIndex]; + console.log(`current suit: ${currentSuit}`); + const currentSuitSymbol = suitSymbols[suitIndex]; + const currentColour = suitColours[suitIndex]; + + // Loop from 1 to 13 to create all cards for a given suit + // Notice rankCounter starts at 1 and not 0, and ends at 13 and not 12. + // This is an example of a loop without an array. + for (let rankCounter = 1; rankCounter <= 13; rankCounter += 1) { + // Convert rankCounter to string + let cardName = `${rankCounter}`; + let displayName = `${rankCounter}`; + // following code will keep display heart suits + // let suitSymbol = `${currentSuitSymbol}`; + + // 1, 11, 12 ,13 + if (cardName === '1') { + cardName = 'ace'; + } else if (cardName === '11') { + cardName = 'jack'; + } else if (cardName === '12') { + cardName = 'queen'; + } else if (cardName === '13') { + cardName = 'king'; + } + + // make a single card object variable + const card = { + name: cardName, + suit: currentSuit, + rank: rankCounter, + colour: currentColour, + displayName, + suitSymbol: currentSuitSymbol, + }; + + console.log(`rank: ${rankCounter}`); + + // add the card to the deck + newDeck.push(card); // add double the cards to the deck + newDeck.push(card); + } + } + + return newDeck; +}; + +// =================================================== +// Game Initialisation Logic +// =================================================== + +// create all the board elements that will go on the screen +// return the built board +// for comfortable qns > create a messageboard element +const buildBoardElements = (board) => { + // create the boardElement that everything will go inside of + const boardElement = document.createElement('div'); + + // give it a class for CSS purposes + boardElement.classList.add('board'); + + // // create a element for player to enter the name + // const inputMessage = document.createElement('box'); + // inputMessage.classList.add('input'); + // inputMessage.innerText = 'Please enter your name: '; + // boardElement.appendChild(inputMessage); + + // // create an input box for userName + // const userName = document.createElement('input'); + // userName.classList.add('name'); + // boardElement.appendChild(userName); + + // // create a button to store the userName + // // user input the name and press the button to store the name into the userName global variable + // const storeNameBtn = document.createElement('button'); + // storeNameBtn.innerText = 'Submit'; + // boardElement.appendChild(storeNameBtn); + // // add eventListener to store the name when button is clicked + + // create a messageboard element + const messageBoard = document.createElement('div'); + messageBoard.classList.add('messageBoard'); + messageBoard.innerText = + 'Click on the boxes to play the game. You have 3 minutes for the game!'; + boardElement.appendChild(messageBoard); + + // === # Time functions! + + // startTimer function + + // create a 3 minutes timer element + let milliseconds = 1800000; + const delayInMilliseconds = 1000; + const output = document.createElement('div'); + output.innerText = milliseconds; + boardElement.appendChild(output); + + // use the timer functions + const ref = setInterval(() => { + output.innerText = milliseconds; + + if (milliseconds === 0) { + // remove all the boxes when time is up + boardElement.innerText = ''; + clearInterval(ref); + output.innerText = 'Time is Up!'; + } + milliseconds -= 1; + }, delayInMilliseconds); + + // # create timerElement where all the timer related elements will go inside + const timerElement = document.createElement('div'); + // # give it a class for CSS purposes + timerElement.classList.add('timer'); + + // create a lap data element + const lapDataBoard = document.createElement('div'); + // give it a class for CSS purposes + lapDataBoard.classList.add('lapData'); + lapDataBoard.innerText = 'Lap Data'; + timerElement.appendChild(lapDataBoard); + + // create Elapsed Time element + const elapTimeBoard = document.createElement('div'); + elapTimeBoard.classList.add('elapTime'); + const timerBoard = document.createElement('div'); + // create a timerBoard to show the minutes and seconds on the timer + timerBoard.classList.add('timer-board'); + timerBoard.innerText = 'Elapsed Time'; + elapTimeBoard.appendChild(timerBoard); + timerElement.appendChild(elapTimeBoard); + + // create start, stop, reset, lap elements + const startButton = document.createElement('button'); + startButton.classList.add('btn'); + startButton.innerText = 'Start'; + // need to create a startTimer function + // startButton.addEventListener('click', startTimer); + // create an internal div + timerElement.appendChild(startButton); + + // stop element + const stopButton = document.createElement('button'); + stopButton.classList.add('btn'); + stopButton.innerText = 'Stop'; + // need to create a stopTimer function + stopButton.addEventListener('click', stopButton); + timerElement.appendChild(stopButton); + + // reset element + const resetButton = document.createElement('button'); + resetButton.classList.add('btn'); + resetButton.innerText = 'Reset'; + // need tp create a resetTimer function + // resetButton.addEventListener('click', resetTimer); + timerElement.appendChild(resetButton); + + // lap element + const lapBoard = document.createElement('button'); + lapBoard.classList.add('btn'); + lapBoard.innerText = 'Lap'; + timerElement.appendChild(lapBoard); + + // append the timerElement into the boardElement + boardElement.appendChild(timerElement); + + // use the board data structure we passed in to create the correct size board + for (let i = 0; i < board.length; i += 1) { + // make a var for just this row of cards + const row = board[i]; + // make an element for this row of cards + const rowElement = document.createElement('div'); + rowElement.classList.add('row'); + + // make all the squares for this row + for (let j = 0; j < row.length; j += 1) { + // create the square element + const square = document.createElement('div'); + + // set a class for CSS purposes + square.classList.add('square'); + + // set the click event + // eslint-disable-next-line + square.addEventListener('click', (event) => { + // we will want to pass in the card element so + // that we can change how it looks on screen, i.e., + // "turn the card over" + + // ~~~ .currentTarget refers to the particular element + // box at the moment out of the entire 16 element boxes + squareClick(messageBoard, event.currentTarget, i, j); + }); + + rowElement.appendChild(square); + } + boardElement.appendChild(rowElement); + } + return boardElement; +}; + +// =================================================== +// Initiate the game +// =================================================== +const initGame = () => { + // create this special deck by getting the doubled cards and + // making a smaller array that is ( boardSize squared ) number of cards + const doubleDeck = makeDeck(); + + // to get 16 cards (boardSize * boardSize) out of the deck + const deckSubset = doubleDeck.slice(0, boardSize * boardSize); + deck = shuffleCards(deckSubset); + + // deal the cards out to the board data structure + for (let i = 0; i < boardSize; i += 1) { + board.push([]); + for (let j = 0; j < boardSize; j += 1) { + board[i].push(deck.pop()); + } + } + + const boardEl = buildBoardElements(board); + + document.body.appendChild(boardEl); +}; + +// initiate the gameplay +initGame(); + +// =================================================== +// Main Functions +// =================================================== diff --git a/styles.css b/styles.css index 04e7110..1b99506 100644 --- a/styles.css +++ b/styles.css @@ -1,3 +1,80 @@ body { - background-color: pink; + background-color: #b7b7a4; + box-sizing: border-box; +} + +.square { + padding: 50px; + margin: 10px; + background-color: white; + display: inline-block; + border-radius: 8px; + height: 13px; + width: 2px; + vertical-align: top; +} + +.input { + padding: auto; + margin: auto; +} + +.card { + padding: 50px; + margin: 10px; + background-color: #9a8c98; + width: 10px; + height: 50px; + text-align: center; + border-radius: 8px; + display: inline-block; +} + +​ .suit { + margin: 5px; + font-size: 20px; +} + +​ .messageBoard { + background-color: white; + padding: 10px; + margin: 10px; + width: 480px; + border-radius: 5px; + text-align: center; +} + +.timer { + padding: 50px; + margin: 10px; + background-color: #ffe8d6; + width: 360px; + height: 150px; + text-align: center; + border-radius: 8px; + display: block; +} + +.lapData { + margin: 10px auto; + border: 2px solid black; + height: 20px; + border-radius: 10px; + padding: 10px; +} + +.timer-board { + margin: 10 px auto; + height: 20px; + background-color: aliceblue; + border: 2px solid black; + border-radius: 20px; + padding: 10px; +} + +.btn { + margin: 20px 15px; + border: 2px solid black; + border-radius: 10px; + padding: 10px; } From 245326e9d2290a0fbfd7d7976b344cad088e1979 Mon Sep 17 00:00:00 2001 From: shchengweii Date: Sun, 16 Jan 2022 22:36:24 +0800 Subject: [PATCH 2/3] edited timerGame to include start stop and reset functions --- index.html | 35 ++++++++++++++++++++++-- script2.js | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ styles.css | 78 ++++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 175 insertions(+), 10 deletions(-) create mode 100644 script2.js diff --git a/index.html b/index.html index 4771b50..e737a8b 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,44 @@ - Timer + + + + SWE101 + + +

Timer!

+
+
+
Lapse Data
+
+
+
+ Elased Time +
00:00
+
+
+ + +
+
+ + +
+
+
+ - + + diff --git a/script2.js b/script2.js new file mode 100644 index 0000000..9f612db --- /dev/null +++ b/script2.js @@ -0,0 +1,72 @@ +// alert("hello!") + +// =================================================== +// Global Variables +// =================================================== +let timer; + +// create a timer function globally to run the time +let totalSeconds = 0; +const increaseInMilliseconds = 1000; + +// timer display functions +// hr:min:sec (milsec) +// 00:00:00 (000) +// e.g +// split 1: 00:00:03 (361) +// + + + +// =================================================== +// Selection of buttons & addEventListeners +// =================================================== + +// set up for #start-btn +let startBtn = document.getElementById("start-btn") +// link button to call back function +startBtn.addEventListener('click',()=> { + timer = setInterval(() => { + startBtn.disabled = true; + // resetBtn.disabled = true; + document.getElementById("lapse-time").innerHTML =`Time: ${totalSeconds} seconds`; + console.log('start timer'); + + // emable startBtn again + startBtn.disabled = false; + totalSeconds += 1; +}, increaseInMilliseconds); +}) + +// set up for #stop-btn +const stopBtn = document.getElementById("stop-btn") +// clear the timer when the button is clicked +stopBtn.addEventListener('click',()=>clearInterval(timer)) + +// set up for #reset-btn +const resetBtn = document.getElementById("reset-btn") +// link button to call back function +resetBtn.addEventListener('click',()=>resetTimer()) + +// set up for #lap-btn +const lapBtn = document.getElementById("lap-btn") +// link button to call back function +resetBtn.addEventListener('click',()=>lapTimer()) + + + +// =================================================== +// helper functions +// =================================================== + + + +// resetBtn callback functions +const resetTimer=()=> { + // lapBtn.disabled=true; + document.getElementById("lapse-time").innerHTML = "00:00" + totalSeconds = 0; +} + + +// lapBtn callback functions diff --git a/styles.css b/styles.css index 1b99506..52bec19 100644 --- a/styles.css +++ b/styles.css @@ -1,9 +1,71 @@ body { background-color: #b7b7a4; box-sizing: border-box; + font-family: "Caveat", cursive; + margin: 10vw 20vw 0 20vw; + text-align: center; +} + +#header { + text-align: center; + size: 30em; +} +#time-container { + display: flex; + flex-direction: row; + justify-content: center; + position: absolute; + width: auto; + height: auto; +} + +#col-1 { + width: 30vw; + height: 40vh; +} + +#col-2 { + width: 30vw; + height: 40vh; +} + +.lapdata-row { + background-color: white; + width: 100%; + height: 100%; + overflow: scroll; +} +.time-row { + background-color: tomato; + width: 100%; + height: 20%; +} + +.btns-row-1 { + display: flex; + flex-direction: row; + justify-content: space-between; + height: 20%; +} +.btns-row-2 { + display: flex; + flex-direction: row; + justify-content: space-between; + height: 20%; +} + +.button { + width: 100%; + height: 100%; + cursor: pointer; } -.square { +.button:hover { + background-color: #ffe4e1; + color: #ff4500; +} + +/* .square { padding: 50px; margin: 10px; background-color: white; @@ -12,9 +74,9 @@ body { height: 13px; width: 2px; vertical-align: top; -} +} */ -.input { +/* .input { padding: auto; margin: auto; } @@ -28,9 +90,9 @@ body { text-align: center; border-radius: 8px; display: inline-block; -} +} */ -​ .suit { +/* ​ .suit { margin: 5px; font-size: 20px; } @@ -42,9 +104,9 @@ body { width: 480px; border-radius: 5px; text-align: center; -} +} */ -.timer { +/* .timer { padding: 50px; margin: 10px; background-color: #ffe8d6; @@ -77,4 +139,4 @@ body { border: 2px solid black; border-radius: 10px; padding: 10px; -} +} */ From 054f5792571c93103354db3e129908463065eedc Mon Sep 17 00:00:00 2001 From: shchengweii Date: Mon, 17 Jan 2022 14:43:14 +0800 Subject: [PATCH 3/3] added lapsestopwatch laps and splits --- index.html | 10 +++++--- script2.js | 74 ++++++++++++++++++++++++++++++++++++++++++++++-------- styles.css | 3 ++- 3 files changed, 72 insertions(+), 15 deletions(-) diff --git a/index.html b/index.html index e737a8b..663cf7d 100644 --- a/index.html +++ b/index.html @@ -18,12 +18,16 @@

Timer!

-
Lapse Data
+
Lapse Data
- Elased Time -
00:00
+ Elased Time
+ 00: + 00: + 00: + 000 +
diff --git a/script2.js b/script2.js index 9f612db..3b5555c 100644 --- a/script2.js +++ b/script2.js @@ -7,16 +7,26 @@ let timer; // create a timer function globally to run the time let totalSeconds = 0; -const increaseInMilliseconds = 1000; +const increaseInMilliseconds = 10; // timer display functions // hr:min:sec (milsec) // 00:00:00 (000) // e.g // split 1: 00:00:03 (361) -// +// select the respecitve span elements and assign to variables +const milliSecondOutput = document.getElementById('milli-second') +const secondOutput = document.getElementById('second') +const minuteOutput = document.getElementById('minute') +const hourOutput = document.getElementById('hour') +const lapData = document.getElementById("lapdata-row") +// declare global variables +let milliSecond = 0; +let second = 0; +let minute = 0; +let hour = 0; // =================================================== // Selection of buttons & addEventListeners @@ -28,13 +38,41 @@ let startBtn = document.getElementById("start-btn") startBtn.addEventListener('click',()=> { timer = setInterval(() => { startBtn.disabled = true; - // resetBtn.disabled = true; - document.getElementById("lapse-time").innerHTML =`Time: ${totalSeconds} seconds`; + + milliSecond++; + // increament for milliSecond + if (milliSecond <99) { + milliSecondOutput.innerHTML = `${milliSecond}` + } + if (milliSecond >99) { + second++; + milliSecond = 0 + secondOutput.innerHTML = `0${second}` + } + // increament for second + if (second >10) { + secondOutput.innerHTML = `${second}` + } + if (second >59) { + minute++; + second = 0 + minuteOutput.innerHTML = `0${minute}` + } + + // increament for minute + if (minute >10) { + secondOutput.innerHTML = `${second}` + } + if (minute >59) { + hour++; + minute = 0; + hourOutput.innerHTML = `0${hour}` + } + console.log('start timer'); - // emable startBtn again + // enable startBtn again startBtn.disabled = false; - totalSeconds += 1; }, increaseInMilliseconds); }) @@ -48,10 +86,10 @@ const resetBtn = document.getElementById("reset-btn") // link button to call back function resetBtn.addEventListener('click',()=>resetTimer()) -// set up for #lap-btn +// // set up for #lap-btn const lapBtn = document.getElementById("lap-btn") // link button to call back function -resetBtn.addEventListener('click',()=>lapTimer()) +lapBtn.addEventListener('click',()=>lapTimer()) @@ -59,14 +97,28 @@ resetBtn.addEventListener('click',()=>lapTimer()) // helper functions // =================================================== +// create a startTimer function +// const startTimer = () => {} -// resetBtn callback functions +// resetBtn callback function const resetTimer=()=> { // lapBtn.disabled=true; - document.getElementById("lapse-time").innerHTML = "00:00" - totalSeconds = 0; + milliSecond = 0; + second = 0; + minute = 0; + hour = 0; + milliSecondOutput.innerHTML = '000' + secondOutput.innerHTML = '00:' + minuteOutput.innerHTML = '00:' + hourOutput.innerHTML = '00:' + lapData.innerHTML=""; } // lapBtn callback functions +const lapTimer =()=>{ + const lapList = document.createElement("li"); + lapList.innerHTML = `${hour}:${minute}:${second}:${milliSecond}` + lapData.appendChild(lapList); +} \ No newline at end of file diff --git a/styles.css b/styles.css index 52bec19..8bd33db 100644 --- a/styles.css +++ b/styles.css @@ -3,6 +3,7 @@ body { box-sizing: border-box; font-family: "Caveat", cursive; margin: 10vw 20vw 0 20vw; + font-size: large; text-align: center; } @@ -29,7 +30,7 @@ body { height: 40vh; } -.lapdata-row { +#lapdata-row { background-color: white; width: 100%; height: 100%;