Use the new star dance pngs (with visible shadow) (closes #934).

I created a new png sprite from the new sequence pngs. Since it was
only four different images, each of them repeated for 6 frames,
I created a sprite with only those four images and changed the spritely
framerate from 24 down to 4 for this particular sprite.
Implement functions to query/aggregate event logs (closes #957).

These functions are to be used for composing the daily emails.

They are split across two modules, some of them reside in the
cardstories.event_logs module itself, while others are part
of the mailing.aggregate module.

To be honest I'm not entirely sure why I split them like this.
The idea was the the more generic functions that only query
the event_logs table should be part of the event_logs module,
while those more specific to emails would be inside mailing.aggregate.
In the end I'm not really sure whether the event_logs function turned
out to be as generic as I imagined.

The idea is that for mail sending we will be using plain sync
python functions, not twisted's async stuff. This is to keep things
simple for now.
Adds test_aggregate.py to be automatically run by the test suite.
Show advertise window immediately (refs #932)

After this changeset the advertise window will be shown immediately
after entering the invitation_owner state.
Merge remote-tracking branch 'antoviaque/master'
Merge remote-tracking branch 'mtyaka/master'
Fix the issue with tab not closing for the next GM of the table (closes #939).

The problem was with the poll that was running when the on_next_game_ready callback
was invoked. The callback first closes the current tab, which is an async operation.
When the tab is closed, the table plugin sees this as the next owner quitting the game,
which causes the table plugin to assign a new owner, and trigger the on_next_owner_change
event. This makes the poll return and issue another poll request with the "old" game_id.
The service sees a new poll request from a player that already closed the tab of that game,
so it thinks the owner is reopening the tab, and so adds the old game back to the tabs table,
which then reappears as an open tab on the player's screen.

This took me a long while to understand. The solution is to discards the running poll
prior to issuing the close tab request.

I also noticed there was a redundant call to on_next_game_ready, which I took
the opportunity to remove.
Fix invitation_pick animations (closes #959).

This one was caused by a line that slipped through unchanged through
refactoring. The fix is a one-liner, although it took me a while to find
the culprit, even after doing a git bisect.

There's no test for this one as I think it would be too much effort for
a bug that was essentially caused by a bad function call - and as such
isn't likely to happen again.
Merge branch 'master' of git://gitorious.org/cardstories-mtyaka/cardstories
Implement and tie together missing pieces for the daily email feature (closes #964).

This implements fetching players from the django db, and iterating over them,
preparing data to be used in the email via the mailing.aggregate module functions.

The get_player_name in the mailing.aggregate module is a bit weird in that it
doesn't lookup the player id in the django database to get the correspoding name,
but instead expects to be "seeded" with info of all players in the db.
It then creates and stores a dict of player_id to player names in memory,
so that player name lookups are plain in memory dictionary lookups.

This was a bit of a (premature) optimization on my part, as I was initially thinking
to be fetching django data via HTTP requests, which would have been much heavier
than direct db lookups, and the optimization might make more sense then.
But the idea stuck, and since it actually makes some tests simpler,
I decided to keep it.

The mailing.send module will need to be updated to work with the new mailing.loop module.

The ability to opt-out of receiving the daily emails still needs to be implemented
on the django side and this code will have to be updated to respect it once it's done
(but the changes should be minor).
Fix KeyError bug in table.py (closes #950).

The problem was with the code for the closed tab handler in the table plugin.
The code blindly assumed a table for game that was being closed existed,
which isn't the case for games that were created before the last server restart.

I believe the best fix (which would also solve some of the other problems of tables)
would be to make tables persistent somehow, so that not everything is lost after
a server restart. That would make a lot of things easier, but would require a
major refactoring and isn't something we could afford right now,
so I only added a check for table existing in game2table dict before trying
to call the on_tab_closed handler on it.
Show game info on Facebook feed (refs #965 and #966)

This implements the feature specified on #932 where when the game master
clicks "like" on the invitation box, the corresponding item on his
timeline/feed should contain a link to the current game, as well as the
game's story.

Showing the copy-pastable URL to the current game on the invitation box
was also implemented here.  I tried to get it to copy-to-clipboard on
click, but apparently that's a security liability and therefore not
practical in any sane cross-browser way.

Notes:

* The feature where the user could enter a list of emails to invite was
  completely removed client-side (but not server-side).

* Since we're including the Facebook JS SDK anyway, the top Like button
  now uses it, too, instead of the iframe.

* The Facebook App ID must be set correctly in settings.py or
  local_settings.py, otherwise the Like buttons won't work (they did
  before this, but the app id's were hardcoded).

* The Facebook SDK is now loaded by the Django template, as opposed to
  being loaded at runtime when the invitation box is opened.  This
  should give the impression that it's speedier.

* Django templates were a bit rearranged where the Facebook and G+
  SDKs were concerned: they're now included by default in the base
  template (since they're always used).
Build package on Ubuntu 10.04 (refs #971)

This fixes the debian scripts so that the package can be built and
installed on Ubuntu 10.04.
Fix missing story in feed bug (refs #966)

This fixes a bug where the story wasn't visible on the FB feed.
Fix FB bugs (refs #966)

This fixes two bugs related to the Facebook like buttons:

* The were not being rendered when changing tabs or creating a new game.
  This is because on these situations, the DOM is recreated, and because
  of this the Facebook SDK must be notified.

* The Send button rendered a blank box, because according to the
  Facebook debugger (https://developers.facebook.com/tools/debug) the
  <og:image> meta tag did not contain an absolute URL.
Fix 'NoneType' object is unsubscriptable errors (closes #949).

The problem was that when the game is destroyed, the poll returns with None.
This was implemented intentionally, though I am not sure what the reason
behind it was.

It was tripping up the tab polling code because if one of the games in the
tabs was cancelled (when game is cancelled, destroy is called on it),
poll returned with None and the code that was looking for the 'modified'
argument errored out.

I solved this by touching the game with a type='cancel' touch before destroying
it in the cancel method. This makes any polls return gracefully before the game
is destroyed. When a user has a canceled game opened, it now correctly detects
it changed state and shows our "Game has been canceled" popup.
Without this change, the client code was erroring out because 'modified' wasn't
there.

Another possible source of game.destroy() calls is when shutting down the service.
All games are destroyed then. The errors were harmless, but I added a check
for the returned poll arguments being equal to None, before trying to search
for 'modified', to silence the errors.
Merge branch 'master' of git://gitorious.org/~arbrandes/cardstories/arbrandes-cardstories
Merge branch 'master' of git://gitorious.org/cardstories-mtyaka/cardstories
Closes #962 - HTML/MIME Email design integration

Integrates HTML and plain text version of the designed email, and hooks
it to the loop logic.

Supported:
- GMail
- Outlook 2002+
- Thunderbird 3+
- iPad
- iPhone iOS4/5
- Apple Mail
- Yahoo Mail
- AOL Mail
- Blackberry 4 (plain text)
- Hotmail (gracefully degraded with uniform background color)

Not supported (mail and content are readable, but formatting has bugs):
- Android 2.2 (images not displayed, cf bug fixed ~1 month ago
https://code.google.com/p/android/issues/detail?id=1180)
- Outlook < 2002
- Lotus Notes < v8 (IBM discontinued support for v7 since last year)
- BlackBerry 5 OS - HTML (No support for PNG transparency - borders
appear black)
- Nokia/Symbian (No support for PNG transparency - borders appear black)
- Windows Phone 7 (No support for PNG transparency - border appear black

Incompatible (unusable):
- Windows Mobile 6 (only the background appears)

Related changes:

- Add two undocumented variables to README (DEFAULT_FROM_EMAIL,
BASE_URL)
- Allow result set to be empty when getting player last_activity from
event log
- Add test_aggregate.py to make check
- Short README file for the mailing directory
- Hook to include unsubscription URL in emails
(aggregate.get_unsubscribe_url and context['unsubscribe_url'])
- Includes EmailMultiRelated class from django snippets (to attach
inlined elements)
- Adapted test_loop.py to new parameters set for send.send_mail()
Closes #984 - Optimize PNG images

Ran the biggest PNG images through http://tinypng.org/. This gives a
~50% average reduction in size, and reduces the weight to preload by
3MB (!)