Index: pages/api/blackjack/index.js
===================================================================
--- pages/api/blackjack/index.js	(revision 87614a539b5a6d95f9aee8012bfdef4edeeb2fb5)
+++ pages/api/blackjack/index.js	(revision 87614a539b5a6d95f9aee8012bfdef4edeeb2fb5)
@@ -0,0 +1,611 @@
+import { v4 as uuidv4 } from 'uuid';
+
+import axios from 'axios';
+
+require('dotenv').config();
+
+/**
+ * ********************* BEGIN OF DEALING WITH GAME STATES *********************
+ */
+
+const singleDeck = ["SA", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "SX", "SJ", "SQ", "SK",
+                    "HA", "H2", "H3", "H4", "H5", "H6", "H7", "H8", "H9", "HX", "HJ", "HQ", "HK",
+                    "CA", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CX", "CJ", "CQ", "CK",
+                    "DA", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DX", "DJ", "DQ", "DK"    ];
+
+/* We are using 5 decks */
+const deck = singleDeck.concat(singleDeck).concat(singleDeck).concat(singleDeck).concat(singleDeck);
+
+let game = {
+  deck: [...deck],
+  status: '_1_room_created',
+  playerCards: [],
+  dealerName: 'Lazar',
+  dealerCards: [],
+  initialBet: 0,
+  sideBet: 0,
+  sideBetName: '',
+  outcome: '',
+  earnings: 0,              // positive for draw, 2x for win, negative for loss.
+  sideBetOutcome: '',
+  sideBetEarnings: 0,
+}
+
+let rooms = []
+
+/**
+ * Replace deck if empty
+ */
+function checkDeckSize(game) {
+  if (game.deck.length === 0) {
+    game.deck = [...deck];
+  }
+}
+
+/**
+ * Draw a SINGLE random card
+ */
+function drawASingleCard(room) {
+  checkDeckSize(room);
+  let idx = Math.floor(Math.random() * room.deck.length);
+  let card = room.deck[idx];
+
+  room.deck.splice(idx, 1);
+
+  return card;
+}
+
+/**
+ * Deal the initial hand of cards
+ */
+function getInitialCards(room) {
+  room.playerCards.push(drawASingleCard(room));
+  room.playerCards.push(drawASingleCard(room));
+
+  room.dealerCards.push(drawASingleCard(room));
+  room.dealerCards.push(drawASingleCard(room));
+}
+
+function calculateEarnings(room) {
+  let betEarnings = 0;
+
+  if (room.outcome === 'draw') {
+    betEarnings = room.initialBet;
+  }
+  else if (room.outcome === 'player_won' || room.outcome === 'dealer_busted') {
+    betEarnings = 2 * room.initialBet;
+  }
+  else if (room.outcome === 'player_lost' || room.outcome === 'player_busted') {
+    betEarnings = -1 * room.initialBet;
+  }
+
+  return betEarnings;
+}
+
+function calculateSideBetEarnings(room) {
+  let sideBetEarnings = -1 * room.sideBet;
+
+  if (room.sideBetName != '') {
+    if (room.sideBetName === 'mixed_pair') {
+      if (checkIfSameValue(room.playerCards)) {
+        sideBetEarnings = room.sideBet * 5;
+      }
+    }
+    else if (room.sideBetName === 'coloured_pair') {
+      if (checkIfSameValue(room.playerCards) && checkIfSameColour(room.playerCards)) {
+        sideBetEarnings = room.sideBet * 12;
+      }
+    }
+    else if (room.sideBetName === 'perfect_pair') {
+      if (checkIfSameValue(room.playerCards) && checkIfSameSuit(room.playerCards)) {
+        sideBetEarnings = room.sideBet * 25;
+      }
+    }
+    else if (room.sideBetName === 'flush') {
+      const tmpCards = room.playerCards.slice().concat(room.dealerCards[0]);
+      if (checkIfSameSuit(tmpCards)) {
+        sideBetEarnings = room.sideBet * 5;
+      }
+    }
+    else if (room.sideBetName === 'straight') {
+      const tmpCards = room.playerCards.slice().concat(room.dealerCards[0]);
+      if (checkIfStraight(tmpCards)) {
+        sideBetEarnings = room.sideBet * 10;
+      }
+    }
+    else if (room.sideBetName === 'three_of_a_kind') {
+      const tmpCards = room.playerCards.slice().concat(room.dealerCards[0]);
+      if (checkIfSameValue(tmpCards)) {
+        sideBetEarnings = room.sideBet * 30;
+      }
+    }
+    else if (room.sideBetName === 'straight_flush') {
+      const tmpCards = room.playerCards.slice().concat(room.dealerCards[0]);
+      if (checkIfStraight(tmpCards) && checkIfSameSuit(tmpCards)) {
+        sideBetEarnings = room.sideBet * 40;
+      }
+    }
+    else if (room.sideBetName === 'suited_triple') {
+      const tmpCards = room.playerCards.slice().concat(room.dealerCards[0]);
+      if (checkIfSameSuit(tmpCards) && checkIfSameValue(tmpCards)) {
+        sideBetEarnings = room.sideBet * 100;
+      }
+    }
+  }
+
+  return sideBetEarnings;
+}
+
+/**
+ * Set up a room
+ */
+function createARoom(session_id) {
+  let room = {
+    ...game, playerCards: [...game.playerCards], dealerCards: [...game.dealerCards],
+  }
+
+  rooms[session_id] = room;
+}
+/**
+ * ********************* END OF DEALING WITH GAME STATES *********************
+ */
+
+/**
+ * ********************* BEGIN OF REQUEST HANDLER *********************
+ */
+export default async function handler(req, res) {
+  /**
+   * GET method
+   */
+   if (req.method === 'GET') {
+    /**
+     * /---------------------- GET ----------------------/
+     * @action play_again
+     * @param session_id
+     */
+    if (req.query.action === 'play_again' && req.query?.session_id) {
+      const session_id = req.query.session_id;
+
+      if (rooms[session_id] !== undefined && rooms[session_id].status.substr(1, 1) === '5') {
+        rooms[session_id] = {...game, playerCards: [...game.playerCards], dealerCards: [...game.dealerCards]};
+
+        res.json({
+          success: true,
+          game: rooms[session_id],
+        })
+
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
+     * @action stand
+     * @param session_id
+     */
+    if (req.query.action === 'stand' && req.query?.session_id) {
+      const session_id = req.query.session_id;
+
+      if (rooms[session_id] !== undefined && rooms[session_id].status.substr(1, 1) === '4') {
+        const room = rooms[session_id];
+
+        while (calculateHandValue(room.dealerCards) < 17) {
+          room.dealerCards.push(drawASingleCard(room));
+        }
+
+        room.status = '_5_game_over';
+
+        if (calculateHandValue(room.dealerCards) > 21) {
+          room.outcome = 'dealer_busted';
+        }
+        else if (calculateHandValue(room.playerCards) > calculateHandValue(room.dealerCards)) {
+          room.outcome = 'player_won';
+        }
+        else if (calculateHandValue(room.playerCards) < calculateHandValue(room.dealerCards)) {
+          room.outcome = 'player_lost';
+        }
+        else {
+          room.outcome = 'draw';
+        }
+
+        room.earnings = calculateEarnings(room);
+
+        rooms[session_id] = room;
+
+        axios.get(`${process.env.HOME_URL}/api/postgre/?action=add_credits&session_id=${session_id}&credits=${room.earnings}&game=blackjack&outcome=${room.outcome}`).then(postgreRes => {
+          if (postgreRes.data?.success) {
+            res.json({
+              success: true,
+              status: rooms[session_id].status,
+              playerCards: rooms[session_id].playerCards,
+              dealerCards: rooms[session_id].dealerCards,
+              outcome: rooms[session_id].outcome,
+              earnings: rooms[session_id].earnings,
+              credits: postgreRes.data?.credits,
+            })
+          }
+          else {
+            res.json({
+              success: false,
+            })
+          }
+        });
+
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
+     * @action hit_a_card
+     * @param session_id
+     */
+    if (req.query.action === 'hit_a_card' && req.query?.session_id) {
+      const session_id = req.query.session_id;
+
+      if (rooms[session_id] !== undefined && rooms[session_id].status.substr(1, 1) === '4') {
+        const room = rooms[session_id];
+
+        room.playerCards.push(drawASingleCard(room));
+
+        rooms[session_id] = room;
+
+        if (calculateHandValue(room.playerCards) > 21) {
+          room.status = '_5_game_over';
+          room.outcome = 'player_busted';
+
+          room.earnings = calculateEarnings(room);
+
+          rooms[session_id] = room;
+
+          axios.get(`${process.env.HOME_URL}/api/postgre/?action=add_credits&session_id=${session_id}&credits=${room.earnings}&game=blackjack&outcome=${room.outcome}`).then(postgreRes => {
+            if (postgreRes.data?.success) {
+              res.json({
+                success: true,
+                status: rooms[session_id].status,
+                playerCards: rooms[session_id].playerCards,
+                outcome: rooms[session_id].outcome,
+                earnings: rooms[session_id].earnings,
+                credits: postgreRes.data?.credits,
+              })
+            }
+            else {
+              res.json({
+                success: false,
+              })
+            }
+          });
+        }
+        else {
+          res.json({
+            success: true,
+            status: rooms[session_id].status,
+            playerCards: rooms[session_id].playerCards,
+            outcome: rooms[session_id].outcome,
+            earnings: rooms[session_id].earnings,
+          })
+        }
+
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+
+     /**
+     * /---------------------- GET ----------------------/
+     * @action get_initial_cards
+     * @param session_id
+     */
+    if (req.query.action === 'get_initial_cards' && req.query?.session_id) {
+      const session_id = req.query.session_id;
+
+      if (rooms[session_id] !== undefined && rooms[session_id].status.substr(1, 1) === '3') {
+        const room = rooms[session_id];
+
+        getInitialCards(room);
+
+        room.status = '_4_cards_on_the_table';
+
+        rooms[session_id] = room;
+
+        if (room.sideBetName !== '' && room.sideBetName !== 'none') {
+          room.sideBetEarnings = calculateSideBetEarnings(room);
+          room.sideBetOutcome = room.sideBetEarnings > 0 ? 'side_bet_won' : 'side_bet_lost';
+
+          rooms[session_id] = room;
+
+          axios.get(`${process.env.HOME_URL}/api/postgre/?action=add_credits&session_id=${session_id}&credits=${room.sideBetEarnings}`).then(postgreRes => {
+            if (postgreRes.data?.success) {
+              res.json({
+                success: true,
+                status: rooms[session_id].status,
+                playerCards: rooms[session_id].playerCards,
+                dealerCards: Array(rooms[session_id].dealerCards[0]).concat('back'),
+                sideBetOutcome: rooms[session_id].sideBetOutcome,
+                sideBetEarnings: rooms[session_id].sideBetEarnings,
+                credits: postgreRes.data?.credits,
+              })
+            }
+            else {
+              res.json({
+                success: false,
+              })
+            }
+          });
+        }
+        else {
+          res.json({
+            success: true,
+            status: rooms[session_id].status,
+            playerCards: rooms[session_id].playerCards,
+            dealerCards: Array(rooms[session_id].dealerCards[0]).concat('back'),
+            sideBetOutcome: rooms[session_id].sideBetOutcome,
+            sideBetEarnings: rooms[session_id].sideBetEarnings,
+          })
+        }
+
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
+     * @action make_side_bet
+     * @param session_id
+     * @param bet
+     * @param betName
+     */
+     if (req.query.action === 'make_side_bet' && req.query?.session_id && req.query?.bet && req.query?.betName) {
+      const session_id = req.query.session_id;
+
+      if (rooms[session_id] !== undefined && rooms[session_id].status.substr(1, 1) === '2') {
+        if (req.query?.skip !== 'true' && parseInt(req.query.bet) <= 0) {
+            return ;
+        }
+
+        const room = rooms[session_id];
+
+        room.sideBet = parseInt(req.query.bet);
+        room.sideBetName = req.query.betName;
+        room.status = '_3_made_side_bet';
+
+        rooms[session_id] = room;
+
+        res.json({
+          success: true,
+          status: rooms[session_id].status,
+        })
+        
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+    
+    /**
+     * /---------------------- GET ----------------------/
+     * @action make_initial_bet
+     * @param session_id
+     * @param bet
+     */
+    if (req.query.action === 'make_initial_bet' && req.query?.session_id && req.query?.bet) {
+      const session_id = req.query.session_id;
+
+      if (rooms[session_id] !== undefined && rooms[session_id].status.substr(1, 1) === '1') {
+        if (parseInt(req.query.bet) <= 0) return ;
+
+        const room = rooms[session_id];
+
+        room.initialBet = parseInt(req.query.bet);
+        room.status = '_2_made_initial_bet';
+
+        rooms[session_id] = room;
+
+        res.json({
+          success: true,
+          status: rooms[session_id].status,
+        })
+
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
+     * @action remove_room
+     * @param session_id
+     */
+    if (req.query.action === 'remove_room' && req.query?.session_id) {
+      const session_id = req.query.session_id;
+
+      if (rooms[session_id] !== undefined) {
+        delete rooms[session_id];
+      }
+      
+      res.json({
+        success: true,
+      })
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
+     * @action get_player_info_on_enter
+     * @param session_id
+     */
+    if (req.query.action === 'get_player_info_on_enter' && req.query?.session_id) {
+      const session_id = req.query.session_id;
+
+      if (rooms[session_id] !== undefined) {
+
+      }
+      else {
+        createARoom(session_id);
+      }
+
+      let dealerCardsTmp = [];
+      if (rooms[session_id].status.substr(1, 1) != '1') { // 5 == game_over
+        rooms[session_id].dealerCards.forEach((card, i) => {
+          if (i === 0) {
+            dealerCardsTmp.push(card);
+          }
+          else {
+            dealerCardsTmp.push('back');
+          }
+        })
+      }
+
+      res.json({
+        success: true,
+        status: rooms[session_id].status,
+        initialBet: rooms[session_id].initialBet,
+        sideBet: rooms[session_id].sideBet,
+        sideBetName: rooms[session_id].sideBetName,
+        playerCards: rooms[session_id].playerCards,
+        dealerCards: dealerCardsTmp,
+        outcome: rooms[session_id].outcome,
+        earnings: rooms[session_id].earnings,
+      })
+    }
+  }
+}
+/**
+ * ********************* END OF REQUEST HANDLER *********************
+ */
+
+/**
+ * ********************* BEGIN OF FUNCTIONS THAT CHECK CARD COMBINATIONS *********************
+ */
+
+function calculateHandValue(cards) {
+  let value = 0;
+  let aces = 0;
+  for (let i = 0; i < cards.length; i++) {
+    let card = cards[i];
+    if (card.substring(1) === 'A') {
+      value += 11;
+      aces++;
+    } else if (card.substring(1) === 'X' || card.substring(1) === 'J' || card.substring(1) === 'Q' || card.substring(1) === 'K') {
+      value += 10;
+    } else {
+      value += parseInt(card.substring(1));
+    }
+  }
+  while (value > 21 && aces > 0) {
+    value -= 10;
+    aces--;
+  }
+  return value;
+}
+
+function checkIfSameValue(cards) {
+  for (let i = 1; i < cards.length; i++) {
+    if (cards[i][1] !== cards[i-1][1]) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+function checkIf2CardsAreSameColour(card1, card2) {
+  if (card1[0] === card2[0]) return true;
+  if (card1[0] === 'H' && card2[0] === 'D') return true;
+  if (card1[0] === 'D' && card2[0] === 'H') return true;
+  if (card1[0] === 'S' && card2[0] === 'C') return true;
+  if (card1[0] === 'C' && card2[0] === 'S') return true;
+  return false;
+}
+
+function checkIfSameColour(cards) {
+  for (let i = 1; i < cards.length; i++) {
+    if (!checkIf2CardsAreSameColour(cards[i], cards[i-1])) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+function checkIfSameSuit(cards) {
+  for (let i = 1; i < cards.length; i++) {
+    if (cards[i][0] !== cards[i-1][0]) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+function checkIfStraight(cards) {
+  let values = ['A', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'J', 'Q', 'K'];
+
+  let valuesInCards = [];
+  for (let i = 0; i < cards.length; i++) {
+    valuesInCards.push(cards[i][1]);
+  }
+
+  let temp = values.reduce((c, v, i) => Object.assign(c, {[v]: i}), {});
+
+  valuesInCards = valuesInCards.sort((a, b) => temp[a] - temp[b]);
+
+  let idx = values.indexOf(valuesInCards[0]);
+
+  let straight = true;
+
+  for (let i = 0; i < valuesInCards.length; i++) {
+    if (valuesInCards[i] !== values[idx]) {
+      straight = false;
+      break; 
+    }
+
+    idx++;
+    if (idx >= temp.length) {
+      straight = false;
+      break;
+    }
+  }
+
+  if (straight) {
+    return true;
+  }
+
+  values = ['2', '3', '4', '5', '6', '7', '8', '9', 'X', 'J', 'Q', 'K', 'A'];
+  temp = values.reduce((c, v, i) => Object.assign(c, {[v]: i}), {});
+
+  valuesInCards = valuesInCards.sort((a, b) => temp[a] - temp[b]);
+
+  idx = values.indexOf(valuesInCards[0]);
+
+  for (let i = 0; i < valuesInCards.length; i++) {
+    if (valuesInCards[i] !== values[idx]) return false;
+
+    idx++;
+    if (idx >= temp.length) return false;
+  }
+
+  return true;
+}
+/**
+ * ********************* END OF FUNCTIONS THAT CHECK CARD COMBINATIONS *********************
+ */
Index: pages/api/hello.js
===================================================================
--- pages/api/hello.js	(revision 6568bdeae3dbd082b040ec9b3d752c195313b7e5)
+++ 	(revision )
@@ -1,5 +1,0 @@
-// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
-
-export default function handler(req, res) {
-  res.status(200).json({ name: 'John Doe' })
-}
Index: pages/api/postgre/index.js
===================================================================
--- pages/api/postgre/index.js	(revision 87614a539b5a6d95f9aee8012bfdef4edeeb2fb5)
+++ pages/api/postgre/index.js	(revision 87614a539b5a6d95f9aee8012bfdef4edeeb2fb5)
@@ -0,0 +1,450 @@
+import { v4 as uuidv4 } from 'uuid';
+
+import axios from 'axios';
+
+require('dotenv').config();
+
+const crypto = require('crypto');
+
+const Pool = require('pg').Pool
+const pool = new Pool({
+  connectionString: 'postgres://postgres:postgres@db/postgres'
+});
+
+const sessions = []
+// example session
+// const session = {
+//   id,
+//   displayName,
+//   username,
+//   credits,
+//   lastActivity,
+// }
+
+// update credits in database
+// setInterval(() => {
+//   sessions.filter(session => Date.now() - session.lastActivity > 5*60*1000).forEach(session => {
+//     pool.query('UPDATE players SET credits = $1 WHERE username = $2', [session.credits, session.username], (error, results) => {
+//       if (error) throw error;
+//     });
+//   });
+// }, 5*60*1000)
+
+export default function handler(req, res) {
+  /**
+   * GET method
+   */
+  if (req.method === 'GET') {
+    /**
+     * /---------------------- GET ----------------------/
+     * @action give_credits
+     * @param session_id
+     * @param credits
+     */
+    if (req.query?.action === 'add_credits' && req.query?.session_id && req.query?.credits) {
+      const session_id = req.query.session_id
+      const session = sessions.find(session => session.id === session_id)
+
+      if (session) {
+        session.lastActivity = Date.now();
+
+        if (parseInt(req.query.credits) > 0) {
+          session.credits = session.credits + parseInt(req.query.credits)
+
+          pool.query('UPDATE players SET credits = $1 WHERE username = $2', [session.credits, session.username], (error, results) => {
+            if (error) throw error;
+          });
+        }
+
+        if (req.query?.dont_update_stats) {
+          // continue
+        } else {
+          pool.query('SELECT * FROM stats WHERE username = $1', [session.username], (error, results) => {
+            if (error) throw error;
+
+            if (results.rows.length > 0) {
+              const stats = results.rows[0]
+
+              if (parseInt(req.query.credits) > 0) {
+                pool.query('UPDATE stats SET money_earned = $1 WHERE username = $2', [parseInt(stats.money_earned) + parseInt(req.query.credits), session.username], (error, results) => {
+                  if (error) throw error;
+                });
+              }
+
+              if (req.query?.game === 'blackjack') {
+                if (req.query?.outcome === 'player_busted' || req.query?.outcome === 'player_lost') {
+                  pool.query('UPDATE stats SET blackjack_games = $1 WHERE username = $2', [parseInt(stats.blackjack_games) + 1, session.username], (error, results) => {
+                    if (error) throw error;
+                  });
+                }
+                else if (req.query?.outcome === 'dealer_busted' || req.query?.outcome === 'player_won') {
+                  pool.query('UPDATE stats SET blackjack_games = $1, blackjack_won_games = $2 WHERE username = $3', [parseInt(stats.blackjack_games) + 1, parseInt(stats.blackjack_won_games) + 1, session.username], (error, results) => {
+                    if (error) throw error;
+                  });
+                }
+              }
+            }
+          });
+        }
+          
+        res.json({
+          success: true,
+          credits: session.credits,
+        })
+
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
+     * @action take_credits
+     * @param session_id
+     * @param credits
+     */
+    if (req.query?.action === 'take_credits' && req.query?.session_id && req.query?.credits) {
+      const session_id = req.query.session_id
+      const session = sessions.find(session => session.id === session_id)
+
+      if (session) {
+        session.lastActivity = Date.now();
+
+        session.credits = session.credits - parseInt(req.query.credits)
+
+        pool.query('UPDATE players SET credits = $1 WHERE username = $2', [session.credits, session.username], (error, results) => {
+          if (error) throw error;
+        });
+
+        pool.query('SELECT * FROM stats WHERE username = $1', [session.username], (error, results) => {
+          if (error) throw error;
+
+          if (results.rows.length > 0) {
+            const stats = results.rows[0]
+
+            pool.query('UPDATE stats SET money_bet = $1 WHERE username = $2', [parseInt(stats.money_bet) + parseInt(req.query.credits), session.username], (error, results) => {
+              if (error) throw error;
+            });
+          }
+        });
+
+        res.json({
+          success: true,
+          credits: session.credits,
+        })
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
+     * @action get_stats
+     * @param session_id
+     */
+    if (req.query?.action === 'get_stats' && req.query?.session_id) {
+      const session_id = req.query.session_id
+      const session = sessions.find(session => session.id === session_id)
+
+      if (session) {
+        session.lastActivity = Date.now();
+
+        pool.query('SELECT * FROM stats WHERE username = $1', [session.username], (error, results) => {
+          if (error) throw error;
+
+          if (results.rows.length > 0) {
+            res.json({
+              success: true,
+              stats: results.rows[0],
+            })
+          }
+          else {
+            res.json({
+              success: false,
+            })
+          }
+        });
+        
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
+     * @action get_player_info_on_enter
+     * @param session_id
+     */
+    if (req.query?.action === 'get_player_info_on_enter' && req.query?.session_id) {
+      const session_id = req.query.session_id
+      const session = sessions.find(session => session.id === session_id)
+
+      if (session) {
+        res.json({
+          success: true,
+          displayName: session.displayName,
+          session_id: session.id,
+          credits: session.credits,
+        })
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
+     * @action check_if_logged_in
+     * @param session_id
+     */
+     if (req.query?.action === 'check_if_logged_in' && req.query?.session_id) {
+      const session_id = req.query.session_id
+      const session = sessions.find(session => session.id === session_id)
+
+      if (session) {
+        res.json({
+          success: true,
+          displayName: session.displayName,
+          session_id: session.id,
+          credits: session.credits,
+        })
+        return ;
+      }
+
+      res.json({
+        success: false,
+      })
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
+     * @action logout
+     * @param session_id
+     */
+    if (req.query?.action === 'logout' && req.query?.session_id) {
+      const session_id = req.query.session_id
+      const session = sessions.find(session => session.id === session_id)
+
+      if (session) {
+        pool.query('UPDATE players SET credits = $1 WHERE username = $2', [session.credits, session.username], (error, results) => {
+          if (error) throw error;
+        });
+
+        sessions.splice(sessions.indexOf(session), 1);
+
+        axios.get(`${process.env.HOME_URL}/api/blackjack/?action=remove_room&session_id=${session_id}`);
+      }
+
+      res.json({
+        success: true,
+        message: 'Successfully logged out',
+      })
+    }
+  }
+
+  /**
+   * POST method
+   */
+  if (req.method === 'POST') {
+    const { body } = req;
+
+    /**
+     * /---------------------- POST ----------------------/
+     * @action register
+     * @param username
+     * @param displayName
+     * @param password
+     */
+    if (body?.action === 'register') {
+      // checks
+      if (body?.username == "undefined" || body?.username == "null" || body?.username == "") {
+        res.json({
+          success: false,
+          message: 'Username is required',
+        });
+        return ;
+      }
+      if (/[^a-zA-Z]/g.test(body?.username)) {
+        res.json({
+          success: false,
+          message: 'Username must contain only letters',
+        })
+        return ;
+      }
+      if (body?.displayName == "undefined" || body?.displayName == "null" || body?.displayName == "") {
+        res.json({
+          success: false,
+          message: 'Display name is required',
+        });
+        return ;
+      }
+      if (body?.displayName?.toLowerCase() === "guest") {
+        res.json({
+          success: false,
+          message: 'Display name cannot be guest',
+        });
+        return ;
+      }
+      if (body?.password == "undefined" || body?.password == "null" || body?.password == "") {
+        res.json({
+          success: false,
+          message: 'Password is required',
+        });
+        return ;
+      }
+
+      // everything's okay
+      body.username = body.username.toLowerCase()
+
+      // hash password
+      const salt = crypto.randomBytes(16).toString('hex');
+      const hashedPassword = crypto.pbkdf2Sync(body.password, salt, 1000, 64, 'sha512').toString('hex');
+
+      // check if user already exists
+      pool.query('SELECT * FROM users WHERE username = $1', [body.username], (error, results) => {
+        if (error) throw error;
+
+        if (results.rows.length > 0) {
+          res.json({
+            success: false,
+            message: 'Username already exists',
+          });
+          return ;
+        }
+
+        // store user in database
+        pool.query('INSERT INTO users (username, password, salt) VALUES ($1, $2, $3)', [body.username, hashedPassword, salt], (error, usersResults) => {
+          if (error) throw error;
+
+          pool.query('INSERT INTO players (username, display_name, credits) VALUES ($1, $2, $3)', [body.username, body.displayName, 1000], (error, playersResults) => {
+            if (error) throw error;
+
+            pool.query('INSERT INTO stats (username, blackjack_games, roulette_games, poker_games, blackjack_won_games, roulette_won_games, poker_won_games, money_bet, money_earned) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)', [body.username, 0, 0, 0, 0, 0, 0, 0, 0], (error, statsResults) => {
+              if (error) throw error;
+
+              res.json({
+                success: true,
+                message: 'Registration successful',
+              });
+              return ;
+            });
+          });
+        });
+      });
+    }
+
+    /**
+     * /---------------------- POST ----------------------/
+     * @action login
+     * @param username
+     * @param password
+     */
+    if (body?.action === 'login') {
+      // checks
+      if (body?.username == "undefined" || body?.username == "null" || body?.username == "") {
+        res.json({
+          success: false,
+          message: 'Username is required',
+        });
+        return ;
+      }
+      if (/[^a-zA-Z]/g.test(body?.username)) {
+        res.json({
+          success: false,
+          message: 'Username must contain only letters',
+        })
+        return ;
+      }
+      if (body?.password == "undefined" || body?.password == "null" || body?.password == "") {
+        res.json({
+          success: false,
+          message: 'Password is required',
+        });
+        return ;
+      }
+
+      // everything's okay
+      body.username = body.username.toLowerCase();
+
+      // check if user exists
+      pool.query('SELECT * FROM users WHERE username = $1', [body.username], (error, usersResults) => {
+        if (error) throw error;
+
+        if (usersResults.rows.length === 0) {
+          res.json({
+            success: false,
+            message: 'User does not exist. Try Registering instead.',
+          });
+          return ;
+        }
+        else {
+          if (usersResults.rows.length > 0) {
+            const user = usersResults.rows[0];
+            const salt = user.salt;
+            const hashedPassword = crypto.pbkdf2Sync(body.password, salt, 1000, 64, 'sha512').toString('hex');
+
+            if (hashedPassword === user.password) {
+              pool.query('SELECT * FROM players WHERE username = $1', [body.username], (error, playersResults) => {
+                if (playersResults.rows.length > 0) {
+                  let session = sessions.find(session => session.username === playersResults.rows[0].username)
+
+                  if (session) {
+                    // Already logged in
+                    res.json({
+                      success: false,
+                      message: 'You are already logged in',
+                    })
+                  }
+                  else {
+                    // create a session
+                    session = {
+                      id: uuidv4(),
+                      displayName: playersResults.rows[0].display_name,
+                      username: playersResults.rows[0].username,
+                      credits: playersResults.rows[0].credits,
+                      lastActivity: Date.now(),
+                    }
+                    
+                    sessions.push(session);
+    
+                    res.json({
+                      success: true,
+                      message: 'Login successful',
+                      session: session,
+                    })
+                  }
+
+                  return ;
+                }
+              });
+            }
+            else {
+              res.json({
+                success: false,
+                message: 'Username and password do not match.',
+              });
+            }
+          }
+        }
+      });
+    }
+  }
+
+  /**
+   * PUT method
+   */
+  if (req.method === 'PUT') {
+
+  }
+}
