Better handling of room creation and management

This commit is contained in:
Marcus Noble 2020-11-27 18:29:18 +00:00
parent 5716a9338a
commit aad99975c6
11 changed files with 2898 additions and 91 deletions

1
public/build/bundle.css Normal file
View File

@ -0,0 +1 @@
main.svelte-1tky8bj{text-align:center;padding:1em;max-width:240px;margin:0 auto}h1.svelte-1tky8bj{color:#ff3e00;text-transform:uppercase;font-size:4em;font-weight:100}@media(min-width: 640px){main.svelte-1tky8bj{max-width:none}}main.svelte-1tky8bj{text-align:center;padding:1em;max-width:240px;margin:0 auto}h1.svelte-1tky8bj{color:#ff3e00;text-transform:uppercase;font-size:4em;font-weight:100}@media(min-width: 640px){main.svelte-1tky8bj{max-width:none}}main.svelte-1tky8bj{text-align:center;padding:1em;max-width:240px;margin:0 auto}h1.svelte-1tky8bj{color:#ff3e00;text-transform:uppercase;font-size:4em;font-weight:100}@media(min-width: 640px){main.svelte-1tky8bj{max-width:none}}main.svelte-1tky8bj{text-align:center;padding:1em;max-width:240px;margin:0 auto}h1.svelte-1tky8bj{color:#ff3e00;text-transform:uppercase;font-size:4em;font-weight:100}@media(min-width: 640px){main.svelte-1tky8bj{max-width:none}}

2726
public/build/bundle.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -24,6 +24,10 @@ form {
margin: 0 auto;
}
label {
font-weight: bold;
}
input[type=text] {
text-transform: lowercase;
}
@ -31,6 +35,7 @@ input[type=text] {
input {
border: 1px solid silver;
display: block;
text-align: center;
font-size: 16px;
margin-bottom: 10px;
padding: 5px;
@ -73,6 +78,11 @@ footer {
text-shadow: 2px 2px 2px black;
}
#buzzer.active {
background: greenyellow;
box-shadow: inset 4px 4px 4px rgba(0,0,0,.5);
}
#buzzer:active {
box-shadow: inset 4px 4px 4px rgba(0,0,0,.5);
}

91
room.js
View File

@ -41,24 +41,30 @@ function addParticipant(roomId, participantId, participantName) {
function removeParticipant(roomId, participantId) {
let room = getOrCreateRoom(roomId);
room.participants.find(p => p.participantId === participantId).active = false;
room.audience.forEach(ws => {
ws.send(JSON.stringify({
type: "participants",
participants: room.participants
}));
});
let participant = room.participants.find(p => p.participantId === participantId);
if (participant) {
participant.active = false;
room.audience.forEach(ws => {
ws.send(JSON.stringify({
type: "participants",
participants: room.participants
}));
});
}
}
function addParticipantWS(roomId, participantId, ws) {
let room = getOrCreateRoom(roomId);
room.participants.find(p => p.participantId === participantId).ws = ws;
room.audience.forEach(ws => {
ws.send(JSON.stringify({
type: "participants",
participants: room.participants
}));
});
let participant = room.participants.find(p => p.participantId === participantId);
if (participant) {
participant.ws = ws;
room.audience.forEach(ws => {
ws.send(JSON.stringify({
type: "participants",
participants: room.participants
}));
});
}
}
function addAudienceWS(roomId, ws) {
@ -74,26 +80,53 @@ function buzz(roomId, participant) {
let room = getOrCreateRoom(roomId);
if (room.canBuzz) {
room.canBuzz = false;
setTimeout(() => room.canBuzz = true, 5000);
participant = room.participants.find(p => p.participantId === participant.participantId);
room.participants.forEach(p => {
if (p.ws && p.participantId !== participant.participantId) {
p.ws.send(JSON.stringify({
if (participant) {
room.participants.forEach(p => {
if (p.ws && p.participantId !== participant.participantId) {
p.ws.send(JSON.stringify({
type: "buzz",
participant: participant.participantName,
msg: `<img src="${participant.character}"><div>${participant.participantName} buzzed!</div>`
}));
}
});
room.audience.forEach(ws => {
ws.send(JSON.stringify({
type: "buzz",
participant: participant.participantName,
msg: `<img src="${participant.character}"><div>${participant.participantName} buzzed!</div>`
participant: participant
}));
}
});
room.audience.forEach(ws => {
ws.send(JSON.stringify({
type: "buzz",
participant: participant
}));
});
});
}
}
}
module.exports = {getOrCreateRoom, addParticipant, addParticipantWS, addAudienceWS, buzz, removeParticipant}
function reset(roomId) {
let room = getOrCreateRoom(roomId);
room.canBuzz = true;
room.participants.forEach(p => {
p.ws.send(JSON.stringify({
type: "reset"
}));
});
}
function closeRoom(roomId) {
let room = getOrCreateRoom(roomId);
room.canBuzz = false;
room.participants.forEach(p => {
if (p.ws) {
p.ws.send(JSON.stringify({
type: "close"
}));
}
});
delete rooms[roomId];
}
module.exports = {getOrCreateRoom, addParticipant, addParticipantWS, addAudienceWS, buzz, removeParticipant, reset, closeRoom}

View File

@ -6,6 +6,7 @@ const WebSocket = require('ws');
const http = require('http');
const randomWords = require('random-words');
const rooms = require('./room');
const room = require("./room");
const app = express();
const server = http.createServer(app);
@ -25,32 +26,33 @@ app.get("/", (request, response) => {
});
});
app.get("/:roomId/join", (request, response) => {
let room = rooms.getOrCreateRoom(request.params.roomId.toLowerCase());
app.get("/:roomId", (request, response) => {
let room = rooms.getOrCreateRoom(request.params.roomId.trim().toLowerCase());
let participant = room.participants.find(p => p.participantId === request.fingerprint.hash);
if (participant) {
if (room.audience.length === 0) {
response.render('audience', {
layout: false,
room: request.params.roomId.trim().toLowerCase(),
participants: room.participants,
});
} else if (participant) {
response.render('room', {
layout: false,
room: request.params.roomId.toLowerCase(),
room: request.params.roomId.trim().toLowerCase(),
name: participant.participantName,
participantName: participant.participantName,
participantId: participant.participantId,
character: participant.character,
});
} else {
response.render('join', {layout: false, room: request.params.roomId.toLowerCase()});
response.render('join', {layout: false, room: request.params.roomId.trim().toLowerCase()});
}
});
app.get("/:roomId/audience", (request, response) => {
let room = rooms.getOrCreateRoom(request.params.roomId.toLowerCase());
response.render('audience', {layout: false, room: request.params.roomId.toLowerCase(), participants: room.participants });
});
app.post("/:roomId/join", (request, response) => {
app.post("/:roomId", (request, response) => {
rooms.addParticipant(request.params.roomId.toLowerCase(), request.fingerprint.hash, request.body.name);
response.redirect(`/${request.params.roomId.toLowerCase()}/join`);
response.redirect(`/${request.params.roomId.toLowerCase()}`);
});
server.listen(process.env.PORT, () => {
@ -65,6 +67,17 @@ wss.on('connection', (ws, req) => {
if (roomId.includes("/audience")) {
roomId = roomId.replace("/audience", "");
rooms.addAudienceWS(roomId, ws);
ws.on('message', (message) => {
message = JSON.parse(message);
if (message.type === "reset") {
rooms.reset(roomId);
}
});
ws.on('close', () => {
room.closeRoom(roomId);
});
} else {
let participant;
ws.on('message', (message) => {

View File

@ -14,22 +14,32 @@
</header>
<main>
<p>
Share this link for players to join:<br>
<a id="playerRoom" href=""></a>
</p>
<button id="resetBuzzers">Reset</button>
<h2>Participants</h2>
<div id="participants"></div>
</main>
<script>
let socket = new WebSocket(`wss://${window.location.hostname}/{{room}}/audience`);
document.getElementById("playerRoom").href = window.location;
document.getElementById("playerRoom").innerText = window.location;
let proto = location.protocol == 'http:' ? 'ws' : 'wss'
let socket = new WebSocket(`${proto}://${window.location.hostname}:${window.location.port}/{{room}}/audience`);
let buzzed;
socket.onmessage = function(event) {
let msg = JSON.parse(event.data);
if (msg.type === "buzz") {
beep();
let buzzed = document.getElementById(`p-${msg.participant.participantId}`);
buzzed = document.getElementById(`p-${msg.participant.participantId}`);
buzzed.classList.add('buzzed');
setTimeout(() => buzzed.classList.remove('buzzed'), 5000)
} else if (msg.type === "participants") {
let participantContainer = document.getElementById('participants');
let contents = '';
@ -48,6 +58,13 @@
function beep() {
window.navigator.vibrate(500);
}
document.getElementById('resetBuzzers').addEventListener('click', function() {
socket.send(JSON.stringify({
type: "reset"
}));
buzzed.classList.remove('buzzed');
})
</script>
</body>
</html>

View File

@ -14,11 +14,7 @@
</header>
<main>
<h2>Oh hi!</h2>
<p>
Create or join a room
</p>
<h2>Create or join a room</h2>
<form>
<label>
@ -33,8 +29,7 @@
document.querySelector('form').addEventListener('submit', function(event) {
event.preventDefault();
let roomId = document.getElementById('roomId').value;
window.location = `//${window.location.host}/${roomId}/join`;
window.location = `//${window.location.host}/${roomId}`;
});
</script>
</body>

View File

@ -10,13 +10,11 @@
</head>
<body>
<header>
<h1>Join {{room}}</h1>
<h1>Join '{{room}}'</h1>
</header>
<main>
<h2>Oh hi,</h2>
<p>Tell me your (team) name:</p>
<h2>Please tell me your (team) name:</h2>
<form method="POST">
<label>
@ -25,10 +23,6 @@
</label>
<button type="submit" id="submit-name">Submit</button>
</form>
<p>
<a href="/{{room}}/audience">Join the audience</a>
</p>
</main>
</body>
</html>

View File

@ -14,7 +14,7 @@
</header>
<main>
<h2>Oh hi, {{name}} <img src="{{character}}"/></h2>
<h2>{{name}} <img src="{{character}}"/></h2>
<button id="buzzer">
BUZZ
@ -26,7 +26,8 @@
</div>
<script>
let socket = new WebSocket(`wss://${window.location.hostname}/{{room}}`);
let proto = location.protocol == 'http:' ? 'ws' : 'wss'
let socket = new WebSocket(`${proto}://${window.location.hostname}:${window.location.port}/{{room}}`);
socket.onopen = function(e) {
socket.send(JSON.stringify({
@ -42,6 +43,10 @@
let msg = JSON.parse(event.data);
if (msg.type === "buzz") {
showMessage(msg.msg);
} else if (msg.type === "reset") {
reset();
} else if (msg.type === "close") {
roomClosed();
}
};
@ -50,6 +55,7 @@
socket.send(JSON.stringify({
type: "buzz"
}));
document.getElementById('buzzer').classList.add('active');
});
document.getElementById('buzzer').addEventListener('mousedown', function() {
@ -57,6 +63,7 @@
socket.send(JSON.stringify({
type: "buzz"
}));
document.getElementById('buzzer').classList.add('active');
});
function showMessage(msg) {
@ -65,10 +72,20 @@
let mb = document.getElementById('messageBox');
mb.innerHTML = msg;
mb.classList.remove('hide');
setTimeout(() => {
document.getElementById('buzzer').disabled = false;
mb.classList.add('hide');
}, 5000)
}
function reset() {
document.getElementById('buzzer').disabled = false;
document.getElementById('buzzer').classList.remove('active');
let mb = document.getElementById('messageBox');
mb.classList.add('hide');
}
function roomClosed() {
document.getElementById('buzzer').disabled = true;
let mb = document.getElementById('messageBox');
mb.innerHTML = "Room closed";
mb.classList.remove('hide');
}
function beep() {