Skip to content

Commit

Permalink
feature(game-log): user should be able to view a game log of past games
Browse files Browse the repository at this point in the history
- add API endpoint to get games history
- add API endpoint to get leaderboard
- add API endpoint to get donations

[Delivers #156882168]
  • Loading branch information
amarachukwu-agbo committed May 22, 2018
1 parent 883c84a commit cf8ced0
Show file tree
Hide file tree
Showing 14 changed files with 925 additions and 131 deletions.
131 changes: 102 additions & 29 deletions app/controllers/games.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,112 @@

import gameModel from '../models/game';
import Helper from '../helpers/index';

/**
* class Game - Represents a game
*/
class Game {
/**
* Save a game when it ends
*
* @param {object} req - The HTTP request
* @param {object} res - The HTTP response
* @returns {void}
*/
static saveGame(req, res) {
const {
players, winner, gameStarter, roundsPlayed,
} = req.body;
const gameID = req.params.id;

const gameEntry = new gameModel({
players,
gameID,
winner,
gameStarter,
roundsPlayed,
});

gameEntry.save()
.then((game) => {
res.status('201').json({
msg: 'Success, Game saved',
game
});
})
.catch((error) => {
res.status('400').json({
msg: 'Failure, Game not saved',
error
});
});
}

/**
* Get the history of games played
*
* @param {object} req - The HTTP request
* @param {object} res - The HTTP response
* @returns {void}
*/
const saveGame = (req, res) => {
const {
players, winner, gameStarter, roundsPlayed,
} = req.body;
const gameID = req.params.id;

const gameEntry = new gameModel({
players,
gameID,
winner,
gameStarter,
roundsPlayed,
});

gameEntry.save()
.then((game) => {
res.status('201').json({
msg: 'Success, Game saved',
game
});
})
.catch((error) => {
res.status('400').json({
msg: 'Failure, Game not saved',
*/
static gameHistory(req, res) {
const { page, limit, offset } = Helper.setupPagination(req);
gameModel.count()
.then((count) => {
const pagination = Helper.pagination(page, count, limit);
gameModel.find((error, games) => {
if (error) {
return res.status(500).json({
msg: 'Games History could not be retrieved',
error
});
}
pagination.pageSize = games.length;

const gameLog = games.map(game => ({
game,
playersNames: Helper.getPlayers(game.players)
}));

return res.status(200).json({
message: 'Games have been successfully retrieved',
games: gameLog,
pagination
});
}).skip(offset).limit(+limit);
}).catch(error => res.status(500).json({
message: 'Games History could not be retrieved',
error
});
});
};
}));
}

/**
* Get the leaderboard for the game
*
* @param {object} req - The HTTP request
* @param {object} res - The HTTP response
* @returns {void}
*/
static gameLeaderboard(req, res) {
gameModel.find(
{}, 'gameID winner roundsPlayed, playedAt -_id',
(err, games) => {
if (err) {
return res.status(500).json({
message: 'Leaderboard could not be gotten',
err
});
}
const groupedBoard = Helper.groupByWinner(games, 'winner');
const leaderboard = Helper.sortLeaderboard(groupedBoard);

return res.status(200).json({
message: 'Leaderboard successfully retrieved',
leaderboard
});
}
);
}
}

export default saveGame;
export default Game;
34 changes: 34 additions & 0 deletions app/controllers/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
import mongoose from 'mongoose';
import jwt from 'jsonwebtoken';
import Helper from '../helpers/index';

require('dotenv').config({ path: '.env' });

Expand Down Expand Up @@ -390,3 +391,36 @@ exports.game = function (req, res) {
.json({ games: userGameDetails, point: pointsWon, code: 200 });
});
};

exports.getDonations = function (req, res) {
const { page, limit, offset } = Helper.setupPagination(req);
User.$where('this.donations.length > 0').count()
.then((count) => {
const pagination = Helper.pagination(page, count, limit);
User.$where('this.donations.length > 0')
.skip(offset).limit(+limit).exec((error, donation) => {
pagination.dataCount = donation.length;
if (error) {
res.status(500).json({
message: 'Donations could not be retrieved',
error
});
}
const userDonations = donation.map(donor => ({
donor,
donations: Helper.calculateDonation(donor.donations),
}));

res.status(200).json({
message: 'Donations successfully retrieved',
userDonations,
pagination
});
});
}).catch((error) => {
res.status(500).json({
message: 'Donations could not be retrieved',
error
});
});
};
102 changes: 102 additions & 0 deletions app/helpers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* Class Helper Contains helper functions
*/
export default class Helper {
/**
* Group Games by their winners
* @param {Array} gamesArray - All games played
* @param {String} winner - The game winner
* @returns {Object} - The grouped leaderboard
*/
static groupByWinner(gamesArray, winner) {
const grouped = gamesArray.reduce((acc, obj) => {
const key = obj[winner];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
return grouped;
}

/**
* Sort the leaderboard to start with top winners
* @param {Object} obj - The leaderboard object
* @returns {Object} - The sorted leaderboard
*/
static sortLeaderboard(obj) {
const sortable = Object.keys(obj).map(arrayKey => obj[arrayKey]);
sortable.sort((a, b) => {
let comparison = 0;
if (b.length > a.length) {
comparison = 1;
} else if (b.length < a.length) {
comparison = -1;
}
return comparison;
});
const leaderBoard = sortable.reduce((acc, item) => {
const key = item[0].winner;
acc[key] = item;
return acc;
}, {});
return leaderBoard;
}

/**
* Calculate the donations for a user
* @param {Array} donations - The user's donations
* @returns {String} - The sum of donations
*/
static calculateDonation(donations) {
const donationSum = donations.reduce((acc, donation) => {
const amount = parseInt(donation.amount.split('$')[1], 10);
acc += amount;
return acc;
}, 0);
return `$${donationSum}`;
}

/**
* Get usernames of players
* @param {Array} players - The game players
* @returns {Array} - The array of player usernames
*/
static getPlayers(players) {
const playersNames = players.reduce((acc, player) => {
acc.push(player.username);
return acc;
}, []);
return playersNames;
}
/**
* Set up pagination variables
* @param {Object} req - The HTTP response
* @returns {Object} - The setup
*/
static setupPagination(req) {
const setup = {};
setup.page = req.query.page > 0 ? req.query.page : 1;
setup.limit = req.query.limit > 0 ? req.query.limit : 10;
setup.offset = (setup.page - 1) * setup.limit;
return setup;
}

/**
* Pagination
* @param {Number} page - The current page
* @param {Number} count - The total number of data
* @param {Number} limit - The data limit for each page
* @returns {Object} - The pagination object
*/
static pagination(page, count, limit) {
const pagination = {};
pagination.dataCount = count;
pagination.page = page;
pagination.pageCount = Math.ceil(count / limit);
pagination.limit = limit;
return pagination;
}
}

3 changes: 2 additions & 1 deletion app/views/includes/foot.jade
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ script(type='text/javascript', src='/lib/bootstrap/js/bootstrap.js')

//AngularJS
script(type='text/javascript', src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js")
script(type='text/javascript', src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js")
script(type='text/javascript' src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-route.js")

script(type='text/javascript', src='https://code.angularjs.org/1.6.1/angular-resource.js')
Expand Down Expand Up @@ -50,6 +50,7 @@ script(type='text/javascript', src='/js/firebase.config.js')
script(type='text/javascript', src='/js/controllers/index.js')
script(type='text/javascript', src='/js/controllers/header.js')
script(type='text/javascript', src='/js/controllers/game.js')
script(type='text/javascript', src='/js/controllers/dashboard.js')
script(type='text/javascript', src='/js/init.js')

//Socket.io Client Library
Expand Down
12 changes: 10 additions & 2 deletions config/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { validateSignIn } from './middlewares/validateSignIn';
import validator from './middlewares/validator';
import auth from './middlewares/checkToken';
import saveGame from '../app/controllers/games';
import game from '../app/controllers/games';

module.exports = function (app, passport) {
// User Routes
Expand Down Expand Up @@ -102,6 +102,14 @@ module.exports = function (app, passport) {
'/api/games/:id/start',
auth.verifyToken,
validator.gameValidation,
saveGame
game.saveGame,
);
// Game history API endpoint
app.get('/api/games/history', auth.verifyToken, game.gameHistory);

// User donations API endpoint
app.get('/api/donations', auth.verifyToken, users.getDonations);

// Leaderboard API endpoint
app.get('/api/leaderboard', auth.verifyToken, game.gameLeaderboard);
};
Loading

0 comments on commit cf8ced0

Please sign in to comment.