|
|
|
/* eslint-disable no-unused-vars, no-undef */
|
|
|
|
/**
|
|
|
|
* Returns the value of the url-param 'g'
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
function getLobbyParam() {
|
|
|
|
let matches = window.location.href.match(/\??&?g=(\d+)/);
|
|
|
|
if (matches)
|
|
|
|
return matches[1];
|
|
|
|
else
|
|
|
|
return '';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* REturns the value of the r url param
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
function getRoundParam() {
|
|
|
|
let matches = window.location.href.match(/\??&?r=(\d+)/);
|
|
|
|
if (matches)
|
|
|
|
return matches[1];
|
|
|
|
else
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Submits the value of the username-input to set the username.
|
|
|
|
* @returns {Promise<Boolean>}
|
|
|
|
*/
|
|
|
|
async function submitUsername() {
|
|
|
|
let unameInput = document.querySelector('#input-username');
|
|
|
|
let username = unameInput.value.replace(/^\s+|\s+$/g, '');
|
|
|
|
|
|
|
|
if (username.length > 1) {
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
mutation($username:String!) {
|
|
|
|
bingo {
|
|
|
|
setUsername(username: $username) {
|
|
|
|
id
|
|
|
|
username
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {username: username});
|
|
|
|
if (response.status === 200) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
showError(`Failed to submit username. HTTP Error: ${response.status}`);
|
|
|
|
console.error(response);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
showError('You need to provide a username (minimum 2 characters)!');
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a lobby and redirects to the lobby.
|
|
|
|
* @returns {Promise<boolean>}
|
|
|
|
*/
|
|
|
|
async function createLobby() {
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
mutation {
|
|
|
|
bingo {
|
|
|
|
createLobby {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`);
|
|
|
|
if (response.status === 200 && response.data.bingo.createLobby) {
|
|
|
|
insertParam('g', response.data.bingo.createLobby.id);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
showError('Failed to create Lobby. HTTP ERROR: ' + response.status);
|
|
|
|
console.error(response);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Lets the player leave the lobby
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async function leaveLobby() {
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
mutation($lobbyId:ID!){
|
|
|
|
bingo {
|
|
|
|
mutateLobby(id:$lobbyId) {
|
|
|
|
leave
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`, {lobbyId: getLobbyParam()});
|
|
|
|
if (response.status === 200) {
|
|
|
|
insertParam('g', '');
|
|
|
|
} else {
|
|
|
|
showError('Failed to leave lobby');
|
|
|
|
console.error(response);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a message to the chat
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async function sendChatMessage() {
|
|
|
|
let messageInput = document.querySelector('#chat-input');
|
|
|
|
if (messageInput.value && messageInput.value.length > 0) {
|
|
|
|
let message = messageInput.value;
|
|
|
|
messageInput.value = '';
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
mutation($lobbyId:ID!, $message:String!){
|
|
|
|
bingo {
|
|
|
|
mutateLobby(id:$lobbyId) {
|
|
|
|
sendMessage(message:$message) {
|
|
|
|
id
|
|
|
|
htmlContent
|
|
|
|
type
|
|
|
|
author {
|
|
|
|
username
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {message: message, lobbyId: getLobbyParam()});
|
|
|
|
if (response.status === 200) {
|
|
|
|
addChatMessage(response.data.bingo.mutateLobby.sendMessage);
|
|
|
|
} else {
|
|
|
|
messageInput.value = message;
|
|
|
|
console.error(response);
|
|
|
|
showError('Error when sending message.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the words for the lobby
|
|
|
|
* @param words
|
|
|
|
* @returns {Promise<LobbyWrapper.words|*|properties.words|{default, type}|boolean>}
|
|
|
|
*/
|
|
|
|
async function setLobbyWords(words) {
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
mutation($lobbyId:ID!, $words:[String!]!){
|
|
|
|
bingo {
|
|
|
|
mutateLobby(id:$lobbyId) {
|
|
|
|
setWords(words:$words) {
|
|
|
|
words {
|
|
|
|
content
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {lobbyId: getLobbyParam(), words: words});
|
|
|
|
if (response.status === 200) {
|
|
|
|
return response.data.bingo.mutateLobby.setWords.words;
|
|
|
|
} else {
|
|
|
|
console.error(response);
|
|
|
|
showError('Error when setting lobby words.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts a new round of bingo
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async function startRound() {
|
|
|
|
let textinput = document.querySelector('#input-bingo-words');
|
|
|
|
let words = getLobbyWords();
|
|
|
|
let resultWords = await setLobbyWords(words);
|
|
|
|
textinput.value = resultWords.map(x => x.content).join('\n');
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
mutation($lobbyId:ID!){
|
|
|
|
bingo {
|
|
|
|
mutateLobby(id:$lobbyId) {
|
|
|
|
startRound {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {lobbyId: getLobbyParam()});
|
|
|
|
|
|
|
|
if (response.status === 200) {
|
|
|
|
insertParam('r', response.data.bingo.mutateLobby.startRound.id);
|
|
|
|
} else {
|
|
|
|
console.error(response);
|
|
|
|
showError('Error when starting round.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the words of the lobby word input.
|
|
|
|
* @returns {string[]}
|
|
|
|
*/
|
|
|
|
function getLobbyWords() {
|
|
|
|
let textinput = document.querySelector('#input-bingo-words');
|
|
|
|
let words = textinput.value.replace(/[<>]/g, '').split('\n').filter((el) => {
|
|
|
|
return (!!el && el.length > 0); // remove empty strings and non-types from word array
|
|
|
|
});
|
|
|
|
return words;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Submits the toggle of a bingo field
|
|
|
|
* @param wordPanel
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async function submitFieldToggle(wordPanel) {
|
|
|
|
let row = Number(wordPanel.getAttribute('b-row'));
|
|
|
|
let column = Number(wordPanel.getAttribute('b-column'));
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
mutation($lobbyId:ID!, $row:Int!, $column:Int!){
|
|
|
|
bingo {
|
|
|
|
mutateLobby(id:$lobbyId) {
|
|
|
|
toggleGridField(location:{row:$row, column:$column}) {
|
|
|
|
submitted
|
|
|
|
grid {
|
|
|
|
bingo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {lobbyId: getLobbyParam(), row: row, column: column});
|
|
|
|
|
|
|
|
if (response.status === 200) {
|
|
|
|
wordPanel.setAttribute('b-sub', response.data.bingo.mutateLobby.toggleGridField.submitted);
|
|
|
|
if (response.data.bingo.mutateLobby.toggleGridField.grid.bingo)
|
|
|
|
document.querySelector('#container-bingo-button').setAttribute('class', '');
|
|
|
|
else
|
|
|
|
document.querySelector('#container-bingo-button').setAttribute('class', 'hidden');
|
|
|
|
} else {
|
|
|
|
console.error(response);
|
|
|
|
showError('Error when submitting field toggle');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Submits bingo
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async function submitBingo() {
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
mutation($lobbyId:ID!){
|
|
|
|
bingo {
|
|
|
|
mutateLobby(id:$lobbyId) {
|
|
|
|
submitBingo {
|
|
|
|
winner {
|
|
|
|
id
|
|
|
|
username
|
|
|
|
}
|
|
|
|
status
|
|
|
|
start
|
|
|
|
finish
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {lobbyId: getLobbyParam()});
|
|
|
|
|
|
|
|
if (response.status === 200 && response.data.bingo.mutateLobby.submitBingo) {
|
|
|
|
let round = response.data.bingo.mutateLobby.submitBingo;
|
|
|
|
displayWinner(round);
|
|
|
|
} else {
|
|
|
|
console.error(response);
|
|
|
|
showError('Failed to submit bingo');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Displays the winner of the game in a popup.
|
|
|
|
* @param roundInfo {Object} - the round object as returned by graphql
|
|
|
|
*/
|
|
|
|
function displayWinner(roundInfo) {
|
|
|
|
let name = roundInfo.winner.username;
|
|
|
|
let winnerDiv = document.createElement('div');
|
|
|
|
let greyoverDiv = document.createElement('div');
|
|
|
|
winnerDiv.setAttribute('class', 'popup');
|
|
|
|
winnerDiv.innerHTML = `
|
|
|
|
<h1>${name} has won!</h1>
|
|
|
|
<button id="button-lobbyreturn" onclick="window.location.reload()">Return to Lobby!</button>
|
|
|
|
`;
|
|
|
|
greyoverDiv.setAttribute('class', 'greyover');
|
|
|
|
//winnerDiv.onclick = () => {
|
|
|
|
// window.location.reload();
|
|
|
|
//};
|
|
|
|
document.body.append(greyoverDiv);
|
|
|
|
document.body.appendChild(winnerDiv);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Shows an error Message.
|
|
|
|
* @param errorMessage
|
|
|
|
*/
|
|
|
|
function showError(errorMessage) {
|
|
|
|
// TODO: Implement
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads information about the rounds winner and the round stats.
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async function loadWinnerInfo() {
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
query($lobbyId:ID!) {
|
|
|
|
bingo {
|
|
|
|
lobby(id:$lobbyId) {
|
|
|
|
currentRound {
|
|
|
|
status
|
|
|
|
winner {
|
|
|
|
id
|
|
|
|
username
|
|
|
|
}
|
|
|
|
start
|
|
|
|
finish
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {lobbyId: getLobbyParam()});
|
|
|
|
if (response.status === 200) {
|
|
|
|
let roundInfo = response.data.bingo.lobby.currentRound;
|
|
|
|
displayWinner(roundInfo);
|
|
|
|
} else {
|
|
|
|
console.error(response);
|
|
|
|
showError('Failed to get round information');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a message to the chat
|
|
|
|
* @param messageObject {Object} - the message object returned by graphql
|
|
|
|
*/
|
|
|
|
function addChatMessage(messageObject) {
|
|
|
|
let msgSpan = document.createElement('span');
|
|
|
|
msgSpan.setAttribute('class', 'chatMessage');
|
|
|
|
msgSpan.setAttribute('msg-id', messageObject.id);
|
|
|
|
if (messageObject.type === "USER") {
|
|
|
|
msgSpan.innerHTML = `
|
|
|
|
<span class="chatUsername">${messageObject.author.username}:</span>
|
|
|
|
<span class="chatMessageContent">${messageObject.htmlContent}</span>`;
|
|
|
|
} else {
|
|
|
|
msgSpan.innerHTML = `
|
|
|
|
<span class="chatMessageContent ${messageObject.type}">${messageObject.htmlContent}</span>`;
|
|
|
|
}
|
|
|
|
|
|
|
|
let chatContent = document.querySelector('#chat-content');
|
|
|
|
chatContent.appendChild(msgSpan);
|
|
|
|
chatContent.scrollTop = chatContent.scrollHeight; // auto-scroll to bottom
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a player to the player view
|
|
|
|
* @param player
|
|
|
|
*/
|
|
|
|
function addPlayer(player) {
|
|
|
|
let playerContainer = document.createElement('div');
|
|
|
|
playerContainer.setAttribute('class', 'playerEntryContainer');
|
|
|
|
playerContainer.setAttribute('b-pid', player.id);
|
|
|
|
playerContainer.innerHTML = `<span class="playernameSpan">${player.username}</span>`;
|
|
|
|
document.querySelector('#player-list').appendChild(playerContainer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Refreshes the bingo chat
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async function refreshChat() {
|
|
|
|
try {
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
query($lobbyId:ID!){
|
|
|
|
bingo {
|
|
|
|
lobby(id:$lobbyId) {
|
|
|
|
messages {
|
|
|
|
id
|
|
|
|
type
|
|
|
|
htmlContent
|
|
|
|
author {
|
|
|
|
username
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {lobbyId: getLobbyParam()});
|
|
|
|
if (response.status === 200) {
|
|
|
|
let messages = response.data.bingo.lobby.messages;
|
|
|
|
for (let message of messages)
|
|
|
|
if (!document.querySelector(`.chatMessage[msg-id="${message.id}"]`))
|
|
|
|
addChatMessage(message);
|
|
|
|
} else {
|
|
|
|
showError('Failed to refresh messages');
|
|
|
|
console.error(response);
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
showError('Failed to refresh messages');
|
|
|
|
console.error(err);
|
|
|
|
}
|
|
|
|
console.log('Refresh Chat');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Refreshes the player list
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async function refreshPlayers() {
|
|
|
|
try {
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
query($lobbyId:ID!){
|
|
|
|
bingo {
|
|
|
|
lobby(id:$lobbyId) {
|
|
|
|
players {
|
|
|
|
id
|
|
|
|
username
|
|
|
|
wins(lobbyId:$lobbyId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {lobbyId: getLobbyParam()});
|
|
|
|
if (response.status === 200) {
|
|
|
|
let players = response.data.bingo.lobby.players;
|
|
|
|
for (let player of players)
|
|
|
|
if (!document.querySelector(`.playerEntryContainer[b-pid="${player.id}"]`))
|
|
|
|
addPlayer(player);
|
|
|
|
} else {
|
|
|
|
showError('Failed to refresh players');
|
|
|
|
console.error(response);
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
showError('Failed to refresh players');
|
|
|
|
console.error(err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes players that are not existent in the player array
|
|
|
|
* @param players {Array<Object>} - player id response of graphql
|
|
|
|
*/
|
|
|
|
function removeLeftPlayers(players) {
|
|
|
|
for (let playerEntry of document.querySelectorAll('.playerEntryContainer'))
|
|
|
|
if (!players.find(x => (x.id === playerEntry.getAttribute('b-pid'))))
|
|
|
|
playerEntry.remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Refreshes if a player-refresh is needed.
|
|
|
|
* Removes players that are not in the lobby anyomre.
|
|
|
|
* @param players
|
|
|
|
*/
|
|
|
|
function checkPlayerRefresh(players) {
|
|
|
|
let playerRefresh = false;
|
|
|
|
removeLeftPlayers(players);
|
|
|
|
for (let player of players)
|
|
|
|
if (!document.querySelector(`.playerEntryContainer[b-pid="${player.id}"]`))
|
|
|
|
playerRefresh = true;
|
|
|
|
if (playerRefresh)
|
|
|
|
refreshPlayers();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if messages need to be refreshed and does it if it needs to.
|
|
|
|
* @param messages
|
|
|
|
*/
|
|
|
|
function checkMessageRefresh(messages) {
|
|
|
|
let messageRefresh = false;
|
|
|
|
for (let message of messages)
|
|
|
|
if (!document.querySelector(`.chatMessage[msg-id="${message.id}"]`))
|
|
|
|
messageRefresh = true;
|
|
|
|
if (messageRefresh)
|
|
|
|
refreshChat();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* refreshes the lobby and calls itself with a timeout
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async function refreshLobby() {
|
|
|
|
try {
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
query($lobbyId:ID!){
|
|
|
|
bingo {
|
|
|
|
lobby(id:$lobbyId) {
|
|
|
|
players {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
messages {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
currentRound {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
words {
|
|
|
|
content
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {lobbyId: getLobbyParam()});
|
|
|
|
if (response.status === 200) {
|
|
|
|
let {players, messages, currentRound} = response.data.bingo.lobby;
|
|
|
|
checkPlayerRefresh(players);
|
|
|
|
checkMessageRefresh(messages);
|
|
|
|
let wordContainer = document.querySelector('#bingo-words');
|
|
|
|
|
|
|
|
if (wordContainer)
|
|
|
|
wordContainer.innerHTML = `<span class="bingoWord">
|
|
|
|
${response.data.bingo.lobby.words.map(x => x.content).join('</span><span class="bingoWord">')}</span>`;
|
|
|
|
|
|
|
|
if (currentRound && currentRound.id && Number(currentRound.id) !== Number(getRoundParam()))
|
|
|
|
insertParam('r', currentRound.id);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
showError('Failed to refresh lobby');
|
|
|
|
console.error(response);
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
showError('Failed to refresh lobby');
|
|
|
|
console.error(err);
|
|
|
|
} finally {
|
|
|
|
setTimeout(refreshLobby, 1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks the status of the lobby and the current round.
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
|
|
|
async function refreshRound() {
|
|
|
|
let roundOver = false;
|
|
|
|
try {
|
|
|
|
let response = await postGraphqlQuery(`
|
|
|
|
query($lobbyId:ID!) {
|
|
|
|
bingo {
|
|
|
|
lobby(id:$lobbyId) {
|
|
|
|
players {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
messages {
|
|
|
|
id
|
|
|
|
}
|
|
|
|
currentRound {
|
|
|
|
id
|
|
|
|
status
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}`, {lobbyId: getLobbyParam()});
|
|
|
|
if (response.status === 200) {
|
|
|
|
let {players, messages, currentRound} = response.data.bingo.lobby;
|
|
|
|
|
|
|
|
checkPlayerRefresh(players);
|
|
|
|
checkMessageRefresh(messages);
|
|
|
|
if (!currentRound || currentRound.status === "FINISHED") {
|
|
|
|
roundOver = true;
|
|
|
|
await loadWinnerInfo();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
showError('Failed to refresh round');
|
|
|
|
console.error(response);
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
showError('Failed to refresh round');
|
|
|
|
console.error(err);
|
|
|
|
} finally {
|
|
|
|
if (!roundOver)
|
|
|
|
setTimeout(refreshRound, 1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
window.addEventListener("unhandledrejection", function (promiseRejectionEvent) {
|
|
|
|
promiseRejectionEvent.promise.catch(err => console.log(err));
|
|
|
|
showError('Connection problems... Is the server down?');
|
|
|
|
});
|
|
|
|
|
|
|
|
// prevent ctrl + s
|
|
|
|
window.addEventListener("keydown", async (e) => {
|
|
|
|
if (e.which === 83 && (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)) {
|
|
|
|
e.preventDefault();
|
|
|
|
if (document.querySelector('#input-bingo-words'))
|
|
|
|
await setLobbyWords(getLobbyWords());
|
|
|
|
}
|
|
|
|
}, false);
|