Most of my (non-video game) software projects are private but when I create public stuff, I'll present them here.




MAML Book-Keeping

I've created book-keeping software for the Mid-Atlantic Mauling League, a Blood Bowl league I commission.

A big goal was that I wanted to have most of the book keeping be result-driven. That is to say, I wanted to simply enter game results in to a database and have those results drive game-outcome presentation, standings, scheduling, statistics, and notifications.

Results table view
The structure of the results table. The database is normalized so that most of these fields are foreign keys.

Result records are added at the time they are legal games to be scheduled. Once added, they will be read and generate a new week/round in a given competition. The schedule will be updated with these new games. As games are scheduled, they will be automatically sorted and the information will automatically be distributed via Twitch, Twitter, Facebook, and Mastodon.

maml.club schedule example
An example of the schedule as presented on https://www.maml.club/.

When games are completed, the corresponding result record is updated to include the final score of the game. Aggregate data is then calculated on demand: things like winner and loser, competition points, win-loss record, standings, and TD sums and differential. Even the Blood Bowl championship bracket is generated dynamically.

maml.club standings example
An example of competition standings as presented on https://www.maml.club/.

Even historical records are calculated and presented to the user. The user can group historical data by various fields such as team, race, and coach. They sort data by points, win percentage, wins, losses, draws, TDs, etc.

maml.club statistics example
An example of league statistics as presented on https://www.maml.club/.
maml.club statistics grouping, sorting, and ordering example
Statistics can be grouped, sorted, and ordered by a variety of options.
maml.cluc statistics showing different grouping and sorting
Here, the statistics have been sorted by race and their historical win percentage in the league.

All of this information is presented three ways: the maml.club website, the MAML Discord server, and social media.

Once a record has been updated, the website automatically updates. It's not just the data that updates. Navigation is generated as required. Proper nouns such as competition name change as required and different "pages" are added as required by the season and the particular format & length of a given competition. This also allows past results to be displayed and navigated through.

Standings, brackets, and schedules are also automatically updated for Discord. They are provided as dynamically generated images and delivered by Nightbot. Custom commands expose this information to users in both Discord and in Twitch chat. It should be noted that since these are images, I have Nightbot tack an arbitrary query string to the end of a URI to force a cache refresh. Otherwise, users might see out-of-date information when retrieving a cached image.

These images come in a variety of configurable formats. For example: I use one configuration to display the standings and schedule live on stream as interstitials while I use a different configuration to display the MAML logo for Discord and user usage.

Standings in the MAML Discord server
The standings images in the MAML Discord server.

Finally, social media accounts are updated as needed. Twitter and Facebook will automatically post when a game has been scheduled. Facebook posts these as actual Facebook events. Twitch will be automatically updated with the title of the next scheduled game as well as updating the standings panel. Twitter, Facebook, and Discord will automatically post when a game has gone live. When a stream ends, those three platforms will post the video-on-demand of the game. Bluesky updates are currently done by hand.

Automated Twitter posts
An example of posts automatically made to Twitter by the book keeping software.




Nightbot Die Roller

I've created a simple Nightbot die roller. It rolls dice of any natural number of faces. It supports 'd' notation as well a single digits. It also has a Blood Bowl gag because I like Blood Bowl.

Nightbot die roller screenshot
Output of the Nightbot die roller in Discord.