Asparck

Projects

Personally I find peoples' "programming origin story" to be valuable in understanding their perspective, so here are some side projects that I've hacked on over the years, in roughly reverse chronological order. This list is definitely incomplete, but you'll get the idea.

Relatedly, I've also given a decent amount of talks and taken a couple of online courses to learn new things.

Slow Rush Studios (Rust)

I'm building a couch-coop 2D pixel-physics platformer game at Slow Rush Studios.

Name is yet to be determined, but do click through to that website to subscribe & stay in the loop if you're curious.

Learning WebGPU (Rust)

I went through a chunk of Learn Wgpu, a course to learn the WebGPU API using Rust's WGPU library.

Asteroids clones (Rust)

I implemented Asteroids in Macroquad and in Bevy, to get a feel for each of the two most popular 2D Rust game engines.

Wizard Heist (Unity/C#)

I implemented (the start of) a prototype game focused around wizards stealing objects in Unity. I had basic platforming and spell casting working, but life (buying a house & a road trip) interfered so I never progressed it beyond that. I also found it very frustrating to work in Unity on a freeform project without an experienced "guide"; the combination of 10+ years of legacy approaches plus the newer approaches being half baked & undocumented lead to some very frustrating debugging sessions.

Little Crab TV software renderer (Rust)

Roughly following the approach laid out in Tiny Renderer, I implemented the Little Crab TV software renderer in Rust, from scratch (i.e. rendering 3D without OpenGL/DirectX/etc).

Naturally I added a UI, but unlike the sample code, I also took pains to support each incremental mode of drawing - so you can use the UI to see the progression from drawing individual pixels, lines, filled triangles, models without backface culling, etc all the way up to a pseudo-phong-shaded textured 3D model with support for Screen Space Ambient Occlusion and specular, normal and glow maps on the model.

The All Seeing Crab raytracer (Rust)

Following the Ray Tracing in One Weekend book series, I wrote The All Seeing Crab raytracer in Rust based on the first two books.

The resulting ray tracer supports many different materials as well as features such as transparency, shadow & light scattering etc. I implemented some neat additional features such as a UI to select scenes, control settings, and show in progress renders pixel-line by pixel-line, and rendering the image as colored text in your terminal too.

Crafting Interpreters (Java & C)

I read through Crafting Interpreters and implemented the 2 interpreters for the (didactical) Lox programming language; each interpreter is additionally extended with additional language features as suggested in the challenge exercises.

This was a fantastic course; it easily surpasses several university courses I took on programming language design & implementation.

Catlike tutorials and Pirate Tower Defense game (Unity/C#)

Catlike Coding's Unity tutorials are stunningly good, primarily because they demonstrate Unity best practices while still treating the reader as if they have a measure of intelligence.

I implemented a few of their tutorials to learn the basics (and then some) of the Unity game engine: Catlike basics, Catlike Movement, Catlike object management.

Eventually this lead to implementing the basic Catlike Tower Defense game, with many additions and changes to make it into more of a full game themed around defending against pirates - level select, level editor integration, particle effects, win conditions, animated models, better camera controller, etc.

Elm asteroids game tutorial (Elm)

I wrote a small set of exercises to teach Elm by writing a clone of Asteroids for a workshop that I ran. I wasn't an expert on Elm but I knew a bit about it, and we know that in the land of the blind, the one-eyed man is king! Plus, teaching is a great way to learn more about something.

QMK keyboard layout (C)

I acquired a Kinesis Advantage 2 keyboard and - after a very painful few months - got back up to my regular ~90 WPM typing speed on my custom keyboard layout implemented using the QMK firmware.

To add support for QMK, I had to swap out the keyboard's controller board with a custom controller - which I fortunately was able to source from a friendly person on Reddit, so no un- & re-soldering was required.

This process also involved trialing several keyboard layouts. Initially I got up to 40 WPM on Dvorak before realizing that its very-different layout layout makes keyboard shortcuts way too painful in existing apps; I didn't have the patience to remap everything. Then I got onto Colemak, which was pretty good, except for that with my columnar-layout keyboard (as opposed to the regular staggered-layout) the qwerty-g and qwerty-h keys were getting hit too often. Eventually I settled on Colemak-mod-DH with a couple more tweaks.

I also implemented several other layers, including a symbol layer optimized for typing common digraphs used in programming. All existing analysis of keyboard layouts that I could find were focused on typing standard written text, usually in English, which tends to discount the value of symbols such as ; and .. So to help implement this, I wrote a simple character frequency analyser.

Beancount accounting (Python)

Saving money is one thing, but keeping track of it in many different accounts is another, especially when dealing with foreign currencies and frequently opening and closing accounts to take advantage of various bonuses. Eventually I stumbled on Beancount, which is a plain text implementation of double entry accounting - which means that it properly tracks money in different accounts, without having to stick login details into a third party system.

To use it ergonomically (and convince my wife to do the same), I wrote importers for various bank CSV and PDF statements, some custom reports, scripts to fetch current market prices of various securities, and a bunch of scripts and lints run on each commit to make sure we're not doing anything insane. After a few years, I can say it is working quite well - though I do wish banks would be legally required to provide CSV exports, as PDF importing is painful to implement! (especialaly when statement formats change, or a few extra pages are tacked on as a once-off..)

Shasum for Windows (Rust)

I was using Windows and needed a way to verify my backups matched their source files, so I wrote a small port of shasum in Rust so I could easily run it on Windows as part of my backup scripts.

It iterates through directories, calculates sha1 hashes of every file in the directory and deterministically outputs the filenames and sha1 sums. Thus, the outputs of 2 executions can be easily diff'd to find files that have been not been backed up correctly.

Game of Life tutorial (Rust)

To teach rust for a workshop I ran, I wrote exercises to implement Game of Life. The rendering code is pretty horrendous, but the rest of the codebase serves pretty well as a teaching aide as it is heavily commented.

Factorio-A11y, an accessibility mod (Lua)

Factorio is a very heavily mouse and keyboard oriented game, which precludes people who are unable to effectively use a mouse and keyboard from playing, so I started factorio-a11y, an accessibility mod for Factorio. It provides alternative means to accomplish key actions in the game via a mix of hotkeys and console commands intended to be triggered by voice control, joysticks/controllers, and eye/head-tracking equipment.

Voice control of arbitrary software (Python/Dragonfly)

I developed a set of voice commands which allow me to work without using my hands at all; keyboard interaction and mouse movements are performed by scripts I wrote using Dragonfly, powered by Nuance's Dragon NaturallySpeaking for the actual voice recognition. The details of how it works are relatively complex, but the core idea is that Dragonfly provides a mechnaism to define a grammar in an EBNF-like domain specific language, then I defined the grammar and arbitrary python code which should be run for each recognised element.

This project was interesting because it gave me a whole new perspective on software accessibility. Missing keyboard shortcuts are annoying for a regular user, but for an impaired user, missing keyboard shortcuts mean bespoke development is required to expose the same functionality - or perhaps the task can't be done at all.

It was also a great experiment in human computer interaction. As far as I could tell, there had been significant research into voice recognition for arbitrary dictation, and a decent amount of research into voice-based controls for non-technical users (e.g. Alexa), but there was very little serious research or development into voice control for programmers and power users. I realized that the tradeoffs of voice control are quite different from those of a keyboard and mouse: many more possible inputs which are easier to remember than keyboard shortcuts (I have at least 500 commands in my grammar), but at the cost of higher latency and some misrecognitions.

Additionally, there are interesting internal tradeoffs in grammar design: longer commands are more reliable, but slower and less convenient (although usually still faster than typing out a word), short commands also need to balance phonetic dissimilarity with other commands vs their own memorability, the complexity of the grammar itself needs to be managed to keep recognition times under a second, etc.

As of 2019 I still use and work on this project, as the interaction mechanism is well suited to certain tasks and is a nice change from keyboard and mouse, but for my own convenience and privacy I've kept my grammars and accompanying code private.

Jess, a JSON pager (Rust)

jess is less but for JSON data; it renders JSON data in a tabular format, and allows interacting with it via a text-based user interface. For example, if an object contains a value which is itself an object, you can select that value and "zoom in" on it to see more details. It also supports tailing files for further input (like less +F foo.txt), and incrementally parsing concatenated JSON files (object by object, pausing at the first incomplete object).

I started it because I was frustrated with how unreadable JSON logs are by default, particularly outside of specialized tools such as Kibana/Splunk. With a bit of effort you can format the JSON to make it more readable, but then log lines often take up 10+ lines for a single conceptual line of log output, making it annoying to scan logs - so you're back to grepping through them, in which case you might as well be outputting plain logs in the first place.. but then you lose your structured logs, argh! Along the way, the project increased in scope to make it also useful for exploring static large JSON data sets.

This project is still in on-again, off-again (private) development. Eventually, this project should integrate with JQ and/or JMESPath; ideally it should eventually be flexible and clever enough to supplant special-case tools such as Bunyan's CLI.

Rocksy, a development proxy (Rust)

While playing around with Elm, I realized that Elm didn't have a nice way to proxy some requests to the Elm development server while other requests were routed to the backend server of choice. In Webpack-land, this problem is solved by the webpack dev server supporting a proxy option, or it could be solved separately by setting appropriate CORS headers, but I didn't want to introduce Webpack or risk development-only CORS headers accidentally being sent in production. I also didn't want to run nginx or another such full blown proxy just for my messing around.

So, I did significantly more work to generalize Webpack dev server's proxy into a solution that's reusable by any front-end and back-end stack. I wrote Rocksy in Rust using Hyper and Rust's then-nascent futures support, and it works well enough now that I haven't had to touch it since.

Decider, a decision-making web app (Typescript/React)

As an excuse to get more familiar with Typescript, I came up with a novel twist on the standard "weighted pros & cons on a legal pad" decision making technique, and implemented about 80% of it in Typescript and React.

BeNice, a comment sentiment analyser (Python)

I helped my data scientist wife develop a small-scale neural-network-based web API for classifying online comments as friendly or mean, based on sample data scraped from Reddit's API. Frankly this barely belongs on this list - all I did was provide guidance on design, and help her out when she got stuck using Flask, and all the interesting data stuff (building & validating the classification model) was done by her.

Sherlock-thread, a debugging tool (Rust)

Sherlock-thread is an experimental debug-tooling project for Linux written in Rust, intended to force applications to include thread identifiers whenever they output a line of log information. It works by replacing the symbols for writing strings to file descriptors at application load time (using LD_PRELOAD), and then intercepting write calls which are writing to stdout/stderr, modifying them to add the thread identifier.

It works fairly reliably thanks to glibc almost always being dynamically linked (partly due to its GPL license), but it does not work at all for programs which statically link a C standard library (e.g. musl often gets statically linked) or programs which avoid calling C standard library functions (e.g. anything written in Go). However, at the time I did this project, Rust did not support calling varargs functions, so it was not possible to complete this project (unless I rewrote it into C or similar), so I didn't waste time polishing this project.

Logprof, a log-based profiler (Rust)

For an Atlassian hackathon, I wrote logprof, which is a simple profiling tool based on analyzing the speed at which logs are received (or existing timestamps on logs). The gist is that if you have a long running process (e.g. a build) that emits logs, this tool lets you find where your time went by highlighting which bits are slow (optionally via sparkline-graph-like visualizations), which is the first step to speeding up that long running process.

Logprof's README has several detailed examples showing more usage.

Maven-nailed, a speed boost to Maven (Java)

Frustrated with Maven's 1-3 second startup delay impacting my development loop, I forked maven-nailgun as maven-nailed, then updated it to add support for the latest version of Maven used by Atlassian at the time, added tests, and made it easier to install for people (important because it required patching Maven!), with the idea of getting other developers at Atlassian to adopt it too.

Board game turn timer (JavaScript)

I wrote & published a super-simple web app for running on a phone or table, intended to be used as a turn timer for boardgames; functionally it's similar to a chess clock, but for up to 4 players.

Eclipse-multicursor, a plugin for the Eclipse IDE (Java)

Inspired by Sublime Text's multiple cursors, I took a stab at implementing multicursor editing for Eclipse. My approach was a straightforward but somewhat limited approach using Eclipse's existing LinkedMode APIs. I also prototyped a more flexible approach, but unfortunately shortly after I started this project I changed employers and switched to using IntelliJ IDEA, so I stopped working on this.

Still, I occasionally get bug reports raised against it, and the Eclipse editor team approached me about adopting it and the project continues to accumulate stars on Github, so all things considered I'd say this project has been more successful than it had any right to be!

Snapsy, a scan-to-PDF app (C#)

I wanted to stop keeping paper around, which meant scanning existing paper into PDF format. There didn't seem to be a good option for doing this in bulk with consumer scanners except a buggy & unmaintained open source project called NAPS, so I forked that project as Snapsy, added some features I wanted, and fixed a whole bunch of bugs in it. I used it for a year or two until I found a better workflow, at which point I deprecated the project.

Calamity, a client-oriented bug tracker (Python/Django)

To keep on top of issues and requests raised by customers of my Golf Booking SaaS business (and after getting fed up with the inadequacies of free solutions like Traq and Redmine), I built a bug tracking site. It was functionally very similar to early incarnations of Github issues, except specialized to make it easier for each of my customers to get a view of issues and activity relevant to them.

I improved and maintained this for about 3-4 years before eventually migrating everything to Trello in the name of simplifying the amount of services that I was running; at that time, several business concerns which had made it more compelling to roll my own solution originally had also dissolved, making deprecation of this a win all round.

Golf Booking SaaS (Python/Django)

As a paid side-project-turned-micro-SaaS-business, I built (and still maintain) a Golf Booking site & CMS for several Australian golf associations. I wrote these in Python using Django, and later added in a dose of managing WordPress, and everything is fronted by Nginx. The system has been rock solid for 8+ years in terms of functionality and reliability, even though my visual design work from ~2010 has some... room for improvement.

I also put in a lot of work to fully automate the bootstrapping and deployment of code for new VPSes using Ansible (containerizing wasn't a viable option yet). Security is locked down, all configuration is stored as code, local and offsite encrypted backups are fully configured (you can see some of my Tarsnap tooling), and while it was probably overkill at the time as compared to maintaining a manual checklist, it taught me a great deal about Linux system administration, Ansible (which very importantly, helped me automate my Factorio server several years later!), scripting and has significantly eased my maintenance burden since then.

Automated SMS sender (C#)

I built a small application in C# which sent a different SMS message every day to a specific phone number by integrating with an ISP's SOAP API. Technically straightforward in hindsight, but it was the first time I actually did something vaguely useful with an external API, and my first time building anything in C#.

Missile Command clone (Lua/Love2D)

A friend and I had a brief stint of collaborating on making a 2-player version of Atari's classic Missile Command game in Lua, using the Love2D framework. We never actually shipped it (didn't help that we were learning Lua at the same time!), but I enjoyed implementing bezier curves to make missiles smoothly travel from their silos to their targets :)

Low-end Webdev (PHP)

I'd been dabbling in HTML web development ever since I discovered Geocities (RIP), but it took me a while to realize you could execute arbitrary code on the backend too, using a magical thing called PHP. I promptly rebuilt my own personal website using it, then quickly thereafter landed a side-gig to build a website for an alternative modalities health clinic.

Early desktop apps (Visual Basic 6)

Some time during high school I acquired a copy of Visual Basic 6, which unlocked a whole new world for me. I had no idea what I was doing, but suddenly I could throw together forms to make desktop applications and I learned about calling Windows APIs and network programming using sockets too!

Suddenly there seemed to be no limit to what I could build, so I wrote a whole bunch of things:

Early gamedev (Blitz Basic & Blitz 3D)

Aside from a brief flirtation with C wherein I got hung up on understanding pointers, the first language I coded anything serious in was a demo copy of Blitz Basic, a game-development oriented BASIC shipped on a CD of some computer magazine. Eventually during high school I got my hands on its successor Blitz 3D, and started making some 3D games.

I didn't know about version control, so most of the sources have been lost, but some things I made were: