-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature(game-log): user should be able to view a game log of past games
- add API endpoint to get games history - add API endpoint to get leaderboard - add API endpoint to get donations [Delivers #156882168]
- Loading branch information
1 parent
883c84a
commit cf8ced0
Showing
14 changed files
with
925 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.