tsu is Employable

…as a Web, Desktop, and Mobile Developer

About Me

Hi, I'm Levi: a reliable, talented and industrious generalist software developer, working out of Vancouver, British Columbia. I believe in my work, and am always looking for ways to better my skills. I'm an excellent communicator, and enjoy an iterative development process, putting the client at the center of his product's evolution.

I've made extensive use of PHP 4 and 5, Python (via Django), Node.js (via Express and Socket.io), Ruby (via Ruby on Rails and Sinatra), and Erlang (via Cowboy) to develop web applications alongside the MySQL, PostgreSQL, Redis, and Riak databases. To interact with some of these web applications, I've developed RESTful HTTP APIs and worked in C#, Objective-C, and node-webkit to create networked GUI API-client software. I have experience in implementing rich AJAX-based front-end functionality (mainly using jQuery, but recently working with AngularJS), and I'm adept at transcribing graphical layout designs into standards-compliant HTML5, CSS3 and Javascript. I am comfortable with revision-control processes (my own favorite VCS being Git), and I write thorough tests for every unit of functionality I deliver.

Much of my previous code has been developed for the cloud, either running directly on Amazon EC2 in a variety of languages, or using Google App Engine (with Java and Python) or Heroku (with Ruby) to enable transparent scaling and distribution of load between application instances. I know how to balance flexibility with speed in database design, having experience with both relational, and object- or document-based (NoSQL) storage, and having specifically used Redis, Memcached, and Amazon S3 in several environments where they better served the client's needs than ordinary RDBMS storage. I also have experience in integrating applications with a variety of other third-party services and APIs, including Facebook, Twilio, and Dropbox.

I have a hobby of learning more academic languages, such as Prolog, Clojure, and Haskell, and make heavy use of concepts borrowed from them in the projects I work on, to both speed—and reduce errors in—development. I also have a keen interest in lower-level development, with experience in game development using C and Lua, and experience in optimizing assembler for the IA-32 architecture. I have a great passion for programming in general, and I hope it's one you can put to good use.

I'm currently looking for full-time employment. If you have a job offer, or any questions for me, you can:

tsu has So Many Projects

Peri

Talking to myself Peri is a multi-user realtime group chat service, focused on "co-browsing": visiting the same sites (or watching the same videos, or listening to the same music) at the same time, and discussing them. It also has elements of an MMO game: the URLs visited by a group correspond to "rooms" in a virtual environment, which the users may explore; rooms have doors leading to other rooms in the same way that the pages at each URL link to other URLs.

Peri grew out of an established need for a place to work collaboratively on certain kinds of content. The main types of resources the group wished to visit were Etherpad documents and Livestreams. Both of the services mentioned had their own forms of multi-user chat, but neither was exceptionally good (they seemed to be added as afterthoughts) and, more importantly, they were completely disconnected from one-another. I developed Peri with the goal of providing a framework for chatting, identity, and presence, into which other resources could then be embedded.

I first deployed Peri on Heroku, but its requirements (for example, the use of websockets) caused me to transition it to running directly on Amazon EC2. Peri also relies on the Redis key-value datastore for most operations (going through the useful Ohm object layer), but keeps its event history in a PostgreSQL database, as it is infrequently accessed and requires stronger persistence guarantees. Instead of a complex intertwining of SQL and Redis calls, the application layer simply writes all events to Redis; a worker process then prunes batches of event history and moves them to SQL in the background. The application will then read back the history from the first place it finds it.

As I developed Peri, it separated into two clearly-defined codebases: first, an application server, written in Ruby's Sinatra web framework, which clients initially connect to, which serves the jQuery AJAX client and responds to client requests (e.g. to post new chat lines); and also, a push socket server, using Node.js's Socket.io framework, which clients speak with directly for the rest of their lifecycles once they've established a session with the application server. The application server handles all actual business logic; all the messages the push socket server delivers are received on a message queue (in this case, Redis' PubSub functionality) from the application server.

Later, a large refactoring replaced most of the backend code, both Node.js and Ruby, with Erlang; replaced Redis in its message-queuing and short-term persistence capacities with a combination of RabbitMQ, Riak, and direct BERT RPC calls; replaced Socket.io with Sock.js; and replaced the mostly-jQuery frontend codebase with one based on AngularJS.

Starboard

Starboard with example tasks loaded Starboard is a web service for forming and tracking habits. It uses a variety of gamification techniques ("don't break the chain"-style cumulative rewards, variable-interval bonuses, experience points, check-in health, etc.) to get people "addicted" to performing self-specified tasks on a regular schedule, such as exercising, eating healthily, or performing daily chores. It also serves as a daily review in preventing bad habits such as smoking. Starboard has a whiteboxed version available for corporate use in employee self-rating and review, and also offers "program subscriptions," where users can work together through a set of tasks developed by a life coach or other third-party.

I created Starboard from the beginning to run on Heroku's cloud service, relying on the Redis NoSQL key-value datastore for all required persistence. Every action performed through the interface or the REST API is guaranteed to be atomic—this is important when accessing the service through the iOS client and web application in parallel.

The core of Starboard is a small Sinatra-based Ruby web application. It interfaces with a variety of other services: Starboard uses Recurly for recurring billing support; it makes use of the Dropbox API to allow users to provide "evidence" for some task-completions; and Disqus and Gravatar are used for some social features.

Starboard also has a native iOS application (currently in development) which allows users to provide instant evidence for task-completions using the camera, and which emphasizes the social features of the service: allowing users to cheer one-another on when they are struggling with a task, or to give them a thumbs-up (with attached bonus gifts) when they complete a long chain of tasks.

Persona

Persona home page, when logged in Persona is a social Q&A site in the style of StackOverflow, intended for writers as an aid in character design. Rather than each user of the site having a single identity, users create multiple personas—the equivalents of fictional characters from their stories—and take on their roles, developing the personalities and traits of their characters through their actions. A persona may answer user-submitted questions, converse with other personae, join and create groups, and participate in interviews or quizzes; personae also earn points and social rewards (“karma”) through their actions, which grant additional privileges to both them and their owner.

Persona characters, like members of a social network, each have a feed, populated by their actions and comments to others, and made available both through the website and through the RSS 2.0 and Atom feed protocols. The feed display on the website is customizable and theme-able, and the items appearing in it may be filtered to each user’s tastes, allowing users to set up a “blog” equivalent for each character. The feeds, personae, or entire users may be freely imported and exported from the Persona website as XML documents. Persona also allows external services and clients to perform Persona actions, or exchange Persona data using OAuth and a RESTful HTTP API.

Persona relies on OpenID integration for the entirety of the client life-cycle. As such, there is no registration step; users simply sign in, and find their name and details imported using OpenID SRE, user display icon imported from Gravatar, and a single persona already created with their preferred online pseudonym. Persona then uses a recommendation engine (an SVD collaborative-filtering approach; built using Amazon Elastic MapReduce and wukong) to match users with other users, match personae to other personae, and to find interesting groups for users to join and questions for personae to answer. Every user starts in guided character-development mode, where Persona will also make “reverse” recommendations, allowing the user to specify desired relationships between the personae under their control, to which Persona will suggest answers to personality questions for character pairs that will justify those relationships.

I designed and developed the initial prototype of Persona myself, using the Ruby on Rails web framework, and then put it online in an open beta-test. From user feedback, and usage information I gathered via Google Analytics and through A/B split-tests (conducted using the A/Bingo library), I then redesigned and polished many facets of the service, and introduced several new features (such as a recommendation system.) After four months of refinement, I declared Persona “stable” and released it to the public. It gained momentum and users, and after a while, I introduced Google AdSense ads. Persona is now self-supporting from its own ad revenue, and continues to gain new users every day.

SpiltWines

SpiltWines logo SpiltWines is a social network to connect wine-tasters to a receptive audience, and to increase the reach of wine-reviewers. The social graph of the service represents both mutual friendships between users, and "follower" relationships between wine-reviewers and their readers. Reviews of wines can be voted on, affecting a reviewer's visibility level within the network's various public channels; users can send messages and make comments on wines and wineries; and wineries can publish PR stories on their own page.

I worked with the SpiltWines team to develop their back-end throughout 2011. Development was split into two main phases. During the first phase, I collected core requirements, including that the code would be re-deployed to a variety of commodity *nix machines without having to install any particular packages. I proposed that the simplest route would be to design the back-end web service as a standard LAMP (Linux, Apache, PHP, and MySQL) application. I then drafted an API specification proposal and iterated it with the team until we were both satisfied everything was covered. I developed the core of the application—including user messaging, contacts, wall posting, reviewing, moderation, administration, user-lifecycle, and backend-testing functionality—and wrote a set of prototype HTML views for the application to deliver, which could later be replaced by the team's front-end developer.

In the second phase of development, new requirements were generated based on user-experience surveys using the initial prototype. With a larger userbase, it was hard to find good reviews, so I designed and implemented a ranking algorithm based on user-voting input for reviews. There were also problems with users posting defamatory comments and stories, so I created a global moderation queue that new posts had to go through for approval. Additionally, wineries were given the ability to manage the mentions of their own wines: for a fee, they could have their product highlighted, where mentions of their wine would link to their wine's page in the network.

Stargazer

Stargazer in top-down, gridless viewer mode Stargazer is a star-chart editor and analysis tool, designed to allow writers of science-fiction to interactively create stars and planets, systems, constellations, and galaxies, and to indicate trade, travel, and communication routes between them, and zones of ownership or influence. This information can then be queried in many ways, giving writers useful working knowledge such as:

  • “Given that system B is 3 hyperdrive jumps away from system A, and 4ly away from system C, which would they come into contact with first?”
  • “What is the fastest route to from system A to system Z—halfway across the galaxy—that doesn’t cross into any zones with laws prohibiting carbon-based life transport?”
  • “What is the extent of the region where a probe floating into system B could have originated, if it is carbon-dated to be 4000 years old, has no propulsion, and was found in geosynchronous orbit?”
  • “How long will it take my characters to go to every planet I want them on?” (Usually followed by “Oh, I need to move my systems closer together, then!”)

I wrote Stargazer in Ruby, relying on the Rubygame wrapper for the SDL multimedia library for graphical rendering. Stargazer stores its data in galaxy files—renamed ZIP files containing SQLite databases and imported multimedia assets—but it can also import from, and export to, CSV and XML formats, to allow interoperation with other software. Stargazer is platform-independent; it is packaged to run stand-alone, without installation, on Windows, OS X, and Linux.

Every star, planet, satellite, route or region has a few key characteristics, such as name and position, but may have additional arbitrary, namespace-segmented metadata associated with it. Stargazer has a pluggable architecture, with each object type being rendered by an individual plug-in; one of the first user-contributed plug-ins was an Encyclopedia Galactica, which took a “description” metadata record for each object and rendered it in a fashion similar to Wikipedia entries, initialized from procedurally-generated pictures and in-universe history.

Stargazer has a networking component that allows users to upload their galaxy to a central repository (a web-application written in PHP5), which then, through an HTTP API, provides support for an in-application scoreboard on several metrics, such as galactic “richness” (level of detail provided by the user), “prosperity” (level of trade), and “imperialism” (size of ownership zones, over level of inter-zone communication.) There are regular contests, where the winners on these metrics receive reward objects for their galaxy—secure, server-signed tokens representing planets or satellites which the Stargazer application renders and treats specially.

Nodepad

Nodepad displaying a complex document and the Style editor Nodepad is a document editor I developed in C#, which was designed around the Snowflake Method workflow for fiction writing. Nodepad works with a hierarchical structure of named text blocks, called nodes. Users start with a root node—an empty document—and then write in the Content Editor pane (which is auto-saved) until they feel that whatever they have written has grown too large, and needs to be broken down. They then select the part of their text which has a repetitive structure, and node it; the structure is automatically detected, and each item is extracted into a new node, which appears as a child of the current node in the Node Explorer pane. The user can then repeat the workflow on each child node, recursively, until the document is complete.

I built Nodepad to obey the Unix philosophy. I avoided creating any complex document format for storing nodes; instead, I relied entirely on the filesystem for data serialization and storage. Each “node” is a folder—and, conversely, any folder can be opened as a node—and the content of each node is simply the content of an RTF content file in the folder. Thus, any tool that understands the filesystem—such as Git, Dropbox, or Windows Search—can treat a Nodepad node tree as if it were any other hierarchy of files and folders, enabling simple support for search, remote mirroring, and revision-control, which would otherwise have to be built-in. Each node has an optional XML hooks file, allowing individual nodes to react to events upon them, or their children, by triggering scripts written in Lua. Premade Lua scripts are provided for integration with the SVN and Git revision-control systems. Nodepad also natively understands NTFS features such as reparse points and aliases, so, with a few simple drag-and-drop movements, nodes may be made to “live” in multiple sections of the tree at once (with Nodepad at the ready to prevent directory-graph cycles).

Mergechan

An example thread on a Mergechan board Mergechan is software for running a semi-anonymous, image-sharing-centered conversation forum (usually known as an imageboard), similar in concept to the Futaba BBS Script and its spiritual successor Wakaba. Mergechan is written in Python, and runs on Google App Engine. I wrote Mergechan in response to two common problems encountered with other imageboard software:

  • On imageboards that allow anonymous posting, it is difficult to prevent off-topic posts, or posts that contain illegal materials or violate the site’s TOS. Unless carefully moderated, such sites will inevitably become filled with spam. It is difficult to punish this behavior, because anonymous posters have not provided any identifiable information that may be used to block or ban them from returning.
  • A given conversation thread on an imageboard will usually be of interest to only some of the website’s community. Most imageboard-hosting websites solve this problem by dividing the discussion between multiple copies of the imageboard software. This works in some cases, but more often than not a conversation thread will actually belong under more than one of the categories the site has defined, or transition from one category to another during the discussion.

I solved the spam problem by giving posts on Mergechan a dual identity. Before being allowed to post, users must first sign into the service using a reputable identity—in this case, a Google Accounts account (usually a Gmail address.) This gives the moderators a name and an email address to use in contacting the user, and a company (Google) to file complaints with if the user posts illegal materials. This also makes users more reluctant to spam, since Google does a good job of preventing users from registering large numbers of accounts.

When a user posts, their account is recorded in the post data, but is not displayed to other users, only to moderators. Instead, a second identity—a temporary pseudonym of the user’s choice—is displayed, preserving user-to-user anonymity. However, beside every post, a visual hash of the combination of the user’s account ID and the thread ID also appears, generated using the Python Imaging Library. This allows users to visually identify when the same user is speaking within a thread, while still allowing users to participate in different threads without leaking their identity between them.

I solved the content categorization problem by removing categorization altogether. Mergechan instead operates on a tagging and filtering model: every post in a Mergechan conversation thread has a set of tags attached to it, first by its author, and then by any readers of the thread. The union of these all these sets of tags, weighted by their number of appearances, becomes the set of tags for the thread itself. Users then filter the list of conversation threads by tags they do, or do not, want to appear in the resulting threads.

Wikirei

A freshly-generated Wikirei wiki, showing recently edited pages Wikirei is wiki software I wrote with Sinatra in Ruby. I designed it with a top-down focus on making a Wikirei site appear to be a static, polished, and minimal product until you log in. In this way, it is similar to a Content Management System (CMS), with different users holding different roles in the content-publishing process—but once you do log in (with OpenID), it becomes very clear that Wikirei is a wiki.

Wikirei follows a moderation-queuing approach, allowing every user the ability to suggest changes, but only a subset of users—the moderators—the ability to accept changes. This works very well as a model for a site that is co-owned by a corporation and a community: anyone in the community may contribute to the wiki, but the corporate users get the final say of what appears on the rendered website, without the ability to censor the community (as unpublished revisions remain in the revision stream, and may still be linked to or shared.)

Wikirei allows entries to be nested, tagged, and for each revision to hold arbitrary metadata and file attachments. Wikirei articles may be written using MediaWiki markup (parsed using Marker), or Haml, allowing Wikirei to store its own templates and special sections as wiki articles (which, like all other articles, go through the moderation queue—preventing XSS and site-defacement attacks.)

Sponge

Sponge with tutorial notes loaded Sponge is a to-do list manager I developed in C#, in the style of David Allen’s GTD (Getting Things Done) principles. Sponge was designed to remove the need for any operation other than entering new items, searching for things to be done, and checking off done items. There is no categorization system to hide to-do items from oneself; there is no way to rearrange one’s items or to annotate them with excessive detail. Instead, a visual tagging system and a full-text search are used to filter the single to-do list stream, so one may find the items they can currently accomplish.

Sponge Tag Editor The only way to interact with the to-do list stream is through the entry box at the bottom of the Sponge window. In it, you may enter freeform text (which will appear as your to-do list item), prepend a parenthetical list of words, either space- or comma-separated (which will appear as tags), or prepend a tilde (~) character, which will cause the item to appear as done. This is also Sponge’s storage format; a “Sponge document” is a plaintext list, and may be edited just as easily in Notepad as in Sponge.

Wallchive Creator

Wallchive Creator loaded with a set of wallpapers, ready to create a wallchive Everyone’s monitor resolution is slightly different, but everyone wants wallpaper that fits their screen exactly, with no stretching or blurring. Although the designers and illustrators who produce wallpaper may re-render their product in each of eighteen different resolutions, frequently, you’ll only be able to find a copy at one of those resolutions—the wrong one. Even more frequently, what you’ll find is a screenshot of someone’s desktop, with the wallpaper perhaps hidden underneath what they were actually trying to demonstrate—and you’ll be left wondering “but where can I get that wallpaper?”

Wallchives are a “clever hack” to solve these problems. A wallchive is “actually” a JPEG file—or, it could be equivalently said, “actually” a ZIP archive. These two file formats work together in such a way that they may simply be concatenated—glued together—and the result will function as both. If you open a wallchive with an image viewer, you will see a picture; if you open it with an archive extractor, you’ll get files.

I created Wallchive Creator to exploit this congruity, to allow people to show off their desktops while pre-empting any requests for the wallpaper underneath it. The Wallchive Creator is a simple wizard, written in C#; first, it loads a set of wallpaper, in as many resolutions as you have available; then, you provide it with a place to save the result; and finally, you activate it, and it minimizes itself, temporarily sets your desktop to display a wallpaper from the set, and takes a screenshot. The wallpaper set is archived (using the SharpZipLib library), the screenshot attached, and the result saved as a wallchive.

You may then post the result online—to a forum discussion, your Flickr account, etc.—and it will appear to any image-parsing software to be a picture: it will allow thumbnail generation, EXIF access, and so on. Mention in the description, though, that it is as large as it is for a reason!

tsu has The Skills

General

  • Test-driven/Behavior-driven Development
  • Lean Startup process
  • Technical writing
  • Gamification
  • A/B split-testing

Computer Science

  • Type/Category Theory
  • Garbage collection
  • Parsing/Lexing
  • Regular Expressions
  • ASCII and UTF-8 encodings
  • IEEE754 floating-point minutiae
  • I18n
  • Jump tables and threaded code
  • Design of bytecode VMs
  • Virtual memory, page-faults, cache coherency
  • Hard and soft real-time scheduling
  • Cryptography (secure signing/hashing/random-number generation/etc.)
  • Clustered storage with consistent hashing
  • Consensus protocols, operational transforms
  • Parallelism

Networking

  • SNMP
  • TCP minutiae
  • IPv6 protocols
  • SCTP (with UDP-virtualized transport)
  • P2P routing
  • SMTP delivery
  • TLS, IPSec, VPN tunneling
  • XMPP messaging and presence
  • DNS minutiae
  • Message prediction and deterministic/replayable protocol design

Technologies

  • OpenGL and SDL
  • OAuth and OpenID
  • Postgres, Memcached, Redis, Riak
  • LLVM

Ruby

  • DSL creation
  • C bindings
  • Metaclass minutiae
  • GC and ObjectSpace minutiae
  • Optimizing inner loops using C
  • Wire protocol packing/unpacking
  • Performance and memory profiling
  • Interactive debugging

  • Rails and Sinatra
  • RSpec, Cucumber
  • Nokogiri
  • EventMachine
  • Shell scripting, Rake

C and Assembler

  • IA32/64 ABI and calling conventions
  • Hygenic string-manipulation
  • Intrusive data structures
  • Object pools and Arenas
  • Optimization pitfalls
  • Undefined behavior
  • Sequence points
  • Memory-mapping data
  • Processor endianness handling
  • Creating shared libraries
  • Preprocessor and templated symbols
  • Cross-compilation toolchains
  • Compiler pragmas
  • Debugging

Erlang

  • Elixir syntax
  • OTP Behaviors
  • Parse Transforms
  • BEAM VM Architecture
  • Core Erlang format
  • BERT encoding
  • Distribution Protocol
  • Release Management for Hot Code-Loading
  • Application Distribution

  • Sock.js
  • Mnesia
  • Rebar

Javascript

  • Coffeescript syntax
  • ES6 extensions
  • asm.js
  • Optimization by Runtime Code Generation with Hardcoded Data

  • JQuery/Zepto.js, Underscore
  • AngularJS, Meteor
  • Windows Scripting Host
  • node-webkit
  • Chrome App/Extension APIs
  • Express.js
  • DOM
  • WebGL
  • HTML5 Audio
  • Promises/Async
  • Socket.io
  • Touch/Gestures API

HTML and CSS

  • Reflow points
  • Stacking contexts
  • Designing for font-size change
  • Media queries, device orientation

  • HAML and SASS/SCSS formats
  • HTML5 semantic tags
  • CSS3 transitions and animations
  • 3D transforms
  • Print-media CSS
  • DPI detection for retina-capable images

Less Recently…

  • Lua
  • Objective-C
  • Python
  • C++
  • Java
  • PHP
  • C#
  • Smalltalk

Learning…

  • Go
  • Clojure
  • Haskell
  • Scala
  • Rust