Monday, November 28, 2011

This “UPS My Choice” Thing is Actually Pretty Neat

Does anyone remember using eBay before the whole “My eBay” thing existed? No? You may find it hard to believe, but when eBay launched (a looonnnng time ago) they’d email you confirmations of your activity (bids, sales, etc.) and you’d use those emails to keep track of that was going. It wasn’t until years later that eBay offered a centralized “my account” page with that information.

It’s insane to imagine today that it used to work that way but I swear it did!

And yet UPS doesn’t even work that well for most people today. You order something and if you’re lucky, the vendor gives you a tracking number which you constantly monitor to see where your widgets are and when they’ll arrive. Some vendors and shippers added the ability to subscribe to email notification for specific tracking numbers, which helped, but that wasn’t a great solution either.

Then, when I started tracking a package last month, I somehow ended up at UPS’s My Choice system. At first I thought this was just a reinvented notification engine. It didn’t really make sense to me initially because it seemed like the nice features were hiding behind the premium version. And I was really tired.

I scoffed at the notion that I’d have to pay some annual fee to get trivial functionality out of a shipping company and forgot about it.

Then, a couple weeks later I got this in my email:

image

It took me a couple seconds to realize what had happened. I apparently wasn’t paying attention to the sign up process because what UPS is doing is notifying me (automatically) whenever anyone ships me a package. It matches packages by address and name (multiple names allowed) and lets me know when they’re on their way, if they are delayed, and when they’ve arrived.

This is more than I expected and it turns out to be pretty much exactly what I want. In the weeks since, the emails keep coming:

image

These emails take you to the UPS version of “My eBay”, which does exactly what you’d hope.

They still offer completely unhelpful delivery windows, like this:

image

Which means it’ll get here sometime between 7:30 am and 7:30 pm. Or later. Maybe.

But To their credit, allegedly the paid version of “My Choice” improves this by giving you a two-hour delivery window, among other things for $40/year.

This is one of those things that is hard to understand why it hasn’t existed all along. Thanks, UPS, I love it!

Your move, FedEx. I’d call out USPS, too, but their tracking is so laughable that the notion of them implementing anything serious is ridiculous.

Wednesday, November 23, 2011

I Vote To Close This Meeting

So my company is doing this cool thing: they're giving every employee a tablet.

The idea is that we're a tech company and can probably figure how to use them to improve efficiency or blah blah blah, and they're cool and will make us happy. Yay!

So aside from making our existing tools work well on mobile and surfing the top apps/games lists in the AppStore, here's a problem I want an app for:

Unproductive meetings

I'm talking about meetings where people keep talking in circles, refusing to converge to a decision. Or meetings where the chit chat is getting out of hand and some of us have actual work to do.

I'm guilty of this, too. Really.

Most people are too polite or non-confrontational to do anything so we need something that allows people to say, "hey let's refocus here because this is all an epic waste of time" without actually saying it.

Imagine everyone sitting around the conference room table with their tablets blathering on. Now suppose everyone had an app running with the following features:

- the meeting agenda
- a place for minutes/action items
- a timer showing how much time is left
- a timer indicating how much money has been spent (labor) since the meeting began
- a reminder tone very 25% of the duration of the meeting

Those are all highly collaborative with shared workspaces, etc. But these features are really just an excuse to deploy this:

- anonymous voting buttons that allow anyone to make a statement

Maybe votes only activate something if two people vote...not sure. (It's really just like voting to close questions on Stack Overflow.) I want to be able, with one or two taps, notify the group that things need to move on for some canned reason.

Reasons are simple things like:
- off topic
- not relevant to the group (i.e. you two go figure it out later and report back)
- conclusion needed (i.e. what's the action item from this thread of discussion)
- other voices needed (i.e. share the podium, pal)

Does this exist? Thoughts?

(Apologies for any formatting issues or typos...I'm posting this from my phone.)

Monday, November 21, 2011

Case Sensitivity in ASP.NET

I’m personally a fan of respecting case sensitivity. Historically it seems that most programming languages are picky about “a” vs. “A”, and even most operating systems. VB, and Windows, however, are not.

This leads to some frustratingly elusive bugs on occasion because there are instances in VB where case does matter. Take for instance the following objects, commonly available while processing an ASP.NET request:

  • Request
  • Session
  • Cookies
  • Viewstate

The first three (among others) are implemented with a hash table that does case-insensitive lookups. (There’s an awesome answer over on Stackoverflow that explains why it works this way).

So after playing fast and loose with case sensitivity, it’s easy to treat the viewstate object the same way. But, as you’ve surely guessed by now, lookups in the viewstate bag are case-sensitive.

Unfortunately, I can’t find a reference that documents this at the moment, but I can confirm it works that way from personal experience. Here’s one of my recent commits:

imageimage

And a flood of Google results from others affected confirms it’s not a fluke affecting just me.

Happy debugging!

Tuesday, November 15, 2011

LEDs Have Arrived!

LEDs are awesome. In exchange for tiny amounts of energy, they produce intense, bright light. Plus they are cool to the touch and very durable. In recent years they have even become affordable!

I think the age of LED lighting has finally arrived. Sure, they conquered flash lights and specialty applications years ago but I think they’ve hit a big bigger milestone this year: they have crushed the Christmas Lights market. The options you find walking down the Christmas lights aisles (yes, aisles) have been slowly moving from traditional incandescents to LED-based products. Last year I looked at the LED options but shied away because they were still too expensive.

This year was different. First off, I couldn’t even find the old bulbs at first—LEDs have nearly pushed them out completely. Second, they are now in the “yeah, that’s doable” price range. Still spendy, but not ridiculous.

And so tonight I took advantage of the warm, calm, no-wind weather to hang 225 lights.

Photo Nov 15, 8 48 43 PMPhoto Nov 15, 8 48 04 PM

Apologies for the weak photography. The resident photographer is away at the moment so I just used my phone. In the dark.

Side note: you know what’d be an awesome product? Shorter sections of lights. I need 18” to finish that top eve. What am I supposed to do…?

So how’d we do energy-wise? I’d say pretty awesome:

Photo Nov 15, 8 42 49 PM

That’s 7.5 tiny watts. At 10¢/KWH, running these for 7 hours a day will cost just…

image

0.5¢/day. Half a penny a day. Is that right?! Whoa.

That seems a bit lower than I expected. I just checked the box and all the lights together are rated at about 18 watts. So either that’s conservative or my meter isn’t working quite right… In any event, they are quite efficient!

If you’ve been avoiding these things, I suggest you take another look. Here’s hoping that interior lighting is the next empire to fall to the mighty LED! (I know LED bulbs exist, but $15/bulb is too much!).

A Candy Land Simulator: The Game Engine, Implemented

Note: this post is from a series on Candy Land.

We’re back again. We still have our board and cards (these are old hat now, right?):

var board = [
    { color: 'Red' },
    { color: 'Orange', bridgeTo: 59 }
    // ...
];

var cards = [
    'Red'   , 'Red'   , 'Red'   , 'Red'   , 'Red'   , 'Red'   , 'Red'   , 'Red'
    // ...
];

And we just added some players:

var players = [
    { name: 'Michael', isLosingATurn: false, position: -1, isWinner: false, moves = 0 },
    { name: 'Thing 1', isLosingATurn: false, position: -1, isWinner: false, moves = 0 }
];

So let’s get down to implementing some of the game engine we spec'd out yesterday. First, here’s the test harness:

image

I decided to add an option of letting players stop the game as soon as one player wins (like normal people), or to play through until everyone “wins” like my kids play. This is the main function that we run when we click the button to start the game. It loads up that option from a checkbox, and the players:

// for stats
var gamesPlayed = 0;
var totalMoves = 0;

// run this when the button is clicked
$('#run').click(function(){
    
    var options = { 
        // see if the option to run until everyone wins is checked
        doRunUntilEveryoneWins: $('#all-win').is(':checked')
    };

    // configure two players
    var players = [
        // ladies first
        { name: 'Thing 1', isLosingATurn: false, 
          position: -1, isWinner: false, moves: 0 },
        { name: 'Michael', isLosingATurn: false, 
          position: -1, isWinner: false, moves: 0 }
    ];

    // call "DoGame" to play an entire game, passing 
    // in the players array
    DoGame(options, players);
    
    // update stats
    gamesPlayed++;
    totalMoves += players[0].moves + players[1].moves;
    $('#average').text(Math.ceil(totalMoves/gamesPlayed));
    
    // append another row to the table
    $('#results').show()
        .find('table').append( 
            $('<tr/>').append( $('<td/>').text(players[0].moves) )
                      .append( $('<td/>').text(players[1].moves) )
                      .append( $('<td/>').text(players[0].moves 
                                               + players[1].moves) )
            );
});

As you’ll see, I’ve taken a few other liberties during the implementation that deviate slightly from the original design. That’s normal.

So when we actually call “DoGame()”, this is called:

function DoGame(options, players){
    // initialize the board
    var board = MakeBoard();

    // initialize the deck
    var cards = MakeDeck();

    // call "DoGameLoop" (pass in the board and deck) 
    // until it returns false, which indicates the game is over
    while(DoGameLoop(options, players, board, cards));
}

Which calls “DoGameLoop” repeatedly until it signals that the game is over:

// return false when the game is over
function DoGameLoop(options, players, board, cards){
    
    // we will set this to true if someone is playing...
    var IsSomeoneStillPlaying = false; 
    
    // for each player: DoPlayerLoop
    for(var i = 0; i < players.length; ++i){
        var player = players[i];
        
        // skip this player if they've won already
        // or made 10000 moves (that would be too many)
        if(!player.isWinner && player.moves < 10000){
            
            // do the actual move
            DoPlayerLoop(options, player, board, cards);
            
            // keep track if this player has won
            IsSomeoneStillPlaying |= !player.isWinner;

            // see if we should stop when just one player wins (configurable)
            if(!options.doRunUntilEveryoneWins && player.isWinner){
                return false;
            }
        }  
    }
    
    // things went as planned, return true if some players are still playing
    return IsSomeoneStillPlaying;
}

That just calls “DoPlayerLoop” for each player:

function DoPlayerLoop(options, player, board, cards){
    // if we are losing a turn, turn off the "isLosingATurn" 
    // property and we're done (exit now)
    if(player.isLosingATurn){
        player.isLosingATurn = false;
          return true;
    }
    
    // draw a card and increment the "moves" counter
    var drawnCard = DrawACard(cards);
    player.moves++;
    
    // we'll can play either 1 or 2 moves because we have doubles
    var currentSpace = DoMove(options, player, board, drawnCard);
    
    // if the player drew a double card, they move again  
    if(drawnCard.isDouble && !player.isWinner){
        DoMove(options, player, board, drawnCard ); // do it again!
    }
    
    if(player.isWinner){
        // woohoo
        return true;
    }
    
    // if the space we landed on is a bridge, follow the bridge
    if(currentSpace.bridgeTo){
        player.position = currentSpace.bridgeTo;
        currentSpace = board[player.position];
    }
          
    // if we are now on a lose-a-turn space, turn on the 
    // "isLosingATurn" property so we know 
    // to skip our turn the next time around
    if(currentSpace.loseTurn){
        player.isLosingATurn = true;
    }
}

The real workhorse in there is the call to DoMove, which actually advances the game token along the board:

function DoMove(options, player, board, card){
    // we'll cycle through the board. 
    // if we have a regular color card (or double), we'll go 
    // until we hit the color, OR reach the end of the board
    var currentSpace;
    var iterations = 0;
    do{
        // advance one space
        player.position++;
    
        // if we hit the end of the board
        // we start over if we have a character card
        // or we win if we have a regular color card
        if(player.position == board.length){
            if(card.isCharacter){
                // if we have a character card and we've reached the 
                // end of the board, wrap around
                player.position = 0;
            }
            else{
                // if your move takes you to the last square or beyond, you win 
                // set the "isWinner" property to true and exit
                player.isWinner = true;
            }
        }
        currentSpace = board[player.position];

        // loop until we find the space we're looking for
        // or we win
        // or we iterate 10000 times (because something must be broken)
    }while(currentSpace 
           && currentSpace.color != card.color 
           && !player.isWinner && ++iterations < 10000);
    
    return currentSpace;
}

All this, including the source to the utility functions (e.g. DrawACard) is available in the fiddle. Here’s the working version:

In the next post I’ll do some additional testing and verification. A brief, casual comparison to other papers online reveals that my results are reasonable. I’m not saying they are correct, but I’m at least in the ball park for finding the length of an average game (around 45-50 cards).

Monday, November 14, 2011

Outlook Tip: Automatically Archive Annoying Meeting Invitation Responses

If you use Outlook’s handy meeting request feature to plan events like presentations and lunches involving a lot of people, you have probably experienced this shortly after sending out an invite:

image

For the unitiated, what you’re looking at is the flurry of responses that come in after the invite goes out. Outlook uses actual emails to keep track of people accepting/declining invites. And by default, they all just show up in your inbox.

Normally when something like this comes up, I just create a rule to take care of it. This case is no different but it’s not as simple as it seems. The problem is that when accepting or declining an invite, Outlook lets you add a message:

image

I don’t want to automatically process or hide the responses if the sender went to the trouble to actually write something inside. With that in mind, I have the following rule:

image

Basically, the rule executes whenever a message is sent just to me and has the telltale text in the subject. But, if the message body contains any text, leave the message in place. I couldn’t find any reasonable way to check if the body contains any text, so I had to resort to the hack of just checking for vowels. I guess you could add all the letters of the alphabet…but that’d just be silly.

Here’s the rule if you just want to import it (and update the move-to folder). If that makes you nervous (it should!), it’s not hard to recreate from the above screenshot.

Once in place, your inbox should be nice and clean again…or at least not cluttered by empty RSVPs.

Saturday, November 12, 2011

A Candy Land Simulator: The Game Engine

Note: this post is from a series on Candy Land.

Last time we captured the board and the card deck into Javascript objects that look like this:

var board = [
    { color: 'Red' },
    { color: 'Orange', bridgeTo: 59 }
    // ...
];

var cards = [
    'Red'   , 'Red'   , 'Red'   , 'Red'   , 'Red'   , 'Red'   , 'Red'   , 'Red'
    // ...
];

players

Now we need to simply draw cards and keep track of a player through the game. I guess we should come up with some simple way to track that. Players will have a name and a position on the board. We also need to know if the player is losing a turn because they stepped on a licorice space. This should do it:

var players = [
    { name: 'Michael', isLosingATurn: false, position: -1 },
    { name: 'Thing 1', isLosingATurn: false, position: -1 },
];

As we design the rest of the engine, we’ll add to that as necessary.

OK, now we need to create a game loop. A game loop basically covers all the actions that happen in one cycle of the game. Since Candy Land players don’t affect each other (except for a shared deck of cards), all the interesting stuff happens in the player loop, with alternating players.

Here’s a first pass of what we need:

var players = [
    { name: 'Michael', isLosingATurn: false, position: -1, isWinner: false, moves: 0 },
    { name: 'Thing 1', isLosingATurn: false, position: -1, isWinner: false, moves: 0 }
];

// call "DoGame" to play an entire game, passing in the players array
          
function DoGame(players){
    // initialize the board
          
    // initialize the deck

    // call "DoGameLoop" (pass in the board and deck) until it returns false, 
// which indicates the game is over
// when the game is over print out summary stats (e.g move counts) and exit } function DoGameLoop(players, board, cards){ // if all players have finished (yes, my kids insist that the game continues // until everyone finishes :/) exit, the game is over (return false) // for each player: DoPlayerLoop // things went as planned, return true } function DoPlayerLoop(player, board, cards){ // if we are lose a turn, turn off the "isLosingATurn" property and we're done (exit now) // draw a card and increment the "moves" counter // find the next space to move to based on the card // if your move takes you to the last square or beyond, you win // set the "isWinner" property to true and exit // if the space we landed on is a bridge, follow the bridge // if we are now on a lose-a-turn space, turn
// on the "isLosingATurn" property so we know
// to skip our turn the next time around } function DrawACard(cards){ // if there are no cards left in the deck they must have all been played so // reshuffle them! Boom, now there are cards in the deck // remove a card and return it } function MakeDeck(){ // return a new, shuffled deck } function MakBoard(){ // return a new board }

That should read pretty easily from top to bottom (you may have to use your imagination a little bit). We’ll implement some of these in the next post.