content: import itertools
  import random
  import pickle
  import time
  
  # cribbed from
  # http://pastebin.com/mzNmCdV5 
  # http://stackoverflow.com/questions/2518753/best-way-to-implement-a-deck-for-a-card-game-in-python
  # data
  SUITS = ('c', 'd', 'h', 's')
  RANKS = ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
  
  DECK = tuple(''.join(card) for card in itertools.product(RANKS, SUITS))
  
  ORDER_LOOKUP = dict(zip(DECK, range(52)))
  RANK_LOOKUP = dict(zip(RANKS, range(13)))
  SUIT_LOOKUP = dict(zip(SUITS, range(4)))
  
  # utility functions
  def cmp_cards(a, b):
      return cmp(ORDER_LOOKUP[a], ORDER_LOOKUP[b])
      
  def cmp_tuples(a, b):
      n1 = len(a)
      n2 = len(b)
      if n1 != n2:
          return cmp(n1, n2)
      return cmp(a, b)
      
  def suit(card):
      return card[1]
      
  def suit_int(card):
      return SUIT_LOOKUP[card[1]]
      
  def rank(card):
      return card[0]
      
  def rank_int(card):
      return RANK_LOOKUP[card[0]]
      
  def card_int(card):
      s = 1 << suit_int(card)
      r = rank_int(card)
      c = (s << 4) | r
      return c
      
  # test functions
  def is_straight(cards):
      previous = rank_int(cards[0]) - 1
      for card in cards:
          r = rank_int(card)
          if r != previous + 1:
              if not (r == 12 and previous == 3):
                  return False
          previous = r
      return True
      
  def is_flush(cards):
      s = suit(cards[0])
      return all(suit(card) == s for card in cards)
      
  def same_rank(cards):
      r = rank(cards[0])
      return all(rank(card) == r for card in cards)
      
  def split_ranks(cards, indexes):
      for index in indexes:
          a, b = cards[:index], cards[index:]
          if same_rank(a) and same_rank(b):
              return True
      return False
      
  def is_full_house(cards):
      return split_ranks(cards, (2, 3))
      
  def is_four(cards):
      return split_ranks(cards, (1, 4))
      
  def is_pat(cards):
      return is_straight(cards) or is_flush(cards) or is_full_house(cards) or is_four(cards)
      
  def is_straight_flush(cards):
      return is_straight(cards) and is_flush(cards)
      
  def rank_count(cards):
      result = {}
      for card in cards:
          r = rank_int(card)
          result[r] = result.get(r, 0) + 1
      return result
      
  def is_three(cards, counts=None):
      counts = counts or rank_count(cards)
      for rank, count in counts.iteritems():
          if count == 3:
              return True
      return False
      
  def is_two_pair(cards, counts=None):
      pairs = 0
      counts = counts or rank_count(cards)
      for rank, count in counts.iteritems():
          if count == 2:
              pairs += 1
      return pairs == 2
      
  def is_pair(cards, counts=None):
      counts = counts or rank_count(cards)
      for rank, count in counts.iteritems():
          if count == 2:
              return True
      return False
      
  def get_ranks(counts):
      values = [(count, rank) for rank, count in counts.iteritems()]
      values.sort(reverse=True)
      values = [n[1] for n in values]
      return values
      
  def get_straight_rank(cards):
      top = rank_int(cards[-1])
      bottom = rank_int(cards[0])
      if top == 12 and bottom == 0:
          return 3
      return top
      
  def evaluate_hand(cards):
      flush = is_flush(cards)
      straight = is_straight(cards)
      counts = rank_count(cards)
      ranks = get_ranks(counts)
      if straight:
          ranks = [get_straight_rank(cards)]
      if straight and flush:
          value = 9
      elif is_four(cards):
          value = 8
      elif is_full_house(cards):
          value = 7
      elif flush:
          value = 6
      elif straight:
          value = 5
      elif is_three(cards, counts):
          value = 4
      elif is_two_pair(cards, counts):
          value = 3
      elif is_pair(cards, counts):
          value = 2
      else:
          value = 1
      ranks.insert(0, value)
      return tuple(ranks)
  