diff --git a/backend/api/rounds.js b/backend/api/rounds.js index 761dd65f3abfadf347af73fd58b2be006de89665..f9d4a3730a3468e8dc8a0a85e52b7f20391107fb 100644 --- a/backend/api/rounds.js +++ b/backend/api/rounds.js @@ -45,35 +45,24 @@ router.get("/round/:roundId", (req, res) => { ); }); -function updateHighscore(gameid, playerid, value) { +function updateHighscore(client, gameid, playerid, value) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + const db = client.db("gameWare"); + const collection = "highscores"; + + db.collection(collection).updateOne( + { + gameId: mongo.ObjectID(gameid), + playerId: mongo.ObjectID(playerid) + }, + { $max: { value: value } }, + { upsert: true }, + (err, result) => { if (err) { - resolve(500); // Internal server error + resolve(500); + return; } - - const db = client.db("gameWare"); - const collection = "highscores"; - - db.collection(collection).updateOne( - { - gameId: mongo.ObjectID(gameid), - playerId: mongo.ObjectID(playerid) - }, - { $max: { value: value } }, - { upsert: true }, - (err, result) => { - if (err) { - resolve(500); - return; - } - resolve(result); - } - ); + resolve(result); } ); }); @@ -419,11 +408,12 @@ router.put("/:roundid/:tournamentid", (req, res) => { if (updatedDocument.value) { //console.log("Successfully updated document"); updateHighscore( + client, updatedDocument.value.gameId, updatedDocument.value.playerId, updatedDocument.value.scoreValue ); - roundcheck(tournament).then(checkresult => { + roundcheck(client, tournament, id).then(checkresult => { res.json(checkresult); client.close(); return; @@ -440,9 +430,10 @@ router.put("/:roundid/:tournamentid", (req, res) => { ); }); -function roundcheck(tournament) { +function roundcheck(client, tournament, roundid) { return new Promise((resolve, reject) => { - getCurrentRound(tournament).then(roundResult => { + getCurrentRound(client, tournament).then(roundResult => { + // gets the current round of the tournament if (roundResult == 500) { resolve(500); return; @@ -450,273 +441,300 @@ function roundcheck(tournament) { const active = roundResult.currentRound; const start = roundResult.startTime; const maxPlayers = roundResult.maxPlayers; - console.log( - "Active: " + active + " , start: " + start + " , max: " + maxPlayers - ); - checkRounds(tournament, active, start).then(result => { - if (!result) { - resolve("Score updated. Round " + active + " in progress"); //1. check if other rounds are done - } else { - fetchRounds(tournament, active).then(rounds => { - players = rounds.length; - for (let i = 0; i < rounds.length; i++) { - let round = rounds[i]; - updateScore(round._id, i + 1, rounds.length); - } - updateTournamentRound(tournament).then(result => { - if (result.value) { - tourny = result.value; - const game = - tourny.games[tourny.currentRound % tourny.games.length]; - const date = new Date(); - date.setTime( - date.getTime() + tourny.timePerRound * 60 * 60 * 1000 - ); - for (let i = 0; i < tourny.players.length; i++) { - newRound( - tournament, - tourny.players[i], - game, - tourny.currentRound, - date - ); + + fetchRounds(client, tournament, active).then(rounds => { + // fetched the round objects of the active round + checkRounds(rounds, start, maxPlayers, active).then(resultarray => { + // check to find out if [0] tournament will move on, [1] which players are timed out + // [2] which players are still in the tournament + let result = resultarray[0]; + let timedOut = resultarray[1]; + let left = resultarray[2]; + let end = false; + if ((left.length < 2 && active != 1) || left.length == 0) { + end = true; + //if there are less then two people left in the first round, or zero people left in the first round + //the tournament ends + } + timeOut(client, tournament, timedOut, end, active).then( + //updates the state of the tournament and ends it if necessary + //TODO: notify the players that the tournament ended + timeoutresult => { + if (end) { + resolve(getRound(client, roundid)); + return; + } + if (result) { + //Tournament moves on to next round + let eligibleRounds = []; + for (let i = 0; i < rounds.length; i++) { + let round = rounds[i]; + if (round.hasPlayed === true) { + eligibleRounds.push(round); + } + } + //Here we find the rounds that were actually completed + for (let i = 0; i < eligibleRounds.length; i++) { + let round = eligibleRounds[i]; + updateScore(client, round._id, i + 1, eligibleRounds.length); + //And here we update the tournament score } - resolve(tourny); + updateTournamentRound(client, tournament).then(result => { + //updates the tournaments round if there are more rounds left + if (result.value) { + tourny = result.value; + const game = + tourny.games[tourny.currentRound % tourny.games.length]; + const date = new Date(); + date.setTime( + date.getTime() + tourny.timePerRound * 60 * 60 * 1000 + ); + for (let i = 0; i < tourny.players.length; i++) { + newRound( + client, + tournament, + tourny.players[i], + game, + tourny.currentRound, + date + ); + // created new rounds for all the players left + } + resolve(getRound(client, roundid)); + } else { + // if the tournament now is done we simply end it + endTournament(client, tournament); + resolve(getRound(client, roundid)); + return; + } + }); } else { - resolve("Score updated. Tournament over"); + resolve(getRound(client, roundid)); // Tournament still waiting for other players } - }); - }); - } - - //2.1 Get rounds by roundnr, sort by score - //2.2 for each entry in fetched array, call the update method. - //3. set tournamentplayer score + } + ); + }); }); }); }); } -function getCurrentRound(tournamentId) { +function getRound(client, id) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + const db = client.db("gameWare"); + const collection = "rounds"; + + db.collection(collection).findOne({ _id: id }, (err, result) => { + if (err) { + resolve(500); // Internal server error + return; + } + resolve(result); + return; + }); + }); +} + +function endTournament(client, tournament) { + return new Promise((resolve, reject) => { + const db = client.db("gameWare"); + const collection = "tournaments"; + db.collection(collection).updateOne( + { _id: tournament }, + { $set: { active: false } }, + (err, result) => { if (err) { resolve(500); // Internal server error return; } - const db = client.db("gameWare"); - const collection = "tournaments"; - - db.collection(collection).findOne( - { - _id: tournamentId - }, - { currentRound: 1, startTime: 1, maxPlayers: 1 }, - (err, result) => { - if (err) { - resolve(500); // Internal server error - return; - } - resolve(result); - return; - } - ); + resolve(result); + return; } ); }); } -function newRound(tournamentId, playerId, gameId, roundNr, deadlineDate) { +function timeOut(client, tournament, players, end) { + if (!players) { + players = []; + } return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + const db = client.db("gameWare"); + db.collection("tournaments").updateOne( + { + _id: tournament + }, + { + $pull: { players: { $in: players } }, + $inc: { currentPlayers: -players.length }, + $set: { active: !end } + }, + (err, result) => { if (err) { - res.sendStatus(500); // Internal server error + resolve(500); // Internal server error return; } - - // Using the database gameWare and collection rounds - const db = client.db("gameWare"); - const collection = "rounds"; - - db.collection(collection).insertOne( - { - tournamentId: mongo.ObjectID(tournamentId), - playerId: mongo.ObjectID(playerId), - gameId: mongo.ObjectID(gameId), - roundNr: roundNr, - deadlineDate: deadlineDate, - scoreValue: 0, - hasPlayed: false, - tournamentPoints: 0 - }, - (err, result) => { - if (err) { - resolve(500); // Internal server error - return; - } - resolve(result.ops[0]); - } - ); + resolve(result); + return; } ); }); } -function updateTournamentRound(tournament) { +function getCurrentRound(client, tournamentId) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + const db = client.db("gameWare"); + const collection = "tournaments"; + + db.collection(collection).findOne( + { + _id: tournamentId + }, + { currentRound: 1, startTime: 1, maxPlayers: 1 }, + (err, result) => { if (err) { resolve(500); // Internal server error + return; } - - const db = client.db("gameWare"); - const collection = "tournaments"; - - db.collection(collection) - .findOneAndUpdate( - { - _id: tournament, - $expr: { - $lt: ["$currentRound", "$totalGames"] - } - }, - { - $inc: { currentRound: 1 } - }, - { - returnOriginal: false - } - ) - .then(updatedDocument => { - resolve(updatedDocument); - }); + resolve(result); + return; } ); }); } -function checkRounds(tournament, active, start, max) { +function newRound( + client, + tournamentId, + playerId, + gameId, + roundNr, + deadlineDate +) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + // Using the database gameWare and collection rounds + const db = client.db("gameWare"); + const collection = "rounds"; + + db.collection(collection).insertOne( + { + tournamentId: mongo.ObjectID(tournamentId), + playerId: mongo.ObjectID(playerId), + gameId: mongo.ObjectID(gameId), + roundNr: roundNr, + deadlineDate: deadlineDate, + scoreValue: 0, + hasPlayed: false, + tournamentPoints: 0 + }, + (err, result) => { if (err) { resolve(500); // Internal server error + return; } - - const db = client.db("gameWare"); - const collection = "rounds"; - - db.collection(collection) - .find( - { - tournamentId: tournament, - roundNr: active - }, - { - hasPlayed: 1 - } - ) - .toArray((err, result) => { - if (err) { - resolve(500); - return; - } - - let amountComplete = 0; - for (let i = 0; i < result.length; i++) { - if (result[i].hasPlayed === false) { - amountComplete++; - } - } - if (amountComplete == max) { - resolve(true); - } else if (amountComplete > 1 && new Date() > start) { - resolve(true); - } - resolve(false); - }); + resolve(result.ops[0]); } ); }); } -function fetchRounds(tournamentId, activeRound) { +function updateTournamentRound(client, tournament) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database - if (err) { - resolve(500); // Internal server error + const db = client.db("gameWare"); + const collection = "tournaments"; + + db.collection(collection) + .findOneAndUpdate( + { + _id: tournament, + $expr: { + $lt: ["$currentRound", "$totalGames"] + } + }, + { + $inc: { currentRound: 1 } + }, + { + returnOriginal: false } + ) + .then(updatedDocument => { + resolve(updatedDocument); + }); + }); +} - const db = client.db("gameWare"); - const collection = "rounds"; - - db.collection("rounds") - .find({ - tournamentId: tournamentId, - roundNr: activeRound - }) - .sort({ - scoreValue: -1 - }) - .toArray((err, result) => { - if (err) { - return; - } - resolve(result); - }); +function checkRounds(result, start, max, roundNr) { + return new Promise((resolve, reject) => { + let timedOut = []; + let left = []; + let amountComplete = 0; + for (let i = 0; i < result.length; i++) { + if (result[i].hasPlayed === true) { + amountComplete++; + left.push(result[i].playerId); + } else if (new Date(result[i].deadlineDate) <= new Date()) { + timedOut.push(result[i].playerId); + } else { + left.push(result[i].playerId); } - ); + } + if (amountComplete == max) { + // All players have completed their round + resolve([true, [], left]); + } else if (amountComplete > 1 && new Date() >= start && roundNr == 1) { + // more than two have completed first round + // startDelay passed. + resolve([true, timedOut, left]); + } else if (amountComplete + timedOut.length == max && amountComplete >= 2) { + // More than two players have completed round and all players have either completed their round or timed out. + resolve([true, timedOut, left]); + } else { + resolve([false, timedOut, left]); + } }); } -function updateScore(id, placement, playerAmount) { - let tournamentPoints = (playerAmount - placement + 1) * 10; - +function fetchRounds(client, tournamentId, activeRound) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + const db = client.db("gameWare"); + const collection = "rounds"; + + db.collection("rounds") + .find({ + tournamentId: tournamentId, + roundNr: activeRound + }) + .sort({ + scoreValue: -1 + }) + .toArray((err, result) => { if (err) { - resolve(500); // Internal server error + return; } + resolve(result); + }); + }); +} - const db = client.db("gameWare"); - const collection = "rounds"; - - db.collection(collection) - .findOneAndUpdate( - { - _id: mongo.ObjectID(id) - }, - { $set: { tournamentPoints: tournamentPoints } }, - { returnNewDocument: true } - ) - .then(updatedDocument => { - resolve(updatedDocument); - }); - } - ); +function updateScore(client, id, placement, playerAmount) { + let tournamentPoints = (playerAmount - placement + 1) * 10; + + return new Promise((resolve, reject) => { + const db = client.db("gameWare"); + const collection = "rounds"; + + db.collection(collection) + .findOneAndUpdate( + { + _id: mongo.ObjectID(id) + }, + { $set: { tournamentPoints: tournamentPoints } }, + { returnNewDocument: true } + ) + .then(updatedDocument => { + resolve(updatedDocument); + }); }); } diff --git a/backend/api/tournament.js b/backend/api/tournament.js index d01943897295b1acf1a9b12129f5d8a419c62394..75fca82ff4723dcf547206643122d5ba1e2213fc 100644 --- a/backend/api/tournament.js +++ b/backend/api/tournament.js @@ -340,283 +340,334 @@ router.get("/player/:userid/:active", (req, res) => { ); }); -router.post("/roundcheck", (req, res) => { - let tournament; - if (tournament == null) { - res.status(400).send("ID missing"); +router.put("/roundcheck/:tournamentId", (req, res) => { + let tournament = null; + try { + tournament = mongo.ObjectID(req.params.tournamentId); + } catch (error) { + res.status(400).send("No document with specified id was found"); return; } - try { - tournament = mongo.ObjectID(req.body.tournamentid); - } catch (err) { - res.status(400).send("Invalid ID"); + if (!tournament) { + res.status(400).send("Request body not valid"); return; } - getCurrentRound(tournament).then(roundResult => { - if (roundResult == 500) { - res.sendStatus(500); - return; - } - const active = roundResult; - checkRounds(tournament, active).then(result => { - if (!result) { - res.status(204).send("Round " + active + " in progress"); //1. check if other rounds are done - } else { - fetchRounds(tournament, active).then(rounds => { - players = rounds.length; - for (let i = 0; i < rounds.length; i++) { - let round = rounds[i]; - updateScore(round._id, i + 1, rounds.length); - } - updateTournamentRound(tournament).then(result => { - if (result.value) { - tourny = result.value; - const game = - tourny.games[tourny.currentRound % tourny.games.length]; - const date = new Date(); - date.setTime( - date.getTime() + tourny.timePerRound * 60 * 60 * 1000 - ); - for (let i = 0; i < tourny.players.length; i++) { - newRound( - tournament, - tourny.players[i], - game, - tourny.currentRound + 1, - date - ); - } - res.json(tourny); - client.close(); - } else { - res.status(200).send("Tournament over"); + MongoClient.connect( + connectionUrl, + { useNewUrlParser: true, useUnifiedTopology: true }, + (err, client) => { + // Unable to connect to database + if (err) { + res.sendStatus(500); // Internal server error + return; + } + + getCurrentRound(client, tournament).then(roundResult => { + // gets the current round of the tournament + if (roundResult == 500) { + res.sendStatus(500); + return; + } + const active = roundResult.currentRound; + const start = roundResult.startTime; + const maxPlayers = roundResult.maxPlayers; + + fetchRounds(client, tournament, active).then(rounds => { + // fetched the round objects of the active round + checkRounds(rounds, start, maxPlayers, active).then(resultarray => { + // check to find out if [0] tournament will move on, [1] which players are timed out + // [2] which players are still in the tournament + let result = resultarray[0]; + let timedOut = resultarray[1]; + let left = resultarray[2]; + let end = false; + if ((left.length < 2 && active != 1) || left.length == 0) { + end = true; + //if there are less then two people left in the first round, or zero people left in the first round + //the tournament ends } + timeOut(client, tournament, timedOut, end, active).then( + //updates the state of the tournament and ends it if necessary + //TODO: notify the players that the tournament ended + timeoutresult => { + if (end) { + res.json({ + active: false, + nextRound: false + }); + return; + } + if (result) { + //Tournament moves on to next round + let eligibleRounds = []; + for (let i = 0; i < rounds.length; i++) { + let round = rounds[i]; + if (round.hasPlayed === true) { + eligibleRounds.push(round); + } + } + //Here we find the rounds that were actually completed + for (let i = 0; i < eligibleRounds.length; i++) { + let round = eligibleRounds[i]; + updateScore( + client, + round._id, + i + 1, + eligibleRounds.length + ); + //And here we update the tournament score + } + updateTournamentRound(client, tournament).then(result => { + //updates the tournaments round if there are more rounds left + if (result.value) { + tourny = result.value; + const game = + tourny.games[tourny.currentRound % tourny.games.length]; + const date = new Date(); + date.setTime( + date.getTime() + tourny.timePerRound * 60 * 60 * 1000 + ); + for (let i = 0; i < tourny.players.length; i++) { + newRound( + client, + tournament, + tourny.players[i], + game, + tourny.currentRound, + date + ); + // created new rounds for all the players left + } + res.json({ + active: true, + nextRound: true + }); + } else { + // if the tournament now is done we simply end it + endTournament(client, tournament); + res.json({ + active: false, + nextRound: false + }); + return; + } + }); + } else { + res.json({ + active: true, + nextRound: false + }); // Tournament still waiting for other players + } + } + ); }); }); - } - - //2.1 Get rounds by roundnr, sort by score - //2.2 for each entry in fetched array, call the update method. - //3. set tournamentplayer score - }); - }); + }); + } + ); }); -function getCurrentRound(tournamentId) { +function endTournament(client, tournament) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + const db = client.db("gameWare"); + const collection = "tournaments"; + db.collection(collection).updateOne( + { _id: tournament }, + { $set: { active: false } }, + (err, result) => { if (err) { resolve(500); // Internal server error return; } - const db = client.db("gameWare"); - const collection = "tournaments"; - - db.collection(collection).findOne( - { - _id: tournamentId - }, - { currentRound: 1 }, - (err, result) => { - if (err) { - resolve(500); // Internal server error - return; - } - resolve(result); - return; - } - ); + resolve(result); + return; } ); }); } -function newRound(tournamentId, playerId, gameId, roundNr, deadlineDate) { +function timeOut(client, tournament, players, end) { + if (!players) { + players = []; + } return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + const db = client.db("gameWare"); + db.collection("tournaments").updateOne( + { + _id: tournament + }, + { + $pull: { players: { $in: players } }, + $inc: { currentPlayers: -players.length }, + $set: { active: !end } + }, + (err, result) => { if (err) { - res.sendStatus(500); // Internal server error + resolve(500); // Internal server error return; } - - // Using the database gameWare and collection rounds - const db = client.db("gameWare"); - const collection = "rounds"; - - db.collection(collection).insertOne( - { - tournamentId: mongo.ObjectID(tournamentId), - playerId: mongo.ObjectID(playerId), - gameId: mongo.ObjectID(gameId), - roundNr: roundNr, - deadlineDate: deadlineDate, - scoreValue: 0, - hasPlayed: false, - tournamentPoints: 0 - }, - (err, result) => { - if (err) { - resolve(500); // Internal server error - return; - } - resolve(result.ops[0]); - } - ); + resolve(result); + return; } ); }); } -function updateTournamentRound(tournament) { +function getCurrentRound(client, tournamentId) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + const db = client.db("gameWare"); + const collection = "tournaments"; + + db.collection(collection).findOne( + { + _id: tournamentId + }, + { currentRound: 1, startTime: 1, maxPlayers: 1 }, + (err, result) => { if (err) { resolve(500); // Internal server error + return; } - - const db = client.db("gameWare"); - const collection = "tournaments"; - - db.collection(collection) - .findOneAndUpdate( - { - _id: tournament, - $expr: { - $lt: ["$currentRound", "$totalGames"] - } - }, - { - $inc: { currentRound: 1 } - }, - { - returnNewDocument: true - } - ) - .then(updatedDocument => { - resolve(updatedDocument); - }); + resolve(result); + return; } ); }); } -function checkRounds(tournament, active) { +function newRound( + client, + tournamentId, + playerId, + gameId, + roundNr, + deadlineDate +) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + // Using the database gameWare and collection rounds + const db = client.db("gameWare"); + const collection = "rounds"; + + db.collection(collection).insertOne( + { + tournamentId: mongo.ObjectID(tournamentId), + playerId: mongo.ObjectID(playerId), + gameId: mongo.ObjectID(gameId), + roundNr: roundNr, + deadlineDate: deadlineDate, + scoreValue: 0, + hasPlayed: false, + tournamentPoints: 0 + }, + (err, result) => { if (err) { resolve(500); // Internal server error + return; } - - const db = client.db("gameWare"); - const collection = "rounds"; - - db.collection(collection) - .find( - { - tournamentId: tournament, - roundNr: active - }, - { - hasPlayed: 1 - } - ) - .toArray((err, result) => { - if (err) { - resolve(500); - return; - } - let complete = true; - for (let i = 0; i < result.length; i++) { - if (result[i].hasPlayed === false) { - complete = false; - } - } - resolve(complete); - }); + resolve(result.ops[0]); } ); }); } -function fetchRounds(tournamentId, activeRound) { +function updateTournamentRound(client, tournament) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database - if (err) { - resolve(500); // Internal server error + const db = client.db("gameWare"); + const collection = "tournaments"; + + db.collection(collection) + .findOneAndUpdate( + { + _id: tournament, + $expr: { + $lt: ["$currentRound", "$totalGames"] + } + }, + { + $inc: { currentRound: 1 } + }, + { + returnOriginal: false } + ) + .then(updatedDocument => { + resolve(updatedDocument); + }); + }); +} - const db = client.db("gameWare"); - const collection = "rounds"; - - db.collection("rounds") - .find({ - tournamentId: tournamentId, - roundNr: activeRound - }) - .sort({ - scoreValue: -1 - }) - .toArray((err, result) => { - if (err) { - return; - } - resolve(result); - }); +function checkRounds(result, start, max, roundNr) { + return new Promise((resolve, reject) => { + let timedOut = []; + let left = []; + let amountComplete = 0; + for (let i = 0; i < result.length; i++) { + if (result[i].hasPlayed === true) { + amountComplete++; + left.push(result[i].playerId); + } else if (new Date(result[i].deadlineDate) <= new Date()) { + timedOut.push(result[i].playerId); + } else { + left.push(result[i].playerId); } - ); + } + if (amountComplete == max) { + // All players have completed their round + resolve([true, [], left]); + } else if (amountComplete > 1 && new Date() >= start && roundNr == 1) { + // more than two have completed first round + // startDelay passed. + resolve([true, timedOut, left]); + } else if (amountComplete + timedOut.length == max && amountComplete >= 2) { + // More than two players have completed round and all players have either completed their round or timed out. + resolve([true, timedOut, left]); + } else { + resolve([false, timedOut, left]); + } }); } -function updateScore(id, placement, playerAmount) { - let tournamentPoints = (playerAmount - placement + 1) * 10; - +function fetchRounds(client, tournamentId, activeRound) { return new Promise((resolve, reject) => { - MongoClient.connect( - connectionUrl, - { useNewUrlParser: true, useUnifiedTopology: true }, - (err, client) => { - // Unable to connect to database + const db = client.db("gameWare"); + const collection = "rounds"; + + db.collection("rounds") + .find({ + tournamentId: tournamentId, + roundNr: activeRound + }) + .sort({ + scoreValue: -1 + }) + .toArray((err, result) => { if (err) { - resolve(500); // Internal server error + return; } + resolve(result); + }); + }); +} - const db = client.db("gameWare"); - const collection = "rounds"; - - db.collection(collection) - .findOneAndUpdate( - { - _id: mongo.ObjectID(id) - }, - { $set: { tournamentPoints: tournamentPoints } }, - { returnNewDocument: true } - ) - .then(updatedDocument => { - resolve(updatedDocument); - }); - } - ); +function updateScore(client, id, placement, playerAmount) { + let tournamentPoints = (playerAmount - placement + 1) * 10; + + return new Promise((resolve, reject) => { + const db = client.db("gameWare"); + const collection = "rounds"; + + db.collection(collection) + .findOneAndUpdate( + { + _id: mongo.ObjectID(id) + }, + { $set: { tournamentPoints: tournamentPoints } }, + { returnNewDocument: true } + ) + .then(updatedDocument => { + resolve(updatedDocument); + }); }); } diff --git a/frontend/android/assets/bg1_finTourn.jpg b/frontend/android/assets/bg1_finTourn.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ed9d995aba8bd7b8910fb998321b8d19794dbe87 Binary files /dev/null and b/frontend/android/assets/bg1_finTourn.jpg differ diff --git a/frontend/android/assets/glassy/raw/dialog_holo_light.9.png b/frontend/android/assets/glassy/raw/dialog_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..4a544eee5cb114d01abfc2da9ff112a5840f1c80 Binary files /dev/null and b/frontend/android/assets/glassy/raw/dialog_holo_light.9.png differ diff --git a/frontend/android/assets/glassy/skin/glassy-ui.atlas b/frontend/android/assets/glassy/skin/glassy-ui.atlas index 0ecdc0423e6e29c711226b70e98a06ba7e682f78..8d717f3118a1b076b6e3b6f2914958767e15f8a8 100644 --- a/frontend/android/assets/glassy/skin/glassy-ui.atlas +++ b/frontend/android/assets/glassy/skin/glassy-ui.atlas @@ -52,6 +52,15 @@ checkbox-off orig: 25, 20 offset: 0, 0 index: -1 +dialog_holo_light + rotate: false + xy: 514, 907 + size: 111, 111 + split: 18, 18, 75, 19 + pad: 18, 18, 77, 19 + orig: 111, 111 + offset: 0, 0 + index: -1 font-big-export rotate: false xy: 1, 616 diff --git a/frontend/android/assets/glassy/skin/glassy-ui.json b/frontend/android/assets/glassy/skin/glassy-ui.json index d694ae7cf1e71094c5094c819793619e9cbf88de..13c0dbf6f5bf79adc12bde16db58ab37c2bed0d0 100644 --- a/frontend/android/assets/glassy/skin/glassy-ui.json +++ b/frontend/android/assets/glassy/skin/glassy-ui.json @@ -37,6 +37,12 @@ com.badlogic.gdx.graphics.Color: { g: 0 b: 0 a: 1 + }, + ui: { + a: 1 + b: 0.9 + g: 0.71 + r: 0.2 } } com.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: { @@ -58,6 +64,15 @@ com.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: { a: 1 } } + dialogDim: { + name: white + color: { + r: 0 + g: 0 + b: 0 + a: 0.45 + } + } } com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: { default: { @@ -221,5 +236,11 @@ com.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle: { titleFont: font titleFontColor: black } + dialog: { + stageBackground: dialogDim + titleFont: font + background: window + titleFontColor: ui + } } } \ No newline at end of file diff --git a/frontend/core/src/com/gameware/game/GameWare.java b/frontend/core/src/com/gameware/game/GameWare.java index 5c2cf6344795b346f0c0be7e1777e20bc802819a..2e55349b23b7cb08f049199dc450a0970675b421 100644 --- a/frontend/core/src/com/gameware/game/GameWare.java +++ b/frontend/core/src/com/gameware/game/GameWare.java @@ -14,7 +14,6 @@ import com.gameware.game.states.GameStateManager; import com.gameware.game.states.PlayStateTemplate; import com.gameware.game.states.LoginState; - import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -35,6 +34,7 @@ public class GameWare extends ApplicationAdapter { private static Music music; private static Boolean musicOn = false; private static Boolean soundEffects = true; + private Boolean includeFin = false; //private static Boolean darkMode = false; //private static String darkModeLabelString = "default"; private Player player; @@ -171,4 +171,8 @@ public class GameWare extends ApplicationAdapter { public Boolean getSoundEffects() { return soundEffects; } + + public Boolean getIncludeFin(){ return includeFin; } + + public void setIncludeFin(Boolean t){ includeFin = t; } } diff --git a/frontend/core/src/com/gameware/game/QueryIntermediate.java b/frontend/core/src/com/gameware/game/QueryIntermediate.java index 376912fe0617944dbad6fc5723d5cd83a31b3faa..e64c02c40c9afb18c2cc225af6e56ee1fb9d7328 100644 --- a/frontend/core/src/com/gameware/game/QueryIntermediate.java +++ b/frontend/core/src/com/gameware/game/QueryIntermediate.java @@ -17,12 +17,16 @@ import com.gameware.game.models.Round; import com.gameware.game.models.Tournament; import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.NoSuchElementException; +import java.util.TimeZone; public class QueryIntermediate { @@ -317,4 +321,15 @@ public class QueryIntermediate { return player; } + // ---------------- Model help methods ---------------- + public static Date convertToDate(String UTCDateString) { + TimeZone utc = TimeZone.getTimeZone("UTC"); + SimpleDateFormat sourceFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + sourceFormat.setTimeZone(utc); + try { + return sourceFormat.parse(UTCDateString); + } catch (ParseException e) { + return null; + } + } } diff --git a/frontend/core/src/com/gameware/game/models/Player.java b/frontend/core/src/com/gameware/game/models/Player.java index 9bd149737a1d7fe39967bd392d1125bb4772aa50..08ce14e2b45c1d4eb8f5db5b9c835c8853f6ae6b 100644 --- a/frontend/core/src/com/gameware/game/models/Player.java +++ b/frontend/core/src/com/gameware/game/models/Player.java @@ -1,7 +1,9 @@ package com.gameware.game.models; import com.badlogic.gdx.utils.Json; +import com.gameware.game.QueryIntermediate; +import java.util.Date; import java.util.jar.JarEntry; public class Player implements ModelInterface { @@ -25,6 +27,10 @@ public class Player implements ModelInterface { return name; } + public Date getDateJoined() { + return QueryIntermediate.convertToDate(dateJoined); + } + public void reset() { this._id = null; this.name = null; diff --git a/frontend/core/src/com/gameware/game/models/Round.java b/frontend/core/src/com/gameware/game/models/Round.java index 1d4c543b1fb4aa37a2ebcb66a36a829e6f879c1e..2dfb61857f14e0d7698c2ceb5773ccef8a44fa41 100644 --- a/frontend/core/src/com/gameware/game/models/Round.java +++ b/frontend/core/src/com/gameware/game/models/Round.java @@ -1,6 +1,9 @@ package com.gameware.game.models; import com.badlogic.gdx.utils.Json; +import com.gameware.game.QueryIntermediate; + +import java.util.Date; public class Round implements ModelInterface { private String _id; @@ -26,7 +29,7 @@ public class Round implements ModelInterface { public int getRoundNr() { return roundNr; } - public String getDeadlineDate() { return deadlineDate; } + public Date getDeadlineDate() { return QueryIntermediate.convertToDate(deadlineDate); } public double getScoreValue() { return scoreValue; } diff --git a/frontend/core/src/com/gameware/game/models/Tournament.java b/frontend/core/src/com/gameware/game/models/Tournament.java index f0a9d044b32aa9543bc6aa8494c989e988981e0f..324bd432331f8976ddf80c3543153f64dfcc4d11 100644 --- a/frontend/core/src/com/gameware/game/models/Tournament.java +++ b/frontend/core/src/com/gameware/game/models/Tournament.java @@ -1,6 +1,7 @@ package com.gameware.game.models; import com.badlogic.gdx.utils.Json; +import com.gameware.game.QueryIntermediate; import java.text.DateFormat; import java.text.ParseException; @@ -96,14 +97,22 @@ public class Tournament implements ModelInterface { return currentRound; } - public String getDateCreated() { - return dateCreated; + public Date getDateCreated() { + return QueryIntermediate.convertToDate(dateCreated); } public boolean isActive() { return active; } + public int getTotalGames() { + return totalGames; + } + + public Date getStartTime() { + return QueryIntermediate.convertToDate(startTime); + } + public int getCurrentPlayers() { return currentPlayers; } diff --git a/frontend/core/src/com/gameware/game/sprites/Bubble.java b/frontend/core/src/com/gameware/game/sprites/Bubble.java index d810c562caaecc2e607d89b39ed004ced4ca079a..b73e52ffa1225b41cfcb9a8cd9f0328acff56e6b 100644 --- a/frontend/core/src/com/gameware/game/sprites/Bubble.java +++ b/frontend/core/src/com/gameware/game/sprites/Bubble.java @@ -21,6 +21,7 @@ public class Bubble extends Actor { private boolean textureChanged = false; private int timesTouched; private ArrayList<Texture> poppedTextures; + private Texture unpoppedTex; // Wrapping Texture in Image because Image extends Widget extends Actor, so it can be used in a table private Image bubble; @@ -31,6 +32,8 @@ public class Bubble extends Actor { this.id = id; this.timesTouched = 0; + this.unpoppedTex = unpoppedTex; + bubble = new Image(unpoppedTex); // Add different textures for popped bubbles @@ -91,10 +94,10 @@ public class Bubble extends Actor { } public void reset() { - } - - public Object report() { - return null; + justTouched = false; + textureChanged = false; + timesTouched = 0; + this.bubble.setDrawable(new TextureRegionDrawable(new TextureRegion(this.unpoppedTex))); } public void dispose() { diff --git a/frontend/core/src/com/gameware/game/sprites/ColorRushButton.java b/frontend/core/src/com/gameware/game/sprites/ColorRushButton.java index 0a0f61e4ef1aecde49330a4dcde8d5f73115e1ba..9347f873034145a205a988356e9987825f9c4ede 100644 --- a/frontend/core/src/com/gameware/game/sprites/ColorRushButton.java +++ b/frontend/core/src/com/gameware/game/sprites/ColorRushButton.java @@ -27,12 +27,7 @@ public class ColorRushButton extends Sprite{ @Override public void reset() { - - } - - @Override - public Object report() { - return null; + this.disabled = false; } @Override diff --git a/frontend/core/src/com/gameware/game/sprites/ColorRushTarget.java b/frontend/core/src/com/gameware/game/sprites/ColorRushTarget.java index bc145c639ec89915d806df26c4112f468804694e..b1cea5206afac91aec478cffb0a04c3174aee1c2 100644 --- a/frontend/core/src/com/gameware/game/sprites/ColorRushTarget.java +++ b/frontend/core/src/com/gameware/game/sprites/ColorRushTarget.java @@ -35,11 +35,6 @@ public class ColorRushTarget extends Sprite{ } - @Override - public Object report() { - return null; - } - @Override public void draw(SpriteBatch sb) { sb.begin(); diff --git a/frontend/core/src/com/gameware/game/sprites/LoadingCircle.java b/frontend/core/src/com/gameware/game/sprites/LoadingCircle.java index 48914698cad54fa099bb04c36d56ff418b0a40f5..4be099df3802edf0dc6913d711404092806702bf 100644 --- a/frontend/core/src/com/gameware/game/sprites/LoadingCircle.java +++ b/frontend/core/src/com/gameware/game/sprites/LoadingCircle.java @@ -48,9 +48,4 @@ public class LoadingCircle extends Sprite { public void reset() { } - - @Override - public Object report() { - return null; - } } diff --git a/frontend/core/src/com/gameware/game/sprites/PauseButton.java b/frontend/core/src/com/gameware/game/sprites/PauseButton.java index fd3faf33b222c5ef8e44eb34a977603eca0d39b5..13936591e8af1866c3761c87afd3c57fa56d885f 100644 --- a/frontend/core/src/com/gameware/game/sprites/PauseButton.java +++ b/frontend/core/src/com/gameware/game/sprites/PauseButton.java @@ -38,11 +38,6 @@ public class PauseButton extends Sprite { } - @Override - public Object report() { - return null; - } - @Override public void draw(SpriteBatch sb) { sb.begin(); diff --git a/frontend/core/src/com/gameware/game/sprites/PauseCircle.java b/frontend/core/src/com/gameware/game/sprites/PauseCircle.java index b175ea638fc2587bc02a475ebd35b149ef25cc22..2bd78d9df4ef1425f3efcb29aaa42c3a439ed45a 100644 --- a/frontend/core/src/com/gameware/game/sprites/PauseCircle.java +++ b/frontend/core/src/com/gameware/game/sprites/PauseCircle.java @@ -32,11 +32,6 @@ public class PauseCircle extends Sprite { } - @Override - public Object report() { - return null; - } - @Override public void draw(SpriteBatch sb) { this.sr.begin(ShapeRenderer.ShapeType.Filled); diff --git a/frontend/core/src/com/gameware/game/sprites/Sprite.java b/frontend/core/src/com/gameware/game/sprites/Sprite.java index 4241dbd66df13a59e51e47999f400b2ce9796d2f..ce9583421d33fcf1dc5eb90b3f3192ab4b958524 100644 --- a/frontend/core/src/com/gameware/game/sprites/Sprite.java +++ b/frontend/core/src/com/gameware/game/sprites/Sprite.java @@ -11,7 +11,6 @@ public abstract class Sprite { protected Object bounds; public abstract void reset(); - public abstract Object report(); public abstract void draw(SpriteBatch sb); public abstract void update(float dt); diff --git a/frontend/core/src/com/gameware/game/states/BubbleWrapState.java b/frontend/core/src/com/gameware/game/states/BubbleWrapState.java index 1bfc7795194db62996a22cf80f516d7204522d0d..c6e5a1c0f967a9086319c3463ae192f366bab46f 100644 --- a/frontend/core/src/com/gameware/game/states/BubbleWrapState.java +++ b/frontend/core/src/com/gameware/game/states/BubbleWrapState.java @@ -161,11 +161,10 @@ public class BubbleWrapState extends PlayStateTemplate { @Override public void reset() { - + this.poppedBubbles = 0; + this.currentTime = 0f; + createBubbles(); + createBubbleWrapLayout(); } - @Override - public Object report() { - return null; - } } diff --git a/frontend/core/src/com/gameware/game/states/ColorRushState.java b/frontend/core/src/com/gameware/game/states/ColorRushState.java index cd6627ccd082ca91ecc38ee0d4933cf5c8fc8e6d..4e205b2c7be0e3710dc925785ead99eeba714644 100644 --- a/frontend/core/src/com/gameware/game/states/ColorRushState.java +++ b/frontend/core/src/com/gameware/game/states/ColorRushState.java @@ -221,15 +221,46 @@ public class ColorRushState extends PlayStateTemplate { @Override public void reset() { + this.disabledDuration = 0f; + this.currentDuration = 0f; + this.setScore(0); + this.targetsHit = 0; + this.activeTargets.clear(); + this.previousTargets.clear(); + + //If the game is reset when the buttons are disabled, they are also reset + this.disabledDuration = 0f; + this.buttonsEnabled = true; + for(ColorRushButton button : this.buttons){ + button.setEnabledColor(); + } - } + int targetWidth = Gdx.graphics.getWidth()/8; + int targetHeight = Gdx.graphics.getWidth()/8; + int targetX = Gdx.graphics.getWidth()/2 - targetWidth/2; + int targetY = Gdx.graphics.getHeight()/3; + int prevColor = -1; + int targetAmount = 7; - @Override - public Object report() { - return null; + // Creates the targets + for(int i = 0; i<targetAmount; i++){ + int color = (int) (Math.floor(Math.random()*this.colorTextures.size())); + + // No repeating colors + while(prevColor == color){ + color = (int) (Math.floor(Math.random()*this.colorTextures.size())); + } + + prevColor = color; + + activeTargets.add(new ColorRushTarget(targetX, targetY, targetWidth, targetHeight, this.colorTextures.get(color), color, this.disposeTargetLeft)); + this.disposeTargetLeft = !this.disposeTargetLeft; + targetY += targetHeight; + } } + public void colorChanged(int color){ // If the user pressed the correct button diff --git a/frontend/core/src/com/gameware/game/states/CreateJoinTournamentState.java b/frontend/core/src/com/gameware/game/states/CreateJoinTournamentState.java index 2e44cfd0803c9fb49ccf5dc90716806f6020fa11..f917f99c223e94fd16bdbf4582b17bd2d5a3b6c0 100644 --- a/frontend/core/src/com/gameware/game/states/CreateJoinTournamentState.java +++ b/frontend/core/src/com/gameware/game/states/CreateJoinTournamentState.java @@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.ui.Dialog; import com.badlogic.gdx.scenes.scene2d.ui.CheckBox; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; @@ -19,6 +20,7 @@ import com.gameware.game.QueryIntermediate; import com.gameware.game.models.Round; import com.gameware.game.models.Tournament; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -27,10 +29,12 @@ public class CreateJoinTournamentState extends State { private Table outerTable; private Table innerTable; private ScrollPane tournamentsPane; + private Dialog dialog; private Label gameNameText = new Label("Multiplayer", skin, "big"); private Label stateTitleText = new Label("Currently playing", skin, "big"); - private Label joinTournamentFeedbackLabel = new Label("", skin); + private CheckBox includeCheckBox; + public Label tournamentFeedbackLabel = new Label("", skin); private String backBtnText = "Back"; private String createBtnText = "Create new"; @@ -43,11 +47,15 @@ public class CreateJoinTournamentState extends State { private String isFinishedText = "Finished"; private String noAvailableTournamentsText = "No available tournaments"; private String joinedText = "Joined "; + public String leftTournamentText = "Left "; + + private List<Tournament> tournaments = new ArrayList<>(); + private Tournament tournamentTryingToLeave = null; + private int padding = 50; private String includeFinTournamentsLabelText = "Include finished \n tournaments?"; private boolean includeFinishedTournaments = false; - private List<Tournament> tournaments = new ArrayList<>(); private List<Tournament> finTournaments = new ArrayList<>(); public class EnterClickListener extends ClickListener{ @@ -78,6 +86,10 @@ public class CreateJoinTournamentState extends State { public CreateJoinTournamentState(GameStateManager gsm) { super(gsm); + + + includeFinishedTournaments = GameWare.getInstance().getIncludeFin(); + try{ tournaments = QueryIntermediate.getTournamentsForPlayer(GameWare.getInstance().getPlayer().getId(),true); finTournaments = QueryIntermediate.getTournamentsForPlayer(GameWare.getInstance().getPlayer().getId(),false); @@ -113,11 +125,13 @@ public class CreateJoinTournamentState extends State { outerTable.add(tournamentsPane).spaceBottom(spacingOnBottom); outerTable.getCell(tournamentsPane).size(Gdx.graphics.getWidth()/1.1f, Gdx.graphics.getHeight()/4f); outerTable.row(); - outerTable.add(joinTournamentFeedbackLabel).spaceBottom(spacingOnBottom);; + outerTable.add(tournamentFeedbackLabel).spaceBottom(spacingOnBottom);; outerTable.row(); Table btnTable = new Table(); btnTable.add(new Label(includeFinTournamentsLabelText,skin,"big")).spaceBottom(spacingOnBottom); - btnTable.add(makeIncludeCheckbox()).spaceBottom(spacingOnBottom); + includeCheckBox = makeIncludeCheckbox(); + btnTable.add(includeCheckBox).spaceBottom(spacingOnBottom); + btnTable.row(); btnTable.add(makeCreateBtn()).size(buttonWidth, buttonHeight).spaceBottom(spacingOnBottomInputFIeld).spaceRight(spacingOnBottom); btnTable.add(makeJoinBtn()).size(buttonWidth, buttonHeight).spaceBottom(spacingOnBottomInputFIeld); @@ -126,6 +140,34 @@ public class CreateJoinTournamentState extends State { outerTable.add(btnTable); stage.addActor(outerTable); + + makeDialog(); + } + + private void makeDialog(){ + dialog = new Dialog("", skin, "dialog") { + public void result(Object obj) { + if(obj.equals(true)){ + tournaments.remove(tournamentTryingToLeave); + try { + QueryIntermediate.leaveTournament(tournamentTryingToLeave.get_id(), GameWare.getInstance().getPlayer().getId()); + + //Fjerner alt og legger til alt igjen, aka dårlig måte å gjøre på men fant ingen annen måte + outerTable.remove(); + makeStage(); + tournamentFeedbackLabel.setText(leftTournamentText+tournamentTryingToLeave.getName()); + } catch(Exception e){ + System.out.println(e); + } + } else{ + makeDialog(); + } + + } + }; + dialog.text(""); + dialog.button("Yes", true).pad(padding); //sends "true" as the result + dialog.button("No", false).pad(padding); //sends "false" as the result } private void createTournamentList(){ @@ -219,6 +261,7 @@ public class CreateJoinTournamentState extends State { @Override public void clicked(InputEvent e, float x, float y){ includeFinishedTournaments = !includeFinishedTournaments; + GameWare.getInstance().setIncludeFin(includeFinishedTournaments); stage.clear(); makeStage(); } @@ -248,34 +291,38 @@ public class CreateJoinTournamentState extends State { } @Override - public void reset() { } - - @Override - public Object report() { - return this; + public void reset() { + tournaments.clear(); + finTournaments.clear(); + includeCheckBox.setChecked(false); + try { + tournaments = QueryIntermediate.getTournamentsForPlayer(GameWare.getInstance().getPlayer().getId(),true); + finTournaments = QueryIntermediate.getTournamentsForPlayer(GameWare.getInstance().getPlayer().getId(),false); + } catch (IOException e) { + e.printStackTrace(); + } + makeStage(); } + private void handleBackBtnClick(){ gsm.set(new MenuState(gsm)); } private void handleEnterBtnClick(Tournament t, Round r){ System.out.println("Entered tournament with id = "+ t.get_id()); - gsm.set(new ViewTournamentState(gsm, t, r)); + if(!t.isActive()){ + gsm.set(new FinishedTournamentState(gsm,t)); + } + else{ + gsm.set(new ViewTournamentState(gsm, t, r)); + } } private void handleLeaveBtnClick(Tournament t){ - System.out.println("Left tournament with id = "+ t.get_id()); - tournaments.remove(t); - try { - QueryIntermediate.leaveTournament(t.get_id(), GameWare.getInstance().getPlayer().getId()); - - //Fjerner alt og legger til alt igjen, aka dårlig måte å gjøre på men fant ingen annen måte - outerTable.remove(); - makeStage(); - } catch(Exception e){ - System.out.println(e); - } + dialog.text("Do you want do leave\n"+t.getName()+"?").pad(padding); + dialog.show(stage); + tournamentTryingToLeave = t; } private void handleCreateBtnClick(){ @@ -287,14 +334,14 @@ public class CreateJoinTournamentState extends State { Tournament newT = QueryIntermediate.joinATournament(GameWare.getInstance().getPlayer().getId()); tournaments.add(newT); - joinTournamentFeedbackLabel.setText(joinedText+newT.getName()); + tournamentFeedbackLabel.setText(joinedText+newT.getName()); //Fjerner alt og legger til alt igjen, aka dårlig måte å gjøre på men fant ingen annen måte outerTable.remove(); makeStage(); }catch(Exception e){ System.out.println(e); - joinTournamentFeedbackLabel.setText(noAvailableTournamentsText); + tournamentFeedbackLabel.setText(noAvailableTournamentsText); } }; diff --git a/frontend/core/src/com/gameware/game/states/CreateNewTournamentState.java b/frontend/core/src/com/gameware/game/states/CreateNewTournamentState.java index 4f445a7eb565135866814ba302f5af2ad3762b80..d6495deb3d0d4a5d2097b31faf3827be7aec56e2 100644 --- a/frontend/core/src/com/gameware/game/states/CreateNewTournamentState.java +++ b/frontend/core/src/com/gameware/game/states/CreateNewTournamentState.java @@ -36,6 +36,7 @@ public class CreateNewTournamentState extends State { private String startDelayText = "Hours waiting for more \n players before start"; private SelectBox startDelaySelectBox; private Label errorLabel = new Label("", skin, "error"); + private ArrayList<CheckBox> checkBoxes = new ArrayList<>(); private List<Game> games; @@ -116,6 +117,7 @@ public class CreateNewTournamentState extends State { } }); gameCB.getImage().setScale(2,2); + checkBoxes.add(gameCB); table.add(gameCB).spaceBottom(spacingOnBottom); table.row(); } @@ -181,13 +183,17 @@ public class CreateNewTournamentState extends State { public void reset() { errorLabel.setText(""); nameInputField.setText(""); - } + timePerRoundSelectBox.setSelected(1); + maxPlayersSelectBox.setSelected(2); + roundsPerGameSelectBox.setSelected(1); + startDelaySelectBox.setSelected(1); + for(CheckBox cb : checkBoxes){ + cb.setChecked(false); + } - @Override - public Object report() { - return this; } + private void handleCancelBtnClick() { gsm.set(new CreateJoinTournamentState(gsm)); } diff --git a/frontend/core/src/com/gameware/game/states/FinishedTournamentState.java b/frontend/core/src/com/gameware/game/states/FinishedTournamentState.java new file mode 100644 index 0000000000000000000000000000000000000000..12cd600498330899e2378a2f1f54e91b00db119a --- /dev/null +++ b/frontend/core/src/com/gameware/game/states/FinishedTournamentState.java @@ -0,0 +1,175 @@ +package com.gameware.game.states; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.ui.Dialog; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.gameware.game.GameWare; +import com.gameware.game.QueryIntermediate; +import com.gameware.game.models.Point; +import com.gameware.game.models.Round; +import com.gameware.game.models.Tournament; + +import java.util.ArrayList; +import java.util.List; + +public class FinishedTournamentState extends State { + + private Table table; + private Table hsTable; + private Table btnTable; + private ScrollPane scrollPane; + private Tournament tournament; + private Dialog dialog; + + private int padding = 50; + + private Label tournamentNameText; + private String backBtnText = "Back"; + private String leaveBtnText = "Leave"; + private String finishedText = "Final results"; + private String winnerName; + + private String colOneText = "Player"; + private String colTwoText = "Total"; + private List<Point> points = new ArrayList<>(); + + public class LeaveClickListener extends ClickListener{ + public void clicked(InputEvent event, float x, float y) { + handleLeaveBtnClick(); + }; + } + + public FinishedTournamentState(GameStateManager gsm, Tournament tournament) { + super(gsm); + this.tournament = tournament; + tournamentNameText = new Label(tournament.getName(), skin, "big"); + try { + points = QueryIntermediate.getTournamentPoints(tournament.get_id()); + }catch(Exception e){ + System.out.println(e); + } + makeStage(); + } + + + private void makeStage(){ + table = new Table(); + table.setFillParent(true); + table.setBackground(backgroundFinTourn); + tournamentNameText.setFontScale(tinierTitleFontBigScale); + + table.add(tournamentNameText).spaceBottom(spacingOnBottomInputFIeld); + table.row(); + table.add(new Label(finishedText,skin,"big")).spaceBottom(spacingOnBottomInputFIeld); + table.row(); + + hsTable = new Table(); + Pixmap bgPixmap = new Pixmap(1,1, Pixmap.Format.RGB565); + bgPixmap.setColor(Color.GOLD); + bgPixmap.fill(); + TextureRegionDrawable textureRegionDrawableBg = new TextureRegionDrawable(new TextureRegion(new Texture(bgPixmap))); + hsTable.setBackground(textureRegionDrawableBg); + + hsTable.setFillParent(true); + hsTable.add(new Label(colOneText, skin)); + hsTable.add(new Label(colTwoText, skin)).spaceRight(spacingOnBottom); + hsTable.row(); + for(Point point : points){ + hsTable.add(new Label(point.getName(), skin)); + hsTable.add(new Label(point.getTotalPoints()+"", skin)); + hsTable.row(); + } + scrollPane = new ScrollPane(hsTable, skin); + table.add(scrollPane).spaceBottom(spacingOnBottomInputFIeld).spaceBottom(spacingOnBottomInputFIeld); + table.row(); + winnerName = points.get(0).getName(); + table.add(new Label("Winner: "+winnerName,skin,"big")).spaceBottom(spacingOnBottom); + table.row(); + + btnTable = new Table(); + TextButton leaveBtn = new TextButton(leaveBtnText, skin); + leaveBtn.addListener(new LeaveClickListener()); + btnTable.add(leaveBtn).spaceBottom(spacingOnBottomInputFIeld).spaceRight(spacingOnBottom); + btnTable.add(makeBackBtn()); + table.add(btnTable); + + stage.addActor(table); + + makeDialog(); + } + + private void makeDialog(){ + dialog = new Dialog("", skin, "dialog") { + public void result(Object obj) { + if(obj.equals(true)){ + try { + QueryIntermediate.leaveTournament(tournament.get_id(), GameWare.getInstance().getPlayer().getId()); + CreateJoinTournamentState state = new CreateJoinTournamentState(gsm); + state.tournamentFeedbackLabel.setText(state.leftTournamentText+tournament.getName()); + gsm.set(state); + } catch(Exception e){ + System.out.println(e); + } + } else{ + makeDialog(); + } + + } + }; + dialog.text("Do you want do leave\n"+tournament.getName()+"?").pad(padding); + dialog.button("Yes", true).pad(padding); //sends "true" as the result + dialog.button("No", false).pad(padding); //sends "false" as the result + } + + private TextButton makeBackBtn(){ + TextButton backBtn = new TextButton(backBtnText, skin); + backBtn.addListener(new ClickListener() { + @Override + public void clicked(InputEvent e, float x, float y){ + handleBackBtnClick(); + } + }); + return backBtn; + } + + @Override + protected void handleInput() { } + + @Override + public void update(float dt) { + Gdx.input.setInputProcessor(stage); + stage.act(dt); + } + + @Override + public void render(SpriteBatch sb) { + stage.draw(); + } + + @Override + public void dispose() { + stage.dispose(); + } + + @Override + public void reset() { } + + private void handleBackBtnClick(){ + gsm.set(new CreateJoinTournamentState(gsm)); + } + + private void handleLeaveBtnClick(){ + dialog.show(stage); + } +} diff --git a/frontend/core/src/com/gameware/game/states/GameStateManager.java b/frontend/core/src/com/gameware/game/states/GameStateManager.java index 420e7306fef9dc1c56a69ca5dc83ae273b90279f..6c56681cc0c6a89870789a58b82b2743d6bba9a6 100644 --- a/frontend/core/src/com/gameware/game/states/GameStateManager.java +++ b/frontend/core/src/com/gameware/game/states/GameStateManager.java @@ -47,9 +47,13 @@ public class GameStateManager { } public Object report(){ - //Don't know what this method should do... - return this; + return states; + } + public void reset(){ + for(int i = 0; i < states.size(); i++){ + states.pop(); + } } } diff --git a/frontend/core/src/com/gameware/game/states/LoginState.java b/frontend/core/src/com/gameware/game/states/LoginState.java index 7b8b9caf29e40e232162d02d3c359a373d4a21b8..fa9804c7766882f1f87db93da343dd5309605f9d 100644 --- a/frontend/core/src/com/gameware/game/states/LoginState.java +++ b/frontend/core/src/com/gameware/game/states/LoginState.java @@ -1,9 +1,11 @@ package com.gameware.game.states; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.InputListener; +import com.badlogic.gdx.scenes.scene2d.ui.Dialog; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; @@ -39,7 +41,6 @@ public class LoginState extends State { private String takenUsernameText = "Username already taken"; private String ioExceptionText = "Something went wrong with query"; - public LoginState(GameStateManager gsm) { super(gsm); makeStage(); @@ -56,6 +57,8 @@ public class LoginState extends State { } } }); + + usernameInputField.setFocusTraversal(false); return usernameInputField; } @@ -158,12 +161,6 @@ public class LoginState extends State { passwordInputField.setText(passwordInputText); } - @Override - public Object report() { - return this; - } - - private void handleLoginBtnClick(){ String username = usernameInputField.getText(); String password = passwordInputField.getText(); diff --git a/frontend/core/src/com/gameware/game/states/MenuState.java b/frontend/core/src/com/gameware/game/states/MenuState.java index f32ba69d41de088108cda6e748fb4e946fc1601a..4a53d254c75b98f7acabd8104e18f22dc8c932c2 100644 --- a/frontend/core/src/com/gameware/game/states/MenuState.java +++ b/frontend/core/src/com/gameware/game/states/MenuState.java @@ -118,9 +118,6 @@ public class MenuState extends State{ @Override public void reset() { } - @Override - public Object report() { return this; } - private void handleOptionsBtnClick(){ gsm.set(new OptionsState(gsm)); } diff --git a/frontend/core/src/com/gameware/game/states/OptionsState.java b/frontend/core/src/com/gameware/game/states/OptionsState.java index 699f575dea22a45624ff8669491973c99d9a3cc6..c1f4d76e6e62bfb29a9526fcfee3dce756bd0420 100644 --- a/frontend/core/src/com/gameware/game/states/OptionsState.java +++ b/frontend/core/src/com/gameware/game/states/OptionsState.java @@ -65,11 +65,6 @@ public class OptionsState extends State { } } - @Override - public Object report() { - return this; - } - private void makeStage(){ table = new Table(); table.setFillParent(true); diff --git a/frontend/core/src/com/gameware/game/states/PauseState.java b/frontend/core/src/com/gameware/game/states/PauseState.java index 3a168203804252681ac505df7980ae289feee8bd..4ef33b946354ba3d903c1fbd72accfc39fa053e4 100644 --- a/frontend/core/src/com/gameware/game/states/PauseState.java +++ b/frontend/core/src/com/gameware/game/states/PauseState.java @@ -91,9 +91,4 @@ public class PauseState extends State { public void reset() { } - - @Override - public Object report() { - return null; - } } diff --git a/frontend/core/src/com/gameware/game/states/PlayStateTemplate.java b/frontend/core/src/com/gameware/game/states/PlayStateTemplate.java index 87e2d4aaa8e91974bbf1fe465ced24a0e76fb1b1..9bdb537deff383c0d2008fd15c460cb0b2a915d1 100644 --- a/frontend/core/src/com/gameware/game/states/PlayStateTemplate.java +++ b/frontend/core/src/com/gameware/game/states/PlayStateTemplate.java @@ -45,9 +45,9 @@ public abstract class PlayStateTemplate extends State { if(round == null) { gsm.set(new ScoreState(gsm, this.score, new SinglePlayerSelectGameState(gsm))); } else{ - //TODO: nextRound blir null :/ -// gsm.set(new ScoreState(gsm, this.score, new ViewTournamentState(gsm, tournament, nextRound))); - gsm.set(new ScoreState(gsm, this.score, new CreateJoinTournamentState(gsm))); +// TODO: change when backend gives updated round object + gsm.set(new ScoreState(gsm, this.score, new ViewTournamentState(gsm, tournament, nextRound))); +// gsm.set(new ScoreState(gsm, this.score, new CreateJoinTournamentState(gsm))); } } diff --git a/frontend/core/src/com/gameware/game/states/ScoreState.java b/frontend/core/src/com/gameware/game/states/ScoreState.java index b21c9c483637c86e182246504528df30b7378624..571f2aa387d1a1c7a481a7eb399059718896b1f5 100644 --- a/frontend/core/src/com/gameware/game/states/ScoreState.java +++ b/frontend/core/src/com/gameware/game/states/ScoreState.java @@ -77,9 +77,4 @@ public class ScoreState extends State { public void reset() { } - - @Override - public Object report() { - return null; - } } diff --git a/frontend/core/src/com/gameware/game/states/SinglePlayerSelectGameState.java b/frontend/core/src/com/gameware/game/states/SinglePlayerSelectGameState.java index 069561e5e43921bb76805f9e7d2512e40e883529..414bd67f73ccd67a89e0a7ea9285fb891d2fb788 100644 --- a/frontend/core/src/com/gameware/game/states/SinglePlayerSelectGameState.java +++ b/frontend/core/src/com/gameware/game/states/SinglePlayerSelectGameState.java @@ -76,11 +76,6 @@ public class SinglePlayerSelectGameState extends State { } - @Override - public Object report() { - return this; - } - private TextButton makeBackBtn(){ TextButton backBtn = new TextButton(backBtnText, skin); backBtn.addListener(new ClickListener() { diff --git a/frontend/core/src/com/gameware/game/states/State.java b/frontend/core/src/com/gameware/game/states/State.java index e69776549c02902e81784813d40a73c5e59eb82f..4ac47b3576e71bd5592e6b1376f458852af5f731 100644 --- a/frontend/core/src/com/gameware/game/states/State.java +++ b/frontend/core/src/com/gameware/game/states/State.java @@ -27,6 +27,7 @@ public abstract class State { protected TextureRegionDrawable background = new TextureRegionDrawable(new TextureRegion(new Texture("bg1.jpg"))); protected TextureRegionDrawable backgroundLighter = new TextureRegionDrawable(new TextureRegion(new Texture("bg1_lighter.jpg"))); protected TextureRegionDrawable backgroundScore = new TextureRegionDrawable(new TextureRegion(new Texture("bg_score.jpg"))); + protected TextureRegionDrawable backgroundFinTourn = new TextureRegionDrawable(new TextureRegion(new Texture("bg1_finTourn.jpg"))); protected State(GameStateManager gsm){ this.gsm = gsm; @@ -44,6 +45,5 @@ public abstract class State { public abstract void render(SpriteBatch sb); public abstract void dispose(); public abstract void reset(); - public abstract Object report(); } diff --git a/frontend/core/src/com/gameware/game/states/TournamentHighScoreState.java b/frontend/core/src/com/gameware/game/states/TournamentHighScoreState.java index c28cec58892c8a4d1c6617bac370fd047b9161fe..a3332125d0a31faccdd4ffca95bbbdc16330d87d 100644 --- a/frontend/core/src/com/gameware/game/states/TournamentHighScoreState.java +++ b/frontend/core/src/com/gameware/game/states/TournamentHighScoreState.java @@ -125,9 +125,4 @@ public class TournamentHighScoreState extends State{ @Override public void reset() { } - - @Override - public Object report() { - return null; - } } diff --git a/frontend/core/src/com/gameware/game/states/ViewHighScoreForGameState.java b/frontend/core/src/com/gameware/game/states/ViewHighScoreForGameState.java index 740b52ea43b24f49b9c421df167abcbbd9b2faaf..cf8617a8952cca42b68d9393f167007239dbb6a9 100644 --- a/frontend/core/src/com/gameware/game/states/ViewHighScoreForGameState.java +++ b/frontend/core/src/com/gameware/game/states/ViewHighScoreForGameState.java @@ -79,11 +79,6 @@ public class ViewHighScoreForGameState extends State { } - @Override - public Object report() { - return this; - } - private TextButton makeBackBtn(){ TextButton backBtn = new TextButton(backBtnText, skin); backBtn.addListener(new ClickListener() { diff --git a/frontend/core/src/com/gameware/game/states/ViewHighScoreState.java b/frontend/core/src/com/gameware/game/states/ViewHighScoreState.java index 7c9c9e0a8cd36ca323746a3402031201b4ddb0b2..1581ab299d45bd28f4ad0a4df81af07ca4f27c72 100644 --- a/frontend/core/src/com/gameware/game/states/ViewHighScoreState.java +++ b/frontend/core/src/com/gameware/game/states/ViewHighScoreState.java @@ -74,11 +74,6 @@ public class ViewHighScoreState extends State { } - @Override - public Object report() { - return this; - } - private TextButton makeBackBtn(){ TextButton backBtn = new TextButton(backBtnText, skin); backBtn.addListener(new ClickListener() { diff --git a/frontend/core/src/com/gameware/game/states/ViewTournamentState.java b/frontend/core/src/com/gameware/game/states/ViewTournamentState.java index 76392f3bf5eaf3d46872c1016d95719eb0bebf96..dd9814c1194909e628f9f701017ce4217a942b31 100644 --- a/frontend/core/src/com/gameware/game/states/ViewTournamentState.java +++ b/frontend/core/src/com/gameware/game/states/ViewTournamentState.java @@ -3,6 +3,7 @@ package com.gameware.game.states; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.ui.Dialog; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; @@ -17,6 +18,9 @@ public class ViewTournamentState extends State { private Table table; private Tournament tournament; private Round round; + private Dialog dialog; + + private int padding = 50; private Label stateNameText; private String backBtnText = "Back"; @@ -27,14 +31,10 @@ public class ViewTournamentState extends State { private String roundsLeftText = "Rounds left"; public class LeaveClickListener extends ClickListener{ - private Tournament tournament; - - public LeaveClickListener(Tournament tournament){ - this.tournament = tournament; - } + //TODO: if (tournamentpoints != null && currentRoundNr == (tournament.totalGames) -> gå til finished state public void clicked(InputEvent event, float x, float y) { - handleLeaveBtnClick(tournament); + handleLeaveBtnClick(); }; } @@ -68,7 +68,7 @@ public class ViewTournamentState extends State { Table innerTable = new Table(); TextButton leaveBtn = new TextButton(leaveBtnText, skin); - leaveBtn.addListener(new LeaveClickListener(tournament)); + leaveBtn.addListener(new LeaveClickListener()); innerTable.add(leaveBtn).size(buttonWidth, buttonHeight).spaceBottom(spacingOnBottomInputFIeld).spaceRight(spacingOnBottom); innerTable.add(makeViewPointsBtn()).size(buttonWidth, buttonHeight).spaceBottom(spacingOnBottomInputFIeld); innerTable.row(); @@ -76,6 +76,31 @@ public class ViewTournamentState extends State { table.add(innerTable); stage.addActor(table); + + makeDialog(); + } + + private void makeDialog(){ + dialog = new Dialog("", skin, "dialog") { + public void result(Object obj) { + if(obj.equals(true)){ + try { + QueryIntermediate.leaveTournament(tournament.get_id(), GameWare.getInstance().getPlayer().getId()); + CreateJoinTournamentState state = new CreateJoinTournamentState(gsm); + state.tournamentFeedbackLabel.setText(state.leftTournamentText+tournament.getName()); + gsm.set(state); + } catch(Exception e){ + System.out.println(e); + } + } else{ + makeDialog(); + } + + } + }; + dialog.text("Do you want do leave\n"+tournament.getName()+"?").pad(padding); + dialog.button("Yes", true).pad(padding); //sends "true" as the result + dialog.button("No", false).pad(padding); //sends "false" as the result } private TextButton makeBackBtn(){ @@ -136,11 +161,6 @@ public class ViewTournamentState extends State { @Override public void reset() { } - @Override - public Object report() { - return this; - } - private void handleBackBtnClick(){ gsm.set(new CreateJoinTournamentState(gsm)); } @@ -156,12 +176,7 @@ public class ViewTournamentState extends State { gsm.set(new TournamentHighScoreState(gsm, tournament, round)); } - private void handleLeaveBtnClick(Tournament t){ - try { - QueryIntermediate.leaveTournament(t.get_id(), GameWare.getInstance().getPlayer().getId()); - gsm.set(new CreateJoinTournamentState(gsm)); - } catch(Exception e){ - System.out.println(e); - } + private void handleLeaveBtnClick(){ + dialog.show(stage); } }