text: """Display game events on ledbar
  
  Usage:
    munerator [options] ledbar
  
  Options:
    -v --verbose          Verbose logging
    --context-socket url  ZMQ socket for context events [default: tcp://quake.brensen.com:9002]
    --ledbar-api url      URL to ledbar api [default: http://10.110.0.119/led/{led}/{color_code}]
    --numleds num         Number of leds in the bar to use [default: 19]
  
  """
  import collections
  import itertools
  import json
  import logging
  import urllib2
  from functools import partial
  
  import zmq
  from docopt import docopt
  from webcolors import name_to_hex
  
  log = logging.getLogger(__name__)
  
  
  class Ledbar(object):
  
      def __init__(self, numleds, ledbar_api):
          self.prev_state = ['#000000'] * numleds
          self.ledbar_api = ledbar_api
          self.numleds = numleds
  
      def api_call(self, url):
          try:
              urllib2.urlopen(url, timeout=0.5)
          except:
              log.debug('urlopen failed')
  
      def update_leds(self, state):
          for i, color in enumerate(state):
              if not color.startswith('#'):
                  color = name_to_hex(color)
  
              if color != self.prev_state[i]:
                  led = self.numleds - (i + 1)
                  color_code = color.lstrip('#')
  
                  url = self.ledbar_api.format(led=led, color_code=color_code)
                  log.debug('url: %s' % url)
                  self.api_call(url)
  
              self.prev_state[i] = color
  
  
  def update_ledbar(in_socket, numleds, ledbar):
      ids = None
  
      while True:
          msg = in_socket.recv_string()
  
          log.debug('got : %s' % msg)
          data = json.loads(msg.split(' ', 1)[-1])
          kind = data.get('kind')
          client_id = data.get('client_id', '')
  
          if kind == 'initgame' or ids is None:
              ids = collections.defaultdict(itertools.count().next)
              num_players = data.get('game_info', {}).get('num_players', 0)
              state = ['white'] * num_players + ['black'] * (numleds - num_players)
          elif client_id.isdigit() and int(client_id) < numleds:
              s = state[ids[int(client_id)]]
              if kind == 'clientbegin':
                  team = data.get('client_info', {}).get('team')
                  if team and team in ['red', 'blue']:
                      s = team
                  else:
                      s = 'white'
              elif kind == 'hit':
                  if s in ['cyan', 'invisible']:
                      continue
                  health = int(data.get('health'))
                  if health < 50:
                      s = 'orange'
                  elif health < 25:
                      s = 'orangered'
              elif kind == 'quad':
                  s = 'cyan'
              elif kind == 'invisible':
                  s = 'black'
              elif kind == 'clientdisconnect':
                  s = '#212121'
              state[ids[int(client_id)]] = s
          elif kind == 'killer':
              state[ids[int(client_id)]] = 'green'
          elif kind == 'killed':
              state[ids[int(client_id)]] = 'red'
  
          ledbar.update_leds(state)
  
  
  def main(argv):
      args = docopt(__doc__, argv=argv)
  
      context = zmq.Context()
      in_socket = context.socket(zmq.SUB)
      in_socket.connect(args['--context-socket'])
  
      filters = ['initgame', 'shutdowngame', 'clientdisconnect', 'quad',
                 'clientbegin', 'clientuserinfochanged', 'hit', 'kill']
      add_filter = partial(in_socket.setsockopt, zmq.SUBSCRIBE)
      map(add_filter, filters)
  
      numleds = int(args['--numleds'])
      ledbar_api = args['--ledbar-api']
  
      ledbar = Ledbar(numleds, ledbar_api)
  
      update_ledbar(in_socket, numleds, ledbar)
  