Liza Shulyayeva

Laravel Migration Done

The first commit auto-tweeted from the @gastropoda_ twitter account yesterday was actually the last commit dedicated to the Laravel port reimplementation:

Yeah, that one. It contained basically some racing fixes and the reimplementation of recurring events (snail idle actions, store restocking, nightly snail energy depletion), the corner store, and user inventory.

Laravel - you have arrivedI started the port on July 10, so accounting for 2 days away in Amsterdam where no snail work got done, overall it took 16 days to migrate everything to Laravel (between about 1-4 hours of work per day).

From now on any further work on Gastropoda will move past the functionality of the vanilla PHP version. And I’ve already started! I’ve implemented rudimentary race logs and action templates (right now the only action template is ‘move’, but there will be lots of other actions a snail can perform during a race).

The Gastropoda board on Trello has been helping me keep track of my progress and it’s getting fuller by the day. If you haven’t checked out Trello yet, you should. Here is a non-referral link or, if you’re feeling nice, a referral link.

Up next I’ll be working on whatever the crap I want. More specifically, I might start with adding a couple more action templates for the races. Then I might switch to something totally different and look into generating better shell patterns and colors on the snails. The snails are actually displayed on HTML5 canvas (since they crawl), so all of that is done in JS/HTML5. I bet I can get some really cool and more natural looking visual effects in place of the placeholder patterns I have now. I also still need to capture a static snail image and store it in the DB for cases where a single snail avatar needs to be displayed as a simple image only.

A Battle With Racing

I’m still on the Laravel migration. It’s going pretty well, except for last night. Last night I was porting racing.

It was awful.

I didn’t get to bed until something like 4am and my brain seems to have blocked out a sizeable chunk of what actually happened from memory, but during the course of the afternoon I went through problem after problem. Each time I solved one thing some other functionality broke and by the end I didn’t know wtf was going on.

The problem started with my fundamental misunderstanding of the Eloquent update(). After reading the Laravel documentation I got the impression that update’s entire purpose is updating specific attributes of a model. You pass an array of attributes, Eloquent updates the table.

Apparently that’s not how it works. When you run Model::update($propertiesToUpdate) it doesn’t just update those properties - it looks for any dirtying of the model and apparently tries to save everything that may have changed. Unfortunately in my current setup the model also represents a complete instance of a snail that has additional properties set after it is loaded. So as an example…snail->currentEnergy is not stored in the database, but calculated when the model is loaded based on the snail’s current protein, fat, and carb counts. When I tried making neccessary changes to the racing snail post-race to record depletion of these macros I was getting an error about a column not existing. But it wasn’t supposed to exist at all.

I went to Laravel IRC for help. People were very helpful and responsive. It took a while of going in circles. I was getting a little frustrated with the whole situation because it cannot be that difficult to save a fricking change to some specific fricking fields and only those fields in the db through Eloquent. I would have thought it would be at least as simple a process as manually building a query and running mysqli was. In the end we decided that using the query builder was my best bet. So now instead of using $snail->update($propertiesToUpdate) I use DB::table('snails')->where('snailID', $this->snailID)->update($propertiesToUpdate)

This works. I do eventually want to go back and change my entire setup to avoid dirtying the model. For now, though, I just want to get this thing back to the state it was in the vanilla PHP version.

Anyway, then there were some other issues with Eloquent relationships, but those were caused by sleepiness more so than any actual bug or source of confusion. Here’s an example of how my Laravel relationships are set up for races and their entries at the moment:

  • Race model hasMany entries
  • RaceEntry model hasOne snail

This makes it easy to immediately load the entries associated with each race as well as the snails associated with each entry for use during the race. In a similar way, I can easily get a snail’s owner via a belongsTo relationship. From there it’s just a matter of Eager loading the model associated with the relationship when loading the parent model itself. Or lazy loading it via $race->load('entries') for example.

Anyway, the races are running now. They’re not done, but they’re now up to the same state as the vanilla PHP version. Up next I want to do a bit of cleanup and then start reimplementing items. This port is taking longer than I thought, but I can see the benefits of using Laravel. I’m finding myself cutting out huge chunks of code I had in the vanilla version that, with the help of Laravel and Eloquent, are just no longer needed. Eloquent makes data retrieval and validation much easier and faster to implement.

Up next I want to do some cleanup and then start on the item reimplementation. Wish me luck.

Setting Up an AWS EC2 Instance for Gastropoda

It all started with a cool little PHP script that someone posted on /r/gamedev this morning to publish completed Trello tasks easily to a change log of sorts.

I had just re-started using Trello, creating a public Gastropoda board to keep track of my progress (starting with the migration to Laravel).

So I was excited to try out the script and have some sort of automated progress log. What I conveniently forgot was that my Octopress host - AWS S3 - only hosts static sites. PHP is out of the question. And I figured…I could probably generate the actual page and publish it as a static site just like I do with Octopress, but I’m going to need to host Gastropoda somewhere anyway and I wanted the whole Trello-link thing to be real time. I may as well set up the whole shebang now.

Well, I didn’t end up setting up the whole shebang because I didn’t want to pay for RDS while only hosting one PHP file. I did, however, set up an EC2 instance through Elastic Beanstalk and point a subdomain to it. You can now find a simple progress log (taken from my Trello “Done” column) at gastropoda.liza.io

My worry with this thing is how much it’ll cost. S3 instance is ridiculously cheap, but it seems as soon as you migrate to the world of ec2 and databases the costs go up substantially. If you just want to host a static site, S3 is way cheaper than a regular shared host. However EC2 with RDS can be considerably more expensive than a shared host (although the service is of course better). We’ll see what the first bill is for this one simple low-traffic PHP page. The setup looks like this:

  • Set up through Elastic Beanstalk
  • One application with so far one environment
  • t2.micro (so with VPC)
  • No RDS (yet, though I’ll obviously need it when it comes time to host the actual simulation)
  • Continuing to use Route 53 for domain management
  • Hosting actual site files on S3 (of course as it’s auto-uploaded to the designated bucket during deployment)

There are some bugs with the script (like labels having to be applied in a certain order if there are multiples on one task), which I might take the time to fix myself later. For now though it works.

In the meantime, I’m now porting the racing implementation from vanilla PHP to Laravel. I’d say I’m about 75% of the way there. Slowly but surely.

Summer Holidays and Amsterdam

July is when Sweden goes on holidays. Businesses are closed for the summer (quite a few of them, anyway), people take time off work, the weather doesn’t suck. Usually people tend to go away to other countries, which to me is ludicrous because after all that snow and cold these months are finally when Sweden gets warm and sunny. I guess I’m kind of fibbing - I get it. You want to get out and see other places during your vacation.

So we went to Amsterdam for two days this month. It was great, but too short. On the last day we almost “forgot” that we had a plane to catch that night and considered maybe just “accidentally missing it”. It’d be an adventure, that’s for sure. But as the day went on I actually got excited about coming back home to Sweden. Amsterdam is great to visit, but there’s nothing there that makes me feel like I’d rather be there than in Stockholm. One big thing I did take away from it though was the desire to bike far more regularly instead of catching the train. I think since we got back we haven’t gotten on a train to Södermalm once, opting to cycle instead.

We didn’t take our laptops and put heavy restrictions on internet use. Mostly we just wanted to disconnect and relax. It worked, although I kept thinking about snails, taking notes, etc.

When we got to the Amsterdam airport we saw the TVs in an electronics store talking about a flight and showing disturbing footage. Through a store clerk who translated for us we learned that flight MH17 had just been shot down by terrorists in Ukraine after leaving that same airport that same evening. We were in shock for a while, with no idea of what was happening. I finally got to wifi to be able to read some English and Russian-language news. I hope that the terrorists - and anyone sponsoring them - are brought to justice.

{{ ‘amsterdam’ image_list }}

Custom Validators in Laravel

I’m still going with the Laravel port. One thing I’ve found really interesting is custom validators. In Laravel models you can set field rules, such as…

public static $rules = array(
    'name'                => 'required|alpha_spaces|unique:jars',
    'ownerID'             => 'integer',
    'isBreedingJar'       => 'boolean',
    'capacity'            => 'integer|max:15',
    'comment'             => 'between:0,32|alpha_spaces',
);

In the vanilla PHP version I had to perform a check in updateSnail() - if the modified field was currentJarID, I had to find the number of snails inside a jar with that same ID and compare the jar’s capacity to the count of those snails. If capacity <= current snail count, the snail was not allowed to be placed into that jar.

With Laravel, I hacked together the same thing in the form of a new validation rule. This way I don’t have to explicitly perform this check whenever I move a snail myself - I just set the rule name in the rules array for the Snail model and it does the rest whenever it sees the snail’s currentJarID being modified.

I plan on changing this when I can see better ways of doing this. For now, setting it up like this seems to work:

1) Create app/validators.php

2) Extend Validator with your own rule

Validator::extend('limited_jar_space', function($attribute, $value, $parameters)
{
    $jarID = Input::get('currentJarID');

    $jarController = new JarController();
    $jar = $jarController->getJarDetails($jarID, 'capacity');
    
    $snailController = new SnailController();
    $snailCount = count($snailController->findSnailsInJar($jarID));

    if ($jar->capacity <= $snailCount) {
        return false;
    }
    return true;
});

3) Create a custom error message in lang/x/validation.php

"limited_jar_space"        => "The jar is full!",

4) Add app/validators.php to start/global.php

require app_path().'/validators.php';

5) So now I can use the rule "limited_jar_space" for currentJarID in the snail model to make sure the jar a user is trying to move their snail to has enough space left.

public static $rules = array(
    'name'                   => 'alpha_spaces|unique:snails',
    'ownerID'                => 'integer',
    'currentJarID'           => 'integer|limited_jar_space',
);

Experimenting With Laravel

I’m sitting here working on Gastropoda on a train to Norrköping. A couple of days ago I started experimenting with Laravel after the friendly folks on /r/php provided some invaluable input to my vanilla PHP vs framework question.

Laravel has been easy to set up. All in all getting Vagrant up and running and Laravel installed took maybe up to an hour. I’ve been trying to think of a good way to port my existing setup to an MVC-based framework. I’m basically going to paste a copy of what I posted on the laravel.io forum to explain the work ahead.

Basically, in the vanilla PHP version I have pages, main object classes, and manager object classes. Two examples:

  • snail.php
  • snail.class.php
  • snailmanager.class.php

  • jar.php
  • jar.class.php
  • jarmanager.class.php

I should note that snail data is not limited to being displayed on snail.php - snails are also instantiated and displayed on jar.php, for example.

Currently, in the no-framework version, I’ve been structuring every main object class (ie snail.class.php) in a way that ensures the class only contains methods that pertain to a specific instance of an object. So you’d never see a method like findSnailsByJarID() in snail.class.php because it would often return more than one snail. Instead, those sorts of things - methods that require pulling out multiple snails based on given requirements or trigger any sort of events on a set of snails/jars/whatever would go into snailmanager.class.php, jarmanager.class.php, etc.

An example of stuff in snail.class.php would be: updateSnail, loadSnailInfo, generateNewbornSnail, generateGeneString, depleteEnergy, etc.

An example of stuff in snailmanager.class.php would be: findSnailsByJarID, nightlyEnergyDepletion (which would call depleteEnergy for each relevant snail), etc.

The question

How should I split this up in an MVC pattern as pertaining to Laravel? Where should the logic pertaining to each instance of an object go? Some people have suggested putting everything into the controller, others in the model. Most seem to suggest not separating methods that affect one instance of an object from methods that perform actions on multiple objects (so there would be no separation such as the one I had with snail.class.php and snailmanager.class.php).

Anyway, while I do more research I’ve kind of been hacking it together with the expectation of later changing it as I learn. So the way I have it set up now for a jar is:

  • /models/Jar.php
  • /controllers/JarController.php
  • /views/stable/jar.php

The data I need to pass to the view is retrieved via a View Composer, which communicates with JarController, SnailController, and UserController to get information about a jar’s owner and all the snails within it. In a sense my controllers in Laravel kind of take on the role of the managers in the vanilla PHP version, except when data needs to change the view would never talk directly to the model but go through a relevant controller. The view also no longer decides anything (eg, whether to show the Edit form for a jar if the user viewing a jar is its owner). This is all done before, in the view composer, and from there the edit form is displayed if it is available.

Anyway, I am going to have to change how this works a likely stupid amount of time as I go.

The Beginnings of a Currency

When I moved back to the PHP version of Gastropoda I implemented snail death, so that snails actually die when their energy reaches 0. This resulted in all of my snails dying because they were both far below 0 (the cron job that depleted their energy daily continued to run while I was on a different branch).

So there’s currency now. Each user gets 500SEK when they start their stable. I’ve already used mine up on lettuce leaves from the other new thing - the Corner Store:

Gastropoda corner store

(Eh, obviously I need to still build grouping of listings of the same item/price combinations).

When I buy an item it ends up in my closet, which is accessible from my Stable page.

Gastropoda closet

From there you can choose what to do with the item (so far you can only place it in a jar). It ends up here:

Lettuce in jar

At which point snails can eat it to absorb the vitamins and nutrients from that item.

Now…lettuce leaves don’t contain much other than water, so unless I want to keep buying craploads of lettuce leaves on a daily basis to stick them in for the snails they are still going to die. Not to mention, I can’t stock up on lettuce leaves in advance because food is soon going to rot just as in real life if left too long. Snails can handle rotten food, but only to an extent.

Oh also the store restocks itself based on the rarity of each item template. Eh…very far from done, but here:

    function RestockStore() {
        $itemmanager = new ItemManager();
        // Loop through all item templates
        $qry = 'Select templateID, basePrice, rarity from item_templates';
        $result = DB::$mysqli->query($qry);
        if (!$result) {
            return false;
        }
        // Get each template as an array (to make into object later..this is separate from the Item object)
        while ($itemTemplate = $result->fetch_assoc()) {
            // Generate a random integer from 0 to 100
            $randomInteger = Utility::RandomInteger(0,100);
            // If the random integer is higher than the item's rarity (from 0-100)...
            if ($randomInteger > $itemTemplate['rarity']) {
                // Create one instance of that item 
                $item = $itemmanager->CreateNewItem($itemTemplate['templateID']);
                // Create a store listing
                $storeListing = new StoreListing();
                $storeListing->itemID = $item->itemID;
                $storeListing->sellerID = 0;
                $storeListing->price = $itemTemplate['basePrice'];
                $storeListing->SaveListing();
            }
        }
        return true;        
    }

This currently runs every 5 minutes, but I will make this less frequent when I’ve made it restock multiple instances of the same item.

Up next…

Next I will do a few days of bug fixing and cleaning everything up, then I’ll add a more substantial consumable (so that I can feed the snails only once a day for example), and then I need to start taking a look at snail growth. Currently babies are born at their adult size, but in reality they need to grow over the course of at least a few days.

To the Node and Back

I spent a couple of weeks porting Gastropoda from PHP to Node.js after caving in to peer pressure and hearing “PHP sucks” from every side imaginable.

And yes, I know - Why would you go from PHP to JS? Screw JS! Boo!

I like JavaScript. All of my hobby project save Time to Die have been made in JavaScript. And even JS doesn’t seem to be quite as hated as PHP (not anymore, anyway).

So I finished most of the port (from PHP and MySQL to Node and MongoDB). It was ok. I mean, it was pretty quick and aside from a few mild detours it went pretty smoothly.

But as I was maybe 3/4 of the way to having an exact replica of the functionality of the PHP version I reflected and realized that I just wasn’t having very much fun. Gastropoda is a hobby project - who the crap cares if I use the “worst language in the world” to build it? I’m doing my best to build it the right way (as much as there is a right way with PHP), but it will never be perfect. The Node version would have never been perfect, either. I’m not sure why I didn’t enjoy it as much. Maybe it had something to do with reimplementing all the features that I had already done just a few weeks ago. And refactoring the JS version as I learned better Node practices, implementing promises, etc. The weird thing is I don’t even mind revising the PHP version as I learn better ways of doing things. It was only boring when I was using Node, and I can’t really explain why.

It’s really just as I got Bluebird working for promises that I decided that the process of developing the same exact simulation with Node just wasn’t as fun for me as it had been this whole time in PHP. You could argue that maybe I’ve gotten too comfortable with PHP and Node just had more of a hump that I had to get over, that maybe I got lazy and went back to the “easier” option, but I don’t know if that’s the case. After all, the very first draft of Gastropoda, when I built it for One Game a Month last year, was built using Node and Mongo. All of my other projects were JS. That was before I’d written a single PHP project. Gastropoda is the first PHP hobby project I’ve ever done and while I don’t hate using it as much as many people seem to I’m certainly not comfortable with it in any sense of the word. There is always something new to learn…some weird quirk or best practice that has me rewriting tons of work. It’s just that for some reason with PHP I don’t really mind doing all that.

Anyway, instead of spending any more time on the port I switched back to the PHP branch and implemented snail death. I’m not against trying out ports to other languages, but I have a feeling in the end I’ll keep coming back to PHP for this particular project. In the future I’d love to dig into Go, and maybe play around with Rust. Just…probably not for this. Ever since I first thought of the idea of Gastropoda (before it ever had that name, or any name), I had imagined it in PHP - just like the games I played when we got our first computer and a dial-up connection after moving to the US. And maybe for a hobby project that nostalgia is reason enough to stick with “a fractal of bad design”.

A Move and a Quick Gastropoda Update

Moving

Buying an apartment in Sweden is refreshingly hassle-free but by no means stress-free. You find one you like online, you go to a viewing, you bid…and bid…and bid until you can’t bid no mo’. Alternatively, you find one you like online and just bid.

So we just moved in today. We only took some essentials with us, so here we are in a huge empty apartment. It’s nice - our goal is to not clutter it with crap. We’ll only buy the things that we actually need. For now that’s a bed. Maybe some chairs.

Moving out of the old place is going to be the most stressful part. There is all the packing and then the moving and then the cleaning. I wish I could just never go back to the old place again, but it’s not that easy. I’ll just focus on the fact that we have a porch now.

It still hasn’t really sunk in that I actually bought an apartment with someone (or at all). People have suggested that I buy back in Australia, but it never seemed like a good idea. It would just tie me down to a country that, while nice, I knew I didn’t want to stay in. I guess that went for more than just the place, too. On the other hand, Sweden feels much more like “home”, so the question of committment never crossed my mind.

Gastropoda

I have been battling it out with the nutrition system. Energy wasn’t being converted properly between calories/joules/carbs/fat/protein, resulting in some very annoying and difficult to diagnose behaviour. Snails with 200% energy and whatnot, snails whose energies didn’t deplete as much as they should in the daily event, etc.

That’s sorted out now. It’s now time to go back and review/clean up everything and make sure it’s all commented before working on any further features. I swear I’m going to forget what the crap I did unless I add some notes.

The Day of the Lettuce Leaf

Today I put the first item (a consumable lettuce leaf) into Gastropoda.

The items

The lettuce leaf was to be the first food item in Gastropoda. However, before I could make the leaf itself I had to make the food system, which I hadn’t yet planned out in great detail. Four new tables were involved:

  • items
  • item_templates
  • item_types
  • item_nutrition

item_templates is the main one, where every possible item is going to be stored. items is the one that actually records each instance of each item currently owned by a user in the world. item_types defines what kind of item a certain entry in the template is (eg “consumable”, “decorative”, “substrate”, etc). item_nutrition is exclusively used for items of the consumable type (which is why I separated it out into a separate table; it’s not going to be relevant for every item template).

So I created a template for the Lettuce Leaf in item_templates:

Lettuce Leaf item template

Then, I looked up the nutritional information of a lettuce leaf and added an entry for it in the item_nutrition table:

Lettuce Leaf nutrition

The energy here is in Joules and the rest of the measurements are in milligrams.

Next, I created an actual lettuce leaf item in the items table, listing my user as the owner:

Lettuce Leaf item

I put it into jar #2, where all of my snails are currently housed.

There is now also an Item class.

The snail stuff

I had to add a few new attributes to the snails:

  • carbohydratesCurrent (in milligrams)
  • carbohydratesIdealPercentage (of total energy)
  • fatCurrent (in mg)
  • fatIdealPercentage (of total energy)
  • proteinCurrent (in mg)
  • proteinIdealPercentage (of total energy)
  • vitCCurrent (mg)
  • vitCIdealPercentage (of current body weight; overall growth)
  • vitDCurrent (mg)
  • vitDIdealPercentage (of current body weight; calcium absorption)
  • vitB6Current (mg)
  • vitB6IdealPercentage (of current body weight; brain development, metabolism)
  • vitB12Current (mg)
  • vitB12IdealPercentage (of current body weight; blood and energy)
  • calciumCurrent (mg)
  • calciumIdealPercentage (body weight; shell growth/shell strength)
  • ironCurrent (mg)
  • ironIdealPercentage (body weight; none. Requirement is 0; toxic unless in tiny doses)
  • magnesiumCurrent (mg)
  • magnesiumIdealPercentage (body weight; calcium absorption)

I read whatever snail nutrition research papers I could find, but there wasn’t that much about their vitamin requirements so at the moment these are largely based on human RDIs modified for snail weights (with some randomization).

This does mean that I’ll have to update the way I do energy depletion. I have to find out how quickly vitamins are metabolized, and decrease energy by burning down carbs, fat, and protein at appropriate rates.

Item consumed

The other stuff

As I mentioned previously, you can’t really feed a snail individually unless it’s in its own jar (or you’re injecting it, which is a bit extreme). So you place food inside a jar and then any snail in that jar has a chance of taking a bite. Right now it’s random, but there are already some attributes in place which, when hooked up, will increase or decrease the likelihood that the snail will try to eat food - and also that it’ll actually get it when competing with the other snails.

The issue right now is that even though you can see the snails crawling around live on the canvas, and the food when it’s there, you do not see snail actions in real time (yet). So you won’t actually see the snail crawl up to the lettuce to eat it - it’ll all be done in the background and you’ll just see a new event on your snail when it’s consumed something. It’s kind of unsatisfying, since if you’re seeing them crawling around you feel like you should be able to see them also performing various actions. I’ll have to work on this down the line.

Lettuce Leaf in a jar (Obviously it’s not being properly positioned yet…)

So basically a snail takes a bite of the lettuce leaf and its nutritional stats are updated based on the item it’s consumed. These will then be used to calculate deficiencies and other effects that the snail’s diet has on its health and performance.

When the lettuce leaf has no bites left, it’s simply deleted.

So that’s the gist of it!