Googlefest 2014

Googlefest 2014

Yesterday I got to go to Googlefest 2014 in Charleston SC with my dad and my brother. It was a lot of fun. We took some photos with a six foot Android mascot. I also got to try out Google Glass. It was neat, but definitely not worth the current $1500 price tag.

Android and Me

It was a short event but I learned some useful things.

One of the speakers talked about Gen C (pretty much matched the info on this page). This group of individuals is defined by their mindset rather than their age. Marketing to Gen C is much different than marketing to other generation groups. They care more about the opinions of their peers, are more mobile, and love video. The presentation gave some good pointers on getting started with marketing to this group.

Another speaker went over Google Analytics. In addition to some tips and tricks I wasn’t aware of, she pointed us to the Google Analytics Academy. This site provides free analytics training provided by Google. I’ve gone through most of the first course and have learned a ton. I’ve always had Google Analytics on my sites, but turns out it is so much more powerful than I thought.

We also grabbed a pile of goodies: Moleskine-style notebooks, pens, mechanical pencils, tote bags, magnet words, and some sort of weird elastic thing with Google printed on it. Not sure what the elastic thing is supposed to be. My mom thinks it is a hair tie but that seems like a weird giveaway.

Goodies

The most interesting, albeit least useful to me, portion of the conference focused on emergency management. The South Carolina Emergency Management Division spoke on how they use Google’s tools and products to help them do their jobs. For example, they have Google Earth configured to show storm surge, hurricane evacuation routes, earthquake fault lines, and epicenters of previous earthquakes. They also use social media to get live feedback from average people during emergencies. This allows them to find problems before they are officially reported, or to determine if an emergency is actually happening (e.g., was that tremor felt all over or just in this building?).

I love short conferences like this. They are fun to attend and provide condensed doses of useful information. Thanks Google!

Read More

Picking a random date between two dates

Picking a random date between two dates

Many years ago I created the Fake Name Generator, a website that lets you create fake names, addresses, birth dates, and other profile information. I’ve had issues with the birth date component ever since I wrote the dang thing, including a huge bug I fixed a few years ago.

Well today I was informed of another bug. A while back I added the ability for visitors to select an age range for their generated identities. The code that handled this was atrocious: it would figure out the birth year range by subtracting the selected min/max ages from the current year, then pick a random year within that range. It would then pick a random number 1 to 12 to represent the month, a random number 1 to 31 to represent the day of the month, then it would use checkdate() to see if the date is valid (for example, 2/31/1990 would be invalid). If it is invalid, it would try again. Most of the possible generated dates are valid so it only occasional has to try again.

Aside from being ugly, the big problem with this code is that it doesn’t always generate birth dates within the selected age range. Say you want to generate a birth date that would make someone at least 19 years old and no older than 19 years old (i.e., exactly 19 years old). In January most of the generated birth dates will make an 18 year old, in June you’ll have about a 50/50 split of 18 and 19 year olds, and in December most will be 19 year olds. This is because my code was only dealing with the birth year, and wasn’t taking into account the birth day or month in relation to the current date. Not very noticeable if your age range is something like 1 to 100 years old, but very noticeable if it is January 10th and you want a birth date for a 19 year old. Like I said, horrible code.

So here is my latest try. This function takes a minimum and maximum age as parameters, and spits out an array with the birth date and age:

function dateTime($minAge = 19, $maxAge = 85)
{
    // Sanity check
    if(!is_numeric($minAge)) $minAge = 19;
    if(!is_numeric($maxAge)) $maxAge = 85;
    if($minAge > $maxAge) $minAge = $maxAge;

    $tz = new DateTimeZone('US/Eastern');

    $minDate = new DateTime('now', $tz);
    $minDate->modify("-$maxAge years -1 year +1 day");
    $maxDate = new DateTime('now', $tz);
    $maxDate->modify("-$minAge years");

    $minEpoch = $minDate->format('U');
    $maxEpoch = $maxDate->format('U');

    $birthday = new DateTime('@'.mt_rand($minEpoch, $maxEpoch), $tz);
    $today = new DateTime('now', $tz);

    $date = array(
        'year'      => $birthday->format('Y'),
        'month'     => $birthday->format('n'),
        'month-name'=> $birthday->format('F'),
        'day'       => $birthday->format('j'),
        'formatted' => $birthday->format('n/j/Y'),
        'age'       => $today->diff($birthday)->y,
    );

    return $date;
}

The code is a bit long, but is actually pretty straightforward:

First we do a little sanity check. I want my code to return valid data even if someone manages to pass in a bad value, so I check to make sure the min and max ages are numeric and that the min age isn’t larger than the max age. This could be improved, but I think it is good enough for my needs.

Next we create a DateTimeZone object. My server’s time is set to US Eastern, so I want all my dates to use this time zone. This object will get passed into the constructor for DateTime later in the code.

In the next block of code I create two DateTime objects with today’s date. I use the modify method to subtract an appropriate amount of time from each object so I get the minimum and maximum birth date that someone could have and still fall within the desired age range. DateTime makes this easy by allowing things like +1 day. It doesn’t care about plurals, so you can use day and days, year and years interchangeably and inappropriately.

This next bit was a stroke of genius (which I later discovered is what some experts online would consider “the obvious way”). I convert the minimum and maximum dates into Unix timestamps, which are just integers. So if we are generating an identity for someone between 20 and 50 years old, the minimum date would be something like -219961293 and the maximum would be 758259507.

Now that our dates are just integers, picking a random date between the two is easy. I create a new DateTime object with the date set to a random Unix timestamp between the minimum and maximum Unix timestamps I came up with in the previous step. I then create another DateTime object, $today, to use later to come up with the identity’s age.

I use an array to hold each bit of the birth date, a formatted version of the birth date, and the age. To get the parts of the birth date I just call the format method on my $birthday DateTime object. To get the age I use the diff method on my $today DateTime object to find the number of full years between the $birthday object and the $today object.

If all you want is to pick a random date between two dates, then this is obviously more than you need. You could probably get away with this, if you were sure that the input dates were valid:

function randomDate($startDate = 'now', $endDate = 'now')
{
    $minDate = new DateTime($startDate);
    $maxDate = new DateTime($endDate);

    $minEpoch = $minDate->format('U');
    $maxEpoch = $maxDate->format('U');

    $randomDate = new DateTime('@'.mt_rand($minEpoch, $maxEpoch));
    $today = new DateTime('now');

    $date = array(
        'year'      => $randomDate->format('Y'),
        'month'     => $randomDate->format('n'),
        'month-name'=> $randomDate->format('F'),
        'day'       => $randomDate->format('j'),
        'formatted' => $randomDate->format('n/j/Y'),
        'age'       => $today->diff($randomDate)->y,
    );

    return $date;
}

DateTime can figure out most dates, so you could do something like randomDate(‘March 1, 1980’, ‘5/20/1999’). If you don’t pass any dates in then it will use today’s date.

I could probably re-use some of those DateTime objects, but I don’t think having a few of them matters enough to obfuscate the code. I could also just return the $birthday object rather than building an array to return, but my existing code expects an array.

I’m open to critiques and suggestions for improvements. I’m thick skinned so feel free to completely bash my code if you’d like. Or if you are having a problem with the code, please let me know and I’d be happy to try to help you out!

Read More

Enabling mouse support in Vim

Enabling mouse support in Vim
Hopefully you are using newer equipment than this...

Hopefully you are using newer equipment than this…

If you’ve ever logged into a server using an ssh client (like PuTTY), then you’ve probably used Vim. This infinitely customizable text editor typically runs within a keyboard-only shell, and thus only lets you use the keyboard (unless you are running something like gVim). You use the arrow keys to move the cursor around and a slew of keyboard shortcuts to insert, move, delete, or otherwise manipulate the text.

If you are a Linux user I just told you a bunch of stuff you already know. But did you know that Vim has mouse support? You just have to turn it on. Open Vim and enter this command:

:set mouse=a

You’ll now have mouse support until you exit Vim and load it up again. To make the change permanent, edit your .vimrc file (typically at ~/.vimrc) and add set mouse=a to the end of the file.

So how do you use the mouse in Vim? What benefits will you get? There are a few things you need to know:

  1. Copying text: You may be in the habit of highlighting text and having it put on your system’s clipboard. This won’t work anymore. When you click and drag to highlight text, you’ll be put into Visual mode, an amazingly powerful part of Vim that many people never use. I highly recommend learning more about Visual mode, but if you want the original behavior you can hold shift while selecting text.
  2. Placing the cursor: Instead of having to use the arrow keys to move your cursor, you can now just click wherever you want it to be. Huge time saver.
  3. Scrolling: Yup, you can scroll with the mouse wheel now. No more hitting page down a hundred times in a giant file. Just scroll that wheel to get to wherever you want in your file.

After a few days of reaping the many benefits of Douglas Engelbart’s wonderful little invention, you may be asking yourself: Why isn’t mouse support turned on by default?! I’m not really sure. I did a bit of searching but couldn’t find a definitive answer. If you figure it out, please let me know!

Read More

git in color

git in color

By default, git doesn’t use color. It is gray gray gray. Bleh. But with a single line in your shell you can enable color for git:

git config --global --add color.ui true

Bam! Color for your git diff, merge, add, commit… Everything. It is amazing how much a little color can help.

Without Color

Without Color

With Color

With Color

Read More

Postmark is awesome for transactional emails

Postmark is awesome for transactional emails
Update 2/20/14: I’ve switched to SendGrid. I’ve been using them for a few weeks and am completely satisfied!

Update 10/31/13: Postmark has terminated my account because they aren’t comfortable with the Fake Name Generator. I’m disappointed that they would make this decision, and I can no longer recommend their services.

The Fake Name Generator lets people order (for free!) large lists of fake names, addresses, and other information. It can take a few minutes to generate the data files, so users are required to give me their email address so I can send them an email when their order is ready.

This has caused me a few problems:

  1. Order fulfillment emails sometimes go to spam. So people enter more orders, which takes up server processing time, and they still don’t get them because they never check their spam folder. Or they put in a support request, which means I’m having to spend time chasing the issue.
  2. People enter fake email addresses. This one drives me crazy. There isn’t any way to give them their order if they don’t give me a valid email address, yet people will put in a dozen orders using bogus email addresses that ultimately bounce back to my inbox.

To solve this, I’ve done a few things.

First, instead of sending email directly from my server, I’m using Postmark, a service that is specifically designed for transactional emails. Postmark is amazing. With just a few clicks I had a virtual mail server configured with DKIM, SPF, and SenderID. It uses an API instead of clunky SMTP to accept emails. This was easy to integrate using some free code I found online. Because it is only used for transactional emails, deliverability is extremely high.

It also comes with a few additional perks. It lets me see every email I send out, so if I do get a support request, I don’t have to ask anyone to forward me emails or links or wonder if the email was actually delivered.

Postmark helped me solve the bounce problem, too. It lets you use a hook URL to handle bounces. I set up a simple script that grabs the email address for any bounced email and blocks that email from ever ordering from my site again.

There are a lot of alternatives to Postmark out there and some are considerably cheaper, such as Amazon SES and SendGrid. I did a fair amount of research before picking a vendor. To be honest, Postmark just seems better. They are more reliable, they have more features that I’ll actually use, their pricing is pay-as-you-go (no monthly minimums), and their API is lightweight and easy to use.

Read More

Configuring PhpStorm for use with CakePHP

Configuring PhpStorm for use with CakePHP

This article assumes the reader is using PhpStorm 6.0.3 and CakePHP 2.3.8.

My friend Joey has gotten me interested in PhpStorm and CakePHP. His company is in love with both, so I figure there must be some value there.

The latest production release of PhpStorm, out of the box, doesn’t do a stellar job of working with CakePHP. Some files aren’t syntax highlighted, it complains about non-existent problems, and auto-complete is imperfect. These issues are easy to fix with a tiny bit of work:

Syntax highlighting. To get syntax highlighting working properly, you need to add *.ctp to the PHP file extensions list. Open PhpStorm and go to File->Settings. Click File Types, then click PHP files (PHP) in the box of Recognized File Types. Click the green + to add an entry to the Registered Patterns. Type *.ctp then click OK. Click OK to close the settings dialog and to apply your changes.

Fix a few warnings. If you are in a controller, you may notice that PhpStorm complains that: Multiple definitions exist for class AppController. To fix this (and related warnings and some auto-complete issues), go to File->Settings. Click Directories. Select lib->Cake->Console and click Excluded. Select lib->Cake->Test and click Excluded. Click OK to close the settings dialog and to apply your changes. This fix has to be done to each project.

Improve auto-complete. Added a few comments to your various files will improve auto-complete.

Controllers and Models. Add a property to the top of each controller or model that references any models you want to use in that file. For example, if your model was named Post, you would add:

<?php

/**
 * @property Post $Post
 */

?>

Views. Add the following to the top of each .ctp file:

<?php

/**
 * @var $this view
 */

?>

Auto-upload files when they are saved. I like to develop on real servers, so I set my IDE to upload my files after each save. Go to File->Settings, then find Deployment->Options. Choose On explicit save action (Ctrl+S) for Upload changed files automatically to the default server, then click OK. This is another per-project setting.

Read More