The Triviosity Rewrite

Filed under: Coding,Games,PHP — Darryl Clarke @ 7:09 pm

The Rewind

In 2010 I put a game online. Triviosity, a daily trivia game with occasional specially crafted challenges, has been online for over 8 year. It’s a game that people play on a regular basis and it’s always held a piece of my heart. When I originally wrote it I had full intent to make it a mobile app. An iOS app specifically. The original was built with Zend Framework 1, had a clunky API back-end with intent for the mobile app, and quite frankly it was rock solid. It ran without issues. Unfortunately the iOS app never happened, and as other frameworks and tools blossomed, ZF1 became outdated and not worth the time to build upon it.

Fast Forward

On thanksgiving weekend in October 2017 I decided it was time to rewrite my old game. It was time to switch up the technology and actually make the mobile app. At first glance I thought it was going to be a very daunting task. Switching from ZF1 to Laravel 5.5 seemed like it was going to be a huge undertaking. But it wasn’t. My data models from the original game were so awesome that porting the “beef” of it (I like to work with fat models) only took me a few days.

I sat on that small victory for months. Enter the void of hesitation. Was it too easy? Was I going about it all wrong? Was I doing this the right way? Is anyone new even going to play this rewrite?

If there’s one thing I absolutely detest it’s doing something over. I had to do this, but I hated doing this. There was a necessary evil at play – I want to build the new mobile apps. But I need to redo the old game to get there.

Then I got rolling. I don’t know what changed. I got about 90% complete then I stopped.

Who’s going to play this thing? Why am I doing this? Question, doubt, rinse, repeat.

Then the tidal wave hit. Frack it. “I’m putting this live.” It’s “good enough” and I can fix the missing parts. As a matter of fact, once I put it live, my desire to finish it and make it better went up exponentially.

On July 30, 2018 the unscheduled launch of the new Triviosity happened. A few hundred error emails later, and a bunch of random fixes, the dust had settled. And it’s alive.

Performance

There are two things that take precedence in my work. Security and Performance. Without going into too much detail about security (I can’t give away all my secrets) the new API includes request signing, encryption, and wonderful third party oAuth based authentication.

For performance, It was critical that I make this as fast as I possibly can while still leveraging my old (affordable) web servers. After launching you can see a substantial drop in load times and render times. (This isn’t just the home page either, it’s all pages.)

look at those performances

super graphs

The kicker was simple. Use the tool-set you have properly. As I mentioned, this was being built with Laravel 5.5 (and upgraded to 5.6 before my actual launch). As such, there’s one hell of a generally under-utilized tool-set available to me to use. So here’s a simplified rundown:

  1. CacheCache all the things you can. Cache your config files, routes, database queries. There are pages (score listings) that have a substantial amount of queries of data that doesn’t change often. Caching this turned render time from 500ms to 100ms.
  2. Compile / Minify CSS and JS – Laravel has a webpack config that utilizes a basic Laravel Mix out of the box. It has many nifty plugins to do everything you need. I only really needed the sass compiler, minifier, and JS minifier. This task is often overlooked and it yields some of the greatest performance boosts. The production build tool is A+.
  3. Offload to the Queue! – Using an asynchronous queue to handle things that don’t need to happen for the end user to continue is also a huge boost to performance. Things that can happen in the background: big database updates, sending emails, generating images – all done without the user feeling the slightest bit of a slowdown.
  4. Use the F’ing Framework – Far too often (I’m guilty of this too) I see code that “uses” a framework, but then it doesn’t actually use the framework. Laravel and it’s dependencies have been built up over the years to do a lot of the repetitious work. If I told you the code for the game controller was only 230 lines, you probably wouldn’t believe me. I leverage the framework’s models and view renderer to do the majority of the work. For reference, the old game play code was almost 1000 lines. Less code, same game, more efficient.
  5. Ditch The Cruft – I don’t use any external third party JS on this site with the exception of Google Analytics and Google AdSense (non blocking). Facebook, Google, and Twitter authentication is completely via server side redirects. The share buttons are just good old fashioned native links (which, as a bonus, launch the native apps on most mobile devices).

This is how you get a double A’s on speed tests.

The Future

Now that I have successfully released the best performing site of my life, I can finally work on the native mobile apps. I have no direct timeline for these. I’ll be building them as 100% native apps (Swift for iOS and Kotlin for Android) and not using some goofy cross-platform build tool so that will have some affect on the time frame. But they’ll be fast. They’ll be secure. They’ll be just as awesome and performance ready as the site itself.

Now with an even more rock-solid foundation I can build on this. We can all expect more curated challenges with great features.

TL;DR

It took me about 10 months to complete the rewrite. But in reality only 40 days. It kicks ass. It’s fast. It’s great. The mobile versions are coming soon.

Now go play some Triviosity. And let me know if you break something.

Murder, He Wrote

Filed under: Things You Didn't Know — Darryl Clarke @ 11:36 am

Today’s short and bittersweet jury duty process shook me to my roots.

It started off innocuous enough. Get to the courthouse on time, check in, sit and wait in a large wood panelled room that was built some time in the late 60s. With little to no information provided we waited. People slowly trickled in well past the posted time of “9am” but that didn’t seem to matter.

At some point around 9:30 we were provided with a start time. “The judge will be in at 10am.” followed by a collective sigh. Nobody really wanted to be here. But, a las, it is our civic duty.

As time rolled on, in seemingly slow motion, the court clerk did a mic test and other menial tasks to prepare the court.

Finally at around 10:15 the important people shuffle in through a door to the left followed by the defacto “all rise.”

The charges are read and a plea is submitted. “Not guilty,” — If it were the other way, this story is over. Potential jurors go home. However, not the situation, this case is going the distance now.

Thus begins the juror elimination round. The judge reads out some basic instructions followed by a few questions, in my informal summation:

Anyone know the defendant, the lawyers, or me? No, cool.

Anyone know any of these witnesses? (Reads a huge list) No, cool.

Does anyone have a personal reason why they may be unable to view this case with an open mind? A few people stir. A few hands pop up. People are directed to the right side of the court. A short line up builds. My insides start shaking like a scared little child. Apparently I’ve have something to say to this question.

I shuffle over to the line of about ten people and wait. One souls friend was killed recently, he was dismissed. Another had some strange story, I missed most of it for my internal fears, dismissed. A young lady in front of me tells the court her uncle was killed in a similar way. Dismissed.

I can only assume by now that what I am about to say is a valid answer. Unbeknownst to me I was about to tell a room full of strangers something that hardly any of my closest friends even know.

Sucking back the internal fears, focused solely on the judge, I leaned into the mic and said “In 1988 my father was shot.” The judge peered over to me about to say something else, I leaned back in and said “he was murdered.”

“You are dismissed” she said without hesitation.

I quickly exited the courtroom as fast as I could without running, while the court was still reading my juror number and confirmation of dismissal. In the hall way the lady before me was also making her exit. We chatted a bit down the six flights of escalators.

“I wasn’t really prepared for those memories to be surfaced like that.” She noted.

“Same.” still shaking on the inside. “Definitely not what I ever expected.” I said with a deep sigh.

She too experienced the inner trembles of having to say a terrible truth in front of a room full of strangers.

“Have a nice day” we said. I guess.

We found the exit and went our separate ways in the greyness of the cold wet morning.

All joking aside from “how do I get out of Jury duty?” I had no idea that I already held an unwanted card up my sleeve. I had no idea. It’s inexplicably strange that I’m actually quite happy that I got out of this. But the circumstances and process were an absolutely terrible and unexpected experience.

The reality is though, the question asked and my answer given would in fact impede my ability to view this case with an open mind.

The irony is I didn’t have to do that, the case is set to last a fairly long time and I had a simpler, legit out. But hey, sometimes the hard ones come up first.

So now they know, and now you know.

Making Games: The First Few Releases

Filed under: Coding,Games — Darryl Clarke @ 11:40 am

making gamesNot too long ago, just before the start of 2016, I decided I’d start making games. I decided I would become a part time independent game developer. (cheap plug, you can find them all here: Games By Darryl)

I started out with an ultra ambitious plan to release one game per month for the entire year of 2016.

Come March, I finally released one. I released Digits! (iOS, Android) to the world on March 5th. A possibly unique game involving simple math. The initial response was pretty interesting to watch. Local friends would download it, tell people in their near proximity to download it. A classic example of “word of mouth”.

A few friends would crack some jokes “oh, so you’re a game developer now, eh?”, “mr. big time game maker!”.

One hundred and sixty six downloads later, it was pretty much over. Nothing left but the trickle that would go on for eternity of anywhere between zero and five downloads per month.

About two weeks later, I released Connexxion! (iOS, Android) to the world. This game is a remix of an older game I used to play, Chain Reaction. It was fairly simple to play, but slightly too frustrating for those who couldn’t quite understand it. It was an anti-game. It gets easier as you go, as long as you can make it past the first few levels.

I’m not exactly sure what happened but the initial downloads for this game was much higher than that of Digits. There was a lot of the same initial reaction from local friends. This game’s “word of mouth” involved a few swear words due to the initial frustration of it. But overall things were looking up.

After about three hundred and ten downloads, it entered into trickle mode.

When I released those two quickly I thought for sure I could re-target my twelve game plan. At this point I had a list. I had a list of more than enough game ideas to do this. The ideas weren’t over complicated and definitely things I could complete in short cycles. However, that plan fell flat on it’s face again.

As I started working on other games (I had at least three in-progress games at the end of March, 2016) I started getting distracted by my own other ideas. This stalled progress hard.

I released my third game, FOUR (iOS, Android) some time in May. This time based word hunt game is ugly to say the least. It had a whopping sixty-six downloads and fell flat on it’s face. It isn’t a bad game. It was just ugly and hard.

I released a two more games in 2016, bringing the total to five of my attempted twelve:

And so far this calendar year, 2017, I have released one game. A knock-off 2048 tile game; 2048 Plus (iOS, Android) – It, without going into much detail, has surpassed all of my prior games in downloads simply because I rode the coat tails of a fad.

To say the least making games requires you to ride the TIDE.

Time.

Time is critical to making games. I can make time. I did most of this stuff on weekends or evenings. The only real issue with time comes when you need to loop back and update or fix a prior game and that maintenance cycle conflicts with your forward cycle.

Ideas.

Ideas are cheap. Making games from the ideas is also cheap. Making them actually work and look decent enough takes design.

Design.

This is where I start failing as a solo developer. Design has a bunch of moving parts. All these parts need to work together to create a useful and entertaining user experience. I feel like the user interface elements in Digits and Connexxion were simple enough and clean enough to pass, and will likely never need an update.

Other games though suffered hard from my lack of design time. Making games like Bounce was different because of the type of game. I didn’t focus enough on design elements to make it a fun game.

Since I am not a graphic artist, I find myself using other asset packages. I pay for graphics. I build from other people’s art. There are a lot of members of the indie development community that severely frown upon this. “You’re not an indie dev, you didn’t design it all!” – it doesn’t bother me, but it probably hinders support from others. However, I will continue to kit-bash and mix and mash any of these paid assets I have or will buy, because that’s the only way I can do this solo.

Execution.

When I refer to execution, I mean putting everything together. It’s one thing to make a little game, but the real nitty-gritty parts of it:

  • Testing on platforms, Apple and Android
  • Deploying to app stores (Apple, Android, Amazon, or more) takes time, graphics, writing. I have to not only make the game work; I have to try and sell it.

There’s also a lot of internals that aren’t game-play related that need to be looked after. Analytic tracking, ads (sorry, I want to make money too), achievements, leader boards. These are things that I thought I could leave out when I was rushing to make my first twelve. I found out quickly that I needed these things. As such, making games needs more time.

As this fast moving 2017 winds down, I still have a couple of games in progress, and an update to try and get out. I’ll just have to see what level the TIDE is at. In a future post I may talk about some other experiences with social media and the indie developer community.

The Apple Conundrum

Filed under: Randomness — Darryl Clarke @ 1:06 pm

apple conundrum and devices that i can't plug in anymoreApple, once upon a time, was the go to source for hardware for developers. Some developers may still swear by it. I however, am rolling far away from the Apple tree.

The price of current edition Mac Book Pros have gone up so much that I can not justify buying it. Apple products do not make me money. They are not required for me to do my (entire) job.

Rewind about 12 years. I bought my first 15″ Mac Book Pro. This was the first time they were aluminum bodied. That MBP was a sweet sweet piece of hardware, and as a novelty, I know I paid way too much for it. I fell for the Apple upgrades and spent about $2500 for it. That laptop lasted me about 2.5 years with one battery replacement, and a few other hardware related issues, which was unfortunate.

Move forward to 2009 when Apple released the full body aluminum models. This design was damn near perfect. I got myself a 13″ MBP for around $1700. In 2011 I upgraded the RAM to 8GB because I could. In 2014 I upgraded the hard drive to SSD and retained the original HD as extra storage because I could. In 2017 this MBP still functions fully, albeit a slightly diminished battery capacity. I’ve gotten over 8 years out of about $2200 in total. Unfortunately for me, Apple has deemed this hardware to be “no good!” incapable of upgrading it to the latest OS, which means I can no longer do part of my job (iOS development) on this fully functional hardware. This form of forced obsolescence is, quite frankly, bullshit.

Move forward to today. To get a MBP of approximately the same capacity (500+GB space and 8GB ram), ignoring “slight” CPU improvements, and a fairly under-powered GPU, I’m looking at a minimum $2229 out of the gate. And guess what? I can’t even do my job with that as-is courtesy of Apple Innovation and their desire to remove all of the ports. I’d need to add a pile of dongles or a “dock” just to get back regular USB, ethernet, external monitors, etc. That’s an extra $300 easily.

At the very most in my life I need a Mac OS machine that’s capable of running the latest Xcode on the latest OS.

Which brings me the conundrum. Do I bother to blow money on a new laptop that I (for the most part) know will not last me as long as my prior laptop?

Do I try and buy a used one that’s capable of running macOS High Sierra? The resale value tends to be a bit high too though, but at least that money doesn’t go right back to Apple.

Do I find an alternative Ubuntu capable laptop and just pick up a cheap-ish Mac Mini to do my Xcode work on? I could probably buy both of them for less than $2000 easily. Unfortunately that puts a kink in the work flow, that’s for sure.

What do other hybrid developers do? I work with web, native mobile, and other “creative” code projects. All of which are cross platform except iOS.

Thoughts or opinions welcome.

A Quickie on Using Android Studio on Ubuntu

Filed under: Coding — Tags: , , , — Darryl Clarke @ 7:01 pm

The original post below applies to old versions. For 0.4.x plus, you don’t need to do this. You just need to have a proper Oracle JRE/JDK installed system wide which you can do with this:

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update && sudo apt-get install oracle-jdk7-installer

With the recent preview release of Android Studio it’s important to know that it won’t work properly on Ubuntu with the OpenJDK that’s available.

Fortunately, it’s easy to get it going.

  1. Download the official Oracle JDK
  2. Unpack it (I put mine in ~/SDK/jdk1.7.0_21/ )
  3. Point your JAVA_HOME to this.
    ~/android-studio/bin$ export JAVA_HOME=~/SDK/jdk1.7.0_21/
  4. Run the android studio startup script.
    ~/android-studio/bin$ ./studio.sh
  5. Make awesome android apps.

Have Fun!

Allowing the Facebook Debugger through nginx’s auth_basic

Filed under: Security — Tags: , , , — Darryl Clarke @ 10:15 am

In my prior post, Allowing the Facebook Debugger through .htaccess, I showed how you could do just that. But, as time goes on, I spend more and more time with nginx and I need to adapt my rules.

So, today, I decided I should do the exact same thing with nginx. All of the dev sites I work on are generally password protected with a standard auth_basic setup. This is great, keeps the robots out and prying eyes away. But it’s always an issue when you need to test sharing and other external scrapers.  As it turns out, doing so with nginx is just as simple as it was with Apache.

My initial ‘location’ block was a simple configuration:

location  /  {
  auth_basic            "Restricted";
  auth_basic_user_file  htpasswd;

  if (!-e $request_filename) {
    rewrite ^(.+)$ /index.php last;
  }
}

To allow Facebook debugger through the simple auth_basic was as easy as adding an if check and a secondary ‘location’ rule.

location  /  {
  error_page 418 = @allowed;

 if ($http_user_agent ~* facebookexternalhit) {
         # bypass httpauth.
        return 418;
  }
  auth_basic            "Restricted";
  auth_basic_user_file  htpasswd;

  if (!-e $request_filename) {
    rewrite ^(.+)$ /index.php last;
  }
}

location @allowed {
if (!-e $request_filename) {
              rewrite ^(.+)$ /index.php last;
 }
}

The first thing added was a rule for nginx to understand what I mean when I say ‘return 418’ – this is the http response code for “I’m a teapot” The if block simply checks if it’s a known facebook agent, and the third block is a custom location that strips out the authentication requirements.

It’s generally fairly simple the concept and can be applied to any other external scrapers that you may need.

Older Posts »