I am a really lazy person, there, I said it. I also get distracted really often. These two things combined might be the worst thing that can happen to one’s productivity. After trying many methods of creating todo lists, I have settled on two. Markdown files for detailed note-taking, and todo.txt for the list of things to do. On my phone, the Simpletask Cloudless app did an amazing job of bringing some order into my chaotic schedule.

But I felt that I could use some more incentive to do work. Something to gameify my tasks, if you will. What better way do this than a fancy graph with some numbers. I decided to host the resulting graph on my website and regularly update it.

If you want to see the final result, you can see the code file here and the resulting graph here.

Parsing the todo file

Normally, we would need to parse the todo.txt format, but since we’re only going to look at the completed tasks, we can get by with some string splitting. Let’s write a Python function to “parse” the file and get some statistics from it.

def get_stats(filename):
    data = {}
    with open(filename) as todofile:
        for line in todofile:
            date = line.split()[1]
            if date in data:
                data[date] += 1
            else:
                data[date] = 1
    return data

This function returns a dictionary of dates and the number of tasks completed. There’s only one problem with this, the days where we did nothing are skipped, making our graph look wrong. To fix this, we will write another function to return the dates of the last 15 days. We’ll use the datetime library for this.

import datetime

def get_last_days(days):
    for day in range(days)[::-1]:
        date = datetime.datetime.today() - datetime.timedelta(days=day)
        yield date.date().isoformat() # Isoformat is 2017-04-18

After that we can collect these values on an array, which we will use to make our final graph. My todo archive is at the Sync folder, which is synchronized with my phone regularly.

stats = get_stats("/home/leonardo/Sync/default/done.txt")

todoCounts = []
for date in get_last_days(15):
    # Get the value from the todo.txt file
    # Use 0 as default
    todoCounts.append(stats.get(date, 0))

Creating the graph

The only thing left to do is plot these values on a graph. For the graph, we’ll use matplotlib. Let’s configure it a little so the graph looks like what we want.

import matplotlib.pyplot as plt

plt.grid(True)
plt.title("Todo.txt Progress")
plt.ylabel("Number of tasks done")

This should display a grid behind the line graph and add titles to make the plot more clear.

plt.yticks(range(max(todoCounts) + 1))
plt.xticks(range(15), get_last_days(15), rotation=80)

This will make the Y axis only have integers and get rid of fractional values, giving us a cleaner graph. It will also write the dates below the graph, rotated 80 degrees to fit together.

Let’s call the plot function to put the values into our graph and save it to my websites public folder.

plt.plot(todoCounts, marker="o")

plt.tight_layout()
plt.savefig("public/img/todo.jpeg", dpi=100)

Final words

I added this script to the hooks on my websites Makefile, so everytime I compile my blog it will get updated. One of the reasons I put it public is to give me some feeling of responsibility and judgement, even if practically no one will look at it.

Todo list graph


Hey everyone! Thanks for reading my blog post. If you enjoyed it, you can check out my other posts or subscribe via RSS. RSS is still relevant, right?