Last active
December 31, 2015 23:00
-
-
Save sterlingwes/03064438de8dd031504b to your computer and use it in GitHub Desktop.
WIP Parser for Storytime Data
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
var Parser = require('./StorytimeParser') | |
var parser = new Parser('./hours2015') | |
var hours = parser.filterGt(7).toSheet() | |
var json = JSON.stringify(hours, null, ' ') | |
console.log(json) | |
require('fs').writeFileSync('./hours2015-sheet.json', json, 'utf8') |
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
var DEFAULT_UNITS = 'hours' | |
var HOURS_FROM_MILLISECONDS = 3600000 | |
var MINUTES_FROM_MILLISECONDS = HOURS_FROM_MILLISECONDS / 60 | |
var m = require('moment') | |
/* | |
* allows for manipulating the raw data stored by Storytime | |
* | |
* filepath (string) - expects a json file relative to the execution context | |
*/ | |
function StorytimeHoursParser (filepath) { | |
this.basis = this.json = require(filepath) | |
} | |
/* | |
* filters down hours to a single project | |
* | |
* projectName (string) lowercase matching | |
*/ | |
StorytimeHoursParser.prototype.fromProject = function (projectName) { | |
this.basis = this.json.filter(function (story) { | |
return story.project.toLowerCase().trim() === projectName | |
}) | |
return this | |
} | |
/* | |
* filter if hours value is greater than provided value | |
* | |
* ceil (number) to set max | |
*/ | |
StorytimeHoursParser.prototype.filterGt = function (ceil) { | |
this.max = ceil | |
return this | |
} | |
/* | |
* allows for defining the starting datetime from which we want values totaled | |
* | |
* time (datetime) must be parseable by momentjs constructor | |
*/ | |
StorytimeHoursParser.prototype.since = function (time) { | |
this.from = m(time).valueOf() | |
return this | |
} | |
/* | |
* convert a millisecond timestamp diff to minutes | |
* | |
* diff (integer) | |
*/ | |
StorytimeHoursParser.prototype.minutes = function (diff) { | |
return Math.round(diff / MINUTES_FROM_MILLISECONDS) | |
} | |
/* | |
* convert a millisecond timestamp diff to hours (with two decimals) | |
* | |
* diff (integer) | |
*/ | |
StorytimeHoursParser.prototype.hours = function (diff) { | |
return Math.round(diff / HOURS_FROM_MILLISECONDS * 100) / 100 | |
} | |
/* | |
* iterator for working with a story and it's hours | |
* | |
* hash (object) passed from the reducer in get() for accumulating values | |
* story (object) the current story which has {project, name, hours[]} | |
* sesh (object) the current hours object which has {start, end} times | |
*/ | |
StorytimeHoursParser.prototype.consolidateHours = function (hash, story, sesh) { | |
if (this.from && sesh.start < this.from) return | |
var consolidated = hash[story.project] = hash[story.project] || {} | |
consolidated = consolidated[story.name] = consolidated[story.name] || {} | |
var dateString = m(sesh.start).format('YYYYMMDD') | |
if (!consolidated[dateString]) consolidated[dateString] = 0 | |
var diff = sesh.end - sesh.start | |
var unitVal = this[this.units](diff) | |
if (this.max && unitVal > this.max) return | |
consolidated[dateString] += unitVal | |
} | |
/* | |
* iterate over everything and gather values | |
* | |
* value unit (string) hours | minutes (defaults to minutes) | |
* | |
* returns an object | |
* -> storyName (string) -> dateString (YYYYMMDD) -> minuteVal (number) | |
*/ | |
StorytimeHoursParser.prototype.get = function (units) { | |
this.units = units || DEFAULT_UNITS | |
var json = this.basis.reduce(function (hash, story) { | |
story.hours.forEach(this.consolidateHours.bind(this, hash, story)) | |
return hash | |
}.bind(this), {}) | |
return json | |
} | |
/* | |
* convert hours object into an array of objects where each object key can | |
* be a spreadsheet column | |
* | |
* returns an array of objects | |
*/ | |
StorytimeHoursParser.prototype.toSheet = function (units) { | |
var hoursObj = this.get(units) | |
var rows = [] | |
Object.keys(hoursObj).forEach(function (project) { | |
var projectHours = hoursObj[project] | |
Object.keys(projectHours).forEach(function (story) { | |
var storyHours = projectHours[story] | |
Object.keys(storyHours).forEach(function (date) { | |
rows.push({ | |
project: project, | |
story: story, | |
date: date, | |
value: storyHours[date] | |
}) | |
}) | |
}) | |
}) | |
// sort by (in order): | |
// - date (asc) | |
// - story (alpha asc) | |
return rows.sort(function (itemA, itemB) { | |
var dateCompare = itemA.date.localeCompare(itemB.date) | |
if (!dateCompare) { | |
return itemA.story.localeCompare(itemB.story) | |
} | |
return dateCompare | |
}) | |
} | |
module.exports = StorytimeHoursParser |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment