Wednesday, March 30, 2016

Dependency Cost

Over the weekend I was alerted to a bug in the Amphibian.com web application by a reader. For him, the "previous" and "next" navigation links would not work. Clicking on them put the page into endless "Grabbing Frogs" mode and never displayed another comic.

Fortunately, the issue was not difficult to correct. Since Amphibian.com is (almost) a single-page-application, each time a new comic replaces the currently visible one I have to generate a new Pinterest button for the correct comic. Yeah, you're probably wondering, "why a Pinterest button?" I don't know. It seemed like a good idea at the time...

I'm generating the new button by calling a slightly undocumented function in the Pinterest code. I don't think they intended for it to be used on pages quite like mine. The problem arises when the function is unavailable. Maybe Pinterest is blocked. Maybe Pinterest is down. Maybe certain browsers actually download an older version of the code where that function doesn't exist. Doesn't matter why - the end result is the same. Without that function, an error occurs in my JavaScript and the new comic is never displayed. I fixed this issue and then immediately found another similar issue with my call to Emoji One's JavaScript. Fixed that too.

This got me thinking about what I'll call Dependency Cost. I didn't really think about the cost of my code being dependent on Pinterest and Emoji One behaving in a certain way. I don't control either of them, and they could change or vanish at any time - resulting in my comic readers getting shut out of my site. When you think about it, this is really an unacceptable situation. But how many situations like this are you in right now with your code? I think we're all in too many. Take the setup Amphibian.com for example - it's built on Node using Express and over a dozen other modules all downloaded from npm at first install. What if I had to recreate the site and npm was down. Do I think npm will be around forever? Nothing lasts forever.

Just something to think about when you're building your next application. Or you can think about today's comic. That's much more fun.

Amphibian.com comic for 30 March 2016

Monday, March 28, 2016

Know Your vi

I through in a little jab at vi in the third frame of today's comic. The truth is, I actually use vi almost every day at work. Remote displays are such a hassle. It got me thinking about this nice vi cheat sheet I was given on my first day of work (almost 15 years ago).

It hung on the wall of my cubicle all these years. I found a copy of it on the Internet and wanted to share it with you!

There are a couple of cleaned-up versions of this same style sheet floating around. I like it because it spells out "vi" with the commands. Just in case you forget what the commands are for. Mine is a copy of a copy of a copy and has some hand-written notes on it too, just like the one I found above. Gives it character.

Right after you read today's comic, go log on to a Linux terminal and edit something with vi!

Amphibian.com comic for 28 March 2016

Friday, March 25, 2016

Easter Eggs

While today's comic is about Easter eggs (maybe?) the comic itself does not contain any. And by that I mean it doesn't have any fun undocumented features. It might have real eggs. Who knows?

The term "Easter Egg" for an undocumented message, joke, or feature in a software product comes from the concept of the Easter Egg Hunt where children search for brightly colored eggs containing prizes. Similarly, if you find the hidden commands or whatever to unlock the Easter Egg in a software application, you get the prize. The hiding of Easter Eggs inside software dates back an Atari game from the late 1979 when the uncredited developer hid his name inside the game. It was supposedly given the name "Easter Egg" by Atari personnel after its discovery.

If I'd had more time, I would have put one in the comic today. But, alas, my life is a bit of a disaster lately and I'm not even sure what day it is most of the time. I just got back from my second business trip in 3 weeks and I have a list of over 10,000 things to do before the end of the month. Okay, I'm exaggerating a little. The list is really only 9,875 things.

The closest thing that Amphibian.com has to an Easter Egg is the teapot response. If you go to https://amphibian.com/teapot you will get a message indicating that your tea is ready. But if you look at the HTTP response code, it's actually in the error range - specifically a 418. That's the response to indicate "I'm a teapot" in the Hyper Text Coffee Pot Protocol. I may expand on this someday.



It's not quite an Easter Egg, but there's also a way on the site to force an error condition for test purposes. It lets you see a 2-frame comic which is my lame attempt to tell you that there's been a server-side failure. You will hopefully never see it except by going to https://amphibian.com/broken.

So enjoy today's comic about eggs and Easter but not really Easter but definitely eggs. Yeah.

Amphibian.com comic for 25 March 2016

Wednesday, March 23, 2016

Perspective Transformations in Inkscape

I still haven't gotten a chance to go back to work on one of my games. I'm on another trip for work this week. But I did learn something new related to today's comic.

While it doesn't have any special features, it does have a piece of paper on the ground with writing on it. The writing is skewed to show perspective. This is something that I hadn't been able to figure out before today - how to make a perspective transformation in Inkscape.

Here's how to do it. First, get whatever object you want to transform. It can be text or a picture of something, but you have to turn it into a path first. You can do that by using the Path - Object to Path menu option.

In this example, I'll transform one of my frog images. It is made up of lots of paths, all in a group. That's ok. To perform the skew, draw another path around the object in the shape that you want it to look like in the end. Start in the lower left corner and draw the line clockwise.


After you have the shape outlined by the new path, select the shape to be transformed first and the path second (Shift+click). Then use the menu option Extensions - Modify Path - Perspective. It takes a few seconds, but should look like this after it runs.
You can delete the outline path if you want.
That's how I made the text on the "landing page" look like it does. I'm always happy when I learn something new. I'm also happy when you read my frog comics.

Amphibian.com comic for 23 March 2016

Monday, March 21, 2016

Amphibian.com's got Web Sockets

Today's comic might look like a simple joke about planting light bulbs, but it is really so much more. Well, actually it's only a little bit more. But still more.

The lamp post in the third frame can be turned on and off by clicking on it. But it doesn't just go on and off for you the clicker; it goes on and off for everyone looking at the comic. Try it. Go to Amphibian.com and look at the lamp. Call a friend on the other side of the world and have them also go to Amphibian.com and look at the lamp. Click on the lamp. You'll both see it toggle state at the same time.

I finally got around to integrating Web Sockets via Socket.io into the site. The state of the lamp is stored on the server and clicks emit "lamp-toggle" events from the clients. When a toggle event is received on the server, the state of the lamp switches and the new state (on or off) is broadcast out to all the clients. The clients show or hide the "glow" effect accordingly.

Server Code:

var lampOn = true;

io.on("connection", function (socket) {

    socket.on("lamp-toggle", function(data) {

        if (lampOn) {
            io.emit("lamp-off");
        } else {
            io.emit("lamp-on");
        }

        lampOn = !lampOn;

    });

});

Client Code:

var socket = io("http://amphibian.com");

socket.on("lamp-off", function(d) { 
    $("#glow").hide();
});

socket.on("lamp-on", function(d) {
    $("#glow").show();
});

$("#lamp").click(function() {
    socket.emit("lamp-toggle");
});

On the server side, I had a little trouble with the fact that I have Node HTTP servers for both secure and insecure web traffic in the application. I wanted the same Socket.io instance to service both. Fortunately, it is easy to attach a Socket.io server to multiple HTTP servers. In the code snippet below, I call attach on an existing Socket.io instance to bind it to a second HTTP server (line 17).

var app = express();

var server = http.createServer(app).listen(3000, function() {
    console.log('listening on port %d', server.address().port);
});

// create a Socket.io server attached to the HTTP server just created
var io = require('socket.io')(server);

if (ssl) {

    var secureServer = https.createServer(sslOptions, app).listen(4443, function() {
        console.log('listening securely on port %d', secureServer.address().port);
    });

    // attach the Socket.io server to the secure HTTP server as well
    io.attach(secureServer);

}

Back in the client, I just had to be smart about which URL to connect to. I never got Web Sockets to work correctly with Nginx, so I'm just bypassing it when I make the connections back from the client. Nginx listens on ports 80 and 443 and proxies HTTP traffic to the Node application which actually listens on ports 3000 and 4443. When I set up Socket.io in the client, I use these ports directly. Browsers still allow Web Socket connections to different ports on the same server without raising cross-site scripting concerns. But you can't mix insecure HTTP and secure Web Sockets (or vice versa). Look at this update to the client code from above, where I examine the browser's location to determine what URL I should use for connecting:

var urlParts = window.location.href.split("/");
var cUrl = urlParts[0] + "//" + urlParts[2];
if (!window.location.port) {
    if (urlParts[0] !== "https:") {
        cUrl += ':3000';
    } else {
        cUrl += ':4443';
    }
}

var socket = io(cUrl);

// ... rest of client code from above ...

So go play around with that lamp! And feel free to read more comics while you're there.

Amphibian.com comic for 21 March 2016

Friday, March 18, 2016

Pseudocode

You may have heard stories of brilliant software engineers jotting down code on bar napkins when they have a sudden epiphany while drinking with their friends. Maybe you've done this sort of thing yourself. Maybe, like the frogs in today's comic, you've written down code in a stranger place.

I've never written code with letter-shaped pasta, but I have written out lots of algorithms on paper beside my keyboard. It's never in perfect form for compilation, but is usually just pseudocode. I am not a genius when it comes to algorithms; I can rarely go straight from my brain to they keyboard and have the code work on the first (or fifty-first) try. When I was working on the match-3 game back in January, it took lots of scratch paper pseudocode to get things working correctly.

For whatever reason, writing out the algorithm in pencil and then working through it on paper really works for me. I usually write a list of the variables off to the side, along with their current values as I work through the steps. I erase and re-write the value of each variable as it changes. This is a skill I was taught in college, using a whiteboard instead of paper, but it works just as well.

If you haven't done something similar yourself, give it a try next time you're stumped on an algorithm problem. Or just take a break from programming and read some of my comics!

Amphibian.com comic for 18 March 2016

Wednesday, March 16, 2016

I Don't Like Gingerbread

I have noticed that it's been over 2 weeks since I worked on my platformer. I haven't abandoned it, but I have taken a break from it to work on other things. A trip to Texas where I got sick and this stupid Daylight Savings Time thing messing up my sleep schedule haven't helped.

This basically means that I don't have any code or Phaser insights to share at the moment. I honestly don't have much of anything to share, other than comics and the fact that I don't like gingerbread.

But today's comic has a gingerbread house! Well, technically it's a gingerbread grocery store, but the fact remains that I don't like gingerbread. When we make "gingerbread" houses around here at Christmastime, we use graham crackers which I consider to be more edible.

Why am I writing about this? I have no idea.

Amphibian.com comic for 16 March 2016