Timeline

I’ve been working on a new software project that I’m going to call “Timeline”. When I first learned C#, I wrote a simpler timeline program that I’ve used to keep track of “big” events like houses, vacations, jobs and projects. After getting the Jawbone fitness tracker, I wanted to add that data to my timeline program.

Instead of just adding that to my existing program, I decided to re-write the program to be more flexible. I wanted to be able to have events with child events and to “tag” people in events instead of having a copy of the event on each person.

The program is complete and I am currently submitting it to freeware sites. I didn’t release my first timeline program because it wasn’t able to handle incorrect inputs and it wasn’t very intuitive to use. I am going to release this version, so I’ve made the program more robust.

I am distributing the software on my Weissoft website: http://weissoft.com/timeline

This program took 90 hours to write and is 10965 lines of C# code along with 943 lines of php/javascript/html for the website. 4644 of the C# lines were generated by the GUI designer.

Publishing this software for others to use added about 20 hours to the project. This includes the time to write documentation, create a simple website to distribute it, add a lot more “bad input” checks to the code, create an error reporting system and made a “new user” screen. I didn’t include all the extra testing that I did since I would have had to find and fix those bugs eventually anyway.

Things that went well

I am happy with the error reporting system that I added to this program. When the application encounters an unexpected error (an uncaught exception), or an error that it can’t handle, the program brings up this dialog:

AppError

The user can fill in more information about what they were doing and an email address where I can contact them. The error report gets uploaded to my website and I get an email.

I used SQLite for the database the program writes user data to. I like having a format that can be accessed by external tools and the SQLite C# library is robust and easy to use.

I got all my graphics from TheNounProject.com. They provide a searchable set of free, simple, black and white images. They make great buttons and symbols. The images are free as long as you credit the creator in your software.

I really like the “Linq” tools in C#. They are an SQL like set of extension functions that operate on any list of data. You can select subsets of data, find items that match criteria, sort, etc. They take lambda functions as their parameter so you can use data contained in the list and local variables to do the logic. Here is an example from this program:

List<HealthDatum> healthDatum =
  HealthDatum.healthDatum(_person, leftDate, rightDate, true)
    .Where(datum => datum.Type.IsTracked &&
           (Properties.Settings.Default.ShowPrivate || !datum.IsPrivate))
    .OrderBy(datum => datum.Type.EntryType)
    .ThenBy(datum => datum.Start)
    .ToList();

This makes a list of all the health data WHERE the type of that data is “tracked” (displayed) and not private if we aren’t currently showing private data, ORDERed by the type of data, THEN by the start time.

Another C# feature that I found really handy are the tools for GUI threading. There are two ways of doing background tasks that I used in this program, and both were easier than they have been in the past.

I have an option to “compress” the Jawbone data to save space (Jawbone records step data every minute or so, and that adds up after a few months). I have a GUI option to do the compression, but the task can take several seconds. So I want to bring up a wait cursor and “lock” the GUI, but I don’t want it to look like the program has frozen. This used to require a Worker thread and creating a class to manage the background task. Now the code looks like this:

private void mCompressBtn_Click(object sender, EventArgs e)
{
  ... // Setup the GUI to tell the user what is happening
  Cursor.Current = Cursors.WaitCursor;
  Task.Run(() => { DBManager.compressData(mDatePicker.Value);}).Wait();
  Cursor.Current = Cursors.Default;
  ... // Setup the GUI to tell the user we are done
}

This code is the GUI click callback, so it would normally run in the main GUI event loop. It runs a background task to compress the data and waits for it to complete before executing the rest of the code in this function. However, it does this whole thing in another thread so that the main GUI doesn’t appear to lock up.

What could have gone better

I started with some code and designs from my first Timeline program which just tracked events. I made some early class hierarchy decisions for the code that draws events based on that design. When I added drawing the health data, I tried to cram it into the existing design. After fighting with drawing problems for a while, I scraped the design and started over.

I should have made the decision about whether to release the program at the start of the project. I ended up spending extra time going back to code that had already been written to make it more robust. Of course that introduced some bugs in code that I had already tested.

Future plans

I would like to add other fitness trackers (like Fitbit) to this software. But I am limited by the time it would take and because I’d have to buy a tracker from the other companies to test with. I’ll be watching for cheap trackers at garage sales and thrift stores.

I would also like to add some kind of automated tool that can find correlations between events. I track both mood and energy level, and I’d like to be able to find events (like sleep, exercise, etc) that predict future mood/energy. Once I have been using the program for several months, I’ll go back and see if I can find any correlations. If it works, I’ll add it to the program.

2 thoughts on “Timeline”

Leave a Reply