Created
October 17, 2017 15:38
-
-
Save jaredwilli/c76778a5a4c758574063b16eea817514 to your computer and use it in GitHub Desktop.
Coding Challenge
This file contains hidden or 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
/** | |
* Localytics Coding Challenge | |
* | |
* Written by Jared Williams | |
* http://github.com/jaredwilli | |
* | |
* Life would be so much easier if we only had the source code... | |
*/ | |
/** | |
* Details for Coding Challenge | |
* See the two tab delimited files attached: | |
* | |
* @param products.tab = A list of product names tab delimited with categories | |
* @param sales.tab = A list of product names tab delimited with sales amount | |
* | |
* From this data we'd like you to answer two questions: | |
* 1. What category has the highest average sales price? (Please include the average sale price) | |
* 2. What is the minimum and maximum sale in the category 'Breakfast' | |
* | |
* This comes from when someone worked at a company that made back office software for restaurants. You can imagine the second file is a Point of Sale record for the day. | |
* | |
* Please email the code in a zip file in approximately one hour, along with the answers. If you have trouble emailing us the code, please send us a private gist (gist.github.com). | |
* P.S. - We've had people install MySQL, import the data and provide the answer by executing queries. While that is a good approach, we'd rather see everything done within a self-contained, simple script. | |
* P.P.S - You can do this in any language. If you choose to use Java, here is an example on how to read a file: http://www.programcreek.com/2011/03/java-read-a-file-line-by-line-code-example/ | |
*/ | |
/** | |
* Check if File APIs are supported | |
*/ | |
function isFileSupported() { | |
if (window.File && window.FileReader && window.FileList && window.Blob) { | |
console.log('Great! Lets do this!!'); | |
return true; | |
} else { | |
console.error('The File APIs are not fully supported in this browser.'); | |
return false; | |
} | |
} | |
/** | |
* Format price values to two decimals | |
* @param {*} val | |
*/ | |
function _formatPrice(val) { | |
return parseFloat(Math.round(val * 100) / 100).toFixed(2); | |
} | |
function compare(arr) { | |
var obj = {}; | |
obj.min = arr.reduce(function(prev, curr) { | |
return prev[1] < curr[1] ? prev : curr; | |
}); | |
obj.max = arr.reduce(function(prev, curr) { | |
return prev[1] > curr[1] ? prev : curr; | |
}); | |
return obj; | |
} | |
/** | |
* Compare the data sets stored as arrays in objects for each file | |
* | |
* @param {*} fileArr | |
*/ | |
function getDetails(filesObj) { | |
// with es6 this would be done with arugment defaults | |
filesObj = filesObj || {}; | |
// Get the top 5 category by sales | |
if (filesObj.sales && filesObj.products) { | |
// Map the sales array and format the prices to 2 decimals | |
var formattedSales = filesObj.sales.map(function(sale) { | |
sale[1] = _formatPrice(sale[1]); | |
return sale; | |
}); | |
// sort the sales by price value highest to lowest and slice the top 5 | |
var top5 = formattedSales | |
.sort(function(a, b) { | |
return a[1] < b[1] ? 1 : -1; | |
}) | |
.slice(0, 5); | |
// Build output | |
var html = '<h2>Top 5</h2><ul>'; | |
top5.forEach(function(item) { | |
html += '<li>' + item[0] + ' - $' + item[1] + '</li>'; | |
}); | |
html += '</ul>'; | |
document.getElementById('top-five').innerHTML = html; | |
/** | |
* Breakfast | |
*/ | |
// Eat for breakfast - mmm :) | |
var breakfast = filesObj.products.filter(function(prod) { | |
return prod[1] === 'Breakfast'; | |
}); | |
var bfastList = []; | |
// kinda lost it here for a bit... crunch time | |
breakfast.forEach(function(bfast) { | |
formattedSales.forEach(function(sale) { | |
if (sale[0] === bfast[0]) { | |
bfastList.push(sale); | |
} | |
}); | |
}); | |
var minMax = compare(bfastList); | |
// Build output | |
var html2 = '<h2>Max/Min Product by Category: <b>Breakfast</b></h2><ul><li>Max: ' + | |
minMax.max[0] + ' - $' + minMax.max[1] + '</li><li>Min: ' + | |
minMax.min[0] + ' - $' + minMax.min[1] + '</li></ul>'; | |
document.getElementById('category').innerHTML = html2; | |
} | |
} | |
/** | |
* Handle file selection, reading the files and parsing the data into arrays | |
* @param {*} e | |
*/ | |
function filesSelected(e) { | |
// If File APIs supported | |
if (!isFileSupported()) { | |
return false; | |
} | |
var files = e.target.files; | |
var filesObj = {}; | |
// Loop over each file selected (if more than one) | |
for (var i = 0; i < files.length; i++) { | |
var reader = new FileReader(); | |
// Read the files in closure | |
reader.onload = (function(file) { | |
var fileName = file.name.split('.')[0], | |
fileArr = []; | |
return function(e) { | |
fileArr = e.target.result.split('\n').filter(String); | |
fileArr = fileArr | |
.map(function(line) { | |
return line.split('\t'); | |
}) | |
.sort(); | |
// Store each files data under the filename | |
filesObj[fileName] = fileArr; | |
// Handle the data for each file | |
getDetails(filesObj); | |
}; | |
})(files[i]); | |
reader.readAsText(files[i]); | |
} | |
} | |
var upload = document.getElementById('files'); | |
upload.addEventListener('change', filesSelected, false); |
This file contains hidden or 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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<title>Localytics Coding Challenge</title> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
</head> | |
<body style="padding: 20px; margin: 0 auto; width: 50%;"> | |
<label>Select product and sales CSV files: (multi-select)</label> | |
<input type="file" id="files" name="files[]" multiple /> | |
<div id="top-five"></div> | |
<div id="category"></div> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> | |
<script src="app.js"></script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment