Last active
June 3, 2020 14:33
-
-
Save Matt-T-Git/0a37f918b02fbd1944e62c051aaa3001 to your computer and use it in GitHub Desktop.
Technical exercise answer with comments -- Company House Challenge
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
/** | |
* Technical Exercise Answer, Companies House | |
* Mathew Thomas 16/05/2020 | |
*/ | |
const express = require('express'); // Express NodeJS module | |
const path = require('path'); // Path NodeJS module | |
const bodyParser = require('body-parser'); // Body-Parser NodeJS module | |
const port = 8080; // Define port as 8080 as per exercise requirements | |
const app = express(); // Create app object | |
app.use(bodyParser.json()); // app use bodyparser | |
/* This data would usually be stored in a database but, | |
for the sake of this exercise I will define as a const */ // No SQL database, MongoDB perhaps? | |
// Define games data | |
const games = [ | |
{ | |
"title": "Uncharted 4", | |
"id": 1, | |
"description": "For the first time ever in Uncharted history, drive vehicles during gameplay", | |
"by": "Sony", | |
"platform": ["PS4"], | |
"age_rating": "16", | |
"likes": 100, | |
"comments": [{ | |
"user": "bob", | |
"message": "Cracking game far too much cinematic", | |
"dateCreated": "2011-01-03", | |
"like": 6 | |
}, { | |
"user": "testingPriest", | |
"message": "Not enough shooting for me,far too easy ", | |
"dateCreated": "2011-04-02", | |
"like": 5 | |
}] | |
}, | |
{ | |
"title": "Call of Duty, Infinite Warfare", | |
"id": 2, | |
"description": "Fast paced shooter", | |
"by": "Infiniward", | |
"platform": ["XBOX", "PS4"], | |
"age_rating": "18", | |
"likes": 40, | |
"comments": [{ | |
"user": "jim", | |
"message": "Awesome game", | |
"dateCreated": "2015-01-25", | |
"like": 7 | |
}, { | |
"user": "Dave", | |
"message": "Too many n00bs ", | |
"dateCreated": "2016-05-00", | |
"like": 8 | |
}, { | |
"user": "bob", | |
"message": "some comment", | |
"dateCreated": "2011-09-19", | |
"like": 2 | |
}, { | |
"user": "richard", | |
"message": "some other comment", | |
"dateCreated": "2011-10-19", | |
"like": 1 | |
}] | |
} | |
] | |
//// Part 2 Task //// | |
// Get Games Report | |
app.get('/games/report', (req, res) => { | |
console.log('Returning games report'); | |
/// Highest likes | |
var highestLikes = getMax(games, "likes"); // Get the game with highest number of likes -- (getMax function below) pass in array and key of json object to compare | |
/// Most comments | |
var comms = []; // Init comments array | |
var usrs = []; // Init users arry | |
var msgs = []; // Init messages array | |
// Loop through games array and extract comments array into its own array -- comms (minus the game info -- title etc...) -- just to make simpler cleaner data to work with | |
for (var i = 0; i < games.length; i++) { | |
comms.push(games[i].comments); | |
} | |
// Loop through comms array and extract each message object into its own array (msgs) we now have an array of only comnments - no info on which comment belongs to which game | |
for (var i = 0; i < comms.length; i++) { | |
if (comms.hasOwnProperty(i)) { | |
msgs.push(comms[i]); | |
} | |
} | |
// As we still have messages as an array of arrays we need to join the arrays to create a sinlge array then extract only the user key value and push to array containing only the users (usrs) | |
var mergedMessgaeArray = [].concat.apply([], msgs); | |
for (var i = 0; i < mergedMessgaeArray.length; i++) { | |
usrs.push(mergedMessgaeArray[i].user); | |
} | |
// Avg likes per game | |
var gameArr = []; // Init array to hold new game objects | |
// Loop over the games array | |
for (var i = 0; i < games.length; i++) { | |
// Loop each game in the games array | |
for (game of games) { | |
// Create a new game object (gme) to append to our game array (gameArr) | |
var gme = new Object(); | |
gme.title = game.title; // Append game title to gme object | |
gme.comments = game.comments; // Append game comment to gme object | |
gme.commentCount = gme.comments.length; // Set gme object commentCount property to ammount of comments the object has | |
var commentTotalValue = 0; | |
// Loop through the gme object comments and appnend the likes value to a variable (commentTotalValue) | |
for (var c of gme.comments) { | |
commentTotalValue += c.like; | |
} | |
// Get the avg likes value by dividing the total comment count (commentTotalValue) by the gme object total number of comments (gme.commentCount) & round up to the nearest integer using Math.ceil | |
gme.averageLikeValue = Math.ceil(commentTotalValue / gme.commentCount); | |
// Create an object thatr contains the game title and avg likes & push to gameArr array | |
var obj = new Object(); | |
obj.title = gme.title; | |
obj.average_likes = gme.averageLikeValue; | |
gameArr.push(obj); | |
} | |
} | |
// Return Object --> Create our return object (Gather all data relevant data into an obj) | |
var returnObject = new Object(); | |
returnObject.user_with_most_comments = highest(usrs); // Set obj user with the most comments (using highest function below) | |
returnObject.highest_rated_game = highestLikes.title; // Set obj ighest rated game title | |
returnObject.average_likes_per_game = gameArr; // Set avg like per game array | |
res.send(returnObject); // Return the object | |
}); | |
//// Part 1 Task //// | |
// Get game by ID | |
app.get('/games/**', (req, res) => { | |
console.log('Returning game by ID'); | |
const gameId = parseInt(req.params[0]); // Get the game ID passed in the GET request | |
const foundGame = games.find(subject => subject.id === gameId); // Find the game in games where the game ID (subject.id) is equal to the game ID passed in the GET request | |
if (foundGame) { // If we find a game that matches the request the we assign the game attriubutes to the request attributes & return the foundgame object | |
for (let attribute in foundGame) { | |
if (req.body[attribute]) { | |
foundGame[attribute] = req.body[attribute]; | |
console.log(`Set ${attribute} to ${req.body[attribute]} in game: ${gameId}`); | |
} | |
} | |
res.send(foundGame); | |
} else { // If no game was found for the supplied ID we return a 404 and log to console 'game not found' | |
console.log(`Game not found.`); | |
res.status(404).send(); | |
} | |
}); | |
//// Helpers //// | |
// Get Max (compare array elements and find max) | |
function getMax(arr, prop) { // Pass in the array and element to parse | |
var max; | |
for (var i = 0; i < arr.length; i++) { // Loop through the games array | |
if (max == null || parseInt(arr[i][prop]) > parseInt(max[prop])) // compare each element Int value | |
max = arr[i]; // max holds each pass of the loop max | |
} | |
return max; // return the max | |
} | |
// Highest appearences (Pass array to compare key values) | |
// Get greatest of an array of objects key values using reduce function & compare element values | |
const highest = arr => (arr || []).reduce((acc, el) => { | |
acc.k[el] = acc.k[el] ? acc.k[el] + 1 : 1 | |
acc.max = acc.max ? acc.max < acc.k[el] ? el : acc.max : el | |
return acc | |
}, { k: {} }).max | |
// App listen on port 8080 | |
console.log(`Games service listening on port ${port}`); | |
app.listen(port); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment