Skip to content

Instantly share code, notes, and snippets.

@jaredwilli
Created October 17, 2017 15:38
Show Gist options
  • Save jaredwilli/c76778a5a4c758574063b16eea817514 to your computer and use it in GitHub Desktop.
Save jaredwilli/c76778a5a4c758574063b16eea817514 to your computer and use it in GitHub Desktop.
Coding Challenge
/**
* 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);
<!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