diff --git a/index.js b/index.js index d1df9db..53db607 100644 --- a/index.js +++ b/index.js @@ -574,38 +574,114 @@ function initSocket(socket, userId) { }); }); - // TODO - socket.on("startReadAnswers", (data, fn) => { - // Get all the chosen cards for this round - db.query(` - SELECT id - FROM white_cards - WHERE id IN ( - SELECT card_id - FROM room_white_cards - WHERE room_id = ? AND state = ${vars.CardStates.selected} - ); - `, [user.roomId], (err, results, fields) => { - if (err) { - return console.warn("Failed to get selected cards for room #" + user.roomId + ":", err); - } else if (results.length == 0) { - return console.warn("Didn't find any selected cards for room #" + user.roomId + " despite all players having submitted"); - } + socket.on("startReadingAnswers", (data, fn) => { + var user = getUser(userId, true); + if (user.error) return fn(user); + if (user.state != vars.UserStates.czar) { + console.warn("User #" + userId + " with state '" + user.state + "' tried to start reading answers!"); + return fn({error: "Invalid User State"}); + } - var cardChoices = {}; + db.getRoom(user.roomId, room => { + if (room.error) return fn(room); + if (room.state != vars.RoomStates.choosingCards) return fn({error: "Invalid Room State"}); - results.forEach(result => { - cardChoices[result.id] = { - id: result.id, - text: result.text - }; + db.getRoomUsers(user.roomId, response => { + if (response.error) { + console.warn("Failed to get users when switching to reading mode in room #" + user.roomId); + return fn(response); + } else if (response.userIds.length == 0) return fn({error: "Invalid Room"}); + + + db.query(` + SELECT id + FROM white_cards + WHERE id IN ( + SELECT card_id + FROM room_white_cards + WHERE room_id = ? AND state = ${vars.CardStates.selected} + ); + `, [user.roomId], (err, results, fields) => { + if (err) { + console.warn("Failed to get selected cards for room #" + user.roomId + ":", err); + return fn({error: "MySQL Error"}); + } else if (results.length < 2) { + return fn({error: "Not enough cards selected!"}); + } + + fn({}); + db.setRoomState(user.roomId, vars.RoomStates.readingCards); + + response.userIds.forEach(roomUserId => { + if (!users.hasOwnProperty(roomUserId)) return; + + users[roomUserId].socket.emit("startReadingAnswers", { + count: results.length + }); + }); + }); }); + }); + }); + + socket.on("revealResponse", (data, fn) => { + if (!helpers.validateUInt(data.position)) return fn({error: "Invalid Card Position"}); + var user = getUser(userId, true); + if (user.error) return fn(user); + if (user.state != vars.UserStates.czar) { + console.warn("User #" + userId + " with state '" + user.state + "' tried to reveal a response!"); + return fn({error: "Invalid User State"}); + } - response.userIds.forEach(roomUserId => { - if (!users.hasOwnProperty(roomUserId)) return; + db.getRoom(user.roomId, room => { + if (room.error) return fn(room); + if (room.state != vars.RoomStates.readingCards) return fn({error: "Invalid Room State"}); - users[roomUserId].socket.emit("cardChoices", { - choices: cardChoices + db.getRoomUsers(user.roomId, response => { + if (response.error) { + console.warn("Failed to get users when revealing card in room #" + user.roomId); + return fn(response); + } else if (response.userIds.length == 0) return fn({error: "Invalid Room"}); + + db.query(` + SELECT id, text + FROM white_cards + WHERE id IN ( + SELECT card_id + FROM room_white_cards + WHERE room_id = ? AND state = ${vars.CardStates.selected} + ) + ORDER BY RAND() + LIMIT 1; + `, [user.roomId], (err, results, fields) => { + if (err) { + console.warn("Failed to get selected cards for room #" + user.roomId + ":", err); + return fn({error: "MySQL Error"}); + } else if (results.length == 0) { + return fn({error: "No cards left!"}); + } + + var card = { + id: results[0].id, + text: results[0].text + } + + db.query(`UPDATE room_white_cards SET state = ${vars.CardStates.revealed} WHERE card_id = ? `, + [card.id], (err, results) => { + if (err) { + console.warn("Failed to mark card as read:", err); + return fn({error: "MySQL Error"}); + } + fn({}); + response.userIds.forEach(roomUserId => { + if (!users.hasOwnProperty(roomUserId)) return; + var socketUser = users[roomUserId]; + socketUser.socket.emit("revealResponse", { + position: data.position, + card: card + }); + }); + }); }); }); }); diff --git a/public/inc/main.js b/public/inc/main.js index 453ed05..1803f12 100644 --- a/public/inc/main.js +++ b/public/inc/main.js @@ -559,11 +559,6 @@ $("#set-username").submit(event => { populateUserList(users); $("#setup-spinner").hide(); - - // TODO: get cards from server - for (var i = 0; i < 4; i++) { - appendCardBack($("#response-cards")); - } }); } }); @@ -685,6 +680,24 @@ socket.on("answersReady", () => { $("#central-action").show().text("Read Answers"); }); +socket.on("startReadingAnswers", (data) => { + room.state = RoomStates.readingCards; + var isCzar = users[userId].state == UserStates.czar; + + $("#cur-black-card").addClass("responses-shown"); + + for (var i = 0; i < data.count; i++) { + addResponseCard(i, isCzar); + } +}); + +socket.on("revealResponse", (data) => { + var cardElement = $("#response-card-" + data.position); + cardElement.removeClass("back").addClass("front"); + cardElement.children(".card-text").text(data.card.text); + cardElement.attr("id", "response-revealed-" + data.card.id); +}); + /******************** * Card Interaction * ********************/ @@ -695,14 +708,27 @@ var selectedCard = null; // Set to true while waiting for a server response from selectCard var submittingCard = false; -function appendCardBack(target, isWhite=true) { +function appendCardBack(target, id, isWhite=true) { target.append(` -
+
Cards Against Quarantine
`); } +function addResponseCard(id, isCzar) { + appendCardBack($("#response-cards"), "response-card-" + id); + + // Only the czar can reveal answers + if (isCzar) { + $("#response-card-" + id).click(event => { + socket.emit("revealResponse", {position: id}, response => { + if (response.error) return console.warn("Failed to reveal respose #" + id + ":", response.error); + }); + }); + } +} + function appendCard(card, target, isWhite=true) { var color = isWhite ? "white" : "black"; var id = color + "-card-" + card.id; @@ -784,7 +810,10 @@ $("#central-action").click(event => { var curState = users[userId].state; if (curState == UserStates.czar) { - console.debug("do it !"); + socket.emit("startReadingAnswers", {}, response => { + if (response.error) return console.warn("Failed to start reading answers:", response.error); + $("#central-action").hide(); + }); } else if (curState == UserStates.choosing) { submitCard(); } diff --git a/public/inc/main.scss b/public/inc/main.scss index 63e2868..9940723 100644 --- a/public/inc/main.scss +++ b/public/inc/main.scss @@ -277,6 +277,25 @@ input[type=text] { .card { margin: 10px; transition: $resizeTransition; + + .card-text::after { + bottom: 112px; + + + + @media only screen and (min-width: 1450px) { + bottom: 3px; + } + @media only screen and (min-width: 1550px) { + bottom: 8px; + } + } + + &:hover { + .card-text::after { + bottom: 0; + } + } } @media only screen and (max-height: 850px) { @@ -347,7 +366,6 @@ input[type=text] { } &:not(.czar-mode) { top: calc(35% - #{$cardHeight * $cardScale / 2 - 37px}); - background-color: red; } } diff --git a/public/index.html b/public/index.html index 3d2292f..056ec6f 100644 --- a/public/index.html +++ b/public/index.html @@ -24,10 +24,10 @@
-
+
-
Select Winner
+
diff --git a/vars.js b/vars.js index 149ef87..1363654 100644 --- a/vars.js +++ b/vars.js @@ -23,6 +23,6 @@ exports.RoomStates = Object.freeze({ exports.CardStates = Object.freeze({ "hand": 1, // The card is in a players hand "selected": 2, // The card has been submitted - "read": 3, // The card has been flipped over and read + "revealed": 3, // The card has been flipped over and read "played": 4 // The card has been removed from play }); \ No newline at end of file