design and programming portfolio of Derek Stevens:

Planetary Gears: lighweight world clock webapp in jquery

main view of planetary gears

Planetary Gears is a world-clock, timer, and calendar webapp written using jquery, fuse.js, and moment-timezone. I wrote it for a client and released it under the 2-clause BSD License back in November 2019. Since I have a moment, I am doing an expose` of the app here.

The basic view is as above, and searching for a timezone brings up a list of possible matches:

view of the autocomplete search function

You can click on any option in the autocomplete box to select it and add it to the table, or just press Enter to add the first match.

view of the main table with another timezone added

You can add as many rows to the table as you want, and change the paramters like whether "now" is centered in the time interval or the beginning of the time interval, how large the interval is, and whether time is displayed in 12 or 24 hour format.

view of the same table with the Japan timezone moved to the top

Using the buttons on the left edge of the table you can change the order of the zones or remove them.

Time blocks are one-hour long but not necessarily starting on the hour! Irregular timezones are properly calculated using moment-timezone. The blocks are color-coded, showing early, work, and late hours, as well as weekends.

view of the calendar function

The calendar part of the app displays a month-by-month calendar or year-by-year. You can easily use the control forms at top to change the mode and the displayed month/year. The current day is hilighted on the calendar if applicable.

view of the timer function

There is also a simple timer/stopwatch function in the app. The timer goes up to 24 hours and optionally plays a chime when the time's up. The stopwatch has a lap counter like a real stopwatch, in case you need it.

An instance of Planetary Gears is always running on this server at, and if you want to run it on a server of your own, you can clone the git repository and drop it anywhere in your server's document hierarchy. Any bug reports or feature requests, let me know! And enjoy :)

Ryudo: the minimalistic window manager that flows

[download image] [download image] [download image]

Neat projects often emerge where you least expect. After trying to use rio from plan9port in combination with my wmctrl script qwopTiler, I was a bit saddened when I realized that they wouldn't gel, since rio is not Extended-Window-Management-Hints (EHWM) compliant and much of the functionality of wmctrl depends on EHWM.

But all was not lost, as the features I wanted were simple, as is the source of rio. So ryudo was born.

Building on top of nice features from rio like the sweep-to-resize and slick menu system, ryudo adds keyboard shortcuts for all your typical window management operations like hide, unhide, maximize, and close, as well as keybinds for quick window snapping just like was implemented in qwopTiler, and an extra feature to launch a centered terminal with a keyboard shortcut.

The border colors, border widths, menu colors, and keybind settings are all together in the config.h file, so changing the settings doesn't require one to hunt in the source for them. Other minor features were the re-enabling of the -ffm (focus-follows-mouse) runtime option and the final cutting of long window names in the hidden window list to 23 characters max (plus a '~' symbol to signify that it is truncated).

Some caveats inherited from the rio and 9wm code are RGBA windows being bound to an RGB space (which means a tool like transset needs to be used to acheive window translucency -- not a terrible setback), and a lack of click-to-raise behavior in focus-follows-mouse mode. The latter might be fixable by tweaking active() and setactive() but I've yet to find motivation or time to mess with that too much.

In all, ryudo has proven in my usage so far to be extremely lightweight and usable, supporting keyboard and mouse control depending on preference. If you like rio or 9wm and want a little more versatility, give ryudo a try! If you have experience in C and/or X11 programming and want to improve ryudo, hack away -- the source is free for all.

Steppenwolf GTK themes

[download image] [download image] [download image]

steppenwolf and steppenwolf-dark are GTK themes -- user interface themes for Linux desktops and GTK applications in general. steppenwolf is based on OneStepBack by Jean-Pierre Bucciol, and steppenwolf-dark is based on steppenwolf in turn.

Originally, steppenwolf was developed as a theme to provide sleek menus, tooltips, and notifications in grey-on-black that lend well to alpha blending and the simple style I use in my openbox themes, along with high visibility and low resource usage.

The dark theme takes more inspiration from Matcha, although the code, being from the OneStepBack lineage rather than an Arc lineage, is much lighter. How much lighter? Well, the GTK-2 port of Matcha is approximately 2000 lines of code, while steppenwolf-dark is 400, and the GTK-3 port of Matcha is 10000 lines of code, with steppenwolf-dark clocking in at 1100. I don't know about you, but I'd much rather parse 1100 or 400 lines of code than 10000 or 2000 to load my applications.

Both themes share the same aesthetic for the menus, tooltips, and notifications, and the same turquoise hilight color. The skeuomorphic widget styles of the original theme are traded in the dark theme for a more flat aesthetic. The GTK-2 versions require no external theme-engine dependency, using only the native and pixmap engines.

The steppenwolf themes provide a consistent look across applications with the GTK-2/3 versions and reasonable compatibility with the QGTK style plugin for QT5 applications. The GTK-3 themes, being written in a variant of css, make the theme spec easily translatable to most application frameworks, which is nice. To boot, the low resource usage makes them ideal for workstations or old machines where performance is the prime concern. If you're looking for a fresh theme experience on your Linux desktop or for your GTK applications on another operating system, look no further than steppenwolf!


list view

checklist is a simple baby registry webapp in python + django, made to prepare for the birth of my son, Zia. It's still hosted/live for posterity, since Zia is at the time of this writing three and a half months old!

The backend is, again, django, and data store is in SQLite. Each row in the database is a unique ID field, a product description/name, a link to where it can be purchased, slots for a name and email of the person pledging to get the item, and finally a boolean value for if the item has been pledged/claimed. The main list view simply shows all database entries which have not been claimed, in order of ID numbers.

individual view
Upon clicking an entry in the main list view, you are brought to the above view, where you can follow the link to an online shop and enter your name and email address. If you pledge the item, you must fill out both fields.

security feature
If you, say, bookmark the detail view for any particular item, and return there after it has been pledged, you will see the above view, thus even knowing the ID number (and thus the URL) of any item, you cannot overwrite the database entry for another person's pledge.

As administrator, I can view the status of the database either by using the django admin panel or from the serverside with the django shell. From there I can add, edit, or delete rows.


[download image]

dice, originally pyDice is a simple django webapp dice roller for tabletop role playing games. It was written as a proof of concept python CGI script, and then ported to django for the same reason. Being CGI/django based, it doesn't require Javascript on the client-side, so *anyone* can use it!

Catbug: In The See-Through Zone!

[download image] [download image]

Catbug: In the See-Through Zone is a simple arcade-style game originally written in C as a Christmas gift to my wife, and then later ported to Javascript as a learning exercise and to share the game with more people. The premise is simple: catch the food objects as they fly by, and collect points. Miss too many food items and it's Game Over. At 10, 20, 40, 80, etc. points, your health points recover and their maximum increases by one. The higher your score, the faster the food items tend to move.

The C version of the game shares a lot of low-level code with the HyperKaos engine -- both being written using the SDL 1.2 library. The Javascript version of the game is written completely from scratch using the HTML5 canvas feature. Most of the code is, once you normalize for the idiomatics between C and Javascript, very similar, except one part. The main loop part of the game code differs greatly between the versions.

In C, it's easy for the main loop to be just that -- a loop, and for any special conditions based on the game state to be handled inside the sub-functions of the loop. In Javascript, because of the way that renders are pushed to the browser, we have to do something a bit different. The loop() function is not really a loop, and instead requests that the browser call itself (loop()) again when it's time to refresh the screen. The weird part is, if control flow is held by another function when that time comes, behavior is unpredictable. This means we must make sure that all functions have finished executing before the request to run loop() again can be made. So instead of a simple loop with a chain of sub-functions, each taking care of its own logic, we have an if-else ladder or switch-case state-machine that handles the game logic, and most functions that would be loops in the C version have to be made into singleton classes that keep track of their states between method executions.

So in addition to those logistical changes, the other change to the Javascript version of Catbug: In the See Through Zone is touch-controls -- the whole point was to make it as accessible as possible, and that means mobile support. So the game checks your user-agent string on initialization and if it thinks you're on a mobile browser, it will throw the touch controls on screen. The controls aren't perfect, but they're good enough according to the Law of Diminishing Returns. You have to lift your finger off of one directional button before pressing the next, as I couldn't exactly figure out how to get the buttons to transition properly and to inhibit scrolling if you dragged a finger across the directional pad. The consensus from the Facebook release party was that the controls worked pretty well, though. :)

HyperKaos Engine

prototype title screen

The HyperKaos Engine is a 2D adventure/puzzle game engine originally written in C++ and then rewritten in C (with the SDL v1.2 library). It features a top-down adventure perspective reminiscent of the original Legend of Zelda (one room per screen), and a host of systems for interacting with the game world.

old prototype room
A room consists of a background spritesheet (four 320x180 sprites in a vertical spritesheet to enable ambient animation), and arrays of entities like obstacles, people, sigils (magic triggers), warps, and of course the titular HyperKaos.

Kaos.h file
HyperKaos are event chains, and they are made up of Kaos. The Kaos API is simple. Each subclass must implement run() and destroy(), and their constructors all share the same signature, taking a string as input and parsing it for necessary data to construct the Kaos. The inheritence of the Kaos API is implemented with a void pointer in the Kaos struct and a pointer to a Kaos in the subclass struct, creating a link both ways between the base class and the subclass. When the constructor for the subclass is run, it is responsible for linking the two structs together and assigning the function pointers for run() and destroy().

prototype map data file
Map data is broken in to chunks and loaded on demand when the player enters that area of the game world. Chunk data was originally hardcoded in bufferData(), which was messy, inflexible, and very hard to debug. The new system is to have bufferData() call worldBuilder(), which reads map data from a text file in the mapdata/ directory. This is the reason for having all the Kaos subclass constructors take a single string argument. worldBuilder() checks the type of Kaos to be built and calls its constructor, passing it the args list as-is. The constructor then parses this list for the information it needs to build the Kaos. If any part of the map data file is malformed, the game exits with an error message.

old prototype textbox
intro screen -- scene demo
The Kaos API is so versatile that HyperKaos chains underlie everything from textboxes to the magic system to scene triggers. The scene system is simple but powerful, allowing to break out of the top-down room context to display arbitrarily layered and moving sprites for a set time (they can be skipped if you want, like any good cutscene engine!).

save menu
The HyperKaos chains are also directly related to the save system. Each chain has an ID number which is multiplied onto the save state number when the chain is run. If its ID is 1, it doesn't have an effect on the overall state of the game. If its ID is a unique prime number, it alters the save state, making it a unique product of primes. This can be used to create branching storylines and a complexly changing world. The engine only supports one save slot for now, but you can easily copy and paste save files to bypass this.

Ayanami Shell CMS

Ayanami CMS is the backend of this website. It is a static site generator and content management system that aims to make it easy to keep a simple website up to date.

ayanami init screen
You run it from the serverside, after logging in via SSH. This offloads security concerns from the script itself, letting it do what it's meant to do: generate the website.

ayanami action choice
It leads you through an interactive session, selecting the page of the website to edit, and then whether to post something new, edit an existing post, or rebuild the page and/or the media library from an updated template.

If you post something new, the script leads you through the motions, asking for a title, a linked file (as many as you want if you just want to dump some images), and then giving control to your editor of choice to create the main content for the post. Depending on the type of file you link, the post will use a different template to hilight the filetype (ie, music or video player, vertical image gallery, file download with image preview). If you don't link a file in that step, you can still embed files in the main post content with HTML tags (as I'm doing with this post).

ayanami database screen
If you choose to edit a post, you are met with the database for that page. It will paginate with the same number of posts per page as the webpage itself (a setting in Ayanami's You can paginate forward, return to the first page, exit back to initialization, or choose a post to edit.

In editing a post, you cannot change the template type or number of files linked, but you can change the title, URL of linked files, and the post body. You can also delete a post.

ayanami HTML builder
After finalizing a new or edited post, builds the permalink for it (called "islands"), and then builds the page itself, taking care of pagination based on the setting in

The media library (formerly called the "archive") is a simple HTTP fileserver interface which lists files in the directories given in the "librarydirs" variable in the configuration. Here, I use it to host my mixes and digital art, and to mirror some of my videos.