text: from datetime import datetime
  from itertools import count
  import random
  import string
  import basehash
          
  class Format:
      def __init__(self, channel_id, *args, **kwargs):
          self.__id = 0
          self.__channel_id = channel_id
          self.roles = [None, "Test", "More Test"]
          self.name = "Pickup"
          self.teams = 2
          
  
  def role_to_key(role):
      return role.upper() if role else role        
  
  class Pickup:
      __base36 = basehash.base36(4)
      __new_ids = {None:count()}
      __id_shifts = {None:random.randrange(__base36.maximum)}
      __default_format = Format(0)
  
      def __init__(self, channel_id, name = None, format = __default_format, timestamp = None):
          self.__id = Pickup.__gen_id(channel_id)
          self.__channel_id = channel_id
          if timestamp:
              self.timestamp = timestamp
          else:
              self.timestamp = datetime.now()
          if name:
              self.name = name
          else:
              self.name = format.name
          self.__teams = [Team() for i in range(format.teams)]
          self.__roles = {role_to_key(role) : role for role in format.roles}
          self.__players = {role_to_key(role):set() for role in format.roles}
      
      
      
      @classmethod
      def __gen_id(cls, c_id):
          if not c_id in cls.__new_ids:
              cls.__new_ids[c_id] = count()
          return next(cls.__new_ids[c_id])
      
      @classmethod
      def __id_shift(cls, c_id):
          if not c_id in cls.__id_shifts:
              cls.__id_shifts[c_id] = random.randrange(cls.__base36.maximum)
          return cls.__id_shifts[c_id]
      
      @classmethod
      def __pub_id(cls, id, c_id):
          return cls.__base36.hash((id + cls.__id_shift(c_id)) % cls.__base36.maximum)
         
         
          
      @property  
      def id(self):
          return Pickup.__pub_id(self.__id, self.__channel_id)
      
      @property
      def name_and_id(self):
          return self.name + ' (' + self.id + ')'
      
      @property  
      def channel_id(self):
          return self.__channel_id
      
      @property
      def unique_id(self):
          return str(self.__channel_id) + '-' + self.id
      
      
      
      @property
      def teams(self):
          return self.__teams
      
      def add_team(self):
          self.__teams.append(Team())
      
      def add_teams(self, num):
          for i in range(num):
              self.add_team()
      
      def remove_team(self, team):
          del self.__teams[team]
      
      def remove_teams(self, teams):
          for team in teams:
              self.remove_team(team)
          
      def add_player_to_team(self, player, team):
          if team in range(len(self.__teams)):
              self.__teams[team].add_player(player)
          
      def add_players_to_team(self, players, team):
          if team in range(len(self.__teams)):
              self.__teams[team].add_players(players)
          
      def remove_player_from_team(self, player, team = None):
          if team == None:
              for team in self.__teams:
                  team.remove_player(player)
          elif team in range(len(self.__teams)):
              self.__teams[team].remove_player(player)
          
      def remove_players_from_team(self, players, team = None):
          if team == None:
              for team in self.__teams:
                  team.remove_players(players)
          elif team in range(len(self.__teams)):
              self.__teams[team].remove_players(players)
          
      def add_captain(self, player, team):
          if team in range(len(self.__teams)):
              self.__teams.captain = player
          
      def remove_captain(self, team = None, player = None):
          if player and team:
              if team in range(len(self.__teams)) and self.__teams[team].captain == player:
                  self.__teams[team].captain = None
          elif team:
              if team in range(len(self.__teams)):
                  self.__teams[team].captain = None
          elif player:
              for team in self.__teams:
                  if team.captain == player:
                      team.captain = None
      
      
      
      @property  
      def players(self):
          return set().union(*[self.__players[role_key] for role_key in self.__players])
          
      def players_in(self, role):
          if role_to_key(role) in self.__players:
              return self.__players[role_to_key(role)]
          else:
              return set()
      
      @property  
      def picked_players(self):
          return set().union(*[team.players for team in self.__teams])
      
      @property  
      def unpicked_players(self):
          return self.players - self.picked_players
      
      def unpicked_players_in(self, role):
          return self.players_in(role) - self.picked_players
      
      @property
      def players_in_no_role(self):
          return self.players_in(None)
      
      @property
      def players_in_any_role(self):
          return set().union(*[self.__players[role_key] if role_key else set() for role_key in self.__players])
          
      def add_player(self, player, roles = None):
          if roles:
              for role in roles:
                  role_key = role_to_key(role)
                  if role_key in self.__players:
                      self.__players[role_key].add(player)
              #don't allow player to be in both a role and no role list
              if player in self.players_in_no_role and player in self.players_in_any_role:
                  self.__players[None].discard(player)
          elif len(self.roles) == 1:
              #add player to only role
              self.__players[role_to_key(list(self.roles)[0])].add(player)
          elif None in self.__players and player not in self.players:
              #add player to no role list if it exists and player isn't already added
              self.__players[None].add(player)
          
      def add_players(self, players, roles = None):
          for player in players:
              self.add_players(player, roles)
          
      def remove_player(self, player, roles = None):
          if not roles:
              for role_key in self.__players:
                  self.__players[role_key].discard(player)
              self.remove_player_from_team(player)
          else:
              for role in roles:
                  role_key = role_to_key(role)
                  if role_key in self.__players:
                      self.__players[role_key].discard(player)
              if None not in roles and player not in self.players and None in self.__players:
                  self.__players[None].add(player)
                  
          
      def remove_players(self, player, roles = None):
          for player in players:
              self.remove_player(player, roles)
              
              
              
      @property
      def roles(self):
          return set(self.__roles.values())
          
      def has_role(self, role):
          return role_to_key(role) in self.__roles
          
      def add_role(self, role):
          role_key = role_to_key(role)
          if not key in self.__roles:
              self.__players[role_key] = set()
              self.__roles[role_key] = role
          
      def remove_role(self, role):
          role_key = role_to_key(role)
          if role_key in self.__players:
              del self.__players[role_key]
              del self.__roles[role_key]
              
              
              
  class Team:
      def __init__(self, captain = None):
          self.__players = set()
          self.__captain = captain
          
          
          
      @property
      def captain(self):
          return self.__captain
          
      @captain.setter
      def captain(self, captain):
          if captain:
              self.__players.add(captain)
          self.__captain = captain
          
          
          
      @property
      def players(self):
          return self.__players
          
      @property
      def picked_players(self):
          return self.__players - {captain}
          
      def add_player(self, player):
          self.__players.add(player)
          
      def remove_player(self, player):
          self.__players.discard(player)
          
      def add_players(self, players):
          self.__players |= set(players)
          
      def remove_players(self, players):
          self.__players -= set(players)
          