Browse Source

add db connection to server + server tool + app db conn for get games

jojo 5 years ago
parent
commit
5833ba002e

+ 1 - 1
.eslintrc.json

@@ -6,7 +6,7 @@
     "plugin:import/warnings"
   ],
   "parserOptions": {
-    "ecmaVersion": 7,
+    "ecmaVersion": 2017,
     "sourceType": "module"
   },
   "env": {

+ 6 - 0
app-server/app-server.js

@@ -0,0 +1,6 @@
+const express = require('express');
+const app = express();
+const port = 2612;
+
+app.use(express.static('webpack'));
+app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`));

File diff suppressed because it is too large
+ 29 - 827
package-lock.json


+ 2 - 0
package.json

@@ -8,12 +8,14 @@
   "scripts": {
     "server": "cd server && npm start",
     "dev": "DEV=true SERVER_PORT=2610 SERVER_URL='http://localhost' webpack --watch",
+    "build-web-serve": "DEV=true webpack --mode=production",
     "build": "webpack --mode=production",
     "postbuild": "cordova prepare",
     "win-build": "cordova build windows --win",
     "preandroid-build": "set ORG_GRADLE_PROJECT_cdvMinSdkVersion=20 ",
     "android-build": "cordova build android",
     "browser": "cordova run browser",
+    "appserver": "node app-server/app-server.js",
     "win": "cordova run windows --win",
     "android": "cordova run android --emulator",
     "start": "npm-run-all --parallel server dev lint:watch",

+ 161 - 0
server/db/mariadb-connector.js

@@ -0,0 +1,161 @@
+'use strict';
+import mariadb from 'mariadb';
+
+export default class MariadbConnector {
+  constructor() {
+    this.pool = mariadb.createPool({
+      host: 'localhost',
+      user: 'node',
+      password: 'nodejs1234',
+      database: 'twelve_heroes',
+      connectionLimit: 5
+    });
+  }
+
+  async getUsernames() {
+
+    let conn;
+    let players = [];
+    try {
+      conn = await this.pool.getConnection();
+      const rows_players = await conn.query("SELECT username FROM players");
+      for (const { username: u } of rows_players) {
+        players.push(u);
+      }
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+    return players;
+  }
+
+  async addPlayer(username) {
+    console.log('mariadb add player : ', username);
+    let conn;
+    try {
+      conn = await this.pool.getConnection();
+      const val = await conn.query("INSERT INTO players value (?, NOW(),NULL)", [username]);
+      console.log('OK removing player : ', val);
+      return val;
+    } catch (err) {
+      console.log('error adding player : ', err);
+      throw err;
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+  }
+  async removePlayer(username) {
+    console.log('mariadb remove player : ', username);
+    let conn;
+    try {
+      conn = await this.pool.getConnection();
+      const val = await conn.query("DELETE FROM players WHERE username=?", [username]);
+      console.log('OK removing player : ', val);
+      return val;
+    } catch (err) {
+      console.log('error removing player : ', err);
+      throw err;
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+  }
+
+  async addNewGame(game) {
+    console.log('mariadb add game : ', game);
+    let conn;
+    try {
+      conn = await this.pool.getConnection();
+      const val = await conn.query("INSERT INTO games values (NULL,?,?,?,?,?,?,NOW())",
+        [game.player1,
+        game.player2,
+        game.deck,
+        convertAdvRulesToString(game.advRules),
+        game.status,
+        game.data]);
+      console.log('OK adding game : ', val);
+      return val.insertId;
+    } catch (err) {
+      console.log('error adding game : ', err);
+      throw err;
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+  }
+
+  removeGameById(gameId) {
+    return this.removeGame("DELETE FROM games WHERE id=?", [gameId]);
+  }
+  removeGamesByPlayer1(player1Name) {
+    return this.removeGame("DELETE FROM games WHERE player1=?", [player1Name]);
+  }
+  removeGamesByPlayerAny(playerName) {
+    return this.removeGame("DELETE FROM games WHERE player1=? OR player2=?", [playerName, playerName]);
+  }
+  removeGamesByStatus(status) {
+    return this.removeGame("DELETE FROM games WHERE status=?", [status]);
+  }
+  removeGamesByDays(days) {
+    return this.removeGame("DELETE FROM games WHERE  datediff(NOW(),last_played) > ?", [days]);
+  }
+  removeFinishedGamesByDays(days) {
+    return this.removeGame("DELETE FROM games WHERE status='FINISHED' AND datediff(NOW(),last_played) > ?", [days]);
+  }
+
+  async removeGame(queryStr, queryArgs) {
+    console.log('mariadb remove game  : ', queryStr);
+    let conn;
+    try {
+      conn = await this.pool.getConnection();
+      const val = await conn.query(queryStr, queryArgs);
+      console.log('OK removing game : ', val);
+      return val;
+    } catch (err) {
+      console.log('error removing game : ', err);
+      throw err;
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+  }
+
+  async getNonFinishedGamesForPlayer(username) {
+
+    let conn;
+    let games = [];
+    try {
+      conn = await this.pool.getConnection();
+      const res = await conn.query(
+        "SELECT * FROM`games` WHERE status != 'FINISHED' AND(player1 = ? OR player2 = '' OR player2 = ?)",
+        [username,username]);
+      for (const { player1,player2,deck,adv_rules } of res) {
+        games.push({player1,player2,deck,adv_rules});
+      }
+      console.log(`returning for ${username} : `, games);
+    } finally {
+      if (conn && conn !== null) {
+        conn.end();
+      }
+    }
+    return games;
+
+  }
+}
+let convertAdvRulesToString = function (advRulesArray) {
+  let advRulestStr = '';
+  let last = advRulesArray.length - 1;
+  advRulesArray.forEach((rule, index) => {
+    advRulestStr += rule;
+    if (index < last) {
+      advRulestStr += ',';
+    }
+  });
+  return advRulestStr;
+};

+ 0 - 107
server/main.js

@@ -1,107 +0,0 @@
-'use strict';
-import PlayerId from './players/player-id';
-import DuelController from './game-server/duel-controller';
-
-console.log('Starting 12 heroes server');
-
-const io = require('socket.io');
-const server = io.listen(2610);
-
-let players = [];
-
-const authorizedPlayersNames = ["jojo", "mart", "lily"];
-let authorizedPlayers = new Map();
-let connectedPlayers = new Map();
-
-authorizedPlayersNames.forEach(name => {
-  authorizedPlayers.set(name, new PlayerId(name));
-});
-let addNewPlayer = function (playerSocket, playerName) {
-  console.log('players length : ' + players.length + ' : ' + players);
-  if (players.length < 2) {
-    let newPlayer = new PlayerId(playerSocket, playerName);
-    console.log('push player : ' + newPlayer);
-    players.push(newPlayer);
-  }
-  if (players.length === 2) {
-    let duelController = new DuelController(players[0], players[1]);
-  }
-};
-
-server.on('connection', function (socket) {
-  console.log("A player connected with id : " + socket.id);
-
-  socket.on('disconnect', (reason) => {
-    if (reason === 'client namespace disconnect') {
-      console.log("A player disconnected with id : " + socket.id);
-      let playerName = connectedPlayers.get(socket.id);
-      if (playerName) {
-        connectedPlayers.delete(socket.id);
-        authorizedPlayers.get(playerName).setConnected(false);
-        authorizedPlayers.get(playerName).setSocket(null);
-        console.log(playerName + " disconnected");
-      }
-    } else {
-      console.log("disconnected unexpectidly with reason : " + reason);
-    }
-  });
-  socket.on('connect', () => {
-    console.log("Connected to server");
-
-  });
-  socket.on('auth', (playerName, callback) => {
-    console.log(' Received auth message, player name : ' + playerName);
-    let response = {};
-    let kickout = false;
-    if (!authorizedPlayersNames.includes(playerName)) {
-      response = {
-        res: "ko",
-        message: playerName + " Not found"
-      };
-      kickout = true;
-    }
-    // If the player is already connected and active
-    else if (authorizedPlayers.get(playerName).isConnected()
-      && authorizedPlayers.get(playerName).getSocket().connected) {
-      response = {
-        res: "ko",
-        message: playerName + " already connected"
-      };
-      kickout = true;
-    }
-    else {
-      // Player marked as connected but socket is down
-      if (authorizedPlayers.get(playerName).isConnected()) {
-        authorizedPlayers.get(playerName).getSocket().disconnect(true);
-      }
-      response = {
-        res: "ok",
-        message: playerName + " connected"
-      };
-      authorizedPlayers.get(playerName).setConnected(true);
-      authorizedPlayers.get(playerName).setSocket(socket);
-      connectedPlayers.set(socket.id, playerName);
-    }
-
-    callback(response);
-    if (kickout === true) {
-      setTimeout(() => {
-        socket.disconnect(true);
-      }, 600);
-    }
-  });
-
-  socket.on('games-list', (playerName, callback) => {
-    console.log(' Received games-list message, player name : ' + playerName);
-    let games= {
-      game1: {p1:"jojo", p2:'lily',mode:'faction', rules:[]},
-      game2: {p1:"mart", p2:'',mode:'tournament', rules:['popularity', 'discard']},
-      game3: {p1:"jojo", p2:'mart',mode:'draft', rules:['discard']}
-    };
-    let response = {
-      res: "ok",
-      message: games
-    };
-    callback(response);
-  });
-});

+ 4 - 2
server/package.json

@@ -6,7 +6,8 @@
     "Server"
   ],
   "scripts": {
-    "start": "babel-node main.js"
+    "start": "babel-node server.js",
+    "tools": "node tools/server-tools.js"
   },
   "author": "JOJO",
   "license": "MIT",
@@ -16,6 +17,7 @@
   },
   "devDependencies": {
     "@babel/node": "7.6.2",
-    "heroku": "^7.39.1"
+    "heroku": "^7.39.1",
+    "socket.io-client": "^2.3.0"
   }
 }

+ 238 - 0
server/server.js

@@ -0,0 +1,238 @@
+'use strict';
+import PlayerId from './players/player-id';
+import DuelController from './game-server/duel-controller';
+import MariadbConnector from './db/mariadb-connector';
+import ServerToolListner from './tools/server-tool-listener';
+
+
+function Server() {
+  console.log('Starting 12 heroes server');
+
+  const io = require('socket.io');
+  const server = io.listen(2610);
+
+  let mariadbConn = new MariadbConnector();
+
+
+  let authorizedPlayers = new Map();
+  let connectedPlayers = new Map();
+  let authorizedPlayersNames = new Set();
+
+
+
+  // let players = [];
+
+
+  // let addNewPlayer = function (playerSocket, playerName) {
+  //   console.log('players length : ' + players.length + ' : ' + players);
+  //   if (players.length < 2) {
+  //     let newPlayer = new PlayerId(playerSocket, playerName);
+  //     console.log('push player : ' + newPlayer);
+  //     players.push(newPlayer);
+  //   }
+  //   if (players.length === 2) {
+  //     let duelController = new DuelController(players[0], players[1]);
+  //   }
+  // };
+
+  server.on('connection', function (socket) {
+    console.log("A player connected with id : " + socket.id);
+
+    socket.on('disconnect', (reason) => {
+      if (reason === 'client namespace disconnect') {
+        console.log("A player disconnected with id : " + socket.id);
+        let playerName = connectedPlayers.get(socket.id);
+        if (playerName) {
+          connectedPlayers.delete(socket.id);
+          authorizedPlayers.get(playerName).setConnected(false);
+          authorizedPlayers.get(playerName).setSocket(null);
+          console.log(playerName + " disconnected");
+        }
+      } else {
+        console.log("disconnected unexpectidly with reason : " + reason);
+      }
+    });
+    socket.on('connect', () => {
+      console.log("Connected to server");
+
+    });
+    socket.on('auth', async (playerName, callback) => {
+      console.log(' Received auth message, player name : ' + playerName);
+      await updatePlayersFromDb();
+
+      let response = {};
+      let kickout = false;
+      if (!authorizedPlayersNames.has(playerName)) {
+        response = {
+          res: "ko",
+          message: playerName + " Not found"
+        };
+        kickout = true;
+      }
+      // If the player is already connected and active
+      else if (authorizedPlayers.get(playerName).isConnected()
+        && authorizedPlayers.get(playerName).getSocket().connected) {
+        response = {
+          res: "ko",
+          message: playerName + " already connected"
+        };
+        kickout = true;
+      }
+      else {
+        // Player marked as connected but socket is down
+        if (authorizedPlayers.get(playerName).isConnected()) {
+          authorizedPlayers.get(playerName).getSocket().disconnect(true);
+        }
+        response = {
+          res: "ok",
+          message: playerName + " connected"
+        };
+        authorizedPlayers.get(playerName).setConnected(true);
+        authorizedPlayers.get(playerName).setSocket(socket);
+        connectedPlayers.set(socket.id, playerName);
+      }
+
+      callback(response);
+      if (kickout === true) {
+        setTimeout(() => {
+          socket.disconnect(true);
+        }, 600);
+      }
+    });
+
+    socket.on('games-list', async (playerName, callback) => {
+      console.log(' Received games-list message, player name : ' + playerName);
+      let response = {};
+      try {
+        let games = await getNonFinishedGames(playerName);
+        response = {
+          res: "ok",
+          message: games
+        };
+      } catch (error) {
+
+        response = {
+          res: "ko",
+          message: 'Error from server'
+        };
+      }
+      callback(response);
+    });
+
+  });
+
+  let updatePlayersFromDb = async function () {
+    try {
+      let usernames = await mariadbConn.getUsernames();
+      authorizedPlayersNames = new Set(usernames);
+      console.log('authorizedPlayersNames update : ', authorizedPlayersNames);
+      authorizedPlayersNames.forEach(name => {
+        if (!authorizedPlayers.has(name)) {
+          console.log('New username authorized :', name);
+          authorizedPlayers.set(name, new PlayerId(name));
+        }
+      });
+      return 'ok';
+    } catch (error) {
+      console.log('Error getting usernames from DB : ', error);
+      return error.Error;
+    }
+  };
+
+  let getCurrentListAuthorizedPlayers = function () {
+    return [...authorizedPlayersNames];
+  };
+  let addPlayerDb = async function (username) {
+
+    console.log('add player in db : ' + username);
+    try {
+      let response = await mariadbConn.addPlayer(username);
+      authorizedPlayersNames.add(username);
+      authorizedPlayers.set(username, new PlayerId(username));
+      return 'OK ' + JSON.stringify(response);
+    } catch (err) {
+      return 'KO ' + err.message;
+    }
+  };
+  let removePlayerDb = async function (username) {
+
+    console.log('remove player in db : ' + username);
+    try {
+      let response = await mariadbConn.removePlayer(username);
+      authorizedPlayersNames.delete(username);
+      authorizedPlayers.delete(username);
+      return 'OK ' + JSON.stringify(response);
+    } catch (err) {
+      return 'KO ' + err.message;
+    }
+  };
+
+  let addGameDb = async function (game) {
+
+    try {
+      let response = await mariadbConn.addNewGame(game);
+      return 'OK ' + JSON.stringify(response);
+    } catch (err) {
+      return 'KO ' + err.message;
+    }
+  };
+
+  let removeGameDb = async function (method, ...args) {
+    try {
+      let response;
+      switch (method) {
+        case 'byId':
+          response = await mariadbConn.removeGameById(args[0]);
+          break;
+        case 'byPlayer1':
+          response = await mariadbConn.removeGamesByPlayer1(args[0]);
+          break;
+        case 'byPlayerAny':
+          response = await mariadbConn.removeGamesByPlayerAny(args[0]);
+          break;
+        case 'byStatus':
+          response = await mariadbConn.removeGamesByStatus(args[0]);
+          break;
+        case 'byDays':
+          response = await mariadbConn.removeGamesByDays(args[0]);
+          break;
+        case 'finishedByDays':
+          response = await mariadbConn.removeFinishedGamesByDays(args[0]);
+          break;
+
+        default:
+          return 'KO : Unknown method to remove game from DB : ' + method;
+      }
+      return 'OK ' + JSON.stringify(response);
+    } catch (err) {
+      return 'KO ' + err.message;
+    }
+  };
+
+  let getNonFinishedGames = async function (username) {
+
+    try {
+      let games = await mariadbConn.getNonFinishedGamesForPlayer(username);
+      return games;
+    } catch (err) {
+      console.log('KO : not able to get games : ' + err);
+      throw err;
+    }
+  };
+
+  return {
+    updatePlayersFromDb,
+    getCurrentListAuthorizedPlayers,
+    addPlayerDb,
+    removePlayerDb,
+    addGameDb,
+    removeGameDb,
+    getNonFinishedGames
+  };
+
+}
+
+let server = new Server();
+
+let serverToolListner = new ServerToolListner(server);
+serverToolListner.listen(1664);

+ 49 - 0
server/tools/server-tool-listener.js

@@ -0,0 +1,49 @@
+'use strict';
+
+import io from 'socket.io';
+
+export default class ServerToolListner {
+  constructor(server) {
+    this.server=server;
+  }
+
+  listen(port) {
+    let server = this.server;
+    this.serverTool = io.listen(port);
+    this.serverTool.on('connection', function (socket) {
+      console.log('tool connected');
+
+      socket.on('players', (option,callback) =>  {
+        callback(server.getCurrentListAuthorizedPlayers());
+        socket.disconnect(false);
+      });
+      socket.on('syncdb', async (option,callback) =>  {
+        let response = await server.updatePlayersFromDb();
+        callback(response);
+        socket.disconnect(false);
+      });
+
+      socket.on('add-player', async (username,callback) =>  {
+        let response = await server.addPlayerDb(...username);
+        callback(response);
+        socket.disconnect(false);
+      });
+      socket.on('remove-player', async (username,callback) =>  {
+        let response = await server.removePlayerDb(...username);
+        callback(response);
+        socket.disconnect(false);
+      });
+
+      socket.on('add-game', async (game,callback) =>  {
+        let response = await server.addGameDb(...game);
+        callback(response);
+        socket.disconnect(false);
+      });
+      socket.on('remove-game', async (options,callback) =>  {
+        let response = await server.removeGameDb(...options);
+        callback(response);
+        socket.disconnect(false);
+      });
+    });
+  }
+}

+ 82 - 0
server/tools/server-tools.js

@@ -0,0 +1,82 @@
+'use strict';
+
+// process.exit(1);
+var usage = function () {
+  var text = `
+    USAGE : npm run tools <option>
+      with <option> :
+       - players : get authorized players
+       - add-player <username> : Add a new authorized player
+       - remove-player <username> : Remove an authorized player
+       - syncdb : Force server to sync with db
+       - add-game <json>: Add new game into DB
+          '{"player1":"","player2":"","deck":"","advRules":[],"status":"","data":"{}"}'
+            deck     : faction tournament draft  (one of these)
+            advRules : popularity discard        (0 or any of these)
+            status   : CREATED ONGOING FINISHED  (one of these)
+       - remove-game <method> <filter> : Remove game(s) from DB
+          <method>          /  <filter>
+            byId                 gameId
+            byPlayer1            username
+            byPlayerAny          username
+            byStatus             CREATED ONGOING FINISHED  (one of these)
+            byDays               number of days old is last connection
+            finishedByDays       number of days old is last connection(only finished)
+       `;
+  console.log(text);
+};
+
+var args = process.argv.slice(2);
+
+if (args.length === 0) {
+  usage();
+  process.exit(0);
+}
+var command = "";
+var option = "";
+switch (args[0]) {
+  case "players":
+  case "syncdb":
+    command = args[0];
+    break;
+
+  case "add-player":
+  case "remove-player":
+  case "add-game":
+  case "remove-game":
+
+    if (args[0] === "remove-game" && args.length < 3) {
+      usage();
+      process.exit(0);
+    }
+    if (args[1] && args[1] !== "") {
+      command = args[0];
+      if (args[0] === "add-game") {
+        try {
+          option = [JSON.parse(args[1])];
+        } catch (error) {
+          console.log(error);
+          process.exit(0);
+        }
+      } else {
+        args.shift();
+        option = args;
+      }
+    } else {
+      console.log('error ; specify a username');
+      usage();
+    }
+    break;
+
+  default:
+    usage();
+    break;
+}
+
+if (command !== "") {
+  console.log('Connecting to server...');
+  var socket = require('socket.io-client')("http://localhost:1664");
+  socket.emit(command, option,function (response) {
+    console.log('Done, response from server : ', response);
+  });
+}

+ 8 - 7
src/menu/views/menu-pages/online-room-div-page.js

@@ -36,25 +36,26 @@ export default function OnlineRoomDivPage(element, listener) {
     listener.onRequestOnlineGamesList()
       .then( (games) => {
         console.log('received games : ', games);
+
         while(listOnlineGames.firstChild) listOnlineGames.removeChild(listOnlineGames.firstChild);
         console.log('removed ex list');
-        Object.values(games).forEach(game => {
+        games.forEach(game => {
           console.log(game);
           let title='';
           let desc='';
           let rules= '';
-          if (game.rules.length !== 0) {
-            game.rules.forEach(rule => {
+          if (game.adv_rules.length !== 0) {
+            game.adv_rules.forEach(rule => {
               rules += ' + ' + rule;
             });
           } else {
             rules= ' + no adv. rules';
           }
-          desc=`${game.mode}${rules}`;
-          if (game.p2 !== '') {
-            title=`Resume ${game.p1} VS ${game.p2}`;
+          desc=`${game.deck}${rules}`;
+          if (game.player2 !== '') {
+            title=`Resume ${game.player1} VS ${game.player2}`;
           } else {
-            title=`${game.p1} waiting...`;
+            title=`${game.player1} waiting...`;
           }
           let li = document.createElement("li");
           let spanTitle = document.createElement("span");

+ 1 - 1
webpack.config.js

@@ -7,7 +7,7 @@ var { CleanWebpackPlugin } = require('clean-webpack-plugin');
 
 var definePlugin = new webpack.DefinePlugin({
   'process.env.DEV': JSON.stringify(JSON.parse(process.env.DEV || 'false')),
-  'process.env.SERVER_URL': JSON.stringify(process.env.SERVER_URL || 'http://172.112.37.58'),
+  'process.env.SERVER_URL': JSON.stringify(process.env.SERVER_URL || 'http://109.214.245.153'),
   'process.env.SERVER_PORT': JSON.stringify(process.env.SERVER_PORT || '2610')
 });
 

Some files were not shown because too many files changed in this diff