One of my sons loves to play a dice game where you keep rolling until all of your dice are the same value. Since we have family spread around the country, I decided to build it as an online multiplayer game so we could play together. It’s still a work in progress, but it works. Click the image to play it now! If you want to try multiplayer, I would recommend arranging a time to meet someone on there – there aren’t that many random people hanging out waiting for someone to log in and play against them 🙂
The Tech Side
The game itself is built using the Phaser 3 JavaScript and HTML5 game framework. I used Babel so I could use new JavaScript language features on the development side, but it gets translated into older and more compatible JavaScript when I publish the game. I also used the webpack asset bundler. This manages a lot of the rote publishing tasks like minifying the code, importing images and sounds into a final project folder, etc. It also makes development quicker by automatically updating and refreshing the game whenever you make change to the code.
To achieve the multiplayer functionality, I built a NodeJS server app that connects to the clients via SocketIO to enable real-time coordination between the players. The app uses Express to define routes, and it uses EJS for the view templates. It took a little time to get the project switched over from purely single player to a multiplayer client-server architecture, but my son thinks it was worth it!
Several years ago, I was tasked with creating a simple relaxation breathing app so a counselor’s clients could practice at home. At the time, I was using Corona SDK for some game projects, so I whipped the relaxation breathing app together pretty quickly. While this app is not available for download, I decided it would make a very useful demo for learning the React Native framework for building cross-platform apps in JavaScript.
Screenshots
Lessons Learned from React Native
It is very easy to get started with React Native if you’re familiar with JavaScript already (and even more so if you’ve worked with React for a web project already). If you’re only going to make apps on occasion and you’re already using JavaScript regularly, this is an easy way to stand up a new project quickly.
There are definitely some drawbacks, however. I found the documentation to be frustrating relative to other frameworks like Flutter. While there were many available demos, I found it hard to track down details whenever I wanted to do something different from the demos. The stack navigator from React Native 4 was poorly documented – especially how it differed in Native versus the web. I did eventually work out all the kinks and get it working quite nicely.
The overall development process was greatly simplified by using a managed Expo project. It allows live updating of code and greatly simplifies the build experience. Luckily, everything I needed (including the audio-visual components for the guided relaxation audio file) was already included in Expo. Leaving the managed Expo ecosystem requires a bit of work, so I’m glad I didn’t have to go there for this project.
Since I spend a lot of time in the world of web development, the flex layout and CSS-inspired styling options seemed very natural. If you ever get frustrated with the layout options of other mobile frameworks, this one is about as easy as I’ve ever experienced.
One of my most intricate projects (recently shut down) was an artificial intelligence program that identified potential real estate investment opportunities. At a high level, it combed through a particular MLS each day to look for properties that might be under-valued enough to warrant a flip. The parameters used by the application to identify potential investment properties is still proprietary, but I am able to share the technology I built to make it happen every day without any manual intervention needed.
Gathering Data with Selenium
Most MLS do not provide an API or method of exporting data, so the app needed to actually browse the website itself. Selenium is a package for Python that allows the developer to automate web browsing. The realtor showed me how he would manually search for investment properties, and I translated that into an automated web browsing session that captured all of the necessary information. This involved multiple MLS searches, so I had to combine multiple data sets from the MLS for further processing.
Emailing with Mailchimp
Every day, the application sent out a summary email to investors or realtors who had signed up for the service. Rather than trying to create my own email delivery system that could handle all the quirks that come along for the ride, I decided to use Mailchimp as the email delivery service. This provided several benefits. First, it made it pretty easy to manage payments and signups on the user-facing website. I didn’t have to reinvent the wheel with a custom plugin, because Mailchimp already has a plethora of plugins available.
Second, it allowed me to offload the ability to deliver a large amount of emails. With just a few API calls to Mailchimp, my application could set it and forget it. Delivering a single email from an application is easy. Delivering a lot of emails takes way more thought and infrastructure than you might think. I’m happy to let Mailchimp handle that for me.
Automating Everything with AWS
Since the application needed to run every single day, I didn’t want to have to trigger anything manually (and neither did the business owner). But I’m also a frugal type, so I didn’t want to waste the business owner’s money. I eventually landed on an AWS EC2 instance that automatically started itself at a particular time of day, and it suspended itself when its task was complete. The instance was setup to run the program whenever it resumed from sleep UNLESS a “debugging” key was set inside AWS. This allowed me to fire up the instance and check any local logs or issues without running the application itself.
Remote Error Reporting with Sentry
When your application runs in the Cloud, how do you know when something goes wrong? Sentry allows me to log very detailed errors and receive an email notification when they happen. It gathers breadcrumbs along the way, and it only logs them if an error actually happens. So, for instance, I can add extra information to help me track down where in the program flow the error occurred, and that information gets discarded unless something goes wrong. Very slick.
I added an extra layer to this error reporting as well. Since the errors were mostly accounting for changes on the MLS website, I needed to see what the web browser looked like when the error occurred. But for a web browser running automatically in the Cloud, there isn’t a screen to look at. So I used a virtual screen whenever there was an error. In essence, I rendered the current website view to an image and then had the application email me that screenshot for extra information on the error. I can’t tell you how many times that screenshot turned a tricky error trail into an easy fix.
Summary
This was a fun project since it required me to coordinate so many different parts seamlessly. It was mighty satisfying when those daily investment summaries started going out every day without me lifting a finger. And the remote error reporting mechanism allowed me to fix any issues very quickly. It also gave me an excuse to learn a lot more about AWS.
For Hacktoberfest 2019 I updated the Code4Kids Level 1 Camp source files. We learned quite a bit from our second go-around with this camp. Some of the projects were dropped because they were too complicated, so I replaced them with much more straightforward projects.
View on GitHub
I also dropped the concept of badges. I thought the students would be more motivated if I “game-ified” the camp and celebrated their progress like a game awarding experience points. We never needed the badges to increase motivation, however, as all the students were engaged throughout the entire week of the camp! Since we’re so tangible throughout the camp, I think the students were able to see and celebrate their progress without resorting to game-ification.
The multi-day cardboard maze project was a big hit! Instead of just drawing a maze and watching the robot follow it, this year we had the students build their own maze with cardboard pieces. As we learned new skills, we returned to the maze to try them out. For example, we first drew lines inside the maze to see if the robot could make it out. Then we added color codes to help the robot know which way to turn when it was confused. Then we programmed the robot with visual code blocks to get through the maze. It provided an iterative learning experience that helped them transfer knowledge across domains. Big hit! And many thanks to Roberta for cutting four hundred pieces of cardboard to make it happen!
My son loves Star Wars. That’s actually an understatement. My son LOVES Star Wars! I’ve only known one person who loves Star Wars as much as my son. Me!
We’re teaching him about money and saving, so I found this Jabba the Hutt piggy bank on Thingiverse and printed it for him. I was worried that the threaded insert on the bottom wouldn’t actually fit since my 3D printer is a bit long in the tooth and inaccurate in some dimensions, but it fit great! Then he got to customize it with a little bit of acrylic paint!
My son and I built the PyGamer from Adafruit a couple of months ago. He loves Blaze and the Monster Machines, so we’ve been working on a racing game in MakeCode Arcade. It’s inspired by the old game Spy Hunter.
Since he loves Super Wings as well, we made a simple flying game in MakeCode Arcade. You have to collect the packages while avoiding (or shooting) the obstacles. You can also travel to different planets by landing on special areas of the screen. We drew several different characters from Super Wings, so the sprite can be switched out. Right now it has to be manually moved in the code, but if we keep working on it we’ll add a menu to let the player choose their character.
I’m also working on a top-down role playing game engine using CircuitPython. This is an exercise in working around the limitations of the platform. There aren’t many examples yet, and I’ve only found one simple Python game engine for the PyGamer, so I’m extending that engine for my own purposes. I’ve added some GUI elements like modal dialogs. The map has passable and impassable tiles, and it also has special regions that trigger actions (like going to a new scene). It’s still very much a work in progress, so your mileage may vary!
For this year’s Hacktoberfest, I added the Code4Kids Level 1 Camp source files to GitHub. Hopefully some teachers will be able to learn from my experiences with the camp and integrate some of these ideas into their classrooms.
View on GitHub
I added solutions to all the Lightbot levels. Some of them are a bit tricky, so this should help parents and teachers when they’re trying to help multiple students at once.
I also added the Color Code and Blockly projects. Remember not to give the students the solutions! Things go wrong in computer programming, and figuring out how to fix it is a major skill.
Have you ever been in church, and the preacher starts telling one of their stories that you heard six months ago? I am terrified of doing that! But I also know that I have no chance of remembering when and where I told a particular story. So I wrote a simple Python program to comb through my sermons and extract stories. All of my sermon Word documents follow a patterned naming scheme that uses the date. The program uses this fact to remember the last time I ran the story extractor and then grab stories from all of the sermons that are newer than that date. Inside the Word documents, I mark key phrases from my stories in bold, and the program extracts all bold text from the Word document and saves it to a text file (with a divider and the date and title of the sermon so I know which sermon contained the story). I copy and paste the output into Evernote so I can do a search for stories on my phone if needed. I’m sure I miss it every once in a while, but it gives me much greater peace of mind and hopefully keeps my congregation much greater engagement with fresh stories!
The program has a number of ways it could be improved, but it works for my purposes right now. Some ideas for improving it:
Add a simple GUI
Save the date of last run in a config file and update it automatically instead of having to update the date in the source code
LibreOffice randomly breaks up bolded text into different spans underneath the hood, so a single sentence can come out as multiple pieces instead of a contiguous sentence in the extractor. I would love to figure out the pattern here and find a way to automatically re-join those pieces. It works for me right now, so I haven’t made it a priority to fix that annoyance yet.