Creating My Ultimate Packing List

I wonder if there is such a thing as over automating mundane tasks with a computer. Sometimes I feel that I might put more time into developing a computer based solution to a problem that far exceeds the amount of time it would take with a traditional method. Of course, this omits the benefits of practicing problem-solving and the possibility that it may ultimately take less time than if I would otherwise have to repeat the traditional method many times. Next week I am moving across the Atlantic and I don’t want to miss bringing anything important (I am notorious for forgetting small but important things at home). I decided to write a very simple script to produce a checklist that will keep my packing on track.

A couple of months ago, I discovered the Todo.txt system for managing my todo list. If you are not familiar with Todo.txt, it is a very simple method of keeping a todo list in… you guessed it… a text file! Obviously, this is nothing new or profound but the community at todotxt.com, specifically the originator Gina Trapani have defined a syntax for a todo list and have written a collection of applications to view and modify the todo file. When the todo.txt file is coupled with applications that can access Dropbox, you end up with a very simple system that can keep a todo list synchronized and usable on pretty much any platform that has Internet connectivity (in my case a laptop running Linux and my Android cellphone).

Below is a simple example of todo.txt syntax:

(A) Complete readings for economics lecture 5 @Home
(A) Submit course registration @School
(C) Organize shampoo in the shower @Home

The letter in parentheses represents the task priority from A-Z, the text is the task and the word after the ‘@’ represents a location or category for the task. For example, if you are at home, you can use the todo.txt apps (or just grep) any tasks for @Home.

So what does all this have to do with packing!? When I sat down to start my packing list for the move, I decided that I wanted to write it as a text file on Dropbox so that if I ever remembered something to add, I could add it right away instead of waiting until I got to the specific device that had the list. I decided against paper simply since it can get really messy if you keep brain dumping on the same sheet of paper… and if it gets lost… I just fell naturally into writing the packing list in something similar to todo.txt. In my case, I used the letter in parentheses to represent a category (‘C’ for clothes, ‘B’ for bike stuff, ‘T’ for toiletries, ‘E’ for electronics, etc). By keeping a category at the start of each row, I can easily sort my list by category or print out a mini-list for one category. I decided to use the ‘@’ notation to describe what bag or box the given item was being packed in, this way I could create a list to check each bag before the move.

Then I got a little carried away… I am an avid cyclist and will be bringing my bike with me in a box but I will also have several bike bags inside the box and each will have a list of bike-related items for example, I would have:

(B) Bike @BikeBox
(B) Pannier @BikeBox
(B) Tool Kit @Pannier
(E) Bike Computer @Pannier
(B) Bike Hand Pump @Pannier
(B) USB Front Bike Light @BikeBox

I decided that I wanted to print out the list, but I didn’t want to format it in a word processor in case I needed to add other items closer to packing day. This is when the computer geek in me got excited. It is no secret that I am a big fan of \LaTeX and I determined that the best way to get a good packing list would be to write a script to read in my todo.txt packing list and output a color-coded (by location) checklist as a pdf. The checklist would properly nest each of the packing locations and keep the categories separate within each location’s list. For example, in my list above, I would end up with a packing list for the bike box which would include the pannier and its sub-list, all sorted by category. Therefore I would end up with something like:

Bike Box
--- Bike (B)
--- Pannier (B)
--- --- Tool Kit (B)
--- --- Bike Hand Pump (B)
--- --- Bike Computer (E)
--- USB Front Bike Light (B)

The first step was to create a basic mock-up of the desired output in LaTeX:

\documentclass{letter}
\usepackage{color}
\usepackage{wasysym}

\let\olditem\item
\renewcommand\item{\olditem[$\Box$] }

\newenvironment{bagList}[2]
{
\par
$\Box$\textbf{#1}
\begin{itemize}
\color{#2}
}{ \end{itemize}}

\begin{document}

\begin{bagList}{Bike Box}{cyan}
\item Bike (B)
\begin{bagList}{Pannier (B)}{red}
\item Tool Kit (B)
\item Bike Hand Pump (B)
\item Bike Computer (E)
\end{bagList}
\item USB Front Bike Light
\end{bagList}

\end{document}

Giving the result:

testListPacking

The Code

*** Please go to the bottom of the page to find a collapsed frame with the full Python code.

I decided to write a Python script to read in my text based packing list and output the finished pdf. I selected Python since it is a simple object-oriented language that can be prototyped very quickly and can be called as a script. Python is also an excellent language for working with strings. The basic steps in the program are as follows:

  1. Read in the packing text file
  2. Create a list of items to pack
  3. Identify all of the unique packing locations ‘@’ symbols
  4. Create a tree of locations representing the idea that some bags might be stored in other bags or boxes
  5. Write a preamble with all the LaTeX declarations and environment definitions to a temporary file
  6. Write each item into the temporary file by travelling through the location tree
  7. Write a closing statement into the temporary file to end the document
  8. Call pdflatex to output the pdf
  9. Clean-up temporary files

LaTeX Constants

I set the following strings in the script that control the style of the LaTeX document. A new color is used for each location, therefore you need to have at least as many colors defined as locations. The preamble string has all of the LaTeX declarations and definitions that must be written before we start to add items. The post string simply contains the command to end the LaTeX document.

# Color list, need a different color for each location.  Add more if necessary.
latexColors = ['Bittersweet','Blue','Brown','CadetBlue','Cyan','DarkOrchid','ForestGreen','Goldenrod','JungleGreen','LimeGreen','Mahogany','Melon','Mulberry']

# The opening string for the LaTeX document, if you want to change the appearance of the lists look here
preamble = r'''\documentclass[12pt]{letter}
\usepackage[usenames,dvipsnames]{color}
\usepackage{wasysym}
\usepackage{enumitem}
\usepackage[margin=0.5in]{geometry}
\setlength\leftmargini {2em}
\setlength\leftmarginii {4em}
\setlength\leftmarginiii {6em}
\setlength\leftmarginiv {8em}
\let\olditem\item
\renewcommand\item{\olditem[$\Box$] }

% By using the itemize environment as a base, you are limited to 
% 4 levels of sub lists
\newenvironment{bagList}[2]
{
\par
%\vspace*{\baselineskip}
$\Box$  \textbf{#1}
\begin{itemize}[noitemsep, topsep=0pt]
\olditem[] % needed in case of immediately nested list
\vspace{-0.75\baselineskip}
\color{#2}
}{ \end{itemize}}

\begin{document}
'''

# The string to end the document
post = r'''\end{document}'''

Item Class

I wrote a simple class to represent each item that is in the list.
Each item has:

  1. A name
  2. A category
  3. A location

The __repr__ function allows me to change the way in which the item is printed in the LaTeX file, in this case I print the item name followed by its category.

# Define class for each item.  Each item has a category 
#(in brackets), a name and a location (after the @ sign)
class Item:
    def __init__(self, category, item, location):
        self.category = category
        self.item = item
        self.location = location

    def getCategory(self):
        return self.category

    def getItem(self):
        return self.item

    def getLocation(self):
        return self.location

    def __repr__(self):
        return "{0} {1}".format(self.item, self.category)

TreeNode Class

My main, and really only, challenge for this script was how to implement the tree of locations. It is necessary to determine the order of the locations before writing to the LaTeX file so as to ensure that nesting is properly managed. I am sure that there are many ways to implement this tree. The one I selected has the advantage of being simple and intuitive for this specific problem; however, if it was dealing with a very large tree, it would be very inefficient.

The algorithm I use for creating the tree is as follows:

  1. Generate a root node.
  2. Identify a set of the locations used in the list.
  3. If there are no locations in the set then end.
  4. For each location in the set:
    1. Search the list to see if this location is also an item, if so then set this location’s parent as the item’s ‘@’, else set the parent as root.
    2. Try to add the location to the tree (it will succeed if the location’s parent is already in the tree).
    3. If the insertion succeeded, remove this location from the set.
  5. Goto 3.

When you try to add an element to the tree, you specify its name and the name of its parent. The tree is traversed and if its parent is found then the element is added below it and the addition returns True. If the element cannot be added then the addition returns False. By taking the set of locations and repeatedly attempting to add each location you will eventually add all of the elements into the location tree.

# A very simple tree class.  This class automatically places 
# new nodes below the specified parent.  If the parent does 
# not exist, it does not enter the new node.
class TreeNode:
    def __init__(self, name):
        # desc is a dictionary of child nodes, the key is the 
        #  node name and the value is another TreeNode object
        self.desc = dict()
        self.name = name

    # Add a child node
    def addDesc(self, pt, parent):
        if parent == self.name:
            self.desc[pt.getName()] = pt
            return True
        else:
            for k in self.desc.keys():
                # Recursively search for the specified parent
                if(self.desc[k].addDesc(pt, parent)):
                    return True
            # Return false if the parent cannot be found
            return False

    def getName(self):
        return self.name

    # Returns a list of descendants, descendants with their own 
    # children are returned as lists within the list (therefore
    # this will return a tree using the called node as the root)
    def getDesc(self):
        listorder = []
        listorder.append(self.name)
        keylist = list(self.desc.keys())
        keylist.sort()
        for k in keylist:
            dlist = self.desc[k].getDesc()
            listorder.append(dlist)
        return listorder

Writing the Items

In order to write each item to the LaTeX file, I wrote a recursive function that writes all of the items for a given location in the tree. If while the function is writing a location and it discovers an item that is also a location, it will call the recursive function for that location in order to nest it into the list.

# A recursive function to write the latex representation 
# of the tree to a file t
# t --> file descriptor
# location --> treeNode to use as root
# itemList --> list of items to print
# colorIndex --> the current color to use
def latexWrite(t, location, itemList, colorIndex):
    # Start the list for location
    t.write("\\begin{{bagList}}{{{0}}}{{{1}}}\n".format(location[0], latexColors[colorIndex]))
    colorIndex = colorIndex+1
    # Go through each item in the itemList
    for i in itemList:
        found = False
        # Check to see if the current item belongs in the 
        # current location
        if i.getLocation() == location[0]:
            # Check to see if the current item is actually 
            # another location
            for l in location:
                if i.getItem() == l[0]:
                    # If the item is a location, then write 
                    # the list for that location
                    colorIndex = latexWrite(t, l, itemList, colorIndex)
                    found = True
            if found == False:
                # If the item is not a location then write it into
                # the list for the current location
                t.write("\\item {0}\n".format(i))
    t.write("\\end{bagList}\n")
    return colorIndex

Result

Once the code is called it uses subprocess to call pdflatex (this makes this script work only on Linux machines with pdflatex installed but I am sure you could set it up to call a pdf->latex program in Windows). The following is a capture of part of my actual packing list relating to the bike box:
finalList

This is the complete code for my packing list compiler:

#!/usr/bin/python

import sys
import re 
import subprocess
import os
import shlex

# Color list, need a different color for each location.  Add more if necessary.
latexColors = ['Bittersweet','Blue','Brown','CadetBlue','Cyan','DarkOrchid','ForestGreen','Goldenrod','JungleGreen','LimeGreen','Mahogany','Melon','Mulberry']

# The opening string for the LaTeX document, if you want to change the appearance of the lists look here
preamble = r'''\documentclass[12pt]{letter}
\usepackage[usenames,dvipsnames]{color}
\usepackage{wasysym}
\usepackage{enumitem}
\usepackage[margin=0.5in]{geometry}
\setlength\leftmargini {2em}
\setlength\leftmarginii {4em}
\setlength\leftmarginiii {6em}
\setlength\leftmarginiv {8em}
\let\olditem\item
\renewcommand\item{\olditem[$\Box$] }

% By using the itemize environment as a base, you are limited to 4 levels of sub lists
\newenvironment{bagList}[2]
{
\par
%\vspace*{\baselineskip}
$\Box$  \textbf{#1}
\begin{itemize}[noitemsep, topsep=0pt]
\olditem[] % needed in case of immediately nested list
\vspace{-0.75\baselineskip}
\color{#2}
}{ \end{itemize}}

\begin{document}
'''

# The string to end the document
post = r'''\end{document}'''

# Define class for each item.  Each item has a category (in brackets), a name and a location (after the @ sign)
class Item:
    def __init__(self, category, item, location):
        self.category = category
        self.item = item
        self.location = location

    def getCategory(self):
        return self.category

    def getItem(self):
        return self.item

    def getLocation(self):
        return self.location

    def __repr__(self):
        return "{0} ({1})".format(self.item, self.category)

# A very simple tree class.  This class automatically places new nodes below the specified parent.  If the parent does not exist, it does not enter the new node.
class TreeNode:
    def __init__(self, name):
        # desc is a dictionary of child nodes, the key is the node name and the value is another TreeNode object
        self.desc = dict()
        self.name = name

    # Add a child node
    def addDesc(self, pt, parent):
        if parent == self.name:
            self.desc[pt.getName()] = pt
            return True
        else:
            for k in self.desc.keys():
                # Recursively search for the specified parent
                if(self.desc[k].addDesc(pt, parent)):
                    return True
            # Return false if the parent cannot be found
            return False

    def getName(self):
        return self.name

    # Returns a list of descendants, descendants with their own children are returned as lists within the list (therefore this will return a tree using the called node as the root)
    def getDesc(self):
        listorder = []
        listorder.append(self.name)
        keylist = list(self.desc.keys())
        keylist.sort()
        for k in keylist:
            dlist = self.desc[k].getDesc()
            listorder.append(dlist)
        return listorder

# A recursive function to write the latex representation of the tree to a file t
# Parameters: t --> file descriptor, location --> treeNode to use as root, itemList --> list of items to print, colorIndex --> the current color to use
def latexWrite(t, location, itemList, colorIndex):
    # Start the list for location
    t.write("\\begin{{bagList}}{{{0}}}{{{1}}}\n".format(location[0], latexColors[colorIndex]))
    colorIndex = colorIndex+1
    # Go through each item in the itemList
    for i in itemList:
        found = False
        # Check to see if the current item belongs in the current location
        if i.getLocation() == location[0]:
            # Check to see if the current item is actually another location
            for l in location:
                if i.getItem() == l[0]:
                    # If the item is a location, then write the list for that location
                    colorIndex = latexWrite(t, l, itemList, colorIndex)
                    found = True
            if found == False:
                # If the item is not a location then write it into the list for the current location
                t.write("\\item {0}\n".format(i))
    t.write("\\end{bagList}\n")
    return colorIndex
            
def main(argv):
    # Open file passed through args
    if len(argv) < 2:
        print("Too few arguments, need a filename")
        sys.exit(1)

    with open(argv[1], 'r') as l:
        itemList = []
        # Go through list and identify all of the storage containers @'s, each item can be represented by a category, a name and a storage container
        for line in l:
            # create an item
            if re.search('@',line):
                try:
                    itemList.append(Item(re.search('\((.+?)\)', line).group(1), re.search('\) (.+?) @',line).group(1), re.search('@(.+?)$',line).group(1)))
                except AttributeError:
                    print("Problem with line: {0}".format(line))
            else:
                try:
                    itemList.append(Item(re.search('\((.+?)\)', line).group(1), re.search('\) (.+?)$',line).group(1),''))
                except AttributeError:
                    print("Problem with line: {0}".format(line))
            

        # Create list of storage locations
        locations = []
        for item in itemList:
            if item.getLocation() != '':
                locations.append(item.getLocation())
        locations = list(set(locations))
        # Make sure there are enough colors
        if len(locations) > len(latexColors):
            print("Too many locations for colors, add more colors to the list")
            sys.exit(1)

    
        # Sort all items by category then by name
        itemList.sort(key = lambda item: (item.location, item.category, item.item))

        # Create the ordered list of locations in tree form
        locations.sort()
        tree = TreeNode ("root")
        # Iterate through all locations repeatedly until all locations are in the tree
        while(len(locations)!=0):
            locations_orig = list(locations)
            for location in locations_orig:
                # Does location have a parent
                parent = "root"
                for item in itemList:
                    if item.getItem() == location:
                        parent = item.getLocation()
                if tree.addDesc(TreeNode(location),parent):
                    locations.remove(location)

        # Get the tree into a list
        orderedList = tree.getDesc()
        # Put each item into the appropriate list and create the latex file
        with open('list.tex','w') as t:
            t.write(preamble)
            colorIndex = 0
            for item in orderedList:
                if isinstance(item, list):
                    colorIndex = latexWrite(t,item,itemList,colorIndex)
            # Write any items without a location
            for item in itemList:
                if item.getLocation() == '':
                    t.write("\par$\Box$ {0}".format(item))
            t.write(post)
        proc=subprocess.Popen(shlex.split('pdflatex list.tex'))
        proc.communicate()
        os.unlink('list.tex')
        os.unlink('list.log')
        sys.exit(0)

if __name__ == "__main__":
    main(sys.argv)

Application to Todo Lists

After writing this script, I realized that this could be used to create formatted copies of a todo.txt list. I do not make extensive use of the ‘@’ notation in my todo lists but if you did and were interested in creating a nested list, you could make sub-locations into items… unfortunately this would mean that you would have todos that aren’t exactly todos. For example:

(A) Pick up keys for new office @AdminBuilding
(A) Make dinner to freeze for Tuesday @Home
(B) Check tracking number on package
(A) AdminBuilding @University
(B) Meet with HR rep @AdminBuilding
(C) Get parking pass @ParkingCentre
(A) ParkingCentre @University
(D) Get to know the campus @University

This results in:
todo

Now I actually need to pack :P

Please feel free to leave any comments you have. I appreciate constructive feedback on my code.

Studying Engineering – A Survivor’s Guide (Part 2)

Not every strategy works for every student but I found a few tips over the years in Engineering that I feel helped me make it through and I wanted to pass these suggestions on to other students who may find them useful.

Numbers are essential in engineering, as they are in almost every field, and we work with them every day especially when we are working to understand engineering concepts. When I was in high school I was one of the students that would always ask the math teacher if I could use a calculator and then look moderately distraught when they said one wasn’t necessary (you know the type of person I mean :) ). I really started looking at numbers when one of my teachers brought in a slide rule and was using it to illustrate a lesson. I thought that it looked pretty interesting and so I found one and learnt how it worked. After a while I was using the slide rule to help with some of my physics labs. Then I made a strange conclusion, the slide rule sped me up…

My slide rule has a precision of 3 digits, doesn’t sound like much, my calculator that has 15 digits. However, I found that most of my answers still fell incredibly close to those of my classmates. I started to think about how much accuracy was really needed in the problems we were tackling (in high school), in my case normally no more than three, almost never more than 4. Using the slide rule improved my addition and subtraction since I started doing it in my head, for simple problems I started to realize that I could omit some digits of lower significance. Please don’t get me wrong the idea isn’t to say the world is fine without precision, it is an art (which I certainly have not mastered), what I am proposing is that it is beneficial to get to know what numbers mean. By having to process equations in parts using the slide rule versus just typing a long expression into a calculator, I became more focused on the intermediate answers as opposed to looking at only the final result. The intermediate results give you insight (particularly in physics) on the components of the problem, often if a mistake is made you will spot the error before you get to the final result, with a calculator it can be difficult to see where the mistake entered into your calculations.

After using the slide rule, I wondered how people had historically accessed trigonometric functions. I quickly tracked down a couple of good books of mathematical tables, each of which includes valuable sections on calculus as well. Using tables helps you to naturally get a “feel” for the standard functions we use every day. I believe that this “feel” for numbers is essential in engineering, it gives you a sense of when something seems odd about a result and can help you track down the cause of errors.

In University many of my classes did not allow calculators for the final exams. Since most calculators can do far more than arithmetic professors want a level field. Whenever calculators were not allowed professors would confine themselves to arithmetic problems that you could solve in your head. Now I would look on in embarrassment as a small number of colleagues lamented the lack of calculators.

I love my calculator, I don’t think there is any shame in using the tools available to us. Especially if you understand why you are doing the calculations a calculator is a great tool. After hearing a professor extol the virtues of the HP-35 and reverse polish notation (RPN), I purchased a remake of the classic calculator, the HP-35S. RPN is in my opinion a fantastic way of interacting with a calculator. Instead of typing 2+3 you type 2 3 +, the display has two lines so it looks just as if you were doing it on paper. Once your operation is complete, your answer is entered as the first operand for your next operation. In this way, you see all of the intermediary results of your expression. When I am working with an RPN calculator I often spot errors early and can correct them by reversing the last few operations. I don’t have to deal with typing in brackets and so using an RPN calculator normally has fewer key presses than an algebraic device.

Numbers are very important in engineering, I think everyone can agree on that, and I feel it is very important to develop a “feel” for the numbers you are using. I suggest that on top of a complete understanding of arithmetic (yes, it is instructive to understand long division) it is useful to have experience looking up or calculating trigonometric functions, understanding number systems and always checking your intermediate values in a calculation.

I would love to hear what strategies others have used to improve and hone their basic mathematical skills.

Making Your Résumé Beautiful And Maintainable With LaTeX

What is \LaTeX?

LaTeX is a document mark-up language that is used to define how text is laid out on a page. I think of it as a computer language that compiles into a document rather than a program. It allows you latitude in developing custom styles and allows you to treat your text documents as you would code. It takes some work to setup a document in LaTeX, but once it is done you will have a beautiful document that behaves exactly as you want and is very easy to update and maintain.

For a little over a year I have been using LaTeX to write my resume. I have found that it creates a reliable and attractive finished product that I can modify very easily. LaTeX gives you a lot of control over the formatting without forcing you to manage readjusting the layout yourself every time you make a change. When I got started it took me about a day to figure out how to compile the LaTeX and then assemble my resume. I based my initial draft off of one I found online but then I expanded some of the environments, as I will show below.

This post is to demonstrate one way of creating a LaTeX resume. Obviously your resume style may be very different from mine, indeed depending on the position my resume can look very different compared to the format used below. This post will not provide a step-by-step guide to getting LaTeX up and running. It is very easy to do in most Linux distributions and I believe that the following link should help Windows folks: TexLive.

Please click to see full resume code, see below for information on individual components. To see how this document looks when compiled look at the pdf at the bottom of the page.

% Modified Jul 5,2013

\documentclass[10pt, letterpaper, oneside]{article}

\usepackage{geometry}
\usepackage[T1]{fontenc}
\usepackage[dvipsnames]{color}
\usepackage{baskervald}
\usepackage{multirow}
\usepackage{tabularx}
\usepackage{multicol}
\usepackage{enumitem}

\pagestyle{plain}

\geometry{letterpaper,tmargin=1in,bmargin=1in,lmargin=1in,rmargin=1in,headheight=0in,headsep=0in,footskip=.3in}

\setlength{\parindent}{0in}
\setlength{\parskip}{0in}

% Name and contact information
\newcommand{\name}{Campbell Hennessy}
\newcommand{\street}{xxxxxx}
\newcommand{\city}{Smalltown ON}
\newcommand{\postal}{AAA AAA}
\newcommand{\phone}{(123) 456-7890}
\newcommand{\email}{campbell.hennessy@gmail.com}

% Colors
\definecolor{light-grey}{gray}{0.8}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Commands and Environments for resume

% A horizontal rule for sections
\newcommand{\HRule}[2]{\textcolor{#1}{\rule{\linewidth}{#2}}}

% A section tile command
\newcommand{\sectiontitle}[1]{\begin{minipage}{\textwidth}\HRule{black}{0.25mm}\vspace{-10pt}\begin{center}\Large\MakeUppercase{#1}\end{center}\end{minipage}\\\HRule{light-grey}{0.15mm}\vspace{\baselineskip}}

% An environment for a resume section
\newenvironment{ressection}[1]{
  \sectiontitle{#1}}
  {\vspace{-\baselineskip}}

% A ressection that has to be on one page, awards, education etc
\newenvironment{tightressection}[1]{
  \begin{minipage}{\textwidth}
  \sectiontitle{#1}}
  {\vspace{\baselineskip}\end{minipage}}

% A column if there is a two columned section such as in awards
\newenvironment{rescolumn}{
  \begin{minipage}{0.5\textwidth}
    \begin{itemize}[noitemsep,nolistsep]}
  {\end{itemize}
    \end{minipage}}

% A resitem is a simple list element
\newcommand{\resitem}[1]{
	\vspace{2pt}
	\item \begin{flushleft} #1 \end{flushleft}
}

% An entry for memberships
% Arg1: Board
% Arg2: Position
% Arg3: Date
\newcommand{\boardentry}[3]{
  \begin{minipage}{\textwidth}
  \vspace{-9pt}
  \textbf{#1}\\
  \textit{#2}, \textit{#3}\\
  \vspace{0.5\baselineskip}
  \end{minipage}
}


% An entry for education
% Arg1: Institution
% Arg2: Program
% Arg3: Dates
\newcommand{\resedentry}[3]{
  \begin{minipage}{\textwidth}
  \vspace{-10pt}
  \textbf{#1}\\
  \textit{#2}\hfill\textcolor{light-grey}{#3}\\
  \vspace{0.5\baselineskip}
  \end{minipage}
}

% Resentry defines a position
% Arg1: Position title
% Arg2: Company or Office---Company
% Arg3: Location, PROV
% Arg4: Date Range
\newcommand{\resentryheader}[4]{
	\vspace{-5pt}
	\textbf{#1}\hspace{\stretch{1}}\textcolor{light-grey}{#3}\\
	\textit{#2}\hspace{\stretch{1}}\textcolor{light-grey}{#4}\\
}

% This is a resume entry with a header and bullet items
\newenvironment{resentry}[4]{
  \begin{minipage}{\textwidth}
	\resentryheader{#1}{#2}{#3}{#4}
        \vspace{-\baselineskip}
	\begin{itemize}[noitemsep,nolistsep]
}{
	\end{itemize}
        \vspace{\baselineskip}
        \end{minipage}
}


%%%%%%%%%%%%
% Begin The Resume

\begin{document}

\begin{tabularx}{\linewidth}{X r}
\multirow{3}{*}{\Huge\textbf{\name}} & \\& \email\\\\
\end{tabularx}\\

\begin{ressection}{experience}
  \begin{resentry}{Inshore Rescue Boat Coxswain (Summers)}{Inshore Rescue Boat Program --- Canadian Coast Guard}{Hill Is, ON}{May 2012 --- Present}
    \resitem{Command a Coast Guard fast rescue craft (FRC) and Coast Guard station.}
    \resitem{Responsible for the on-site training and direction of two crewmembers.}
    \resitem{Responsible to respond within 15 minutes as the primary marine search and rescue unit in our operational area to search and rescue taskings provided by the Joint Rescue Coordination Centre.}
    \resitem{Responsible for carrying out public search and rescue prevention programs such as Pleasure Craft Courtesy Checks and informational interviews.}
  \end{resentry}

  \begin{resentry}{Lab Assistant}{Department of Electronics --- Carleton University}{Ottawa, ON}{January 2013 --- April 2013}
    \resitem{Assist in the labs for a new third year electrical engineering project course.}
    \resitem{Act as a consultant for the students on topics relating to embedded hardware and software design.}
    \resitem{Assist in diagnosing technical problems and directing students to appropriate technical resources.}
  \end{resentry}

  \begin{resentry}{Senior Campus Tour Guide}{Undergraduate Recruitment --- Carleton University}{Ottawa, ON}{September 2009 (Senior: October 2011) --- Present}
    \resitem{Provide 1.5 to 2 hour campus tours and information to prospective students and their families.}
%    \resitem{Work with other tour guides to staff departmental recruitment events.}
%    \resitem{Organize tour structure dynamically to present to the interests of the guests.}
    \resitem{As a Senior Guide, evaluate and advise new guides and participate in special recruitment events.}
    \resitem{Represent Carleton Engineering at the Ontario Universities Fair (2011 and 2012).}
  \end{resentry}

  \begin{resentry}{Research Assistant}{Department of Electronics --- Carleton University}{Ottawa, ON}{January 2012 --- May 2012}
    \resitem{Assisted Professor Alan Steele with research into open hardware electronics.}
    \resitem{Designed and tested circuits and sensors for use in a micro-aerial vehicle (MAV).}
    \resitem{Designed an integrated electronics platform for further MAV research based around the ATMega1284 microcontroller}
  \end{resentry}

  \begin{resentry}{Teaching Assistant}{Department of Mathematics and Statistics --- Carleton University}{Ottawa, ON}{September 2009 --- December 2011}
    \resitem{Ran weekly tutorial sessions for 30 to 40 students in engineering/business calculus and linear algebra.}
    \resitem{Marked all tests and assignments for students in my tutorial section.}
    \resitem{Provided students with weekly office hours to answer any questions and to provide additional assistance.}
  \end{resentry}

  \begin{resentry}{Inshore Rescue Boat Crew (Summers)}{Inshore Rescue Boat Program --- Canadian Coast Guard}{Hill Is. and Brebeuf Is., ON}{May 2010 --- August 2011}
    \resitem{Carried out responsibilities of a crew member on a Canadian Coast Guard FRC.}
    \resitem{Operated all equipment on the FRC including radio and electronic navigation systems.}
  \end{resentry}

  \begin{resentry}{Residence Fellow}{Department of Housing and Conference Services --- Carleton University}{Ottawa, ON}{August 2008 --- May 2010}
    \resitem{Worked within a team of all residence life staff in order to develop initiatives to create a welcoming environment for residence students.}
%    \resitem{Directed residents to appropriate University support services.}
    \resitem{Provided encouragement and support to students on my floor in residence.}
    \resitem{Helped resolve disputes between roommates and other students on the floor.}
%    \resitem{Designed active and passive programs to educate and involve students.}
  \end{resentry}

  \begin{resentry}{Kitchen Assistant}{Camp Chief Hector --- Calgary YMCA/YWCA}{Exshaw, AB}{May 2009 --- August 2009}
    \resitem{Worked as a kitchen assistant at an overnight children's summer camp.}
  \end{resentry}

  \begin{resentry}{Summer Orientation Leader (Parent Outreach)}{First Year Experience Office --- Carleton University}{Ottawa, ON}{May 2008 --- August 2008}
    \resitem{As a member of a team, engaged new university students and their families in informative sessions about academic and social life at Carleton University.}
 %   \resitem{Guided incoming students on campus tours.}
    \resitem{Kept informed of plans and programs at Carleton University and informed about general trends at 
Canadian Universities.}
    \resitem{Encouraged incoming students to get involved at Carleton.}
  \end{resentry}

  \begin{resentry}{Lifeguard/Swimming Instructor/Pool Staff}{Perth Indoor Swimming Pool}{Perth, ON}{August 2005 --- August 2007}
    \resitem{Worked as a lifeguard, swimming instructor and day camp councilor.}
  \end{resentry}

\end{ressection}

% Volunteer Experience
\begin{ressection}{Extra-Curricular/Volunteer work}
  \begin{resentry}{Medical First Responder}{Carleton University Student Emergency Response Team --- Carleton University}{Ottawa, ON}{September 2007 --- Present}
    \resitem{Work as a member within the team to provide medical first response services to Carleton University.}
    \resitem{Assist members of the Carleton community, using training as an Advanced Medical First Responder, with injuries or medical emergencies}
    \resitem{Cover at least one twelve hour shift and attend at least two hours of training each week}
  \end{resentry}

  \begin{resentry}{Trainer}{Carleton University Student Emergency Response Team --- Carleton University}{Ottawa, ON}{Sept 2010 --- Dec 2012}
    \resitem{Run weekly trainings for team members to review and improve their first aid skills.}
    \resitem{Develop practice and evaluation scenarios for members}
    \resitem{Hold office hours as necessary to give specific help to team members when needed.}
  %  \resitem{Assist in the evaluation of team members to determine their eligibility to go on call.}
  \end{resentry}

  \begin{resentry}{Conference Director}{2011 Mixer Committee --- Association of Campus Emergency Response Teams}{Ottawa, ON}{February 2011 --- November 2011}
    \resitem{Lead a team of volunteers to organize a national conference for campus emergency responders.}
    \resitem{Responsible for the overall financing and organizing the conference.}
    \resitem{Hosted over 160 delegates from universities in Ontario, Quebec and British Columbia for the 3 day conference.}
  \end{resentry}

\end{ressection}
    
% Awards
\begin{tightressection}{awards}
  \begin{rescolumn}
      \resitem{John Matheson Leadership Award (\$100), 2007}
      \resitem{Charles and Helen Pattenson Scholarship (\$3000), 2007}
      \resitem{Claude Bissell Scholarship (\$3000), 2008}
      \resitem{Murdoch Maxwell MacOdrum Scholarship (\$3000), 2009}
    \end{rescolumn}
  \begin{rescolumn}
      \resitem{David A. Golden Scholarship (\$3000), 2010}
      \resitem{Manimaran Kanagasabapathy Memorial Scholarship (\$1720), 2010 \& 2011}
      \resitem{Adrian D.C. Chan Award for Volunteer and Community Service (\$500), 2013}
      \resitem{University Medal for Engineering (Carleton University), 2013}
    \end{rescolumn}
\end{tightressection}

% Publications
\begin{tightressection}{academic presentations}
  \begin{itemize}[noitemsep,nolistsep]
    \resitem{Presentation: ``Design of an Open Source Hardware Sensor and Data Logging Unit''.  Presented at the National Conference on Undergraduate Research, University of Wisconsin - La Crosse, April 2013.}
    \resitem{Presentation of Unpublished Paper: ``Inside Everything: Strategies to Promote Taiwan's Continued Importance in the Global Semiconductor Market''. Presented at the National Chengchi University, Taipei, October 2012.}
  \end{itemize}
\end{tightressection}

% Qualifications
\begin{tightressection}{current qualifications}
  \begin{rescolumn}
      \resitem{Advanced Medical First Responder (St John Ambulance, re-certified September 2010)}
      \resitem{CPR Healthcare Provider Level (Ottawa Paramedic Service, re-certified September 2012)}
      \resitem{Standard First Aid/CPR C (Ottawa Paramedic Service, re-certified September 2012)}
      \resitem{Oxygen Administration \& AED (Ottawa Paramedic Service, re-certifiedSeptember 2012)}
    \end{rescolumn}
  \begin{rescolumn}
      \resitem{Small Vessel Operator Proficiency (Transport Canada, May 2010)}
      \resitem{Rigid Hull Inflatable Operator Training (Transport Canada, May 2010)}
      \resitem{Marine Emergency Duties A3 (May 2010)}
      \resitem{Marine VHF Operator License with DSC option (April 2010)}
      \resitem{Pleasure Craft Operator's Card}
    \end{rescolumn}
\end{tightressection}

%Boards and Committees
\begin{tightressection}{Boards and Committees}
  \boardentry{Carleton University Amateur Radio Club Executive}{Operations Executive}{September 2011 --- May 2013}
  \boardentry{Canadian Association of Campus Emergency Response Teams (ACERT)}{Member of the Board of Directors}{February 2012 --- May 2013}
  \boardentry{CUSERT Executive Selection Board}{Member (2011), Chair (2012)(2013)}{Annually in April, 2011 --- 2013}
  \boardentry{Adrian D.C. Chan Award Committee}{Student Member}{October 2011 --- March 2012}
  \boardentry{ACERT Mixer Committee}{Chair}{February 2011 --- November 2011}
  \boardentry{CUSERT Executive}{External-Communications}{May 2008 --- May 2009}
\end{tightressection}

% Education
\vspace{-15pt}
\begin{tightressection}{education}
  \resedentry{Carleton University}{Bachelor of Engineering (Computer Systems) (CGPA: 11.90/12)}{September 2009 --- May 2013}
  \resedentry{Carleton University}{Bachelor of Public Affair and Policy Management (Incomplete) (CGPA: 11.45/12)}{September 2007 --- April 2009}
\end{tightressection}

\end{document}

Document Setup

First you have to setup constants that define what packages to use (these are a part of LaTeX). I setup some constants for details on myself that I can use in the resume as well as a definition for a color I use to differentiate some text sections in the job entries.

\documentclass[10pt, letterpaper, oneside]{article}

\usepackage{geometry}
\usepackage[T1]{fontenc}
\usepackage[dvipsnames]{color}
\usepackage{baskervald}
\usepackage{multirow}
\usepackage{tabularx}
\usepackage{multicol}
\usepackage{enumitem}

\pagestyle{plain}

\geometry{letterpaper,tmargin=1in,bmargin=1in,lmargin=1in,rmargin=1in,headheight=0in,headsep=0in,footskip=.3in}

\setlength{\parindent}{0in}
\setlength{\parskip}{0in}

% Name and contact information
\newcommand{\name}{Campbell Hennessy}
\newcommand{\street}{xxxxxx}
\newcommand{\city}{Smalltown ON}
\newcommand{\postal}{AAA AAA}
\newcommand{\phone}{(123) 456-7890}
\newcommand{\email}{campbell.hennessy@gmail.com}

% Colors
\definecolor{light-grey}{gray}{0.8}

The documentclass defines the font and the page size. All of the usepackage statements allow you to use the stated LaTeX packages to add features to your resume. The geometry package for example, can change the margins instantly by editing the geometry line; since all of the spacing used in formatting is relative to the usable page space, you can change the margins and all of your resume items will adjust to use the space while keeping in line with your formatting rules. Each of the newcommand lines effectively generates a shortcut for inserting the information in the curly braces into the document. I used definecolor to create a color, light-grey, to use to highlight some sections of text in the resume.

Commands and Environments

I have organized my resume using custom LaTeX environments, these environments allow me to apply commands to the beginning and to the end of sections of text. I have also defined some of my own commands which are effectively shortcuts to call a series of other commands. If you follow through this section you can get a feel for how to develop your own commands and environments if you need features beyond what I use in my resume.

% A horizontal rule for sections
\newcommand{\HRule}[2]{\textcolor{#1}{\rule{\linewidth}{#2}}}

% A section tile command
\newcommand{\sectiontitle}[1]{\begin{minipage}{\textwidth}\HRule{black}{0.25mm}\vspace{-10pt}\begin{center}\Large\MakeUppercase{#1}\end{center}\end{minipage}\\\HRule{light-grey}{0.15mm}\vspace{\baselineskip}}

The HRule command creates a horizontal line of a given colour, I use these to divide sections in my resume. The sectiontitle command defines a title for a resume section such as “Work Experience”. By changing just this one line you can change the appearance of all of your section titles, no having to go through and highlight each line one at a time.

% An environment for a resume section
\newenvironment{ressection}[1]{
  \sectiontitle{#1}}
  {\vspace{-\baselineskip}}

The ressection environment allows you to create a basic resume section, it takes care of placing the title and making sure that there isn’t a large space between this section and the next.

% Resentry defines a position
% Arg1: Position title
% Arg2: Company or Office---Company
% Arg3: Location, PROV
% Arg4: Date Range
\newcommand{\resentryheader}[4]{
	\vspace{-5pt}
	\textbf{#1}\hspace{\stretch{1}}\textcolor{light-grey}{#3}\\
	\textit{#2}\hspace{\stretch{1}}\textcolor{light-grey}{#4}\\
}

% A resitem is a simple list element
\newcommand{\resitem}[1]{
	\vspace{2pt}
	\item \begin{flushleft} #1 \end{flushleft}
}

The two commands above are the basis for the experience entries in the resume. The first, resentryheader, creates a header with a job title, company, location and the dates worked. The second, resitem, inserts the details of the job. The commands are combined into the environment, resentry, below.

% This is a resume entry with a header and bullet items
\newenvironment{resentry}[4]{
  \begin{minipage}{\textwidth}
	\resentryheader{#1}{#2}{#3}{#4}
        \vspace{-\baselineskip}
	\begin{itemize}[noitemsep,nolistsep]
}{
	\end{itemize}
        \vspace{\baselineskip}
        \end{minipage}
}

The resentry creates a contained environment for work or volunteer positions. It ensures that each position is completely contained on the same page. This feature prevents a position from being spread across two pages (I find split entries to be distracting). Below you can see a sample work experience resume section with one job entry.

\begin{ressection}{experience}
  \begin{resentry}{Lab Assistant}{Department of Electronics --- Carleton University}{Ottawa, ON}{January 2013 --- April 2013}
    \resitem{Assist in the labs for a new third year electrical engineering project course.}
    \resitem{Act as a consultant for the students on topics relating to embedded hardware and software design.}
    \resitem{Assist in diagnosing technical problems and directing students to appropriate technical resources.}
  \end{resentry}
\end{ressection}

ExpSnip
While I don’t mind if my work experience sections flow across pages, I do not like it when some of the smaller resume sections such as education start on the end of a page and flow onto the next. To avoid this I created a special resume section environment, tightressection, which ensures the section stays on a single page.

% A ressection that has to be on one page, awards, education etc
\newenvironment{tightressection}[1]{
  \begin{minipage}{\textwidth}
  \sectiontitle{#1}}
  {\vspace{\baselineskip}\end{minipage}}

For some resume sections, such as awards, I can fit each entry using only half of the width of the page. I have an environment, rescolumn that can create columns using half of the side of a page.

% A column if there is a two columned section such as in awards
\newenvironment{rescolumn}{
  \begin{minipage}{0.5\textwidth}
    \begin{itemize}[noitemsep,nolistsep]}
  {\end{itemize}
    \end{minipage}}

The tightressection and rescolumn are used in my qualifications section to create a two-columned section that stays on a single page.

\begin{tightressection}{current qualifications}
  \begin{rescolumn}
      \resitem{Advanced Medical First Responder (St John Ambulance, re-certified September 2010)}
      \resitem{CPR Healthcare Provider Level (Ottawa Paramedic Service, re-certified September 2012)}
      \resitem{Standard First Aid/CPR C (Ottawa Paramedic Service, re-certified September 2012)}
      \resitem{Oxygen Administration \& AED (Ottawa Paramedic Service, re-certifiedSeptember 2012)}
    \end{rescolumn}
  \begin{rescolumn}
      \resitem{Small Vessel Operator Proficiency (Transport Canada, May 2010)}
      \resitem{Rigid Hull Inflatable Operator Training (Transport Canada, May 2010)}
      \resitem{Marine Emergency Duties A3 (May 2010)}
      \resitem{Marine VHF Operator License with DSC option (April 2010)}
      \resitem{Pleasure Craft Operator's Card}
    \end{rescolumn}
\end{tightressection}

Quals

Finally, I have special commands for education and positions on committees or boards. The special commands are seen below along with my education section to show their use.

% An entry for memberships
% Arg1: Board
% Arg2: Position
% Arg3: Date
\newcommand{\boardentry}[3]{
  \begin{minipage}{\textwidth}
  \vspace{-9pt}
  \textbf{#1}\\
  \textit{#2}, \textit{#3}\\
  \vspace{0.5\baselineskip}
  \end{minipage}
}


% An entry for education
% Arg1: Institution
% Arg2: Program
% Arg3: Dates
\newcommand{\resedentry}[3]{
  \begin{minipage}{\textwidth}
  \vspace{-10pt}
  \textbf{#1}\\
  \textit{#2}\hfill\textcolor{light-grey}{#3}\\
  \vspace{0.5\baselineskip}
  \end{minipage}
}

% Education
\vspace{-15pt}
\begin{tightressection}{education}
  \resedentry{Carleton University}{Bachelor of Engineering (Computer Systems) (CGPA: 11.90/12)}{September 2009 --- May 2013}
  \resedentry{Carleton University}{Bachelor of Public Affair and Policy Management (Incomplete) (CGPA: 11.45/12)}{September 2007 --- April 2009}
\end{tightressection}

education

Adapt and Update

Now that all the environments are defined it is very easy to add in new experience or sections. I always customize my resume for each application. Before moving to LaTeX, I kept a full resume that had all of my job experience with complete descriptions for each job. When I needed to prepare a resume for an application, I would copy and paste what I wanted into a new document. With LaTeX, I keep the complete resume in LaTeX. If I don’t want something in a particular application, I place a ‘%’ in front of any lines to be omitted. When the document is made, LaTeX ignores all lines prefixed by ‘%’. This allows me to quickly remove positions or even individual bullet points from job descriptions.

If you are used to working with code, you can take advantage of your favourite version control system to keep previous revisions of your resume or even to create specialized branches for specific applications. I have used Git in the past to track and collaborate on a large technical document and really appreciate the ability to treat text like code.

Please feel free to leave any questions or comments :)

PDF of the code above:

GDE Error: Error retrieving file - if necessary turn off error checking (404:Not Found)

Studying Engineering – A Survivor’s Guide (Part 1)

Having just completed my BEng (Computer Systems), I thought I would post what I feel are some helpful tips that I wish I had known earlier in my education. Over the years I had a few ah-ha moments in class. The earliest, and probably the most profound, occurred in our very first class in our introduction to engineering course. The professor found about ten different ways to tell us that engineering was incredibly difficult. His thesis seemed to be that we would struggle to get grades in the 60s. Of course there will be some students who will give it their all and just make it to the 60s but something didn’t sit right with me about that talk. As I went through my degree and talked to students in my year and in the years below I have come to the belief that there are four groups that walked out of that lecture.

1) The ones that listened, believed him and went on to never try to get past the 60s since the professor said that was enough.
2) The ones that listened, believed and gave up.
3) The ones that listened, believed and tried really hard and made it past the professor’s expectations. This group was often interesting because I found that they didn’t generally get the top marks. Some students get so convinced that engineering is so difficult that they dig too deep into the details. This is probably going to serve them very well in the future but tests are generally broad and conceptual so it didn’t yield as high of marks as someone who knew medium depth on everything.
4) Those who didn’t believe the professor and just did how they wanted to do.

What I hope you will take away from this post is that while engineering may be difficult, it is certainly not the hardest thing in the world but there are a lot of people who might try to convince you that it is nearly impossible. I feel that these people normally have your best interests at heart and think that if you hear engineering is difficult that it might make you work harder. Unfortunately, a lot of people seem to be discouraged, stagnated or stressed out by these comments. I started my University career in a degree on public policy. Comparing it to engineering, I found the difficulty to be fairly similar between programs. The degrees are different, but the difficulty and effort required were about the same. Surviving engineering begins, in my opinion, with having a positive attitude towards your chosen discipline. Do not get trapped under an artificial ceiling by people who are trying to get you to work hard by highlighting the difficulty ahead. Do your best not because you are told the program is hard but because it is what you want to do.

My taste in Linux: Arch Linux

I began using Linux almost immediately after buying my first computer in grade 11.  I remember ordering Ubuntu off of their ShipIt service.  When I first started using Linux, it could take me days to complete an install.  Then I would invariably crash the whole system within a few days.  Now a Linux install is almost second nature and I use various distributions on all of my devices.  I am not sure if it is Linux that has gotten easier, if it is me that has gotten better or if it’s the fact that I don’t need to wait 2 minutes for Google to get me search results over my parents’ dial-up modem.

Whenever I present tools in the future, I will almost always be discussing them from a Linux perspective.  Fortunately, many projects also work in Windows and Mac OS albeit with the necessary idiosyncrasies.  My preferred “flavor” of Linux is currently ArchLinux.  Really, I support users using whatever operating system they prefer.  There is nothing wrong with Mac, Windows or a Linux distribution.  Different users have different needs and preferences.

I have been using Arch for over a year now and I really appreciate the amount of control it gives me over my operating system and consequentially how I work.  Their community is fantastic and their Wiki is (dare I say) almost complete.  You can always find the information you are looking for or someone to point you in the right direction.

If you are coming to this page from another post:  I highly recommend you try installing Arch Linux (or another flavor such as Ubuntu) in a virtual machine to give it a try.  Most Windows and Mac machines should be able to run VirtualBox without difficulty.  Here is a tutorial on setting up ArchLinux in a VirtualBox.  I was planning on writing my own but then I found that site from Josh Braun and thought better of repeating the effort when such a good guide exists already.  Alongside the ArchLinux Beginners Guide this should allow you to have a smooth and educational introduction to Arch.