e-ucm/rage-analytics-backend

View on GitHub
routes/games.js

Summary

Maintainability
B
5 hrs
Test Coverage
'use strict';

var express = require('express'),
    Q = require('q'),
    router = express.Router(),
    restUtils = require('./rest-utils'),
    request = require('request');

var games = require('../lib/games'),
    versions = require('../lib/versions'),
    activities = require('../lib/activities'),
    kibana = require('../lib/kibana/kibana');

/**
 * @api {get} /games/my Return all games of the author in the x-gleaner-user header.
 * @apiName getSessions
 * @apiGroup Sessions
 *
 * @apiHeader {String} x-gleaner-user.
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *    [
 *      {
 *          "_id": "559a447831b76cec185bf511",
 *          "title": "My Game",
 *          "created": "2017-07-06T09:00:52.630Z",
 *          "authors": ["someDeveloper"],
 *          "developers": ["someDeveloper"],
 *          "public": "true",
 *          "deleted": "false"
 *      }
 *    ]
 */
router.get('/my', restUtils.find(games, function (req, callback) {
    var user = req.headers['x-gleaner-user'];
    // Creates a Query for the 'find' operation
    callback({
        developers: user.toString(),
        $or: [ {deleted: false}, {deleted: undefined} ]
    });
}));

/**
 * @api {get} /games/public Returns all the public games.
 * @apiName GetGames
 * @apiGroup Games
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      [
 *          {
 *              "_id": "559a447831b7acec185bf513",
 *              "title": "My Game",
 *              "created": "2017-07-06T09:00:52.630Z",
 *              "authors": ["someDeveloper"],
 *              "developers": ["someDeveloper"],
 *              "public": "true",
 *              "deleted": "false"
 *          }
 *      ]
 *
 */
router.get('/public', restUtils.find(games, function (req, callback) {
    // Creates a Query for the 'find' operation
    callback({
        public: true,
        deleted: false
    });
}));

/**
 * @api {get} /games/:gameId Returns a specific game.
 * @apiName GetGames
 * @apiGroup Games
 *
 * @apiParam {String} gameId Game id.
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *          "_id": "559a447831b7acec185bf513",
 *          "title": "My Game",
 *          "created": "2017-07-06T09:00:52.630Z",
 *          "authors": ["someDeveloper"],
 *          "developers": ["someDeveloper"],
 *          "public": "true",
 *          "deleted": "false"
 *      }
 *
 */
router.get('/:gameId', function (req, res) {
    var username = req.headers['x-gleaner-user'];
    restUtils.processResponse(games.getGame(req.params.gameId, username), res);
});

/**
 * @api {post} /games Adds a new game.
 * @apiName PostGames
 * @apiGroup Games
 *
 * @apiHeader {String} x-gleaner-user.
 *
 * @apiParam {String} [title] The title of the game.
 * @apiParam {Boolean} [public] If other people can see the game.
 *
 * @apiParamExample {json} Request-Example:
 *      {
 *          "title": "My Game",
 *          "public": "true"
 *      }
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *          "_id": "559a447831b7acec185bf513",
 *          "title": "My Game",
 *          "created": "2017-07-06T09:00:52.630Z",
 *          "authors": ["someDeveloper"],
 *          "developers": ["someDeveloper"],
 *          "public": "true",
 *          "deleted": "false"
 *      }
 *
 */
router.post('/', function (req, res) {
    var username = req.headers['x-gleaner-user'];
    restUtils.processResponse(games.createGame(username,
        req.body.title || '', req.body.public || false), res);
});

/**
 * @api {post} /game/bundle/ Creates new Game, including a version one, dashboards and visualizations.
 * @apiName PostBundleGame
 * @apiGroup Games
 *
 * @apiParam {String} name The name for the Game.
 *
 * @apiParamExample {json} Request-Example:
 *      {
 *          "title": "New name",
 *          "public": false
 *      }
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *          "gameId": "55e433c773415f105025d2d4",
 *          "versionId": "55e433c773415f105025d2d5",
 *          "name": "New name",
 *          "created": "2015-08-31T12:55:05.459Z",
 *          "developers": [
 *              "user"
 *          ],
 *          "_id": "55e44ea9f1448e1067e64d6c"
 *      }
 *
 */
router.post('/bundle', function (req, res) {
    var username = req.headers['x-gleaner-user'];
    var config = req.app.config;
    var extra = {
        timeFrom: 'now-7d',
        refreshInterval: {
            display: '10 seconds',
            pause: false,
            section: 1,
            value: 10000
        }
    };

    restUtils.processResponse(games.createGame(username,
        req.body.title || '', req.body.public || false)
        .then(function (game) {
            var gameId = game._id.toString();
            return versions.createVersion({ gameId: game._id })
                .then(function (version) {
                    return games.kibana.createGameTemplates(gameId, req.app.esClient)
                        .then(function () {

                            var deferred = Q.defer();

                            kibana.getKibanaBaseVisualizations('dev', config, gameId, req.app.esClient)
                                .then(function(visualizations) {
                                    console.log('PostBundle -> VisObtained!');
                                    return kibana.createIndex(config, version._id.toString(), gameId,
                                        username, req.app.esClient)
                                        .then(function(result) {
                                            console.log('PostBundle -> IndexCreated!');
                                            return kibana.createVisualizationsAndDashboard(config, version._id.toString(),
                                                gameId, visualizations, username, req.app.esClient, extra);
                                        })
                                        .then(function(result) {
                                            console.log('PostBundle -> VisAndDashCreated!');
                                            deferred.resolve(game);
                                        })
                                        .fail(function(e) {
                                            deferred.reject(e);
                                        });
                                })
                                .fail(function(err) {
                                    console.log('PostBundle -> getKibanaBaseVisualizationsFailcase!');
                                    console.log(JSON.stringify(err, null, 2));
                                    return deferred.reject(err);
                                });

                            return deferred.promise;
                        });
                });
        }), res);

    console.log('PostBundle -> finnished!');
});

/**
 * @api {put} /games/:gameId Changes the title, developers and public attribute of a game.
 * @apiName PutGames
 * @apiGroup Games
 *
 * @apiParam {String} gameId The id of the game.
 * @apiParam {String} [title] The new title of the game
 * @apiParam {Boolean} [public] Whether the game is public or not.
 * @apiParam {String[]} [developers] Array with the username of the authors that you want to add to the game. Also can be a String
 * @apiParamExample {json} Request-Example:
 *      {
 *          "title": "My New Name",
 *          "developers": ["Some Username"],
 *          "public": "true"
 *      }
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *          "_id": "559a447831b7acec185bf513",
 *          "title": "My Game"
 *          "authors": ["someDeveloper"],
 *          "developers": ["Some Username"],
 *          "public": "true"
 *      }
 */
router.put('/:gameId', function (req, res) {
    var username = req.headers['x-gleaner-user'];
    restUtils.processResponse(games.modifyGame(req.params.gameId, username, req.body, true), res);
});

/**
 * @api {put} /games/:gameId/remove Removes an developer of the game
 * @apiName PutGames
 * @apiGroup Games
 *
 * @apiParam {String} gameId The id of the game.
 * @apiParam {String[]} [author] Array with the username of the authors that you want to add to the game. Also can be a String
 * @apiParamExample {json} Request-Example:
 *      {
 *          "developers": ["Some Username"]
 *      }
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *          "_id": "559a447831b7acec185bf513",
 *          "title": "My Game"
 *          "authors": ["someDeveloper"],
 *          "developers": [],
 *          "public": "true"
 *      }
 */
router.put('/:gameId/remove', function (req, res) {
    var username = req.headers['x-gleaner-user'];
    restUtils.processResponse(games.modifyGame(req.params.gameId, username, req.body, false), res);
});

/**
 * @api {delete} /games/:id Removes the game if doesn't contain activities else change the deleted field by true.
 * @apiName DeleteGame
 * @apiGroup Games
 *
 * @apiParam {String} id Game id.
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *         "message": "Success."
 *      }
 *
 */
router.delete('/:id', function (req, res) {
    var username = req.headers['x-gleaner-user'];
    restUtils.processResponse(games.removeGame(username, req.params.id), res);
});

/**
 * VERSIONS
 **/

/**
 * @api {get} /games/:gameId/versions Returns all the versions of a given game.
 * @apiName GetVersions
 * @apiGroup Games
 *
 * @apiParam {String} gameId Game id.
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      [
 *          {
 *              "_id": "559a447831b76cec185bf513",
 *              "gameId": "559a447831b7acec185bf513"
 *          }
 *      ]
 *
 */
router.get('/:gameId/versions', function(req, res) {
    var query = {
        // Creates a Query for the 'find' operation
        gameId: games.toObjectID(req.params.gameId)
    };
    console.info(query);
    restUtils.processResponse(versions.find(query), res);
});

/**
 * @api {get} /games/:id/xapi/:versionId Returns the game with the given id.
 *              This route is mainly used as the Object.id of the xAPI statements.
 * @apiName GetGame
 * @apiGroup Games
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *          "_id": "559a447831b7acec185bf513",
 *          "title": "My Game"
 *          "authors": ["someDeveloper"],
 *          "developers": ["someDeveloper"],
 *          "public": "true"
 *      }
 *
 */
router.get('/:id/xapi/:versionId', restUtils.findById(games));

/**
 * @api {post} /games/:gameId/versions Adds a new version for a specific game.
 * @apiName PostVersions
 * @apiGroup Games
 *
 * @apiParam {String} gameId Game id.
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *          "_id": "559a447831b76cec185bf513",
 *          "gameId": "559a447831b7acec185bf513"
 *      }
 *
 */
router.post('/:gameId/versions', function(req, res) {
    restUtils.processResponse(versions.createVersion({
        gameId: req.params.gameId
    }), res);
});

/**
 * @api {get} /games/:gameId/versions/:id Returns a version for a specific game.
 * @apiName GetVersions
 * @apiGroup Games
 *
 * @apiParam {String} gameId Game id.
 * @apiParam {String} id Version id.
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *          "_id": "559a447831b76cec185bf513",
 *          "gameId": "559a447831b7acec185bf514"
 *      }
 *
 */
router.get('/:gameId/versions/:id', restUtils.findById(versions));

/**
 * @api {post} /games/:gameId/versions/:id Adds a new name or link for a specific version.
 * @apiName PutVersions
 * @apiGroup Games
 *
 * @apiParam {String} gameId Game id.
 * @apiParam {String} id Version id.
 *
 * @apiParamExample {json} Request-Example:
 *      {
 *          "name": "New name",
 *          "link": "New Link"
 *      }
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *          "name": "New name",
 *          "link": "New Link",
 *          "_id": "559a447831b76cec185bf513",
 *          "gameId": "559a447831b7acec185bf513"
 *      }
 *
 */
router.post('/:gameId/versions/:id', restUtils.findAndModify(versions, function (req) {
    // Ensures that the 'gameId' attribute cannot be changed in a 'version'
    if (req.body && req.body.gameId) {
        delete req.body.gameId;
    }
}));

/**
 * SESSIONS
 */

/**
 * @api {get} /games/:gameId/versions/:versionsId/activities Returns all the Activities of a
 * given version of a game.
 * @apiName GetActivities
 * @apiGroup Activities
 *
 * @apiParam {String} gameId The Game id of the activity.
 * @apiParam {String} versionId The Version id of the activity.
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      [
 *          {
 *              "_id": "559a447831b76cec185bf501"
 *              "gameId": "559a447831b76cec185bf513",
 *              "versionId": "559a447831b76cec185bf514",
 *              "classId": "559a447831b76cec185bf542",
 *              "created": "2015-07-06T09:00:50.630Z",
 *              "start": "2015-07-06T09:00:52.630Z",
 *              "end": "2015-07-06T09:03:45.631Z"
 *          },
 *          {
 *              "_id": "559a447831b76cec185bf511"
 *              "gameId": "559a447831b76cec185bf513",
 *              "versionId": "559a447831b76cec185bf514",
 *              "classId": "559a447831b76cec185bf547",
 *              "created": "2015-07-06T09:00:50.630Z",
 *              "start": "2015-07-06T09:03:52.636Z",
 *              "end": "2015-07-06T09:03:58.631Z"
 *          }
 *      ]
 *
 */
router.get('/:gameId/versions/:versionId/activities', function (req, res) {
    restUtils.processResponse(activities.getGameActivities(req.params.gameId, req.params.versionId), res);
});

/**
 * @api {get} /games/:gameId/versions/:versionsId/activities/my Returns all the Activities of a given
 * version of a game where the user participates.
 * @apiName GetActivities
 * @apiGroup Activities
 *
 *  @apiHeader {String} x-gleaner-user.
 *
 * @apiParam {String} gameId The Game id of the activity.
 * @apiParam {String} versionId The Version id of the activity.
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      [
 *          {
 *              "_id": "559a447831b76cec185bf501"
 *              "gameId": "559a447831b76cec185bf513",
 *              "versionId": "559a447831b76cec185bf514",
 *              "classId": "559a447831b76cec185bf542",
 *              "start": "2015-07-06T09:00:52.630Z",
 *              "end": "2015-07-06T09:03:45.631Z"
 *          },
 *          {
 *              "_id": "559a447831b76cec185bf511"
 *              "gameId": "559a447831b76cec185bf513",
 *              "versionId": "559a447831b76cec185bf514",
 *              "classId": "559a447831b76cec185bf546",
 *              "start": "2015-07-06T09:03:52.636Z"
 *          }
 *      ]
 *
 */
router.get('/:gameId/versions/:versionId/activities/my', function (req, res) {
    restUtils.processResponse(activities.getUserActivitiesByGame(req.params.gameId, req.params.versionId,
        req.headers['x-gleaner-user']), res);
});

/**
 * @api {get} /statements Returns all statements.
 * @apiName GetSessions
 * @apiGroup Sessions
 *
 * @apiParam {String} id The Session id
 *
 * @apiSuccess(200) Success.
 *
 * @apiSuccessExample Success-Response:
 *      HTTP/1.1 200 OK
 *      {
 *          "statements": [
 *          {
 *              "id": "e5efec39-3992-401d-be17-86d24c3f1e76",
 *              "actor": {
 *              "objectType": "Agent",
 *              "name": "s",
 *              "account": {
 *                  "homePage": "http://www.gleaner.com/",
 *                  "name": "s"
 *              }
 *          },
 *          "verb": {
 *              "id": "http://www.gleaner.com/started_game",
 *              "display": {
 *                  "es-ES": "started_game",
 *                  "en-US": "started_game"
 *              }
 *          },
 *          "object": {
 *              "id": "http://www.gleaner.com/games/lostinspace/none",
 *              "objectType": "Activity",
 *              "definition": {
 *                  "type": "http://www.gleaner.com/objects/none",
 *                  "extensions": {
 *                      "event": "game_start",
 *                      "gameplayId": "55e57b03553dded764546f03"
 *                  }
 *              }
 *          },
 *          "stored": "2015-09-10T11:01:04Z"
 *      }
 *
 */
router.get('/statements', function (req, res, next) {

    var options = {
        uri: req.app.config.lrs.uri + '/statements',
        method: 'GET',
        json: true,
        headers: {
            Authorization: 'Basic ' + new Buffer(req.app.config.lrs.username + ':' + req.app.config.lrs.password)
                .toString('base64'),
            'X-Experience-API-Version': '1.0.1'
        }
    };

    request(options, function (err, response, body) {
        if (err) {
            next(err);
        } else {
            if (!body) {
                body = {statements: []};
            }
            res.json(body);
        }
    });
});

module.exports = router;