Programming   |   UI & Design   |   Post-Production   |   Acting
Joseph Howes
Cosmos
MagnaStor
Woodshed
Universe At War
Programming

Overview

In a hurry?

Download a PDF of my resume.
See my GitHub page.

The broader the base, the taller the tower.

I love big challenges. The bigger, the better. My approach to code is much like my approach to art: When I envision the end goal, all the obstacles become stepping stones. I delegate when I have to, but I rarely seek experts. I become the expert.

COSMOS: A SPACETIME ODYSSEY

Episode 6: Deeper, Deeper, Deeper Still

I'm not gonna lie -- there was very little actual programming on this project (which mostly called for my modelling / animation skills). It is here because I was hired for my programming ability, and because I will be proud of participating in this event until the day I die.

I was called into Cosmos by the great filmmakers The Brownlee Brothers who were contracted to do two segments for this incredible television documentary series.

When I was researching a way to generate topaz, quartz, and kaolinite lattices that we could fly a camera through, I realized that in order to even approach accuracy, I would need a way to very quickly describe the positions of the atoms in 3-space, define the bonds, and have Blender generate a "lattice tunnel" procedurally. I implemented a quick-and-dirty Python module to do this for me, but realized that accurate lattices are so dense with geometry that we could never fly a camera through them and get the tunnel effect that was called for. We came up with a non-procedural compromise that worked out much better for the final product.

Responsibilities:

  • Implemented Python module to accurately and procedurally represent atomic positions and bonds for the lattice structures of topaz, quartz, and kaolinite.

MagnaStor

MagnaStor is a kernel-level archival filesystem which features constant data integrity checking, automatic offsite replication, and an easy-to-use interface for administering volumes.

I was originally contracted to assist for six months to help finish work on the kernel module and start a user interface layer. This turned into a six year project, where I became a part owner of the company. I was primarily responsible for feature implementation and bug fixing, but also directed marketing efforts and technical writing.

Responsibilities:

  • Implementation of kernel code in C and MOH.
  • Implementation of server-side userland infrastructure in C and MOH.
  • Implementation of GUI elements in AJAX with JSON structured communication with the backend, and also a Java GUI with a proprietary backend protocol.
  • Built a custom ticketing system in PHP backed by PostgreSQL which we used to track issues, cover regression testing, and coordinate builds and releases.

Woodshed Supermetronome

Woodshed Supermetronome is my own practise utility for musicians, available on the App Store. Musicians use it to build click tracks with varying sounds, time signatures, tempos, and durations.

Highlights

  • Implemented in Objective-C using Xcode.
  • Originally used manual reference counting, but recently learned ARC and switched the entire codebase over to it.
  • Used Instruments to test for memory leaks and performance issues.
  • Core concept was to base playback on sleep(), which turned out to be too imprecise. Researched writing directly to raw audio buffers and wrote my own abstraction layer so that absolute precision could be achieved.

Universe At War: Earth Assault

Realtime Strategy Game for xbox and Windows

At Petroglyph Games, I was honored to work with the legendary inventors of the realtime strategy genre on Universe At War: Earth Assault. Some of the greatest people and best programmers I have ever met in my life work there, and I am endlessly grateful to them for giving me the opportunity to bring this fantastic game to life.

Responsibilities:

  • Integration with Windows Live services in C++.
  • Implemented matchmaking front ends in Lua.
  • Implemented achievement tracking systen in C++.

Skills & Confidences

B.Sc. Computer Science from University of Calgary. Focused on computer graphics under Przemyslaw Prusinkiewicz. Assisted with research projects around creating tools for artists to easily define the gross parameters for L-systems, allowing them to quickly generate photorealistic plant life with high level controls.

For the values below, "years" indicate the total number of years during which I have actively used the skill, not the count of years since I learned it. For example, I first acquired the C++ skill ~20 years ago, and I have used it during 8 of those years.

Languages, APIs, Databases

C (12 years) MOH (6 years) Java (16 years) JavaScript (16 years) HTML (16 years) CSS (13 years) Full Stack Web Application Development (15 years) Database Development (15 years, Oracle, PostgreSQL, MySQL, SQLite) Multithreaded Processes (15 years) MOH (6 years, proprietary object-oriented framework for C) C++ (8 years) AJAX (4 years) jQuery (3 years) PHP (6 years) Python (2 years) Django (2 years) Objective-C (3 years) Unix Shell Scripting (14 years) Lua (2 years) Perl (1 year) C# (4 months) Unity Game Engine (4 months) OpenGL (2 years) nodejs (2 weeks) Web Sockets (2 weeks)

Tools

vi / vim / vile Mercurial (6 years) CVS (8 years) Windows Usage / Admin (19 years) Mac Usage / Admin (5 years) Unix Usage / Admin [FreeBSD, OpenBSD, Solaris, Linux] (19 years) Perforce (1 year) git (2 years) Xcode (4 years) Visual Studio (4 years) NetBeans (2 years) Eclipse (6 years)

Code Samples

I am generally unable to share the most interesting code I have written, because it is either valuable or does not belong to me. I am happy to show and demonstrate this code in person, but I will not share it on the web.

The samples here are intended to demonstrate my attention to coding standards and the correct use of comments. This is code that I am proud of, that I own entirely, and am able to share.

FizzBuzz (Java)

Let's get this out of the way right now.

public class FizzBuzz { public static void main(String[] args) { fizzBuzz(); } static void fizzBuzz() { try { for (int i = 1; i <= 100; i++) fbRender(i, System.out); } catch (IOException ioe) { ioe.printStackTrace(); } } static void fbRender(int i, OutputStream out) throws IOException { if ((i % 15) == 0) out.write("FizzBuzz\n".getBytes()); else if ((i % 3) == 0) out.write("Fizz\n".getBytes()); else if ((i % 5) == 0) out.write("Buzz\n".getBytes()); else out.write((i + "\n").getBytes()); } }

Defensive Quicksort (C)

This is a simple integer array sort, but with a demonstration of the defensiveness we practice for MagnaStor's kernel module. The error handling mechanism here is purposefully grossly inadequate for brevity. Our MOH framework features an error handling system that is fully featured, robust, and elegant.

The BSD KNF coding style here is indicative of the high value I place on adhering to (and strictly enforcing) a coding standard.

#include <stdarg.h> #include <stdlib.h> #include <stdio.h> #include <time.h> #define ERR_INVALARG 1U #define MAXERRSZ 1024 #define ERROR(code, ...) \ _error(code, __FILE__, __LINE__, __VA_ARGS__) typedef enum { ASCENDING, DESCENDING } direction; #define RANDBOUND 1000 #define NUMCOUNT 25 int _error(unsigned int code, const char *file, int line, const char *fmt, ...) { char msg[MAXERRSZ]; va_list ap; int sz; va_start(ap, fmt); sz = vsnprintf(msg, sizeof (msg), fmt, ap); va_end(ap); if (sz >= (sizeof (msg) - 1)) fprintf(stderr, "error message buffer (%lu) too small for message (%u)\n", sizeof (msg), sz); else fprintf(stderr, "error (%u): %s[+%d]: %s\n", code, file, line, msg); return (code); } void init(void) { time_t t; srand((unsigned) time(&t)); } int populatearray(int *arr, int arrcount) { int err; int i; if (arr == NULL) { err = ERROR(ERR_INVALARG, "arr is null"); return (err); } if (arrcount <= 0) return (0); for (i = 0; i < arrcount; i++) arr[i] = (rand() % RANDBOUND); return (0); } void dumparray(int *arr, int arrcount) { int err; int i; if (arr == NULL) return; if (arrcount <= 0) return; for (i = 0; i < arrcount; i++) printf("\t[%d]: %d\n", i, arr[i]); } void swap(int *i, int *j) { int tmp; if (i == NULL) return; if (j == NULL) return; tmp = *i; *i = *j; *j = tmp; } int staysleft(int piv, int val, direction dir) { if ((val <= piv) && (dir == ASCENDING)) return (1); if ((val >= piv) && (dir == DESCENDING)) return (1); return (0); } int staysright(int piv, int val, direction dir) { if ((val >= piv) && (dir == ASCENDING)) return (1); if ((val <= piv) && (dir == DESCENDING)) return (1); return (0); } int partition(int *arr, int arrcount, int start, int end, direction dir, int *res) { int right; int done; int left; int err; int piv; if (arr == NULL) { err = ERROR(ERR_INVALARG, "arr is null"); return (err); } if (res == NULL) { err = ERROR(ERR_INVALARG, "res is null"); return (err); } if (arrcount <= 1) return (0); /* * The joesort strategy relies on a terminal case (when the array count is * even) where the end argument may become negative. A negative end value * that is less than start is expected. */ if (start >= end) return (0); /* * If we reach this point, both start and end must be exactly in-bounds. */ if ((start < 0) || (start >= arrcount)) { err = ERROR(ERR_INVALARG, "start value (%d) out of bounds (%d)", start, arrcount); return (err); } if ((end < 0) || (end >= arrcount)) { err = ERROR(ERR_INVALARG, "end value (%d) out of bounds (%d)", end, arrcount); return (err); } piv = arr[start]; left = start + 1; right = end; done = 0; while (done == 0) { while ((left <= right) && staysleft(piv, arr[left], dir)) left++; while (staysright(piv, arr[right], dir) && (right >= left)) right--; if (right < left) done = 1; else swap(&arr[left], &arr[right]); } swap(&arr[start], &arr[right]); *res = right; return (0); } int joesort(int *arr, int arrcount, int start, int end, direction dir) { int err; int p; if (arrcount <= 0) return (0); /* * The joesort strategy relies on terminal cases where the start value may * reach arrcount. A greater value indicates programmer error. */ if ((start < 0) || (start > arrcount)) { err = ERROR(ERR_INVALARG, "start value (%d) out of bounds (%d)", start, arrcount); return (err); } /* * The joesort strategy relies on terminal cases where the end value may * dip down to -1. A lesser value indicates programmer error. */ if ((end < -1) || (end >= arrcount)) { err = ERROR(ERR_INVALARG, "end value (%d) out of bounds (%d)", end, arrcount); return (err); } /* * This check appears after the validity checks above so that it doesn't * hide clear cases of programmer error. */ if (start >= end) return (0); err = partition(arr, arrcount, start, end, dir, &p); if (err != 0) { ERROR(err, "failed to partition (%d to %d)", start, end); return (err); } err = joesort(arr, arrcount, start, p - 1, dir); if (err != 0) { ERROR(err, "failed to sort low partition (%d to %d)", start, (p - 1)); return (err); } err = joesort(arr, arrcount, p + 1, end, dir); if (err != 0) { ERROR(err, "failed to sort high partition (%d to %d)", p + 1, end); return (err); } return (0); } int main(void) { int arr[NUMCOUNT]; int err; init(); err = populatearray(arr, NUMCOUNT); if (err != 0) { ERROR(err, "failed to populate array (size %lu)", NUMCOUNT); return (err); } printf("before:\n"); dumparray(arr, NUMCOUNT); err = joesort(arr, NUMCOUNT, 0, NUMCOUNT - 1, ASCENDING); if (err != 0) { ERROR(err, "failed to sort array (size %lu)", NUMCOUNT); return (err); } printf("\nafter:\n"); dumparray(arr, NUMCOUNT); return (0); }

Grid Toy (Javascript)

This class is part of an internal tool I built for the development of a mobile / browser game I am working on called "Evolvis". The game involves creatures arranged in a grid who form patterns (think "Conway as a slot machine" mini-game within a greater, space-based IP). The game recognizes patterns with a brute-force bitmask stenciling strategy. I created GridToy as a tool to automatically generate the bitmask arrays for each cardinal rotation and reflection, with deduplication.

/** * Terminology * =========== * * Primary Table: * -------------- * The larger, leftmost, interactive table with which the user defines the * shape. * * Normal Table: * ------------- * The preview table which represents one of the four cardinal rotations. * * Horizontal Reflection Table: * ---------------------------- * The preview table which is a horizontal reflection of one of the four * cardinal rotations. * * Vertical Reflection Table: * -------------------------- * The preview table which is a vertical reflection of one of the four cardinal * rotations. */ function GridPreview(orientation, id, rows, cols) { this.COORDS_NORMAL = 1; this.COORDS_HREFLECT = 2; this.COORDS_VREFLECT = 3; this.orientation = orientation; this.id = id; this.normalKey = this.orientation + "N"; this.hReflectKey = this.orientation + "HR"; this.vReflectKey = this.orientation + "VR"; this.normalWrapObj = $("#" + id + "Normal"); this.hReflectWrapObj = $("#" + id + "HReflect"); this.vReflectWrapObj = $("#" + id + "VReflect"); this.normalIDGrid = new Array(); this.hReflectIDGrid = new Array(); this.vReflectIDGrid = new Array(); if (orientation == 90 || orientation == 270) { this.cols = rows; this.rows = cols; } else { this.cols = cols; this.rows = rows; } } GridPreview.prototype.update = function() { this.clear(); this.createTables(); } GridPreview.prototype.clear = function() { this.normalWrapObj.html(""); } GridPreview.prototype.createTables = function() { var html; html = this.getPreviewTableHTML(this.orientation, this.COORDS_NORMAL, this.normalIDGrid); this.normalWrapObj.html(html); html = this.getPreviewTableHTML("horiz", this.COORDS_HREFLECT, this.hReflectIDGrid); this.hReflectWrapObj.html(html); html = this.getPreviewTableHTML("vert", this.COORDS_VREFLECT, this.vReflectIDGrid); this.vReflectWrapObj.html(html); } GridPreview.prototype.getTransformedCoords = function(type, row, col) { switch(type) { case this.COORDS_NORMAL: return (this.getTransformedCoordsNormal(row, col)); case this.COORDS_HREFLECT: return (this.getTransformedCoordsHReflect(row, col)); case this.COORDS_VREFLECT: return (this.getTransformedCoordsVReflect(row, col)); default: alert("invalid type: " + type); } } GridPreview.prototype.getTransformedCoordsNormal = function(row, col) { var res; res = []; if (this.orientation == 0) { res[0] = this.rows - row - 1; res[1] = col; } else if (this.orientation == 90) { res[0] = col; res[1] = row; } else if (this.orientation == 180) { res[0] = row; res[1] = this.cols - col - 1; } else { res[0] = this.cols - col - 1; res[1] = this.rows - row - 1; } return (res); } GridPreview.prototype.getTransformedCoordsHReflect = function(row, col) { var res; res = []; if (this.orientation == 0) { res[0] = this.rows - row - 1; res[1] = this.cols - col - 1; } else if (this.orientation == 90) { res[0] = this.cols - col - 1; res[1] = row; } else if (this.orientation == 180) { res[0] = row; res[1] = col; } else { res[0] = col; res[1] = this.rows - row - 1; } return (res); } GridPreview.prototype.getTransformedCoordsVReflect = function(row, col) { var res; res = []; if (this.orientation == 0) { res[0] = row; res[1] = col; } else if (this.orientation == 90) { res[0] = col; res[1] = this.rows - row - 1; } else if (this.orientation == 180) { res[0] = this.rows - row - 1; res[1] = this.cols - col - 1; } else { res[0] = this.cols - col - 1; res[1] = row; } return (res); } GridPreview.prototype.getPreviewTableHTML = function(title, type, idGrid) { var xformed; var rowArr; var alive; var html; var cls; var eid; html = title + "<br>"; html += "<table cellspacing='1' cellpadding='0' border='0' " + "style='margin-bottom: 1em;'>"; for (var i = 0; i < this.rows; i++) { html += "<tr>"; rowArr = new Array(); for (var j = 0; j < this.cols; j++) { xformed = this.getTransformedCoords(type, i, j); eid = this.id + "N_" + xformed[0] + "_" + xformed[1]; rowArr.push(eid); alive = this.primaryCellIsAlive(xformed[0], xformed[1]); cls = "previewcelldiv"; if (alive) cls += " alive"; html += "<td>"; html += "<div id='" + eid + "' class='" + cls + "'>"; html += "</div>"; html += "</td>"; } html += "</tr>"; idGrid.push(rowArr); } html += "</table>"; return (html); } /** * Returns true if the cell at position row,col is alive in the primary table. */ GridPreview.prototype.primaryCellIsAlive = function(row, col) { var eObj; eObj = $("#" + row + "_" + col); if (eObj.css("background-color") == "rgb(0, 0, 0)") return (false); return (true); } GridPreview.prototype.getComment = function(shapeName) { var comm; comm = "\t/**\n"; comm += "\t * Shape: " + shapeName + "\n"; comm += "\t *\n"; for (var i = 0; i < this.rows; i++) comm += "\t * " + this.getCommentForRow(i) + "\n"; comm += "\t */\n"; return (comm); } GridPreview.prototype.getCommentForRow = function(row) { var comm; comm = ""; for (var i = 0; i < this.cols; i++) { if (this.cellIsAlive(this.normalIDGrid, row, i)) comm += "# "; else comm += ". "; } return (comm); } GridPreview.prototype.getCode = function(type) { var code; var grid; grid = this.normalIDGrid; if (type == this.COORDS_HREFLECT) grid = this.hReflectIDGrid; else if (type == this.COORDS_VREFLECT) grid = this.vReflectIDGrid; code = this.getCodeForGrid(grid); return (code); } GridPreview.prototype.getCodeForGrid = function(grid) { var first; var code; first = true; code = "new long[] {"; for (var i = 0; i < this.rows; i++) { if (first) first = false; else code += ","; code += this.getMaskForRow(grid, this.rows - i - 1); } code += "}"; return (code); } GridPreview.prototype.getMaskForRow = function(grid, row) { var eObj; var mask; var pos; var res; mask = 0x0; pos = 0x1; for (var i = 0; i < this.cols; i++) { if (this.cellIsAlive(grid, row, i)) mask |= pos; pos <<= 1; } return ("0x" + mask.toString(16) + "L"); } /** * Returns true if the cell at row,col is alive in the normal table. */ GridPreview.prototype.cellIsAlive = function(grid, row, col) { var rowArr; var eObj; var eid; rowArr = grid[row]; eid = rowArr[col]; eObj = $("#" + eid); if (eObj.css("background-color") == "rgb(0, 0, 0)") return (false); return (true); } GridPreview.prototype.getDims = function() { return ("new int[] {" + this.rows + ", " + this.cols + "}"); } GridPreview.prototype.getOffsets = function(grid) { var tcolOut; var tcol; var trow; tcol = null; trow = null; for (var i = 0; i < this.rows; i++) { for (var j = 0; j < this.cols; j++) { if (this.cellIsAlive(grid, i, j)) { trow = i; tcol = j; break; } } } if (tcol == null) return ("[0, 0]"); tcolOut = "" + tcol; if (tcol != 0) tcolOut = "-" + tcolOut; return ("new int[] {" + (this.rows - trow - 1) + ", " + tcolOut + "}"); } GridPreview.prototype.getMaskDefinitionKeys = function(arr) { arr.push(this.normalKey); arr.push(this.hReflectKey); arr.push(this.vReflectKey); } GridPreview.prototype.getMaskDefinitions = function(dic) { var def; def = new MaskDefinition(this.normalKey, this.getCodeForGrid(this.normalIDGrid), this.getOffsets(this.normalIDGrid), this.getDims()); dic[this.normalKey] = def; def = new MaskDefinition(this.hReflectKey, this.getCodeForGrid(this.hReflectIDGrid), this.getOffsets(this.hReflectIDGrid), this.getDims()); dic[this.hReflectKey] = def; def = new MaskDefinition(this.vReflectKey, this.getCodeForGrid(this.vReflectIDGrid), this.getOffsets(this.vReflectIDGrid), this.getDims()); dic[this.vReflectKey] = def; } GridPreview.prototype.markMaskDuplicates = function(maskDefs) { var def; def = maskDefs[this.normalKey]; if (def.isDuplicate()) this.normalWrapObj.css("border", "2px solid red"); else this.normalWrapObj.css("border", "2px solid #a0a0a0"); def = maskDefs[this.hReflectKey]; if (def.isDuplicate()) this.hReflectWrapObj.css("border", "2px solid red"); else this.hReflectWrapObj.css("border", "2px solid #a0a0a0"); def = maskDefs[this.vReflectKey]; if (def.isDuplicate()) this.vReflectWrapObj.css("border", "2px solid red"); else this.vReflectWrapObj.css("border", "2px solid #a0a0a0"); }

Conway Simulation (Python)

This class was used to represent a Universe object for a CGI short documentary about Conway's Game of Life.

import math import random from golmodel.lifeform import LifeForm class Universe(object): """ A 'Universe' is an iterable, 2D grid of LifeForm objects. When iterating over the universe, lifeforms are yielded in row-major form (so every LifeForm in row 0 is returned, followed by every LifeForm in row 1, etc). """ def __init__(self, rows = 10, cols = 10): self._rows = rows self._cols = cols self._lf_count = rows * cols self._life_forms = [] # 1D list representation of 2D grid self._make_universe() def __iter__(self): return iter(self._life_forms) @property def rows(self): return self._rows @property def cols(self): return self._cols def _make_universe(self): """Instantiates all the LifeForm objects in the Universe.""" for i in range(self._lf_count): # 'simulate' 2D grid with math row = i // self._cols col = i % self._cols self._life_forms.append(LifeForm(i, row, col)) def randomize(self, thresh = 0.4, doKills = True): """Randomly kill or birth life forms in the universe.""" for lf in self: if random.random() > thresh: if doKills: lf.kill(0) else: lf.birth(0) lf.commit() def get_life_form(self, row, col): """Returns the life form at row, col.""" index = (row * self._cols) + col return self._life_forms[index] def get_neighbour_count(self, lf): """ Returns the living neighbour count for the box surrounding the given life form. """ cnt = 0 if lf.row > 0: cnt += self.get_neighbour_count_for_row(lf.row - 1, lf.col) cnt += self.get_neighbour_count_for_row(lf.row, lf.col, True) if lf.row < self._rows - 1: cnt += self.get_neighbour_count_for_row(lf.row + 1, lf.col) return cnt def get_neighbour_count_for_row(self, row, col, is_home = False): """ Returns the neighbour count for the given row and surrounding columns. If is_home is true, then the center column is not considered. """ cnt = 0 if col > 0: if self.get_life_form(row, col - 1).is_alive(): cnt += 1 if (is_home == False) and self.get_life_form(row, col).is_alive(): cnt += 1 if col < self._cols - 1: if self.get_life_form(row, col + 1).is_alive(): cnt += 1 return cnt def get_transition_count(self): """ Returns the total count of life/death transitions that have occurred during the lifetime of the universe. """ total = 0 for lf in self: print("%d: %d %s" % (lf.lfid, len(lf.transitions), \ lf.transitions_to_string())) total += lf.get_transition_count() return total def __repr__(self): return "Universe[rows=%d, cols=%d, lf_count=%d]" % \ (self._rows, self._cols, self._lf_count)