LogRide for Android
In November of 2018, I was contacted through the grapevine that some students at another themed entertainment club at another university in florida - specifically, TPED at UF - were looking for some help. They'd built a mobile application called LogRide for iOS, which served as both a database of parks and attractions and as a checklist tool - you can mark off each time you ride a ride, and it'll keep track of it for all of your parks. They needed someone to port it to Android, and I ended up fitting the bill.
So, over the winter break of 2018-2019, I developed what would become the first version of LogRide for Android.
Table of Contents
The First Version
Right away, I knew I wanted this to be cross-platform. Developing two versions in parallel - especially with asymmetrically balanced teams (2v1) - was going to be a little bit of a waste of development power. On top of this, I really didn't want to touch Android development in native Java/XHTML again. So, I decided to try Google's Flutter.
Flutter is neat. When I started playing with it, it was a bit less developed and a lot more... rough around the edges. Not to mention I had no idea how to properly manage state. I tried playing with it the first time to create a kind-of configuration app or remote control for the MagicRadio over bluetooth, but that never passed the app layout stage. This time was for real, with a kind-of proper API and starting point to work from.
After browsing a bunch of screenshots from the iOS team, I came up with these screenshot plans.
Great for a phone that doubles as a shortsword.
I began implementing the main home page in Flutter, with a lot of tweaks from this initial plan. Nothing about this is clean or useful, so I did a bit of work on making it... better.
Before I show you more layout changes, I'd like to talk about the way data is stored in LogRide. MySQL is used for our bulk data - this is information about parks, attractions, etc. Things that don't change too frequently, and are used by all of our users. Firebase, by Google, is used for personal information storage. This was nice as it gave us (effectively) free authentication and synchronization of user data.
It quickly became apparent to me that managing two streams of data at once was going to be... messy. Especially with Flutter, I really was going to have to put in a lot of planning to do this intelligently.
With my retrospective goggles, I did not do it intelligently.
My implementation with the first version of LogRide was to download all of our initially relevant MySQL data to the phone upon starting the app, and then rely upon that for operation of the app. With a park or two, this was easy. When you get up to about a dozen parks, it really, really suffers. Terribly inefficient.
With that in mind, let's see what Version 1 looked like.
It... wasn't bad. A lot of screen real estate was taken up by empty space and headers, but it worked well enough. If you only wanted your favorites, you could hide down the "all parks" section to reveal only favorite parks. The biggest drawback of this version is the lack of extra navigation - you've got this page, one to the left, one to the right, a page to add parks, and a page to view park details itself (screenshot lost). That would change with the release version of LogRide.
When I showed this to the team, they were excited. It matched the spirit of the iOS application, with some nice android flavor. We'd just adjust the home screen to remove a lot of that empty space, and we'd be in a really good spot.
The Release Version
This is probably the version of LogRide I'm most proud of. It doesn't have the most features, it doesn't have the most snappy UI elements, and it most certainly doesn't have much flair, but it's the version we released to the public as the first version of LogRide for Android. And I loved it.
Shortly after the completion of the initial prototype, the iOS team made the decision to undergo a full UI change to include a bottom navigation bar. So, I recycled as much as I could from the old version and crammed it into the new navigation system. In addition, I implemented the various new features that went alongside that - The Newsfeed (now discontinued, unfortunately), it had a slightly better stats menu, an improved UX for adding a park, proper attraction details, a (nonfunctional) "collections" menu that boasted our stats, and a settings page with all that entailed.
It was clean, homogenous in design, and fast. I loved it.
Wait Times
With spring break coming up, and the app mostly caught-up to the iOS team, I decided to do a bit of work I could do with only my laptop: develop a brand new system and API for delivering wait-times to our app. There already existed a service out there for getting wait times from a lot of different parks (cubehouse/themeparks), but it had no idea what our LogRide data was, or how to translate betwen LogRide data and Themeparks data. So, over a few days, I put together a little system to do just that.
Since themeparks is a NodeJS library, I learned how to use it. It's neat. I don't have much more to say about that at this point, but it's neat. Working with Heroku can be pretty neat, too - the auto deploy from Github is really, really nice.
In short, the WaitTimes service for LogRide takes in a GET request with a given LogRide park ID, asks for wait time data from Themeparks for the park that that ID correlates to, and then translates those results back into LogRide attraction IDs for the clients to display.
The difficulty comes from the mapping of attraction IDs.
There's just... so many.
Cardin Menkemeller, the head of the LogRide team, and I worked continuously on matching Themeparks attraction names to LogRide IDs for about a day or two. Eventually, it was done and reliable.
I documented the service in a very nice readme.md, and once spring break was over, I put it to good use on the Android Side and let the iOS team implement the client-side how they wanted. I got complements about the documentation. That always feels nice.
Experiments / Graveyard
Here lieth things that I was playing around with at this time that I never quite finished, or were in the app but removed at some point.
In the highest honor among them was my multi-selection fan.
The Fan
LogRide for iOS had begun implementing their premium featureset, which included a bunch of different ways to view how a park's attractions had changed over the years. This was all done in the attractions listing view, which was getting a bit... cramped. Their solution was more buttons that took up space, but I wanted something a bit more... dynamic. I wanted The Fan.
The concept was simple: When you long-tap the primary navigation button for LogRide, a "Fan" of option would blossom out like a boquet of flowers. I was pretty proud of the implementation, too - all done using some simple math animating the elements in polar space, then converting those into cartesian coordinates. In the end, I think it ended up really nice, as shown below:
As it was entirely programmatic, the animation could be tweaked in almost every way, from the number of items (which would automatically adjust spacing for more), to the speed, to the rate at which it expanded. It was very powerful, and (with the exception that you don't even know they're there initially), very intuitive.
Trip Reports
This was an improved version of the feature that already had existed on iOS. By leveraging the benefits of the Flutter widget system, I made a really neat way to create and render to an image a bunch of interesting user data (and customize what showed up). Here's it in action below, with some test data:
Unfortunately, summer classes started for me, and they got... extensive. All my development went on the backburner.
The Distance
From here, LogRide became a bit of a lower priority for me.
I'd been used to small, month to three-month-long projects up to that point.
And with a somewhat difficult to cooperate with iOS team, I really didn't feel like I was developing LogRide, but keeping up with LogRide. With the exception of the Wait times service, it felt like most of what I was doing wasn't cooperative, but combatative. I'd have to shake down the iOS team and source code for how / why any given service worked, question them about idiosynchrasies in the systems, and then just suck it up when something broke out of my control. Not an environment I wanted to continue on too frequently with.
It really became low priority for me after this point. But it was still there. I couldn't start other projects, because I'd feel like I was betraying LogRide by not working on it, but I wouldn't want to work on it due to the weight of the technical debt. Not fun.
My Last Update
I'd classify Version 3.0.2 as my last update where I did active development of LogRide. Cardin, mentioned beforehand, actually got a job doing Flutter development. His experience in this let him really take LogRide to a technically compenent level with BLoC design patterns and what not. 3.0.0 brought multiple-photo support for attractions, a map with pointers for park browsing, a feedback system for your open submissions, haunts, midways, and a trip report summary page. But I was beginning to check out. Version 4.0, released in January of 2021, was almost entirely Cardin, refactoring a lot of stuff and integrating LogRide Pro into the Android side finally.
It's not my app anymore. And that's a relief.
I still use it regularly, and keep it up to date with Cardin's work. I just really, really don't want to write code for it. In any capacity.
Burnout is real.
Download LogRide from the Google Play store: https://play.google.com/store/apps/details?id=us.stoeckert.thomas.logride
Download LogRide from the Apple App Store: LogRide - Theme Park Tracker on the App Store (apple.com)