Friday, November 28, 2014

Get Hooked


Have you heard about microservices yet? There's been no small amount of discussion about their benefits recently. Even Martin Fowler says that the microservices pattern of enterprise system architecture has seen many positive results among his colleagues in the past few years (read his whole article here).

If you didn't click on the link, I'll summarize it for you here: the microservice architectural style is an approach to developing a single application as a suite of small services that communicate through very lightweight mechanisms such as HTTP APIs. What does that mean? It means you break your big monolithic system down into a bunch of small parts that each do a single job and are deployed independently.

I decided to play around with a popular microservice framework based on Node.js, hook.io. It is a very interesting premise. You set up a public Gist at GitHub, which the hook.io framework executes when called. For my experiment, I created a hook which can give me the date for Easter for any given year.

The first step is to create a public Gist for your hook. You can find mine here, but it's basically just the following code:

module['exports'] = function easter(hook) {
 
  var year = hook.params.year;
  hook.debug("i am going to calculate the date of Easter for " + year);
  
  // using the "Meeus/Jones/Butcher" algorithm
  var a = year % 19;
  var b = Math.floor(year/100);
  var c = year % 100;
  var d = Math.floor(b/4);
  var e = b % 4;
  var f = Math.floor((b + 8) / 25);
  var g = Math.floor((b - f + 1) / 3);
  var h = ((19*a) + b - d - g + 15) % 30;
  var i = Math.floor (c/4);
  var k = c % 4;
  var L = (32 + (2*e) + (2*i) - h - k) % 7;
  var m = Math.floor((a + (11*h) + (22*L)) / 451);
  var month = Math.floor((h + L - (7*m) + 114) / 31);
  var day = ((h + L - (7*m) + 114) % 31) + 1;
  
  hook.debug("month is " + month);
  hook.debug("day is " + day);
  var monthNames = [ "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December" ];
    
  hook.res.end("Easter is " + monthNames[month-1] + " " + day + " in " + year + "\n");
 
};
 
module['exports'].schema = {
  "year": {
    "type": "number"
  }
};

On the first line, you define your module's exported function. Since every hook is passed a Hook object as its first argument, I define that as the lone parameter.

What will that Hook object look like? According to the hook.io documentation, there are a number of fields available on it. For my simple purposes, the most interesting will be Hook.debug and Hook.params. The debug field is a function that you can call to dump information out to a debug console. It is actually quite nice because all your debug ends up as an array of objects with time, data, and ip fields. But I'm getting ahead of myself...

On line 3, I use the year param to get the year that will be passed in when my hook is called (more on how that happens a little later). On lines 4, 22, and 23 I output some debug, but the rest of the function is just the algorithm for calculating Easter's date. It's quite an interesting problem, but in the end I come up with a friendly result string which I return to the caller on line 27 by passing it to the Hook.end function.

Now that I've made a Gist, I can make a new Hook. You can too! Just go to http://hook.io/new and give your hook a name and the URL of your Gist. I named my hook "easter". For the Hook Theme, I just chose "simple" but that doesn't matter a whole lot in my example. That was it - my hook was easy to create.

Now what? How do you actually run the thing? Your hooks can be accessed by URL at
http://hook.io/<your userid>/<hook name>
and the parameters can be passed along as parts of the query string. For example, if I want to run my Easter date hook and pass in a year of 1918, I would just go to the following URL:
http://hook.io/cwleonard/easter?year=1918
Note how the parameter is named year, which matches the field name I was looking for on line 3.

There's one minor gotcha here, and that is how the framework processes requests based on the HTTP Accept header. If I go to my hook's URL from my web browser, it won't actually run. Instead, it gives me a nice human-readable form to fill out and push a "run" button. This is because browsers generally set "Accept" to "text/html" and hook.io is trying to help me out by giving me a friendly form. To get around this, just put "&run=true" on the end of the URL. Don't worry, if you call the URL by other means (from JavaScript, curl, etc.) the "Accept" header won't be set to "text/html" (unless you want it to be) and it will run automatically. See the documentation for more details.

Now that I've covered all those details, try going to this URL:
http://hook.io/cwleonard/easter?year=1918&run=true
You should see a successful result and finally learn that Easter was on March 31st in 1918! Scroll down to the bottom of the results page and you can see the debug output as well.

A cool feature here is that if I find a bug in my code or just want to change my algorithm, all I have to do is edit the Gist. I don't have to do anything on the hook.io site, it just picks up the change next time I run.

One final thing I should explain is how hook.io is able to make that nice HTML form for you to enter the year if you forgot to add "&run=true" on the end. Note lines 31-35 of the Gist. They specify a schema for the hook, which allows forms to be automatically generated. My schema is extremely simple since I only have one field.

There are many interesting ways to use a microservice framework such as this. Imagine if you decomposed your big do-everything application into a bunch of small hooks and then tied them all together from a lightweight container. Even in my simple web comic, I have dozens of routes which could be broken out into microservices - one that just processes the images, one that serves comic data, one that updates the stats, etc.

Using curl to find Easter
You can even use command-line tools such as curl to access these microservices. The possibilities are endless! Use your imagination and come up with some cool new ideas!

I hope this simple example was helpful if you are going to try making some microservices of your own. There are a lot more features to the hook.io framework that you should check and and experiment with. Read the documentation (it's not that long!) to discover all the options. Remember, when you think big, think small.

Amphibian.com comic for 28 November 2014

Wednesday, November 26, 2014

Celebrating Thankfulness

Tomorrow is Thanksgiving Day here in the United States. An official holiday only since 1863, but celebrated for as long as European colonists have inhabited the continent. Traditionally, we trace the Thanksgiving celebration back to the Pilgrims of Plymouth, Massachusetts. Their first celebration of thanksgiving for the harvest (and their survival after a year in New England) took place in 1621, but most likely earlier in the year. The date of the feast was possibly September 29th, according to one historian. That date coincides with Michaelmas, which incidentally is celebrated as Goose Day here in central Pennsylvania.

Well, now that we've covered the background, let's talk about today. How do we celebrate our thankfulness for living in the richest nation on earth in the richest time in history? Many of us celebrate by overeating and falling asleep in the afternoon. We'll need our rest because at midnight we get up and go out to the shopping malls and attempt to kill each other in order to get a slight discount on some junk that we probably don't really need.

Huh? Does that sound like the behavior of people who are truly thankful for what they have?

Our behaviors around this time of the year seem more like celebrations of gluttony and greed than thankfulness. Now, I like turkey and mashed potatoes as much as the next guy (maybe even more so - we cook a turkey here at least 5 or 6 times per year) but mass consumption of the native fowl does little to show how thankful we are.

What does true thankfulness look like? To be honest, I'm not entirely sure. Maybe I'm not thankful enough, or at least don't show it enough. I believe that a person who is really thankful would display qualities such as contentment, joy, and charity. If I asked my family and friends, would they say that I exhibit those traits?

Perhaps what we need is for some modern-day Charles Dickens to write a Thanksgiving Carol and restore the true meaning of the holiday. I'll start working on it. The main characters will all be frogs.

Amphibian.com comic for 26 November 2014

Monday, November 24, 2014

So, about those cookies...

Today I am finally going to talk about cookies. Yes, the tagline of the blogs does read "Software, and frogs, and cookies" but if you've been reading it for a while you've probably noticed a distinct lack of cookies. I actually did talk about cookies in my review of the iPhone game Cookie Dozer back in 2010, but that's been the only time. Four years! And I've never before shared any information about the kind of cookies you can actually eat. Keep reading.

If you've ever read my comic you'll know that it's mostly bad technology puns. That has never been more evident than today, where we find the frogs handing out chocolate chip cookies to track potential customers instead of using the web browser key/value storage mechanism.

You might have not given it much thought before, but just how does Facebook know to put up an ad for some item I was just looking at on Amazon? The answer is because both sites use third-party cookies to track your web activity. It works something like this...
You view a product page on Amazon. Somewhere on that page is an invisible element, often an image, served by a third-party website. Let's say it comes from example.com, for example. Since it gave you some content, it can also set a cookie that only example.com can read. It will generate some unique identifier for your activity and store that in a cookie on your browser. On the server site, they put the cookie id in a database along with information about the page you were on when you got the cookie.
The next day you visit Facebook to share some cute picture of your cat. Facebook also serves you an element from example.com, in this case probably an ad banner. But since example.com can read any other cookies set by example.com, they pull the id out of the cookie you got when you visited Amazon the day before. They quickly look up in their database what page you were on when you got the cookie and then respond with an ad banner for that specific product.
You say to yourself, "Oh, yeah. I wanted to buy that yesterday but I forgot." Then you click on the ad and buy the item. 
Some people get really bent out of shape about this practice. Yes, it's true that if enough sites on the Internet serve you content from example.com, they could build up quite a lot of data about you and your browsing habits. For the most part, they just want to use it to more precisely target advertising at you. There is always the potential, however, that this data could be used for something more nefarious. Fortunately, most modern browsers make it easy enough for you to block third-party cookies (meaning when you go to Amazon.com, you can only get cookies from Amazon.com - not from example.com) and you're fairly safe.

Over the years, the use of cookies in this way has given them a bad name. Really, there's nothing wrong with a site like amphibian.com setting a cookie in your browser when you are actually on amphibian.com. Websites legitimately do this to overcome the stateless nature of web applications.

To make you feel better about cookies, today's comic will set a harmless cookie in your browser. It can only be read by the comic website, and it doesn't contain any information about you. But it does contain a recipe for chocolate chip cookies!

If you want to see it, open up your browser's developer console and type the following command:
$.cookie('frog-tracking-cookie');
Just hit enter, and you should see the cookie recipe. I kept it short, but you should be able to understand it.

If you've gone as far as entering that command, you may also be interested to learn why it works. I use the jquery.cookie plugin for reading and writing cookies from the comic. On some future date, the comic will attempt to read back the cookie it sets today...you'll just have to wait and see what happens!

Amphibian.com comic for 24 November 2014

Friday, November 21, 2014

Assessing Your Assessments

I don't know where you work. Maybe you don't even have a job. But if you have a job, I will bet that you get a performance review at least once per year.

It's that time of year right now where I work. Unfortunately, this type of process is extremely pervasive - almost all companies do it in some form. It is theoretically possible that you like it. Perhaps you always get good reviews and your boss loves you. I usually receive good reviews, but there are some parts of the system that still bother me.

We use a process in which employees are asked to submit written evaluations of the people they worked with closely that year. In addition to that, we submit a self-assessment. Our managers use this information to come up with a summary of our performance.

The first problem is that people just don't like writing reviews of their coworkers. We all drag our feet every year and miss the deadlines to turn in the reviews. Then our managers prod us until we do it.

The other problem with this is that it relies on everyone being very objective. Human beings are very bad at being objective. And for the most part, people don't like to write critical things about the people they have to work with every day. Even when the inputs we provide are confidential, word gets around and people have a way of finding out who said what. This tends to artificially inflate ratings. Maybe the guy in the cubicle next to you has some legitimate issues that need to be addressed, but you don't want him to be in a bad mood after getting his evaluation because you have to sit next to him.

You know, if you don't have anything nice to say, don't say anything at all. People might sometimes tell others verbally that you do a terrible job, but most people don't want to put that in writing with their signature on the bottom.

The last problem (that I'll mention today) is that when you write your self-assessment, you are probably saying really great things about yourself. You are awesome. You should be employee of the year. You are personally responsible for $12.4 million in sales this year. You can leap tall buildings in a single bound. What are the chances that you'll mention anything negative? How is that useful at all to your manager? Best case is that she agrees with you, but worst case is that she has to shatter your superlative self-image with the cold, hard hammer of reality. Nobody likes that.

For the record, I tend to be more critical of myself than most people. One year, let's call it 2007, my self assessment was due on a day that was going very badly. Things were broken, We were way behind schedule. Terribly over budget. Our project could be cancelled any day. How was I to assess myself for that year? I filled out the form with a single sentence: "This year I accomplished nothing of any value." The next day, my manager called and politely asked me to update the document.

If you agree (or not) with any of this, you might also want to read this article: Get Rid of the Performance Review. It's from 2008, but not much has changed.

And have fun writing those reviews!

Amphibian.com comic for 21 November 2014

Wednesday, November 19, 2014

One Pepperoni

Is the word pepperoni singular or plural? Or both?

I admit that I didn't know before I tried to write about a pair of pepperoni pizzas that were appointed to be a frog's marketing team. It makes more sense if you've heard about Amazon's 2-Pizza Teams. Or maybe it makes less sense.

But anyway, it turns out that our American word pepperoni is just how we messed up peperoni, which is the plural of an Italian word for a bell pepper. I don't really know how that happened, since most people think of spicy meat (but from what animal?) when they think of pepperoni - not sweet peppers. So is it plural then? Not really...

The general consensus is that pepperoni is plural only when you're actually saying peperoni and you're speaking Italian. When you're speaking American English about the zesty red circles on your pizza, it is singular. It's pretty much a totally different thing, even though it probably sounds the same. Hey, it's not the first word we've hijacked.

This means that I wrote pepperonis when referring to more than one of them. Even though that looks weird. Lots of words look weird when you write them down I guess. Like vacuum. And bologna. And phlegm.

Amphibian.com comic for 19 November 2014

Monday, November 17, 2014

Cupcake Clicking

It has finally arrived! Today is the first of my comics which includes an interactive component. This was one of my goals when I set out to create a web comic that was really part of the web almost 9 months ago. It's been a long time coming, but I wasn't going to make comics that you click just for the sake of clicking - it had to be part of the joke.

If you haven't seen it yet, go look at it now and come back: Baited Breadth, Amphibian.com for 17 November 2014.

The more times you click on the "click bait" cupcake, the more success the frog can report to his vice president in the last cell. And the more clicks he captures, the more he is rewarded. The highest reward comes at 150 clicks, so your finger might get a little tired earning the frog that honor.

Obviously, there's a JavaScript component here. It's not the most complicated thing in the world, but it did have to work with the general framework on the comic. It's not actually the first JavaScript component either, the 3D comic last week had JavaScript which enabled turning on and off the stereoscopic version of the final cell.

The basic premise is this: when you load the comic page as a whole, which means you type "amphibian.com" directly into the browser or follow a link, any special JavaScript required by that comic is downloaded with all the rest of the JavaScript. But if you navigate around using the "Previous" and "Next" comic links, the whole page doesn't reload. In those cases, just the HTML of the comic cells is sent to the browser via AJAX. Any custom JavaScript is loaded dynamically at that time. If you go back and forth, it means that custom JavaScript can be loaded multiple times on what is essentially a single page. I had to be mindful of that fact.

Here is a stripped-down version of the cupcake clicker code.

$(function() {

    // put variables here that need to persist between clicks 
    var clickCounter = 0;

    $("#cupcake").unbind("click"); // in case this gets executed more than once

    $("#cupcake").click(function() { 

        // this is where you do stuff for the click

        clickCounter++;
        if (clickCounter > 30) {
            // do something special
        }

    });

});

First, note how the whole thing is an anonymous function given to the jQuery $() function. This means the code inside will get executed after the document is first ready (in the case of the JavaScript being pulled down on an initial page load) or immediately if the document is already done (in the case of the dynamic loading).

Because this can get called multiple times, I make sure to remove all existing "click" bindings from the cupcake on line 6. If I don't do this, jQuery will keep adding additional "click" bindings on for each call - meaning that clickCounter will be incremented multiple times for each click and other such weird behavior!

Line 8 adds the "click" listener. Because it creates a closure containing the clickCounter variable, it can be accessed with each click and maintain its value.

Hopefully this is just the first of many interactive frog & technology jokes that will appear. I'm going to try to make some that use more advanced features available to the browser, especially on mobile. Things like geolocation and the accelerometers. Keep reading!

Amphibian.com comic for 17 November 2014

Friday, November 14, 2014

Unbundle the Hamburger Button

Today's comic pokes fun at a few mobile application trends with which you are most likely familiar. The first is what they call un-bundling. You know, you have an app that does everything - it shares photos, lets you chat with friends, finds you a ride to work, orders dinner, and tells you what people think of your new haircut. Then they go and break it up into a bunch of separate apps so you can't do everything in one place anymore. Good idea, or mobile nightmare?

The reason I use Messenger
We've seen so many examples of unbundling this year:


There are other examples, one of which was sure to impact you. I'm sure the change was traumatic. Personally, I went at least 3 days without reading a single Facebook message because I didn't take the time to install Messenger. I sure did miss that Pusheen.

Why did all the unbundling occur? It could be caused by the next trend - the Hamburger Button. You know, that ubiquitous button with the three horizontal lines. It's in every mobile app ever made. It's even on some websites when you view them on your desktop computer. What does it do? Nobody really knows. You just have to push it once and see what happens.

Don't get too excited, it probably just hides a bunch of features that are seldom used. So there's features in your app which you probably don't use, but the app maker doesn't want to remove them. Weren't we just talking about features in your apps that you do use and the app maker removes them? Weird, I know.
Typical Hamburger Buttons - Click Here for...Something!
Some people are advocating for the end of the Hamburger Button. A particularly critical review of its use can be found here: Kill The Hamburger Button.

But I'd prefer to see it taken to some absurd extreme first. For example, when will I see an app using buttons like these very creative icons by Nick Meloy?

Hamburger Buttons, by Nick Meloy
All of this sounds silly, but there's more! The final trend that ties all these things together is the one-button app! Apps like Yo. It just has one button. You push it and it sends "Yo" to someone. A brilliant team applied this same ultra-simple design to food ordering, and gave us Push for Pizza, the simplest food-ordering app ever. There's one button. You push it, and you get pizza.

So, why not make an app with just the Hamburger Button? Especially if it actually gets you a hamburger.

Amphibian.com comic for November 14, 2014

Wednesday, November 12, 2014

Amazing Anaglyphs

For today's comic about 3D printers, the final cell has an optional stereoscopic 3D effect. You are probably familiar with this type of 3D imagery, where you have to look at it with those cardboard glasses with the two different colored lenses. Pictures like this are called anaglyphs. The most common form are the red/cyan type. Those two colors are used because red and cyan are opposite each other on the color spectrum.

Red/Cyan Stereoscopic 3D Glasses
Making the 3D version of the comic was not as easy as I initially thought it would be. As you may know, I create my comics by combining multiple SVG images on a web page. My first idea was to apply an SVG filter to create the anaglyph effect.

The first hurdle was to actually create the filter. I mistakenly assumed that Inkscape's filter editor might be usable. Ugh. Poor assumption. I had to edit the SVG file in a text editor, but it was certainly easy enough to apply the filter in Inkscape.

The Anaglyph SVG Filter


Here is the filter I created. Apply it to any element in a SVG document to make it pop off the screen!

<filter
     color-interpolation-filters="sRGB"
     inkscape:label="3d"
     id="filter3895-1-1">
    <feOffset
      result="l1"
      in="SourceGraphic"
      id="feOffset3897-8-2"
      dy="0"
      dx="-5" />
    <feOffset
      result="r1"
      in="SourceGraphic"
      id="feOffset3899-9-3"
      dy="0"
      dx="5" />
    <feColorMatrix
      result="r2"
      values="1 0 0 0 0 0 1 0 0 1 0 0 1 0 1 0 0 0 1 0 "
      in="r1"
      id="feColorMatrix3901-2-3" />
    <feColorMatrix
      result="l2"
      values="1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "
      in="l1"
      id="feColorMatrix3903-7-4" />
    <feMerge
        id="feMerge3905-9-1">
       <feMergeNode
           id="feMergeNode3907-5-1"
           in="l2" />
       <feMergeNode
           id="feMergeNode3909-4-3"
           in="r2" />
    </feMerge>
    <feBlend
       mode="multiply"
       in2="l2"
       in="r2"
       id="feBlend3911-3-8" />
</filter>

Here's the before-and-after pictures.

Before the Anaglyph Filter
After the Anaglyph Filter
Let me explain a little about what it does. First, it splits the source graphic into two new graphics. Each one has an X offset. In this case, I use an offset of 5 in each direction. To make the image appear to come further out of the screen, just use a larger value here. The first offset graphic (see the tag starting on line 5) will be the left side because it has the dx value of -5. The second offset graphic (starting on line 11) will be the right side because it has the dx value of 5. The resulting new graphics are called l1 and r1, respectively. The next step is to apply a different color transformation to each of the new graphics. The feColorMatrix tags on lines 17 and 22 perform these modifications. One side gets all the red removed and the other all the cyan. Finally, both of the new graphics get merged back together and a multiply blend is applied. This multiplies the color values together wherever they overlap, which results in the original color being seen again. On the edges, where there is no overlap, you can see a little of the all-red and all-cyan images.

Looks good, right? Put on your 3D glasses and that frog is jumping out at you. There was just one slight problem...This only works on individual graphics. If you try to arrange multiple images on a web page with these filters applied, the colors won't all blend together to create a cohesive scene. It looks weird, trust me.

The Anaglyph CSS


First idea was a failure. Next idea: use the new color-blending features of CSS3 on the images to create the scene! Here's how that works.

First, I created two SVG images of the frog. On one image I applied a filter to strip out the cyan color channel, and on the other I applied a filter to strip out the red channel. That gave me these oddly colored graphics:

frog_cyan_channel.svg

frog_red_channel.svg
I could then use these graphics together as backgrounds for a DIV, blending them together to create the same type of effect seen in the SVG filter. Here is an example of just that:

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Color Test</title>
  <style>

.ana {

  background:
    url(frog_red_channel.svg),
    url(frog_cyan_channel.svg);
  background-position:
    0px 0px,
    10px, 0px;
  background-repeat: no-repeat;
  background-blend-mode: multiply;

}

  </style>
</head>

<body>

  <div class="ana" style="top: 45px; width: 326px; height: 281px;"></div>

</body>

</html>

When you view this page in your browser, it looks like this:

Anaglyph via CSS blending
The CSS involved here is actually fairly simple. The DIV has two background images, the two color-filtered frog graphics. The position of the second background is given as "10px" which moves it 10 pixels to the right of the first background. This offset can be changed to make the frog appear closer to the viewer. The background-repeat is turned off so that we don't see another image along the edge, since the DIV has to be made 10 pixels wider than either image to ensure that there's room for the offset. Finally, background-blend-mode is set to multiply. Just like in the SVG filter, this causes the color values to be multiplied together anywhere the two images overlap - which brings back the original color in most of the image. Only along the edges do you see the all-red or all-cyan versions.

But alas, it's still not that easy. This works great for a single image. However, if you try to put one image done this way on top of another image, like I do in my comic, the colors from the two images won't blend with each other. They only blend their own backgrounds. Plus, this kind of blending still doesn't work on text even in the latest web browsers. That means even if I could figure out a slick way to overcome the first problem, I wouldn't be able to make the frog's words float in front of your face. Foiled again!

Even though this didn't work out either, I did learn quite a bit. You can read the following page to learn more about CSS blend modes: Basics of CSS Blend Modes.

The Classic Approach


In the end, I had to use the old-fashioned way to create the 3D version of the comic. I created two different versions of the cell, each with the individual components (frogs, text, and printer) slightly offset. I used my standard PhantomJS script to turn each one into a PNG image. Then I used GIMP to do the same thing to those two images that I'd been doing in the SVG filter and CSS - strip out the opposite colors from each image and then blend to put them together to form a single image.

After creating your 2 images, one for the right eye and one for the left eye, open them as Layers in GIMP.


You should end up with layers something like this. Make sure the right eye's image is on top. If it didn't end up there, just move it up.


Next, set your foreground color to red. Pure red. #FF0000.


Now create two new layers, with "Foreground color" selected as the fill type. Create one on top of the right side image and one between the right and left side images.


Your layers should now look like this:


Select the lower layer, the one directly above the left-side image, and from the Colors menu, select Invert. That should change the entire fill color to cyan.


And your layers should now look like this:


Next, click on each of the color layers and change their Mode to Screen. The mode selector is at the very top of the layer area above Opacity. Just click on the drop down on the right side and you'll see lots of options. Screen is the one you want.


Now from the Layer menu, select Merge Down on each of the pure color layers. This will combine them with the image layers directly below them.


And you have just two layers remaining and they should look something like the following picture. The one final step is to change the Mode on the top layer (should be the right eye image if you've done everything correctly) to Multiply. You can merge down again if you want to create a single layer, but your image should already look like a red/cyan anaglyph if you have both layers visible. Now you can export it!

Mode on the top layer is "Multiply"
It was quite a journey of discovery that I took to learn and experiment with all this, just to get a single cell in a single comic. I hope you enjoy looking at it as much as I enjoyed making it.

Amphibian.com comic for 12 November 2014

Monday, November 10, 2014

A Trio of Helpful Functions

Today I'd like to share three very small but useful JavaScript functions I found while building 2-Player Solitaire.

First, you can't have a card game without shuffling the deck. I found this shuffle function on http://jsfromhell.com/array/shuffle. In just a few lines, it randomizes the order of elements in a given array. Every day I'm shufflin'...

function shuffle(v) {
    for(var j, x, i = v.length; i; j = parseInt(Math.random() * i), x = v[--i], v[i] = v[j], v[j] = x);
    return v;
}

The second one is the function I use to create game ids. The games are identified by 5-character case-sensitive alphanumeric strings. It's easy to get ids of a different length, just change the number of iterations through the loop.

function makeGameId() {
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for( var i=0; i < 5; i++ ) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
}

Finally, there is this beautiful function for creating random GUIDs. This one is from http://byronsalau.com/blog/how-to-create-a-guid-uuid-in-javascript/. I use this to generate the unique identifiers for the cards in the game.

function createGuid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
}

I hope these can be as helpful to you as they have been to me.

Amphibian.com comic for 10 November 2014

Friday, November 7, 2014

Call Now, Log Later

Sometimes, you really want to cut down trees. But most of the time, logging is just having your software write information to a location where you can examine it at a later time. If you're looking for advice on chainsaws or flannel shirts, I'm sorry but this isn't the blog for you.

I can't tell you much about forestry, but I can tell you about logging from your Node.js application using the Express framework.
Logging, pre-Internet.
AZ Lumber & Timber Co. - 1937

Often, using Express means using the Morgan middleware for logging. Morgan is the HTTP request logger for Express. It allows you to easily output all the typical information you might want to see about your requests and responses. It's easy to use and allows you to customize the format or select one of several standard types.

But what if you want to log differently? I wanted to write the typical HTTP request/response data to a database table so that I could run queries against it later. For testing purposes, I also wanted to be able to optionally output the logs to the screen instead of the database.

I ended up writing my own logger middleware which can use either Morgan (for output to the screen) or a custom function (for output to my database) depending on a flag in my configuration object.

Take a look...

module.exports = function(conf) {

    var myLogger = null;

    if (conf.logToDatabase) {

        // here is where you can set up your database
        // connection or whatever you need

        myLogger = function(req, res, next) {
   
            function storeData() {

                res.removeListener('finish', storeData);
                res.removeListener('close', storeData);

                var reqIp = req.ip;
                var reqVerb = req.method;
                var reqPath = req.originalUrl || req.url;
                var resStatus = res.statusCode;
                var resSize = res.get('content-length');
                var reqRef = req.get('referer');
                var reqAgent = req.get('user-agent');

                // here is where you would call the function to
                // insert your data into the database

            };

            // defer logging until the end so we know the response stuff
            res.on('finish', storeData);
            res.on('close', storeData);   

            next();

        };

    } else {

        var morgan = require("morgan");
        myLogger = morgan("combined");

    }

    return function(req, res, next) {
        myLogger(req, res, next);
    };

};

Based on a check of the logToDatabase field in the supplied conf object (line 5), I decide which logger function to wrap in my returned function. If logToDatabase is defined and true, I create my own. Otherwise, I create an instance of Morgan.

Keep in mind that logging middleware is usually specified first in your Express application. That means the logger function is going to be called before any of your other routes get their chance to process the request. How can the log include things like the response code and content-length if those things haven't been determined yet? The trick to getting the HTTP response data into the logs is found on lines 31 and 32.

Notice that my custom logger doesn't actually do much when it is invoked. It defines a function, storeData, but doesn't actually call it. Instead, I assign the storeData function to be a listener on the "finish" and "close" response events and then just call next(). After that, all the other routes can process the request. Eventually, everybody is done with it and the Express framework ensures that at least one of the "finish" and "close" events gets fired.

It's then that storeData gets invoked. Thanks to the closure, it still has access to the request and response objects - and the response object will be fully populated with data.

On lines 14 and 15, you'll see that I remove the listener from both events. This is because I don't know which of the two events got fired, and it is possible that both will be fired. I don't want to log things twice! Since I can be certain that the function has been called at this point (since it's inside the function!) it is safe to remove both listeners.

Call now, log later.

This is a very useful pattern when developing for Node, not just when logging HTTP request data with Express. Creating function closures and using them to defer execution until an event occurs is a common theme that you'll encounter again and again. Now you'll be prepared.

Amphibian.com comic for 7 November 2014

Wednesday, November 5, 2014

Old Arcade Games, in your Browser

I don't have much time today, so I'll just say a few quick words about old video games.

First, they are awesome. I don't care how many polygons you have, I still like BurgerTime better. Video games didn't used to be all about graphics and controllers with 35 buttons. Pac-Man didn't have any buttons, just a stick. It didn't need anything else. That's the sign of a good game.

Second, you can now play them in your web browser. YES! The Internet Archive has just opened the Internet Arcade, where you can play thousands of classic arcade games in a JavaScript implementation of MAME. Sound doesn't seem to work, probably because JavaScript can't really play sounds (yet) but it's still pretty good.

I recommend:

Frogger
BurgerTime
Dig Dug
But feel free to find your own favorite in the extensive collection!

Amphibian.com comic for 5 November 2014

Monday, November 3, 2014

What do SQL and XSLT Have in Common?

Besides both making me angry and frustrated, what do SQL and XSLT have in common? They're both declarative programming languages.

Declarative languages express the logic of a computation without describing its control flow. This simply means that you tell the computer what you want the end result to look like instead of telling it how to perform the steps.

As I said, both SQL and XSLT are declarative languages. But so is HTML. I usually don't think about HTML as a program, but it is a set of instructions which tell the browser what to display. There's no way to express any kind of interaction with those components in pure HTML, which is why web development almost always includes JavaScript in addition to the HTML.

Imperative languages, by contrast, are concerned with the "how." In languages like C, C++, and Java, you are typically creating algorithms. You give the computer a series of steps that it needs to perform. If you want to display some text on the screen, those steps might be very difficult depending on a variety of factors. Compare that with "<p>Here is some text</p>" in HTML.

I won't tell you that one is better than the other. You should always pick the right tool for the job. But I will admit that I started programming in imperative languages long before I ever tried to use a declarative one, and the difference was often frustrating. Especially because languages such as SQL actually allow some imperative-style structure to sneak in. That enabled me to do things "wrong" because the wrong way was more familiar, and just set me up for total failure later when I tried to use XSLT.

Regular expressions are another example of a declarative language. Also another example of a language that I can never seem to get right, but I did find this really awesome tool for creating and testing them. I would highly recommend it next time you need to come up with one.

Amphibian.com comic for 3 November 2014