diff --git a/backend/api/functions.js b/backend/api/functions.js
new file mode 100644
index 0000000000000000000000000000000000000000..6cf642b16257060fc8c04068b6fde475201c2b01
--- /dev/null
+++ b/backend/api/functions.js
@@ -0,0 +1,262 @@
+const mongo = require("mongodb");
+
+module.exports = {
+  notifyPlayers: function (client, players, timeout, tournament) {
+    const objects = [];
+    return new Promise((resolve, reject) => {
+      const db = client.db("gameWare");
+      if (players.length == 0) {
+        resolve();
+      }
+      for (let i = 0; i < players.length; i++) {
+        objects.push({
+          playerId: mongo.ObjectID(players[i]),
+          tournamentId: tournament,
+          timeout: timeout,
+        });
+      }
+      // Get the collection and bulk api artefacts
+      var collection = db.collection("alerts"),
+        bulkUpdateOps = [];
+
+      objects.forEach(function (doc) {
+        bulkUpdateOps.push({ insertOne: { document: doc } });
+      });
+
+      if (bulkUpdateOps.length > 0) {
+        collection.bulkWrite(bulkUpdateOps).then(function (r) {
+          resolve();
+        });
+      }
+    });
+  },
+
+  endTournament: function (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;
+          }
+          resolve(result);
+          return;
+        }
+      );
+    });
+  },
+
+  timeOut: function (client, tournament, players, end, rounds) {
+    if (!players) {
+      players = [];
+    }
+    return new Promise((resolve, reject) => {
+      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) {
+            resolve(500); // Internal server error
+            return;
+          }
+          db.collection("rounds").deleteMany(
+            {
+              _id: { $in: rounds },
+            },
+            (err, result) => {
+              if (err) {
+                resolve(500); // Internal server error
+                return;
+              }
+              resolve(result);
+              return;
+            }
+          );
+        }
+      );
+    });
+  },
+
+  getCurrentRound: function (client, tournamentId) {
+    return new Promise((resolve, reject) => {
+      const db = client.db("gameWare");
+      const collection = "tournaments";
+
+      db.collection(collection).findOne(
+        {
+          _id: tournamentId,
+        },
+        { currentRound: 1, startTime: 1, maxPlayers: 1, currentPlayers: 1 },
+        (err, result) => {
+          if (err) {
+            resolve(500); // Internal server error
+            return;
+          }
+          resolve(result);
+          return;
+        }
+      );
+    });
+  },
+
+  newRound: function (
+    client,
+    tournamentId,
+    players,
+    gameId,
+    roundNr,
+    deadlineDate
+  ) {
+    return new Promise((resolve, reject) => {
+      // Using the database gameWare and collection rounds
+      const db = client.db("gameWare");
+      const collection = db.collection("rounds");
+      let objects = [];
+
+      for (let i = 0; i < players.length; i++) {
+        objects.push({
+          tournamentId: mongo.ObjectID(tournamentId),
+          playerId: mongo.ObjectID(players[i]),
+          gameId: mongo.ObjectID(gameId),
+          roundNr: roundNr,
+          deadlineDate: deadlineDate,
+          scoreValue: 0,
+          hasPlayed: false,
+          tournamentPoints: 0,
+        });
+      }
+
+      let bulkUpdateOps = [];
+
+      objects.forEach(function (doc) {
+        bulkUpdateOps.push({ insertOne: { document: doc } });
+      });
+
+      if (bulkUpdateOps.length > 0) {
+        collection.bulkWrite(bulkUpdateOps).then(function (r) {
+          resolve();
+        });
+      }
+    });
+  },
+
+  updateTournamentRound: function (client, tournament) {
+    return new Promise((resolve, reject) => {
+      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);
+        });
+    });
+  },
+
+  checkRounds: function (result, start, max, roundNr, current) {
+    return new Promise((resolve, reject) => {
+      let timedOut = [];
+      let timedOutRounds = [];
+      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);
+          timedOutRounds.push(result[i]._id);
+        } else {
+          left.push(result[i].playerId);
+        }
+      }
+      if (amountComplete == max) {
+        // All players have completed their round
+        resolve([true, [], left, []]);
+      } else if (amountComplete == current && roundNr > 1) {
+        // 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, timedOutRounds]);
+      } else if (
+        amountComplete + timedOut.length == current &&
+        amountComplete >= 2 &&
+        roundNr > 1
+      ) {
+        // More than two players have completed round and all players have either completed their round or timed out.
+        resolve([true, timedOut, left, timedOutRounds]);
+      } else {
+        resolve([false, timedOut, left, timedOutRounds]);
+      }
+    });
+  },
+
+  fetchRounds: function (client, tournamentId, activeRound) {
+    return new Promise((resolve, reject) => {
+      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);
+        });
+    });
+  },
+
+  updateScore: function (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/rounds.js b/backend/api/rounds.js
index ef1a00cd99a81d3b098e49ff51b3545678d7cf21..6f6069e0b279c62d34736da67310846b18ff8587 100644
--- a/backend/api/rounds.js
+++ b/backend/api/rounds.js
@@ -3,6 +3,7 @@ const router = express.Router();
 const mongo = require("mongodb");
 const MongoClient = mongo.MongoClient;
 const connectionUrl = process.env.MONGO_CONNECTION_STRING;
+const functions = require("./functions");
 
 router.get("/round/:roundId", (req, res) => {
   // Connect to database
@@ -432,17 +433,17 @@ router.put("/:roundid/:tournamentid", (req, res) => {
 
 function roundcheck(client, tournament, roundid) {
   return new Promise((resolve, reject) => {
-    getCurrentRound(client, tournament).then((roundResult) => {
+    functions.getCurrentRound(client, tournament).then((roundResult) => {
       // gets the current round of the tournament
       if (roundResult == 500) {
         resolve(500);
-        return;
       }
       const active = roundResult.currentRound;
       const start = roundResult.startTime;
       const maxPlayers = roundResult.maxPlayers;
+      const currentPlayers = roundResult.currentPlayers;
 
-      fetchRounds(client, tournament, active).then((rounds) => {
+      functions.fetchRounds(client, tournament, active).then((rounds) => {
         // fetched the round objects of the active round
         let activePlayer;
         for (let i = 0; i < rounds.length; i++) {
@@ -451,132 +452,156 @@ function roundcheck(client, tournament, roundid) {
             break;
           }
         }
-        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 timedOutRounds = resultarray[3];
-          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
-          }
+        functions
+          .checkRounds(rounds, start, maxPlayers, active, currentPlayers)
+          .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 timedOutRounds = resultarray[3];
+            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, timedOutRounds).then(
-            //updates the state of the tournament and ends it if necessary
-            (timeoutresult) => {
-              notifyPlayers(client, timedOut, true, tournament);
-              const indeks = left.indexOf(activePlayer);
-              left.splice(indeks, 1);
-              if (end) {
-                notifyPlayers(client, left, false, tournament);
-                endTournament(client, tournament);
-                getRound(client, roundid).then((round) => {
-                  resolve({
-                    round: round,
-                    roundCheck: {
-                      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
-                    }
-                    getRound(client, roundid).then((round) => {
-                      resolve({
-                        round: round,
-                        roundCheck: {
-                          active: true,
-                          nextRound: true,
-                        },
-                      });
+            functions
+              .timeOut(client, tournament, timedOut, end, timedOutRounds)
+              .then(
+                //updates the state of the tournament and ends it if necessary
+                () => {
+                  functions
+                    .notifyPlayers(client, timedOut, true, tournament)
+                    .then(() => {
+                      const indeks = left.indexOf(activePlayer);
+                      left.splice(indeks, 1);
+                      if (end) {
+                        functions
+                          .notifyPlayers(client, left, false, tournament)
+                          .then(() => {
+                            functions
+                              .endTournament(client, tournament)
+                              .then(() => {
+                                getRound(client, roundid).then((round) => {
+                                  resolve({
+                                    round: round,
+                                    roundCheck: {
+                                      active: false,
+                                      nextRound: false,
+                                    },
+                                  });
+                                });
+                              });
+                          });
+                      } else 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];
+                          functions.updateScore(
+                            client,
+                            round._id,
+                            i + 1,
+                            eligibleRounds.length
+                          );
+                          //And here we update the tournament score
+                        }
+                        functions
+                          .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 * 24 * 60 * 60 * 1000
+                              );
+
+                              functions
+                                .newRound(
+                                  client,
+                                  tournament,
+                                  tourny.players,
+                                  game,
+                                  tourny.currentRound,
+                                  date
+                                )
+                                .then(() => {
+                                  getRound(client, roundid).then((round) => {
+                                    resolve({
+                                      round: round,
+                                      roundCheck: {
+                                        active: true,
+                                        nextRound: true,
+                                      },
+                                    });
+                                  });
+                                });
+                              // created new rounds for all the players left
+                            } else {
+                              // if the tournament now is done we simply end it
+                              functions
+                                .endTournament(client, tournament)
+                                .then(() => {
+                                  functions
+                                    .notifyPlayers(
+                                      client,
+                                      left,
+                                      false,
+                                      tournament
+                                    )
+                                    .then(() => {
+                                      getRound(client, roundid).then(
+                                        (round) => {
+                                          resolve({
+                                            round: round,
+                                            roundCheck: {
+                                              active: false,
+                                              nextRound: false,
+                                            },
+                                          });
+                                        }
+                                      );
+                                    });
+                                });
+                            }
+                          });
+                      } else {
+                        getRound(client, roundid).then((round) => {
+                          resolve({
+                            round: round,
+                            roundCheck: {
+                              // Tournament still waiting for other players
+                              active: true,
+                              nextRound: false,
+                            },
+                          });
+                        });
+                      }
                     });
-                  } else {
-                    // if the tournament now is done we simply end it
-                    endTournament(client, tournament);
-                    notifyPlayers(client, left, false, tournament);
-                    getRound(client, roundid).then((round) => {
-                      resolve({
-                        round: round,
-                        roundCheck: {
-                          active: false,
-                          nextRound: false,
-                        },
-                      });
-                    });
-                    return;
-                  }
-                });
-              } else {
-                getRound(client, roundid).then((round) => {
-                  resolve({
-                    round: round,
-                    roundCheck: {
-                      // Tournament still waiting for other players
-                      active: true,
-                      nextRound: false,
-                    },
-                  });
-                });
-              }
-            }
-          );
-        });
+                }
+              );
+          });
       });
     });
   });
 }
 
-function notifyPlayers(client, players, timeout, tournament) {
-  const db = client.db("gameWare");
-  for (let i = 0; i < players.length; i++) {
-    db.collection("alerts").insertOne({
-      playerId: mongo.ObjectID(players[i]),
-      tournamentId: tournament,
-      timeout: timeout,
-    });
-  }
-}
-
 function getRound(client, id) {
   return new Promise((resolve, reject) => {
     const db = client.db("gameWare");
@@ -593,222 +618,6 @@ function getRound(client, id) {
   });
 }
 
-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;
-        }
-        resolve(result);
-        return;
-      }
-    );
-  });
-}
-
-function timeOut(client, tournament, players, end, rounds) {
-  if (!players) {
-    players = [];
-  }
-  return new Promise((resolve, reject) => {
-    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) {
-          resolve(500); // Internal server error
-          return;
-        }
-        db.collection("rounds").remove(
-          {
-            _id: { $in: rounds },
-          },
-          (err, result) => {
-            if (err) {
-              resolve(500); // Internal server error
-              return;
-            }
-            resolve(result);
-            return;
-          }
-        );
-      }
-    );
-  });
-}
-
-function getCurrentRound(client, tournamentId) {
-  return new Promise((resolve, reject) => {
-    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;
-      }
-    );
-  });
-}
-
-function newRound(
-  client,
-  tournamentId,
-  playerId,
-  gameId,
-  roundNr,
-  deadlineDate
-) {
-  return new Promise((resolve, reject) => {
-    // 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]);
-      }
-    );
-  });
-}
-
-function updateTournamentRound(client, tournament) {
-  return new Promise((resolve, reject) => {
-    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);
-      });
-  });
-}
-
-function checkRounds(result, start, max, roundNr) {
-  return new Promise((resolve, reject) => {
-    let timedOut = [];
-    let timedOutRounds = [];
-    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);
-        timedOutRounds.push(result[i]._id);
-      } 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, timedOutRounds]);
-    } 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, timedOutRounds]);
-    } else {
-      resolve([false, timedOut, left, timedOutRounds]);
-    }
-  });
-}
-
-function fetchRounds(client, tournamentId, activeRound) {
-  return new Promise((resolve, reject) => {
-    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 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);
-      });
-  });
-}
-
 // Export API routes
 module.exports = router;
 
diff --git a/backend/api/tournament.js b/backend/api/tournament.js
index 1a7f4df6952f8bdcae31f77331bceec65cf2bf88..4f9dfd69066790267a9dab3580dfe25da8166e51 100644
--- a/backend/api/tournament.js
+++ b/backend/api/tournament.js
@@ -2,6 +2,7 @@ const express = require("express");
 const router = express.Router();
 const mongo = require("mongodb");
 const MongoClient = mongo.MongoClient;
+const functions = require("./functions");
 const connectionUrl = process.env.MONGO_CONNECTION_STRING;
 
 router.post("/leave", (req, res) => {
@@ -38,6 +39,9 @@ router.post("/leave", (req, res) => {
           {
             $pull: { players: playerid },
             $inc: { currentPlayers: -1 },
+          },
+          {
+            returnOriginal: false,
           }
         )
         .then((updatedDocument) => {
@@ -47,10 +51,18 @@ router.post("/leave", (req, res) => {
               playerId: playerid,
             })
             .then((result) => {
+              if (parseInt(updatedDocument.value.currentPlayers) === 0) {
+                db.collection("tournaments").deleteOne({
+                  _id: tournamentid,
+                });
+              }
               res.json({ deletedRounds: result.result.n });
               client.close();
             })
-            .catch((err) => res.sendStatus(500));
+            .catch((err) => {
+              console.log(err);
+              res.sendStatus(500);
+            });
         });
     }
   );
@@ -97,7 +109,7 @@ router.post("/new", (req, res) => {
         }
         let startTime = new Date(
           tournamentdate.getTime() +
-            parseInt(req.body.startDelay) * 60 * 60 * 1000
+            parseInt(req.body.startDelay) * 24 * 60 * 60 * 1000
         );
         values.players = [mongo.ObjectID(req.body.playerId)];
         values.games = games;
@@ -122,7 +134,7 @@ router.post("/new", (req, res) => {
           return;
         }
         tournamentdate.setTime(
-          tournamentdate.getTime() + req.body.timePerRound * 60 * 60 * 1000
+          tournamentdate.getTime() + req.body.timePerRound * 24 * 60 * 60 * 1000
         );
         createFirstRound(result.insertedId, result, tournamentdate);
       });
@@ -196,7 +208,7 @@ router.post("/join", (req, res) => {
               tournamentdate = updatedDocument.value.dateCreated;
               tournamentdate.setTime(
                 tournamentdate.getTime() +
-                  updatedDocument.value.timePerRound * 60 * 60 * 1000
+                  updatedDocument.value.timePerRound * 24 * 60 * 60 * 1000
               );
               // create the first round for the newly joined player
               createFirstRound(
@@ -333,13 +345,42 @@ router.get("/player/:userid/:active", (req, res) => {
             //console.log(err);
             return;
           }
-          res.json(result);
-          client.close();
+          if (req.params.active === "true") {
+            let IDs = result.map((tourny) => tourny._id);
+            doChecks(client, IDs).then(() => {
+              db.collection(collection)
+                .find({
+                  players: id,
+                  active: req.params.active === "true",
+                })
+                .toArray((err, result) => {
+                  if (err) {
+                    res.sendStatus(500);
+                    //console.log(err);
+                    return;
+                  }
+                  res.json(result);
+                  client.close();
+                  return;
+                });
+            });
+          } else {
+            res.json(result);
+            client.close();
+          }
         });
     }
   );
 });
 
+async function doChecks(client, ids) {
+  for (const tourny of ids) {
+    let id = mongo.ObjectID(tourny);
+    const check = await roundcheck(client, id);
+  }
+  return;
+}
+
 router.put("/roundcheck/:tournamentId", (req, res) => {
   let tournament = null;
   try {
@@ -362,33 +403,48 @@ router.put("/roundcheck/:tournamentId", (req, res) => {
         res.sendStatus(500); // Internal server error
         return;
       }
-
-      getCurrentRound(client, tournament).then((roundResult) => {
-        // gets the current round of the tournament
-        if (roundResult == 500) {
+      roundcheck(client, tournament).then((result) => {
+        if (result == 500) {
           res.sendStatus(500);
-          client.close();
           return;
-        } else if (roundResult.active === false) {
-          res.status(400).send("Tournament not active");
-          client.close();
+        } else if (result == 400) {
+          res.sendStatus(400);
           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
-          /*
-          let activePlayer;
-          for (let i = 0; i < rounds.length; i++) {
-            if (rounds[i]._id === roundid) {
-              activePlayer = rounds[i].playerId;
-              break;
-            }
-          }*/
-          checkRounds(rounds, start, maxPlayers, active).then((resultarray) => {
+        res.json(result);
+        return;
+      });
+    }
+  );
+});
+
+function roundcheck(client, tournament) {
+  return new Promise((resolve, reject) => {
+    functions.getCurrentRound(client, tournament).then((roundResult) => {
+      // gets the current round of the tournament
+      if (roundResult == 500) {
+        resolve(500);
+      } else if (roundResult.active === false) {
+        resolve(400);
+      }
+      const active = roundResult.currentRound;
+      const start = roundResult.startTime;
+      const maxPlayers = roundResult.maxPlayers;
+      const currentPlayers = roundResult.currentPlayers;
+
+      functions.fetchRounds(client, tournament, active).then((rounds) => {
+        // fetched the round objects of the active round
+        /*
+      let activePlayer;
+      for (let i = 0; i < rounds.length; i++) {
+        if (rounds[i]._id === roundid) {
+          activePlayer = rounds[i].playerId;
+          break;
+        }
+      }*/
+        functions
+          .checkRounds(rounds, start, maxPlayers, active, currentPlayers)
+          .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];
@@ -396,327 +452,117 @@ router.put("/roundcheck/:tournamentId", (req, res) => {
             let left = resultarray[2];
             let timedOutRounds = resultarray[3];
             let end = false;
+            //console.log(result + " " + left + "; " + timedOut);
+            //console.log(left.length + " ," + active);
             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, timedOutRounds).then(
-              //updates the state of the tournament and ends it if necessary
-
-              (timeoutresult) => {
-                notifyPlayers(client, timedOut, true, tournament);
-                /*const indeks = left.indexOf(activePlayer);
+            functions
+              .timeOut(client, tournament, timedOut, end, timedOutRounds)
+              .then(
+                //updates the state of the tournament and ends it if necessary
+
+                () => {
+                  functions
+                    .notifyPlayers(client, timedOut, true, tournament)
+                    .then(() => {
+                      /*const indeks = left.indexOf(activePlayer);
                 left.splice(indeks, 1);*/
-                if (end) {
-                  notifyPlayers(client, left, false, tournament);
-                  endTournament(client, tournament);
-                  res.json({
-                    active: false,
-                    nextRound: false,
-                  });
-                  client.close();
-                  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
+                      if (end) {
+                        functions
+                          .notifyPlayers(client, left, false, tournament)
+                          .then(() => {
+                            functions
+                              .endTournament(client, tournament)
+                              .then(() => {
+                                resolve({
+                                  active: false,
+                                  nextRound: false,
+                                });
+                              });
+                          });
+                      } else 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];
+                          functions.updateScore(
+                            client,
+                            round._id,
+                            i + 1,
+                            eligibleRounds.length
+                          );
+                          //And here we update the tournament score
+                        }
+                        functions
+                          .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 * 24 * 60 * 60 * 1000
+                              );
+
+                              functions
+                                .newRound(
+                                  client,
+                                  tournament,
+                                  tourny.players,
+                                  game,
+                                  tourny.currentRound,
+                                  date
+                                )
+                                .then(() => {
+                                  resolve({
+                                    active: true,
+                                    nextRound: true,
+                                  });
+                                });
+                              // created new rounds for all the players left
+                            } else {
+                              // if the tournament now is done we simply end it
+                              functions
+                                .notifyPlayers(client, left, false, tournament)
+                                .then(() => {
+                                  functions
+                                    .endTournament(client, tournament)
+                                    .then(() => {
+                                      resolve({
+                                        active: false,
+                                        nextRound: false,
+                                      });
+                                    });
+                                });
+                            }
+                          });
+                      } else {
+                        resolve({
+                          active: true,
+                          nextRound: false,
+                        }); // Tournament still waiting for other players
                       }
-                      res.json({
-                        active: true,
-                        nextRound: true,
-                      });
-                      client.close();
-                      return;
-                    } else {
-                      // if the tournament now is done we simply end it
-                      endTournament(client, tournament);
-                      notifyPlayers(client, left, false, tournament);
-                      res.json({
-                        active: false,
-                        nextRound: false,
-                      });
-                      client.close();
-                      return;
-                    }
-                  });
-                } else {
-                  res.json({
-                    active: true,
-                    nextRound: false,
-                  });
-                  client.close(); // Tournament still waiting for other players
+                    });
                 }
-              }
-            );
+              );
           });
-        });
       });
-    }
-  );
-});
-
-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;
-        }
-        resolve(result);
-        return;
-      }
-    );
-  });
-}
-
-function notifyPlayers(client, players, timeout, tournament) {
-  const db = client.db("gameWare");
-  for (let i = 0; i < players.length; i++) {
-    db.collection("alerts").insertOne({
-      playerId: mongo.ObjectID(players[i]),
-      tournamentId: tournament,
-      timeout: timeout,
     });
-  }
-}
-
-function timeOut(client, tournament, players, end, rounds) {
-  if (!players) {
-    players = [];
-  }
-  return new Promise((resolve, reject) => {
-    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) {
-          resolve(500); // Internal server error
-          return;
-        }
-        db.collection("rounds").remove(
-          {
-            _id: { $in: rounds },
-          },
-          (err, result) => {
-            if (err) {
-              resolve(500); // Internal server error
-              return;
-            }
-            resolve(result);
-            return;
-          }
-        );
-      }
-    );
-  });
-}
-
-function getCurrentRound(client, tournamentId) {
-  return new Promise((resolve, reject) => {
-    const db = client.db("gameWare");
-    const collection = "tournaments";
-
-    db.collection(collection).findOne(
-      {
-        _id: tournamentId,
-      },
-      { currentRound: 1, startTime: 1, maxPlayers: 1, active: 1 },
-      (err, result) => {
-        if (err) {
-          resolve(500); // Internal server error
-          return;
-        }
-        resolve(result);
-        return;
-      }
-    );
-  });
-}
-
-function newRound(
-  client,
-  tournamentId,
-  playerId,
-  gameId,
-  roundNr,
-  deadlineDate
-) {
-  return new Promise((resolve, reject) => {
-    // 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]);
-      }
-    );
-  });
-}
-
-function updateTournamentRound(client, tournament) {
-  return new Promise((resolve, reject) => {
-    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);
-      });
-  });
-}
-
-function checkRounds(result, start, max, roundNr) {
-  return new Promise((resolve, reject) => {
-    let timedOut = [];
-    let timedOutRounds = [];
-    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);
-        timedOutRounds.push(mongo.ObjectID(result[i]._id));
-      } 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, timedOutRounds]);
-    } 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, timedOutRounds]);
-    } else {
-      resolve([false, timedOut, left, timedOutRounds]);
-    }
-  });
-}
-
-function fetchRounds(client, tournamentId, activeRound) {
-  return new Promise((resolve, reject) => {
-    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 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/FruitSlicerBackground.png b/frontend/android/assets/FruitSlicerBackground.png
new file mode 100644
index 0000000000000000000000000000000000000000..aeb45918edf0eb4ef09fecb80217325aa7afd82c
Binary files /dev/null and b/frontend/android/assets/FruitSlicerBackground.png differ
diff --git a/frontend/android/assets/FruitSlicerPhotoEdit.png b/frontend/android/assets/FruitSlicerPhotoEdit.png
new file mode 100644
index 0000000000000000000000000000000000000000..e2baec9e8f6bb4b5cfa93044aeae5dbe4b663480
Binary files /dev/null and b/frontend/android/assets/FruitSlicerPhotoEdit.png differ
diff --git a/frontend/android/assets/FruitTexture1.png b/frontend/android/assets/FruitTexture1.png
new file mode 100644
index 0000000000000000000000000000000000000000..fbf6a1c1ae135cf6c3018b72eb05b38b75163f3c
Binary files /dev/null and b/frontend/android/assets/FruitTexture1.png differ
diff --git a/frontend/android/assets/FruitTexture10.png b/frontend/android/assets/FruitTexture10.png
new file mode 100644
index 0000000000000000000000000000000000000000..7dffaa1c39329f5a4fae6df9f10fad0021c816d6
Binary files /dev/null and b/frontend/android/assets/FruitTexture10.png differ
diff --git a/frontend/android/assets/FruitTexture11.png b/frontend/android/assets/FruitTexture11.png
new file mode 100644
index 0000000000000000000000000000000000000000..d006233a48a6cbf19a7509cb22bf74b03556546f
Binary files /dev/null and b/frontend/android/assets/FruitTexture11.png differ
diff --git a/frontend/android/assets/FruitTexture12.png b/frontend/android/assets/FruitTexture12.png
new file mode 100644
index 0000000000000000000000000000000000000000..78b3ecbd0d671af5182a13a679158d5bce80c67b
Binary files /dev/null and b/frontend/android/assets/FruitTexture12.png differ
diff --git a/frontend/android/assets/FruitTexture13.png b/frontend/android/assets/FruitTexture13.png
new file mode 100644
index 0000000000000000000000000000000000000000..3646e13c25640ac0d756b2b1f6ca00eb07019548
Binary files /dev/null and b/frontend/android/assets/FruitTexture13.png differ
diff --git a/frontend/android/assets/FruitTexture14.png b/frontend/android/assets/FruitTexture14.png
new file mode 100644
index 0000000000000000000000000000000000000000..f3873a2977a798eba8b4f224d8374e1e0d5bc9fb
Binary files /dev/null and b/frontend/android/assets/FruitTexture14.png differ
diff --git a/frontend/android/assets/FruitTexture15.png b/frontend/android/assets/FruitTexture15.png
new file mode 100644
index 0000000000000000000000000000000000000000..13d1277bd122dea580a8c519d3b140e4bec723a2
Binary files /dev/null and b/frontend/android/assets/FruitTexture15.png differ
diff --git a/frontend/android/assets/FruitTexture16.png b/frontend/android/assets/FruitTexture16.png
new file mode 100644
index 0000000000000000000000000000000000000000..b7edce403d2eec6121f4b540cb13072536a2d59f
Binary files /dev/null and b/frontend/android/assets/FruitTexture16.png differ
diff --git a/frontend/android/assets/FruitTexture17.png b/frontend/android/assets/FruitTexture17.png
new file mode 100644
index 0000000000000000000000000000000000000000..6e99cf8e4feafe49b8a5bca438489a2bc7d8e5e8
Binary files /dev/null and b/frontend/android/assets/FruitTexture17.png differ
diff --git a/frontend/android/assets/FruitTexture18.png b/frontend/android/assets/FruitTexture18.png
new file mode 100644
index 0000000000000000000000000000000000000000..8bbc6c18d99ceea5edc31c8d518d277c921f9fc0
Binary files /dev/null and b/frontend/android/assets/FruitTexture18.png differ
diff --git a/frontend/android/assets/FruitTexture19.png b/frontend/android/assets/FruitTexture19.png
new file mode 100644
index 0000000000000000000000000000000000000000..29d7cbabcd915be4e4bfb68b1055824d80820001
Binary files /dev/null and b/frontend/android/assets/FruitTexture19.png differ
diff --git a/frontend/android/assets/FruitTexture2.png b/frontend/android/assets/FruitTexture2.png
new file mode 100644
index 0000000000000000000000000000000000000000..81f8fee9bde76bb5354b166c7ba6b83de82ba912
Binary files /dev/null and b/frontend/android/assets/FruitTexture2.png differ
diff --git a/frontend/android/assets/FruitTexture20.png b/frontend/android/assets/FruitTexture20.png
new file mode 100644
index 0000000000000000000000000000000000000000..ddeb3c07ef388c20b7ce096b14524e694ad45880
Binary files /dev/null and b/frontend/android/assets/FruitTexture20.png differ
diff --git a/frontend/android/assets/FruitTexture3.png b/frontend/android/assets/FruitTexture3.png
new file mode 100644
index 0000000000000000000000000000000000000000..73c164172ec4e457e290c93d1a209fbefda89532
Binary files /dev/null and b/frontend/android/assets/FruitTexture3.png differ
diff --git a/frontend/android/assets/FruitTexture4.png b/frontend/android/assets/FruitTexture4.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b05385e113ef2715dc84b9f6957e832723bbc11
Binary files /dev/null and b/frontend/android/assets/FruitTexture4.png differ
diff --git a/frontend/android/assets/FruitTexture5.png b/frontend/android/assets/FruitTexture5.png
new file mode 100644
index 0000000000000000000000000000000000000000..e254e2f96dee2495ed5a71675c9af9c6aabd1aa6
Binary files /dev/null and b/frontend/android/assets/FruitTexture5.png differ
diff --git a/frontend/android/assets/FruitTexture6.png b/frontend/android/assets/FruitTexture6.png
new file mode 100644
index 0000000000000000000000000000000000000000..1f69686583226ab6ada554ea9b90fbe2eaf4d377
Binary files /dev/null and b/frontend/android/assets/FruitTexture6.png differ
diff --git a/frontend/android/assets/FruitTexture7.png b/frontend/android/assets/FruitTexture7.png
new file mode 100644
index 0000000000000000000000000000000000000000..d27047d841cf884933b610d67876cd22fe310a05
Binary files /dev/null and b/frontend/android/assets/FruitTexture7.png differ
diff --git a/frontend/android/assets/FruitTexture8.png b/frontend/android/assets/FruitTexture8.png
new file mode 100644
index 0000000000000000000000000000000000000000..884c52ff4359379a4cb08f3120d51aa321db05de
Binary files /dev/null and b/frontend/android/assets/FruitTexture8.png differ
diff --git a/frontend/android/assets/FruitTexture9.png b/frontend/android/assets/FruitTexture9.png
new file mode 100644
index 0000000000000000000000000000000000000000..34395c2d34b8e9aaee6c2abe99bbcaf86c96df76
Binary files /dev/null and b/frontend/android/assets/FruitTexture9.png differ
diff --git a/frontend/android/assets/sfx/FruitSlicerSquishSound.mp3 b/frontend/android/assets/sfx/FruitSlicerSquishSound.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..50b4128fd80e042af0e6f85265b7068ed3269d5b
Binary files /dev/null and b/frontend/android/assets/sfx/FruitSlicerSquishSound.mp3 differ
diff --git a/frontend/android/assets/sfx/FruitSlicerWhooshSound.mp3 b/frontend/android/assets/sfx/FruitSlicerWhooshSound.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..d57dd2687c1d7614940b655e80a357add37c0107
Binary files /dev/null and b/frontend/android/assets/sfx/FruitSlicerWhooshSound.mp3 differ
diff --git a/frontend/android/assets/sfx/small_click.ogg b/frontend/android/assets/sfx/small_click.ogg
new file mode 100644
index 0000000000000000000000000000000000000000..d5345267fc690b873c111d96ba4d17ebfcb6c049
Binary files /dev/null and b/frontend/android/assets/sfx/small_click.ogg differ
diff --git a/frontend/android/assets/tableBG.png b/frontend/android/assets/tableBG.png
new file mode 100644
index 0000000000000000000000000000000000000000..c63788c6cb611357c7f0663c0609b604ebcd3d05
Binary files /dev/null and b/frontend/android/assets/tableBG.png differ
diff --git a/frontend/android/assets/tableBGRounded.png b/frontend/android/assets/tableBGRounded.png
new file mode 100644
index 0000000000000000000000000000000000000000..f5076b1bb74e656a662e49c83acda133d18808dd
Binary files /dev/null and b/frontend/android/assets/tableBGRounded.png differ
diff --git a/frontend/core/src/com/gameware/game/GameWare.java b/frontend/core/src/com/gameware/game/GameWare.java
index 0c6c0c42ea60b32f96753b88e1159f2907356bb8..6f2691d7925acd48e254a344a2814197e5950b97 100644
--- a/frontend/core/src/com/gameware/game/GameWare.java
+++ b/frontend/core/src/com/gameware/game/GameWare.java
@@ -13,11 +13,11 @@ import com.gameware.game.models.LocalStorage;
 import com.gameware.game.states.BubbleWrapState;
 import com.gameware.game.models.Player;
 import com.gameware.game.states.ColorRushState;
+import com.gameware.game.states.FruitSlicerState;
 import com.gameware.game.states.GameStateManager;
+import com.gameware.game.states.LoginState;
 import com.gameware.game.states.MenuState;
 import com.gameware.game.states.PlayStateTemplate;
-import com.gameware.game.states.LoginState;
-
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -29,6 +29,7 @@ public class GameWare extends ApplicationAdapter {
 	private SpriteBatch batch;
 	private GameStateManager gsm;
 
+	private String fruitSlicerId = "5e90541aeba599f7b1bffceb";
 	private String colorRushId = "5e5d0efaa6e2bc5cb4920b7a";
 	private String bubbleWrapId = "5e5d0f1ea6e2bc5cb4920b7b";
 
@@ -67,8 +68,11 @@ public class GameWare extends ApplicationAdapter {
 		}
 		gsm = GameStateManager.getInstance();
 
+		// Playable minigames
+		gameIdToPlayState.put(fruitSlicerId, new FruitSlicerState(gsm));
 		gameIdToPlayState.put(colorRushId, new ColorRushState(gsm));
 		gameIdToPlayState.put(bubbleWrapId, new BubbleWrapState(gsm));
+
 		batch = new SpriteBatch();
 
 		music = Gdx.audio.newMusic(Gdx.files.internal(("bensound-goinghigher.mp3")));
@@ -84,7 +88,6 @@ public class GameWare extends ApplicationAdapter {
 			gsm.push(new MenuState(gsm));
 		}
 		if(musicOn){music.play();}
-
 	}
 
 	@Override
diff --git a/frontend/core/src/com/gameware/game/QueryIntermediate.java b/frontend/core/src/com/gameware/game/QueryIntermediate.java
index 6e0fea4fd2f25a7c081b86e81779a9330acfce09..19205337c140fd44abd0072682d6020a9e53ed1a 100644
--- a/frontend/core/src/com/gameware/game/QueryIntermediate.java
+++ b/frontend/core/src/com/gameware/game/QueryIntermediate.java
@@ -341,14 +341,13 @@ public class QueryIntermediate {
     }
 
     // ---------------- Alert methods ----------------
-    public static List<Alert> getAlertsForPlayer(String playerId) throws IOException, NoSuchElementException {
+    public static List<Alert> getAlertsForPlayer(String playerId) throws IOException {
         String route = "alerts/" + playerId;
         List<Alert> alerts = new ArrayList<>();
         String[] response = sendGetRequest(route);
         checkStatusCode(response);
         JsonValue base = jsonReader.parse(response[1]);
         JsonValue.JsonIterator iterator = base.iterator();
-        checkIteratorNotEmpty(iterator);
         while (iterator.hasNext()) {
             Alert alert = json.fromJson(Alert.class, iterator.next().toString());
             alerts.add(alert);
diff --git a/frontend/core/src/com/gameware/game/sprites/Fruit.java b/frontend/core/src/com/gameware/game/sprites/Fruit.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f23461d6e6d6c17f336a96b4554dabcaed60aa2
--- /dev/null
+++ b/frontend/core/src/com/gameware/game/sprites/Fruit.java
@@ -0,0 +1,176 @@
+package com.gameware.game.sprites;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.math.Vector3;
+
+
+public class Fruit extends Sprite {
+    private Vector3 cutPosition1;
+    private Vector3 cutPosition2;
+
+    private Vector3 uncutVelocity;
+    private Vector3 cutVelocity1;
+    private Vector3 cutVelocity2;
+
+    private int rotationSpeed;
+    private int cutWidth;
+    private int cutHeight;
+
+    private float cuttingVelocity;
+    private float gravity;
+
+    private boolean isCut;
+
+    private com.badlogic.gdx.graphics.g2d.Sprite uncutFruit;
+    private com.badlogic.gdx.graphics.g2d.Sprite cutFruit1;
+    private com.badlogic.gdx.graphics.g2d.Sprite cutFruit2;
+
+    public Fruit(int x, int y, int width, int height, Vector3 velocity, Texture uncutFruitTexture){
+        this.position = new Vector3(x, y, 0);
+        this.cutPosition1 = new Vector3(0,0,0);
+        this.cutPosition2 = new Vector3(0,0,0);
+
+        this.cuttingVelocity = Gdx.graphics.getWidth()/2;
+        this.gravity = Gdx.graphics.getWidth()/3;
+
+        this.uncutVelocity = velocity;
+        this.cutVelocity1 = new Vector3(-this.cuttingVelocity,0,0);
+        this.cutVelocity2 = new Vector3(this.cuttingVelocity,0,0);
+
+        this.rotationSpeed = (int) ((Math.random() - 0.5) * 1000);
+        this.width = width;
+        this.height = height;
+        this.cutWidth = width/2;
+        this.cutHeight = height;
+
+        this.isCut = false;
+
+        TextureRegion fullTexRegion = new TextureRegion(uncutFruitTexture);
+
+        int regionCutWidth = fullTexRegion.getRegionWidth()/2;
+        int regionCutHeight = fullTexRegion.getRegionHeight();
+
+        TextureRegion leftTexRegion = new TextureRegion(fullTexRegion, 0,0, regionCutWidth, regionCutHeight);
+        TextureRegion rightTexRegion = new TextureRegion(fullTexRegion, regionCutWidth,0, regionCutWidth, regionCutHeight);
+
+        this.uncutFruit = new com.badlogic.gdx.graphics.g2d.Sprite(fullTexRegion);
+        this.cutFruit1 = new com.badlogic.gdx.graphics.g2d.Sprite(leftTexRegion);
+        this.cutFruit2 = new com.badlogic.gdx.graphics.g2d.Sprite(rightTexRegion);
+    }
+
+
+
+
+    @Override
+    public void reset() {
+
+    }
+
+    @Override
+    public void draw(SpriteBatch sb) {
+        sb.begin();
+
+        if(this.isCut){
+            this.cutFruit1.draw(sb);
+            this.cutFruit2.draw(sb);
+        }
+
+        else{
+            this.uncutFruit.draw(sb);
+        }
+
+        sb.end();
+    }
+
+    @Override
+    public void update(float dt) {
+        if(this.isCut){
+            // Updates the position of the two fruit pieces based on its velocity
+
+            this.cutVelocity1.scl(dt);
+            this.cutVelocity2.scl(dt);
+
+            this.cutPosition1.add(this.cutVelocity1.x, this.cutVelocity1.y, 0);
+            this.cutPosition2.add(this.cutVelocity2.x, this.cutVelocity2.y, 0);
+
+            this.cutVelocity1.scl(1/dt);
+            this.cutVelocity2.scl(1/dt);
+
+            // Sets the position of the two fruit pieces
+            this.cutFruit1.setPosition(this.cutPosition1.x, this.cutPosition1.y);
+            this.cutFruit2.setPosition(this.cutPosition2.x, this.cutPosition2.y);
+
+            // Gravity affects the fruit pieces' velocity
+            this.cutVelocity1.y -= this.gravity*2*dt;
+            this.cutVelocity2.y -= this.gravity*2*dt;
+
+            // Oppositely rotates the two pieces by a third of the original rotation speed
+            this.cutFruit1.rotate(this.rotationSpeed / 3*dt);
+            this.cutFruit2.rotate(-this.rotationSpeed / 3*dt);
+        }
+
+        else{
+            // Updates the position of the full fruit based on its velocity
+            this.uncutVelocity.scl(dt);
+            this.position.add(this.uncutVelocity.x, this.uncutVelocity.y, 0);
+            this.uncutVelocity.scl(1/dt);
+
+            // Gravity affects the fruit's velocity
+            this.uncutVelocity.y -= this.gravity*dt;
+
+            // Sets the full fruit's size, position and rotation
+            this.uncutFruit.setOriginCenter();
+            this.uncutFruit.setSize(this.width, this.height);
+            this.uncutFruit.setPosition(this.position.x, this.position.y);
+            this.uncutFruit.rotate(this.rotationSpeed * dt);
+        }
+    }
+
+    @Override
+    public void dispose() {
+    }
+
+    public boolean isDisposable() {
+        // If the uncut fruit or the two cut fruit pieces have fallen this far in the y-direction, we know we can dispose it
+        return this.position.y < -this.height*3 || (this.cutPosition1.y < -this.height*3 && this.cutPosition2.y < -this.height*3);
+    }
+
+    public boolean isPressed(int x, int y) {
+        // If the user touched the fruit
+        if(!this.isCut && x > this.position.x && x < (this.position.x + this.width) && (Gdx.graphics.getHeight() - y) > this.position.y && (Gdx.graphics.getHeight() - y) < (this.position.y + this.height)) {
+            this.isCut = true;
+
+            // Updates the sprite positions
+            this.cutPosition1.x = this.position.x;
+            this.cutPosition1.y = this.position.y;
+            this.cutPosition2.x = this.position.x + this.cutWidth;
+            this.cutPosition2.y = this.position.y;
+
+            // Rotates the two velocities so the two parts of the fruit are moving away from each other
+            this.cutVelocity1.rotate(this.uncutFruit.getRotation(), 0, 0, 1);
+            this.cutVelocity2.rotate(this.uncutFruit.getRotation(), 0, 0, 1);
+
+            // The two pieces keeps 25% of the original full fruits' velocity
+            this.cutVelocity1.add((float)(this.uncutVelocity.x*0.25), (float)(this.uncutVelocity.y*0.25), 0);
+            this.cutVelocity2.add((float)(this.uncutVelocity.x*0.25), (float)(this.uncutVelocity.y*0.25), 0);
+
+            // Sets the size
+            this.cutFruit1.setSize(this.cutWidth, this.cutHeight);
+            this.cutFruit2.setSize(this.cutWidth, this.cutHeight);
+
+            // Sets the origin of rotation the same as the original full fruit
+            this.cutFruit1.setOrigin(cutWidth, cutHeight/2);
+            this.cutFruit2.setOrigin(0, cutHeight/2);
+
+            // Rotates the fruit similar to the full fruit
+            this.cutFruit1.setRotation(this.uncutFruit.getRotation());
+            this.cutFruit2.setRotation(this.uncutFruit.getRotation());
+
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/frontend/core/src/com/gameware/game/states/CreateJoinTournamentState.java b/frontend/core/src/com/gameware/game/states/CreateJoinTournamentState.java
index 719c2143e2d2cc9d33de4a17a13341fb6b68eba7..eb5650d95e643dd5f7f81aac8b903c96d7e57fae 100644
--- a/frontend/core/src/com/gameware/game/states/CreateJoinTournamentState.java
+++ b/frontend/core/src/com/gameware/game/states/CreateJoinTournamentState.java
@@ -18,6 +18,7 @@ import com.badlogic.gdx.utils.Scaling;
 import com.gameware.game.GameWare;
 import com.gameware.game.QueryIntermediate;
 import com.gameware.game.models.Round;
+import com.gameware.game.models.RoundCheck;
 import com.gameware.game.models.Tournament;
 import com.gameware.game.sprites.LoadingText;
 
@@ -54,7 +55,6 @@ public class CreateJoinTournamentState extends State {
 
 
 //    Variables
-    private final int padding = 50;
     private Tournament tournamentTryingToLeave = null;
     private boolean includeFinishedTournaments = GameWare.getInstance().getIncludeFin();
     private final Color scrollPaneBGColor = Color.SKY;
@@ -138,8 +138,8 @@ public class CreateJoinTournamentState extends State {
 
     private Table createTournamentList(){
         Table innerTable = new Table();
-        innerTable.setBackground(makeColorBackground(scrollPaneBGColor));
-        innerTable.defaults().space(spacingLittle);
+        innerTable.setBackground(backgroundTableBlueRounded);
+        innerTable.defaults().space(spacingLittle).expandY();
         innerTable.pad(spacingLittle).padRight(spacingLittle);
 
         if(!tournaments.isEmpty()) {
@@ -260,6 +260,7 @@ public class CreateJoinTournamentState extends State {
             this.joinButtonClicked = false;
         }
 
+
         this.loadingText.update(dt);
     }
 
@@ -314,11 +315,24 @@ public class CreateJoinTournamentState extends State {
 
     private void handleEnterBtnClick(Tournament t, Round r){
         if(GameWare.getInstance().getSoundEffects()){ buttonPressSound.play(); }
+
         if(!t.isActive()){
             gsm.set(new FinishedTournamentState(gsm,t));
         }
         else{
-            gsm.set(new ViewTournamentState(gsm, t, r));
+            RoundCheck rc = null;
+            try {
+                rc = QueryIntermediate.doRoundCheck(t.get_id());
+            }catch(IOException e){
+                e.printStackTrace();
+            }
+            if(rc != null && !rc.isActive()){
+                FinishedTournamentState s = new FinishedTournamentState(gsm, t);
+                s.makeDialogTimeOut();
+                gsm.set(s);
+            } else {
+                gsm.set(new ViewTournamentState(gsm, t, r));
+            }
         }
     }
 
@@ -387,7 +401,7 @@ public class CreateJoinTournamentState extends State {
     void setFeedbackLabelText(String text){
         tournamentFeedbackLabel.getColor().a = 1;
         tournamentFeedbackLabel.addAction(Actions.sequence(
-                new DelayAction(6),
+                new DelayAction(8),
                 Actions.fadeOut(2)));
         tournamentFeedbackLabel.setText(text);
     }
diff --git a/frontend/core/src/com/gameware/game/states/CreateNewTournamentState.java b/frontend/core/src/com/gameware/game/states/CreateNewTournamentState.java
index bfdd91ad85614e182ab5954505c6a759b261dbd4..8346c96034b446605a582c59c4cb063ecfa45949 100644
--- a/frontend/core/src/com/gameware/game/states/CreateNewTournamentState.java
+++ b/frontend/core/src/com/gameware/game/states/CreateNewTournamentState.java
@@ -152,9 +152,13 @@ public class CreateNewTournamentState extends State {
         Table innerTable = new Table();
         innerTable.pad(spacingLittle);
         innerTable.defaults().space(spacingLittle);
-        innerTable.setBackground(makeColorBackground(scrollPaneBGColor));
+        innerTable.setBackground(backgroundTableBlueRounded);
 
         for (final Game g : games){
+            if(GameWare.getInstance().getGameIdToPlayState().get(g.getId()) == null){
+                continue;
+            }
+
             innerTable.add(new Image(GameWare.getInstance().getGameIdToPlayState().get(g.getId()).screenshot));
 
             Table innerInnerTable = new Table();
diff --git a/frontend/core/src/com/gameware/game/states/FinishedTournamentState.java b/frontend/core/src/com/gameware/game/states/FinishedTournamentState.java
index d451925555c2f56004f5ade7f18069bafc900596..d2e0d322f6e9576da08a5ff933619d7b1870ce6c 100644
--- a/frontend/core/src/com/gameware/game/states/FinishedTournamentState.java
+++ b/frontend/core/src/com/gameware/game/states/FinishedTournamentState.java
@@ -34,12 +34,13 @@ public class FinishedTournamentState extends State {
     private final String leaveBtnText = "Leave";
     private final String winnerText = "Winner: ";
     private final String leaveDialogText = "Are you sure want to\nleave ";
+    private final String dialogTimeOutText = "Tournament finished because\nplayers timed out or left";
 
 //    Variables
-    private final int padding = 50;
     private final Color scrollPaneBGColor = Color.GOLD;
 
     private Dialog dialog;
+    private Dialog dialogTimeOut;
 
 
     public FinishedTournamentState(GameStateManager gsm, Tournament tournament) {
@@ -127,6 +128,13 @@ public class FinishedTournamentState extends State {
         dialog.button("No", false).pad(padding);  //sends "false" as the result
     }
 
+    public void makeDialogTimeOut(){
+        dialogTimeOut = new Dialog("", skin, "dialog");
+        dialogTimeOut.text(dialogTimeOutText).pad(padding);
+        dialogTimeOut.button("Okay", false).pad(padding);  //sends "false" as the result
+        dialogTimeOut.show(stage);
+    }
+
     private TextButton makeBackBtn(){
         TextButton backBtn = new TextButton(backBtnText, skin);
         backBtn.addListener(new ClickListener() {
diff --git a/frontend/core/src/com/gameware/game/states/FruitSlicerState.java b/frontend/core/src/com/gameware/game/states/FruitSlicerState.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e5e0c4ab5f381b2f1b4acaa69820363888b4ae5
--- /dev/null
+++ b/frontend/core/src/com/gameware/game/states/FruitSlicerState.java
@@ -0,0 +1,223 @@
+package com.gameware.game.states;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.audio.Sound;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.BitmapFont;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.math.Vector3;
+import com.gameware.game.GameWare;
+import com.gameware.game.sprites.Fruit;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FruitSlicerState extends PlayStateTemplate {
+    private float currentDuration = 0f;
+    private float totalDuration = 60f;
+    private float startingEmitFrequency = 1f;
+    private float endingEmitFrequency = 0.2f;
+    private float timeSinceLastEmit = 0;
+    private int totalFruitsCut = 0;
+    private BitmapFont font;
+    private Texture background = new Texture(Gdx.files.internal("FruitSlicerBackground.png"));
+    private List<Texture> fruitTextures;
+    private List<Fruit> emittedFruits;
+    private Sound sliceWhooshSound;
+    private Sound sliceSquishSound;
+
+    private Fruit fruit;
+
+    public FruitSlicerState(GameStateManager gsm) {
+        super(gsm);
+        super.setPauseButtonWhite();
+        super.screenshot = new Texture(Gdx.files.internal("FruitSlicerPhotoEdit.png"));
+
+        this.sliceWhooshSound = Gdx.audio.newSound(Gdx.files.internal("sfx/FruitSlicerWhooshSound.mp3"));
+        this.sliceSquishSound = Gdx.audio.newSound(Gdx.files.internal("sfx/FruitSlicerSquishSound.mp3"));
+
+        this.fruitTextures = new ArrayList<>();
+        this.emittedFruits = new ArrayList<>();
+
+        // Creates the bitmapfont
+        font = new BitmapFont();
+        font.setColor(Color.WHITE);
+        font.getData().setScale(Gdx.graphics.getWidth()/ GameWare.WIDTH*2);
+
+        for(int textureNum = 1; textureNum <= 20; textureNum++){
+            String filename = "FruitTexture" + String.valueOf(textureNum) + ".png";
+            this.fruitTextures.add(new Texture(Gdx.files.internal(filename)));
+        }
+    }
+
+    @Override
+    public void handleInput(){
+        if(Gdx.input.justTouched()) {
+            int touchX = Gdx.input.getX();
+            int touchY = Gdx.input.getY();
+            boolean didCut = false;
+
+            for(Fruit fruit : this.emittedFruits){
+                if(fruit.isPressed(touchX, touchY)){
+                    this.totalFruitsCut++;
+                    didCut = true;
+                }
+            }
+
+            if(didCut){
+                this.sliceWhooshSound.play();
+                this.sliceSquishSound.play(0.15f);
+            }
+
+            super.setScore(this.totalFruitsCut);
+        }
+    }
+
+    @Override
+    public void update(float dt){
+        // Effectively updates the pause button and the loading text
+        super.update(dt);
+
+        this.handleInput();
+
+        this.currentDuration += dt;
+        this.timeSinceLastEmit += dt;
+
+        if(this.currentDuration > this.totalDuration){
+            super.setGameFinished();
+        }
+
+        // Increases the emiting frequency towards the endingEmitFrequency as the game gets closer to the end
+        float currentFrequency = (float) (this.startingEmitFrequency - (this.startingEmitFrequency - this.endingEmitFrequency) * Math.min(this.currentDuration / (this.totalDuration * 0.6), 1));
+
+        // Emits a new fruit
+        if(this.timeSinceLastEmit > currentFrequency){
+            this.emitNewFruit();
+            this.timeSinceLastEmit = 0;
+        }
+
+        for(Fruit fruit : this.emittedFruits){
+            fruit.update(dt);
+        }
+
+        // Removes the oldest fruit if it is disposable
+        if(this.emittedFruits.size() > 0 && this.emittedFruits.get(0).isDisposable()){
+            this.emittedFruits.get(0).dispose();
+            this.emittedFruits.remove(this.emittedFruits.get(0));
+        }
+    }
+
+    @Override
+    public void render(SpriteBatch sb){
+        sb.begin();
+
+        // Background
+        sb.draw(this.background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+
+        sb.end();
+
+        // Fruits
+        for(Fruit fruit : this.emittedFruits){
+            fruit.draw(sb);
+        }
+
+        sb.begin();
+
+        // Time left
+        this.font.draw(sb, String.valueOf(Math.max(Math.round((this.totalDuration - this.currentDuration) * 100), 0.00) / 100.0), Gdx.graphics.getWidth()/40,Gdx.graphics.getHeight() - Gdx.graphics.getHeight()/40);
+
+        sb.end();
+
+        //Effectively renders the pause button and the loading text
+        super.render(sb);
+    }
+
+    @Override
+    public void dispose(){
+        super.dispose();
+
+        this.background.dispose();
+        this.font.dispose();
+        this.sliceWhooshSound.dispose();
+        this.sliceSquishSound.dispose();
+
+        for(Texture fruit : this.fruitTextures){
+            fruit.dispose();
+        }
+    }
+
+    public void emitNewFruit() {
+        // Four different emit modes: from left, from right, from entire bottom, and from bottom center with different velocity angles
+        int emitMode = (int) (Math.random() * 4);
+        Fruit fruit;
+        Texture fruitTexture = this.fruitTextures.get((int) (Math.random() * 20));
+        Vector3 velocity = new Vector3(Gdx.graphics.getWidth() * 3 / 4, 0, 0);
+
+        int x, y, emitAngle, rotationSpeed;
+
+        float fruitAspectRatio = Float.valueOf(fruitTexture.getWidth()) / Float.valueOf(fruitTexture.getHeight());
+        int fruitWidth = Gdx.graphics.getWidth() / 5;
+        int fruitHeight = (int) (fruitWidth / fruitAspectRatio);
+
+        // Emit from left
+        if (emitMode == 0){
+            x = -fruitWidth * 2;
+            y = (int) (Math.random() * Gdx.graphics.getHeight() / 3);
+            emitAngle = (int) (15 + Math.random() * 60);
+
+            velocity.rotate(emitAngle, 0, 0, 1);
+
+            fruit = new Fruit(x, y, fruitWidth, fruitHeight, velocity, fruitTexture);
+            this.emittedFruits.add(fruit);
+        }
+
+        // Emit from right
+        else if(emitMode == 1) {
+            x = Gdx.graphics.getWidth() + fruitWidth * 2;
+            y = (int) (Math.random() * Gdx.graphics.getHeight() / 3);
+            emitAngle = (int) (180 - (15 + Math.random() * 60));
+
+            velocity.rotate(emitAngle, 0, 0, 1);
+
+            fruit = new Fruit(x, y, fruitWidth, fruitHeight, velocity, fruitTexture);
+            this.emittedFruits.add(fruit);
+        }
+
+        // Emit from entire bottom part of the screen
+        else if(emitMode == 2){
+            int xWidth = Gdx.graphics.getWidth() + fruitWidth * 2;
+            x = (int)(xWidth*Math.random());
+            y = -fruitHeight*2;
+            float emitAngleOffset = 30 - 30 * (Float.valueOf(x) / Float.valueOf(xWidth));
+            emitAngle = (int) (105 - emitAngleOffset);
+
+            velocity.x = (int) (velocity.x * (1.1 + 0.5 * (15 - Math.abs(90 - Float.valueOf(emitAngle)))/15));
+            velocity.rotate(emitAngle, 0, 0, 1);
+
+            fruit = new Fruit(x - fruitWidth, y, fruitWidth, fruitHeight, velocity, fruitTexture);
+            this.emittedFruits.add(fruit);
+        }
+
+        // Emit from bottom center, with random emit angles
+        else if(emitMode == 3){
+            x = Gdx.graphics.getWidth()/2 + fruitWidth/2;
+            y = - fruitHeight*2;
+            emitAngle = (int) (100 - Math.random()*20);
+
+            velocity.x = (int) (velocity.x * 1.4);
+            velocity.rotate(emitAngle, 0, 0, 1);
+
+            fruit = new Fruit(x - fruitWidth, y, fruitWidth, fruitHeight, velocity, fruitTexture);
+            this.emittedFruits.add(fruit);
+        }
+    }
+
+    @Override
+    public void reset(){
+        this.currentDuration = 0f;
+        this.timeSinceLastEmit = 0f;
+        this.totalFruitsCut = 0;
+        this.emittedFruits = new ArrayList<>();
+    }
+}
diff --git a/frontend/core/src/com/gameware/game/states/MenuState.java b/frontend/core/src/com/gameware/game/states/MenuState.java
index 8927d79ec9397ac217eeac51341db9eb0628f3a1..f4461d4273a8914e3b7bb4e2a3369381c3a343b6 100644
--- a/frontend/core/src/com/gameware/game/states/MenuState.java
+++ b/frontend/core/src/com/gameware/game/states/MenuState.java
@@ -4,32 +4,57 @@ 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.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;
 import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
 import com.gameware.game.GameWare;
+import com.gameware.game.QueryIntermediate;
+import com.gameware.game.models.Alert;
+import com.gameware.game.models.Tournament;
 import com.gameware.game.sprites.LoadingText;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
 public class MenuState extends State{
 
+//    Data
+    private List<Alert> alerts = new ArrayList<>();
+
 //    Labels
     private final Label titleLabel = new Label("GameWare", skin, "big");
     private final Label subHeadLabel = new Label("Welcome "+ GameWare.getInstance().getPlayer().getName()+"!", skin, "big");
 
 //    Button texts
-    private final String singlePlayerBtnText = "Single player";
-    private final String multiPlayerBtnText = "Multi player";
+    private final String singlePlayerBtnText = "Single-Player";
+    private final String multiPlayerBtnText = "Multiplayer";
     private final String highScoreBtnText = "High Scores";
     private final String optionBtnText = "Options";
     private final String logOutBtnText = "Log out";
 
     private boolean multiBtnClicked = false;
     private LoadingText loadingText = new LoadingText();
+    private Dialog alertDialog;
 
     public MenuState(GameStateManager gsm) {
         super(gsm);
+
         makeStage();
+
+        try{
+            alerts = QueryIntermediate.getAlertsForPlayer(GameWare.getInstance().getPlayer().getId());
+            if(!alerts.isEmpty()){
+                QueryIntermediate.deleteAlertsForPlayer(GameWare.getInstance().getPlayer().getId());
+                makeAlertDialog(alerts);
+            }
+        }catch(NoSuchElementException e){
+        }catch (IOException e){
+            e.printStackTrace();
+        }
     }
 
 
@@ -59,6 +84,20 @@ public class MenuState extends State{
     }
 
 //    Make widgets methods
+
+    private void makeAlertDialog(List<Alert> alerts){
+        alertDialog = new Dialog("", skin, "dialog") {
+            public void result(Object obj) { }
+        };
+        String s = "Tournaments that finished:\n";
+        for (Alert a : alerts){
+            s += a.getTournamentId()+"\n";
+        }
+        alertDialog.text(s).pad(padding);
+        alertDialog.button("Okay", true).pad(padding); //sends "true" as the result
+        alertDialog.show(stage);
+    }
+
     private TextButton makeSinglePlayerBtn(){
         TextButton singlePlayerBtn = new TextButton(singlePlayerBtnText, skin);
         singlePlayerBtn.addListener(new ClickListener() {
diff --git a/frontend/core/src/com/gameware/game/states/PauseState.java b/frontend/core/src/com/gameware/game/states/PauseState.java
index a1fa1d007b2c9a0a264e57c7b1293689f4b2f3a2..26e83ed633f5dc523899373ce8b405f27a2fcbca 100644
--- a/frontend/core/src/com/gameware/game/states/PauseState.java
+++ b/frontend/core/src/com/gameware/game/states/PauseState.java
@@ -66,6 +66,7 @@ public class PauseState extends State {
             if(this.needsConfirmation) {
                 // User doesn't want to exit after all
                 if(this.confirmationBox.noPressed(touchX, touchY)) {
+                    if(GameWare.getInstance().getSoundEffects()){ pauseStateBtnSound.play(); }
                     this.needsConfirmation = false;
                 }
 
@@ -87,6 +88,7 @@ public class PauseState extends State {
 
                 // First step of exiting; user now needs to confirm the exit via the popup
                 if(this.exitButton.isPressed(touchX, touchY)){
+                    if(GameWare.getInstance().getSoundEffects()){ pauseStateBtnSound.play(); }
                     this.needsConfirmation = true;
                 }
             }
diff --git a/frontend/core/src/com/gameware/game/states/PlayStateTemplate.java b/frontend/core/src/com/gameware/game/states/PlayStateTemplate.java
index 069e060559940f3eb678e8b877d5988d0ca2fc78..6b0056286db271d3ae21a6f2b151bd8ee53c1eb4 100644
--- a/frontend/core/src/com/gameware/game/states/PlayStateTemplate.java
+++ b/frontend/core/src/com/gameware/game/states/PlayStateTemplate.java
@@ -22,6 +22,7 @@ public abstract class PlayStateTemplate extends State {
     private Round round = null;
     private Tournament tournament = null;
     private Round updatedRound = null;
+    private RoundCheck roundCheck = null;
     private PauseButton pauseButton;
     private LoadingText loadingText = new LoadingText();
     protected float totalGameTime = 30f;
@@ -79,14 +80,10 @@ public abstract class PlayStateTemplate extends State {
                 break;
             }
         }
-        RoundCheck rc = null;
         try {
             this.postScore(id);
-
             //Add new instance of the game into the HashMap in GameWare
             GameWare.getInstance().updateGameMap(id, this.getClass().getConstructor(GameStateManager.class).newInstance(gsm));
-
-            rc = QueryIntermediate.doRoundCheck(tournament.get_id());
         }catch(Exception e){
             e.printStackTrace();
         }
@@ -94,7 +91,7 @@ public abstract class PlayStateTemplate extends State {
         if(round == null) {
             //Singleplayer
             gsm.set(new ScoreState(gsm, this.score, new SinglePlayerSelectGameState(gsm)));
-        } else if(!rc.isActive() || (updatedRound.getTournamentPoints() != 0 && updatedRound.getRoundNr() == tournament.getTotalGames())){
+        } else if(!roundCheck.isActive() || (updatedRound.getTournamentPoints() != 0 && updatedRound.getRoundNr() == tournament.getTotalGames())){
             //Tournament finished
             gsm.set(new ScoreState(gsm, this.score, new FinishedTournamentState(gsm, tournament)));
         } else{
@@ -123,6 +120,7 @@ public abstract class PlayStateTemplate extends State {
         } else{
             List<ModelInterface> updatedRoundModels = QueryIntermediate.putRoundScore(round.get_id(),tournament.get_id(), this.score);
             updatedRound = (Round) updatedRoundModels.get(0);
+            roundCheck = (RoundCheck) updatedRoundModels.get(1);
         }
     }
 
diff --git a/frontend/core/src/com/gameware/game/states/SinglePlayerSelectGameState.java b/frontend/core/src/com/gameware/game/states/SinglePlayerSelectGameState.java
index fadaa86c33120880b73e610245996f98149baf2b..3449042b39ea6922ed98e7cf957cac411baa7fe7 100644
--- a/frontend/core/src/com/gameware/game/states/SinglePlayerSelectGameState.java
+++ b/frontend/core/src/com/gameware/game/states/SinglePlayerSelectGameState.java
@@ -74,7 +74,7 @@ public class SinglePlayerSelectGameState extends State {
 //    Make widgets methods
     private Table makeInnerTable(){
         Table innerTable = new Table();
-        innerTable.setBackground(makeColorBackground(scrollPaneBGColor));
+        innerTable.setBackground(backgroundTableBlueRounded);
         innerTable.columnDefaults(0).spaceRight(spacingLittle);
 
         if(games.size()==0){
@@ -82,6 +82,9 @@ public class SinglePlayerSelectGameState extends State {
             innerTable.add(noGamesLabel).pad(padding);
         }else {
             for (Game g : games) {
+                if(GameWare.getInstance().getGameIdToPlayState().get(g.getId()) == null){
+                    continue;
+                }
                 innerTable.add(new Image(GameWare.getInstance().getGameIdToPlayState().get(g.getId()).screenshot)).width(imageWidthAndHeigh).height(imageWidthAndHeigh).pad(spacingLittle);
 
                 Table innerInnerTable = new Table();
diff --git a/frontend/core/src/com/gameware/game/states/State.java b/frontend/core/src/com/gameware/game/states/State.java
index 5cdb709838a1dba973aa70e16f1196f1ba7e8f33..1ba092a55dba1a37ac51445e2f3680e5a9a442a5 100644
--- a/frontend/core/src/com/gameware/game/states/State.java
+++ b/frontend/core/src/com/gameware/game/states/State.java
@@ -47,11 +47,13 @@ public abstract class State {
     protected TextureRegionDrawable backgroundScore = new TextureRegionDrawable(new TextureRegion(new Texture("bg_score.jpg")));
 //    protected TextureRegionDrawable buttonDisabledDrawable = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("glassy/raw/button-disabled.png"))));
     protected TextureRegionDrawable backgroundFinTourn = new TextureRegionDrawable(new TextureRegion(new Texture("bg1_finTourn.jpg")));
+    protected TextureRegionDrawable backgroundTableBlueRounded = new TextureRegionDrawable(new TextureRegion(new Texture("tableBGRounded.png")));
 
 //    Sound Effects
     protected Sound buttonPressSound;
     protected Sound checkBoxSound;
     protected Sound pauseResumeBtnSound;
+    protected Sound pauseStateBtnSound;
 
 //    Variables
     private boolean firstTimeRunningUpdate = true;
@@ -63,7 +65,7 @@ public abstract class State {
         this.buttonPressSound = Gdx.audio.newSound(Gdx.files.internal("sfx/button_press.ogg"));
         this.checkBoxSound = Gdx.audio.newSound(Gdx.files.internal("sfx/check_box.ogg"));
         this.pauseResumeBtnSound = Gdx.audio.newSound(Gdx.files.internal("sfx/pause_button.ogg"));
-
+        this.pauseStateBtnSound = Gdx.audio.newSound(Gdx.files.internal("sfx/small_click.ogg"));
 
         Gdx.input.setInputProcessor(stage);
     }
diff --git a/frontend/core/src/com/gameware/game/states/TournamentHighScoreState.java b/frontend/core/src/com/gameware/game/states/TournamentHighScoreState.java
index 727904b6cce9b7a58b765aa48fe55f63a086fd96..8e5d2dab7c31423db27769047c7f145bfa1f782b 100644
--- a/frontend/core/src/com/gameware/game/states/TournamentHighScoreState.java
+++ b/frontend/core/src/com/gameware/game/states/TournamentHighScoreState.java
@@ -76,7 +76,7 @@ public class TournamentHighScoreState extends State{
         Table innerTable = new Table();
         innerTable.pad(padding);
         innerTable.defaults().space(spacingLittle);
-        innerTable.setBackground(makeColorBackground(scrollPaneBGColor));
+        innerTable.setBackground(backgroundTableBlueRounded);
 
         innerTable.add(colOneLabel).expandX();
         innerTable.add(colTwoLabel).expandX();
diff --git a/frontend/core/src/com/gameware/game/states/ViewHighScoreForGameState.java b/frontend/core/src/com/gameware/game/states/ViewHighScoreForGameState.java
index d31661ecf3536f915d7f86e7f8b8ce444743bad0..252427ac4c08283ccf51a516128bd45cf386fd7b 100644
--- a/frontend/core/src/com/gameware/game/states/ViewHighScoreForGameState.java
+++ b/frontend/core/src/com/gameware/game/states/ViewHighScoreForGameState.java
@@ -82,7 +82,7 @@ public class ViewHighScoreForGameState extends State {
 
         rootTable.row();
         Table secondInnerTable = new Table();
-        secondInnerTable.setBackground(makeColorBackground(Color.SKY));
+        secondInnerTable.setBackground(backgroundTableBlueRounded);
 
         secondInnerTable.add(playerLabel).spaceTop(spacingLittle).pad(padding);
         secondInnerTable.add(playerScoreLabel).spaceTop(spacingLittle).pad(padding);
@@ -109,7 +109,7 @@ public class ViewHighScoreForGameState extends State {
 
     private Table createHighScoreList() {
         Table innerTable = new Table();
-        innerTable.setBackground(makeColorBackground(Color.SKY));
+        innerTable.setBackground(backgroundTableBlueRounded);
         innerTable.defaults().spaceRight(spacingLittle);
 
         if(isNoHS){
diff --git a/frontend/core/src/com/gameware/game/states/ViewHighScoreState.java b/frontend/core/src/com/gameware/game/states/ViewHighScoreState.java
index 9fb7bf698b7ab6f0dcf3f060d14c96c02b765043..2eab3b0b21a3a414a1e2df1d18d84a788a5ba792 100644
--- a/frontend/core/src/com/gameware/game/states/ViewHighScoreState.java
+++ b/frontend/core/src/com/gameware/game/states/ViewHighScoreState.java
@@ -85,13 +85,16 @@ public class ViewHighScoreState extends State {
 //    Make widgets methods
     private Table makeInnerTable(){
         Table innerTable = new Table();
-        innerTable.setBackground(makeColorBackground(scrollPaneBGColor));
+        innerTable.setBackground(backgroundTableBlueRounded);
 
         if(games.size()==0){
 //            If the try failed, and no games found
             innerTable.add(noGamesLabel).pad(padding);
         }else {
             for (Game g : games) {
+                if(GameWare.getInstance().getGameIdToPlayState().get(g.getId()) == null){
+                    continue;
+                }
                 innerTable.add(new Image(GameWare.getInstance().getGameIdToPlayState().get(g.getId()).screenshot)).width(imageWidthAndHeigh).height(imageWidthAndHeigh).pad(spacingLittle);
 
                 Table innerInnerTable = new Table();
diff --git a/frontend/core/src/com/gameware/game/states/ViewTournamentState.java b/frontend/core/src/com/gameware/game/states/ViewTournamentState.java
index 3ff31c4b016428345d768316b9f68f6a5a75877f..ff5772ce147d676a860657793176fbaf8626581a 100644
--- a/frontend/core/src/com/gameware/game/states/ViewTournamentState.java
+++ b/frontend/core/src/com/gameware/game/states/ViewTournamentState.java
@@ -16,9 +16,12 @@ import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
 import com.gameware.game.GameWare;
 import com.gameware.game.QueryIntermediate;
 import com.gameware.game.models.Round;
+import com.gameware.game.models.RoundCheck;
 import com.gameware.game.models.Tournament;
 import com.gameware.game.sprites.LoadingText;
 
+import java.io.IOException;
+
 public class ViewTournamentState extends State {
 
 //    Data
@@ -28,6 +31,7 @@ public class ViewTournamentState extends State {
 //    Labels
     private Label disabledPlayBtnFeedback = new Label("Waiting for other players to finish", skin, "big");
     private Label titleLabel = new Label("N/A", skin, "big");
+    private Label roundDeadline = new Label("N/A", skin, "big");
 
 //    Texts
     private final String backBtnText = "Back";
@@ -39,7 +43,6 @@ public class ViewTournamentState extends State {
     private final String leaveDialogText = "Are you sure want to\nleave ";
 
 //    Variables
-    private final int padding = 50;
     private final float playBtnWidth = buttonWidth*1.4f;
     private final float playBtnHeight = buttonHeight*1.2f;
 
@@ -57,6 +60,7 @@ public class ViewTournamentState extends State {
         this.tournament = tournament;
         this.round = r;
         titleLabel.setText(tournament.getName());
+        roundDeadline.setText("Round deadline\n"+round.getDeadlineDate().toLocaleString());
         makeStage();
     }
 
@@ -65,24 +69,24 @@ public class ViewTournamentState extends State {
         Table rootTable = makeRootTable();
 
         titleLabel.setFontScale(titleFontBigScale);
-        rootTable.add(titleLabel).expandY().top();
+        rootTable.add(titleLabel).expandY().top().colspan(2);
         rootTable.row();
 
         disabledPlayBtnFeedback.getColor().a = 0;
-        rootTable.add(disabledPlayBtnFeedback);
+        rootTable.add(disabledPlayBtnFeedback).colspan(2);
         rootTable.row();
 
-        rootTable.add(makePlayBtn()).size(playBtnWidth, playBtnHeight);
+        rootTable.add(makePlayBtn()).size(playBtnWidth, playBtnHeight).colspan(2);
         rootTable.row();
 
         PlayStateTemplate state = GameWare.getInstance().getGameIdToPlayState().get(round.getGameId());
-        rootTable.add(new Image(state.screenshot)).spaceBottom(spacingMedium);
+        rootTable.add(new Image(state.screenshot)).spaceBottom(spacingMedium).colspan(2);
         rootTable.row();
 
-        rootTable.add(new Label(nrPlayersText+" "+tournament.getPlayers().size(), skin));
+        rootTable.add(new Label(nrPlayersText+" "+tournament.getCurrentPlayers(), skin)).colspan(2);
         rootTable.row();
 
-        rootTable.add(new Label(roundsLeftText+" "+((tournament.getRoundsPerGame()*tournament.getGames().size())-tournament.getCurrentRound()+1), skin));
+        rootTable.add(new Label(roundsLeftText+" "+((tournament.getRoundsPerGame()*tournament.getGames().size())-tournament.getCurrentRound()+1), skin)).colspan(2);
         rootTable.row();
 
         Table innerTable = new Table();
@@ -90,10 +94,13 @@ public class ViewTournamentState extends State {
         leaveBtn.addListener(new LeaveClickListener());
         innerTable.add(leaveBtn).size(buttonWidth, buttonHeight).spaceRight(spacingLittle);
         innerTable.add(makeViewPointsBtn()).size(buttonWidth, buttonHeight);
-        rootTable.add(innerTable);
+
+        rootTable.add(innerTable).colspan(2);
         rootTable.row();
 
         rootTable.add(makeBackBtn()).expand().bottom().left();
+        roundDeadline.setFontScale(0.8f);
+        rootTable.add(roundDeadline).expand().bottom().right();
 
         stage.addActor(rootTable);
         makeDialog();
@@ -236,10 +243,23 @@ public class ViewTournamentState extends State {
 
     private void handlePlayBtnClick(){
         if(GameWare.getInstance().getSoundEffects()){ buttonPressSound.play(); }
-        PlayStateTemplate state = GameWare.getInstance().getGameIdToPlayState().get(round.getGameId());
-        state.setTournament(tournament);
-        state.setRound(round);
-        gsm.set(state);
+
+        RoundCheck rc = null;
+        try {
+            rc = QueryIntermediate.doRoundCheck(tournament.get_id());
+        }catch(IOException e){
+            e.printStackTrace();
+        }
+        if(rc != null && !rc.isActive()){
+                FinishedTournamentState s = new FinishedTournamentState(gsm, tournament);
+                s.makeDialogTimeOut();
+                gsm.set(s);
+        } else {
+            PlayStateTemplate state = GameWare.getInstance().getGameIdToPlayState().get(round.getGameId());
+            state.setTournament(tournament);
+            state.setRound(round);
+            gsm.set(state);
+        }
     }
 
     private void handleViewPointsBtnClick(){