From: dbucklin@sdf.org
Date: 2018-10-24
Subject: Using GNU Recutils to Track Car Maintenance History

I have an older car that needs regular maintenance.  My maintenance
history is stored on a pile of crumpled  papers  in  the  glovebox.
This  makes  it  hard to get a holistic picture of my car's mainte-
nance history.  It's good to know what you've  had  done  when  the
service department is making recommendations.

There are services like Carfax that will provide a detailed history
for a little money, but the value of something like  Carfax  is  to
see  maintenance  records  for a used car before you buy it, not to
track maintenance on a vehicle you already own.   Plus,  I  already
have two years of maintenance data sitting in the glovebox.

What information to track?  I've created a class diagram to help me
think through this.

     @startuml
     'render at plantuml.com/plantuml
     
     class Car
     class Activity
     class Provider
     
     Car: make
     Car: model
     Car: year
     
     Activity: date
     Activity: mileage
     
     Service: description
     
     Provider: name 
     Provider: address 
     Provider: city 
     Provider: state
     Provider: zip
     
     Car *-- Activity
     Provider *-- Activity
     Activity *-- Service
     @enduml

So  we have a **Car** that represents my Honda, a **Provider** like
Jiffy Lube, an **Activity** representing a visit to the  shop,  and
**Service**  items that represent specific things that were done to
the car, like an oil change.

I'm going to change this a bit when I implement it in recutils.

* I only have one car, so I'm not going to associate data with a car.
* I'm going to merge the Activity and Service objects. There
  will be some duplication of data, but it will be easier to manage.
* I'll be doing all my reporting from the Service type, so that's
  where I'll store all the foreign keys.

Here is my recfile with all the field properties.   You  could,  of
course,  do  much of this in a spreadsheet, sacrificing some flexi-
bility.

     %rec: Service
     %key: Id
     %auto: Id
     %type: Provider rec Provider
     %type: Mileage int
     %sort: Mileage
     %mandatory: Id Date Mileage Description Provider

     %rec: Provider
     %key: Id
     %auto: Id
     %mandatory: Id Name

Now, I've gone through the nominally laborious task of  translating
my  service invoices into recfiles.  I had to summarize some of the
line items on the invoices.  I did this in an editor, but you could
also use recins, possibly within a script.

     %rec: Service
     %key: Id
     %auto: Id
     %type: Provider rec Provider
     %sort: Mileage

     Id: 1
     Date: 2017-06-12
     Mileage: 151140
     Description: Tire rotation
     Provider: 1

     Id: 2
     Date: 2017-06-12
     Mileage: 151140
     Description: Replaced thermostat, refilled and bled cooling system
     Provider: 1

     Id: 3
     Date: 2017-06-12
     Mileage: 151140
     Description: Replaced cabin air filter
     Provider: 1

     %rec: Provider
     %key: Id
     %auto: Id

     Id: 1
     Name: Honda Dealer

Now I can pull a succinct history using recsel.

     recsel -t Service -pDate,Mileage,Description service.rec

to get

     Date: 2018-09-10
     Mileage:
     Description: Reinstall FR bumper, clips

     Date: 2017-02-21
     Mileage: 148881
     Description: Minor inspection

     Date: 2017-02-27
     Mileage: 149003
     Description: Oil Change

I  can  limit  the data returned using a selection expression.  For
example, I can have it show only oil changes.

     recsel -t Service -e 'Description = "Oil Change"' -pDate,Mileage,Description service.rec

to get

     Date: 2017-02-27
     Mileage: 149003
     Description: Oil Change

     Date: 2017-10-20
     Mileage: 155328
     Description: Oil Change

     Date: 2018-01-03
     Mileage: 158262
     Description: Oil Change

It would be pretty neat to see how many miles had  elapsed  between
oil changes.  I think awk would be a good tool for this.  First, we
need to transform these vertical  records  into  linewise  records.
There  are  probably  a  number  of ways to do this.  Here's an awk
script that does the job.

     awk '/./ {ln = ln $0 "\t"}; /^$/ {print ln; ln = ""};'

You could also do it in sed like this:

     sed -ne '/./ H;/^$/ {x;s/^\n//;s/\n/\t/g;p};${g;s/^\n//;s/\n/\t/g;p}'

One more thing we need to do is strip the  field  labels  from  the
output  of recsel.  This is easily done by changing the `-p` option
to `-P`.  So, to get tabular output, we pipe the output  of  recsel
into awk.

     recsel -t Service -e 'Description = "Oil Change"' -PDate,Mileage,Description service.rec | awk '/./ {ln = ln $0 "\t"}; /^$/ {print ln; ln = ""};'

to get

     2017-02-27      149003  Oil Change
     2017-10-20      155328  Oil Change
     2018-01-03      158262  Oil Change
     2018-05-17      162140  Oil Change

Now we can do some math with another awk script.  This script looks
at the mileage on each line, subtracts the mileage from the  previ-
ous line, and displays the difference at the end of the line.

     awk '{print $0 "\t" $2-prev; prev = $2}'

We can pipe the output of the previous command into this awk script

to get

     2017-02-27      149003  Oil Change              149003
     2017-10-20      155328  Oil Change              6325
     2018-01-03      158262  Oil Change              2934
     2018-05-17      162140  Oil Change              3878

My guess is I lost a service record for  an  oil  change  somewhere
during  June  2017.  I could check my credit card statements during
that period to see if I can find a payment to an auto shop.  I like
to  think that I'm diligent about oil changes, but I can see I have
some room for improvement.

More ideas:

* Add an Exhibit Number to each Service record so that you
  can quickly find the specific paper maintenance record that it
  came from.
* Use a plotting tool like GNUplot or Google Charts to plot
  mileage or expense over time.
* Track maintenance expenses against the market value of the
  car to help you decide when to replace it.
* Print a succinct maintenance history to keep in your glovebox.