Fixed issues

- fixed bingo button not shown on refresh
- fixed code style
- added eslint
pull/15/head
Trivernis 6 years ago
parent 2fb44df24d
commit 52bd2378fb

@ -14,7 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Chat to the bingo game (renderd with markdown-it) - Chat to the bingo game (renderd with markdown-it)
- Postgres session storage - Postgres session storage
- sql-file directory `sql` - sql-file directory `sql`
- LICENSE.md (GPL v3)
- eslint to dev dependencys
## Changed ## Changed
@ -28,3 +29,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- mobile layout - mobile layout
- code style issues
- Bingo button not shown on refresh

@ -1,4 +1,4 @@
# whooshy # whooshy [![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg?style=flat-square)](https://www.gnu.org/licenses/gpl-3.0)
This repository is the node.js webserver running on `(beta.)trivernis.net`. This repository is the node.js webserver running on `(beta.)trivernis.net`.

@ -29,7 +29,7 @@ async function init() {
return { return {
time: Date.now(), time: Date.now(),
bingo: bingoRouter.graphqlResolver(request, response) bingo: bingoRouter.graphqlResolver(request, response)
} };
}; };
// database setup // database setup
let pgPool = new pg.Pool({ let pgPool = new pg.Pool({
@ -91,7 +91,7 @@ async function init() {
}); });
// error handler // error handler
app.use(function(err, req, res, next) { app.use(function(err, req, res) {
// set locals, only providing error in development // set locals, only providing error in development
res.locals.message = err.message; res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {}; res.locals.error = req.app.get('env') === 'development' ? err : {};

@ -41,7 +41,7 @@ appInit().then((app) => {
*/ */
server.listen(port); server.listen(port);
server.on('error', (error) => onError(error, server)); server.on('error', (error) => onError(error));
server.on('listening', () => onListening(server)); server.on('listening', () => onListening(server));
/** /**
@ -55,16 +55,12 @@ appInit().then((app) => {
function normalizePort(val) { function normalizePort(val) {
let port = parseInt(val, 10); let port = parseInt(val, 10);
if (isNaN(port)) { if (isNaN(port))
// named pipe // named pipe
return val; return val;
} if (port >= 0)
if (port >= 0) {
// port number // port number
return port; return port;
}
return false; return false;
} }
@ -72,10 +68,9 @@ function normalizePort(val) {
* Event listener for HTTP server "error" event. * Event listener for HTTP server "error" event.
*/ */
function onError(error, server) { function onError(error) {
if (error.syscall !== 'listen') { if (error.syscall !== 'listen')
throw error; throw error;
}
let bind = typeof port === 'string' let bind = typeof port === 'string'
? 'Pipe ' + port ? 'Pipe ' + port

724
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -26,5 +26,71 @@
"node-sass": "4.12.0", "node-sass": "4.12.0",
"pg": "^7.11.0", "pg": "^7.11.0",
"pug": "2.0.3" "pug": "2.0.3"
},
"devDependencies": {
"eslint": "^5.16.0",
"eslint-plugin-graphql": "^3.0.3",
"eslint-plugin-promise": "^4.1.1"
},
"eslintConfig": {
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"env": {
"node": true,
"browser": true,
"jquery": true,
"es6": true
},
"extends": [
"eslint:recommended",
"plugin:promise/recommended"
],
"rules": {
"semi": "error",
"semi-style": [
"error",
"last"
],
"no-await-in-loop": "warn",
"curly": [
"warn",
"multi",
"consistent"
],
"block-spacing": [
"warn",
"always"
],
"array-bracket-newline": [
"warn",
"consistent"
],
"camelcase": [
"error",
{
"properties": "always"
}
],
"comma-spacing": [
"error",
{
"after": true
}
],
"brace-style": [
"error",
"1tbs"
],
"no-console": "off",
"promise/no-promise-in-callback": "off",
"promise/always-return": "off",
"promise/catch-or-return": "off"
},
"plugins": [
"eslint-plugin-graphql",
"eslint-plugin-promise"
]
} }
} }

@ -1,3 +1,4 @@
/* eslint-disable no-unused-vars, no-undef */
/** /**
* Returns the value of the url-param 'game' * Returns the value of the url-param 'game'
* @returns {string} * @returns {string}
@ -17,7 +18,7 @@ function getGameParam() {
async function submitBingoWords() { async function submitBingoWords() {
let textContent = document.querySelector('#bingo-textarea').value; let textContent = document.querySelector('#bingo-textarea').value;
let words = textContent.replace(/[<>]/g, '').split('\n').filter((el) => { let words = textContent.replace(/[<>]/g, '').split('\n').filter((el) => {
return (!!el && el.length > 0) // remove empty strings and non-types from word array return (!!el && el.length > 0); // remove empty strings and non-types from word array
}); });
if (words.length === 0) { if (words.length === 0) {
showError('You need to provide at least one word!'); showError('You need to provide at least one word!');
@ -43,7 +44,7 @@ async function submitBingoWords() {
insertParam('game', gameid); insertParam('game', gameid);
} else { } else {
showError(`Failed to create game. HTTP Error: ${response.status}`); showError(`Failed to create game. HTTP Error: ${response.status}`);
console.error(response) console.error(response);
} }
} }
} }
@ -60,7 +61,7 @@ async function createFollowup() {
id id
} }
} }
}`,null,`/graphql?game=${getGameParam()}`); }`, null, `/graphql?game=${getGameParam()}`);
if (response.status === 200 && response.data.bingo.createFollowupGame) { if (response.status === 200 && response.data.bingo.createFollowupGame) {
let gameid = response.data.bingo.createFollowupGame.id; let gameid = response.data.bingo.createFollowupGame.id;
insertParam('game', gameid); insertParam('game', gameid);
@ -88,7 +89,7 @@ async function submitUsername() {
} }
}`, { }`, {
username: username username: username
},`/graphql?game=${getGameParam()}`); }, `/graphql?game=${getGameParam()}`);
if (response.status === 200) { if (response.status === 200) {
unameInput.value = ''; unameInput.value = '';
unameInput.placeholder = response.data.username; unameInput.placeholder = response.data.username;
@ -122,22 +123,59 @@ async function submitWord(word) {
} }
}`, { }`, {
word: word word: word
},`/graphql?game=${getGameParam()}`); }, `/graphql?game=${getGameParam()}`);
if (response.status === 200 && response.data.bingo.toggleWord) { if (response.status === 200 && response.data.bingo.toggleWord) {
let fieldGrid = response.data.bingo.toggleWord.fieldGrid; let fieldGrid = response.data.bingo.toggleWord.fieldGrid;
for (let row of fieldGrid) { for (let row of fieldGrid)
for (let field of row) { for (let field of row)
document.querySelectorAll(`.bingo-word-panel[b-word="${field.base64Word}"]`).forEach(x => { document.querySelectorAll(`.bingo-word-panel[b-word="${field.base64Word}"]`).forEach(x => {
x.setAttribute('b-sub', field.submitted); x.setAttribute('b-sub', field.submitted);
}); });
if (response.data.bingo.toggleWord.bingo)
document.querySelector('#bingo-button').setAttribute('class', '');
else
document.querySelector('#bingo-button').setAttribute('class', 'hidden');
} else {
showError(`Failed to submit word. HTTP Error: ${response.status}`);
console.error(response);
}
}
/**
* Refreshes the bingo grid. Shows the bingo button if a bingo is possible
* @returns {Promise<void>}
*/
async function refreshBingoGrid() {
let response = await postGraphqlQuery(`
query {
bingo {
activeGrid {
bingo
fieldGrid {
word
base64Word
submitted
}
} }
} }
if (response.data.bingo.toggleWord.bingo) { }`, {}, `/graphql?game=${getGameParam()}`);
if (response.status === 200 && response.data.bingo.activeGrid) {
let fieldGrid = response.data.bingo.activeGrid.fieldGrid;
for (let row of fieldGrid)
for (let field of row)
document.querySelectorAll(`.bingo-word-panel[b-word="${field.base64Word}"]`).forEach(x => {
x.setAttribute('b-sub', field.submitted);
});
if (response.data.bingo.activeGrid.bingo)
document.querySelector('#bingo-button').setAttribute('class', ''); document.querySelector('#bingo-button').setAttribute('class', '');
} else { else
document.querySelector('#bingo-button').setAttribute('class', 'hidden'); document.querySelector('#bingo-button').setAttribute('class', 'hidden');
}
} else { } else {
showError(`Failed to submit word. HTTP Error: ${response.status}`); showError(`Failed to submit word. HTTP Error: ${response.status}`);
console.error(response); console.error(response);
@ -162,12 +200,12 @@ async function submitBingo() {
} }
} }
} }
}`,null,`/graphql?game=${getGameParam()}`); }`, null, `/graphql?game=${getGameParam()}`);
if (response.status === 200 && response.data.bingo.submitBingo) { if (response.status === 200 && response.data.bingo.submitBingo) {
let bingoSession = response.data.bingo.submitBingo; let bingoSession = response.data.bingo.submitBingo;
if (bingoSession.bingos.length > 0) { if (bingoSession.bingos.length > 0) {
displayWinner(bingoSession.players.find(x => x.id === bingoSession.bingos[0]).username); displayWinner(bingoSession.players.find(x => x.id === bingoSession.bingos[0]).username);
clearInterval(refrInterval) clearInterval(refrInterval);
} }
} else { } else {
showError(`Failed to submit Bingo. HTTP Error: ${response.status}`); showError(`Failed to submit Bingo. HTTP Error: ${response.status}`);
@ -181,6 +219,7 @@ async function submitBingo() {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async function refresh() { async function refresh() {
await refreshBingoGrid();
let response = await postGraphqlQuery(` let response = await postGraphqlQuery(`
query { query {
bingo { bingo {
@ -205,7 +244,7 @@ async function refresh() {
if (bingoSession.bingos.length > 0) { if (bingoSession.bingos.length > 0) {
displayWinner(bingoSession.players.find(x => x.id === bingoSession.bingos[0]).username); displayWinner(bingoSession.players.find(x => x.id === bingoSession.bingos[0]).username);
clearInterval(refrInterval) clearInterval(refrInterval);
} else { } else {
for (let player of bingoSession.players) { for (let player of bingoSession.players) {
let foundPlayerDiv = document.querySelector(`.player-container[b-pid='${player.id}'`); let foundPlayerDiv = document.querySelector(`.player-container[b-pid='${player.id}'`);
@ -217,16 +256,16 @@ async function refresh() {
document.querySelector('#players-container').appendChild(playerDiv); document.querySelector('#players-container').appendChild(playerDiv);
} else { } else {
let playerNameSpan = foundPlayerDiv.querySelector('.player-name-span'); let playerNameSpan = foundPlayerDiv.querySelector('.player-name-span');
if (playerNameSpan.innerText !== player.username) { if (playerNameSpan.innerText !== player.username)
playerNameSpan.innerText = player.username; playerNameSpan.innerText = player.username;
} }
} }
} }
} for (let chatMessage of bingoSession.getMessages)
for (let chatMessage of bingoSession.getMessages) {
if (!document.querySelector(`.chatMessage[msg-id='${chatMessage.id}'`)) if (!document.querySelector(`.chatMessage[msg-id='${chatMessage.id}'`))
addChatMessage(chatMessage); addChatMessage(chatMessage);
}
} else { } else {
if (response.status === 400) if (response.status === 400)
clearInterval(refrInterval); clearInterval(refrInterval);
@ -288,7 +327,7 @@ async function sendChatMessage() {
type type
} }
} }
}`,{message: message}, `/graphql?game=${getGameParam()}`); }`, {message: message}, `/graphql?game=${getGameParam()}`);
if (response.status === 200) { if (response.status === 200) {
addChatMessage(response.data.bingo.sendChatMessage); addChatMessage(response.data.bingo.sendChatMessage);
messageInput.value = ''; messageInput.value = '';
@ -307,14 +346,14 @@ function addChatMessage(messageObject) {
let msgSpan = document.createElement('span'); let msgSpan = document.createElement('span');
msgSpan.setAttribute('class', 'chatMessage'); msgSpan.setAttribute('class', 'chatMessage');
msgSpan.setAttribute('msg-id', messageObject.id); msgSpan.setAttribute('msg-id', messageObject.id);
if (messageObject.type === "USER") { if (messageObject.type === "USER")
msgSpan.innerHTML = ` msgSpan.innerHTML = `
<span class="chatUsername">${messageObject.username}:</span> <span class="chatUsername">${messageObject.username}:</span>
<span class="chatMessageContent">${messageObject.htmlContent}</span>`; <span class="chatMessageContent">${messageObject.htmlContent}</span>`;
} else { else
msgSpan.innerHTML = ` msgSpan.innerHTML = `
<span class="chatMessageContent ${messageObject.type}">${messageObject.htmlContent}</span>`; <span class="chatMessageContent ${messageObject.type}">${messageObject.htmlContent}</span>`;
}
let chatContent = document.querySelector('#chat-content'); let chatContent = document.querySelector('#chat-content');
chatContent.appendChild(msgSpan); chatContent.appendChild(msgSpan);
chatContent.scrollTop = chatContent.scrollHeight; // auto-scroll to bottom chatContent.scrollTop = chatContent.scrollHeight; // auto-scroll to bottom
@ -338,7 +377,7 @@ function toggleChatView() {
if (contentContainer.getAttribute('class') === 'displayChat') if (contentContainer.getAttribute('class') === 'displayChat')
contentContainer.setAttribute('class', ''); contentContainer.setAttribute('class', '');
else else
contentContainer.setAttribute('class', 'displayChat') contentContainer.setAttribute('class', 'displayChat');
} }
window.addEventListener("unhandledrejection", function(promiseRejectionEvent) { window.addEventListener("unhandledrejection", function(promiseRejectionEvent) {
@ -349,9 +388,9 @@ window.addEventListener("unhandledrejection", function(promiseRejectionEvent) {
window.onload = () => { window.onload = () => {
if (document.querySelector('#chat-container')) if (document.querySelector('#chat-container'))
refresh(); refresh();
if (window && !document.querySelector('#bingoform')) { if (window && !document.querySelector('#bingoform'))
refrInterval = setInterval(refresh, 1000); // global variable to clear refrInterval = setInterval(refresh, 1000); // eslint-disable-line no-undef
}
let gridSizeElem = document.querySelector('#bingo-grid-size'); let gridSizeElem = document.querySelector('#bingo-grid-size');
document.querySelector('#bingo-grid-y').innerText = gridSizeElem.value; document.querySelector('#bingo-grid-y').innerText = gridSizeElem.value;
gridSizeElem.oninput = () => { gridSizeElem.oninput = () => {

@ -1,16 +1,24 @@
/* eslint-disable no-unused-vars, no-undef */
/**
* HTTP POST to an url with a post body
* @param url {String} - the url to post to
* @param postBody {JSON|Object} - the json-object to post
* @returns {Promise<any>}
*/
function postData(url, postBody) { function postData(url, postBody) {
let request = new XMLHttpRequest(); let request = new XMLHttpRequest();
return new Promise((res, rej) => { return new Promise((resolve, reject) => {
request.onload = () => { request.onload = () => {
res({ resolve({
status: request.status, status: request.status,
data: request.responseText data: request.responseText
}); });
}; };
request.onerror = () => { request.onerror = () => {
rej(request.error); reject(request.error);
}; };
request.open('POST', url, true); request.open('POST', url, true);
@ -19,10 +27,22 @@ function postData(url, postBody) {
}); });
} }
/**
* HTTP POST to the current url
* @param postBody {JSON|Object} - the json-object to post
* @returns {Promise<any>}
*/
async function postLocData(postBody) { async function postLocData(postBody) {
return await postData('#', postBody); return await postData('#', postBody);
} }
/**
* HTTP POST to a graphql url endpoint (default '/graphql')
* @param query {String} - the graphql query to post
* @param [variables] {JSON} - optional variables used in the graphql query
* @param [url] {String} - optional alternative graphql endpoint
* @returns {Promise<{data: *, status: *}|{data: *, requestBody: {variables: *, query: *}, errors: *, status: *}>}
*/
async function postGraphqlQuery(query, variables, url) { async function postGraphqlQuery(query, variables, url) {
let body = { let body = {
query: query, query: query,
@ -31,29 +51,33 @@ async function postGraphqlQuery(query, variables, url) {
let response = await postData(url || '/graphql', body); let response = await postData(url || '/graphql', body);
let resData = JSON.parse(response.data); let resData = JSON.parse(response.data);
if (response.status === 200) { if (response.status === 200)
return { return {
status: response.status, status: response.status,
data: resData.data, data: resData.data,
}; };
} else { else
return { return {
status: response.status, status: response.status,
data: resData.data, data: resData.data,
errors: resData.errors, errors: resData.errors,
requestBody: body requestBody: body
}; };
}
} }
/**
* Inserts an url parameter
* @param key {String} - the key of the url parameter
* @param value {String} - the value of the url parameter
*/
function insertParam(key, value) { function insertParam(key, value) {
key = encodeURI(key); key = encodeURI(key);
value = encodeURI(value); value = encodeURI(value);
let kvp = document.location.search.substr(1).split('&'); let kvp = document.location.search.substr(1).split('&');
let i = kvp.length; let i = kvp.length;
let x; let x;
while (i--) { while (i--) {
x = kvp[i].split('='); x = kvp[i].split('=');
@ -63,10 +87,7 @@ function insertParam(key, value) {
break; break;
} }
} }
if (i < 0)
if (i < 0) {
kvp[kvp.length] = [key, value].join('='); kvp[kvp.length] = [key, value].join('=');
}
document.location.search = kvp.join('&'); document.location.search = kvp.join('&');
} }

@ -1,3 +1,10 @@
/* eslint-disable no-unused-vars, no-undef */
/**
* start the download of a subreddit
* @param subredditName {String} - the name of the subreddit to download
* @returns {Promise<any>}
*/
async function startSubredditDownload(subredditName) { async function startSubredditDownload(subredditName) {
let data = await postLocData({ let data = await postLocData({
subreddit: subredditName subreddit: subredditName
@ -5,6 +12,11 @@ async function startSubredditDownload(subredditName) {
return JSON.parse(data.data); return JSON.parse(data.data);
} }
/**
* Get the status of a download
* @param downloadId {String} - the id of the download to get the status for
* @returns {Promise<any>}
*/
async function getDownloadStatus(downloadId) { async function getDownloadStatus(downloadId) {
let data = await postLocData({ let data = await postLocData({
id: downloadId id: downloadId
@ -12,6 +24,11 @@ async function getDownloadStatus(downloadId) {
return JSON.parse(data.data); return JSON.parse(data.data);
} }
/**
* refreshes information about a specific download
* @param downloadId {String} - the id of the download
* @returns {Promise<void>}
*/
async function refreshDownloadInfo(downloadId) { async function refreshDownloadInfo(downloadId) {
let response = await getDownloadStatus(downloadId); let response = await getDownloadStatus(downloadId);
@ -20,7 +37,7 @@ async function refreshDownloadInfo(downloadId) {
let subredditName = dlDiv.getAttribute('subreddit-name'); let subredditName = dlDiv.getAttribute('subreddit-name');
if (response.status === 'pending') { if (response.status === 'pending') {
setTimeout(() => refreshDownloadInfo(downloadId), 1000) setTimeout(() => refreshDownloadInfo(downloadId), 1000);
} else { } else {
let dlLink = document.createElement('a'); let dlLink = document.createElement('a');
dlLink.setAttribute('href', response.file); dlLink.setAttribute('href', response.file);
@ -34,6 +51,10 @@ async function refreshDownloadInfo(downloadId) {
} }
} }
/**
* Submit a subreddit to download (called by button)
* @returns {Promise<void>}
*/
async function submitDownload() { async function submitDownload() {
let subredditName = document.querySelector('#subreddit-input').value; let subredditName = document.querySelector('#subreddit-input').value;
let response = await startSubredditDownload(subredditName); let response = await startSubredditDownload(subredditName);

@ -69,6 +69,9 @@ textarea
width: 100% width: 100%
margin: 0.5rem 0 margin: 0.5rem 0
#chat-container .chatMessage
font-size: 1.2em
@media(min-device-width: 641px) @media(min-device-width: 641px)
textarea textarea
height: 80% height: 80%
@ -177,7 +180,6 @@ textarea
grid-row-start: 1 grid-row-start: 1
grid-row-end: 1 grid-row-end: 1
display: grid display: grid
margin: 1rem
font-size: inherit font-size: inherit
button button
@ -206,7 +208,7 @@ textarea
grid-column-end: 1 grid-column-end: 1
grid-row-start: 3 grid-row-start: 3
grid-row-end: 4 grid-row-end: 4
height: 100% height: calc(100% - 3px)
border: 1px solid $inactive border: 1px solid $inactive
margin: 0 0.5rem margin: 0 0.5rem
word-break: break-word word-break: break-word

@ -57,6 +57,10 @@ textarea
a a
color: $secondary color: $secondary
mark
background-color: $secondary
color: $primarySurface
::-webkit-scrollbar ::-webkit-scrollbar
width: 12px width: 12px
height: 12px height: 12px

@ -1,7 +1,5 @@
const express = require('express'), const express = require('express'),
router = express.Router(), router = express.Router(),
cproc = require('child_process'),
fsx = require('fs-extra'),
mdEmoji = require('markdown-it-emoji'), mdEmoji = require('markdown-it-emoji'),
mdMark = require('markdown-it-mark'), mdMark = require('markdown-it-mark'),
mdSmartarrows = require('markdown-it-smartarrows'), mdSmartarrows = require('markdown-it-smartarrows'),
@ -10,8 +8,6 @@ const express = require('express'),
.use(mdMark) .use(mdMark)
.use(mdSmartarrows); .use(mdSmartarrows);
const rWordOnly = /^\w+$/;
let bingoSessions = {}; let bingoSessions = {};
class BingoSession { class BingoSession {
@ -38,9 +34,9 @@ class BingoSession {
addUser(user) { addUser(user) {
let id = user.id; let id = user.id;
this.users[id] = user; this.users[id] = user;
if (user.username !== 'anonymous') { if (user.username !== 'anonymous')
this.chatMessages.push(new BingoChatMessage(`**${user.username}** joined.`, "INFO")); this.chatMessages.push(new BingoChatMessage(`**${user.username}** joined.`, "INFO"));
}
} }
/** /**
@ -76,13 +72,13 @@ class BingoSession {
*/ */
getMessages(args) { getMessages(args) {
let input = args.input || null; let input = args.input || null;
if (input && input.id) { if (input && input.id)
return this.chatMessages.find(x => (x && x.id === input.id)); return this.chatMessages.find(x => (x && x.id === input.id));
} else if (input && input.last) { else if (input && input.last)
return this.chatMessages.slice(-input.last); return this.chatMessages.slice(-input.last);
} else { else
return this.chatMessages.slice(-10); return this.chatMessages.slice(-10);
}
} }
/** /**
@ -190,7 +186,7 @@ function inflateArray(array, minSize) {
let iterations = Math.ceil(minSize/array.length)-1; let iterations = Math.ceil(minSize/array.length)-1;
for (let i = 0; i < iterations; i++) for (let i = 0; i < iterations; i++)
resultArray = [...resultArray, ...resultArray]; resultArray = [...resultArray, ...resultArray];
return resultArray return resultArray;
} }
/** /**
@ -212,9 +208,9 @@ function generateWordGrid(dimensions, words) {
let grid = []; let grid = [];
for (let x = 0; x < dimensions[1]; x++) { for (let x = 0; x < dimensions[1]; x++) {
grid[x] = []; grid[x] = [];
for (let y = 0; y < dimensions[0]; y++) { for (let y = 0; y < dimensions[0]; y++)
grid[x][y] = shuffledWords[(x * dimensions[0]) + y]; grid[x][y] = shuffledWords[(x * dimensions[0]) + y];
}
} }
return (new BingoGrid(grid)); return (new BingoGrid(grid));
} }
@ -235,55 +231,79 @@ function toggleHeared(base64Word, bingoGrid) {
} }
/** /**
* Checks if a bingo exists in the bingo grid. * Checks if a diagonal bingo is possible
* @param bingoGrid {BingoGrid} * @param fg {Array<Array<boolean>>} - the grid with the checked (submitted) values
* @returns {boolean} * @returns {boolean|boolean|*}
*/ */
function checkBingo(bingoGrid) { function checkBingoDiagnoal(fg) {
let fg = bingoGrid.fieldGrid.map(x => x.map(y => y.submitted)); let bingoCheck = true;
let diagonalBingo = true;
// diagonal check // diagonal check
for (let i = 0; i < fg.length; i++) for (let i = 0; i < fg.length; i++)
diagonalBingo = fg[i][i] && diagonalBingo; bingoCheck = fg[i][i] && bingoCheck;
if (diagonalBingo) { if (bingoCheck)
bingoGrid.bingo = true;
return true; return true;
} bingoCheck = true;
diagonalBingo = true;
for (let i = 0; i < fg.length; i++) for (let i = 0; i < fg.length; i++)
diagonalBingo = fg[i][fg.length - i - 1] && diagonalBingo; bingoCheck = fg[i][fg.length - i - 1] && bingoCheck;
if (diagonalBingo) { return bingoCheck;
bingoGrid.bingo = true; }
return true;
} /**
* Checks if a vertical bingo is possible
* @param fg {Array<Array<boolean>>} - the grid with the checked (submitted) values
* @returns {boolean|boolean|*}
*/
function checkBingoVertical(fg) {
let bingoCheck = true; let bingoCheck = true;
// horizontal check
for (let row of fg) { for (let row of fg) {
bingoCheck = true; bingoCheck = true;
for (let field of row) for (let field of row)
bingoCheck = field && bingoCheck; bingoCheck = field && bingoCheck;
if (bingoCheck) { if (bingoCheck)
bingoGrid.bingo = true;
return true; return true;
} }
} return bingoCheck;
if (bingoCheck) { }
bingoGrid.bingo = true;
return true; /**
} * Checks if a horizontal bingo is possible
bingoCheck = true; * @param fg {Array<Array<boolean>>} - the grid with the checked (submitted) values
* @returns {boolean|boolean|*}
*/
function checkBingoHorizontal(fg) {
let bingoCheck = true;
// vertical check // vertical check
for (let i = 0; i < fg.length; i++) { for (let i = 0; i < fg.length; i++) {
bingoCheck = true; bingoCheck = true;
for (let j = 0; j < fg.length; j++) for (let j = 0; j < fg.length; j++)
bingoCheck = fg[j][i] && bingoCheck; bingoCheck = fg[j][i] && bingoCheck;
if (bingoCheck) { if (bingoCheck)
return true;
}
return bingoCheck;
}
/**
* Checks if a bingo exists in the bingo grid.
* @param bingoGrid {BingoGrid}
* @returns {boolean}
*/
function checkBingo(bingoGrid) {
let fg = bingoGrid.fieldGrid.map(x => x.map(y => y.submitted));
let diagonalBingo = checkBingoDiagnoal(fg);
if (diagonalBingo) {
bingoGrid.bingo = true; bingoGrid.bingo = true;
return true; return true;
} }
let verticalCheck = checkBingoVertical(fg);
if (verticalCheck) {
bingoGrid.bingo = true;
return true;
} }
if (bingoCheck) { let horizontalCheck = checkBingoHorizontal(fg);
if (horizontalCheck) {
bingoGrid.bingo = true; bingoGrid.bingo = true;
return true; return true;
} }
@ -294,9 +314,9 @@ function checkBingo(bingoGrid) {
// -- Router stuff // -- Router stuff
router.use((req, res, next) => { router.use((req, res, next) => {
if (!req.session.bingoUser) { if (!req.session.bingoUser)
req.session.bingoUser = new BingoUser(); req.session.bingoUser = new BingoUser();
}
next(); next();
}); });
@ -311,9 +331,9 @@ router.get('/', (req, res) => {
if (!bingoSession.users[bingoUser.id]) if (!bingoSession.users[bingoUser.id])
bingoSession.addUser(bingoUser); bingoSession.addUser(bingoUser);
if (!bingoUser.grids[gameId]) { if (!bingoUser.grids[gameId])
bingoUser.grids[gameId] = generateWordGrid([bingoSession.gridSize, bingoSession.gridSize], bingoSession.words); bingoUser.grids[gameId] = generateWordGrid([bingoSession.gridSize, bingoSession.gridSize], bingoSession.words);
}
res.render('bingo/bingo-game', { res.render('bingo/bingo-game', {
grid: bingoUser.grids[gameId].fieldGrid, grid: bingoUser.grids[gameId].fieldGrid,
username: bingoUser.username, username: bingoUser.username,
@ -340,7 +360,7 @@ router.graphqlResolver = (req, res) => {
return bingoSession; return bingoSession;
}, },
checkBingo: () => { checkBingo: () => {
return checkBingo(bingoUser.grids[gameId]) return checkBingo(bingoUser.grids[gameId]);
}, },
activeGrid: () => { activeGrid: () => {
return bingoUser.grids[gameId]; return bingoUser.grids[gameId];
@ -348,7 +368,7 @@ router.graphqlResolver = (req, res) => {
// mutation // mutation
createGame: ({input}) => { createGame: ({input}) => {
let words = input.words.filter((el) => { // remove empty strings and non-types from word array let words = input.words.filter((el) => { // remove empty strings and non-types from word array
return (!!el && el.length > 0) return (!!el && el.length > 0);
}); });
let size = input.size; let size = input.size;
if (words.length > 0 && size < 10 && size > 0) { if (words.length > 0 && size < 10 && size > 0) {
@ -404,14 +424,14 @@ router.graphqlResolver = (req, res) => {
} }
}, },
createFollowupGame: () => { createFollowupGame: () => {
if (bingoSession) { if (bingoSession)
if (!bingoSession.followup) if (!bingoSession.followup)
return bingoSession.createFollowup(); return bingoSession.createFollowup();
else else
return bingoSessions[bingoSession.followup]; return bingoSessions[bingoSession.followup];
} else { else
res.status(400); res.status(400);
}
}, },
sendChatMessage: ({input}) => { sendChatMessage: ({input}) => {
input.message = replaceTagSigns(input.message).substring(0, 250); input.message = replaceTagSigns(input.message).substring(0, 250);

@ -2,7 +2,7 @@ const express = require('express');
const router = express.Router(); const router = express.Router();
/* GET home page. */ /* GET home page. */
router.get('/', function(req, res, next) { router.get('/', function(req, res) {
res.render('index', { title: 'Trivernis.net' }); res.render('index', { title: 'Trivernis.net' });
}); });

@ -18,10 +18,9 @@ class RedditDownload {
/** /**
* Generates an id for a subreddit download. * Generates an id for a subreddit download.
* @param subreddit
* @returns {string} * @returns {string}
*/ */
function generateDownloadId(subreddit) { function generateDownloadId() {
return Date.now().toString(16); return Date.now().toString(16);
} }
@ -32,7 +31,7 @@ function generateDownloadId(subreddit) {
*/ */
function startDownload(subreddit) { function startDownload(subreddit) {
if (rWordOnly.test(subreddit)) { if (rWordOnly.test(subreddit)) {
let downloadId = generateDownloadId(subreddit); let downloadId = generateDownloadId();
let dlFilePath = `./public/static/${downloadId}.zip`; let dlFilePath = `./public/static/${downloadId}.zip`;
let dlWebPath = `/static/${downloadId}.zip`; let dlWebPath = `/static/${downloadId}.zip`;
let dl = new RedditDownload(dlWebPath); let dl = new RedditDownload(dlWebPath);
@ -40,13 +39,11 @@ function startDownload(subreddit) {
dl.process = cproc.exec(`python3 -u riddle.py -o ../../public/static/${downloadId} -z --lzma ${subreddit}`, dl.process = cproc.exec(`python3 -u riddle.py -o ../../public/static/${downloadId} -z --lzma ${subreddit}`,
{cwd: './scripts/reddit-riddle', env: {PYTHONIOENCODING: 'utf-8', PYTHONUNBUFFERED: true}}, {cwd: './scripts/reddit-riddle', env: {PYTHONIOENCODING: 'utf-8', PYTHONUNBUFFERED: true}},
(err, stdout) => { (err, stdout) => {
if (err) { if (err)
console.error(err); console.error(err);
} else { else
console.log(`riddle.py: ${stdout}`); console.log(`riddle.py: ${stdout}`);
}
}); });
dl.process.on('exit', (code) => { dl.process.on('exit', (code) => {
if (code === 0) if (code === 0)
dl.status = 'finished'; dl.status = 'finished';
@ -57,20 +54,17 @@ function startDownload(subreddit) {
delete downloads[downloadId]; delete downloads[downloadId];
}, 300000); // delete the file after 5 minutes }, 300000); // delete the file after 5 minutes
}); });
dl.process.on('message', (msg) => { dl.process.on('message', (msg) => {
console.log(msg) console.log(msg);
}); });
downloads[downloadId] = dl; downloads[downloadId] = dl;
return downloadId; return downloadId;
} }
} }
router.use('/files', express.static('./tmp')); router.use('/files', express.static('./tmp'));
router.get('/', (req, res, next) => { router.get('/', (req, res) => {
res.render('riddle'); res.render('riddle');
}); });
@ -84,16 +78,15 @@ router.post('/', (req, res) => {
let id = req.body.id; let id = req.body.id;
let download = downloads[id]; let download = downloads[id];
if (download) { if (download)
res.send({ res.send({
id: id, id: id,
status: download.status, status: download.status,
file: download.file file: download.file
}); });
} else { else
res.send({error: 'Unknown download ID', id: id}); res.send({error: 'Unknown download ID', id: id});
} }
}
}); });
module.exports = router; module.exports = router;

@ -2,8 +2,8 @@ const express = require('express');
const router = express.Router(); const router = express.Router();
/* GET users listing. */ /* GET users listing. */
router.get('/', function(req, res, next) { router.get('/', function(req, res) {
res.send('respond with a resource'); res.send('There are no users :(');
}); });
module.exports = router; module.exports = router;

Loading…
Cancel
Save