Skip to content

Instantly share code, notes, and snippets.

@pdahl95
Created May 15, 2019 18:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pdahl95/629764f0fae38cf847d4f9ded6c962eb to your computer and use it in GitHub Desktop.
Save pdahl95/629764f0fae38cf847d4f9ded6c962eb to your computer and use it in GitHub Desktop.
Tatati Hiring Homework
Start End Name
6:00 AM 12:00 PM Morning
12:00 PM 4:00 PM Afternoon
3:00 PM 8:00 PM Prime
Date Time Creative Spend Views
01/02/2016 8:30 AM TEST001H 120.50 100
01/02/2016 11:30 AM TEST001H 240.50 110
01/02/2016 3:30 PM TEST002H 500 80
01/02/2016 3:34 PM TEST002H 400 90
01/02/2016 3:40 PM TEST001H 400 110
02/02/2016 7:30 AM TEST001H 700 200
02/02/2016 7:30 PM TEST002H 700 300
body{
font-family: Tahoma, Verdana, Segoe, sans-serif;
}
.content {
background-color: #f9fbfd;
width: 95%;
height: 800px;
margin: auto;
box-shadow: 0px 0px 5px rgba(0, 0, 0, .1);
}
table{
width:80%;
padding-left: 2%;
margin: 10px 0px 10px 0px;
margin: 0 auto;
background-color: white;
border-collapse: collapse;
}
tr{
border: solid #f9fbfd;
border-width: 3px 0;
}
td{
padding: 15px;
cellspacing: 4;
}
th{
color: gray;
font-size: 16px;
font-weight: lighter;
text-align: left;
padding-top: 3%;
padding-left: 10px;
}
#spotReport, #rotationReport{
padding-top: 2%;
}
#overalView{
margin: 0 auto;
text-align: center;
width: 80%;
}
.column {
float: left;
width: 30%;
padding: 10px;
}
.row{
margin-left: 5%;
padding-bottom: 3%;
}
.row:after {
content: "";
display: table;
clear: both;
}
/**
* this function converts a csv string to a json array
* @param csv
* @returns {Array}
*/
function csvToJsonArray(csv) {
csv = csv.replace(/["]/g, ""); // csv is a string here, so we should get rid of double quotes
let jsonArray = [];
csv = csv.split("\n"); // split csv string using return TODO: file might have empty lines at the end => fix
let headers = csv[0].split(',');
for (let i = 1, length = csv.length; i < length; i++) {
let row = csv[i].split(',');
let temp = {};
for (let x = 0; x < row.length; x++) {
temp[headers[x]] = row[x];
}
jsonArray.push(temp);
}
return jsonArray;
}
/**
* this function reads a human readable time string am/pm format and sets it in a date object
* this will help us to find if spots fall in a rotation
* @param date
* @param timeString
*/
function setTimeToDate(date, timeString) {
// if time is pm I am adding 12 hours
if (timeString.includes("PM")) {
let time = timeString.replace("PM",""); // remove pm from string
time = time.trim(); // remove white space
date.setHours(Number(time.split(":")[0]) % 12 + 12); // get hour
date.setMinutes(Number(time.split(":")[1])); // get min
} else if (timeString.includes("AM")) {
let time = timeString.replace("AM","");
time = time.trim();
date.setHours(Number(time.split(":")[0]));
date.setMinutes(Number(time.split(":")[1]));
} else {
console.log("File format error!");
}
}
/**
* this will help us to find if spots fall in a rotation
* @param rotations
*/
function buildRotationMap(rotations) {
let map = {};
$.each(rotations, function (ind, row) {
let name = row["Name"];
map[name] = {};
map[name]["start"] = new Date();
map[name]["end"] = new Date();
setTimeToDate(map[name]["start"], row["Start"]);
setTimeToDate(map[name]["end"], row["End"]);
});
return map;
}
/**
*
* @param rotationTable
* @param time
* @returns {Array}
*/
function getMatchedRotations(rotationTable, time) {
let date = new Date();
setTimeToDate(date, time);
let matchedRotations = [];
$.each(rotationTable, function (key, rotation) {
if (date >= rotation['start'] && date <= rotation['end']) {
matchedRotations.push(key);
}
});
return matchedRotations;
}
function buildTableFromObject(object, where, header) {
var table = "<table>";
table += "<tr>";
$.each(header, function (idx, item) {
table += "<th>";
table += item;
table += "</th>";
});
table += "</tr>";
$.each(object, function (key, value) {
table += "<tr><td>";
table += key + "</td>";
$.each(value, function (k, v) {
table += "<td>";
table += v;
table += "</td>";
});
table += "</tr>";
});
table += "</tr>";
table += "</table>";
$(where).html(table);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body>
<div id="overalView">
<div class="row">
<div class="column" id="totalSpots"></div>
<div class="column" id="totalSpend"></div>
<div class="column" id="totalView"></div>
</div>
</div>
<div class="content">
<div id="spotReport"><h1>By Creative</h1></div>
<div id="rotationReport"><h1>By Day - Rotation</h1></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript" src="js/util.js"></script>
<script>
// assumption is made that spots.csv and rotations.csv will be accessed by a ajax call
// for the purpose of this homework I put them in asset folder and I get them using jquery get function
const spotsPath = "assets/spots.csv";
const rotationsPath = "assets/rotations.csv";
let rotationTable = {};
$.get(spotsPath, function (spotsTextFile) {
let spotsText = spotsTextFile;
$.get(rotationsPath, function (rotationTextFile) {
let rotationText = rotationTextFile;
let spots = csvToJsonArray(spotsText);
let rotations = csvToJsonArray(rotationText);
rotationTable = buildRotationMap(rotations);
// Overall view
let totalSpots = spots.length;
console.log(totalSpots);
$("#totalSpots").html("<h3> Total Spots </h3>").append(totalSpots);
let totalSpend;
$("#totalSpend").html("<h3> Total Spend </h3>").append(totalSpend);
let totalView;
$("#totalView").html("<h3> Total Views </h3>").append(totalView);
// Logic to generate by-creative view
let byCreativeView = {};
$.each(spots, function (ind, spot) {
var name = spot["Creative"];
if (!byCreativeView[name]) {
byCreativeView[name] = {};
byCreativeView[name]["spent"] = Number(spot["Spend"]);
byCreativeView[name]["view"] = Number(spot["Views"]);
} else {
byCreativeView[name]["spent"] += Number(spot["Spend"]);
byCreativeView[name]["view"] += Number(spot["Views"]);
}
byCreativeView[name]["cpv"] = Number(byCreativeView[name]["spent"]/byCreativeView[name]["view"]).toFixed(2);
totalSpend += Number(byCreativeView[name]["spent"]);
});
console.log(totalSpend)
buildTableFromObject(byCreativeView, "#spotReport", ["Creative", "Spend", "Views", "CPV"]);
// Logic to generate day-rotation view
let byDayRotationView = {};
$.each(spots, function (ind, spot) {
$.each(getMatchedRotations(rotationTable, spot["Time"]), function (ind, rotationName) {
let key = spot["Date"] +" "+ rotationName;
if (!byDayRotationView[key]) {
byDayRotationView[key] = {};
byDayRotationView[key]["time"] = key;
byDayRotationView[key]["spent"] = Number(spot["Spend"]);
byDayRotationView[key]["view"] = Number(spot["Views"]);
} else {
byDayRotationView[key]["spent"] += Number(spot["Spend"]);
byDayRotationView[key]["view"] += Number(spot["Views"]);
}
byDayRotationView[key]["CPV"] = Number(byDayRotationView[key]["spent"] / byDayRotationView[key]["view"]).toFixed(2);
});
});
buildTableFromObject(byDayRotationView, "#rotationReport", ["Day - Duration", "Spend", "Views", "CPV"]);
});
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment