bdunagan
fill the void

Posted
26 June 2011 @ 3pm

Tagged
data

1 Comment

Visualizing GTD with 1.8K To-Dos in Things

I was poking around ~/Library/Application Support/ on my Mac and stumbled across the XML database for Cultured Code’s Things. Apparently, the first to-do I entered in Things was about Things.

While I’ve emptied the trash quite a few times since I began using Things in 2008, I still have 1.8K to-dos in the app, mostly in the logbook. I thought it would be interesting to plot them by month, using gRaphael.

Each month is a bar, and each January is a red bar. While I average around 50 to-dos each month, I added three times that number in July 2009, undoubtedly wedding tasks. Below is the Ruby script I wrote to process Things’s XML library and write out an HTML page with embedded gRaphael instructions:

# Require libraries
require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'time'

# Use Nokogiri and Xpath magic.
doc = Nokogiri::XML(open(File.expand_path("~/Library/Application Support/Cultured Code/Things/Database.xml")))
dates = doc.xpath("//object/attribute[@name='datecreated']").collect {|item| (Time.utc(2001,1,1) + item.content.to_f).strftime("%Y-%m-01") }
# Add up months and separate years (for gray/red bars).
counts_hash = {}
counts_months = []
counts_years = []
dates.each do |date|
  counts_hash[date] = 0 if !counts_hash.include?(date)
  counts_hash[date] += 1
end
counts_hash.keys.sort.each do |date_key|
  date = Time.parse(date_key)
  counts_months << ((date.month == 1) ? 0 : counts_hash[date_key])
  counts_years << ((date.month == 1) ? counts_hash[date_key] : 0)
end

# Write out the HTML and Javascript to make it work.
html = <<EOF
<html><head>
<script type='text/javascript' src='raphael-min.js'></script>
<script type='text/javascript' src='g.raphael-min.js'></script>
<script type='text/javascript' src='g.bar-min.js'></script>
</head><body>
<script type="text/javascript">
window.onload = function () {
// Add hover functions.
var fin = function () { this.flag = r.g.popup(this.bar.x, this.bar.y, this.bar.value || "0").insertBefore(this); };
var fout = function () { this.flag.animate({opacity: 0}, 60, function () {this.remove();}); };
// Graph with gRaphael.
var r = Raphael("thedata");
var chart = r.g.barchart(10, 10, 450, 100, [#{counts_months}, #{counts_years}], {stacked: true});
chart.bars[0].attr({"fill": "#666"});
chart.bars[1].attr({"fill": "#CD0000"});
chart.hover(fin, fout);
}
</script>
<div id="thedata" class="jsgraph"></div>
</body></html>
EOF
f=File.new("things.html","w")
f.write(html)
f.close

This script is also available through my GitHub repository.


1 Comment

[...] Digging around Things’s To Do list inspired me to tackle a larger personal dataset: iTunes. One feature I love about iTunes is play counts. The app keeps a cumulative count of how many times I’ve played any given track. These counts are maintained by my iPod and iPhone as well, so the numbers give an accurate picture of my music history. Combining those counts with track lengths, I can see how I spend my days in iTunes. [...]


Leave a Comment