0
0
Fork 0

Merge pull request #52 from Oliver-Akins/dev

v1.2.2
This commit is contained in:
Oliver 2021-01-11 16:53:50 -07:00 committed by GitHub
commit 7e12124330
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 149 additions and 40 deletions

1
.gitignore vendored
View file

@ -7,6 +7,7 @@ server/built/*
server/dist/*
server/resources/*
*.log
*.sh
#=============================================================================#
# The files that were auto-generated into a .gitignore by Vue-cli

View file

@ -15,6 +15,7 @@
"@types/engine.io": "^3.1.4",
"@types/node": "^14.14.14",
"@types/socket.io": "^2.1.12",
"axios": "^0.21.1",
"fs": "^0.0.1-security",
"neat-csv": "^6.0.0",
"socket.io": "^3.0.4",

19
server/pnpm-lock.yaml generated
View file

@ -2,6 +2,7 @@ dependencies:
'@types/engine.io': 3.1.4
'@types/node': 14.14.14
'@types/socket.io': 2.1.12
axios: 0.21.1
fs: 0.0.1-security
neat-csv: 6.0.0
socket.io: 3.0.4
@ -54,6 +55,12 @@ packages:
node: '>= 0.6'
resolution:
integrity: sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
/axios/0.21.1:
dependencies:
follow-redirects: 1.13.1
dev: false
resolution:
integrity: sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
/base64-arraybuffer/0.1.4:
dev: false
engines:
@ -127,6 +134,17 @@ packages:
node: '>=10.0.0'
resolution:
integrity: sha512-Ri+whTNr2PKklxQkfbGjwEo+kCBUM4Qxk4wtLqLrhH+b1up2NFL9g9pjYWiCV/oazwB0rArnvF/ZmZN2ab5Hpg==
/follow-redirects/1.13.1:
dev: false
engines:
node: '>=4.0'
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
resolution:
integrity: sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==
/fs/0.0.1-security:
dev: false
resolution:
@ -266,6 +284,7 @@ specifiers:
'@types/engine.io': ^3.1.4
'@types/node': ^14.14.14
'@types/socket.io': ^2.1.12
axios: ^0.21.1
fs: ^0.0.1-security
neat-csv: ^6.0.0
socket.io: ^3.0.4

View file

@ -1,7 +1,7 @@
import { readFileSync } from 'fs';
import { Game } from '../objects/Game';
import { Player } from '../objects/Player';
import { Server, Socket } from 'socket.io';
import { readFileSync, unlinkSync } from 'fs';
import { games, hibernatedGames, log, conf } from '../main';
export default (io: Server, socket: Socket, data: JoinGame) => {
@ -10,28 +10,40 @@ export default (io: Server, socket: Socket, data: JoinGame) => {
// Game object and bring it back to being alive
let hibernatedIndex = hibernatedGames.indexOf(data.game_code)
if (hibernatedIndex >= 0) {
log.info(`Recreating game from datastore.`);
log.info(`Attempting to recreate game from datastore.`);
// Reinstantiate the game using the data from the disk
let datastore = JSON.parse(readFileSync(
`${conf.datastores.directory}/${data.game_code}.${conf.datastores.filetype}`,
`utf-8`
)) as datastoreGame;
let playerData = datastore.players.find(p => p.name === data.name);
// Assert that the name matches someone in the hibernated game
if (!playerData) {
log.info(`[${data.game_code}] User attempted unhibernate game with an invalid name`);
socket.emit(`GameJoined`, {
status: 403,
message: `Game with code "${data.game_code}" could not be found`,
source: `JoinGame`
});
return;
}
// Instantiate the host's player object
let host = new Player(data.name, socket, true);
host.role = playerData.role;
host.team = playerData.team;
// Re-instantiate the game object
let game = Game.fromJSON(host, datastore);
game.log = log.getChildLogger({
displayLoggerName: true,
name: game.id,
});
game.ingame = datastore.ingame;
// Get the specific information for team
let playerData = datastore.players.find(p => p.name === data.name);
if (playerData) {
host.role = playerData.role;
host.team = playerData.team;
};
let hand: string[] = [];
if (host.team) {
let team = game.teams[host.team - 1];
@ -50,12 +62,20 @@ export default (io: Server, socket: Socket, data: JoinGame) => {
`${game.id}:*:${host.role}`,
`${game.id}:${host.team}:${host.role}`
]);
game.log.debug(`Host assigned to team`);
game.log.debug(`Host assigned to team object`);
};
hibernatedGames.splice(hibernatedIndex, 1);
games[game.id] = game;
// Try removing the file from the directory
try {
unlinkSync(`${conf.datastores.directory}/${game.id}.${conf.datastores.filetype}`);
game.log.info(`Game datastore deleted`);
} catch (err) {
game.log.prettyError(err);
};
game.log.info(`Successfully unhibernated`);
socket.join(game.id);
socket.emit(`GameRejoined`, {
@ -94,8 +114,8 @@ export default (io: Server, socket: Socket, data: JoinGame) => {
socket. This will also function as the main game joining for hibernated
games that were reloaded from disk.
*/
let sameName = game.players.find(x => x.name == data.name);
if (sameName != null) {
let sameName = game.players.find(x => x.name === data.name);
if (sameName) {
if (!sameName.socket?.connected) {
sameName.socket = socket;
@ -132,7 +152,7 @@ export default (io: Server, socket: Socket, data: JoinGame) => {
game.log.debug(`${socket.id} attempted to join with a name already in use ${data.name}`);
socket.emit(`GameJoined`, {
status: 403,
message: `A player already has that name in the game.`,
message: `Cannot connect to a game that's in progress.`,
source: `JoinGame`
});
return;

View file

@ -13,9 +13,11 @@ export default (io: Server, socket: Socket, data: ResetGame) => {
return;
};
let game = games[data.game_code];
game.log.info(`Resetting game`)
game.questions.reset();
game.resetObject();
game.ingame = false;
io.to(game.id).emit(`GameReset`, { status: 200 });
} catch (err) {

View file

@ -85,11 +85,11 @@ const modifyPlayer = (io: Server, socket: Socket, data: UpdatePlayer): void => {
switch (data.to.role) {
case "guesser":
if (team.guessers.length >= 7) {
game.log.debug(`Game cannot have more than 7 guessers`);
if (team.guessers.length >= conf.game.guesser_limit) {
game.log.debug(`Game cannot have more than ${conf.game.guesser_limit} guessers`);
socket.emit(`PlayerUpdate`, {
status: 403,
message: `A team can't have 8 or more ${conf.game.guesser_name}`,
message: `That team already has the maximum number of ${conf.game.guesser_name}s`,
source: `UpdatePlayer.Modify`
});
return;
@ -128,11 +128,11 @@ const modifyPlayer = (io: Server, socket: Socket, data: UpdatePlayer): void => {
let team = game.teams[data.to.team - 1];
switch (data.to.role) {
case "guesser":
if (team.guessers.length >= 7) {
game.log.debug(`Game cannot have more than 7 guessers`);
if (team.guessers.length >= conf.game.guesser_limit) {
game.log.debug(`Game cannot have more than ${conf.game.guesser_limit} guessers`);
socket.emit(`PlayerUpdate`, {
status: 403,
message: `A team can't have 8 or more ${conf.game.guesser_name}`,
message: `That team already has the maximum number of ${conf.game.guesser_name}s`,
source: `UpdatePlayer.Modify`
});
return;
@ -181,11 +181,11 @@ const modifyPlayer = (io: Server, socket: Socket, data: UpdatePlayer): void => {
switch (data.to.role) {
case "guesser":
// Ensure we don't get 8 guessers
if (newTeam.guessers.length >= 7) {
game.log.debug(`Game cannot have 8 or more guessers on a team.`);
if (newTeam.guessers.length >= conf.game.guesser_limit) {
game.log.debug(`That team already`);
socket.emit(`PlayerUpdate`, {
status: 403,
message: `Cannot have 8 players as ${conf.game.guesser_name}s on a single team.`,
message: `That team already has the maximum number of ${conf.game.guesser_name}s`,
source: `UpdatePlayer.Modify`
});
return;

View file

@ -1,10 +1,11 @@
import axios from "axios";
import { Team } from "./Team";
import { Deck } from "./Deck";
import { readFile } from "fs";
import neatCSV from "neat-csv";
import { Logger } from "tslog";
import { Player } from "./Player";
import { games, hibernatedGames, conf } from "../main";
import { games, hibernatedGames, conf, log } from "../main";
export class Game {
readonly id: string;
@ -32,10 +33,10 @@ export class Game {
// Get the decks based on what type of data they are.
switch (conf.game.cards.type) {
case "csv":
this.parseDeckCSV(conf);
this.parseDeckCSV();
break;
case "sheets":
this.parseDeckGoogleSheets(conf);
this.parseDeckGoogleSheets();
break;
};
// Instantiate everything for the teams
@ -68,11 +69,10 @@ export class Game {
}
private parseDeckCSV(conf: config) {
private parseDeckCSV() {
/**
* Parses out the CSV files and creates the decks for the game to run on
*
* @param path -> The filepath of the CSV file
* Parses out the CSV files and creates the decks for the game to run
* on.
*/
// parse the questions from the CSV
@ -102,13 +102,61 @@ export class Game {
});
};
private parseDeckGoogleSheets(conf: config) {
private parseDeckGoogleSheets() {
/**
* Fetches and parses the CSV data from Google Sheets instead of local
* CSV files.
*
* @param conf -> The config object
*/
let key = conf.game.cards.key as string;
let questions_id = conf.game.cards.questions.fingerprint;
let objects_id = conf.game.cards.objects.fingerprint;
// Get the questions deck
axios.get(`https://docs.google.com/spreadsheets/d/e/${key}/pub?gid=${questions_id}&single=true&output=csv`)
.then(response => {
// Ensure not errored
if (response.status !== 200) {
log.warn(`Error Downloading CSV: ${response.statusText}`);
return;
};
// Parse the loaded CSV
neatCSV(response.data)
.then((data) => {
let questions: question_deck[] = [];
for (var entry of data) {
questions.push(Object.values(entry)[conf.game.cards.questions.column]);
};
this._questions = new Deck(questions);
});
})
.catch(err => {
log.prettyError(err);
});
// Get the objects deck
axios.get(`https://docs.google.com/spreadsheets/d/e/${key}/pub?gid=${objects_id}&single=true&output=csv`)
.then(response => {
// Ensure not errored
if (response.status !== 200) {
log.warn(`Error Downloading CSV: ${response.statusText}`);
return;
};
// Parse the downloaded CSV
neatCSV(response.data)
.then((data) => {
let objects: object_deck[] = [];
for (var line of data) {
objects.push(Object.values(line));
};
this._objects = new Deck(objects);
});
})
.catch(err => {
log.prettyError(err);
});
};
@ -119,6 +167,7 @@ export class Game {
if (this._objectCard) {
this._objects.discard(this._objectCard);
this._objectCard = null;
this.object = ``;
};
};

View file

@ -17,6 +17,7 @@ interface config {
code_length: number;
writer_name: string;
guesser_name: string;
guesser_limit: number;
cards: {
type: `csv` | `sheets`;
key?: string;

View file

@ -12,7 +12,7 @@ export class Validate {
};
// Assert data in the game object
if (![`csv`].includes(conf.game.cards.type)) {
if (![`csv`, `sheets`].includes(conf.game.cards.type)) {
log.error(`Unsupported cards type: ${conf.game.cards.type}`);
valid = false;
};

View file

@ -11,6 +11,8 @@ code_length = 6
writer_name = "Spirit"
guesser_name = "Medium"
# The limit of players that are allowed to be guessers on each team.
guesser_limit = 7
[game.cards]

View file

@ -61,6 +61,7 @@ export default {
"Toml": "https://www.npmjs.com/package/toml",
"tslog": "https://www.npmjs.com/package/tslog",
"Socket.io": "https://socket.io",
"Axios": "https://www.npmjs.com/package/axios",
"neat-csv": "https://github.com/sindresorhus/neat-csv",
}
}},

View file

@ -13,7 +13,8 @@
v-for="answerIndex in 8"
:class="[
`answer`,
answers[`team_${3 - $store.state.team}`][answerIndex-1].toLowerCase() == $store.state.chosen_object+`.` ? `correct`: ``
answers[`team_${3 - $store.state.team}`][answerIndex-1].toLowerCase() === getObject
? `correct`: ``
]"
:key="`${otherTeamID}-answer-container-${answerIndex}`"
>
@ -57,7 +58,8 @@
v-for="answerIndex in 8"
:class="[
`answer`,
answers[`team_${$store.state.team}`][answerIndex-1].toLowerCase() == $store.state.chosen_object+`.` ? `correct`: ``
answers[`team_${$store.state.team}`][answerIndex-1].toLowerCase() === getObject
? `correct`: ``
]"
:key="`${teamID}-answer-container-${answerIndex}`"
>
@ -122,6 +124,12 @@ export default {
answers() {
return this.$store.state.answers;
},
getObject() {
if (!this.$store.state.chosen_object) {
return ``;
};
return this.$store.state.chosen_object.toLowerCase() + `.`;
},
},
methods: {
isCorrect(team, answerIndex) {

View file

@ -5,7 +5,7 @@
</div>
<div class="flex-center" v-else-if="gameOver">
<a
v-if="$store.state.survery_link"
v-if="$store.state.survey_link"
:href="$store.state.survey_link"
target="_blank"
rel="noopener"
@ -74,8 +74,13 @@ export default {
gameOver() {
if (this.$store.state.chosen_object) {
let targetAnswer = this.$store.state.chosen_object.toLowerCase()+`.`;
return this.$store.state.answers.team_1.includes(targetAnswer)
|| this.$store.state.answers.team_2.includes(targetAnswer);
for (var team in this.$store.state.answers) {
for (var answer of this.$store.state.answers[team]) {
if (answer.toLowerCase() === targetAnswer) {
return true;
};
};
};
};
return false;
},

View file

@ -114,7 +114,7 @@ export default {
* },
*/
console.log(data)
if (!(200 <= data.status && data.status < 300)) {
if (data.status < 200 || 300 <= data.status) {
this.$emit(`error`, data);
return;
};