Skip to content

Instantly share code, notes, and snippets.

@sterlingwes
Last active December 31, 2015 23:00
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 sterlingwes/03064438de8dd031504b to your computer and use it in GitHub Desktop.
Save sterlingwes/03064438de8dd031504b to your computer and use it in GitHub Desktop.
WIP Parser for Storytime Data
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')
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