Ggj18 Post Mortem

Education and Motivation through Jamming

This past weekend, January 26th, 2018, was the date of the most recent Global Game Jam, an event where creators and teams worldwide come together and try to build games to fit a previously-unknown theme within a scant 48 hours. Last year’s GGJ was my first one (though my fourth game jam overall) and I found the experience invaluable. The theme that year - “Waves” - led us to creating a pirate-themed adventure game. One of the diversifiers that year (extra challenges you can add to your game to help it stand out) was accessibility for the differently-abled. Because of this, we chose to build a voice-controlled game for the Amazon Echo, to continue to fit with the theme; sound waves, water waves. Building something unique on hardware I’d never worked with and trying to get it running within so short a time was both exhausting and exhilarating, so I jumped at the chance to participate again.

From Theme to Concept

Huddled together in a small room in the Microsoft building at 6pm Friday, several hundred amateur game designers waited with rapt attention as the sponsoring organizations went through their lectures, all focusing on one thing - what would be the theme announced this year? See, while you can come into the game jam with some prior work or an idea ahead of time, that’s very much defeating the point. The idea is to let the theme drive you and let your creativity run wild. It’s only 48 hours of your life - you don’t have to worry if there’s a market for your game, if it will sell, or even if it will be accepted to an online marketplace. You can let your creativity run truly wild.

Finally, at 8pm, the theme was announced - “Transmission.” A broad theme, to be sure, as they seem to always be for GGJ. Instantly, our shared discord and slack lit up with concepts and ideas. Already having a team I was comfortable with, we fled the room as ice breakers and team matchups started. By the time we’d returned to the apartment we were ready to start whiteboarding. Within about an hour, we had our theme nailed down. We would make a rhythm game where you played as a white blood cell destroying infections in the blood to the beat of the music, which would also be the “patient’s” beating hard. Disease transmission, sound transmission. It seemed like a solid concept that fit the theme and, additionally, I thought it would be easier than some of our previous concepts. After all, rhythm games don’t have gravity, collision detection, or a physics engine. Notes move from one side of the screen to another, and if you press the button at the right time, you score points. How hard could it be?

Immediate Difficulties

As soon as I loaded Unity - my engine of choice for this project - and started coding, I realized my mistake. Syncing visual beats to music is really, really complicated. The computer doesn’t really have a concept of a ‘beat’, and in Unity, everything happens in frames. What happens when the beat of you song happens between frames? What happens if the framerate is worse on a different piece of hardware? In something like a platformer, it barely matters if your sounds are off by a few milliseconds, but in a precision environment like a rhythm game, timing is critical. The player cannot be made to feel like the timing in the game is ‘off’ or the game will not be fun. Furthermore, even if you do somehow get things in sync, you cannot just have the notes instantly appear. The player needs time to react, so the game must anticipate the beat, instantiate the object, and have it land in scoring position on the beat instead. Having only 48 hours to solve this issue, I immediately turned to the first tool in the kit of every dev who’s ever been under deadline.

Searching the Internet for Other Approaches

Lucky for me, there were several different posts on solving problems just like this one. Unfortunately, we tried these all with varying levels of success. The one that eventually proved the most useful to me was Yu Chao’s devlog detailing his approach to rhythm syncing in his game Boots-Cut. This led me to some interesting formulas for converting song tempo to “beats”, and finding the nearest “beat” from AudioSettings.dspTime to garner the most accurate info. Additionally, although we had to alter the math significantly, his utilization of interpolation for movement proved vital. I just wish we had stumbled on it earlier.

Failure to Launch

Sadly, this marks the first of my five game jams where we failed to submit a playable product by deadline (3pm on the Sunday following the start). The game is not completely broken. It compiles to Android as desired, the scene transitions all work, and the beat pattern does in fact spawn viruses as we’d like and move them to their desired scoring positions. The issues are in scoring, which is not implemented at all, and beat synchronization, which requires further testing and may need a total overhaul. In this state, we did not feel we could submit a product. That said, I do hope to put at least a little more time into it to get the game to a state where it could at least be called a demo and I can feel proud hosting it on my itch.io page along with my other game jam projects.

Future Progress

So, what is the state of the game - which we dubbed Sonic HemoFyte - and what can be said for the future of the project?

I would class the state of the game as pre-pre-alpha, and in-progress. As for what needs to be done, the answer is quite a lot actually, and much of it depends on setting up some sort of unit testing. Here are some things I think we might need to do to complete this project:

  • Revisit and refactor core gameplay entirely. We may need to consider changing this game from a rhythm game to a tap-based rail shooter or something. The good news is, I think there could be a market for a semi-educational, kid-friendly game of this type.
  • If we keep the rhythm aspect, we may need to change the overall design. I’m not convinced a rhythm game in this perspective and with these visuals can work. Generally, notes in rhythm games are a universal and simple shape and animations take place in the background. Perhaps moving the graphics into a position as more “flash” instead of being the interactable UI would help. It may also help to have the objects moving linearly across the X or Y axis instead of flying at you.
  • Calibration. Even if we get the beat syncing properly on one device, there is no guarantee that other visual, audio or input devices will not introduce new lag that we can’t anticipate. This reddit post includes some insight into how to build out a calibration system similar to the one in guitar hero to alleviate this issue.
  • Adding more songs. One isn’t enough, obviously. I’d also like to add music by some other artists, including writing some tracks of my own now that I have more time.
  • Bugfixing. Always.

Wrap Up

Even though I can count this among one of our least successful jams, I still can’t say I’m sorry I did it or that I wish we had chosen another game type. I’ve learned so much about Unity, C# and even just coding in general in such a short time, that I think the frustration, stress and trauma were probably worth it. Who knows? Maybe we’ll finish and release the game some day. And if not, there’s always another jam on the horizon.

Mind Your Meds Alpha

Helping patients remember their medications

I’ve had a concept for a while now for a mobile or mobile-accessible web app to help patients keep track of the medications they take. In addition to a host of other features I’d like to build in eventually, even just a list of the pertinent details of the meds their on would be useful for patients when meeting a new doctor, visiting a new hospital or filling out medical paperwork.

When tasked to build a CRUD application with account services for my Sinatra final project, I opted to build an alpha version of this application, with an eye toward expanding in the future.

Technology

Most features required for this app were things I had done before, so there wasn’t much to worry about. I used ActiveRecord to handle the SQLite DB for the backend of the site, having two models:

  • User, which handles user accounts including name, password, and e-mail addresses and have many medications.
  • Medications, which comprise all details of each of a user’s meds, and belong to a user.

Sinatra and rack-flash were used to handle routing and error messages, respectively. In the future, I will not use rack-flash again and instead will be using sinatra-flash. I had to use a few work-arounds to make flash messages persist through redirects, where I could have used flash.keep if I’d used sinatra-flash instead.

I thought about writing my own regex to control for validating e-mail address formatting, but in the end I instead went with the email-validator gem. You can easily determine e-mail validity by passing the address via EmailValidator.valid? which makes things much simpler.

Conclusion and next steps

In general, this was a fairly straight-forward project. The model interactions were one-way and simple, and because medications are private matters, there was no social aspect or inter-user interaction to worry about.

In the end, the majority of concerns involved validating and authenticating. Validating that use input was good and valid, and authenticating that the user had the right to create and edit the information with which they were interacting.

In the future, I would like to take this app further in terms of both basic usability and feautres. In the short term, I’d like to look to some better responsive features, like info boxes than can collapse or expand to make viewing medication details easier instead of necessitating a page transition. Long-term, I’d like to roll this functionality into a mobile app which will allow push notifications for when to take medicine and possibly interact with the NHS API to list contraindications as well.

Building a scraper for new Comixology releases

When tasked to write a command line tool utilizing a web scraper for my program at The Flatiron School, I chose a path that’s pretty standard for me. Namely, I tried to find something I could do that would maybe come in handy later. In this particular situation, I’ve been wanting to make a tool with access to the Comic Vine API for some time. While API access was not on the menu for a scraping tool, I felt like doing something else in the realm of comics might be a useful start. At the very least, perhaps I’d have a start on some object frameworks for the future.

To this end, I chose to build a scraper that would look at the Comixology new release page and extract the new comics that were available, allowing the user to drill down into individual issue to retrieve more information.

When the project first started out, things were fairly easy. Using Nokogiri to scrape the site, I found the CSS selectors fairly simple to differentiate. Comixology has used many specific attributes for the various sections of their pages, which made selecting specific information a breeze.

Strange text formatting

The first minor hurdle came with the formatting of some of the text on the page. Instead of using raw CSS for positioning, page used tabs and newlines for some of their text positioning. This resulted in output like this (in this case, artists):

\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tJohn Buscema\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tKim DeMulder\t\t\t\t\t\t\
t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tDavid Mazzucchelli\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tGerry Ta
loc\t\t\t\t\t\t\t\n\t\t\t\t\t\t


Obviously, that’s no good for a program that’s designed to be human readable. I needed to remove these non-characters, and I also wanted a format that would differentiate names, no matter how many different contributors had worked on a specific book. I ended up using the following line:

issue_hash[:artist] = page.css("h2[title='Art by']").text.gsub("\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n", ", ").gsub("\t", "").gsub("\n", "").split.join(" ")


Essentially, what we do here is find a very specific string that Comixology uses to achieve newlines and position between contributors and replace it with a comma and a space. Then, we find every other tab and newline and remove them outright. Finally, we split the string on space characters and then rejoin. We do this cleanse our strings of repeated spaces, since some strings within the Comixology site use long strings of spaces for positioning. This may seem like a roundabout method of achieving this (versus something like .squeeze), but as it turns out, this is one of the most efficient methods for small strings.

Foreign characters in URLs

The next foible had to do with URL parsing. Scraping Comixology’s main site was working just fine, but I found the app failing when attempting to drill down into some of the issues on the site. Upon further investigation, I found these issues were in foreign languages (French, Italian, etc) and the URLs referring specifically to them included non-unicode characters. These charcaters are not supported by Ruby’s URI implementation.

To deal with this issue, I chose to implement the Addressable gem. Addressable provides many functions for dealing with URIs more robustly than Ruby can natively, but in this case what I wanted was the ability to normalize my path, replacing the foreign characters with their percent-encoded equivalent. See below:

issue_uri = Addressable::URI.parse(issue_url)
parse_path = "https://www.comixology.com/" + issue_uri.normalized_path
page = Nokogiri::HTML(open(parse_path))


###Future plans

The Comixology New Release Extractor is now at a point where I feel comfortable submitting it as a project. However, I would not feel comfortable submitting it to the general public or attempting to publish it as a gem. There are a few changes that need to be made before that can be considered.

Formatting and pagination

Right now, user output is pretty good, if ascetic, at the single issue level. But the full list level is a different story. In its current format, the list option returns 188 issues, at one per line. That’s a lot for a user to scroll through in a terminal window. I tried Pager, but it wasn’t very user friendly. One option might be to use Command Line Reporter, but another possibility would be to split the lines up via nested arrays and build the paging in myself.

I’d also like to begin extracting the release dates and optionally grouping comic releases beneath them, since the new release page displays releases from multiple dates.

Reading ALL comic releases

Comixology’s release page pages out the releases at a maximum of 12 per date. I believe we could read all of the pages from each date by reading the hrefs of the buttons and then checking the CSS of the page they lead to, but that will be both network intensive (slow) and involved to implement.

Making the app into a usable gem

Once all the above are completed, I’ll consider this a possibility.


Summation

Creating this app has definitely been a learning experience. Some things that I thought would be difficult (CSS selectors) ended up being very simple. Other things that I expected to be trivial (output format) turned out to be major issues. I look forward to my instructor code review and my continued improvement on this project.

Dynamic User Input with XML in C#

When I started coding in medical software, one of my first major projects was to create an online patient intake form for doctor’s offices. While this may sound simple, for someone who had basically no experience with server-client architecture, it was actually the equivalent of throwing a new swimmer into the diving well and letting them learn how to swim. Let me explain.

Patient Intake refers to all those forms you fill out the first time you go to a doctor’s office. We wanted to eliminate this paperwork and also the additional wait between arriving at the office and being seen by a physician, so the goal was to make this form available for completion online prior to the appointment. While creating a user input form and storing the data in an SQL server to push to the doctor’s client software later is obviously simple, the problem arose when we discovered just how incredibly varied doctors’ intake forms could be. They were essentially a big mishmash of field types:

  • small text input (ex: patient name, medical complaint)
  • checkboxes (ex: family history of illnesses from list)
  • radio buttons (ex: are you currently a smoker?)
  • date boxes (ex: date of birth)

To make things more complicated, a question which was vital for a podiatrist might be completely useless for, say, an oncologist. Some doctors we surveyed even had off-the-wall questions specific to their practice that we’d never seen or considered before.

Taking all these factors into account, we knew we’d have to make the Patient Intake segment completely customizable within a set of different input types, and the customization interface would need to be easy enough to alter so that either end-users could write them up themselves, or alternatively, so that we could create a simple user interface to do it for them. After examining some of the different options we chose to go with a XML base. The reasons for this were as follows:

  • we work with coders in several different physical locations and XML has strong standards
  • we already had some frameworks in place for transmitting XML, so it synergized well
  • some of our coders speak languages other than English and found XML simpler than JSON, etc.
  • XML work well with MSSQL Server and can be queried directly