diff --git a/.gitignore b/.gitignore
index db4561ea..0216c2ed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,53 +2,5 @@
 __pycache__/
 *.py[cod]
 
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-env/
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-*.egg-info/
-.installed.cfg
-*.egg
-
-# PyInstaller
-#  Usually these files are written by a python script from a template
-#  before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.coverage
-.cache
-nosetests.xml
-coverage.xml
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-target/
+# Log files
+*.log
\ No newline at end of file
diff --git a/data/sites.json b/data/sites.json
new file mode 100644
index 00000000..e02aef27
--- /dev/null
+++ b/data/sites.json
@@ -0,0 +1,2 @@
+{
+}
\ No newline at end of file
diff --git a/log/empty.txt b/log/empty.txt
new file mode 100644
index 00000000..63f6d20a
--- /dev/null
+++ b/log/empty.txt
@@ -0,0 +1 @@
+Place for log files.
\ No newline at end of file
diff --git a/src/Config.py b/src/Config.py
new file mode 100644
index 00000000..dc455d91
--- /dev/null
+++ b/src/Config.py
@@ -0,0 +1,129 @@
+import argparse, sys, os, time
+import ConfigParser
+
+class Config(object):
+	def __init__(self):
+		self.version = "0.1"
+		self.parser = self.createArguments()
+		argv = sys.argv[:] # Copy command line arguments
+		argv = self.parseConfig(argv) # Add arguments from config file
+		self.parseCommandline(argv) # Parse argv
+		self.setAttributes()
+
+
+	def __str__(self):
+		return str(self.arguments).replace("Namespace", "Config") # Using argparse str output
+
+
+	# Create command line arguments
+	def createArguments(self):
+		# Platform specific
+		if sys.platform.startswith("win"):
+			upnpc = "tools\\upnpc\\upnpc-static.exe"
+			coffeescript = "type %s | tools\\coffee\\coffee.cmd"
+		else:
+			upnpc = None
+			coffeescript = None
+
+		# Create parser
+		parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+		subparsers = parser.add_subparsers(title="Action to perform", dest="action")
+
+		# Main
+		action = subparsers.add_parser("main", help='Start UiServer and FileServer (default)')
+
+		# SiteCreate
+		action = subparsers.add_parser("siteCreate", help='Create a new site')
+
+		# SiteSign
+		action = subparsers.add_parser("siteSign", help='Update and sign content.json: address [privatekey]')
+		action.add_argument('address', 		help='Site to sign')
+		action.add_argument('privatekey',	help='Private key (default: ask on execute)', nargs='?')
+
+		# SitePublish
+		action = subparsers.add_parser("sitePublish", help='Publish site to other peers: address')
+		action.add_argument('address', 		help='Site to publish')
+
+		# SiteVerify
+		action = subparsers.add_parser("siteVerify", help='Verify site files using md5: address')
+		action.add_argument('address', 		help='Site to verify')
+
+
+		# Config parameters
+		parser.add_argument('--debug', 			help='Debug mode', action='store_true')
+
+		parser.add_argument('--ui_ip', 			help='Web interface bind address', default="127.0.0.1", metavar='host')
+		parser.add_argument('--ui_port', 		help='Web interface bind port', default=43110, metavar='port')
+		parser.add_argument('--ui_restrict',	help='Restrict web access', default=False, metavar='ip')
+		parser.add_argument('--homepage',		help='Web interface Homepage', default='1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr', metavar='address')
+
+		parser.add_argument('--fileserver_ip', 	help='FileServer bind address', default="*", metavar='host')
+		parser.add_argument('--fileserver_port',help='FileServer bind port', default=15441, metavar='port')
+
+		parser.add_argument('--ip_external',	help='External ip (tested on start if None)', metavar='ip')
+		parser.add_argument('--upnpc',			help='MiniUPnP binary for open port on router', default=upnpc, metavar='executable_path')
+
+		parser.add_argument('--coffeescript_compiler',	help='Coffeescript compiler for developing', default=coffeescript, metavar='executable_path')
+
+		parser.add_argument('--version', 	action='version', version='ZeroNet %s' % self.version)
+
+		return parser
+
+
+	# Find arguments specificed for current action
+	def getActionArguments(self):
+		back = {}
+		arguments = self.parser._subparsers._group_actions[0].choices[self.action]._actions[1:] # First is --version
+		for argument in arguments:
+			back[argument.dest] = getattr(self, argument.dest)
+		return back
+
+
+
+	# Try to find action from sys.argv
+	def getAction(self, argv):
+		actions = [action.choices.keys() for action in self.parser._actions if action.dest == "action"][0] # Valid actions
+		found_action = False
+		for action in actions: # See if any in sys.argv
+			if action in argv:
+				found_action = action
+				break
+		return found_action
+
+
+	# Parse command line arguments
+	def parseCommandline(self, argv):
+		# Find out if action is specificed on start
+		action = self.getAction(argv)
+		if len(argv) == 1 or not action: # If no action specificed set the main action
+			argv.append("main")
+		if "zeronet.py" in argv[0]:
+			self.arguments = self.parser.parse_args(argv[1:])
+		else: # Silent errors if not started with zeronet.py
+			self.arguments = self.parser.parse_args(argv[1:])
+
+
+	# Parse config file
+	def parseConfig(self, argv):
+		if os.path.isfile("zeronet.conf"):
+			config = ConfigParser.ConfigParser(allow_no_value=True)
+			config.read('zeronet.conf')
+			for section in config.sections():
+				for key, val in config.items(section):
+					if section != "global": # If not global prefix key with section
+						key = section+"_"+key
+					if val: argv.insert(1, val)
+					argv.insert(1, "--%s" % key)
+		return argv
+
+
+
+	# Expose arguments as class attributes
+	def setAttributes(self):
+		# Set attributes from arguments
+		args = vars(self.arguments)
+		for key, val in args.items():
+			setattr(self, key, val)
+
+
+config = Config()
diff --git a/src/Crypt/CryptBitcoin.py b/src/Crypt/CryptBitcoin.py
new file mode 100644
index 00000000..f7ba209f
--- /dev/null
+++ b/src/Crypt/CryptBitcoin.py
@@ -0,0 +1,26 @@
+from src.lib.BitcoinECC import BitcoinECC
+import hashlib
+
+
+def newPrivatekey(): # Return new private key
+	bitcoin = BitcoinECC.Bitcoin()
+	bitcoin.GeneratePrivateKey()
+	return bitcoin.PrivateEncoding() 
+
+
+def privatekeyToAddress(privatekey): # Return address from private key
+	bitcoin = BitcoinECC.Bitcoin()
+	bitcoin.BitcoinAddressFromPrivate(privatekey)
+	return bitcoin.BitcoinAddresFromPublicKey()
+
+
+def sign(data, privatekey): # Return sign to data using private key
+	bitcoin = BitcoinECC.Bitcoin()
+	bitcoin.BitcoinAddressFromPrivate(privatekey)
+	sign = bitcoin.SignECDSA(data)
+	return sign
+
+
+def verify(data, address, sign): # Verify data using address and sign
+	bitcoin = BitcoinECC.Bitcoin()
+	return bitcoin.VerifyMessageFromBitcoinAddress(address, data, sign)
diff --git a/src/Crypt/CryptHash.py b/src/Crypt/CryptHash.py
new file mode 100644
index 00000000..e2d202a6
--- /dev/null
+++ b/src/Crypt/CryptHash.py
@@ -0,0 +1,18 @@
+import hashlib
+
+def sha1sum(file, blocksize=65536):
+	if hasattr(file, "endswith"): # Its a string open it
+		file = open(file, "rb")
+	hash = hashlib.sha1()
+	for block in iter(lambda: file.read(blocksize), ""):
+		hash.update(block)
+	return hash.hexdigest()
+
+
+if __name__ == "__main__":
+	import cStringIO as StringIO
+	a = StringIO.StringIO()
+	a.write("hello!")
+	a.seek(0)
+	print hashlib.sha1("hello!").hexdigest()
+	print sha1sum(a)
\ No newline at end of file
diff --git a/src/Crypt/__init__.py b/src/Crypt/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/Debug/DebugHook.py b/src/Debug/DebugHook.py
new file mode 100644
index 00000000..d03e7fb9
--- /dev/null
+++ b/src/Debug/DebugHook.py
@@ -0,0 +1,22 @@
+import gevent, sys
+
+last_error = None
+def handleError(*args):
+	global last_error
+	if not args: # Get last error
+		args = sys.exc_info()
+		silent = True
+	else:
+		silent = False
+	print "Error catched", args
+	last_error = args
+	if not silent: sys.__excepthook__(*args)
+
+OriginalGreenlet = gevent.Greenlet
+class ErrorhookedGreenlet(OriginalGreenlet):
+	def _report_error(self, exc_info):
+		handleError(exc_info[0], exc_info[1], exc_info[2])
+
+sys.excepthook = handleError
+gevent.Greenlet = gevent.greenlet.Greenlet = ErrorhookedGreenlet
+reload(gevent)
\ No newline at end of file
diff --git a/src/Debug/DebugMedia.py b/src/Debug/DebugMedia.py
new file mode 100644
index 00000000..84f48dc2
--- /dev/null
+++ b/src/Debug/DebugMedia.py
@@ -0,0 +1,60 @@
+import os, subprocess, re, logging, time
+from Config import config
+
+# Find files with extension in path
+def findfiles(path, find_ext):
+	for root, dirs, files in os.walk(path, topdown = False):
+		for file in sorted(files):
+			file_path = root+"/"+file
+			file_ext = file.split(".")[-1]
+			if file_ext in find_ext and not file.startswith("all."): yield file_path
+
+
+# Generates: all.js: merge *.js, compile coffeescript, all.css: merge *.css, vendor prefix features
+def merge(merged_path):
+	merge_dir = os.path.dirname(merged_path)
+	s = time.time()
+	ext = merged_path.split(".")[-1]
+	if ext == "js": # If merging .js find .coffee too
+		find_ext = ["js", "coffee"]
+	else:
+		find_ext = [ext]
+
+	# If exits check the other files modification date
+	if os.path.isfile(merged_path): 
+		merged_mtime = os.path.getmtime(merged_path)
+		changed = False
+		for file_path in findfiles(merge_dir, find_ext):
+			if os.path.getmtime(file_path) > merged_mtime: 
+				changed = True
+				break
+		if not changed: return # Assets not changed, nothing to do
+
+	# Merge files
+	parts = []
+	for file_path in findfiles(merge_dir, find_ext):
+		parts.append("\n\n/* ---- %s ---- */\n\n" % file_path)
+		if file_path.endswith(".coffee"): # Compile coffee script
+			if not config.coffeescript_compiler: 
+				logging.error("No coffeescript compiler definied, skipping compiling %s" % merged_path)
+				return False # No coffeescript compiler, skip this file
+			command = config.coffeescript_compiler % file_path.replace("/", "\\")
+			s = time.time()
+			compiler = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+			logging.debug("Running: %s (Done in %.2fs)" % (command, time.time()-s))
+			source = compiler.stdout.read()
+			if source:
+				parts.append(source)
+			else:
+				error = compiler.stderr.read()
+				parts.append("alert('%s compile error: %s');" % (file_path, re.escape(error)) )
+		else: # Add to parts
+			parts.append(open(file_path).read())
+
+	merged = "\n".join(parts)
+	if ext == "css": # Vendor prefix css
+		from lib.cssvendor import cssvendor
+		merged = cssvendor.prefix(merged)
+	merged = merged.replace("\r", "")
+	open(merged_path, "wb").write(merged)
+	logging.debug("Merged %s (%.2fs)" % (merged_path, time.time()-s))
diff --git a/src/Debug/DebugReloader.py b/src/Debug/DebugReloader.py
new file mode 100644
index 00000000..dac6975e
--- /dev/null
+++ b/src/Debug/DebugReloader.py
@@ -0,0 +1,35 @@
+import logging, os, sys, time
+import threading
+
+try:
+	from fs.osfs import OSFS 
+	pyfilesystem = OSFS("src")
+except Exception, err:
+	logging.info("%s: For autoreload please download pyfilesystem (https://code.google.com/p/pyfilesystem/)" % err)
+	pyfilesystem = False
+
+
+class DebugReloader:
+	def __init__ (self, callback, directory = "/"):
+		if pyfilesystem:
+			self.directory = directory
+			self.callback = callback
+			logging.debug("Adding autoreload: %s, cb: %s" % (directory, callback))
+			thread = threading.Thread(target=self.addWatcher)
+			thread.daemon = True
+			thread.start()
+
+
+	def addWatcher(self, recursive=True):
+		try:
+			time.sleep(1) # Wait for .pyc compiles
+			pyfilesystem.add_watcher(self.changed, path=self.directory, events=None, recursive=recursive)
+		except Exception, err:
+			print "File system watcher failed: %s (on linux pyinotify not gevent compatible yet :( )" % err
+
+
+	def changed(self, evt):
+		if not evt.path or evt.path.endswith("pyc"): return False # Ignore *.pyc changes
+		#logging.debug("Changed: %s" % evt)
+		time.sleep(0.1) # Wait for lock release
+		self.callback()
diff --git a/src/Debug/__init__.py b/src/Debug/__init__.py
new file mode 100644
index 00000000..8632f92f
--- /dev/null
+++ b/src/Debug/__init__.py
@@ -0,0 +1 @@
+from DebugReloader import DebugReloader
\ No newline at end of file
diff --git a/src/File/FileRequest.py b/src/File/FileRequest.py
new file mode 100644
index 00000000..df655bda
--- /dev/null
+++ b/src/File/FileRequest.py
@@ -0,0 +1,98 @@
+import os, msgpack, shutil
+from Site import SiteManager
+from cStringIO import StringIO
+
+FILE_BUFF = 1024*512
+
+# Request from me
+class FileRequest:
+	def __init__(self, server = None):
+		if server:
+			self.server = server
+			self.log = server.log
+		self.sites = SiteManager.list()
+
+
+	def send(self, msg):
+		if not isinstance(msg, dict): # If msg not a dict create a {"body": msg}
+			msg = {"body": msg}
+		self.server.socket.send(msgpack.packb(msg, use_bin_type=True))
+
+
+	# Route file requests
+	def route(self, cmd, params):
+		if cmd == "getFile":
+			self.actionGetFile(params)
+		elif cmd == "update":
+			self.actionUpdate(params)
+		elif cmd == "ping":
+			self.actionPing()
+		else:
+			self.actionUnknown(cmd, params)
+
+
+	# Update a site file request
+	def actionUpdate(self, params):
+		site = self.sites.get(params["site"])
+		if not site or not site.settings["serving"]: # Site unknown or not serving
+			self.send({"error": "Unknown site"})
+			return False
+		if site.settings["own"]:
+			self.log.debug("Someone trying to push a file to own site %s, reload local content.json first" % site.address)
+			site.loadContent()
+		buff = StringIO(params["body"])
+		valid = site.verifyFile(params["inner_path"], buff)
+		if valid == True: # Valid and changed
+			buff.seek(0)
+			file = open(site.getPath(params["inner_path"]), "wb")
+			shutil.copyfileobj(buff, file) # Write buff to disk
+			file.close()
+
+			if params["inner_path"] == "content.json": # Download every changed file from peer
+				changed = site.loadContent() # Get changed files
+				peer = site.addPeer(*params["peer"], return_peer = True) # Add or get peer
+				self.log.info("%s changed files: %s" % (site.address_short, changed))
+				for inner_path in changed: # Updated files in content.json
+					site.needFile(inner_path, peer=peer, update=True, blocking=False) # Download file from peer
+				site.onComplete.once(lambda: site.publish()) # On complete publish to other peers
+
+			self.send({"ok": "Thanks, file %s updated!" % params["inner_path"]})
+
+		elif valid == None: # Not changed
+			peer = site.addPeer(*params["peer"], return_peer = True) # Add or get peer
+			for task in site.worker_manager.tasks: # New peer add to every ongoing task
+				site.needFile(task["inner_path"], peer=peer, update=True, blocking=False) # Download file from peer
+
+			self.send({"ok": "File file not changed"})
+
+		else: # Invalid sign or sha1 hash
+			self.send({"error": "File invalid"})
+
+
+	# Send file content request
+	def actionGetFile(self, params):
+		site = self.sites.get(params["site"])
+		if not site or not site.settings["serving"]: # Site unknown or not serving
+			self.send({"error": "Unknown site"})
+			return False
+		try:
+			file = open(site.getPath(params["inner_path"]), "rb")
+			file.seek(params["location"])
+			back = {}
+			back["body"] = file.read(FILE_BUFF)
+			back["location"] = file.tell()
+			back["size"] = os.fstat(file.fileno()).st_size
+			self.send(back)
+		except Exception, err:
+			self.send({"error": "File read error: %s" % err})
+			return False
+
+
+	# Send a simple Pong! answer
+	def actionPing(self):
+		self.send("Pong!")
+
+
+	# Unknown command
+	def actionUnknown(self, cmd, params):
+		self.send({"error": "Unknown command: %s" % cmd})
diff --git a/src/File/FileServer.py b/src/File/FileServer.py
new file mode 100644
index 00000000..dce3d8b7
--- /dev/null
+++ b/src/File/FileServer.py
@@ -0,0 +1,165 @@
+import os, logging, urllib2, urllib, re, time
+import gevent, msgpack
+import zmq.green as zmq
+from Config import config
+from FileRequest import FileRequest
+from Site import SiteManager
+
+
+class FileServer:
+	def __init__(self):
+		self.ip = config.fileserver_ip
+		self.port = config.fileserver_port
+		self.log = logging.getLogger(__name__)
+		if config.ip_external: # Ip external definied in arguments
+			self.port_opened = True
+			SiteManager.peer_blacklist.append((config.ip_external, self.port)) # Add myself to peer blacklist
+		else:
+			self.port_opened = None # Is file server opened on router
+		self.sites = SiteManager.list()
+
+
+	# Handle request to fileserver
+	def handleRequest(self, msg):
+		if "params" in msg:
+			self.log.debug("FileRequest: %s %s %s" % (msg["cmd"], msg["params"].get("site"), msg["params"].get("inner_path")))
+		else:
+			self.log.debug("FileRequest: %s" % msg["cmd"])
+		req = FileRequest(self)
+		req.route(msg["cmd"], msg.get("params"))
+
+
+	# Reload the FileRequest class to prevent restarts in debug mode
+	def reload(self):
+		global FileRequest
+		import imp
+		FileRequest = imp.load_source("FileRequest", "src/File/FileRequest.py").FileRequest
+
+
+	# Try to open the port using upnp
+	def openport(self, port=None, check=True):
+		if not port: port = self.port
+		if self.port_opened: return True # Port already opened
+		if check: # Check first if its already opened
+			if self.testOpenport(port)["result"] == True:
+				return True # Port already opened
+
+		if config.upnpc: # If we have upnpc util, try to use it to puch port on our router
+			self.log.info("Try to open port using upnpc...")
+			try:
+				exit = os.system("%s -e ZeroNet -r %s tcp" % (config.upnpc, self.port))
+				if exit == 0:
+					upnpc_success = True
+				else:
+					upnpc_success = False
+			except Exception, err:
+				self.log.error("Upnpc run error: %s" % err)
+				upnpc_success = False
+
+			if upnpc_success and self.testOpenport(port)["result"] == True:
+				return True
+
+		self.log.info("Upnp mapping failed :( Please forward port %s on your router to your ipaddress" % port)
+		return False
+
+
+	# Test if the port is open
+	def testOpenport(self, port = None):
+		time.sleep(1) # Wait for port open
+		if not port: port = self.port
+		self.log.info("Checking port %s using canyouseeme.org..." % port)
+		try:
+			data = urllib2.urlopen("http://www.canyouseeme.org/", "port=%s" % port, timeout=20.0).read()
+			message = re.match('.*<p style="padding-left:15px">(.*?)</p>', data, re.DOTALL).group(1)
+			message = re.sub("<.*?>", "", message.replace("<br>", " ").replace("&nbsp;", " ")) # Strip http tags
+		except Exception, err:
+			message = "Error: %s" % err
+		if "Error" in message:
+			self.log.info("[BAD :(] Port closed: %s" % message)
+			if port == self.port: 
+				self.port_opened = False # Self port, update port_opened status
+				config.ip_external = False
+			return {"result": False, "message": message}
+		else:
+			self.log.info("[OK :)] Port open: %s" % message)
+			if port == self.port: # Self port, update port_opened status
+				self.port_opened = True
+				match = re.match(".*?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)", message) # Try find my external ip in message
+				if match: # Found my ip in message
+					config.ip_external = match.group(1)
+					SiteManager.peer_blacklist.append((config.ip_external, self.port)) # Add myself to peer blacklist
+				else:
+					config.ip_external = False
+			return {"result": True, "message": message}
+
+
+	# Set external ip without testing
+	def setIpExternal(self, ip_external):
+		logging.info("Setting external ip without testing: %s..." % ip_external)
+		config.ip_external = ip_external
+		self.port_opened = True
+
+
+	# Check site file integrity
+	def checkSite(self, site):
+		if site.settings["serving"]:
+			site.announce() # Announce site to tracker
+			site.update() # Update site's content.json and download changed files
+
+
+	# Check sites integrity
+	def checkSites(self):
+		if self.port_opened == None: # Test and open port if not tested yet
+			self.openport()
+
+		self.log.debug("Checking sites integrity..")
+		for address, site in self.sites.items(): # Check sites integrity
+			gevent.spawn(self.checkSite, site) # Check in new thread
+			time.sleep(2) # Prevent too quick request
+
+
+	# Announce sites every 10 min
+	def announceSites(self):
+		while 1:
+			time.sleep(10*60) # Announce sites every 10 min
+			for address, site in self.sites.items():
+				if site.settings["serving"]:
+					site.announce() # Announce site to tracker
+				time.sleep(2) # Prevent too quick request
+
+
+	# Bind and start serving sites
+	def start(self, check_sites = True):
+		self.log = logging.getLogger(__name__)
+
+		if config.debug:
+			# Auto reload FileRequest on change
+			from Debug import DebugReloader
+			DebugReloader(self.reload)
+
+		self.context = zmq.Context()
+		socket = self.context.socket(zmq.REP)
+		self.socket = socket
+		self.socket.setsockopt(zmq.RCVTIMEO, 5000) # Wait for data receive
+		self.log.info("Binding to tcp://%s:%s" % (self.ip, self.port))
+		try:
+			self.socket.bind('tcp://%s:%s' % (self.ip, self.port))
+		except Exception, err:
+			self.log.error("Can't bind, FileServer must be running already")
+			return
+		if check_sites: # Open port, Update sites, Check files integrity
+			gevent.spawn(self.checkSites)
+
+		gevent.spawn(self.announceSites)
+
+		while True:
+			try:
+				ret = {}
+				req = msgpack.unpackb(socket.recv())
+				self.handleRequest(req)
+			except Exception, err:
+				self.log.error(err)
+				self.socket.send(msgpack.packb({"error": "%s" % err}, use_bin_type=True))
+				if config.debug: # Raise exception
+					import sys
+					sys.excepthook(*sys.exc_info())
diff --git a/src/File/__init__.py b/src/File/__init__.py
new file mode 100644
index 00000000..20b28a97
--- /dev/null
+++ b/src/File/__init__.py
@@ -0,0 +1,2 @@
+from FileServer import FileServer
+from FileRequest import FileRequest
\ No newline at end of file
diff --git a/src/Peer/Peer.py b/src/Peer/Peer.py
new file mode 100644
index 00000000..e14aceaf
--- /dev/null
+++ b/src/Peer/Peer.py
@@ -0,0 +1,84 @@
+import os, logging, gevent, time, msgpack
+import zmq.green as zmq
+from cStringIO import StringIO
+from Config import config
+
+context = zmq.Context()
+
+# Communicate remote peers
+class Peer:
+	def __init__(self, ip, port):
+		self.ip = ip
+		self.port = port
+		self.socket = None
+		self.last_found = None
+		self.added = time.time()
+
+		self.hash_failed = 0
+		self.download_bytes = 0
+		self.download_time = 0
+
+
+	# Connect to host
+	def connect(self):
+		self.log = logging.getLogger("Peer:%s:%s" % (self.ip, self.port))
+		self.socket = context.socket(zmq.REQ)
+		self.socket.setsockopt(zmq.SNDTIMEO, 5000) # Wait for data send
+		self.socket.setsockopt(zmq.LINGER, 500) # Wait for socket close
+		self.socket.connect('tcp://%s:%s' % (self.ip, self.port))
+
+
+	# Done working with peer
+	def disconnect(self):
+		pass
+
+
+	# Found a peer on tracker
+	def found(self):
+		self.last_found = time.time()
+
+
+	# Send a command to peer
+	def sendCmd(self, cmd, params = {}):
+		if not self.socket: self.connect()
+		try:
+			self.socket.send(msgpack.packb({"cmd": cmd, "params": params}, use_bin_type=True))
+			response = msgpack.unpackb(self.socket.recv())
+			if "error" in response:
+				self.log.error("%s %s error: %s" % (cmd, params, response["error"]))
+			return response
+		except Exception, err:
+			self.log.error("%s" % err)
+			if config.debug:
+				import traceback
+				traceback.print_exc()
+			self.socket.close()
+			time.sleep(1)
+			self.connect()
+			return None
+
+
+	# Get a file content from peer
+	def getFile(self, site, inner_path):
+		location = 0
+		buff = StringIO()
+		s = time.time()
+		while 1: # Read in 512k parts
+			back = self.sendCmd("getFile", {"site": site, "inner_path": inner_path, "location": location}) # Get file content from last location
+			if "body" not in back: # Error
+				return False
+
+			buff.write(back["body"])
+			if back["location"] == back["size"]: # End of file
+				break
+			else:
+				location = back["location"]
+		self.download_bytes += back["location"]
+		self.download_time += (time.time() - s)
+		buff.seek(0)
+		return buff
+
+
+	# Send a ping request
+	def ping(self):
+		return self.sendCmd("ping")
diff --git a/src/Peer/__init__.py b/src/Peer/__init__.py
new file mode 100644
index 00000000..82110b81
--- /dev/null
+++ b/src/Peer/__init__.py
@@ -0,0 +1 @@
+from Peer import Peer
diff --git a/src/Site/Site.py b/src/Site/Site.py
new file mode 100644
index 00000000..396e6cdd
--- /dev/null
+++ b/src/Site/Site.py
@@ -0,0 +1,432 @@
+import os, json, logging, hashlib, re, time, string, random
+from lib.subtl.subtl import UdpTrackerClient
+import gevent
+import util
+from Config import config
+from Peer import Peer
+from Worker import WorkerManager
+from Crypt import CryptHash
+import SiteManager
+
+class Site:
+	def __init__(self, address, allow_create=True):
+
+		self.address = re.sub("[^A-Za-z0-9]", "", address) # Make sure its correct address
+		self.address_short = "%s..%s" % (self.address[:6], self.address[-4:]) # Short address for logging
+		self.directory = "data/%s" % self.address # Site data diretory
+		self.log = logging.getLogger("Site:%s" % self.address_short)
+
+		if not os.path.isdir(self.directory): 
+			if allow_create:
+				os.mkdir(self.directory) # Create directory if not found
+			else:
+				raise Exception("Directory not exists: %s" % self.directory)
+		self.content = None # Load content.json
+		self.peers = {} # Key: ip:port, Value: Peer.Peer
+		self.peer_blacklist = SiteManager.peer_blacklist # Ignore this peers (eg. myself)
+		self.last_announce = 0 # Last announce time to tracker
+		self.worker_manager = WorkerManager(self) # Handle site download from other peers
+		self.bad_files = {} # SHA1 check failed files, need to redownload
+		self.content_updated = None # Content.js update time
+		self.last_downloads = [] # Files downloaded in run of self.download()
+		self.notifications = [] # Pending notifications displayed once on page load [error|ok|info, message, timeout]
+		self.page_requested = False # Page viewed in browser
+
+		self.loadContent(init=True) # Load content.json
+		self.loadSettings() # Load settings from sites.json
+
+		if not self.settings.get("auth_key"):
+			self.settings["auth_key"] = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(12)) # To auth websocket
+			self.log.debug("New auth key: %s" % self.settings["auth_key"])
+			self.saveSettings()
+		self.websockets = [] # Active site websocket connections
+
+		# Add event listeners
+		self.addEventListeners()
+
+
+	# Load content.json to self.content
+	def loadContent(self, init=False):
+		old_content = self.content
+		content_path = "%s/content.json" % self.directory
+		if os.path.isfile(content_path): 
+			try:
+				new_content = json.load(open(content_path))
+			except Exception, err:
+				self.log.error("Content.json load error: %s" % err)
+				return None
+		else:
+			return None # Content.json not exits
+
+		try:
+			changed = []
+			for inner_path, details in new_content["files"].items():
+				new_sha1 = details["sha1"]
+				if old_content and old_content["files"].get(inner_path):
+					old_sha1 = old_content["files"][inner_path]["sha1"]
+				else:
+					old_sha1 = None
+				if old_sha1 != new_sha1: changed.append(inner_path)
+			self.content = new_content
+		except Exception, err:
+			self.log.error("Content.json parse error: %s" % err)
+			return None # Content.json parse error
+		# Add to bad files
+		if not init:
+			for inner_path in changed:
+				self.bad_files[inner_path] = True
+		return changed
+
+
+	# Load site settings from data/sites.json
+	def loadSettings(self):
+		sites_settings = json.load(open("data/sites.json"))
+		if self.address in sites_settings:
+			self.settings = sites_settings[self.address]
+		else:
+			if self.address == config.homepage: # Add admin permissions to homepage
+				permissions = ["ADMIN"]
+			else:
+				permissions = []
+			self.settings = { "own": False, "serving": True, "permissions": permissions } # Default
+		return
+
+
+	# Save site settings to data/sites.json
+	def saveSettings(self):
+		sites_settings = json.load(open("data/sites.json"))
+		sites_settings[self.address] = self.settings
+		open("data/sites.json", "w").write(json.dumps(sites_settings, indent=4, sort_keys=True))
+		return
+
+
+	# Sercurity check and return path of site's file
+	def getPath(self, inner_path):
+		inner_path = inner_path.replace("\\", "/") # Windows separator fix
+		inner_path = re.sub("^%s/" % re.escape(self.directory), "", inner_path) # Remove site directory if begins with it
+		file_path = self.directory+"/"+inner_path
+		allowed_dir = os.path.abspath(self.directory) # Only files within this directory allowed
+		if ".." in file_path or not os.path.dirname(os.path.abspath(file_path)).startswith(allowed_dir):
+			raise Exception("File not allowed: %s" % file_path)
+		return file_path
+
+
+	# Start downloading site
+	@util.Noparallel(blocking=False)
+	def download(self):
+		self.log.debug("Start downloading...")
+		self.announce()
+		found = self.needFile("content.json", update=self.bad_files.get("content.json"))
+		if not found: return False # Could not download content.json
+		self.loadContent() # Load the content.json
+		self.log.debug("Got content.json")
+		evts = []
+		self.last_downloads = ["content.json"] # Files downloaded in this run
+		for inner_path in self.content["files"].keys():
+			res = self.needFile(inner_path, blocking=False, update=self.bad_files.get(inner_path)) # No waiting for finish, return the event
+			if res != True: # Need downloading
+				self.last_downloads.append(inner_path)
+				evts.append(res) # Append evt
+		self.log.debug("Downloading %s files..." % len(evts))
+		s = time.time()
+		gevent.joinall(evts)
+		self.log.debug("All file downloaded in %.2fs" % (time.time()-s))
+
+
+	# Update content.json from peers and download changed files
+	@util.Noparallel()
+	def update(self):
+		self.loadContent() # Reload content.json
+		self.content_updated = None
+		self.needFile("content.json", update=True)
+		changed_files = self.loadContent()
+		if changed_files:
+			for changed_file in changed_files:
+				self.bad_files[changed_file] = True
+		self.checkFiles(quick_check=True) # Quick check files based on file size
+		if self.bad_files:
+			self.download()
+		return changed_files
+
+
+
+	# Update content.json on peers
+	def publish(self, limit=3):
+		self.log.info("Publishing to %s/%s peers..." % (limit, len(self.peers)))
+		published = 0
+		for key, peer in self.peers.items(): # Send update command to each peer
+			result = {"exception": "Timeout"}
+			try:
+				with gevent.Timeout(2, False): # 2 sec timeout
+					result = peer.sendCmd("update", {
+						"site": self.address, 
+						"inner_path": "content.json", 
+						"body": open(self.getPath("content.json")).read(),
+						"peer": (config.ip_external, config.fileserver_port)
+					})
+			except Exception, err:
+				result = {"exception": err}
+
+			if result and "ok" in result:
+				published += 1
+				self.log.info("[OK] %s: %s" % (key, result["ok"]))
+			else:
+				self.log.info("[ERROR] %s: %s" % (key, result))
+			
+			if published >= limit: break
+		self.log.info("Successfuly published to %s peers" % published)
+		return published
+
+
+	# Check and download if file not exits
+	def needFile(self, inner_path, update=False, blocking=True, peer=None):
+		if os.path.isfile(self.getPath(inner_path)) and not update: # File exits, no need to do anything
+			return True
+		elif self.settings["serving"] == False: # Site not serving
+			return False
+		else: # Wait until file downloaded
+			if not self.content: # No content.json, download it first!
+				self.log.debug("Need content.json first")
+				self.announce()
+				if inner_path != "content.json": # Prevent double download
+					task = self.worker_manager.addTask("content.json", peer)
+					task.get()
+					self.loadContent()
+					if not self.content: return False
+
+			task = self.worker_manager.addTask(inner_path, peer)
+			if blocking:
+				return task.get()
+			else:
+				return task
+
+
+	# Add or update a peer to site
+	def addPeer(self, ip, port, return_peer = False):
+		key = "%s:%s" % (ip, port)
+		if key in self.peers: # Already has this ip
+			self.peers[key].found()
+			if return_peer: # Always return peer
+				return self.peers[key]
+			else:
+				return False
+		else: # New peer
+			peer = Peer(ip, port)
+			self.peers[key] = peer
+			return peer
+
+
+	# Add myself and get other peers from tracker
+	def announce(self, force=False):
+		if time.time() < self.last_announce+15 and not force: return # No reannouncing within 15 secs
+		self.last_announce = time.time()
+
+		for protocol, ip, port in SiteManager.TRACKERS:
+			if protocol == "udp":
+				self.log.debug("Announing to %s://%s:%s..." % (protocol, ip, port))
+				tracker = UdpTrackerClient(ip, port)
+				tracker.peer_port = config.fileserver_port
+				try:
+					tracker.connect()
+					tracker.poll_once()
+					tracker.announce(info_hash=hashlib.sha1(self.address).hexdigest())
+					back = tracker.poll_once()
+				except Exception, err:
+					self.log.error("Tracker error: %s" % err)
+					continue
+				if back: # Tracker announce success
+					peers = back["response"]["peers"]
+					added = 0
+					for peer in peers:
+						if (peer["addr"], peer["port"]) in self.peer_blacklist: # Ignore blacklist (eg. myself)
+							continue
+						if self.addPeer(peer["addr"], peer["port"]): added += 1
+					if added:
+						self.worker_manager.onPeers()
+						self.updateWebsocket(peers_added=added)
+					self.log.debug("Found %s peers, new: %s" % (len(peers), added))
+					break # Successful announcing, break the list
+				else:
+					self.log.error("Tracker bad response, trying next in list...") # Failed to announce, go to next
+					time.sleep(1)
+			else:
+				pass # TODO: http tracker support
+
+
+	# Check and try to fix site files integrity
+	def checkFiles(self, quick_check=True):
+		self.log.debug("Checking files... Quick:%s" % quick_check)
+		bad_files = self.verifyFiles(quick_check)
+		if bad_files:
+			for bad_file in bad_files:
+				self.bad_files[bad_file] = True
+
+
+	# - Events -
+
+	# Add event listeners
+	def addEventListeners(self):
+		self.onFileStart = util.Event() # If WorkerManager added new task
+		self.onFileDone = util.Event() # If WorkerManager successfuly downloaded a file
+		self.onFileFail = util.Event() # If WorkerManager failed to download a file
+		self.onComplete = util.Event() # All file finished
+		
+		self.onFileStart.append(lambda inner_path: self.fileStarted()) # No parameters to make Noparallel batching working
+		self.onFileDone.append(lambda inner_path: self.fileDone(inner_path))
+		self.onFileFail.append(lambda inner_path: self.fileFailed(inner_path))
+
+
+	# Send site status update to websocket clients
+	def updateWebsocket(self, **kwargs):
+		if kwargs:
+			param = {"event": kwargs.items()[0]}
+		else:
+			param = None
+		for ws in self.websockets:
+			ws.event("siteChanged", self, param)
+
+
+	# File download started
+	@util.Noparallel(blocking=False)
+	def fileStarted(self):
+		time.sleep(0.001) # Wait for other files adds
+		self.updateWebsocket(file_started=True)
+
+
+	# File downloaded successful
+	def fileDone(self, inner_path):
+		# File downloaded, remove it from bad files
+		if inner_path in self.bad_files:
+			self.log.debug("Bad file solved: %s" % inner_path)
+			del(self.bad_files[inner_path])
+
+		# Update content.json last downlad time
+		if inner_path == "content.json":
+			self.content_updated = time.time()
+
+		self.updateWebsocket(file_done=inner_path)
+
+
+	# File download failed
+	def fileFailed(self, inner_path):
+		if inner_path == "content.json":
+			self.content_updated = False
+			self.log.error("Can't update content.json")
+
+		self.updateWebsocket(file_failed=inner_path)
+
+
+	# - Sign and verify -
+
+
+	# Verify fileobj using sha1 in content.json
+	def verifyFile(self, inner_path, file, force=False):
+		if inner_path == "content.json": # Check using sign
+			from Crypt import CryptBitcoin
+
+			try:
+				content = json.load(file)
+				if self.content and not force:
+					if self.content["modified"] == content["modified"]: # Ignore, have the same content.json
+						return None
+					elif self.content["modified"] > content["modified"]: # We have newer
+						return False
+				if content["modified"] > time.time()+60*60*24: # Content modified in the far future (allow 1 day window)
+					self.log.error("Content.json modify is in the future!")
+					return False
+				# Check sign
+				sign = content["sign"]
+				del(content["sign"]) # The file signed without the sign
+				sign_content = json.dumps(content, sort_keys=True) # Dump the json to string to remove whitepsace
+
+				return CryptBitcoin.verify(sign_content, self.address, sign)
+			except Exception, err:
+				self.log.error("Verify sign error: %s" % err)
+				return False
+
+		else: # Check using sha1 hash
+			if self.content and inner_path in self.content["files"]:
+				return CryptHash.sha1sum(file) == self.content["files"][inner_path]["sha1"]
+			else: # File not in content.json
+				self.log.error("File not in content.json: %s" % inner_path)
+				return False
+
+
+	# Verify all files sha1sum using content.json
+	def verifyFiles(self, quick_check=False): # Fast = using file size
+		bad_files = []
+		if not self.content: # No content.json, download it first
+			self.needFile("content.json", update=True) # Force update to fix corrupt file
+			self.loadContent() # Reload content.json
+		for inner_path in self.content["files"].keys():
+			file_path = self.getPath(inner_path)
+			if not os.path.isfile(file_path):
+				self.log.error("[MISSING] %s" % inner_path)
+				bad_files.append(inner_path)
+				continue
+
+			if quick_check:
+				ok = os.path.getsize(file_path) == self.content["files"][inner_path]["size"]
+			else:
+				ok = self.verifyFile(inner_path, open(file_path, "rb"))
+
+			if ok:
+				self.log.debug("[OK] %s" % inner_path)
+			else:
+				self.log.error("[ERROR] %s" % inner_path)
+				bad_files.append(inner_path)
+
+		return bad_files
+
+
+	# Create and sign content.json using private key
+	def signContent(self, privatekey=None):
+		if not self.content: # New site
+			self.log.info("Site not exits yet, loading default content.json values...")
+			self.content = {"files": {}, "title": "%s - ZeroNet_" % self.address, "sign": "", "modified": 0.0, "description": "", "address": self.address, "ignore": ""} # Default content.json
+
+		self.log.info("Opening site data directory: %s..." % self.directory)
+
+		hashed_files = {}
+
+		for root, dirs, files in os.walk(self.directory):
+			for file_name in files:
+				file_path = self.getPath("%s/%s" % (root, file_name))
+				
+				if file_name == "content.json" or (self.content["ignore"] and re.match(self.content["ignore"], file_path.replace(self.directory+"/", "") )): # Dont add content.json and ignore regexp pattern definied in content.json
+					self.log.info("- [SKIPPED] %s" % file_path)
+				else:
+					sha1sum = CryptHash.sha1sum(file_path) # Calculate sha sum of file
+					inner_path = re.sub("^%s/" % re.escape(self.directory), "", file_path)
+					self.log.info("- %s (SHA1: %s)" % (file_path, sha1sum))
+					hashed_files[inner_path] = {"sha1": sha1sum, "size": os.path.getsize(file_path)}
+
+		# Generate new content.json
+		self.log.info("Adding timestamp and sha1sums to new content.json...")
+		import datetime, time
+
+		content = self.content.copy() # Create a copy of current content.json
+		content["address"] = self.address # Add files sha1 hash
+		content["files"] = hashed_files # Add files sha1 hash
+		content["modified"] = time.mktime(datetime.datetime.utcnow().utctimetuple()) # Add timestamp
+		del(content["sign"]) # Delete old site
+
+		# Signing content
+		from Crypt import CryptBitcoin
+
+		self.log.info("Verifying private key...")
+		privatekey_address = CryptBitcoin.privatekeyToAddress(privatekey)
+		if self.address != privatekey_address:
+			return self.log.error("Private key invalid! Site address: %s, Private key address: %s" % (self.address, privatekey_address))
+
+		self.log.info("Signing modified content.json...")
+		sign_content = json.dumps(content, sort_keys=True)
+		self.log.debug("Content: %s" % sign_content)
+		sign = CryptBitcoin.sign(sign_content, privatekey)
+		content["sign"] = sign
+
+		# Saving modified content.json
+		self.log.info("Saving to %s/content.json..." % self.directory)
+		open("%s/content.json" % self.directory, "w").write(json.dumps(content, indent=4, sort_keys=True))
+
+		self.log.info("Site signed!")
diff --git a/src/Site/SiteManager.py b/src/Site/SiteManager.py
new file mode 100644
index 00000000..66fae64a
--- /dev/null
+++ b/src/Site/SiteManager.py
@@ -0,0 +1,62 @@
+import json, logging, time, re, os
+import gevent
+
+TRACKERS = [
+	("udp", "sugoi.pomf.se", 2710),
+	("udp", "open.demonii.com", 1337), # Retry 3 times
+	("udp", "open.demonii.com", 1337),
+	("udp", "open.demonii.com", 1337),
+	("udp", "bigfoot1942.sektori.org", 6969),
+	("udp", "tracker.coppersurfer.tk", 80),
+	("udp", "tracker.leechers-paradise.org", 6969),
+	("udp", "tracker.blazing.de", 80),
+]
+
+# Load all sites from data/sites.json
+def load():
+	from Site import Site
+	global sites
+	if not sites: sites = {}
+	address_found = []
+	added = 0
+	# Load new adresses
+	for address in json.load(open("data/sites.json")):
+		if address not in sites and os.path.isfile("data/%s/content.json" % address):
+			sites[address] = Site(address)
+			added += 1
+		address_found.append(address)
+
+	# Remove deleted adresses
+	for address in sites.keys():
+		if address not in address_found: 
+			del(sites[address])
+			logging.debug("Removed site: %s" % address)
+
+	if added: logging.debug("SiteManager added %s sites" % added)
+
+
+# Checks if its a valid address
+def isAddress(address):
+	return re.match("^[A-Za-z0-9]{34}$", address)
+
+
+# Return site and start download site files
+def need(address, all_file=True):
+	from Site import Site
+	if address not in sites: # Site not exits yet
+		if not isAddress(address): raise Exception("Not address: %s" % address)
+		sites[address] = Site(address)
+	site = sites[address]
+	if all_file: site.download()
+	return site
+
+
+# Lazy load sites
+def list():
+	if sites == None: # Not loaded yet
+		load()
+	return sites
+
+
+sites = None
+peer_blacklist = [] # Dont download from this peers
\ No newline at end of file
diff --git a/src/Site/__init__.py b/src/Site/__init__.py
new file mode 100644
index 00000000..f0f2f304
--- /dev/null
+++ b/src/Site/__init__.py
@@ -0,0 +1 @@
+from Site import Site
\ No newline at end of file
diff --git a/src/Test/__init__.py b/src/Test/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/Test/test.py b/src/Test/test.py
new file mode 100644
index 00000000..6c99d3bd
--- /dev/null
+++ b/src/Test/test.py
@@ -0,0 +1,46 @@
+import sys, os, unittest, urllib, time
+sys.path.append(os.path.abspath("src")) # Imports relative to src dir
+
+from Crypt import CryptBitcoin
+from Ui import UiRequest
+
+class TestCase(unittest.TestCase):
+
+	def testMediaRoute(self):
+		try:
+			urllib.urlopen("http://127.0.0.1:43110").read()
+		except Exception, err:
+			raise unittest.SkipTest(err)
+		self.assertIn("Not Found", urllib.urlopen("http://127.0.0.1:43110/media//sites.json").read())
+		self.assertIn("Not Found", urllib.urlopen("http://127.0.0.1:43110/media/./sites.json").read())
+		self.assertIn("Not Found", urllib.urlopen("http://127.0.0.1:43110/media/../config.py").read())
+		self.assertIn("Forbidden", urllib.urlopen("http://127.0.0.1:43110/media/1P2rJhkQjYSHdHpWDDwxfRGYXaoWE8u1vV/../sites.json").read())
+		self.assertIn("Forbidden", urllib.urlopen("http://127.0.0.1:43110/media/1P2rJhkQjYSHdHpWDDwxfRGYXaoWE8u1vV/..//sites.json").read())
+		self.assertIn("Forbidden", urllib.urlopen("http://127.0.0.1:43110/media/1P2rJhkQjYSHdHpWDDwxfRGYXaoWE8u1vV/../../config.py").read())
+
+
+	def testBitcoinSign(self):
+		s = time.time()
+		privatekey = "23DKQpDz7bXM7w5KN5Wnmz7bwRNqNHcdQjb2WwrdB1QtTf5gM3pFdf"
+		privatekey_bad = "23DKQpDz7bXM7w5KN5Wnmz6bwRNqNHcdQjb2WwrdB1QtTf5gM3pFdf"
+
+		address = CryptBitcoin.privatekeyToAddress(privatekey)
+		self.assertEqual(address, "12vTsjscg4hYPewUL2onma5pgQmWPMs3ez")
+
+		address_bad = CryptBitcoin.privatekeyToAddress(privatekey_bad)
+		self.assertNotEqual(address_bad, "12vTsjscg4hYPewUL2onma5pgQmWPMs3ez")
+
+		sign = CryptBitcoin.sign("hello", privatekey)
+
+		self.assertTrue(CryptBitcoin.verify("hello", address, sign))
+		self.assertFalse(CryptBitcoin.verify("not hello", address, sign))
+
+		sign_bad = CryptBitcoin.sign("hello", privatekey_bad)
+		self.assertFalse(CryptBitcoin.verify("hello", address, sign_bad))
+
+		print "Taken: %.3fs, " % (time.time()-s),
+
+
+if __name__ == "__main__":
+	unittest.main(verbosity=2)
+
diff --git a/src/Ui/UiRequest.py b/src/Ui/UiRequest.py
new file mode 100644
index 00000000..84767abf
--- /dev/null
+++ b/src/Ui/UiRequest.py
@@ -0,0 +1,286 @@
+import time, re, os, mimetypes, json
+from Config import config
+from Site import SiteManager
+from Ui.UiWebsocket import UiWebsocket
+
+status_texts = {
+	200: "200 OK",
+	400: "400 Bad Request",
+	403: "403 Forbidden",
+	404: "404 Not Found",
+}
+
+
+
+class UiRequest:
+	def __init__(self, server = None):
+		if server:
+			self.server = server
+			self.log = server.log
+		self.get = {} # Get parameters
+		self.env = {} # Enviroment settings
+		self.start_response = None # Start response function
+
+
+	# Call the request handler function base on path
+	def route(self, path):
+		if config.ui_restrict and self.env['REMOTE_ADDR'] != config.ui_restrict: # Restict Ui access by ip
+			return self.error403()
+
+		if path == "/":
+			return self.actionIndex()
+		elif path == "/favicon.ico":
+			return self.actionFile("src/Ui/media/img/favicon.ico")
+		# Media
+		elif path.startswith("/uimedia/"):
+			return self.actionUiMedia(path)
+		elif path.startswith("/media"):
+			return self.actionSiteMedia(path) 
+		# Websocket
+		elif path == "/Websocket":
+			return self.actionWebsocket()
+		# Debug
+		elif path == "/Debug" and config.debug:
+			return self.actionDebug()
+		elif path == "/Console" and config.debug:
+			return self.actionConsole()
+		# Test
+		elif path == "/Test/Websocket":
+			return self.actionFile("Data/temp/ws_test.html")
+		elif path == "/Test/Stream":
+			return self.actionTestStream()
+		# Site media wrapper
+		else:
+			return self.actionWrapper(path)
+
+
+	# Get mime by filename
+	def getContentType(self, file_name):
+		content_type = mimetypes.guess_type(file_name)[0]
+		if not content_type: 
+			if file_name.endswith("json"): # Correct json header
+				content_type = "application/json"
+			else:
+				content_type = "application/octet-stream"
+		return content_type
+
+
+	# Send response headers
+	def sendHeader(self, status=200, content_type="text/html; charset=utf-8", extra_headers=[]):
+		headers = []
+		headers.append(("Version", "HTTP/1.1"))
+		headers.append(("Access-Control-Allow-Origin", "*")) # Allow json access
+		headers.append(("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")) # Allow json access
+		headers.append(("Cache-Control", "no-cache, no-store, private, must-revalidate, max-age=0")) # No caching at all
+		#headers.append(("Cache-Control", "public, max-age=604800")) # Cache 1 week
+		headers.append(("Content-Type", content_type))
+		for extra_header in extra_headers:
+			headers.append(extra_header)
+		self.start_response(status_texts[status], headers)
+
+
+	# Renders a template
+	def render(self, template_path, *args, **kwargs):
+		#template = SimpleTemplate(open(template_path), lookup=[os.path.dirname(template_path)])
+		#yield str(template.render(*args, **kwargs).encode("utf8"))
+		template = open(template_path).read()
+		yield template.format(**kwargs)
+
+
+	# - Actions -
+
+	# Redirect to an url
+	def actionRedirect(self, url):
+		self.start_response('301 Redirect', [('Location', url)])
+		yield "Location changed: %s" % url
+
+
+	def actionIndex(self):
+		return self.actionRedirect("/"+config.homepage)
+
+
+	# Render a file from media with iframe site wrapper
+	def actionWrapper(self, path):
+		if self.env.get("HTTP_X_REQUESTED_WITH"): return self.error403() # No ajax allowed on wrapper
+
+		match = re.match("/(?P<site>[A-Za-z0-9]+)(?P<inner_path>/.*|$)", path)
+		if match:
+			inner_path = match.group("inner_path").lstrip("/")
+			if not inner_path: inner_path = "index.html" # If inner path defaults to index.html
+
+			site = self.server.sites.get(match.group("site"))
+			if site and site.content and not site.bad_files: # Its downloaded
+				title = site.content["title"]
+			else:
+				title = "Loading %s..." % match.group("site")
+				site = SiteManager.need(match.group("site")) # Start download site
+				if not site: self.error404()
+
+
+			self.sendHeader(extra_headers=[("X-Frame-Options", "DENY")])
+			return self.render("src/Ui/template/wrapper.html", 
+				inner_path=inner_path, 
+				address=match.group("site"), 
+				title=title, 
+				auth_key=site.settings["auth_key"],
+				permissions=json.dumps(site.settings["permissions"]),
+				show_loadingscreen=json.dumps(not os.path.isfile(site.getPath(inner_path))),
+				homepage=config.homepage
+			)
+
+		else: # Bad url
+			return self.error404(path)
+
+
+	# Serve a media for site
+	def actionSiteMedia(self, path):
+		match = re.match("/media/(?P<site>[A-Za-z0-9]+)/(?P<inner_path>.*)", path)
+
+		referer = self.env.get("HTTP_REFERER")
+		if referer: # Only allow same site to receive media
+			referer = re.sub("http://.*?/", "/", referer) # Remove server address
+			referer = referer.replace("/media", "") # Media
+			if not referer.startswith("/"+match.group("site")): return self.error403() # Referer not starts same address as requested path
+
+		if match: # Looks like a valid path
+			file_path = "data/%s/%s" % (match.group("site"), match.group("inner_path"))
+			allowed_dir = os.path.abspath("data/%s" % match.group("site")) # Only files within data/sitehash allowed
+			if ".." in file_path or not os.path.dirname(os.path.abspath(file_path)).startswith(allowed_dir): # File not in allowed path
+				return self.error403()
+			else:
+				if config.debug and file_path.split("/")[-1].startswith("all."): # When debugging merge *.css to all.css and *.js to all.js
+					site = self.server.sites.get(match.group("site"))
+					if site.settings["own"]:
+						from Debug import DebugMedia
+						DebugMedia.merge(file_path)
+				if os.path.isfile(file_path): # File exits
+					return self.actionFile(file_path)
+				else: # File not exits, try to download
+					site = SiteManager.need(match.group("site"), all_file=False)
+					self.sendHeader(content_type=self.getContentType(file_path)) # ?? Get Exception without this
+					result = site.needFile(match.group("inner_path")) # Wait until file downloads
+					return self.actionFile(file_path)
+
+		else: # Bad url
+			return self.error404(path)
+
+
+	# Serve a media for ui
+	def actionUiMedia(self, path):
+		match = re.match("/uimedia/(?P<inner_path>.*)", path)
+		if match: # Looks like a valid path
+			file_path = "src/Ui/media/%s" % match.group("inner_path")
+			allowed_dir = os.path.abspath("src/Ui/media") # Only files within data/sitehash allowed
+			if ".." in file_path or not os.path.dirname(os.path.abspath(file_path)).startswith(allowed_dir): # File not in allowed path
+				return self.error403()
+			else:
+				if config.debug and match.group("inner_path").startswith("all."): # When debugging merge *.css to all.css and *.js to all.js
+					from Debug import DebugMedia
+					DebugMedia.merge(file_path)
+				return self.actionFile(file_path)
+		else: # Bad url
+			return self.error400()
+
+
+	# Stream a file to client
+	def actionFile(self, file_path, block_size = 64*1024):
+		if os.path.isfile(file_path):
+			# Try to figure out content type by extension
+			content_type = self.getContentType(file_path)
+
+			self.sendHeader(content_type = content_type) # TODO: Dont allow external access: extra_headers=[("Content-Security-Policy", "default-src 'unsafe-inline' data: http://localhost:43110 ws://localhost:43110")]
+			if self.env["REQUEST_METHOD"] != "OPTIONS":
+				file = open(file_path, "rb")
+				while 1:
+					try:
+						block = file.read(block_size)
+						if block:
+							yield block
+						else:
+							raise StopIteration
+					except StopIteration:
+						file.close()
+						break
+		else: # File not exits
+			yield self.error404(file_path)
+
+
+	# On websocket connection
+	def actionWebsocket(self):
+		ws = self.env.get("wsgi.websocket")
+		if ws:
+			auth_key = self.get["auth_key"]
+			# Find site by auth_key
+			site = None
+			for site_check in self.server.sites.values():
+				if site_check.settings["auth_key"] == auth_key: site = site_check
+
+			if site: # Correct auth key
+				ui_websocket = UiWebsocket(ws, site, self.server)
+				site.websockets.append(ui_websocket) # Add to site websockets to allow notify on events
+				ui_websocket.start()
+				for site_check in self.server.sites.values(): # Remove websocket from every site (admin sites allowed to join other sites event channels)
+					if ui_websocket in site_check.websockets:
+						site_check.websockets.remove(ui_websocket)
+				return "Bye."
+			else: # No site found by auth key
+				self.log.error("Auth key not found: %s" % auth_key)
+				return self.error403()
+		else:
+			start_response("400 Bad Request", []) 
+			return "Not a websocket!"
+
+
+	# Debug last error
+	def actionDebug(self):
+		# Raise last error from DebugHook
+		import sys
+		last_error = sys.modules["src.main"].DebugHook.last_error
+		if last_error:
+			raise last_error[0], last_error[1], last_error[2]
+		else:
+			self.sendHeader()
+			yield "No error! :)"
+
+
+	# Just raise an error to get console
+	def actionConsole(self):
+		raise Exception("Here is your console")
+
+
+	# - Tests -
+
+	def actionTestStream(self):
+		self.sendHeader()
+		yield " "*1080 # Overflow browser's buffer
+		yield "He"
+		time.sleep(1)
+		yield "llo!"
+		yield "Running websockets: %s" % len(self.server.websockets)
+		self.server.sendMessage("Hello!")
+
+
+	# - Errors -
+
+	# Send bad request error
+	def error400(self):
+		self.sendHeader(400)
+		return "Bad Request"
+
+
+	# You are not allowed to access this
+	def error403(self):
+		self.sendHeader(403)
+		return "Forbidden"
+
+
+	# Send file not found error
+	def error404(self, path = None):
+		self.sendHeader(404)
+		return "Not Found: %s" % path
+
+	# - Reload for eaiser developing -
+	def reload(self):
+		import imp
+		global UiWebsocket
+		UiWebsocket = imp.load_source("UiWebsocket", "src/Ui/UiWebsocket.py").UiWebsocket
diff --git a/src/Ui/UiServer.py b/src/Ui/UiServer.py
new file mode 100644
index 00000000..61f32a8f
--- /dev/null
+++ b/src/Ui/UiServer.py
@@ -0,0 +1,93 @@
+from gevent import monkey; monkey.patch_all(thread = False)
+import logging, time, cgi, string, random
+from gevent.pywsgi import WSGIServer
+from gevent.pywsgi import WSGIHandler
+from lib.geventwebsocket.handler import WebSocketHandler
+from Ui import UiRequest
+from Site import SiteManager
+from Config import config
+
+# Skip websocket handler if not necessary
+class UiWSGIHandler(WSGIHandler):
+	def __init__(self, *args, **kwargs):
+		super(UiWSGIHandler, self).__init__(*args, **kwargs)
+		self.ws_handler = WebSocketHandler(*args, **kwargs)
+
+
+	def run_application(self):
+		if "HTTP_UPGRADE" in self.environ: # Websocket request
+			self.ws_handler.__dict__ = self.__dict__ # Match class variables
+			self.ws_handler.run_application()
+		else: # Standard HTTP request
+			#print self.application.__class__.__name__
+			return super(UiWSGIHandler, self).run_application()
+
+
+class UiServer:
+	def __init__(self):
+		self.ip = config.ui_ip
+		self.port = config.ui_port
+		if self.ip == "*": self.ip = "" # Bind all
+		#self.sidebar_websockets = [] # Sidebar websocket connections
+		#self.auth_key = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(12)) # Global admin auth key
+		self.sites = SiteManager.list()
+		self.log = logging.getLogger(__name__)
+		
+		self.ui_request = UiRequest(self)
+
+
+	# Handle WSGI request
+	def handleRequest(self, env, start_response):
+		path = env["PATH_INFO"]
+		self.ui_request.env = env
+		self.ui_request.start_response = start_response
+		if env.get("QUERY_STRING"):
+			self.ui_request.get = dict(cgi.parse_qsl(env['QUERY_STRING']))
+		else:
+			self.ui_request.get = {}
+		return self.ui_request.route(path)
+
+
+	# Send a message to all connected client
+	def sendMessage(self, message):
+		sent = 0
+		for ws in self.websockets:
+			try:
+				ws.send(message)
+				sent += 1
+			except Exception, err:
+				self.log.error("addMessage error: %s" % err)
+				self.server.websockets.remove(ws)
+		return sent
+
+
+	# Reload the UiRequest class to prevent restarts in debug mode
+	def reload(self):
+		import imp
+		self.ui_request = imp.load_source("UiRequest", "src/Ui/UiRequest.py").UiRequest(self)
+		self.ui_request.reload()
+
+
+	# Bind and run the server
+	def start(self):
+		handler = self.handleRequest
+
+		if config.debug:
+			# Auto reload UiRequest on change
+			from Debug import DebugReloader
+			DebugReloader(self.reload)
+
+			# Werkzeug Debugger
+			try:
+				from werkzeug.debug import DebuggedApplication
+				handler = DebuggedApplication(self.handleRequest, evalex=True)
+			except Exception, err:
+				self.log.info("%s: For debugging please download Werkzeug (http://werkzeug.pocoo.org/)" % err)
+				from Debug import DebugReloader
+		self.log.write = lambda msg: self.log.debug(msg.strip()) # For Wsgi access.log
+		self.log.info("--------------------------------------")
+		self.log.info("Web interface: http://%s:%s/" % (config.ui_ip, config.ui_port))
+		self.log.info("--------------------------------------")
+
+
+		WSGIServer((self.ip, self.port), handler, handler_class=UiWSGIHandler, log=self.log).serve_forever()
diff --git a/src/Ui/UiWebsocket.py b/src/Ui/UiWebsocket.py
new file mode 100644
index 00000000..8056fc9f
--- /dev/null
+++ b/src/Ui/UiWebsocket.py
@@ -0,0 +1,217 @@
+import json, gevent, time, sys, hashlib
+from Config import config
+from Site import SiteManager
+
+class UiWebsocket:
+	def __init__(self, ws, site, server):
+		self.ws = ws
+		self.site = site
+		self.server = server
+		self.next_message_id = 1
+		self.waiting_cb = {} # Waiting for callback. Key: message_id, Value: function pointer
+		self.channels = [] # Channels joined to
+
+
+	# Start listener loop
+	def start(self):
+		ws = self.ws
+		if self.site.address == config.homepage and not self.site.page_requested: # Add open fileserver port message or closed port error to homepage at first request after start
+			if config.ip_external: 
+				self.site.notifications.append(["done", "Congratulation, your port <b>"+str(config.fileserver_port)+"</b> is opened. <br>You are full member of ZeroNet network!", 10000])
+			elif config.ip_external == False:
+				self.site.notifications.append(["error", "Your network connection is restricted. Please, open <b>"+str(config.fileserver_port)+"</b> port <br>on your router to become full member of ZeroNet network.", 0])
+		self.site.page_requested = True # Dont add connection notification anymore
+
+		for notification in self.site.notifications: # Send pending notification messages
+			self.cmd("notification", notification)
+		self.site.notifications = []
+		while True:
+			try:
+				message = ws.receive()
+				if message:
+					self.handleRequest(message)
+			except Exception, err:
+				if err.message != 'Connection is already closed':
+					if config.debug: # Allow websocket errors to appear on /Debug 
+						import sys
+						sys.modules["src.main"].DebugHook.handleError() 
+					self.site.log.error("WebSocket error: %s" % err)
+				return "Bye."
+
+
+	# Event in a channel
+	def event(self, channel, *params):
+		if channel in self.channels: # We are joined to channel
+			if channel == "siteChanged":
+				site = params[0] # Triggerer site
+				site_info = self.siteInfo(site)
+				if len(params) > 1 and params[1]: # Extra data
+					site_info.update(params[1])
+				self.cmd("setSiteInfo", site_info)
+
+
+	# Send response to client (to = message.id)
+	def response(self, to, result):
+		self.send({"cmd": "response", "to": to, "result": result})
+
+
+	# Send a command
+	def cmd(self, cmd, params={}, cb = None):
+		self.send({"cmd": cmd, "params": params}, cb)
+
+
+	# Encode to json and send message
+	def send(self, message, cb = None):
+		message["id"] = self.next_message_id # Add message id to allow response
+		self.next_message_id += 1
+		self.ws.send(json.dumps(message))
+		if cb: # Callback after client responsed
+			self.waiting_cb[message["id"]] = cb
+
+
+	# Handle incoming messages
+	def handleRequest(self, data):
+		req = json.loads(data)
+		cmd = req["cmd"]
+		permissions = self.site.settings["permissions"]
+		if cmd == "response":
+			self.actionResponse(req)
+		elif cmd == "ping":
+			self.actionPing(req["id"])
+		elif cmd == "channelJoin":
+			self.actionChannelJoin(req["id"], req["params"])
+		elif cmd == "siteInfo":
+			self.actionSiteInfo(req["id"], req["params"])
+		elif cmd == "serverInfo":
+			self.actionServerInfo(req["id"], req["params"])
+		elif cmd == "siteUpdate":
+			self.actionSiteUpdate(req["id"], req["params"])
+		# Admin commands
+		elif cmd == "sitePause" and "ADMIN" in permissions:
+			self.actionSitePause(req["id"], req["params"])
+		elif cmd == "siteResume" and "ADMIN" in permissions:
+			self.actionSiteResume(req["id"], req["params"])
+		elif cmd == "siteList" and "ADMIN" in permissions:
+			self.actionSiteList(req["id"], req["params"])
+		elif cmd == "channelJoinAllsite" and "ADMIN" in permissions:
+			self.actionChannelJoinAllsite(req["id"], req["params"])
+		# Unknown command
+		else:
+			self.response(req["id"], "Unknown command: %s" % cmd)
+
+
+	# - Actions -
+
+	# Do callback on response {"cmd": "response", "to": message_id, "result": result}
+	def actionResponse(self, req):
+		if req["to"] in self.waiting_cb:
+			self.waiting_cb(req["result"]) # Call callback function
+		else:
+			self.site.log.error("Websocket callback not found: %s" % req)
+
+
+	# Send a simple pong answer
+	def actionPing(self, to):
+		self.response(to, "pong")
+
+
+	# Format site info
+	def siteInfo(self, site):
+		ret = {
+			"auth_id": self.site.settings["auth_key"][0:10],
+			"auth_id_md5": hashlib.md5(self.site.settings["auth_key"][0:10]).hexdigest(),
+			"address": site.address,
+			"settings": site.settings,
+			"content_updated": site.content_updated,
+			"bad_files": site.bad_files.keys(),
+			"last_downloads": site.last_downloads,
+			"peers": len(site.peers),
+			"tasks": [task["inner_path"] for task in site.worker_manager.tasks],
+			"content": site.content
+		}
+		if site.settings["serving"] and site.content: ret["peers"] += 1 # Add myself if serving
+		return ret
+
+
+	# Send site details
+	def actionSiteInfo(self, to, params):
+		ret = self.siteInfo(self.site)
+		self.response(to, ret)
+
+
+	# Join to an event channel
+	def actionChannelJoin(self, to, params):
+		if params["channel"] not in self.channels:
+			self.channels.append(params["channel"])
+
+
+	# Server variables
+	def actionServerInfo(self, to, params):
+		ret = {
+			"ip_external": config.ip_external,
+			"platform": sys.platform,
+			"fileserver_ip": config.fileserver_ip,
+			"fileserver_port": config.fileserver_port,
+			"ui_ip": config.ui_ip,
+			"ui_port": config.ui_port,
+			"debug": config.debug
+		}
+		self.response(to, ret)
+
+
+	# - Admin actions -
+	
+	# List all site info
+	def actionSiteList(self, to, params):
+		ret = []
+		SiteManager.load() # Reload sites
+		for site in self.server.sites.values():
+			if not site.content: continue # Broken site
+			ret.append(self.siteInfo(site))
+		self.response(to, ret)
+
+
+	# Join to an event channel on all sites
+	def actionChannelJoinAllsite(self, to, params):
+		if params["channel"] not in self.channels: # Add channel to channels
+			self.channels.append(params["channel"])
+
+		for site in self.server.sites.values(): # Add websocket to every channel
+			if self not in site.websockets:
+				site.websockets.append(self)
+
+
+	# Update site content.json
+	def actionSiteUpdate(self, to, params):
+		address = params.get("address")
+		site = self.server.sites.get(address)
+		if site and (site.address == self.site.address or "ADMIN" in self.site.settings["permissions"]):
+			gevent.spawn(site.update)
+		else:
+			self.response(to, {"error": "Unknown site: %s" % address})
+
+
+	# Pause site serving
+	def actionSitePause(self, to, params):
+		address = params.get("address")
+		site = self.server.sites.get(address)
+		if site:
+			site.settings["serving"] = False
+			site.saveSettings()
+			site.updateWebsocket()
+		else:
+			self.response(to, {"error": "Unknown site: %s" % address})
+
+
+	# Resume site serving
+	def actionSiteResume(self, to, params):
+		address = params.get("address")
+		site = self.server.sites.get(address)
+		if site:
+			site.settings["serving"] = True
+			site.saveSettings()
+			gevent.spawn(site.update)
+			time.sleep(0.001) # Wait for update thread starting
+			site.updateWebsocket()
+		else:
+			self.response(to, {"error": "Unknown site: %s" % address})
diff --git a/src/Ui/__init__.py b/src/Ui/__init__.py
new file mode 100644
index 00000000..9982dc4f
--- /dev/null
+++ b/src/Ui/__init__.py
@@ -0,0 +1,3 @@
+from UiServer import UiServer
+from UiRequest import UiRequest
+from UiWebsocket import UiWebsocket
\ No newline at end of file
diff --git a/src/Ui/media/Loading.coffee b/src/Ui/media/Loading.coffee
new file mode 100644
index 00000000..52a0ff1f
--- /dev/null
+++ b/src/Ui/media/Loading.coffee
@@ -0,0 +1,40 @@
+class Loading
+	constructor: ->
+		if window.show_loadingscreen then @showScreen()
+
+
+	showScreen: ->
+		$(".loadingscreen").css("display", "block").addClassLater("ready")
+		@screen_visible = true
+		@printLine "&nbsp;&nbsp;&nbsp;Connecting..."
+
+
+
+	# We dont need loadingscreen anymore
+	hideScreen: ->
+		if @screen_visible # Hide with animate
+			$(".loadingscreen").addClass("done").removeLater(2000)
+		else # Not visible, just remove
+			$(".loadingscreen").remove()
+		@screen_visible = false
+
+
+	# Append text to last line of loadingscreen
+	print: (text, type="normal") ->
+		if not @screen_visible then return false
+		$(".loadingscreen .console .cursor").remove() # Remove previous cursor
+		last_line = $(".loadingscreen .console .console-line:last-child")
+		if type == "error" then text = "<span class='console-error'>#{text}</span>"
+		last_line.html(last_line.html()+text)
+
+
+	# Add line to loading screen
+	printLine: (text, type="normal") ->
+		if not @screen_visible then return false
+		$(".loadingscreen .console .cursor").remove() # Remove previous cursor
+		if type == "error" then text = "<span class='console-error'>#{text}</span>" else text = text+"<span class='cursor'> </span>"
+		$(".loadingscreen .console").append("<div class='console-line'>#{text}</div>")
+
+
+
+window.Loading = Loading
\ No newline at end of file
diff --git a/src/Ui/media/Notifications.coffee b/src/Ui/media/Notifications.coffee
new file mode 100644
index 00000000..d5190c5a
--- /dev/null
+++ b/src/Ui/media/Notifications.coffee
@@ -0,0 +1,68 @@
+class Notifications
+	constructor: (@elem) ->
+		@
+
+	test: ->
+		setTimeout (=>
+			@add("connection", "error", "Connection lost to <b>UiServer</b> on <b>localhost</b>!")
+			@add("message-Anyone", "info", "New  from <b>Anyone</b>.")
+		), 1000
+		setTimeout (=>
+			@add("connection", "done", "<b>UiServer</b> connection recovered.", 5000)
+		), 3000
+
+
+	add: (id, type, body, timeout=0) ->
+		@log id, type, body, timeout
+		# Close notifications with same id
+		for elem in $(".notification-#{id}")
+			@close $(elem)
+
+		# Create element
+		elem = $(".notification.template", @elem).clone().removeClass("template")
+		elem.addClass("notification-#{type}").addClass("notification-#{id}")
+
+		# Update text
+		if type == "error"
+			$(".notification-icon", elem).html("!")
+		else if type == "done"
+			$(".notification-icon", elem).html("<div class='icon-success'></div>")
+		else
+			$(".notification-icon", elem).html("i")
+
+		$(".body", elem).html(body)
+
+		elem.appendTo(@elem)
+
+		# Timeout
+		if timeout
+			$(".close", elem).remove() # No need of close button
+			setTimeout (=>
+				@close elem
+			), timeout
+
+		# Animate
+		width = elem.outerWidth()
+		if not timeout then width += 20 # Add space for close button
+		elem.css({"width": "50px", "transform": "scale(0.01)"})
+		elem.animate({"scale": 1}, 800, "easeOutElastic")
+		elem.animate({"width": width}, 700, "easeInOutCubic")
+
+		# Close button
+		$(".close", elem).on "click", =>
+			@close elem
+			return false
+
+		@
+
+
+	close: (elem) ->
+		elem.stop().animate {"width": 0, "opacity": 0}, 700, "easeInOutCubic"
+		elem.slideUp 300, (-> elem.remove())
+
+
+	log: (args...) ->
+		console.log "[Notifications]", args...
+
+
+window.Notifications = Notifications
\ No newline at end of file
diff --git a/src/Ui/media/Sidebar.coffee b/src/Ui/media/Sidebar.coffee
new file mode 100644
index 00000000..d57c5bb2
--- /dev/null
+++ b/src/Ui/media/Sidebar.coffee
@@ -0,0 +1,33 @@
+class Sidebar
+	constructor: ->
+		@initFixbutton()
+
+
+	initFixbutton: ->
+		$(".fixbutton-bg").on "mouseover", ->
+			$(@).stop().animate({"scale": 0.7}, 800, "easeOutElastic")
+			$(".fixbutton-burger").stop().animate({"opacity": 1.5, "left": 0}, 800, "easeOutElastic")
+			$(".fixbutton-text").stop().animate({"opacity": 0, "left": 20}, 300, "easeOutCubic")
+
+		$(".fixbutton-bg").on "mouseout", ->
+			$(@).stop().animate({"scale": 0.6}, 300, "easeOutCubic")
+			$(".fixbutton-burger").stop().animate({"opacity": 0, "left": -20}, 300, "easeOutCubic")
+			$(".fixbutton-text").stop().animate({"opacity": 1, "left": 0}, 300, "easeOutBack")
+
+		
+		###$(".fixbutton-bg").on "click", ->
+			return false
+		###
+
+		$(".fixbutton-bg").on "mousedown", ->
+			$(".fixbutton-burger").stop().animate({"scale": 0.7, "left": 0}, 300, "easeOutCubic")
+			#$("#inner-iframe").toggleClass("back")
+			#$(".wrapper-iframe").stop().animate({"scale": 0.9}, 600, "easeOutCubic")
+			#$("body").addClass("back")
+
+		$(".fixbutton-bg").on "mouseup", ->
+			$(".fixbutton-burger").stop().animate({"scale": 1, "left": 0}, 600, "easeOutElastic")
+		
+
+
+window.Sidebar = Sidebar
diff --git a/src/Ui/media/Wrapper.coffee b/src/Ui/media/Wrapper.coffee
new file mode 100644
index 00000000..6dfdffc2
--- /dev/null
+++ b/src/Ui/media/Wrapper.coffee
@@ -0,0 +1,152 @@
+class Wrapper
+	constructor: (ws_url) ->
+		@log "Created!"
+
+		@loading = new Loading()
+		@notifications = new Notifications($(".notifications"))
+		@sidebar = new Sidebar()
+
+		window.addEventListener("message", @onMessageInner, false)
+		@inner = document.getElementById("inner-iframe").contentWindow
+		@ws = new ZeroWebsocket(ws_url)
+		@ws.next_message_id = 1000000 # Avoid messageid collision :)
+		@ws.onOpen = @onOpenWebsocket
+		@ws.onClose = @onCloseWebsocket
+		@ws.onMessage = @onMessageWebsocket
+		@ws.connect()
+		@ws_error = null # Ws error message
+
+		@site_info = null # Hold latest site info
+		@inner_loaded = false # If iframe loaded or not
+		@inner_ready = false # Inner frame ready to receive messages
+		@wrapperWsInited = false # Wrapper notified on websocket open
+		@site_error = null # Latest failed file download
+
+		window.onload = @onLoad # On iframe loaded
+		@
+
+
+	# Incoming message from UiServer websocket
+	onMessageWebsocket: (e) =>
+		message = JSON.parse(e.data)
+		cmd = message.cmd
+		if cmd == "response"
+			if @ws.waiting_cb[message.to]? # We are waiting for response
+				@ws.waiting_cb[message.to](message.result)
+			else
+				@sendInner message # Pass message to inner frame
+		else if cmd == "notification" # Display notification
+			@notifications.add("notification-#{message.id}", message.params[0], message.params[1], message.params[2])
+		else if cmd == "setSiteInfo"
+			@sendInner message # Pass to inner frame
+			if message.params.address == window.address # Current page
+				@setSiteInfo message.params
+		else
+			@sendInner message # Pass message to inner frame
+
+
+	# Incoming message from inner frame
+	onMessageInner: (e) =>
+		message = e.data
+		cmd = message.cmd
+		if cmd == "innerReady"
+			@inner_ready = true
+			@log "innerReady", @ws.ws.readyState, @wrapperWsInited
+			if @ws.ws.readyState == 1 and not @wrapperWsInited # If ws already opened
+				@sendInner {"cmd": "wrapperOpenedWebsocket"}
+				@wrapperWsInited = true
+		else if cmd == "wrapperNotification"
+			@notifications.add("notification-#{message.id}", message.params[0], message.params[1], message.params[2])
+		else # Send to websocket
+			@ws.send(message) # Pass message to websocket
+
+
+	onOpenWebsocket: (e) =>
+		@ws.cmd "channelJoin", {"channel": "siteChanged"} # Get info on modifications
+		@log "onOpenWebsocket", @inner_ready, @wrapperWsInited
+		if not @wrapperWsInited and @inner_ready
+			@sendInner {"cmd": "wrapperOpenedWebsocket"} # Send to inner frame
+			@wrapperWsInited = true
+		if @inner_loaded # Update site info
+			@reloadSiteInfo()
+
+		# If inner frame not loaded for 2 sec show peer informations on loading screen by loading site info
+		setTimeout (=>
+			if not @site_info then @reloadSiteInfo()
+		), 2000
+
+		if @ws_error 
+			@notifications.add("connection", "done", "Connection with <b>UiServer Websocket</b> recovered.", 6000)
+			@ws_error = null
+
+
+	onCloseWebsocket: (e) =>
+		@wrapperWsInited = false
+		setTimeout (=> # Wait a bit, maybe its page closing
+			@sendInner {"cmd": "wrapperClosedWebsocket"} # Send to inner frame
+			if e.code == 1000 # Server error please reload page
+				@ws_error = @notifications.add("connection", "error", "UiServer Websocket error, please reload the page.")
+			else if not @ws_error
+				@ws_error = @notifications.add("connection", "error", "Connection with <b>UiServer Websocket</b> was lost. Reconnecting...")
+		), 500
+
+
+	# Iframe loaded
+	onLoad: (e) =>
+		@log "onLoad", e
+		@inner_loaded = true
+		if not @inner_ready then @sendInner {"cmd": "wrapperReady"} # Inner frame loaded before wrapper
+		if not @site_error then @loading.hideScreen() # Hide loading screen
+		if @ws.ws.readyState == 1 and not @site_info # Ws opened
+			@reloadSiteInfo()
+
+
+	# Send message to innerframe
+	sendInner: (message) ->
+		@inner.postMessage(message, '*')
+
+
+	# Get site info from UiServer
+	reloadSiteInfo: ->
+		@ws.cmd "siteInfo", {}, (site_info) =>
+			@setSiteInfo site_info
+			window.document.title = site_info.content.title+" - ZeroNet"
+			@log "Setting title to", window.document.title
+
+
+	# Got setSiteInfo from websocket UiServer
+	setSiteInfo: (site_info) ->
+		if site_info.event? # If loading screen visible add event to it
+			# File started downloading
+			if site_info.event[0] == "file_added" and site_info.bad_files.length
+				@loading.printLine("#{site_info.bad_files.length} files needs to be downloaded")
+			# File finished downloading
+			else if site_info.event[0] == "file_done"
+				@loading.printLine("#{site_info.event[1]} downloaded")
+				if site_info.event[1] == window.inner_path # File downloaded we currently on
+					@loading.hideScreen()
+					if not $(".loadingscreen").length # Loading screen already removed (loaded +2sec)
+						@notifications.add("modified", "info", "New version of this page has just released.<br>Reload to see the modified content.")
+			# File failed downloading
+			else if site_info.event[0] == "file_failed" 
+				@site_error = site_info.event[1]
+				@loading.printLine("#{site_info.event[1]} download failed", "error")
+			# New peers found
+			else if site_info.event[0] == "peers_added" 
+				@loading.printLine("Peers found: #{site_info.peers}")
+
+		if @loading.screen_visible and not @site_info # First site info display current peers
+			if site_info.peers > 1
+				@loading.printLine "Peers found: #{site_info.peers}"
+			else
+				@site_error = "No peers found"
+				@loading.printLine "No peers found"
+		@site_info = site_info
+
+
+	log: (args...) ->
+		console.log "[Wrapper]", args...
+
+
+ws_url = "ws://#{window.location.hostname}:#{window.location.port}/Websocket?auth_key=#{window.auth_key}"
+window.wrapper = new Wrapper(ws_url)
diff --git a/src/Ui/media/Wrapper.css b/src/Ui/media/Wrapper.css
new file mode 100644
index 00000000..1f588186
--- /dev/null
+++ b/src/Ui/media/Wrapper.css
@@ -0,0 +1,102 @@
+body { margin: 0px; padding: 0px; height: 100%; background-color: #D2CECD; overflow: hidden }
+body.back { background-color: #090909 }
+a { color: black }
+
+.template { display: none !important }
+
+#inner-iframe { width: 100%; height: 100%; position: absolute; border: 0px; transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.8s ease-in-out }
+#inner-iframe.back { transform: scale(0.95) translate(-300px, 0px); opacity: 0.4 }
+
+
+/* Fixbutton */
+
+.fixbutton { 
+	position: absolute; right: 35px; top: 15px; width: 40px;  z-index: 999;
+	text-align: center; color: white; font-family: Consolas; font-size: 25px; line-height: 40px;
+}
+.fixbutton-bg { 
+	border-radius: 80px; background-color: rgba(180, 180, 180, 0.5); cursor: pointer;
+	display: block; width: 80px; height: 80px; transition: background-color 0.2s, box-shadow 0.5s; transform: scale(0.6); margin-left: -20px; margin-top: -20px; /* 2x size to prevent blur on anim */
+	/*box-shadow: inset 105px 260px 0px -200px rgba(0,0,0,0.1);*/ /* box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); */
+}
+.fixbutton-text { pointer-events: none; position: absolute; z-index: 999; width: 40px; backface-visibility: hidden; perspective: 1000px }
+.fixbutton-burger { pointer-events: none; position: absolute; z-index: 999; width: 40px; opacity: 0; left: -20px }
+.fixbutton-bg:hover { background-color: #AF3BFF }
+
+
+/* Notification */
+
+.notifications { position: absolute; top: 0px; right: 85px; display: inline-block; z-index: 999; white-space: nowrap }
+.notification { 
+	position: relative; float: right; clear: both; margin: 10px; height: 50px; box-sizing: border-box; overflow: hidden; backface-visibility: hidden; perspective: 1000px;
+	background-color: white; color: #4F4F4F; font-family: 'Helvetica Neue', 'Segoe UI', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px
+}
+.notification-icon { 
+	display: block; width: 50px; height: 50px; position: absolute; float: left; z-index: 1;
+	text-align: center; background-color: #e74c3c; line-height: 45px; vertical-align: bottom; font-size: 40px; color: white;
+}
+.notification .body { max-width: 420px; padding-left: 68px; padding-right: 17px; height: 50px; vertical-align: middle; display: table-cell }
+.notification.visible { max-width: 350px }
+
+.notification .close { position: absolute; top: 0px; right: 0px; font-size: 19px; line-height: 13px; color: #DDD; padding: 7px; text-decoration: none }
+.notification .close:hover { color: black }
+.notification .close:active, .notification .close:focus { color: #AF3BFF }
+
+/* Notification types */
+.notification-info .notification-icon { font-size: 22px; font-weight: bold; background-color: #2980b9; line-height: 48px }
+.notification-done .notification-icon { font-size: 22px; background-color: #27ae60 }
+
+
+/* Icons (based on http://nicolasgallagher.com/pure-css-gui-icons/demo/) */
+
+.icon-success { left:6px; width:5px; height:12px; border-width:0 5px 5px 0; border-style:solid; border-color:white; margin-left: 20px; margin-top: 15px; transform:rotate(45deg) }
+
+
+/* Loading screen */
+
+.loadingscreen { width: 100%; height: 100%; position: absolute; background-color: #EEE; z-index: 1; overflow: hidden; display: none }
+.loading-text { text-align: center; vertical-align: middle; top: 50%; position: absolute; margin-top: 39px; width: 100% }
+
+/* Console */
+.console { line-height: 24px; font-family: monospace; font-size: 14px; color: #ADADAD; text-transform: uppercase; opacity: 0; transform: translateY(-20px); }
+.console-line:last-child { color: #6C6767 }
+.console .cursor { 
+	background-color: #999; color: #999; animation: pulse 1.5s infinite ease-in-out; margin-right: -9px; 
+	display: inline-block; width: 9px; height: 19px; vertical-align: -4px; 
+}
+.console .console-error { color: #e74c3c; font-weight: bold; animation: pulse 2s infinite linear }
+
+/* Flipper loading anim */
+.flipper-container { width: 40px; height: 40px; position: absolute; top: 0%; left: 50%; transform: translate3d(-50%, -50%, 0); perspective: 1200; opacity: 0 }
+.flipper { position: relative; display: block; height: inherit; width: inherit; animation: flip 1.2s infinite ease-in-out; -webkit-transform-style: preserve-3d; }
+.flipper .front, .flipper .back {
+	position: absolute; top: 0; left: 0; backface-visibility: hidden; /*transform-style: preserve-3d;*/ display: block;
+	background-color: #d50000; height: 100%; width: 100%; /*outline: 1px solid transparent; /* FF AA fix */
+}
+.flipper .back { background-color: white; z-index: 800; transform: rotateY(-180deg) }
+
+/* Loading ready */
+.loadingscreen.ready .console { opacity: 1; transform: translateY(0px); transition: all 0.3s }
+.loadingscreen.ready .flipper-container { top: 50%; opacity: 1; transition: all 1s cubic-bezier(1, 0, 0, 1); }
+
+
+/* Loading done */
+.loadingscreen.done { height: 0%; transition: all 1s cubic-bezier(0.6, -0.28, 0.735, 0.045); }
+.loadingscreen.done .console { transform: translateY(300px); opacity: 0; transition: all 1.5s }
+.loadingscreen.done .flipper-container { opacity: 0; transition: all 1.5s }
+
+/* Animations */
+
+@keyframes flip {
+  0%   { transform: perspective(120px) rotateX(0deg) rotateY(0deg); }
+  50%  { transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) }
+  100% { transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); }
+}
+
+@keyframes pulse {
+  0%   { opacity: 0 }
+  5%   { opacity: 1 }
+  30%   { opacity: 1 }
+  70%  { opacity: 0 }
+  100% { opacity: 0 }
+}
diff --git a/src/Ui/media/all.css b/src/Ui/media/all.css
new file mode 100644
index 00000000..16df57ea
--- /dev/null
+++ b/src/Ui/media/all.css
@@ -0,0 +1,133 @@
+
+
+/* ---- src/Ui/media/Wrapper.css ---- */
+
+
+body { margin: 0px; padding: 0px; height: 100%; background-color: #D2CECD; overflow: hidden }
+body.back { background-color: #090909 }
+a { color: black }
+
+.template { display: none !important }
+
+#inner-iframe { width: 100%; height: 100%; position: absolute; border: 0px; -webkit-transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.8s ease-in-out ; -moz-transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.8s ease-in-out ; -o-transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.8s ease-in-out ; -ms-transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.8s ease-in-out ; transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55), opacity 0.8s ease-in-out  }
+#inner-iframe.back { -webkit-transform: scale(0.95) translate(-300px, 0px); -moz-transform: scale(0.95) translate(-300px, 0px); -o-transform: scale(0.95) translate(-300px, 0px); -ms-transform: scale(0.95) translate(-300px, 0px); transform: scale(0.95) translate(-300px, 0px) ; opacity: 0.4 }
+
+
+/* Fixbutton */
+
+.fixbutton { 
+	position: absolute; right: 35px; top: 15px; width: 40px;  z-index: 999;
+	text-align: center; color: white; font-family: Consolas; font-size: 25px; line-height: 40px;
+}
+.fixbutton-bg { 
+	-webkit-border-radius: 80px; -moz-border-radius: 80px; -o-border-radius: 80px; -ms-border-radius: 80px; border-radius: 80px ; background-color: rgba(180, 180, 180, 0.5); cursor: pointer;
+	display: block; width: 80px; height: 80px; -webkit-transition: background-color 0.2s, box-shadow 0.5s; -moz-transition: background-color 0.2s, box-shadow 0.5s; -o-transition: background-color 0.2s, box-shadow 0.5s; -ms-transition: background-color 0.2s, box-shadow 0.5s; transition: background-color 0.2s, box-shadow 0.5s ; -webkit-transform: scale(0.6); -moz-transform: scale(0.6); -o-transform: scale(0.6); -ms-transform: scale(0.6); transform: scale(0.6) ; margin-left: -20px; margin-top: -20px; /* 2x size to prevent blur on anim */
+	/*box-shadow: inset 105px 260px 0px -200px rgba(0,0,0,0.1);*/ /* -webkit-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); -moz-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); -o-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); -ms-box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1); box-shadow: inset -75px 183px 0px -200px rgba(0,0,0,0.1) ; */
+}
+.fixbutton-text { pointer-events: none; position: absolute; z-index: 999; width: 40px; backface-visibility: hidden; -webkit-perspective: 1000px ; -moz-perspective: 1000px ; -o-perspective: 1000px ; -ms-perspective: 1000px ; perspective: 1000px  }
+.fixbutton-burger { pointer-events: none; position: absolute; z-index: 999; width: 40px; opacity: 0; left: -20px }
+.fixbutton-bg:hover { background-color: #AF3BFF }
+
+
+/* Notification */
+
+.notifications { position: absolute; top: 0px; right: 85px; display: inline-block; z-index: 999; white-space: nowrap }
+.notification { 
+	position: relative; float: right; clear: both; margin: 10px; height: 50px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; -o-box-sizing: border-box; -ms-box-sizing: border-box; box-sizing: border-box ; overflow: hidden; backface-visibility: hidden; -webkit-perspective: 1000px; -moz-perspective: 1000px; -o-perspective: 1000px; -ms-perspective: 1000px; perspective: 1000px ;
+	background-color: white; color: #4F4F4F; font-family: 'Helvetica Neue', 'Segoe UI', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px
+}
+.notification-icon { 
+	display: block; width: 50px; height: 50px; position: absolute; float: left; z-index: 1;
+	text-align: center; background-color: #e74c3c; line-height: 45px; vertical-align: bottom; font-size: 40px; color: white;
+}
+.notification .body { max-width: 420px; padding-left: 68px; padding-right: 17px; height: 50px; vertical-align: middle; display: table-cell }
+.notification.visible { max-width: 350px }
+
+.notification .close { position: absolute; top: 0px; right: 0px; font-size: 19px; line-height: 13px; color: #DDD; padding: 7px; text-decoration: none }
+.notification .close:hover { color: black }
+.notification .close:active, .notification .close:focus { color: #AF3BFF }
+
+/* Notification types */
+.notification-info .notification-icon { font-size: 22px; font-weight: bold; background-color: #2980b9; line-height: 48px }
+.notification-done .notification-icon { font-size: 22px; background-color: #27ae60 }
+
+
+/* Icons (based on http://nicolasgallagher.com/pure-css-gui-icons/demo/) */
+
+.icon-success { left:6px; width:5px; height:12px; border-width:0 5px 5px 0; border-style:solid; border-color:white; margin-left: 20px; margin-top: 15px; transform:rotate(45deg) }
+
+
+/* Loading screen */
+
+.loadingscreen { width: 100%; height: 100%; position: absolute; background-color: #EEE; z-index: 1; overflow: hidden; display: none }
+.loading-text { text-align: center; vertical-align: middle; top: 50%; position: absolute; margin-top: 39px; width: 100% }
+
+/* Console */
+.console { line-height: 24px; font-family: monospace; font-size: 14px; color: #ADADAD; text-transform: uppercase; opacity: 0; -webkit-transform: translateY(-20px); -moz-transform: translateY(-20px); -o-transform: translateY(-20px); -ms-transform: translateY(-20px); transform: translateY(-20px) ; }
+.console-line:last-child { color: #6C6767 }
+.console .cursor { 
+	background-color: #999; color: #999; -webkit-animation: pulse 1.5s infinite ease-in-out; -moz-animation: pulse 1.5s infinite ease-in-out; -o-animation: pulse 1.5s infinite ease-in-out; -ms-animation: pulse 1.5s infinite ease-in-out; animation: pulse 1.5s infinite ease-in-out ; margin-right: -9px; 
+	display: inline-block; width: 9px; height: 19px; vertical-align: -4px; 
+}
+.console .console-error { color: #e74c3c; font-weight: bold; -webkit-animation: pulse 2s infinite linear ; -moz-animation: pulse 2s infinite linear ; -o-animation: pulse 2s infinite linear ; -ms-animation: pulse 2s infinite linear ; animation: pulse 2s infinite linear  }
+
+/* Flipper loading anim */
+.flipper-container { width: 40px; height: 40px; position: absolute; top: 0%; left: 50%; -webkit-transform: translate3d(-50%, -50%, 0); -moz-transform: translate3d(-50%, -50%, 0); -o-transform: translate3d(-50%, -50%, 0); -ms-transform: translate3d(-50%, -50%, 0); transform: translate3d(-50%, -50%, 0) ; -webkit-perspective: 1200; -moz-perspective: 1200; -o-perspective: 1200; -ms-perspective: 1200; perspective: 1200 ; opacity: 0 }
+.flipper { position: relative; display: block; height: inherit; width: inherit; -webkit-animation: flip 1.2s infinite ease-in-out; -moz-animation: flip 1.2s infinite ease-in-out; -o-animation: flip 1.2s infinite ease-in-out; -ms-animation: flip 1.2s infinite ease-in-out; animation: flip 1.2s infinite ease-in-out ; -webkit-transform-style: preserve-3d; }
+.flipper .front, .flipper .back {
+	position: absolute; top: 0; left: 0; backface-visibility: hidden; /*transform-style: preserve-3d;*/ display: block;
+	background-color: #d50000; height: 100%; width: 100%; /*outline: 1px solid transparent; /* FF AA fix */
+}
+.flipper .back { background-color: white; z-index: 800; -webkit-transform: rotateY(-180deg) ; -moz-transform: rotateY(-180deg) ; -o-transform: rotateY(-180deg) ; -ms-transform: rotateY(-180deg) ; transform: rotateY(-180deg)  }
+
+/* Loading ready */
+.loadingscreen.ready .console { opacity: 1; -webkit-transform: translateY(0px); -moz-transform: translateY(0px); -o-transform: translateY(0px); -ms-transform: translateY(0px); transform: translateY(0px) ; -webkit-transition: all 0.3s ; -moz-transition: all 0.3s ; -o-transition: all 0.3s ; -ms-transition: all 0.3s ; transition: all 0.3s  }
+.loadingscreen.ready .flipper-container { top: 50%; opacity: 1; -webkit-transition: all 1s cubic-bezier(1, 0, 0, 1); -moz-transition: all 1s cubic-bezier(1, 0, 0, 1); -o-transition: all 1s cubic-bezier(1, 0, 0, 1); -ms-transition: all 1s cubic-bezier(1, 0, 0, 1); transition: all 1s cubic-bezier(1, 0, 0, 1) ; }
+
+
+/* Loading done */
+.loadingscreen.done { height: 0%; -webkit-transition: all 1s cubic-bezier(0.6, -0.28, 0.735, 0.045); -moz-transition: all 1s cubic-bezier(0.6, -0.28, 0.735, 0.045); -o-transition: all 1s cubic-bezier(0.6, -0.28, 0.735, 0.045); -ms-transition: all 1s cubic-bezier(0.6, -0.28, 0.735, 0.045); transition: all 1s cubic-bezier(0.6, -0.28, 0.735, 0.045) ; }
+.loadingscreen.done .console { -webkit-transform: translateY(300px); -moz-transform: translateY(300px); -o-transform: translateY(300px); -ms-transform: translateY(300px); transform: translateY(300px) ; opacity: 0; -webkit-transition: all 1.5s ; -moz-transition: all 1.5s ; -o-transition: all 1.5s ; -ms-transition: all 1.5s ; transition: all 1.5s  }
+.loadingscreen.done .flipper-container { opacity: 0; -webkit-transition: all 1.5s ; -moz-transition: all 1.5s ; -o-transition: all 1.5s ; -ms-transition: all 1.5s ; transition: all 1.5s  }
+
+/* Animations */
+
+@keyframes flip {
+  0%   { -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg); -moz-transform: perspective(120px) rotateX(0deg) rotateY(0deg); -o-transform: perspective(120px) rotateX(0deg) rotateY(0deg); -ms-transform: perspective(120px) rotateX(0deg) rotateY(0deg); transform: perspective(120px) rotateX(0deg) rotateY(0deg) ; }
+  50%  { -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; -moz-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; -o-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; -ms-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)  }
+  100% { -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); -moz-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); -o-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); -ms-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg) ; }
+}
+@-webkit-keyframes flip {
+  0%   { -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg); -moz-transform: perspective(120px) rotateX(0deg) rotateY(0deg); -o-transform: perspective(120px) rotateX(0deg) rotateY(0deg); -ms-transform: perspective(120px) rotateX(0deg) rotateY(0deg); transform: perspective(120px) rotateX(0deg) rotateY(0deg) ; }
+  50%  { -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; -moz-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; -o-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; -ms-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)  }
+  100% { -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); -moz-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); -o-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); -ms-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg) ; }
+}
+@-moz-keyframes flip {
+  0%   { -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg); -moz-transform: perspective(120px) rotateX(0deg) rotateY(0deg); -o-transform: perspective(120px) rotateX(0deg) rotateY(0deg); -ms-transform: perspective(120px) rotateX(0deg) rotateY(0deg); transform: perspective(120px) rotateX(0deg) rotateY(0deg) ; }
+  50%  { -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; -moz-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; -o-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; -ms-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) ; transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)  }
+  100% { -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); -moz-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); -o-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); -ms-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg) ; }
+}
+
+
+@keyframes pulse {
+  0%   { opacity: 0 }
+  5%   { opacity: 1 }
+  30%   { opacity: 1 }
+  70%  { opacity: 0 }
+  100% { opacity: 0 }
+}
+@-webkit-keyframes pulse {
+  0%   { opacity: 0 }
+  5%   { opacity: 1 }
+  30%   { opacity: 1 }
+  70%  { opacity: 0 }
+  100% { opacity: 0 }
+}
+@-moz-keyframes pulse {
+  0%   { opacity: 0 }
+  5%   { opacity: 1 }
+  30%   { opacity: 1 }
+  70%  { opacity: 0 }
+  100% { opacity: 0 }
+}
+
diff --git a/src/Ui/media/all.js b/src/Ui/media/all.js
new file mode 100644
index 00000000..c519d7c6
--- /dev/null
+++ b/src/Ui/media/all.js
@@ -0,0 +1,895 @@
+
+
+/* ---- src/Ui/media\lib/00-jquery.min.js ---- */
+
+
+/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=mb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=nb(b);function qb(){}qb.prototype=d.filters=d.pseudos,d.setFilters=new qb,g=gb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?gb.error(a):z(a,i).slice(0)};function rb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)
+},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ab=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ib={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qb[0].contentDocument,b.write(),b.close(),c=sb(a,b),qb.detach()),rb[a]=c),c}var ub=/^margin/,vb=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wb=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xb(a,b,c){var d,e,f,g,h=a.style;return c=c||wb(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),vb.test(g)&&ub.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function yb(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var zb=/^(none|table(?!-c[ea]).+)/,Ab=new RegExp("^("+Q+")(.*)$","i"),Bb=new RegExp("^([+-])=("+Q+")","i"),Cb={position:"absolute",visibility:"hidden",display:"block"},Db={letterSpacing:"0",fontWeight:"400"},Eb=["Webkit","O","Moz","ms"];function Fb(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Eb.length;while(e--)if(b=Eb[e]+c,b in a)return b;return d}function Gb(a,b,c){var d=Ab.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Hb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ib(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wb(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xb(a,b,f),(0>e||null==e)&&(e=a.style[b]),vb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Hb(a,b,c||(g?"border":"content"),d,f)+"px"}function Jb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",tb(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Bb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xb(a,b,d)),"normal"===e&&b in Db&&(e=Db[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?zb.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Cb,function(){return Ib(a,b,d)}):Ib(a,b,d):void 0},set:function(a,c,d){var e=d&&wb(a);return Gb(a,c,d?Hb(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=yb(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ub.test(a)||(n.cssHooks[a+b].set=Gb)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Jb(this,!0)},hide:function(){return Jb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Kb(a,b,c,d,e){return new Kb.prototype.init(a,b,c,d,e)}n.Tween=Kb,Kb.prototype={constructor:Kb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Kb.propHooks[this.prop];return a&&a.get?a.get(this):Kb.propHooks._default.get(this)},run:function(a){var b,c=Kb.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Kb.propHooks._default.set(this),this}},Kb.prototype.init.prototype=Kb.prototype,Kb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Kb.propHooks.scrollTop=Kb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Kb.prototype.init,n.fx.step={};var Lb,Mb,Nb=/^(?:toggle|show|hide)$/,Ob=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pb=/queueHooks$/,Qb=[Vb],Rb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Ob.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Ob.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sb(){return setTimeout(function(){Lb=void 0}),Lb=n.now()}function Tb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ub(a,b,c){for(var d,e=(Rb[b]||[]).concat(Rb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Vb(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||tb(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Nb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?tb(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ub(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xb(a,b,c){var d,e,f=0,g=Qb.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Lb||Sb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:Lb||Sb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wb(k,j.opts.specialEasing);g>f;f++)if(d=Qb[f].call(j,a,k,j.opts))return d;return n.map(k,Ub,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xb,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Rb[c]=Rb[c]||[],Rb[c].unshift(b)},prefilter:function(a,b){b?Qb.unshift(a):Qb.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xb(this,n.extend({},a),f);(e||L.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Tb(b,!0),a,d,e)}}),n.each({slideDown:Tb("show"),slideUp:Tb("hide"),slideToggle:Tb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Lb=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Lb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Mb||(Mb=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Mb),Mb=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Yb,Zb,$b=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Zb:Yb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))
+},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Zb={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$b[b]||n.find.attr;$b[b]=function(a,b,d){var e,f;return d||(f=$b[b],$b[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$b[b]=f),e}});var _b=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_b.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ac=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ac," ").indexOf(b)>=0)return!0;return!1}});var bc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cc=n.now(),dc=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var ec=/#.*$/,fc=/([?&])_=[^&]*/,gc=/^(.*?):[ \t]*([^\r\n]*)$/gm,hc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ic=/^(?:GET|HEAD)$/,jc=/^\/\//,kc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,lc={},mc={},nc="*/".concat("*"),oc=a.location.href,pc=kc.exec(oc.toLowerCase())||[];function qc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function rc(a,b,c,d){var e={},f=a===mc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function sc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function uc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:oc,type:"GET",isLocal:hc.test(pc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":nc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sc(sc(a,n.ajaxSettings),b):sc(n.ajaxSettings,a)},ajaxPrefilter:qc(lc),ajaxTransport:qc(mc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gc.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||oc)+"").replace(ec,"").replace(jc,pc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=kc.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pc[1]&&h[2]===pc[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(pc[3]||("http:"===pc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rc(lc,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!ic.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(dc.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=fc.test(d)?d.replace(fc,"$1_="+cc++):d+(dc.test(d)?"&":"?")+"_="+cc++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+nc+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rc(mc,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tc(k,v,f)),u=uc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vc=/%20/g,wc=/\[\]$/,xc=/\r?\n/g,yc=/^(?:submit|button|image|reset|file)$/i,zc=/^(?:input|select|textarea|keygen)/i;function Ac(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wc.test(a)?d(a,e):Ac(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Ac(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ac(c,a[c],b,e);return d.join("&").replace(vc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&zc.test(this.nodeName)&&!yc.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xc,"\r\n")}}):{name:b.name,value:c.replace(xc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bc=0,Cc={},Dc={0:200,1223:204},Ec=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Cc)Cc[a]()}),k.cors=!!Ec&&"withCredentials"in Ec,k.ajax=Ec=!!Ec,n.ajaxTransport(function(a){var b;return k.cors||Ec&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cc[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Dc[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Cc[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Fc=[],Gc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Fc.pop()||n.expando+"_"+cc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Gc.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Gc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Gc,"$1"+e):b.jsonp!==!1&&(b.url+=(dc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Fc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Hc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Hc)return Hc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Ic=a.document.documentElement;function Jc(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Jc(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Ic;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ic})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Jc(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=yb(k.pixelPosition,function(a,c){return c?(c=xb(a,b),vb.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Kc=a.jQuery,Lc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Lc),b&&a.jQuery===n&&(a.jQuery=Kc),n},typeof b===U&&(a.jQuery=a.$=n),n});
+
+
+
+/* ---- src/Ui/media\lib/ZeroWebsocket.coffee ---- */
+
+
+(function() {
+  var ZeroWebsocket,
+    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
+    __slice = [].slice;
+
+  ZeroWebsocket = (function() {
+    function ZeroWebsocket(url) {
+      this.onCloseWebsocket = __bind(this.onCloseWebsocket, this);
+      this.onErrorWebsocket = __bind(this.onErrorWebsocket, this);
+      this.onOpenWebsocket = __bind(this.onOpenWebsocket, this);
+      this.log = __bind(this.log, this);
+      this.route = __bind(this.route, this);
+      this.onMessage = __bind(this.onMessage, this);
+      this.url = url;
+      this.next_message_id = 1;
+      this.waiting_cb = {};
+      this.init();
+    }
+
+    ZeroWebsocket.prototype.init = function() {
+      return this;
+    };
+
+    ZeroWebsocket.prototype.connect = function() {
+      this.ws = new WebSocket(this.url);
+      this.ws.onmessage = this.onMessage;
+      this.ws.onopen = this.onOpenWebsocket;
+      this.ws.onerror = this.onErrorWebsocket;
+      return this.ws.onclose = this.onCloseWebsocket;
+    };
+
+    ZeroWebsocket.prototype.onMessage = function(e) {
+      var cmd, message;
+      message = JSON.parse(e.data);
+      cmd = message.cmd;
+      if (cmd === "response") {
+        if (this.waiting_cb[message.to] != null) {
+          return this.waiting_cb[message.to](message.result);
+        } else {
+          return this.log("Websocket callback not found:", message);
+        }
+      } else if (cmd === "ping") {
+        return this.response(message.id, "pong");
+      } else {
+        return this.route(cmd, message);
+      }
+    };
+
+    ZeroWebsocket.prototype.route = function(cmd, message) {
+      return this.log("Unknown command", message);
+    };
+
+    ZeroWebsocket.prototype.response = function(to, result) {
+      return this.send({
+        "cmd": "response",
+        "to": to,
+        "result": result
+      });
+    };
+
+    ZeroWebsocket.prototype.cmd = function(cmd, params, cb) {
+      if (params == null) {
+        params = {};
+      }
+      if (cb == null) {
+        cb = null;
+      }
+      return this.send({
+        "cmd": cmd,
+        "params": params
+      }, cb);
+    };
+
+    ZeroWebsocket.prototype.send = function(message, cb) {
+      if (cb == null) {
+        cb = null;
+      }
+      if (message.id == null) {
+        message.id = this.next_message_id;
+        this.next_message_id += 1;
+      }
+      this.ws.send(JSON.stringify(message));
+      if (cb) {
+        return this.waiting_cb[message.id] = cb;
+      }
+    };
+
+    ZeroWebsocket.prototype.log = function() {
+      var args;
+      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+      return console.log.apply(console, ["[ZeroWebsocket]"].concat(__slice.call(args)));
+    };
+
+    ZeroWebsocket.prototype.onOpenWebsocket = function(e) {
+      this.log("Open", e);
+      if (this.onOpen != null) {
+        return this.onOpen(e);
+      }
+    };
+
+    ZeroWebsocket.prototype.onErrorWebsocket = function(e) {
+      this.log("Error", e);
+      if (this.onError != null) {
+        return this.onError(e);
+      }
+    };
+
+    ZeroWebsocket.prototype.onCloseWebsocket = function(e) {
+      this.log("Closed", e);
+      if (e.code === 1000) {
+        this.log("Server error, please reload the page");
+      } else {
+        setTimeout(((function(_this) {
+          return function() {
+            _this.log("Reconnecting...");
+            return _this.connect();
+          };
+        })(this)), 10000);
+      }
+      if (this.onClose != null) {
+        return this.onClose(e);
+      }
+    };
+
+    return ZeroWebsocket;
+
+  })();
+
+  window.ZeroWebsocket = ZeroWebsocket;
+
+}).call(this);
+
+
+
+/* ---- src/Ui/media\lib/jquery.cssanim.js ---- */
+
+
+jQuery.cssHooks['scale'] = {
+	get: function(elem, computed, extra) {
+		var match = window.getComputedStyle(elem).transform.match("[0-9\.]+")
+		if (match) {
+			var scale = parseFloat(match[0])
+			return scale
+		} else {
+			return 1.0
+		}
+	},
+	set: function(elem, val) {
+		//var transforms = $(elem).css("transform").match(/[0-9\.]+/g)
+		var transforms = window.getComputedStyle(elem).transform.match(/[0-9\.]+/g)
+		if (transforms) {
+			transforms[0] = val
+			transforms[3] = val
+			//$(elem).css("transform", 'matrix('+transforms.join(", ")+")")
+			elem.style.transform = 'matrix('+transforms.join(", ")+')'
+		} else {
+			elem.style.transform = "scale("+val+")"
+		}
+	}
+}
+
+jQuery.fx.step.scale = function(fx) {
+	jQuery.cssHooks['scale'].set(fx.elem, fx.now)
+};
+
+
+/* ---- src/Ui/media\lib/jquery.csslater.coffee ---- */
+
+
+(function() {
+  jQuery.fn.readdClass = function(class_name) {
+    var elem;
+    elem = this;
+    elem.removeClass(class_name);
+    setTimeout((function() {
+      return elem.addClass(class_name);
+    }), 1);
+    return this;
+  };
+
+  jQuery.fn.removeLater = function(time) {
+    var elem;
+    if (time == null) {
+      time = 500;
+    }
+    elem = this;
+    setTimeout((function() {
+      return elem.remove();
+    }), time);
+    return this;
+  };
+
+  jQuery.fn.hideLater = function(time) {
+    var elem;
+    if (time == null) {
+      time = 500;
+    }
+    elem = this;
+    setTimeout((function() {
+      return elem.css("display", "none");
+    }), time);
+    return this;
+  };
+
+  jQuery.fn.addClassLater = function(class_name, time) {
+    var elem;
+    if (time == null) {
+      time = 5;
+    }
+    elem = this;
+    setTimeout((function() {
+      return elem.addClass(class_name);
+    }), time);
+    return this;
+  };
+
+  jQuery.fn.cssLater = function(name, val, time) {
+    var elem;
+    if (time == null) {
+      time = 500;
+    }
+    elem = this;
+    setTimeout((function() {
+      return elem.css(name, val);
+    }), time);
+    return this;
+  };
+
+}).call(this);
+
+
+
+/* ---- src/Ui/media\lib/jquery.easing.1.3.js ---- */
+
+
+/*
+ * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
+ *
+ * Uses the built in easing capabilities added In jQuery 1.1
+ * to offer multiple easing options
+ *
+ * TERMS OF USE - jQuery Easing
+ * 
+ * Open source under the BSD License. 
+ * 
+ * Copyright © 2008 George McGinley Smith
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, this list of 
+ * conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list 
+ * of conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution.
+ * 
+ * Neither the name of the author nor the names of contributors may be used to endorse 
+ * or promote products derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
+ * OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+*/
+
+// t: current time, b: begInnIng value, c: change In value, d: duration
+jQuery.easing['jswing'] = jQuery.easing['swing'];
+
+jQuery.extend( jQuery.easing,
+{
+	def: 'easeOutQuad',
+	swing: function (x, t, b, c, d) {
+		//alert(jQuery.easing.default);
+		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
+	},
+	easeInQuad: function (x, t, b, c, d) {
+		return c*(t/=d)*t + b;
+	},
+	easeOutQuad: function (x, t, b, c, d) {
+		return -c *(t/=d)*(t-2) + b;
+	},
+	easeInOutQuad: function (x, t, b, c, d) {
+		if ((t/=d/2) < 1) return c/2*t*t + b;
+		return -c/2 * ((--t)*(t-2) - 1) + b;
+	},
+	easeInCubic: function (x, t, b, c, d) {
+		return c*(t/=d)*t*t + b;
+	},
+	easeOutCubic: function (x, t, b, c, d) {
+		return c*((t=t/d-1)*t*t + 1) + b;
+	},
+	easeInOutCubic: function (x, t, b, c, d) {
+		if ((t/=d/2) < 1) return c/2*t*t*t + b;
+		return c/2*((t-=2)*t*t + 2) + b;
+	},
+	easeInQuart: function (x, t, b, c, d) {
+		return c*(t/=d)*t*t*t + b;
+	},
+	easeOutQuart: function (x, t, b, c, d) {
+		return -c * ((t=t/d-1)*t*t*t - 1) + b;
+	},
+	easeInOutQuart: function (x, t, b, c, d) {
+		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
+		return -c/2 * ((t-=2)*t*t*t - 2) + b;
+	},
+	easeInQuint: function (x, t, b, c, d) {
+		return c*(t/=d)*t*t*t*t + b;
+	},
+	easeOutQuint: function (x, t, b, c, d) {
+		return c*((t=t/d-1)*t*t*t*t + 1) + b;
+	},
+	easeInOutQuint: function (x, t, b, c, d) {
+		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
+		return c/2*((t-=2)*t*t*t*t + 2) + b;
+	},
+	easeInSine: function (x, t, b, c, d) {
+		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
+	},
+	easeOutSine: function (x, t, b, c, d) {
+		return c * Math.sin(t/d * (Math.PI/2)) + b;
+	},
+	easeInOutSine: function (x, t, b, c, d) {
+		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
+	},
+	easeInExpo: function (x, t, b, c, d) {
+		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
+	},
+	easeOutExpo: function (x, t, b, c, d) {
+		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+	},
+	easeInOutExpo: function (x, t, b, c, d) {
+		if (t==0) return b;
+		if (t==d) return b+c;
+		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
+		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
+	},
+	easeInCirc: function (x, t, b, c, d) {
+		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
+	},
+	easeOutCirc: function (x, t, b, c, d) {
+		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
+	},
+	easeInOutCirc: function (x, t, b, c, d) {
+		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
+		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
+	},
+	easeInElastic: function (x, t, b, c, d) {
+		var s=1.70158;var p=0;var a=c;
+		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
+		if (a < Math.abs(c)) { a=c; var s=p/4; }
+		else var s = p/(2*Math.PI) * Math.asin (c/a);
+		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+	},
+	easeOutElastic: function (x, t, b, c, d) {
+		var s=1.70158;var p=0;var a=c;
+		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
+		if (a < Math.abs(c)) { a=c; var s=p/4; }
+		else var s = p/(2*Math.PI) * Math.asin (c/a);
+		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
+	},
+	easeInOutElastic: function (x, t, b, c, d) {
+		var s=1.70158;var p=0;var a=c;
+		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
+		if (a < Math.abs(c)) { a=c; var s=p/4; }
+		else var s = p/(2*Math.PI) * Math.asin (c/a);
+		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
+	},
+	easeInBack: function (x, t, b, c, d, s) {
+		if (s == undefined) s = 1.70158;
+		return c*(t/=d)*t*((s+1)*t - s) + b;
+	},
+	easeOutBack: function (x, t, b, c, d, s) {
+		if (s == undefined) s = 1.70158;
+		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
+	},
+	easeInOutBack: function (x, t, b, c, d, s) {
+		if (s == undefined) s = 1.70158; 
+		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
+		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
+	},
+	easeInBounce: function (x, t, b, c, d) {
+		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
+	},
+	easeOutBounce: function (x, t, b, c, d) {
+		if ((t/=d) < (1/2.75)) {
+			return c*(7.5625*t*t) + b;
+		} else if (t < (2/2.75)) {
+			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
+		} else if (t < (2.5/2.75)) {
+			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
+		} else {
+			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
+		}
+	},
+	easeInOutBounce: function (x, t, b, c, d) {
+		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
+		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
+	}
+});
+
+/*
+ *
+ * TERMS OF USE - EASING EQUATIONS
+ * 
+ * Open source under the BSD License. 
+ * 
+ * Copyright © 2001 Robert Penner
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, this list of 
+ * conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list 
+ * of conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution.
+ * 
+ * Neither the name of the author nor the names of contributors may be used to endorse 
+ * or promote products derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
+ * OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+
+/* ---- src/Ui/media/Loading.coffee ---- */
+
+
+(function() {
+  var Loading;
+
+  Loading = (function() {
+    function Loading() {
+      if (window.show_loadingscreen) {
+        this.showScreen();
+      }
+    }
+
+    Loading.prototype.showScreen = function() {
+      $(".loadingscreen").css("display", "block").addClassLater("ready");
+      this.screen_visible = true;
+      return this.printLine("&nbsp;&nbsp;&nbsp;Connecting...");
+    };
+
+    Loading.prototype.hideScreen = function() {
+      if (this.screen_visible) {
+        $(".loadingscreen").addClass("done").removeLater(2000);
+      } else {
+        $(".loadingscreen").remove();
+      }
+      return this.screen_visible = false;
+    };
+
+    Loading.prototype.print = function(text, type) {
+      var last_line;
+      if (type == null) {
+        type = "normal";
+      }
+      if (!this.screen_visible) {
+        return false;
+      }
+      $(".loadingscreen .console .cursor").remove();
+      last_line = $(".loadingscreen .console .console-line:last-child");
+      if (type === "error") {
+        text = "<span class='console-error'>" + text + "</span>";
+      }
+      return last_line.html(last_line.html() + text);
+    };
+
+    Loading.prototype.printLine = function(text, type) {
+      if (type == null) {
+        type = "normal";
+      }
+      if (!this.screen_visible) {
+        return false;
+      }
+      $(".loadingscreen .console .cursor").remove();
+      if (type === "error") {
+        text = "<span class='console-error'>" + text + "</span>";
+      } else {
+        text = text + "<span class='cursor'> </span>";
+      }
+      return $(".loadingscreen .console").append("<div class='console-line'>" + text + "</div>");
+    };
+
+    return Loading;
+
+  })();
+
+  window.Loading = Loading;
+
+}).call(this);
+
+
+
+/* ---- src/Ui/media/Notifications.coffee ---- */
+
+
+(function() {
+  var Notifications,
+    __slice = [].slice;
+
+  Notifications = (function() {
+    function Notifications(elem) {
+      this.elem = elem;
+      this;
+    }
+
+    Notifications.prototype.test = function() {
+      setTimeout(((function(_this) {
+        return function() {
+          _this.add("connection", "error", "Connection lost to <b>UiServer</b> on <b>localhost</b>!");
+          return _this.add("message-Anyone", "info", "New  from <b>Anyone</b>.");
+        };
+      })(this)), 1000);
+      return setTimeout(((function(_this) {
+        return function() {
+          return _this.add("connection", "done", "<b>UiServer</b> connection recovered.", 5000);
+        };
+      })(this)), 3000);
+    };
+
+    Notifications.prototype.add = function(id, type, body, timeout) {
+      var elem, width, _i, _len, _ref;
+      if (timeout == null) {
+        timeout = 0;
+      }
+      this.log(id, type, body, timeout);
+      _ref = $(".notification-" + id);
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        elem = _ref[_i];
+        this.close($(elem));
+      }
+      elem = $(".notification.template", this.elem).clone().removeClass("template");
+      elem.addClass("notification-" + type).addClass("notification-" + id);
+      if (type === "error") {
+        $(".notification-icon", elem).html("!");
+      } else if (type === "done") {
+        $(".notification-icon", elem).html("<div class='icon-success'></div>");
+      } else {
+        $(".notification-icon", elem).html("i");
+      }
+      $(".body", elem).html(body);
+      elem.appendTo(this.elem);
+      if (timeout) {
+        $(".close", elem).remove();
+        setTimeout(((function(_this) {
+          return function() {
+            return _this.close(elem);
+          };
+        })(this)), timeout);
+      }
+      width = elem.outerWidth();
+      if (!timeout) {
+        width += 20;
+      }
+      elem.css({
+        "width": "50px",
+        "transform": "scale(0.01)"
+      });
+      elem.animate({
+        "scale": 1
+      }, 800, "easeOutElastic");
+      elem.animate({
+        "width": width
+      }, 700, "easeInOutCubic");
+      $(".close", elem).on("click", (function(_this) {
+        return function() {
+          _this.close(elem);
+          return false;
+        };
+      })(this));
+      return this;
+    };
+
+    Notifications.prototype.close = function(elem) {
+      elem.stop().animate({
+        "width": 0,
+        "opacity": 0
+      }, 700, "easeInOutCubic");
+      return elem.slideUp(300, (function() {
+        return elem.remove();
+      }));
+    };
+
+    Notifications.prototype.log = function() {
+      var args;
+      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+      return console.log.apply(console, ["[Notifications]"].concat(__slice.call(args)));
+    };
+
+    return Notifications;
+
+  })();
+
+  window.Notifications = Notifications;
+
+}).call(this);
+
+
+
+/* ---- src/Ui/media/Sidebar.coffee ---- */
+
+
+(function() {
+  var Sidebar;
+
+  Sidebar = (function() {
+    function Sidebar() {
+      this.initFixbutton();
+    }
+
+    Sidebar.prototype.initFixbutton = function() {
+      $(".fixbutton-bg").on("mouseover", function() {
+        $(this).stop().animate({
+          "scale": 0.7
+        }, 800, "easeOutElastic");
+        $(".fixbutton-burger").stop().animate({
+          "opacity": 1.5,
+          "left": 0
+        }, 800, "easeOutElastic");
+        return $(".fixbutton-text").stop().animate({
+          "opacity": 0,
+          "left": 20
+        }, 300, "easeOutCubic");
+      });
+      $(".fixbutton-bg").on("mouseout", function() {
+        $(this).stop().animate({
+          "scale": 0.6
+        }, 300, "easeOutCubic");
+        $(".fixbutton-burger").stop().animate({
+          "opacity": 0,
+          "left": -20
+        }, 300, "easeOutCubic");
+        return $(".fixbutton-text").stop().animate({
+          "opacity": 1,
+          "left": 0
+        }, 300, "easeOutBack");
+      });
+
+      /*$(".fixbutton-bg").on "click", ->
+      			return false */
+      $(".fixbutton-bg").on("mousedown", function() {
+        return $(".fixbutton-burger").stop().animate({
+          "scale": 0.7,
+          "left": 0
+        }, 300, "easeOutCubic");
+      });
+      return $(".fixbutton-bg").on("mouseup", function() {
+        return $(".fixbutton-burger").stop().animate({
+          "scale": 1,
+          "left": 0
+        }, 600, "easeOutElastic");
+      });
+    };
+
+    return Sidebar;
+
+  })();
+
+  window.Sidebar = Sidebar;
+
+}).call(this);
+
+
+
+/* ---- src/Ui/media/Wrapper.coffee ---- */
+
+
+(function() {
+  var Wrapper, ws_url,
+    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
+    __slice = [].slice;
+
+  Wrapper = (function() {
+    function Wrapper(ws_url) {
+      this.onLoad = __bind(this.onLoad, this);
+      this.onCloseWebsocket = __bind(this.onCloseWebsocket, this);
+      this.onOpenWebsocket = __bind(this.onOpenWebsocket, this);
+      this.onMessageInner = __bind(this.onMessageInner, this);
+      this.onMessageWebsocket = __bind(this.onMessageWebsocket, this);
+      this.log("Created!");
+      this.loading = new Loading();
+      this.notifications = new Notifications($(".notifications"));
+      this.sidebar = new Sidebar();
+      window.addEventListener("message", this.onMessageInner, false);
+      this.inner = document.getElementById("inner-iframe").contentWindow;
+      this.ws = new ZeroWebsocket(ws_url);
+      this.ws.next_message_id = 1000000;
+      this.ws.onOpen = this.onOpenWebsocket;
+      this.ws.onClose = this.onCloseWebsocket;
+      this.ws.onMessage = this.onMessageWebsocket;
+      this.ws.connect();
+      this.ws_error = null;
+      this.site_info = null;
+      this.inner_loaded = false;
+      this.inner_ready = false;
+      this.wrapperWsInited = false;
+      this.site_error = null;
+      window.onload = this.onLoad;
+      this;
+    }
+
+    Wrapper.prototype.onMessageWebsocket = function(e) {
+      var cmd, message;
+      message = JSON.parse(e.data);
+      cmd = message.cmd;
+      if (cmd === "response") {
+        if (this.ws.waiting_cb[message.to] != null) {
+          return this.ws.waiting_cb[message.to](message.result);
+        } else {
+          return this.sendInner(message);
+        }
+      } else if (cmd === "notification") {
+        return this.notifications.add("notification-" + message.id, message.params[0], message.params[1], message.params[2]);
+      } else if (cmd === "setSiteInfo") {
+        this.sendInner(message);
+        if (message.params.address === window.address) {
+          return this.setSiteInfo(message.params);
+        }
+      } else {
+        return this.sendInner(message);
+      }
+    };
+
+    Wrapper.prototype.onMessageInner = function(e) {
+      var cmd, message;
+      message = e.data;
+      cmd = message.cmd;
+      if (cmd === "innerReady") {
+        this.inner_ready = true;
+        this.log("innerReady", this.ws.ws.readyState, this.wrapperWsInited);
+        if (this.ws.ws.readyState === 1 && !this.wrapperWsInited) {
+          this.sendInner({
+            "cmd": "wrapperOpenedWebsocket"
+          });
+          return this.wrapperWsInited = true;
+        }
+      } else if (cmd === "wrapperNotification") {
+        return this.notifications.add("notification-" + message.id, message.params[0], message.params[1], message.params[2]);
+      } else {
+        return this.ws.send(message);
+      }
+    };
+
+    Wrapper.prototype.onOpenWebsocket = function(e) {
+      this.ws.cmd("channelJoin", {
+        "channel": "siteChanged"
+      });
+      this.log("onOpenWebsocket", this.inner_ready, this.wrapperWsInited);
+      if (!this.wrapperWsInited && this.inner_ready) {
+        this.sendInner({
+          "cmd": "wrapperOpenedWebsocket"
+        });
+        this.wrapperWsInited = true;
+      }
+      if (this.inner_loaded) {
+        this.reloadSiteInfo();
+      }
+      setTimeout(((function(_this) {
+        return function() {
+          if (!_this.site_info) {
+            return _this.reloadSiteInfo();
+          }
+        };
+      })(this)), 2000);
+      if (this.ws_error) {
+        this.notifications.add("connection", "done", "Connection with <b>UiServer Websocket</b> recovered.", 6000);
+        return this.ws_error = null;
+      }
+    };
+
+    Wrapper.prototype.onCloseWebsocket = function(e) {
+      this.wrapperWsInited = false;
+      return setTimeout(((function(_this) {
+        return function() {
+          _this.sendInner({
+            "cmd": "wrapperClosedWebsocket"
+          });
+          if (e.code === 1000) {
+            return _this.ws_error = _this.notifications.add("connection", "error", "UiServer Websocket error, please reload the page.");
+          } else if (!_this.ws_error) {
+            return _this.ws_error = _this.notifications.add("connection", "error", "Connection with <b>UiServer Websocket</b> was lost. Reconnecting...");
+          }
+        };
+      })(this)), 500);
+    };
+
+    Wrapper.prototype.onLoad = function(e) {
+      this.log("onLoad", e);
+      this.inner_loaded = true;
+      if (!this.inner_ready) {
+        this.sendInner({
+          "cmd": "wrapperReady"
+        });
+      }
+      if (!this.site_error) {
+        this.loading.hideScreen();
+      }
+      if (this.ws.ws.readyState === 1 && !this.site_info) {
+        return this.reloadSiteInfo();
+      }
+    };
+
+    Wrapper.prototype.sendInner = function(message) {
+      return this.inner.postMessage(message, '*');
+    };
+
+    Wrapper.prototype.reloadSiteInfo = function() {
+      return this.ws.cmd("siteInfo", {}, (function(_this) {
+        return function(site_info) {
+          _this.setSiteInfo(site_info);
+          window.document.title = site_info.content.title + " - ZeroNet";
+          return _this.log("Setting title to", window.document.title);
+        };
+      })(this));
+    };
+
+    Wrapper.prototype.setSiteInfo = function(site_info) {
+      if (site_info.event != null) {
+        if (site_info.event[0] === "file_added" && site_info.bad_files.length) {
+          this.loading.printLine("" + site_info.bad_files.length + " files needs to be downloaded");
+        } else if (site_info.event[0] === "file_done") {
+          this.loading.printLine("" + site_info.event[1] + " downloaded");
+          if (site_info.event[1] === window.inner_path) {
+            this.loading.hideScreen();
+            if (!$(".loadingscreen").length) {
+              this.notifications.add("modified", "info", "New version of this page has just released.<br>Reload to see the modified content.");
+            }
+          }
+        } else if (site_info.event[0] === "file_failed") {
+          this.site_error = site_info.event[1];
+          this.loading.printLine("" + site_info.event[1] + " download failed", "error");
+        } else if (site_info.event[0] === "peers_added") {
+          this.loading.printLine("Peers found: " + site_info.peers);
+        }
+      }
+      if (this.loading.screen_visible && !this.site_info) {
+        if (site_info.peers > 1) {
+          this.loading.printLine("Peers found: " + site_info.peers);
+        } else {
+          this.site_error = "No peers found";
+          this.loading.printLine("No peers found");
+        }
+      }
+      return this.site_info = site_info;
+    };
+
+    Wrapper.prototype.log = function() {
+      var args;
+      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
+      return console.log.apply(console, ["[Wrapper]"].concat(__slice.call(args)));
+    };
+
+    return Wrapper;
+
+  })();
+
+  ws_url = "ws://" + window.location.hostname + ":" + window.location.port + "/Websocket?auth_key=" + window.auth_key;
+
+  window.wrapper = new Wrapper(ws_url);
+
+}).call(this);
diff --git a/src/Ui/media/img/favicon.ico b/src/Ui/media/img/favicon.ico
new file mode 100644
index 00000000..fad67073
Binary files /dev/null and b/src/Ui/media/img/favicon.ico differ
diff --git a/src/Ui/media/img/favicon.psd b/src/Ui/media/img/favicon.psd
new file mode 100644
index 00000000..1eea4ccf
Binary files /dev/null and b/src/Ui/media/img/favicon.psd differ
diff --git a/src/Ui/media/lib/00-jquery.min.js b/src/Ui/media/lib/00-jquery.min.js
new file mode 100644
index 00000000..25714ed2
--- /dev/null
+++ b/src/Ui/media/lib/00-jquery.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=mb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=nb(b);function qb(){}qb.prototype=d.filters=d.pseudos,d.setFilters=new qb,g=gb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?gb.error(a):z(a,i).slice(0)};function rb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)
+},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ab=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ib={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qb[0].contentDocument,b.write(),b.close(),c=sb(a,b),qb.detach()),rb[a]=c),c}var ub=/^margin/,vb=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wb=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xb(a,b,c){var d,e,f,g,h=a.style;return c=c||wb(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),vb.test(g)&&ub.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function yb(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var zb=/^(none|table(?!-c[ea]).+)/,Ab=new RegExp("^("+Q+")(.*)$","i"),Bb=new RegExp("^([+-])=("+Q+")","i"),Cb={position:"absolute",visibility:"hidden",display:"block"},Db={letterSpacing:"0",fontWeight:"400"},Eb=["Webkit","O","Moz","ms"];function Fb(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Eb.length;while(e--)if(b=Eb[e]+c,b in a)return b;return d}function Gb(a,b,c){var d=Ab.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Hb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ib(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wb(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xb(a,b,f),(0>e||null==e)&&(e=a.style[b]),vb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Hb(a,b,c||(g?"border":"content"),d,f)+"px"}function Jb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",tb(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Bb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xb(a,b,d)),"normal"===e&&b in Db&&(e=Db[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?zb.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Cb,function(){return Ib(a,b,d)}):Ib(a,b,d):void 0},set:function(a,c,d){var e=d&&wb(a);return Gb(a,c,d?Hb(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=yb(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ub.test(a)||(n.cssHooks[a+b].set=Gb)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Jb(this,!0)},hide:function(){return Jb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Kb(a,b,c,d,e){return new Kb.prototype.init(a,b,c,d,e)}n.Tween=Kb,Kb.prototype={constructor:Kb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Kb.propHooks[this.prop];return a&&a.get?a.get(this):Kb.propHooks._default.get(this)},run:function(a){var b,c=Kb.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Kb.propHooks._default.set(this),this}},Kb.prototype.init.prototype=Kb.prototype,Kb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Kb.propHooks.scrollTop=Kb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Kb.prototype.init,n.fx.step={};var Lb,Mb,Nb=/^(?:toggle|show|hide)$/,Ob=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pb=/queueHooks$/,Qb=[Vb],Rb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Ob.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Ob.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sb(){return setTimeout(function(){Lb=void 0}),Lb=n.now()}function Tb(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ub(a,b,c){for(var d,e=(Rb[b]||[]).concat(Rb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Vb(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||tb(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Nb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?tb(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ub(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xb(a,b,c){var d,e,f=0,g=Qb.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Lb||Sb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:Lb||Sb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wb(k,j.opts.specialEasing);g>f;f++)if(d=Qb[f].call(j,a,k,j.opts))return d;return n.map(k,Ub,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xb,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Rb[c]=Rb[c]||[],Rb[c].unshift(b)},prefilter:function(a,b){b?Qb.unshift(a):Qb.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xb(this,n.extend({},a),f);(e||L.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Tb(b,!0),a,d,e)}}),n.each({slideDown:Tb("show"),slideUp:Tb("hide"),slideToggle:Tb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Lb=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Lb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Mb||(Mb=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Mb),Mb=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Yb,Zb,$b=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Zb:Yb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))
+},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Zb={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$b[b]||n.find.attr;$b[b]=function(a,b,d){var e,f;return d||(f=$b[b],$b[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$b[b]=f),e}});var _b=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_b.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ac=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ac," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ac," ").indexOf(b)>=0)return!0;return!1}});var bc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cc=n.now(),dc=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var ec=/#.*$/,fc=/([?&])_=[^&]*/,gc=/^(.*?):[ \t]*([^\r\n]*)$/gm,hc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ic=/^(?:GET|HEAD)$/,jc=/^\/\//,kc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,lc={},mc={},nc="*/".concat("*"),oc=a.location.href,pc=kc.exec(oc.toLowerCase())||[];function qc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function rc(a,b,c,d){var e={},f=a===mc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function sc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function uc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:oc,type:"GET",isLocal:hc.test(pc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":nc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sc(sc(a,n.ajaxSettings),b):sc(n.ajaxSettings,a)},ajaxPrefilter:qc(lc),ajaxTransport:qc(mc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gc.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||oc)+"").replace(ec,"").replace(jc,pc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=kc.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pc[1]&&h[2]===pc[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(pc[3]||("http:"===pc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rc(lc,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!ic.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(dc.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=fc.test(d)?d.replace(fc,"$1_="+cc++):d+(dc.test(d)?"&":"?")+"_="+cc++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+nc+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rc(mc,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tc(k,v,f)),u=uc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vc=/%20/g,wc=/\[\]$/,xc=/\r?\n/g,yc=/^(?:submit|button|image|reset|file)$/i,zc=/^(?:input|select|textarea|keygen)/i;function Ac(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wc.test(a)?d(a,e):Ac(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Ac(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ac(c,a[c],b,e);return d.join("&").replace(vc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&zc.test(this.nodeName)&&!yc.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xc,"\r\n")}}):{name:b.name,value:c.replace(xc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bc=0,Cc={},Dc={0:200,1223:204},Ec=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Cc)Cc[a]()}),k.cors=!!Ec&&"withCredentials"in Ec,k.ajax=Ec=!!Ec,n.ajaxTransport(function(a){var b;return k.cors||Ec&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cc[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Dc[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Cc[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Fc=[],Gc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Fc.pop()||n.expando+"_"+cc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Gc.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Gc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Gc,"$1"+e):b.jsonp!==!1&&(b.url+=(dc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Fc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Hc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Hc)return Hc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Ic=a.document.documentElement;function Jc(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Jc(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Ic;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ic})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Jc(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=yb(k.pixelPosition,function(a,c){return c?(c=xb(a,b),vb.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Kc=a.jQuery,Lc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Lc),b&&a.jQuery===n&&(a.jQuery=Kc),n},typeof b===U&&(a.jQuery=a.$=n),n});
diff --git a/src/Ui/media/lib/ZeroWebsocket.coffee b/src/Ui/media/lib/ZeroWebsocket.coffee
new file mode 100644
index 00000000..4877d477
--- /dev/null
+++ b/src/Ui/media/lib/ZeroWebsocket.coffee
@@ -0,0 +1,81 @@
+class ZeroWebsocket
+	constructor: (url) ->
+		@url = url
+		@next_message_id = 1
+		@waiting_cb = {}
+		@init()
+
+
+	init: ->
+		@
+
+
+	connect: ->
+		@ws = new WebSocket(@url)
+		@ws.onmessage = @onMessage
+		@ws.onopen = @onOpenWebsocket
+		@ws.onerror = @onErrorWebsocket
+		@ws.onclose = @onCloseWebsocket
+
+
+	onMessage: (e) =>
+		message = JSON.parse(e.data)
+		cmd = message.cmd
+		if cmd == "response"
+			if @waiting_cb[message.to]?
+				@waiting_cb[message.to](message.result)
+			else
+				@log "Websocket callback not found:", message
+		else if cmd == "ping"
+			@response message.id, "pong"
+		else
+			@route cmd, message
+
+	route: (cmd, message) =>
+		@log "Unknown command", message
+
+
+	response: (to, result) ->
+		@send {"cmd": "response", "to": to, "result": result}
+
+
+	cmd: (cmd, params={}, cb=null) ->
+		@send {"cmd": cmd, "params": params}, cb
+
+
+	send: (message, cb=null) ->
+		if not message.id?
+			message.id = @next_message_id
+			@next_message_id += 1
+		@ws.send(JSON.stringify(message))
+		if cb
+			@waiting_cb[message.id] = cb
+
+
+	log: (args...) =>
+		console.log "[ZeroWebsocket]", args...
+
+
+	onOpenWebsocket: (e) =>
+		@log "Open", e
+		if @onOpen? then @onOpen(e)
+
+
+	onErrorWebsocket: (e) =>
+		@log "Error", e
+		if @onError? then @onError(e)
+
+
+	onCloseWebsocket: (e) =>
+		@log "Closed", e
+		if e.code == 1000
+			@log "Server error, please reload the page"
+		else # Connection error
+			setTimeout (=>
+				@log "Reconnecting..."
+				@connect()
+			), 10000
+		if @onClose? then @onClose(e)
+
+
+window.ZeroWebsocket = ZeroWebsocket
diff --git a/src/Ui/media/lib/jquery.cssanim.js b/src/Ui/media/lib/jquery.cssanim.js
new file mode 100644
index 00000000..6b0aaf1b
--- /dev/null
+++ b/src/Ui/media/lib/jquery.cssanim.js
@@ -0,0 +1,27 @@
+jQuery.cssHooks['scale'] = {
+	get: function(elem, computed, extra) {
+		var match = window.getComputedStyle(elem).transform.match("[0-9\.]+")
+		if (match) {
+			var scale = parseFloat(match[0])
+			return scale
+		} else {
+			return 1.0
+		}
+	},
+	set: function(elem, val) {
+		//var transforms = $(elem).css("transform").match(/[0-9\.]+/g)
+		var transforms = window.getComputedStyle(elem).transform.match(/[0-9\.]+/g)
+		if (transforms) {
+			transforms[0] = val
+			transforms[3] = val
+			//$(elem).css("transform", 'matrix('+transforms.join(", ")+")")
+			elem.style.transform = 'matrix('+transforms.join(", ")+')'
+		} else {
+			elem.style.transform = "scale("+val+")"
+		}
+	}
+}
+
+jQuery.fx.step.scale = function(fx) {
+	jQuery.cssHooks['scale'].set(fx.elem, fx.now)
+};
\ No newline at end of file
diff --git a/src/Ui/media/lib/jquery.csslater.coffee b/src/Ui/media/lib/jquery.csslater.coffee
new file mode 100644
index 00000000..43c94149
--- /dev/null
+++ b/src/Ui/media/lib/jquery.csslater.coffee
@@ -0,0 +1,35 @@
+jQuery.fn.readdClass = (class_name) ->
+	elem = @
+	elem.removeClass class_name
+	setTimeout ( ->
+		elem.addClass class_name
+	), 1
+	return @
+
+jQuery.fn.removeLater = (time = 500) ->
+	elem = @
+	setTimeout ( ->
+		elem.remove()
+	), time
+	return @
+
+jQuery.fn.hideLater = (time = 500) ->
+	elem = @
+	setTimeout ( ->
+		elem.css("display", "none")
+	), time
+	return @
+
+jQuery.fn.addClassLater = (class_name, time = 5) ->
+	elem = @
+	setTimeout ( ->
+		elem.addClass(class_name)
+	), time
+	return @
+
+jQuery.fn.cssLater = (name, val, time = 500) ->
+	elem = @
+	setTimeout ( ->
+		elem.css name, val
+	), time
+	return @
\ No newline at end of file
diff --git a/src/Ui/media/lib/jquery.easing.1.3.js b/src/Ui/media/lib/jquery.easing.1.3.js
new file mode 100644
index 00000000..ef743210
--- /dev/null
+++ b/src/Ui/media/lib/jquery.easing.1.3.js
@@ -0,0 +1,205 @@
+/*
+ * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
+ *
+ * Uses the built in easing capabilities added In jQuery 1.1
+ * to offer multiple easing options
+ *
+ * TERMS OF USE - jQuery Easing
+ * 
+ * Open source under the BSD License. 
+ * 
+ * Copyright © 2008 George McGinley Smith
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, this list of 
+ * conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list 
+ * of conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution.
+ * 
+ * Neither the name of the author nor the names of contributors may be used to endorse 
+ * or promote products derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
+ * OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+*/
+
+// t: current time, b: begInnIng value, c: change In value, d: duration
+jQuery.easing['jswing'] = jQuery.easing['swing'];
+
+jQuery.extend( jQuery.easing,
+{
+	def: 'easeOutQuad',
+	swing: function (x, t, b, c, d) {
+		//alert(jQuery.easing.default);
+		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
+	},
+	easeInQuad: function (x, t, b, c, d) {
+		return c*(t/=d)*t + b;
+	},
+	easeOutQuad: function (x, t, b, c, d) {
+		return -c *(t/=d)*(t-2) + b;
+	},
+	easeInOutQuad: function (x, t, b, c, d) {
+		if ((t/=d/2) < 1) return c/2*t*t + b;
+		return -c/2 * ((--t)*(t-2) - 1) + b;
+	},
+	easeInCubic: function (x, t, b, c, d) {
+		return c*(t/=d)*t*t + b;
+	},
+	easeOutCubic: function (x, t, b, c, d) {
+		return c*((t=t/d-1)*t*t + 1) + b;
+	},
+	easeInOutCubic: function (x, t, b, c, d) {
+		if ((t/=d/2) < 1) return c/2*t*t*t + b;
+		return c/2*((t-=2)*t*t + 2) + b;
+	},
+	easeInQuart: function (x, t, b, c, d) {
+		return c*(t/=d)*t*t*t + b;
+	},
+	easeOutQuart: function (x, t, b, c, d) {
+		return -c * ((t=t/d-1)*t*t*t - 1) + b;
+	},
+	easeInOutQuart: function (x, t, b, c, d) {
+		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
+		return -c/2 * ((t-=2)*t*t*t - 2) + b;
+	},
+	easeInQuint: function (x, t, b, c, d) {
+		return c*(t/=d)*t*t*t*t + b;
+	},
+	easeOutQuint: function (x, t, b, c, d) {
+		return c*((t=t/d-1)*t*t*t*t + 1) + b;
+	},
+	easeInOutQuint: function (x, t, b, c, d) {
+		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
+		return c/2*((t-=2)*t*t*t*t + 2) + b;
+	},
+	easeInSine: function (x, t, b, c, d) {
+		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
+	},
+	easeOutSine: function (x, t, b, c, d) {
+		return c * Math.sin(t/d * (Math.PI/2)) + b;
+	},
+	easeInOutSine: function (x, t, b, c, d) {
+		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
+	},
+	easeInExpo: function (x, t, b, c, d) {
+		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
+	},
+	easeOutExpo: function (x, t, b, c, d) {
+		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+	},
+	easeInOutExpo: function (x, t, b, c, d) {
+		if (t==0) return b;
+		if (t==d) return b+c;
+		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
+		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
+	},
+	easeInCirc: function (x, t, b, c, d) {
+		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
+	},
+	easeOutCirc: function (x, t, b, c, d) {
+		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
+	},
+	easeInOutCirc: function (x, t, b, c, d) {
+		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
+		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
+	},
+	easeInElastic: function (x, t, b, c, d) {
+		var s=1.70158;var p=0;var a=c;
+		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
+		if (a < Math.abs(c)) { a=c; var s=p/4; }
+		else var s = p/(2*Math.PI) * Math.asin (c/a);
+		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+	},
+	easeOutElastic: function (x, t, b, c, d) {
+		var s=1.70158;var p=0;var a=c;
+		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
+		if (a < Math.abs(c)) { a=c; var s=p/4; }
+		else var s = p/(2*Math.PI) * Math.asin (c/a);
+		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
+	},
+	easeInOutElastic: function (x, t, b, c, d) {
+		var s=1.70158;var p=0;var a=c;
+		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
+		if (a < Math.abs(c)) { a=c; var s=p/4; }
+		else var s = p/(2*Math.PI) * Math.asin (c/a);
+		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
+		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
+	},
+	easeInBack: function (x, t, b, c, d, s) {
+		if (s == undefined) s = 1.70158;
+		return c*(t/=d)*t*((s+1)*t - s) + b;
+	},
+	easeOutBack: function (x, t, b, c, d, s) {
+		if (s == undefined) s = 1.70158;
+		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
+	},
+	easeInOutBack: function (x, t, b, c, d, s) {
+		if (s == undefined) s = 1.70158; 
+		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
+		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
+	},
+	easeInBounce: function (x, t, b, c, d) {
+		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
+	},
+	easeOutBounce: function (x, t, b, c, d) {
+		if ((t/=d) < (1/2.75)) {
+			return c*(7.5625*t*t) + b;
+		} else if (t < (2/2.75)) {
+			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
+		} else if (t < (2.5/2.75)) {
+			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
+		} else {
+			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
+		}
+	},
+	easeInOutBounce: function (x, t, b, c, d) {
+		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
+		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
+	}
+});
+
+/*
+ *
+ * TERMS OF USE - EASING EQUATIONS
+ * 
+ * Open source under the BSD License. 
+ * 
+ * Copyright © 2001 Robert Penner
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, this list of 
+ * conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list 
+ * of conditions and the following disclaimer in the documentation and/or other materials 
+ * provided with the distribution.
+ * 
+ * Neither the name of the author nor the names of contributors may be used to endorse 
+ * or promote products derived from this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
+ * OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
\ No newline at end of file
diff --git a/src/Ui/template/wrapper.html b/src/Ui/template/wrapper.html
new file mode 100644
index 00000000..46c0cc0d
--- /dev/null
+++ b/src/Ui/template/wrapper.html
@@ -0,0 +1,50 @@
+
+<!DOCTYPE html>
+
+<html>
+<head>
+ <title>{title} - ZeroNet</title>
+ <meta charset="utf-8">
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <link rel="stylesheet" href="/uimedia/all.css" />
+</head>
+<body>
+
+<!-- Fixed button -->
+<div class='fixbutton'>
+ <div class='fixbutton-text'>0</div>
+ <div class='fixbutton-burger'>&#9776;</div>
+ <a class='fixbutton-bg' href="/{homepage}"></a>
+</div>
+
+
+<!-- Notifications -->
+<div class='notifications'>
+ <div class='notification template'><span class='notification-icon'>!</span> <span class='body'>Test notification</span><a class="close" href="#Close">&times;</a><div style="clear: both"></div></div>
+</div>
+
+
+<!-- Loadingscreen -->
+<div class='loadingscreen'>
+ <div class='loading-text console'>
+ </div>
+ <div class="flipper-container">
+  <div class="flipper"> <div class="front"></div><div class="back"></div> </div>
+ </div>
+</div>
+
+
+<!-- Site Iframe -->
+<iframe src='/media/{address}/{inner_path}#auth_key={auth_key}' id='inner-iframe' sandbox="allow-forms allow-scripts allow-top-navigation"></iframe>
+
+
+<!-- Site info -->
+<script>address = "{address}"</script>
+<script>auth_key = "{auth_key}"</script>
+<script>inner_path = "{inner_path}"</script>
+<script>permissions = {permissions}</script>
+<script>show_loadingscreen = {show_loadingscreen}</script>
+<script type="text/javascript" src="/uimedia/all.js" asyc></script>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/src/Worker/Worker.py b/src/Worker/Worker.py
new file mode 100644
index 00000000..a1cfe737
--- /dev/null
+++ b/src/Worker/Worker.py
@@ -0,0 +1,68 @@
+import gevent, time, logging, shutil, os
+from Peer import Peer
+
+class Worker:
+	def __init__(self, manager, peer):
+		self.manager = manager
+		self.peer = peer
+		self.task = None
+		self.key = None
+		self.running = False
+		self.thread = None
+
+
+	# Downloader thread
+	def downloader(self):
+		while self.running:
+			# Try to pickup free file download task
+			task = self.manager.getTask(self.peer)
+			if not task: # Die, no more task
+				self.manager.log.debug("%s: No task found, stopping" % self.key)
+				break
+
+			if task["workers_num"] > 0: # Wait a bit if someone already working on it
+				self.manager.log.debug("%s: Someone already working on %s, sleeping 1 sec..." % (self.key, task["inner_path"]))
+				time.sleep(1)
+
+			if task["done"] == False:
+				self.task = task
+				task["workers_num"] += 1
+				buff = self.peer.getFile(task["site"].address, task["inner_path"])
+				if buff: # Download ok
+					correct = task["site"].verifyFile(task["inner_path"], buff)
+				else: # Download error
+					correct = False
+				if correct == True or correct == None: # Hash ok or same file
+					self.manager.log.debug("%s: Hash correct: %s" % (self.key, task["inner_path"]))
+					if task["done"] == False: # Task not done yet
+						buff.seek(0)
+						file_path = task["site"].getPath(task["inner_path"])
+						file_dir = os.path.dirname(file_path)
+						if not os.path.isdir(file_dir): os.makedirs(file_dir) # Make directory for files
+						file = open(file_path, "wb")
+						shutil.copyfileobj(buff, file) # Write buff to disk
+						file.close()
+						task["workers_num"] -= 1
+						self.manager.doneTask(task)
+					self.task = None
+				else: # Hash failed
+					self.task = None
+					self.peer.hash_failed += 1
+					if self.peer.hash_failed > 5: # Broken peer
+						break
+					task["workers_num"] -= 1
+					self.manager.log.error("%s: Hash failed: %s" % (self.key, task["inner_path"]))
+					time.sleep(1)
+		self.running = False
+		self.peer.disconnect()
+		self.manager.removeWorker(self)
+
+
+	# Start the worker
+	def start(self):
+		self.running = True
+		self.thread = gevent.spawn(self.downloader)
+
+	def stop(self):
+		self.running = False
+		self.manager.removeWorker(self)
diff --git a/src/Worker/WorkerManager.py b/src/Worker/WorkerManager.py
new file mode 100644
index 00000000..f54bc448
--- /dev/null
+++ b/src/Worker/WorkerManager.py
@@ -0,0 +1,131 @@
+from Worker import Worker
+import gevent, time, logging
+
+MAX_WORKERS = 10
+
+# Worker manager for site
+class WorkerManager:
+	def __init__(self, site):
+		self.site = site
+		self.workers = {} # Key: ip:port, Value: Worker.Worker
+		self.tasks = [] # {"evt": evt, "workers_num": 0, "site": self.site, "inner_path": inner_path, "done": False, "time_start": time.time(), "peers": peers}
+		self.log = logging.getLogger("WorkerManager:%s" % self.site.address_short)
+		self.process_taskchecker = gevent.spawn(self.checkTasks)
+
+
+	# Check expired tasks
+	def checkTasks(self):
+		while 1:
+			time.sleep(15) # Check every 30 sec
+			if not self.tasks: continue
+			tasks = self.tasks[:] # Copy it so removing elements wont cause any problem
+			for task in tasks:
+				if time.time() >= task["time_start"]+60: # Task timed out
+					self.log.debug("Cleaning up task: %s" % task)
+
+					# Clean up workers
+					workers = self.findWorkers(task)
+					for worker in workers:
+						worker.stop()
+
+					# Remove task
+					self.failTask(task)
+				elif time.time() >= task["time_start"]+15: # Task taking long time
+					self.log.debug("Task taking long time, find more peers: %s" % task["inner_path"])
+					task["site"].announce() # Find more peers
+					if task["peers"]: # Release the peer olck
+						self.log.debug("Task peer lock release: %s" % task["inner_path"])
+						task["peers"] = []
+						self.startWorkers()
+					continue # One reannounce per loop
+
+
+	# Returns the next free or less worked task
+	def getTask(self, peer, only_free=False):
+		best_task = None
+		for task in self.tasks: # Find out the task with lowest worker number
+			if task["peers"] and peer not in task["peers"]: continue # This peer not allowed to pick this task
+			if task["inner_path"] == "content.json": return task # Content.json always prority
+			if not best_task or task["workers_num"] < best_task["workers_num"]: # If task has lower worker number then its better
+				best_task = task
+		return best_task
+
+
+	# New peers added to site
+	def onPeers(self):
+		self.startWorkers()
+
+
+	# Start workers to process tasks
+	def startWorkers(self):
+		if len(self.workers) >= MAX_WORKERS: return False # Workers number already maxed
+		if not self.tasks: return False # No task for workers
+		for key, peer in self.site.peers.iteritems(): # One worker for every peer
+			if key not in self.workers and len(self.workers) < MAX_WORKERS: # We dont have worker for that peer and workers num less than max
+				worker = Worker(self, peer)
+				self.workers[key] = worker
+				worker.key = key
+				worker.start()
+				self.log.debug("Added worker: %s, workers: %s/%s" % (key, len(self.workers), MAX_WORKERS))
+
+
+	# Find workers by task
+	def findWorkers(self, task):
+		workers = []
+		for worker in self.workers.values():
+			if worker.task == task: workers.append(worker)
+		return workers
+
+	# Ends and remove a worker
+	def removeWorker(self, worker):
+		worker.running = False
+		del(self.workers[worker.key])
+		self.log.debug("Removed worker, workers: %s/%s" % (len(self.workers), MAX_WORKERS))
+
+
+	# Create new task and return asyncresult
+	def addTask(self, inner_path, peer=None):
+		self.site.onFileStart(inner_path) # First task, trigger site download started
+		task = self.findTask(inner_path)
+		if task: # Already has task for that file
+			if peer and task["peers"]: # This peer has new version too
+				task["peers"].append(peer)
+				self.startWorkers()
+			return task["evt"]
+		else: # No task for that file yet
+			evt = gevent.event.AsyncResult()
+			if peer:
+				peers = [peer] # Only download from this peer
+			else:
+				peers = None
+			task = {"evt": evt, "workers_num": 0, "site": self.site, "inner_path": inner_path, "done": False, "time_start": time.time(), "peers": peers}
+			self.tasks.append(task)
+			self.log.debug("New task: %s" % task)
+			self.startWorkers()
+			return evt
+
+
+	# Find a task using inner_path
+	def findTask(self, inner_path):
+		for task in self.tasks:
+			if task["inner_path"] == inner_path: 
+				return task
+		return None # Not found
+
+
+	# Mark a task failed
+	def failTask(self, task):
+		task["done"] = True
+		self.tasks.remove(task) # Remove from queue
+		self.site.onFileFail(task["inner_path"])
+		task["evt"].set(False)
+
+
+	# Mark a task done
+	def doneTask(self, task):
+		task["done"] = True
+		self.tasks.remove(task) # Remove from queue
+		self.site.onFileDone(task["inner_path"])
+		task["evt"].set(True)
+		if not self.tasks: self.site.onComplete() # No more task trigger site compelte
+
diff --git a/src/Worker/__init__.py b/src/Worker/__init__.py
new file mode 100644
index 00000000..26649852
--- /dev/null
+++ b/src/Worker/__init__.py
@@ -0,0 +1,2 @@
+from Worker import Worker
+from WorkerManager import WorkerManager
\ No newline at end of file
diff --git a/src/__init__.py b/src/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/lib/BitcoinECC/BitcoinECC.py b/src/lib/BitcoinECC/BitcoinECC.py
new file mode 100644
index 00000000..8ae7bea9
--- /dev/null
+++ b/src/lib/BitcoinECC/BitcoinECC.py
@@ -0,0 +1,466 @@
+# By: HurlSly
+# Source: https://github.com/HurlSly/Python/blob/master/BitcoinECC.py
+# Modified: random number generator in def GeneratePrivateKey(self):
+
+import random
+import hashlib
+import os
+
+class GaussInt:
+    #A class for the Gauss integers of the form a + b sqrt(n) where a,b are integers.
+    #n can be positive or negative.
+    def __init__(self,x,y,n,p=0):
+        if p:
+            self.x=x%p
+            self.y=y%p
+            self.n=n%p
+        else:
+            self.x=x
+            self.y=y
+            self.n=n
+
+        self.p=p
+        
+    def __add__(self,b):
+        return GaussInt(self.x+b.x,self.y+b.y,self.n,self.p)
+        
+    def __sub__(self,b):
+        return GaussInt(self.x-b.x,self.y-b.y,self.n,self.p)
+    
+    def __mul__(self,b):
+        return GaussInt(self.x*b.x+self.n*self.y*b.y,self.x*b.y+self.y*b.x,self.n,self.p)
+    
+    def __div__(self,b):
+        return GaussInt((self.x*b.x-self.n*self.y*b.y)/(b.x*b.x-self.n*b.y*b.y),(-self.x*b.y+self.y*b.x)/(b.x*b.x-self.n*b.y*b.y),self.n,self.p)
+    
+    def __eq__(self,b):
+        return self.x==b.x and self.y==b.y
+    
+    def __repr__(self):
+        if self.p:
+            return "%s+%s (%d,%d)"%(self.x,self.y,self.n,self.p)
+        else:
+            return "%s+%s (%d)"%(self.x,self.y,self.n)
+        
+    def __pow__(self,n):
+        b=Base(n,2)
+        t=GaussInt(1,0,self.n)
+        while b:
+            t=t*t
+            if b.pop():
+                t=self*t
+            
+        return t
+
+    def Inv(self):
+        return GaussInt(self.x/(self.x*self.x-self.n*self.y*self.y),-self.y/(self.x*self.x-self.n*self.y*self.y),self.n,self.p)
+
+def Cipolla(a,p):
+    #Find a square root of a modulo p using the algorithm of Cipolla
+    b=0
+    while pow((b*b-a)%p,(p-1)/2,p)==1:
+        b+=1
+
+    return (GaussInt(b,1,b**2-a,p)**((p+1)/2)).x
+    
+def Base(n,b):
+    #Decompose n in base b
+    l=[]
+    while n:
+        l.append(n%b)
+        n/=b
+
+    return l
+    
+def InvMod(a,n):
+    #Find the inverse mod n of a.
+    #Use the Extended Euclides Algorithm.
+    m=[]
+
+    s=n
+    while n:
+        m.append(a/n)
+        (a,n)=(n,a%n)
+
+    u=1
+    v=0
+    while m:
+        (u,v)=(v,u-m.pop()*v)
+
+    return u%s
+
+def b58encode(v):
+    #Encode a byte string to the Base58
+    digit="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
+    base=len(digit)
+    val=0    
+    for c in v:
+        val*=256
+        val+=ord(c)
+
+    result=""
+    while val:
+        (val,mod)=divmod(val,base)
+        result=digit[mod]+result
+
+    pad=0
+    for c in v:
+        if c=="\0":
+            pad+=1
+        else:
+            break
+
+    return (digit[0]*pad)+result
+
+def b58decode(v):
+    #Decode a Base58 string to byte string
+    digit="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
+    base=len(digit)
+    val=0    
+    for c in v:
+        val*=base
+        val+=digit.find(c)
+
+    result=""
+    while val:
+        (val,mod)=divmod(val,256)
+        result=chr(mod)+result
+
+    pad=0
+    for c in v:
+        if c==digit[0]:
+            pad+=1
+        else:
+            break
+
+    result="\0"*pad+result
+
+    return result
+
+def Byte2Hex(b):
+    #Convert a byte string to hex number
+    out=""
+    for x in b:
+        y=hex(ord(x))[2:]
+        if len(y)==1:
+            y="0"+y
+        out+="%2s"%y
+    
+    return out
+
+def Int2Byte(n,b):
+    #Convert a integer to a byte string of length b
+    out=""
+    
+    for i in range(b):
+        (n,m)=divmod(n,256)
+        out=chr(m)+out
+    
+    return out
+
+class EllipticCurvePoint:
+    #Main class
+    #It is an point on an Elliptic Curve
+    
+    def __init__(self,x,a,b,p,n=0):
+        #We store the coordinate in x and the elliptic curbe parameter.
+        #x is of length 3. This is the 3 projective coordinates of the point.
+        self.x=x[:]
+        self.a=a
+        self.b=b
+        self.p=p
+        self.n=n
+
+    def EqualProj(self,y):
+        #Does y equals self ?
+        #It computes self cross product with y and check if the result is 0.
+        return self.x[0]*y.x[1]==self.x[1]*y.x[0] and self.x[1]*y.x[2]==self.x[2]*y.x[1] and self.x[2]*y.x[0]==self.x[0]*y.x[2]
+
+    def __add__(self,y):
+        #The main function to add self and y
+        #It uses the formulas I derived in projective coordinates.
+        #Projectives coordinates are more performant than the usual (x,y) coordinates
+        #because it we don't need to compute inverse mod p, which is faster.
+        z=EllipticCurvePoint([0,0,0],self.a,self.b,self.p)
+
+        if self.EqualProj(y):
+            d=(2*self.x[1]*self.x[2])%self.p
+            d3=pow(d,3,self.p)
+            n=(3*pow(self.x[0],2,self.p)+self.a*pow(self.x[2],2,self.p))%self.p
+            
+            z.x[0]=(pow(n,2,self.p)*d*self.x[2]-2*d3*self.x[0])%self.p
+            z.x[1]=(3*self.x[0]*n*pow(d,2,self.p)-pow(n,3,self.p)*self.x[2]-self.x[1]*d3)%self.p
+            z.x[2]=(self.x[2]*d3)%self.p
+        else:
+            d=(y.x[0]*self.x[2]-y.x[2]*self.x[0])%self.p
+            d3=pow(d,3,self.p)
+            n=(y.x[1]*self.x[2]-self.x[1]*y.x[2])%self.p
+
+            z.x[0]=(y.x[2]*self.x[2]*pow(n,2,self.p)*d-d3*(y.x[2]*self.x[0]+y.x[0]*self.x[2]))%self.p
+            z.x[1]=(pow(d,2,self.p)*n*(2*self.x[0]*y.x[2]+y.x[0]*self.x[2])-pow(n,3,self.p)*self.x[2]*y.x[2]-self.x[1]*d3*y.x[2])%self.p
+            z.x[2]=(self.x[2]*d3*y.x[2])%self.p
+        
+        return z
+
+    def __mul__(self,n):
+        #The fast multiplication of point n times by itself.
+        b=Base(n,2)
+        t=EllipticCurvePoint(self.x,self.a,self.b,self.p)
+        b.pop()
+        while b:
+            t+=t
+            if b.pop():
+                t+=self
+                
+        return t
+
+    def __repr__(self):
+        #print a point in (x,y) coordinate.
+        return "x=%d\ny=%d\n"%((self.x[0]*InvMod(self.x[2],self.p))%self.p,(self.x[1]*InvMod(self.x[2],self.p))%self.p)
+    
+    def __eq__(self,x):
+        #Does self==x ?
+        return self.x==x.x and self.a==x.a and self.b==x.b and self.p==x.p
+    
+    def __ne__(self,x):
+        #Does self!=x ?
+        return self.x!=x.x or self.a!=x.a or self.b!=x.b or self.p!=x.p
+    
+    def Check(self):
+        #Is self on the curve ?
+        return (self.x[0]**3+self.a*self.x[0]*self.x[2]**2+self.b*self.x[2]**3-self.x[1]**2*self.x[2])%self.p==0
+
+    def GeneratePrivateKey(self):
+        #Generate a private key. It's just a random number between 1 and n-1.
+        #Of course, this function isn't cryptographically secure.
+        #Don't use it to generate your key. Use a cryptographically secure source of randomness instead.
+        #self.d = random.randint(1,self.n-1)
+        self.d = int(os.urandom(32).encode("hex"), 16) # Better random fix
+    
+    def SignECDSA(self,m):
+        #Sign a message. The private key is self.d .
+        h=hashlib.new("SHA256")
+        h.update(m)
+        z=int(h.hexdigest(),16)
+        
+        r=0
+        s=0
+        while not r or not s:
+            k=random.randint(1,self.n-1)
+            R=self*k
+            R.Normalize()
+            r=R.x[0]%self.n
+            s=(InvMod(k,self.n)*(z+r*self.d))%self.n
+
+        return (r,s)
+        
+    def CheckECDSA(self,sig,m):
+        #Check a signature (r,s) of the message m using the public key self.Q
+        # and the generator which is self.
+        #This is not the one used by Bitcoin because the public key isn't known;
+        # only a hash of the public key is known. See the next function.
+        (r,s)=sig        
+        
+        h=hashlib.new("SHA256")
+        h.update(m)
+        z=int(h.hexdigest(),16)
+        
+        if self.Q.x[2]==0:
+            return False
+        if not self.Q.Check():
+            return False
+        if (self.Q*self.n).x[2]!=0:
+            return False
+        if r<1 or r>self.n-1 or s<1 or s>self.n-1:
+            return False
+
+        w=InvMod(s,self.n)
+        u1=(z*w)%self.n
+        u2=(r*w)%self.n
+        R=self*u1+self.Q*u2
+        R.Normalize()
+
+        return (R.x[0]-r)%self.n==0
+
+    def VerifyMessageFromBitcoinAddress(self,adresse,m,sig):
+        #Check a signature (r,s) for the message m signed by the Bitcoin 
+        # address "addresse".
+        h=hashlib.new("SHA256")
+        h.update(m)
+        z=int(h.hexdigest(),16)
+        
+        (r,s)=sig
+        x=r
+        y2=(pow(x,3,self.p)+self.a*x+self.b)%self.p
+        y=Cipolla(y2,self.p)
+
+        for i in range(2):
+            kG=EllipticCurvePoint([x,y,1],self.a,self.b,self.p,self.n)  
+            mzG=self*((-z)%self.n)
+            self.Q=(kG*s+mzG)*InvMod(r,self.n)
+
+            adr=self.BitcoinAddresFromPublicKey()
+            if adr==adresse:
+                break
+            y=(-y)%self.p
+
+        if adr!=adresse:
+            return False
+
+        return True
+
+    def BitcoinAddressFromPrivate(self,pri=None):
+        #Transform a private key in base58 encoding to a bitcoin address.
+        #normal means "uncompressed".
+        if not pri:
+            print "Private Key :",
+            pri=raw_input()
+
+        normal=(len(pri)==51)
+        pri=b58decode(pri)
+        
+        if normal:
+            pri=pri[1:-4]
+        else:
+            pri=pri[1:-5]
+        
+        self.d=int(Byte2Hex(pri),16)
+        
+        return self.BitcoinAddress(normal)
+
+    def PrivateEncoding(self,normal=True):
+        #Encode a private key self.d to base58 encoding.
+        p=Int2Byte(self.d,32)
+        p="\80"+p
+        
+        if not normal:
+            p+=chr(1)
+
+        h=hashlib.new("SHA256")
+        h.update(p)
+        s=h.digest()
+        
+        h=hashlib.new("SHA256")
+        h.update(s)
+        s=h.digest()
+        
+        cs=s[:4]
+
+        p+=cs
+        p=b58encode(p)
+
+        return p
+
+    def BitcoinAddresFromPublicKey(self,normal=True):
+        #Find the bitcoin address from the public key self.Q
+        #We do normalization to go from the projective coordinates to the usual
+        # (x,y) coordinates.
+        self.Q.Normalize()
+        if normal:
+            pk=chr(4)+Int2Byte(self.Q.x[0],32)+Int2Byte((self.Q.x[1])%self.p,32)
+        else:
+            if self.Q.x[1]%2==0:
+                pk=chr(2)+Int2Byte(self.Q.x[0],32)
+            else:
+                pk=chr(3)+Int2Byte(self.Q.x[0],32)
+        
+        version=chr(0)
+        
+        h=hashlib.new("SHA256")
+        h.update(pk)
+        s=h.digest()
+
+        h=hashlib.new("RIPEMD160")
+        h.update(s)
+        kh=version+h.digest()
+
+        h=hashlib.new("SHA256")
+        h.update(kh)
+        cs=h.digest()
+
+        h=hashlib.new("SHA256")
+        h.update(cs)
+        cs=h.digest()[:4]
+
+        adr=b58encode(kh+cs)
+
+        return adr
+
+    def BitcoinAddress(self,normal=True):
+        #Computes a bitcoin address given the private key self.d.
+        self.Q=self*self.d
+        
+        return self.BitcoinAddresFromPublicKey(normal)
+    
+    def BitcoinAddressGenerator(self,k,filename):
+        #Generate Bitcoin address and write them in the filename in the multibit format.
+        #Change the date as you like.
+        f=open(filename,"w")
+        for i in range(k):
+            self.GeneratePrivateKey()
+            adr=self.BitcoinAddress()
+            p=self.PrivateEncoding()
+            f.write("#%s\n%s 2014-01-30T12:00:00Z\n"%(adr,p))
+
+            #print hex(self.d)
+            print adr,p
+        
+        f.close()
+
+    def TestSign(self):
+        #Test signature
+        self.GeneratePrivateKey()
+        self.Q=self*self.d
+        m="Hello World"
+        adresse=self.BitcoinAddresFromPublicKey()
+        (r,s)=self.SignECDSA(m)
+        
+        m="Hello World"
+        print self.VerifyMessageFromBitcoinAddress(adresse,m,r,s)
+
+    def Normalize(self):
+        #Transform projective coordinates of self to the usual (x,y) coordinates.
+        if self.x[2]:
+            self.x[0]=(self.x[0]*InvMod(self.x[2],self.p))%self.p
+            self.x[1]=(self.x[1]*InvMod(self.x[2],self.p))%self.p
+            self.x[2]=1
+        elif self.x[1]:
+            self.x[0]=(self.x[0]*InvMod(self.x[1],self.p))%self.p
+            self.x[1]=1
+        elif self.x[0]:
+            self.x[0]=1
+        else:
+            raise Exception
+
+def Bitcoin():
+    #Create the Bitcoin elliptiv curve
+    a=0
+    b=7
+    p=2**256-2**32-2**9-2**8-2**7-2**6-2**4-1
+    
+    #Create the generator G of the Bitcoin elliptic curve, with is order n.
+    Gx=int("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",16)
+    Gy=int("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",16)
+    n =int("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",16)
+    
+    #Create the generator    
+    return EllipticCurvePoint([Gx,Gy,1],a,b,p,n)
+
+
+if __name__ == "__main__":
+    bitcoin=Bitcoin()
+
+    #Generate the public key from the private one
+    print bitcoin.BitcoinAddressFromPrivate("23DKRBLkeDbcSaddsMYLAHXhanPmGwkWAhSPVGbspAkc72Hw9BdrDF")
+    print bitcoin.BitcoinAddress()
+
+    #Print the bitcoin address of the public key generated at the previous line
+    adr=bitcoin.BitcoinAddresFromPublicKey()
+    print adr
+
+    #Sign a message with the current address
+    m="Hello World"
+    sig=bitcoin.SignECDSA("Hello World")
+    #Verify the message using only the bitcoin adress, the signature and the message.
+    #Not using the public key as it is not needed.
+    print bitcoin.VerifyMessageFromBitcoinAddress(adr,m,sig)
diff --git a/src/lib/BitcoinECC/__init__.py b/src/lib/BitcoinECC/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/lib/__init__.py b/src/lib/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/lib/cssvendor/__init__.py b/src/lib/cssvendor/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/lib/cssvendor/cssvendor.py b/src/lib/cssvendor/cssvendor.py
new file mode 100644
index 00000000..4dbf4f95
--- /dev/null
+++ b/src/lib/cssvendor/cssvendor.py
@@ -0,0 +1,29 @@
+import re
+
+def prefix(content):
+	content = re.sub("@keyframes (.*? {.*?[^ ]})", "@keyframes \\1\n@-webkit-keyframes \\1\n@-moz-keyframes \\1\n", content, flags=re.DOTALL)
+	content = re.sub('([^-\*])(border-radius|box-shadow|transition|animation|box-sizing|transform|filter|perspective|animation-[a-z-]+): (.*?)([;}])', '\\1-webkit-\\2: \\3; -moz-\\2: \\3; -o-\\2: \\3; -ms-\\2: \\3; \\2: \\3 \\4', content)
+	content = re.sub('(?<=[^a-zA-Z0-9-])([a-zA-Z0-9-]+): {0,1}(linear-gradient)\((.*?)(\)[;\n])', 
+		'\\1: -webkit-\\2(\\3);'+
+		'\\1: -moz-\\2(\\3);'+
+		'\\1: -o-\\2(\\3);'+
+		'\\1: -ms-\\2(\\3);'+
+		'\\1: \\2(\\3);', content)
+	return content
+
+if __name__ == "__main__":
+	print prefix("""
+	.test {
+		border-radius: 5px;
+		background: linear-gradient(red, blue);
+	}
+
+
+	@keyframes flip {
+	  0%   { transform: perspective(120px) rotateX(0deg) rotateY(0deg); }
+	  50%  { transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) }
+	  100% { transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); }
+	} 
+
+
+	""")
\ No newline at end of file
diff --git a/src/lib/geventwebsocket/__init__.py b/src/lib/geventwebsocket/__init__.py
new file mode 100644
index 00000000..7e2e0167
--- /dev/null
+++ b/src/lib/geventwebsocket/__init__.py
@@ -0,0 +1,21 @@
+VERSION = (0, 9, 3, 'final', 0)
+
+__all__ = [
+    'WebSocketApplication',
+    'Resource',
+    'WebSocketServer',
+    'WebSocketError',
+    'get_version'
+]
+
+
+def get_version(*args, **kwargs):
+    from .utils import get_version
+    return get_version(*args, **kwargs)
+
+try:
+    from .resource import WebSocketApplication, Resource
+    from .server import WebSocketServer
+    from .exceptions import WebSocketError
+except ImportError:
+    pass
diff --git a/src/lib/geventwebsocket/exceptions.py b/src/lib/geventwebsocket/exceptions.py
new file mode 100644
index 00000000..e066727e
--- /dev/null
+++ b/src/lib/geventwebsocket/exceptions.py
@@ -0,0 +1,19 @@
+from socket import error as socket_error
+
+
+class WebSocketError(socket_error):
+    """
+    Base class for all websocket errors.
+    """
+
+
+class ProtocolError(WebSocketError):
+    """
+    Raised if an error occurs when de/encoding the websocket protocol.
+    """
+
+
+class FrameTooLargeException(ProtocolError):
+    """
+    Raised if a frame is received that is too large.
+    """
diff --git a/src/lib/geventwebsocket/gunicorn/__init__.py b/src/lib/geventwebsocket/gunicorn/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/lib/geventwebsocket/gunicorn/workers.py b/src/lib/geventwebsocket/gunicorn/workers.py
new file mode 100644
index 00000000..d0aa1369
--- /dev/null
+++ b/src/lib/geventwebsocket/gunicorn/workers.py
@@ -0,0 +1,6 @@
+from geventwebsocket.handler import WebSocketHandler
+from gunicorn.workers.ggevent import GeventPyWSGIWorker
+
+
+class GeventWebSocketWorker(GeventPyWSGIWorker):
+    wsgi_handler = WebSocketHandler
diff --git a/src/lib/geventwebsocket/handler.py b/src/lib/geventwebsocket/handler.py
new file mode 100644
index 00000000..be681cee
--- /dev/null
+++ b/src/lib/geventwebsocket/handler.py
@@ -0,0 +1,283 @@
+# Modified: Werkzeug Debugger workaround in run_websocket(self):
+
+import base64
+import hashlib
+import warnings
+
+from gevent.pywsgi import WSGIHandler
+from .websocket import WebSocket, Stream
+from .logging import create_logger
+
+
+class Client(object):
+    def __init__(self, address, ws):
+        self.address = address
+        self.ws = ws
+
+
+class WebSocketHandler(WSGIHandler):
+    """
+    Automatically upgrades the connection to a websocket.
+
+    To prevent the WebSocketHandler to call the underlying WSGI application,
+    but only setup the WebSocket negotiations, do:
+
+      mywebsockethandler.prevent_wsgi_call = True
+
+    before calling run_application().  This is useful if you want to do more
+    things before calling the app, and want to off-load the WebSocket
+    negotiations to this library.  Socket.IO needs this for example, to send
+    the 'ack' before yielding the control to your WSGI app.
+    """
+
+    SUPPORTED_VERSIONS = ('13', '8', '7')
+    GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+
+    def run_websocket(self):
+        """
+        Called when a websocket has been created successfully.
+        """
+
+        if getattr(self, 'prevent_wsgi_call', False):
+            return
+
+        # In case WebSocketServer is not used
+        if not hasattr(self.server, 'clients'):
+            self.server.clients = {}
+
+        # Since we're now a websocket connection, we don't care what the
+        # application actually responds with for the http response
+
+        try:
+            self.server.clients[self.client_address] = Client(
+                self.client_address, self.websocket)
+            if self.application.__class__.__name__ == "DebuggedApplication": # Modified: Werkzeug Debugger workaround (https://bitbucket.org/Jeffrey/gevent-websocket/issue/53/if-the-application-returns-a-generator-we)
+                list(self.application(self.environ, lambda s, h: []))
+            else:
+                self.application(self.environ, lambda s, h: [])
+        finally:
+            del self.server.clients[self.client_address]
+            if not self.websocket.closed:
+                self.websocket.close()
+            self.environ.update({
+                'wsgi.websocket': None
+            })
+            self.websocket = None
+
+    def run_application(self):
+        if (hasattr(self.server, 'pre_start_hook')
+                and self.server.pre_start_hook):
+            self.logger.debug("Calling pre-start hook")
+            if self.server.pre_start_hook(self):
+                return super(WebSocketHandler, self).run_application()
+
+        self.logger.debug("Initializing WebSocket")
+        self.result = self.upgrade_websocket()
+
+        if hasattr(self, 'websocket'):
+            if self.status and not self.headers_sent:
+                self.write('')
+
+            self.run_websocket()
+        else:
+            if self.status:
+                # A status was set, likely an error so just send the response
+                if not self.result:
+                    self.result = []
+
+                self.process_result()
+                return
+
+            # This handler did not handle the request, so defer it to the
+            # underlying application object
+            return super(WebSocketHandler, self).run_application()
+
+    def upgrade_websocket(self):
+        """
+        Attempt to upgrade the current environ into a websocket enabled
+        connection. If successful, the environ dict with be updated with two
+        new entries, `wsgi.websocket` and `wsgi.websocket_version`.
+
+        :returns: Whether the upgrade was successful.
+        """
+
+        # Some basic sanity checks first
+
+        self.logger.debug("Validating WebSocket request")
+
+        if self.environ.get('REQUEST_METHOD', '') != 'GET':
+            # This is not a websocket request, so we must not handle it
+            self.logger.debug('Can only upgrade connection if using GET method.')
+            return
+
+        upgrade = self.environ.get('HTTP_UPGRADE', '').lower()
+
+        if upgrade == 'websocket':
+            connection = self.environ.get('HTTP_CONNECTION', '').lower()
+
+            if 'upgrade' not in connection:
+                # This is not a websocket request, so we must not handle it
+                self.logger.warning("Client didn't ask for a connection "
+                                    "upgrade")
+                return
+        else:
+            # This is not a websocket request, so we must not handle it
+            return
+
+        if self.request_version != 'HTTP/1.1':
+            self.start_response('402 Bad Request', [])
+            self.logger.warning("Bad server protocol in headers")
+
+            return ['Bad protocol version']
+
+        if self.environ.get('HTTP_SEC_WEBSOCKET_VERSION'):
+            return self.upgrade_connection()
+        else:
+            self.logger.warning("No protocol defined")
+            self.start_response('426 Upgrade Required', [
+                ('Sec-WebSocket-Version', ', '.join(self.SUPPORTED_VERSIONS))])
+
+            return ['No Websocket protocol version defined']
+
+    def upgrade_connection(self):
+        """
+        Validate and 'upgrade' the HTTP request to a WebSocket request.
+
+        If an upgrade succeeded then then handler will have `start_response`
+        with a status of `101`, the environ will also be updated with
+        `wsgi.websocket` and `wsgi.websocket_version` keys.
+
+        :param environ: The WSGI environ dict.
+        :param start_response: The callable used to start the response.
+        :param stream: File like object that will be read from/written to by
+            the underlying WebSocket object, if created.
+        :return: The WSGI response iterator is something went awry.
+        """
+
+        self.logger.debug("Attempting to upgrade connection")
+
+        version = self.environ.get("HTTP_SEC_WEBSOCKET_VERSION")
+
+        if version not in self.SUPPORTED_VERSIONS:
+            msg = "Unsupported WebSocket Version: {0}".format(version)
+
+            self.logger.warning(msg)
+            self.start_response('400 Bad Request', [
+                ('Sec-WebSocket-Version', ', '.join(self.SUPPORTED_VERSIONS))
+            ])
+
+            return [msg]
+
+        key = self.environ.get("HTTP_SEC_WEBSOCKET_KEY", '').strip()
+
+        if not key:
+            # 5.2.1 (3)
+            msg = "Sec-WebSocket-Key header is missing/empty"
+
+            self.logger.warning(msg)
+            self.start_response('400 Bad Request', [])
+
+            return [msg]
+
+        try:
+            key_len = len(base64.b64decode(key))
+        except TypeError:
+            msg = "Invalid key: {0}".format(key)
+
+            self.logger.warning(msg)
+            self.start_response('400 Bad Request', [])
+
+            return [msg]
+
+        if key_len != 16:
+            # 5.2.1 (3)
+            msg = "Invalid key: {0}".format(key)
+
+            self.logger.warning(msg)
+            self.start_response('400 Bad Request', [])
+
+            return [msg]
+
+        # Check for WebSocket Protocols
+        requested_protocols = self.environ.get(
+            'HTTP_SEC_WEBSOCKET_PROTOCOL', '')
+        protocol = None
+
+        if hasattr(self.application, 'app_protocol'):
+            allowed_protocol = self.application.app_protocol(
+                self.environ['PATH_INFO'])
+
+            if allowed_protocol and allowed_protocol in requested_protocols:
+                protocol = allowed_protocol
+                self.logger.debug("Protocol allowed: {0}".format(protocol))
+
+        self.websocket = WebSocket(self.environ, Stream(self), self)
+        self.environ.update({
+            'wsgi.websocket_version': version,
+            'wsgi.websocket': self.websocket
+        })
+
+        headers = [
+            ("Upgrade", "websocket"),
+            ("Connection", "Upgrade"),
+            ("Sec-WebSocket-Accept", base64.b64encode(
+                hashlib.sha1(key + self.GUID).digest())),
+        ]
+
+        if protocol:
+            headers.append(("Sec-WebSocket-Protocol", protocol))
+
+        self.logger.debug("WebSocket request accepted, switching protocols")
+        self.start_response("101 Switching Protocols", headers)
+
+    @property
+    def logger(self):
+        if not hasattr(self.server, 'logger'):
+            self.server.logger = create_logger(__name__)
+
+        return self.server.logger
+
+    def log_request(self):
+        if '101' not in self.status:
+            self.logger.info(self.format_request())
+
+    @property
+    def active_client(self):
+        return self.server.clients[self.client_address]
+
+    def start_response(self, status, headers, exc_info=None):
+        """
+        Called when the handler is ready to send a response back to the remote
+        endpoint. A websocket connection may have not been created.
+        """
+        writer = super(WebSocketHandler, self).start_response(
+            status, headers, exc_info=exc_info)
+
+        self._prepare_response()
+
+        return writer
+
+    def _prepare_response(self):
+        """
+        Sets up the ``pywsgi.Handler`` to work with a websocket response.
+
+        This is used by other projects that need to support WebSocket
+        connections as part of a larger effort.
+        """
+        assert not self.headers_sent
+
+        if not self.environ.get('wsgi.websocket'):
+            # a WebSocket connection is not established, do nothing
+            return
+
+        # So that `finalize_headers` doesn't write a Content-Length header
+        self.provided_content_length = False
+
+        # The websocket is now controlling the response
+        self.response_use_chunked = False
+
+        # Once the request is over, the connection must be closed
+        self.close_connection = True
+
+        # Prevents the Date header from being written
+        self.provided_date = True
diff --git a/src/lib/geventwebsocket/logging.py b/src/lib/geventwebsocket/logging.py
new file mode 100644
index 00000000..554ca02d
--- /dev/null
+++ b/src/lib/geventwebsocket/logging.py
@@ -0,0 +1,31 @@
+from __future__ import absolute_import
+
+from logging import getLogger, StreamHandler, getLoggerClass, Formatter, DEBUG
+
+
+def create_logger(name, debug=False, format=None):
+        Logger = getLoggerClass()
+
+        class DebugLogger(Logger):
+            def getEffectiveLevel(x):
+                if x.level == 0 and debug:
+                    return DEBUG
+                else:
+                    return Logger.getEffectiveLevel(x)
+
+        class DebugHandler(StreamHandler):
+            def emit(x, record):
+                StreamHandler.emit(x, record) if debug else None
+
+        handler = DebugHandler()
+        handler.setLevel(DEBUG)
+
+        if format:
+            handler.setFormatter(Formatter(format))
+
+        logger = getLogger(name)
+        del logger.handlers[:]
+        logger.__class__ = DebugLogger
+        logger.addHandler(handler)
+
+        return logger
diff --git a/src/lib/geventwebsocket/protocols/__init__.py b/src/lib/geventwebsocket/protocols/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/lib/geventwebsocket/protocols/base.py b/src/lib/geventwebsocket/protocols/base.py
new file mode 100644
index 00000000..1c05ab62
--- /dev/null
+++ b/src/lib/geventwebsocket/protocols/base.py
@@ -0,0 +1,35 @@
+class BaseProtocol(object):
+    PROTOCOL_NAME = ''
+
+    def __init__(self, app):
+        self._app = app
+
+    def on_open(self):
+        self.app.on_open()
+
+    def on_message(self, message):
+        self.app.on_message(message)
+
+    def on_close(self, reason=None):
+        self.app.on_close(reason)
+
+    @property
+    def app(self):
+        if self._app:
+            return self._app
+        else:
+            raise Exception("No application coupled")
+
+    @property
+    def server(self):
+        if not hasattr(self.app, 'ws'):
+            return None
+
+        return self.app.ws.handler.server
+
+    @property
+    def handler(self):
+        if not hasattr(self.app, 'ws'):
+            return None
+
+        return self.app.ws.handler
diff --git a/src/lib/geventwebsocket/protocols/wamp.py b/src/lib/geventwebsocket/protocols/wamp.py
new file mode 100644
index 00000000..b5586537
--- /dev/null
+++ b/src/lib/geventwebsocket/protocols/wamp.py
@@ -0,0 +1,234 @@
+import inspect
+import random
+import string
+import types
+
+try:
+    import ujson as json
+except ImportError:
+    try:
+        import simplejson as json
+    except ImportError:
+        import json
+
+from ..exceptions import WebSocketError
+from .base import BaseProtocol
+
+
+def export_rpc(arg=None):
+    if isinstance(arg, types.FunctionType):
+        arg._rpc = arg.__name__
+    return arg
+
+
+def serialize(data):
+    return json.dumps(data)
+
+
+class Prefixes(object):
+    def __init__(self):
+        self.prefixes = {}
+
+    def add(self, prefix, uri):
+        self.prefixes[prefix] = uri
+
+    def resolve(self, curie_or_uri):
+        if "http://" in curie_or_uri:
+            return curie_or_uri
+        elif ':' in curie_or_uri:
+            prefix, proc = curie_or_uri.split(':', 1)
+            return self.prefixes[prefix] + proc
+        else:
+            raise Exception(curie_or_uri)
+
+
+class RemoteProcedures(object):
+    def __init__(self):
+        self.calls = {}
+
+    def register_procedure(self, uri, proc):
+        self.calls[uri] = proc
+
+    def register_object(self, uri, obj):
+        for k in inspect.getmembers(obj, inspect.ismethod):
+            if '_rpc' in k[1].__dict__:
+                proc_uri = uri + k[1]._rpc
+                self.calls[proc_uri] = (obj, k[1])
+
+    def call(self, uri, args):
+        if uri in self.calls:
+            proc = self.calls[uri]
+
+            # Do the correct call whether it's a function or instance method.
+            if isinstance(proc, tuple):
+                if proc[1].__self__ is None:
+                    # Create instance of object and call method
+                    return proc[1](proc[0](), *args)
+                else:
+                    # Call bound method on instance
+                    return proc[1](*args)
+            else:
+                return self.calls[uri](*args)
+        else:
+            raise Exception("no such uri '{}'".format(uri))
+
+
+class Channels(object):
+    def __init__(self):
+        self.channels = {}
+
+    def create(self, uri, prefix_matching=False):
+        if uri not in self.channels:
+            self.channels[uri] = []
+
+        # TODO: implement prefix matching
+
+    def subscribe(self, uri, client):
+        if uri in self.channels:
+            self.channels[uri].append(client)
+
+    def unsubscribe(self, uri, client):
+        if uri not in self.channels:
+            return
+
+        client_index = self.channels[uri].index(client)
+        self.channels[uri].pop(client_index)
+
+        if len(self.channels[uri]) == 0:
+            del self.channels[uri]
+
+    def publish(self, uri, event, exclude=None, eligible=None):
+        if uri not in self.channels:
+            return
+
+        # TODO: exclude & eligible
+
+        msg = [WampProtocol.MSG_EVENT, uri, event]
+
+        for client in self.channels[uri]:
+            try:
+                client.ws.send(serialize(msg))
+            except WebSocketError:
+                # Seems someone didn't unsubscribe before disconnecting
+                self.channels[uri].remove(client)
+
+
+class WampProtocol(BaseProtocol):
+    MSG_WELCOME = 0
+    MSG_PREFIX = 1
+    MSG_CALL = 2
+    MSG_CALL_RESULT = 3
+    MSG_CALL_ERROR = 4
+    MSG_SUBSCRIBE = 5
+    MSG_UNSUBSCRIBE = 6
+    MSG_PUBLISH = 7
+    MSG_EVENT = 8
+
+    PROTOCOL_NAME = "wamp"
+
+    def __init__(self, *args, **kwargs):
+        self.procedures = RemoteProcedures()
+        self.prefixes = Prefixes()
+        self.session_id = ''.join(
+            [random.choice(string.digits + string.letters)
+                for i in xrange(16)])
+
+        super(WampProtocol, self).__init__(*args, **kwargs)
+
+    def register_procedure(self, *args, **kwargs):
+        self.procedures.register_procedure(*args, **kwargs)
+
+    def register_object(self, *args, **kwargs):
+        self.procedures.register_object(*args, **kwargs)
+
+    def register_pubsub(self, *args, **kwargs):
+        if not hasattr(self.server, 'channels'):
+            self.server.channels = Channels()
+
+        self.server.channels.create(*args, **kwargs)
+
+    def do_handshake(self):
+        from geventwebsocket import get_version
+
+        welcome = [
+            self.MSG_WELCOME,
+            self.session_id,
+            1,
+            'gevent-websocket/' + get_version()
+        ]
+        self.app.ws.send(serialize(welcome))
+
+    def _get_exception_info(self, e):
+        uri = 'http://TODO#generic'
+        desc = str(type(e))
+        details = str(e)
+        return [uri, desc, details]
+
+    def rpc_call(self, data):
+        call_id, curie_or_uri = data[1:3]
+        args = data[3:]
+
+        if not isinstance(call_id, (str, unicode)):
+            raise Exception()
+        if not isinstance(curie_or_uri, (str, unicode)):
+            raise Exception()
+
+        uri = self.prefixes.resolve(curie_or_uri)
+
+        try:
+            result = self.procedures.call(uri, args)
+            result_msg = [self.MSG_CALL_RESULT, call_id, result]
+        except Exception, e:
+            result_msg = [self.MSG_CALL_ERROR,
+                          call_id] + self._get_exception_info(e)
+
+        self.app.on_message(serialize(result_msg))
+
+    def pubsub_action(self, data):
+        action = data[0]
+        curie_or_uri = data[1]
+
+        if not isinstance(action, int):
+            raise Exception()
+        if not isinstance(curie_or_uri, (str, unicode)):
+            raise Exception()
+
+        uri = self.prefixes.resolve(curie_or_uri)
+
+        if action == self.MSG_SUBSCRIBE and len(data) == 2:
+            self.server.channels.subscribe(data[1], self.handler.active_client)
+
+        elif action == self.MSG_UNSUBSCRIBE and len(data) == 2:
+            self.server.channels.unsubscribe(
+                data[1], self.handler.active_client)
+
+        elif action == self.MSG_PUBLISH and len(data) >= 3:
+            payload = data[2] if len(data) >= 3 else None
+            exclude = data[3] if len(data) >= 4 else None
+            eligible = data[4] if len(data) >= 5 else None
+
+            self.server.channels.publish(uri, payload, exclude, eligible)
+
+    def on_open(self):
+        self.app.on_open()
+        self.do_handshake()
+
+    def on_message(self, message):
+        data = json.loads(message)
+
+        if not isinstance(data, list):
+            raise Exception('incoming data is no list')
+
+        if data[0] == self.MSG_PREFIX and len(data) == 3:
+            prefix, uri = data[1:3]
+            self.prefixes.add(prefix, uri)
+
+        elif data[0] == self.MSG_CALL and len(data) >= 3:
+            return self.rpc_call(data)
+
+        elif data[0] in (self.MSG_SUBSCRIBE, self.MSG_UNSUBSCRIBE,
+                         self.MSG_PUBLISH):
+            return self.pubsub_action(data)
+        else:
+            raise Exception("Unknown call")
+
diff --git a/src/lib/geventwebsocket/resource.py b/src/lib/geventwebsocket/resource.py
new file mode 100644
index 00000000..36c1fb36
--- /dev/null
+++ b/src/lib/geventwebsocket/resource.py
@@ -0,0 +1,74 @@
+import re
+
+from .protocols.base import BaseProtocol
+from .exceptions import WebSocketError
+
+
+class WebSocketApplication(object):
+    protocol_class = BaseProtocol
+
+    def __init__(self, ws):
+        self.protocol = self.protocol_class(self)
+        self.ws = ws
+
+    def handle(self):
+        self.protocol.on_open()
+
+        while True:
+            try:
+                message = self.ws.receive()
+            except WebSocketError:
+                self.protocol.on_close()
+                break
+
+            self.protocol.on_message(message)
+
+    def on_open(self, *args, **kwargs):
+        pass
+
+    def on_close(self, *args, **kwargs):
+        pass
+
+    def on_message(self, message, *args, **kwargs):
+        self.ws.send(message, **kwargs)
+
+    @classmethod
+    def protocol_name(cls):
+        return cls.protocol_class.PROTOCOL_NAME
+
+
+class Resource(object):
+    def __init__(self, apps=None):
+        self.apps = apps if apps else []
+
+    def _app_by_path(self, environ_path):
+        # Which app matched the current path?
+
+        for path, app in self.apps.iteritems():
+            if re.match(path, environ_path):
+                return app
+
+    def app_protocol(self, path):
+        app = self._app_by_path(path)
+
+        if hasattr(app, 'protocol_name'):
+            return app.protocol_name()
+        else:
+            return ''
+
+    def __call__(self, environ, start_response):
+        environ = environ
+        current_app = self._app_by_path(environ['PATH_INFO'])
+
+        if current_app is None:
+            raise Exception("No apps defined")
+
+        if 'wsgi.websocket' in environ:
+            ws = environ['wsgi.websocket']
+            current_app = current_app(ws)
+            current_app.ws = ws  # TODO: needed?
+            current_app.handle()
+
+            return None
+        else:
+            return current_app(environ, start_response)
diff --git a/src/lib/geventwebsocket/server.py b/src/lib/geventwebsocket/server.py
new file mode 100644
index 00000000..00443b8a
--- /dev/null
+++ b/src/lib/geventwebsocket/server.py
@@ -0,0 +1,34 @@
+from gevent.pywsgi import WSGIServer
+
+from .handler import WebSocketHandler
+from .logging import create_logger
+
+
+class WebSocketServer(WSGIServer):
+    debug_log_format = (
+        '-' * 80 + '\n' +
+        '%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' +
+        '%(message)s\n' +
+        '-' * 80
+    )
+
+    def __init__(self, *args, **kwargs):
+        self.debug = kwargs.pop('debug', False)
+        self.pre_start_hook = kwargs.pop('pre_start_hook', None)
+        self._logger = None
+        self.clients = {}
+
+        kwargs['handler_class'] = WebSocketHandler
+        super(WebSocketServer, self).__init__(*args, **kwargs)
+
+    def handle(self, socket, address):
+        handler = self.handler_class(socket, address, self)
+        handler.handle()
+
+    @property
+    def logger(self):
+        if not self._logger:
+            self._logger = create_logger(
+                __name__, self.debug, self.debug_log_format)
+
+        return self._logger
diff --git a/src/lib/geventwebsocket/utf8validator.py b/src/lib/geventwebsocket/utf8validator.py
new file mode 100644
index 00000000..b8a3e8a5
--- /dev/null
+++ b/src/lib/geventwebsocket/utf8validator.py
@@ -0,0 +1,128 @@
+###############################################################################
+##
+##  Copyright 2011-2013 Tavendo GmbH
+##
+##  Note:
+##
+##  This code is a Python implementation of the algorithm
+##
+##            "Flexible and Economical UTF-8 Decoder"
+##
+##  by Bjoern Hoehrmann
+##
+##       bjoern@hoehrmann.de
+##       http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+##
+##  Licensed under the Apache License, Version 2.0 (the "License");
+##  you may not use this file except in compliance with the License.
+##  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+##  Unless required by applicable law or agreed to in writing, software
+##  distributed under the License is distributed on an "AS IS" BASIS,
+##  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+##  See the License for the specific language governing permissions and
+##  limitations under the License.
+##
+###############################################################################
+
+
+## use Cython implementation of UTF8 validator if available
+##
+try:
+    from wsaccel.utf8validator import Utf8Validator
+except:
+    ## fallback to pure Python implementation
+
+    class Utf8Validator:
+        """
+        Incremental UTF-8 validator with constant memory consumption (minimal
+        state).
+
+        Implements the algorithm "Flexible and Economical UTF-8 Decoder" by
+        Bjoern Hoehrmann (http://bjoern.hoehrmann.de/utf-8/decoder/dfa/).
+        """
+
+        ## DFA transitions
+        UTF8VALIDATOR_DFA = [
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  # 00..1f
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  # 20..3f
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  # 40..5f
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  # 60..7f
+            1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,  # 80..9f
+            7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,  # a0..bf
+            8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,  # c0..df
+            0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3,  # e0..ef
+            0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,  # f0..ff
+            0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1,  # s0..s0
+            1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1,  # s1..s2
+            1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,  # s3..s4
+            1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1,  # s5..s6
+            1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  # s7..s8
+        ]
+
+        UTF8_ACCEPT = 0
+        UTF8_REJECT = 1
+
+        def __init__(self):
+            self.reset()
+
+        def decode(self, b):
+            """
+            Eat one UTF-8 octet, and validate on the fly.
+
+            Returns UTF8_ACCEPT when enough octets have been consumed, in which case
+            self.codepoint contains the decoded Unicode code point.
+
+            Returns UTF8_REJECT when invalid UTF-8 was encountered.
+
+            Returns some other positive integer when more octets need to be eaten.
+            """
+            type = Utf8Validator.UTF8VALIDATOR_DFA[b]
+
+            if self.state != Utf8Validator.UTF8_ACCEPT:
+                self.codepoint = (b & 0x3f) | (self.codepoint << 6)
+            else:
+                self.codepoint = (0xff >> type) & b
+
+            self.state = Utf8Validator.UTF8VALIDATOR_DFA[256 + self.state * 16 + type]
+
+            return self.state
+
+        def reset(self):
+            """
+            Reset validator to start new incremental UTF-8 decode/validation.
+            """
+            self.state = Utf8Validator.UTF8_ACCEPT
+            self.codepoint = 0
+            self.i = 0
+
+        def validate(self, ba):
+            """
+            Incrementally validate a chunk of bytes provided as string.
+
+            Will return a quad (valid?, endsOnCodePoint?, currentIndex, totalIndex).
+
+            As soon as an octet is encountered which renders the octet sequence
+            invalid, a quad with valid? == False is returned. currentIndex returns
+            the index within the currently consumed chunk, and totalIndex the
+            index within the total consumed sequence that was the point of bail out.
+            When valid? == True, currentIndex will be len(ba) and totalIndex the
+            total amount of consumed bytes.
+            """
+
+            l = len(ba)
+
+            for i in xrange(l):
+                ## optimized version of decode(), since we are not interested in actual code points
+
+                self.state = Utf8Validator.UTF8VALIDATOR_DFA[256 + (self.state << 4) + Utf8Validator.UTF8VALIDATOR_DFA[ord(ba[i])]]
+
+                if self.state == Utf8Validator.UTF8_REJECT:
+                    self.i += i
+                    return False, False, i, self.i
+
+            self.i += l
+
+            return True, self.state == Utf8Validator.UTF8_ACCEPT, l, self.i
diff --git a/src/lib/geventwebsocket/utils.py b/src/lib/geventwebsocket/utils.py
new file mode 100644
index 00000000..2e5bc3b7
--- /dev/null
+++ b/src/lib/geventwebsocket/utils.py
@@ -0,0 +1,45 @@
+import subprocess
+
+
+def get_version(version=None):
+    "Returns a PEP 386-compliant version number from VERSION."
+
+    if version is None:
+        from geventwebsocket import VERSION as version
+    else:
+        assert len(version) == 5
+        assert version[3] in ('alpha', 'beta', 'rc', 'final')
+
+    # Now build the two parts of the version number:
+    # main = X.Y[.Z]
+    # sub = .devN - for pre-alpha releases
+    #     | {a|b|c}N - for alpha, beta and rc releases
+
+    parts = 2 if version[2] == 0 else 3
+    main = '.'.join(str(x) for x in version[:parts])
+
+    sub = ''
+    if version[3] == 'alpha' and version[4] == 0:
+        hg_changeset = get_hg_changeset()
+        if hg_changeset:
+            sub = '.dev{0}'.format(hg_changeset)
+
+    elif version[3] != 'final':
+        mapping = {'alpha': 'a', 'beta': 'b', 'rc': 'c'}
+        sub = mapping[version[3]] + str(version[4])
+
+    return str(main + sub)
+
+
+def get_hg_changeset():
+    rev, err = subprocess.Popen(
+        'hg id -i',
+        shell=True,
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE
+    ).communicate()
+
+    if err:
+        return None
+    else:
+        return rev.strip().replace('+', '')
diff --git a/src/lib/geventwebsocket/websocket.py b/src/lib/geventwebsocket/websocket.py
new file mode 100644
index 00000000..6d4f76d3
--- /dev/null
+++ b/src/lib/geventwebsocket/websocket.py
@@ -0,0 +1,543 @@
+import struct
+
+from socket import error
+
+from .exceptions import ProtocolError
+from .exceptions import WebSocketError
+from .exceptions import FrameTooLargeException
+
+from .utf8validator import Utf8Validator
+
+
+MSG_SOCKET_DEAD = "Socket is dead"
+MSG_ALREADY_CLOSED = "Connection is already closed"
+MSG_CLOSED = "Connection closed"
+
+
+class WebSocket(object):
+    """
+    Base class for supporting websocket operations.
+
+    :ivar environ: The http environment referenced by this connection.
+    :ivar closed: Whether this connection is closed/closing.
+    :ivar stream: The underlying file like object that will be read from /
+        written to by this WebSocket object.
+    """
+
+    __slots__ = ('utf8validator', 'utf8validate_last', 'environ', 'closed',
+                 'stream', 'raw_write', 'raw_read', 'handler')
+
+    OPCODE_CONTINUATION = 0x00
+    OPCODE_TEXT = 0x01
+    OPCODE_BINARY = 0x02
+    OPCODE_CLOSE = 0x08
+    OPCODE_PING = 0x09
+    OPCODE_PONG = 0x0a
+
+    def __init__(self, environ, stream, handler):
+        self.environ = environ
+        self.closed = False
+
+        self.stream = stream
+
+        self.raw_write = stream.write
+        self.raw_read = stream.read
+
+        self.utf8validator = Utf8Validator()
+        self.handler = handler
+
+    def __del__(self):
+        try:
+            self.close()
+        except:
+            # close() may fail if __init__ didn't complete
+            pass
+
+    def _decode_bytes(self, bytestring):
+        """
+        Internal method used to convert the utf-8 encoded bytestring into
+        unicode.
+
+        If the conversion fails, the socket will be closed.
+        """
+
+        if not bytestring:
+            return u''
+
+        try:
+            return bytestring.decode('utf-8')
+        except UnicodeDecodeError:
+            self.close(1007)
+
+            raise
+
+    def _encode_bytes(self, text):
+        """
+        :returns: The utf-8 byte string equivalent of `text`.
+        """
+
+        if isinstance(text, str):
+            return text
+
+        if not isinstance(text, unicode):
+            text = unicode(text or '')
+
+        return text.encode('utf-8')
+
+    def _is_valid_close_code(self, code):
+        """
+        :returns: Whether the returned close code is a valid hybi return code.
+        """
+        if code < 1000:
+            return False
+
+        if 1004 <= code <= 1006:
+            return False
+
+        if 1012 <= code <= 1016:
+            return False
+
+        if code == 1100:
+            # not sure about this one but the autobahn fuzzer requires it.
+            return False
+
+        if 2000 <= code <= 2999:
+            return False
+
+        return True
+
+    @property
+    def current_app(self):
+        if hasattr(self.handler.server.application, 'current_app'):
+            return self.handler.server.application.current_app
+        else:
+            # For backwards compatibility reasons
+            class MockApp():
+                def on_close(self, *args):
+                    pass
+
+            return MockApp()
+
+    @property
+    def origin(self):
+        if not self.environ:
+            return
+
+        return self.environ.get('HTTP_ORIGIN')
+
+    @property
+    def protocol(self):
+        if not self.environ:
+            return
+
+        return self.environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL')
+
+    @property
+    def version(self):
+        if not self.environ:
+            return
+
+        return self.environ.get('HTTP_SEC_WEBSOCKET_VERSION')
+
+    @property
+    def path(self):
+        if not self.environ:
+            return
+
+        return self.environ.get('PATH_INFO')
+
+    @property
+    def logger(self):
+        return self.handler.logger
+
+    def handle_close(self, header, payload):
+        """
+        Called when a close frame has been decoded from the stream.
+
+        :param header: The decoded `Header`.
+        :param payload: The bytestring payload associated with the close frame.
+        """
+        if not payload:
+            self.close(1000, None)
+
+            return
+
+        if len(payload) < 2:
+            raise ProtocolError('Invalid close frame: {0} {1}'.format(
+                header, payload))
+
+        code = struct.unpack('!H', str(payload[:2]))[0]
+        payload = payload[2:]
+
+        if payload:
+            validator = Utf8Validator()
+            val = validator.validate(payload)
+
+            if not val[0]:
+                raise UnicodeError
+
+        if not self._is_valid_close_code(code):
+            raise ProtocolError('Invalid close code {0}'.format(code))
+
+        self.close(code, payload)
+
+    def handle_ping(self, header, payload):
+        self.send_frame(payload, self.OPCODE_PONG)
+
+    def handle_pong(self, header, payload):
+        pass
+
+    def read_frame(self):
+        """
+        Block until a full frame has been read from the socket.
+
+        This is an internal method as calling this will not cleanup correctly
+        if an exception is called. Use `receive` instead.
+
+        :return: The header and payload as a tuple.
+        """
+
+        header = Header.decode_header(self.stream)
+
+        if header.flags:
+            raise ProtocolError
+
+        if not header.length:
+            return header, ''
+
+        try:
+            payload = self.raw_read(header.length)
+        except error:
+            payload = ''
+        except Exception:
+            # TODO log out this exception
+            payload = ''
+
+        if len(payload) != header.length:
+            raise WebSocketError('Unexpected EOF reading frame payload')
+
+        if header.mask:
+            payload = header.unmask_payload(payload)
+
+        return header, payload
+
+    def validate_utf8(self, payload):
+        # Make sure the frames are decodable independently
+        self.utf8validate_last = self.utf8validator.validate(payload)
+
+        if not self.utf8validate_last[0]:
+            raise UnicodeError("Encountered invalid UTF-8 while processing "
+                               "text message at payload octet index "
+                               "{0:d}".format(self.utf8validate_last[3]))
+
+    def read_message(self):
+        """
+        Return the next text or binary message from the socket.
+
+        This is an internal method as calling this will not cleanup correctly
+        if an exception is called. Use `receive` instead.
+        """
+        opcode = None
+        message = ""
+
+        while True:
+            header, payload = self.read_frame()
+            f_opcode = header.opcode
+
+            if f_opcode in (self.OPCODE_TEXT, self.OPCODE_BINARY):
+                # a new frame
+                if opcode:
+                    raise ProtocolError("The opcode in non-fin frame is "
+                                        "expected to be zero, got "
+                                        "{0!r}".format(f_opcode))
+
+                # Start reading a new message, reset the validator
+                self.utf8validator.reset()
+                self.utf8validate_last = (True, True, 0, 0)
+
+                opcode = f_opcode
+
+            elif f_opcode == self.OPCODE_CONTINUATION:
+                if not opcode:
+                    raise ProtocolError("Unexpected frame with opcode=0")
+
+            elif f_opcode == self.OPCODE_PING:
+                self.handle_ping(header, payload)
+                continue
+
+            elif f_opcode == self.OPCODE_PONG:
+                self.handle_pong(header, payload)
+                continue
+
+            elif f_opcode == self.OPCODE_CLOSE:
+                self.handle_close(header, payload)
+                return
+
+            else:
+                raise ProtocolError("Unexpected opcode={0!r}".format(f_opcode))
+
+            if opcode == self.OPCODE_TEXT:
+                self.validate_utf8(payload)
+
+            message += payload
+
+            if header.fin:
+                break
+
+        if opcode == self.OPCODE_TEXT:
+            self.validate_utf8(message)
+            return message
+        else:
+            return bytearray(message)
+
+    def receive(self):
+        """
+        Read and return a message from the stream. If `None` is returned, then
+        the socket is considered closed/errored.
+        """
+
+        if self.closed:
+            self.current_app.on_close(MSG_ALREADY_CLOSED)
+            raise WebSocketError(MSG_ALREADY_CLOSED)
+
+        try:
+            return self.read_message()
+        except UnicodeError:
+            self.close(1007)
+        except ProtocolError:
+            self.close(1002)
+        except error:
+            self.close()
+            self.current_app.on_close(MSG_CLOSED)
+
+        return None
+
+    def send_frame(self, message, opcode):
+        """
+        Send a frame over the websocket with message as its payload
+        """
+        if self.closed:
+            self.current_app.on_close(MSG_ALREADY_CLOSED)
+            raise WebSocketError(MSG_ALREADY_CLOSED)
+
+        if opcode == self.OPCODE_TEXT:
+            message = self._encode_bytes(message)
+        elif opcode == self.OPCODE_BINARY:
+            message = str(message)
+
+        header = Header.encode_header(True, opcode, '', len(message), 0)
+
+        try:
+            self.raw_write(header + message)
+        except error:
+            raise WebSocketError(MSG_SOCKET_DEAD)
+
+    def send(self, message, binary=None):
+        """
+        Send a frame over the websocket with message as its payload
+        """
+        if binary is None:
+            binary = not isinstance(message, (str, unicode))
+
+        opcode = self.OPCODE_BINARY if binary else self.OPCODE_TEXT
+
+        try:
+            self.send_frame(message, opcode)
+        except WebSocketError:
+            self.current_app.on_close(MSG_SOCKET_DEAD)
+            raise WebSocketError(MSG_SOCKET_DEAD)
+
+    def close(self, code=1000, message=''):
+        """
+        Close the websocket and connection, sending the specified code and
+        message.  The underlying socket object is _not_ closed, that is the
+        responsibility of the initiator.
+        """
+
+        if self.closed:
+            self.current_app.on_close(MSG_ALREADY_CLOSED)
+
+        try:
+            message = self._encode_bytes(message)
+
+            self.send_frame(
+                struct.pack('!H%ds' % len(message), code, message),
+                opcode=self.OPCODE_CLOSE)
+        except WebSocketError:
+            # Failed to write the closing frame but it's ok because we're
+            # closing the socket anyway.
+            self.logger.debug("Failed to write closing frame -> closing socket")
+        finally:
+            self.logger.debug("Closed WebSocket")
+            self.closed = True
+
+            self.stream = None
+            self.raw_write = None
+            self.raw_read = None
+
+            self.environ = None
+
+            #self.current_app.on_close(MSG_ALREADY_CLOSED)
+
+
+class Stream(object):
+    """
+    Wraps the handler's socket/rfile attributes and makes it in to a file like
+    object that can be read from/written to by the lower level websocket api.
+    """
+
+    __slots__ = ('handler', 'read', 'write')
+
+    def __init__(self, handler):
+        self.handler = handler
+        self.read = handler.rfile.read
+        self.write = handler.socket.sendall
+
+
+class Header(object):
+    __slots__ = ('fin', 'mask', 'opcode', 'flags', 'length')
+
+    FIN_MASK = 0x80
+    OPCODE_MASK = 0x0f
+    MASK_MASK = 0x80
+    LENGTH_MASK = 0x7f
+
+    RSV0_MASK = 0x40
+    RSV1_MASK = 0x20
+    RSV2_MASK = 0x10
+
+    # bitwise mask that will determine the reserved bits for a frame header
+    HEADER_FLAG_MASK = RSV0_MASK | RSV1_MASK | RSV2_MASK
+
+    def __init__(self, fin=0, opcode=0, flags=0, length=0):
+        self.mask = ''
+        self.fin = fin
+        self.opcode = opcode
+        self.flags = flags
+        self.length = length
+
+    def mask_payload(self, payload):
+        payload = bytearray(payload)
+        mask = bytearray(self.mask)
+
+        for i in xrange(self.length):
+            payload[i] ^= mask[i % 4]
+
+        return str(payload)
+
+    # it's the same operation
+    unmask_payload = mask_payload
+
+    def __repr__(self):
+        return ("<Header fin={0} opcode={1} length={2} flags={3} at "
+                "0x{4:x}>").format(self.fin, self.opcode, self.length,
+                                   self.flags, id(self))
+
+    @classmethod
+    def decode_header(cls, stream):
+        """
+        Decode a WebSocket header.
+
+        :param stream: A file like object that can be 'read' from.
+        :returns: A `Header` instance.
+        """
+        read = stream.read
+        data = read(2)
+
+        if len(data) != 2:
+            raise WebSocketError("Unexpected EOF while decoding header")
+
+        first_byte, second_byte = struct.unpack('!BB', data)
+
+        header = cls(
+            fin=first_byte & cls.FIN_MASK == cls.FIN_MASK,
+            opcode=first_byte & cls.OPCODE_MASK,
+            flags=first_byte & cls.HEADER_FLAG_MASK,
+            length=second_byte & cls.LENGTH_MASK)
+
+        has_mask = second_byte & cls.MASK_MASK == cls.MASK_MASK
+
+        if header.opcode > 0x07:
+            if not header.fin:
+                raise ProtocolError(
+                    "Received fragmented control frame: {0!r}".format(data))
+
+            # Control frames MUST have a payload length of 125 bytes or less
+            if header.length > 125:
+                raise FrameTooLargeException(
+                    "Control frame cannot be larger than 125 bytes: "
+                    "{0!r}".format(data))
+
+        if header.length == 126:
+            # 16 bit length
+            data = read(2)
+
+            if len(data) != 2:
+                raise WebSocketError('Unexpected EOF while decoding header')
+
+            header.length = struct.unpack('!H', data)[0]
+        elif header.length == 127:
+            # 64 bit length
+            data = read(8)
+
+            if len(data) != 8:
+                raise WebSocketError('Unexpected EOF while decoding header')
+
+            header.length = struct.unpack('!Q', data)[0]
+
+        if has_mask:
+            mask = read(4)
+
+            if len(mask) != 4:
+                raise WebSocketError('Unexpected EOF while decoding header')
+
+            header.mask = mask
+
+        return header
+
+    @classmethod
+    def encode_header(cls, fin, opcode, mask, length, flags):
+        """
+        Encodes a WebSocket header.
+
+        :param fin: Whether this is the final frame for this opcode.
+        :param opcode: The opcode of the payload, see `OPCODE_*`
+        :param mask: Whether the payload is masked.
+        :param length: The length of the frame.
+        :param flags: The RSV* flags.
+        :return: A bytestring encoded header.
+        """
+        first_byte = opcode
+        second_byte = 0
+        extra = ''
+
+        if fin:
+            first_byte |= cls.FIN_MASK
+
+        if flags & cls.RSV0_MASK:
+            first_byte |= cls.RSV0_MASK
+
+        if flags & cls.RSV1_MASK:
+            first_byte |= cls.RSV1_MASK
+
+        if flags & cls.RSV2_MASK:
+            first_byte |= cls.RSV2_MASK
+
+        # now deal with length complexities
+        if length < 126:
+            second_byte += length
+        elif length <= 0xffff:
+            second_byte += 126
+            extra = struct.pack('!H', length)
+        elif length <= 0xffffffffffffffff:
+            second_byte += 127
+            extra = struct.pack('!Q', length)
+        else:
+            raise FrameTooLargeException
+
+        if mask:
+            second_byte |= cls.MASK_MASK
+
+            extra += mask
+
+        return chr(first_byte) + chr(second_byte) + extra
diff --git a/src/lib/subtl/LICENCE b/src/lib/subtl/LICENCE
new file mode 100644
index 00000000..a73bf40a
--- /dev/null
+++ b/src/lib/subtl/LICENCE
@@ -0,0 +1,23 @@
+Copyright (c) 2012, Packetloop. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of Packetloop nor the names of its contributors may be
+      used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/lib/subtl/README.md b/src/lib/subtl/README.md
new file mode 100644
index 00000000..80ae983e
--- /dev/null
+++ b/src/lib/subtl/README.md
@@ -0,0 +1,28 @@
+# subtl
+
+## Overview
+
+SUBTL is a **s**imple **U**DP **B**itTorrent **t**racker **l**ibrary for Python, licenced under the modified BSD license.
+
+## Example
+
+This short example will list a few IP Addresses from a certain hash:
+
+    from subtl import UdpTrackerClient
+    utc = UdpTrackerClient('tracker.openbittorrent.com', 80)
+    utc.connect()
+    if not utc.poll_once():
+        raise Exception('Could not connect')
+    print('Success!')
+
+    utc.announce(info_hash='089184ED52AA37F71801391C451C5D5ADD0D9501')
+    data = utc.poll_once()
+    if not data:
+        raise Exception('Could not announce')
+    for a in data['response']['peers']:
+        print(a)
+
+## Caveats
+
+ * There is no automatic retrying of sending packets yet.
+ * This library won't download torrent files--it is simply a tracker client.
diff --git a/src/lib/subtl/__init__.py b/src/lib/subtl/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/lib/subtl/subtl.py b/src/lib/subtl/subtl.py
new file mode 100644
index 00000000..3f8c47aa
--- /dev/null
+++ b/src/lib/subtl/subtl.py
@@ -0,0 +1,220 @@
+'''
+Based on the specification at http://bittorrent.org/beps/bep_0015.html
+'''
+import random
+import struct
+import time
+import socket
+from collections import defaultdict
+
+
+__version__ = '0.0.1'
+
+CONNECT = 0
+ANNOUNCE = 1
+SCRAPE = 2
+ERROR = 3
+
+
+def norm_info_hash(info_hash):
+    if len(info_hash) == 40:
+        info_hash = info_hash.decode('hex')
+    if len(info_hash) != 20:
+        raise UdpTrackerClientException(
+            'info_hash length is not 20: {}'.format(len(info_hash)))
+    return info_hash
+
+
+def info_hash_to_str(info_hash):
+    return binascii.hexlify(info_hash)
+
+
+class UdpTrackerClientException(Exception):
+    pass
+
+
+class UdpTrackerClient:
+
+    def __init__(self, host, port):
+        self.host = host
+        self.port = port
+        self.peer_port = 6881
+        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        self.conn_id = 0x41727101980
+        self.transactions = {}
+        self.peer_id = self._generate_peer_id()
+        self.timeout = 2
+
+    def connect(self):
+        return self._send(CONNECT)
+
+    def announce(self, **kwargs):
+        if not kwargs:
+            raise UdpTrackerClientException('arguments missing')
+        args = {
+            'peer_id': self.peer_id,
+            'downloaded': 0,
+            'left': 0,
+            'uploaded': 0,
+            'event': 0,
+            'key': 0,
+            'num_want': 10,
+            'ip_address': 0,
+            'port': self.peer_port,
+        }
+        args.update(kwargs)
+
+        fields = 'info_hash peer_id downloaded left uploaded event ' \
+            'ip_address key num_want port'
+
+        # Check and raise if missing fields
+        self._check_fields(args, fields)
+
+        # Humans tend to use hex representations of the hash. Wasteful humans.
+        args['info_hash'] = norm_info_hash(args['info_hash'])
+
+        values = [args[a] for a in fields.split()]
+        payload = struct.pack('!20s20sQQQLLLLH', *values)
+        return self._send(ANNOUNCE, payload)
+
+    def scrape(self, info_hash_list):
+        if len(info_hash_list) > 74:
+            raise UdpTrackerClientException('Max info_hashes is 74')
+
+        payload = ''
+        for info_hash in info_hash_list:
+            info_hash = norm_info_hash(info_hash)
+            payload += info_hash
+
+        trans = self._send(SCRAPE, payload)
+        trans['sent_hashes'] = info_hash_list
+        return trans
+
+    def poll_once(self):
+        self.sock.settimeout(self.timeout)
+        try:
+            response = self.sock.recv(10240)
+        except socket.timeout:
+            return
+
+        header = response[:8]
+        payload = response[8:]
+        action, trans_id = struct.unpack('!LL', header)
+        try:
+            trans = self.transactions[trans_id]
+        except KeyError:
+            self.error('transaction_id not found')
+            return
+        trans['response'] = self._process_response(action, payload, trans)
+        trans['completed'] = True
+        del self.transactions[trans_id]
+        return trans
+
+    def error(self, message):
+        print('error: {}'.format(message))
+
+    def _send(self, action, payload=None):
+        if not payload:
+            payload = ''
+        trans_id, header = self._request_header(action)
+        self.transactions[trans_id] = trans = {
+            'action': action,
+            'time': time.time(),
+            'payload': payload,
+            'completed': False,
+        }
+        self.sock.sendto(header + payload, (self.host, self.port))
+        return trans
+
+    def _request_header(self, action):
+        trans_id = random.randint(0, (1 << 32) - 1)
+        return trans_id, struct.pack('!QLL', self.conn_id, action, trans_id)
+
+    def _process_response(self, action, payload, trans):
+        if action == CONNECT:
+            return self._process_connect(payload, trans)
+        elif action == ANNOUNCE:
+            return self._process_announce(payload, trans)
+        elif action == SCRAPE:
+            return self._process_scrape(payload, trans)
+        elif action == ERROR:
+            return self._proecss_error(payload, trans)
+        else:
+            raise UdpTrackerClientException(
+                'Unknown action response: {}'.format(action))
+
+    def _process_connect(self, payload, trans):
+        self.conn_id = struct.unpack('!Q', payload)[0]
+        return self.conn_id
+
+    def _process_announce(self, payload, trans):
+        response = {}
+
+        info_struct = '!LLL'
+        info_size = struct.calcsize(info_struct)
+        info = payload[:info_size]
+        interval, leechers, seeders = struct.unpack(info_struct, info)
+
+        peer_data = payload[info_size:]
+        peer_struct = '!LH'
+        peer_size = struct.calcsize(peer_struct)
+        peer_count = len(peer_data) / peer_size
+        peers = []
+
+        for peer_offset in xrange(peer_count):
+            off = peer_size * peer_offset
+            peer = peer_data[off:off + peer_size]
+            addr, port = struct.unpack(peer_struct, peer)
+            peers.append({
+                'addr': socket.inet_ntoa(struct.pack('!L', addr)),
+                'port': port,
+            })
+
+        return {
+            'interval': interval,
+            'leechers': leechers,
+            'seeders': seeders,
+            'peers': peers,
+        }
+
+    def _process_scrape(self, payload, trans):
+        info_struct = '!LLL'
+        info_size = struct.calcsize(info_struct)
+        info_count = len(payload) / info_size
+        hashes = trans['sent_hashes']
+        response = {}
+        for info_offset in xrange(info_count):
+            off = info_size * info_offset
+            info = payload[off:off + info_size]
+            seeders, completed, leechers = struct.unpack(info_struct, info)
+            response[hashes[info_offset]] = {
+                'seeders': seeders,
+                'completed': completed,
+                'leechers': leechers,
+            }
+        return response
+
+    def _process_error(self, payload, trans):
+        '''
+        I haven't seen this action type be sent from a tracker, but I've left
+        it here for the possibility.
+        '''
+        self.error(payload)
+        return payload
+
+    def _generate_peer_id(self):
+        '''http://www.bittorrent.org/beps/bep_0020.html'''
+        peer_id = '-PU' + __version__.replace('.', '-') + '-'
+        remaining = 20 - len(peer_id)
+        numbers = [str(random.randint(0, 9)) for _ in xrange(remaining)]
+        peer_id += ''.join(numbers)
+        assert(len(peer_id) == 20)
+        return peer_id
+
+    def _check_fields(self, args, fields):
+        for f in fields:
+            try:
+                args.get(f)
+            except KeyError:
+                raise UdpTrackerClientException('field missing: {}'.format(f))
+
diff --git a/src/main.py b/src/main.py
new file mode 100644
index 00000000..34466373
--- /dev/null
+++ b/src/main.py
@@ -0,0 +1,175 @@
+import os, sys
+sys.path.append(os.path.dirname(__file__)) # Imports relative to main.py
+
+# Load config
+from Config import config
+
+# Init logging
+import logging
+if config.action == "main":
+	if os.path.isfile("log/debug.log"):  # Simple logrotate
+		if os.path.isfile("log/debug-last.log"): os.unlink("log/debug-last.log")
+		os.rename("log/debug.log", "log/debug-last.log")
+	logging.basicConfig(format='[%(asctime)s] %(levelname)-8s %(name)s %(message)s', level=logging.DEBUG, filename="log/debug.log")
+else:
+	logging.basicConfig(level=logging.DEBUG, stream=open(os.devnull,"w")) # No file logging if action is not main
+
+console_log = logging.StreamHandler()
+console_log.setFormatter(logging.Formatter('%(name)s %(message)s', "%H:%M:%S"))
+logging.getLogger('').addHandler(console_log) # Add console logger
+logging.getLogger('').name = "-" # Remove root prefix
+
+# Debug dependent configuration
+if config.debug:
+	console_log.setLevel(logging.DEBUG)
+	from Debug import DebugHook
+	from gevent import monkey; monkey.patch_all(thread=False) # thread=False because of pyfilesystem
+else:
+	console_log.setLevel(logging.INFO)
+	from gevent import monkey; monkey.patch_all()
+
+import gevent
+import time
+
+
+logging.debug("Starting... %s" % config)
+
+
+# Start serving UiServer and PeerServer
+def main():
+	from File import FileServer
+	from Ui import UiServer
+	logging.info("Creating UiServer....")
+	ui_server = UiServer()
+
+	logging.info("Creating FileServer....")
+	file_server = FileServer()
+
+	logging.info("Starting servers....")
+	gevent.joinall([gevent.spawn(ui_server.start), gevent.spawn(file_server.start)])
+
+
+# Site commands
+
+def siteCreate():
+	logging.info("Generating new privatekey...")
+	from src.Crypt import CryptBitcoin
+	privatekey = CryptBitcoin.newPrivatekey()
+	logging.info("-----------------------------------------------------------")
+	logging.info("Site private key: %s (save it, required to modify the site)" % privatekey)
+	address = CryptBitcoin.privatekeyToAddress(privatekey)
+	logging.info("Site address: %s" % address)
+	logging.info("-----------------------------------------------------------")
+
+	logging.info("Creating directory structure...")
+	from Site import Site
+	os.mkdir("data/%s" % address)
+	open("data/%s/index.html" % address, "w").write("Hello %s!" % address)
+
+	logging.info("Creating content.json...")
+	site = Site(address)
+	site.signContent(privatekey)
+
+	logging.info("Site created!")
+
+
+def siteSign(address, privatekey=None):
+	from Site import Site
+	logging.info("Signing site: %s..." % address)
+	site = Site(address, allow_create = False)
+
+	if not privatekey: # If no privatekey in args then ask it now
+		import getpass
+		privatekey = getpass.getpass("Private key (input hidden):")
+	site.signContent(privatekey)
+
+
+def siteVerify(address):
+	from Site import Site
+	logging.info("Verifing site: %s..." % address)
+	site = Site(address)
+
+	logging.info("Verifing content.json signature...")
+	if site.verifyFile("content.json", open(site.getPath("content.json"), "rb"), force=True) != False: # Force check the sign
+		logging.info("[OK] content.json signed by address %s!" % address)
+	else:
+		logging.error("[ERROR] Content.json not signed by address %s!" % address)
+
+	logging.info("Verifying site files...")
+	bad_files = site.verifyFiles()
+	if not bad_files:
+		logging.info("[OK] All file sha1sum matches!")
+	else:
+		logging.error("[ERROR] Error during verifying site files!")
+
+
+def siteAnnounce(address):
+	from Site.Site import Site
+	logging.info("Announcing site %s to tracker..." % address)
+	site = Site(address)
+
+	s = time.time()
+	site.announce()
+	print "Response time: %.3fs" % (time.time()-s)
+	print site.peers
+
+
+def siteNeedFile(address, inner_path):
+	from Site import Site
+	site = Site(address)
+	site.announce()
+	print site.needFile(inner_path, update=True)
+
+
+def sitePublish(address):
+	from Site import Site
+	from File import FileServer # We need fileserver to handle incoming file requests
+	logging.info("Creating FileServer....")
+	file_server = FileServer()
+	file_server_thread = gevent.spawn(file_server.start, check_sites=False) # Dont check every site integrity
+	file_server.openport()
+	if file_server.port_opened == False:
+		logging.info("Port not opened, passive publishing not supported yet :(")
+		return
+	site = file_server.sites[address]
+	site.settings["serving"] = True # Serving the site even if its disabled
+	site.announce() # Gather peers
+	site.publish(10) # Push to 10 peers
+	logging.info("Serving files....")
+	gevent.joinall([file_server_thread])
+
+
+# Crypto commands
+
+def cryptoPrivatekeyToAddress(privatekey=None):
+	from src.Crypt import CryptBitcoin
+	if not privatekey: # If no privatekey in args then ask it now
+		import getpass
+		privatekey = getpass.getpass("Private key (input hidden):")
+
+	print CryptBitcoin.privatekeyToAddress(privatekey)
+
+
+# Peer
+
+def peerPing(ip, port):
+	from Peer import Peer
+	logging.info("Pinging 5 times peer: %s:%s..." % (ip, port))
+	peer = Peer(ip, port)
+	for i in range(5):
+		s = time.time()
+		print peer.ping(),
+		print "Response time: %.3fs" % (time.time()-s)
+		time.sleep(1)
+
+
+def peerGetFile(ip, port, site, filename=None):
+	from Peer import Peer
+	if not site: site = config.homepage
+	if not filename: filename = "content.json"
+	logging.info("Getting %s/%s from peer: %s:%s..." % (site, filename, ip, port))
+	peer = Peer(ip, port)
+	s = time.time()
+	print peer.getFile(site, filename).read()
+	print "Response time: %.3fs" % (time.time()-s)
+
diff --git a/src/util/Event.py b/src/util/Event.py
new file mode 100644
index 00000000..664daae9
--- /dev/null
+++ b/src/util/Event.py
@@ -0,0 +1,29 @@
+# Based on http://stackoverflow.com/a/2022629
+
+class Event(list):
+	def __call__(self, *args, **kwargs):
+		for f in self[:]:
+			if "once" in dir(f): 
+				self.remove(f)
+			f(*args, **kwargs)
+
+
+	def __repr__(self):
+		return "Event(%s)" % list.__repr__(self)
+
+
+	def once(self, func):
+		func.once = True
+		self.append(func)
+		return self
+
+
+if __name__ == "__main__":
+	def say(pre, text):
+		print "%s Say: %s" % (pre, text)
+	onChanged = Event()
+	onChanged.once(lambda pre: say(pre, "once"))
+	onChanged.append(lambda pre: say(pre, "always"))
+	onChanged("#1")
+	onChanged("#2")
+	onChanged("#3")
diff --git a/src/util/Noparallel.py b/src/util/Noparallel.py
new file mode 100644
index 00000000..1af0699f
--- /dev/null
+++ b/src/util/Noparallel.py
@@ -0,0 +1,114 @@
+import gevent, time
+
+class Noparallel(object): # Only allow function running once in same time
+	def __init__(self,blocking=True):
+		self.threads = {}
+		self.blocking = blocking # Blocking: Acts like normal function else thread returned
+
+
+	def __call__(self, func):
+		def wrapper(*args, **kwargs):
+			key = (func, tuple(args), tuple(kwargs)) # Unique key for function including parameters
+			if key in self.threads: # Thread already running (if using blocking mode)
+				thread = self.threads[key]
+				if self.blocking:
+					thread.join() # Blocking until its finished
+					return thread.value # Return the value
+				else: # No blocking
+					if thread.ready(): # Its finished, create a new
+						thread = gevent.spawn(func, *args, **kwargs)
+						self.threads[key] = thread
+						return thread
+					else: # Still running
+						return thread
+			else: # Thread not running
+				thread = gevent.spawn(func, *args, **kwargs) # Spawning new thread
+				self.threads[key] = thread
+				if self.blocking: # Wait for finish
+					thread.join()
+					ret = thread.value
+					if key in self.threads: del(self.threads[key]) # Allowing it to run again
+					return ret
+				else: # No blocking just return the thread
+					return thread
+		wrapper.func_name = func.func_name
+		
+		return wrapper
+
+class Test():
+	@Noparallel()
+	def count(self):
+		for i in range(5):
+			print self, i
+			time.sleep(1)
+		return "%s return:%s" % (self, i)
+
+
+class TestNoblock():
+	@Noparallel(blocking=False)
+	def count(self):
+		for i in range(5):
+			print self, i
+			time.sleep(1)
+		return "%s return:%s" % (self, i)
+
+
+def testBlocking():
+	test = Test()
+	test2 = Test()
+	print "Counting..."
+	print "Creating class1/thread1"
+	thread1 = gevent.spawn(test.count)
+	print "Creating class1/thread2 (ignored)"
+	thread2 = gevent.spawn(test.count)
+	print "Creating class2/thread3"
+	thread3 = gevent.spawn(test2.count)
+
+	print "Joining class1/thread1"
+	thread1.join()
+	print "Joining class1/thread2"
+	thread2.join()
+	print "Joining class2/thread3"
+	thread3.join()
+
+	print "Creating class1/thread4 (its finished, allowed again)"
+	thread4 = gevent.spawn(test.count)
+	print "Joining thread4"
+	thread4.join()
+
+	print thread1.value, thread2.value, thread3.value, thread4.value
+	print "Done."
+
+def testNoblocking():
+	test = TestNoblock()
+	test2 = TestNoblock()
+	print "Creating class1/thread1"
+	thread1 = test.count()
+	print "Creating class1/thread2 (ignored)"
+	thread2 = test.count()
+	print "Creating class2/thread3"
+	thread3 = test2.count()
+	print "Joining class1/thread1"
+	thread1.join()
+	print "Joining class1/thread2"
+	thread2.join()
+	print "Joining class2/thread3"
+	thread3.join()
+
+	print "Creating class1/thread4 (its finished, allowed again)"
+	thread4 = test.count()
+	print "Joining thread4"
+	thread4.join()
+
+
+	print thread1.value, thread2.value, thread3.value, thread4.value
+	print "Done."
+
+if __name__ == "__main__":
+	from gevent import monkey
+	monkey.patch_all()
+
+	print "Testing blocking mode..."
+	testBlocking()
+	print "Testing noblocking mode..."
+	testNoblocking()
diff --git a/src/util/__init__.py b/src/util/__init__.py
new file mode 100644
index 00000000..c226368e
--- /dev/null
+++ b/src/util/__init__.py
@@ -0,0 +1,2 @@
+from Event import Event
+from Noparallel import Noparallel
diff --git a/tools/coffee/README.md b/tools/coffee/README.md
new file mode 100644
index 00000000..dc589d21
--- /dev/null
+++ b/tools/coffee/README.md
@@ -0,0 +1,19 @@
+# CoffeeScript compiler for Windows
+
+A simple command-line utilty for Windows that will compile `*.coffee` files to JavaScript `*.js` files using [CoffeeScript](http://jashkenas.github.com/coffee-script/) and the venerable Windows Script Host, ubiquitous on Windows since the 90s.
+
+## Usage
+
+To use it, invoke `coffee.cmd` like so:
+
+    coffee input.coffee output.js
+    
+If an output is not specified, it is written to `stdout`. In neither an input or output are specified then data is assumed to be on `stdin`. For example:
+
+    type input.coffee | coffee > output.js
+
+Errors are written to `stderr`.
+
+In the `test` directory there's a version of the standard CoffeeScript tests which can be kicked off using `test.cmd`. The test just attempts to compile the *.coffee files but doesn't execute them.
+
+To upgrade to the latest CoffeeScript simply replace `coffee-script.js` from the upstream https://github.com/jashkenas/coffee-script/blob/master/extras/coffee-script.js (the tests will likely need updating as well, if you want to run them).
diff --git a/tools/coffee/coffee-script.js b/tools/coffee/coffee-script.js
new file mode 100644
index 00000000..0e63a65f
--- /dev/null
+++ b/tools/coffee/coffee-script.js
@@ -0,0 +1,12 @@
+/**
+ * CoffeeScript Compiler v1.8.0
+ * http://coffeescript.org
+ *
+ * Copyright 2011, Jeremy Ashkenas
+ * Released under the MIT License
+ */
+(function(root){var CoffeeScript=function(){function require(e){return require[e]}return require["./helpers"]=function(){var e={},t={exports:e};return function(){var t,n,i,r,s,o,a;e.starts=function(e,t,n){return t===e.substr(n,t.length)},e.ends=function(e,t,n){var i;return i=t.length,t===e.substr(e.length-i-(n||0),i)},e.repeat=s=function(e,t){var n;for(n="";t>0;)1&t&&(n+=e),t>>>=1,e+=e;return n},e.compact=function(e){var t,n,i,r;for(r=[],n=0,i=e.length;i>n;n++)t=e[n],t&&r.push(t);return r},e.count=function(e,t){var n,i;if(n=i=0,!t.length)return 1/0;for(;i=1+e.indexOf(t,i);)n++;return n},e.merge=function(e,t){return n(n({},e),t)},n=e.extend=function(e,t){var n,i;for(n in t)i=t[n],e[n]=i;return e},e.flatten=i=function(e){var t,n,r,s;for(n=[],r=0,s=e.length;s>r;r++)t=e[r],t instanceof Array?n=n.concat(i(t)):n.push(t);return n},e.del=function(e,t){var n;return n=e[t],delete e[t],n},e.last=r=function(e,t){return e[e.length-(t||0)-1]},e.some=null!=(a=Array.prototype.some)?a:function(e){var t,n,i;for(n=0,i=this.length;i>n;n++)if(t=this[n],e(t))return!0;return!1},e.invertLiterate=function(e){var t,n,i;return i=!0,n=function(){var n,r,s,o;for(s=e.split("\n"),o=[],n=0,r=s.length;r>n;n++)t=s[n],i&&/^([ ]{4}|[ ]{0,3}\t)/.test(t)?o.push(t):(i=/^\s*$/.test(t))?o.push(t):o.push("# "+t);return o}(),n.join("\n")},t=function(e,t){return t?{first_line:e.first_line,first_column:e.first_column,last_line:t.last_line,last_column:t.last_column}:e},e.addLocationDataFn=function(e,n){return function(i){return"object"==typeof i&&i.updateLocationDataIfMissing&&i.updateLocationDataIfMissing(t(e,n)),i}},e.locationDataToString=function(e){var t;return"2"in e&&"first_line"in e[2]?t=e[2]:"first_line"in e&&(t=e),t?""+(t.first_line+1)+":"+(t.first_column+1)+"-"+(""+(t.last_line+1)+":"+(t.last_column+1)):"No location data"},e.baseFileName=function(e,t,n){var i,r;return null==t&&(t=!1),null==n&&(n=!1),r=n?/\\|\//:/\//,i=e.split(r),e=i[i.length-1],t&&e.indexOf(".")>=0?(i=e.split("."),i.pop(),"coffee"===i[i.length-1]&&i.length>1&&i.pop(),i.join(".")):e},e.isCoffee=function(e){return/\.((lit)?coffee|coffee\.md)$/.test(e)},e.isLiterate=function(e){return/\.(litcoffee|coffee\.md)$/.test(e)},e.throwSyntaxError=function(e,t){var n;throw n=new SyntaxError(e),n.location=t,n.toString=o,n.stack=""+n,n},e.updateSyntaxError=function(e,t,n){return e.toString===o&&(e.code||(e.code=t),e.filename||(e.filename=n),e.stack=""+e),e},o=function(){var e,t,n,i,r,o,a,c,h,l,u,p,d;return this.code&&this.location?(p=this.location,a=p.first_line,o=p.first_column,h=p.last_line,c=p.last_column,null==h&&(h=a),null==c&&(c=o),r=this.filename||"[stdin]",e=this.code.split("\n")[a],u=o,i=a===h?c+1:e.length,l=e.slice(0,u).replace(/[^\s]/g," ")+s("^",i-u),"undefined"!=typeof process&&null!==process&&(n=process.stdout.isTTY&&!process.env.NODE_DISABLE_COLORS),(null!=(d=this.colorful)?d:n)&&(t=function(e){return""+e+""},e=e.slice(0,u)+t(e.slice(u,i))+e.slice(i),l=t(l)),""+r+":"+(a+1)+":"+(o+1)+": error: "+this.message+"\n"+e+"\n"+l):Error.prototype.toString.call(this)},e.nameWhitespaceCharacter=function(e){switch(e){case" ":return"space";case"\n":return"newline";case"\r":return"carriage return";case"	":return"tab";default:return e}}}.call(this),t.exports}(),require["./rewriter"]=function(){var e={},t={exports:e};return function(){var t,n,i,r,s,o,a,c,h,l,u,p,d,f,m,b,g,k,y,v=[].indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(t in this&&this[t]===e)return t;return-1},w=[].slice;for(f=function(e,t,n){var i;return i=[e,t],i.generated=!0,n&&(i.origin=n),i},e.Rewriter=function(){function e(){}return e.prototype.rewrite=function(e){return this.tokens=e,this.removeLeadingNewlines(),this.closeOpenCalls(),this.closeOpenIndexes(),this.normalizeLines(),this.tagPostfixConditionals(),this.addImplicitBracesAndParens(),this.addLocationDataToGeneratedTokens(),this.tokens},e.prototype.scanTokens=function(e){var t,n,i;for(i=this.tokens,t=0;n=i[t];)t+=e.call(this,n,t,i);return!0},e.prototype.detectEnd=function(e,t,n){var i,o,a,c,h;for(a=this.tokens,i=0;o=a[e];){if(0===i&&t.call(this,o,e))return n.call(this,o,e);if(!o||0>i)return n.call(this,o,e-1);c=o[0],v.call(s,c)>=0?i+=1:(h=o[0],v.call(r,h)>=0&&(i-=1)),e+=1}return e-1},e.prototype.removeLeadingNewlines=function(){var e,t,n,i,r;for(r=this.tokens,e=n=0,i=r.length;i>n&&(t=r[e][0],"TERMINATOR"===t);e=++n);return e?this.tokens.splice(0,e):void 0},e.prototype.closeOpenCalls=function(){var e,t;return t=function(e,t){var n;return")"===(n=e[0])||"CALL_END"===n||"OUTDENT"===e[0]&&")"===this.tag(t-1)},e=function(e,t){return this.tokens["OUTDENT"===e[0]?t-1:t][0]="CALL_END"},this.scanTokens(function(n,i){return"CALL_START"===n[0]&&this.detectEnd(i+1,t,e),1})},e.prototype.closeOpenIndexes=function(){var e,t;return t=function(e){var t;return"]"===(t=e[0])||"INDEX_END"===t},e=function(e){return e[0]="INDEX_END"},this.scanTokens(function(n,i){return"INDEX_START"===n[0]&&this.detectEnd(i+1,t,e),1})},e.prototype.matchTags=function(){var e,t,n,i,r,s,o;for(t=arguments[0],i=arguments.length>=2?w.call(arguments,1):[],e=0,n=r=0,s=i.length;s>=0?s>r:r>s;n=s>=0?++r:--r){for(;"HERECOMMENT"===this.tag(t+n+e);)e+=2;if(null!=i[n]&&("string"==typeof i[n]&&(i[n]=[i[n]]),o=this.tag(t+n+e),0>v.call(i[n],o)))return!1}return!0},e.prototype.looksObjectish=function(e){return this.matchTags(e,"@",null,":")||this.matchTags(e,null,":")},e.prototype.findTagsBackwards=function(e,t){var n,i,o,a,c,h,l;for(n=[];e>=0&&(n.length||(a=this.tag(e),0>v.call(t,a)&&(c=this.tag(e),0>v.call(s,c)||this.tokens[e].generated)&&(h=this.tag(e),0>v.call(u,h))));)i=this.tag(e),v.call(r,i)>=0&&n.push(this.tag(e)),o=this.tag(e),v.call(s,o)>=0&&n.length&&n.pop(),e-=1;return l=this.tag(e),v.call(t,l)>=0},e.prototype.addImplicitBracesAndParens=function(){var e;return e=[],this.scanTokens(function(t,i,l){var p,d,m,b,g,k,y,w,T,F,L,C,N,E,x,D,S,R,A,I,_,$,O,j,M,B,V,P;if($=t[0],L=(C=i>0?l[i-1]:[])[0],T=(l.length-1>i?l[i+1]:[])[0],S=function(){return e[e.length-1]},R=i,m=function(e){return i-R+e},b=function(){var e,t;return null!=(e=S())?null!=(t=e[2])?t.ours:void 0:void 0},g=function(){var e;return b()&&"("===(null!=(e=S())?e[0]:void 0)},y=function(){var e;return b()&&"{"===(null!=(e=S())?e[0]:void 0)},k=function(){var e;return b&&"CONTROL"===(null!=(e=S())?e[0]:void 0)},A=function(t){var n;return n=null!=t?t:i,e.push(["(",n,{ours:!0}]),l.splice(n,0,f("CALL_START","(")),null==t?i+=1:void 0},p=function(){return e.pop(),l.splice(i,0,f("CALL_END",")")),i+=1},I=function(n,r){var s;return null==r&&(r=!0),s=null!=n?n:i,e.push(["{",s,{sameLine:!0,startsLine:r,ours:!0}]),l.splice(s,0,f("{",f(new String("{")),t)),null==n?i+=1:void 0},d=function(n){return n=null!=n?n:i,e.pop(),l.splice(n,0,f("}","}",t)),i+=1},g()&&("IF"===$||"TRY"===$||"FINALLY"===$||"CATCH"===$||"CLASS"===$||"SWITCH"===$))return e.push(["CONTROL",i,{ours:!0}]),m(1);if("INDENT"===$&&b()){if("=>"!==L&&"->"!==L&&"["!==L&&"("!==L&&","!==L&&"{"!==L&&"TRY"!==L&&"ELSE"!==L&&"="!==L)for(;g();)p();return k()&&e.pop(),e.push([$,i]),m(1)}if(v.call(s,$)>=0)return e.push([$,i]),m(1);if(v.call(r,$)>=0){for(;b();)g()?p():y()?d():e.pop();e.pop()}if((v.call(c,$)>=0&&t.spaced&&!t.stringEnd||"?"===$&&i>0&&!l[i-1].spaced)&&(v.call(o,T)>=0||v.call(h,T)>=0&&!(null!=(O=l[i+1])?O.spaced:void 0)&&!(null!=(j=l[i+1])?j.newLine:void 0)))return"?"===$&&($=t[0]="FUNC_EXIST"),A(i+1),m(2);if(v.call(c,$)>=0&&this.matchTags(i+1,"INDENT",null,":")&&!this.findTagsBackwards(i,["CLASS","EXTENDS","IF","CATCH","SWITCH","LEADING_WHEN","FOR","WHILE","UNTIL"]))return A(i+1),e.push(["INDENT",i+2]),m(3);if(":"===$){for(N="@"===this.tag(i-2)?i-2:i-1;"HERECOMMENT"===this.tag(N-2);)N-=2;return this.insideForDeclaration="FOR"===T,_=0===N||(M=this.tag(N-1),v.call(u,M)>=0)||l[N-1].newLine,S()&&(B=S(),D=B[0],x=B[1],("{"===D||"INDENT"===D&&"{"===this.tag(x-1))&&(_||","===this.tag(N-1)||"{"===this.tag(N-1)))?m(1):(I(N,!!_),m(2))}if(y()&&v.call(u,$)>=0&&(S()[2].sameLine=!1),w="OUTDENT"===L||C.newLine,v.call(a,$)>=0||v.call(n,$)>=0&&w)for(;b();)if(V=S(),D=V[0],x=V[1],P=V[2],E=P.sameLine,_=P.startsLine,g()&&","!==L)p();else if(y()&&!this.insideForDeclaration&&E&&"TERMINATOR"!==$&&":"!==L&&d());else{if(!y()||"TERMINATOR"!==$||","===L||_&&this.looksObjectish(i+1))break;d()}if(!(","!==$||this.looksObjectish(i+1)||!y()||this.insideForDeclaration||"TERMINATOR"===T&&this.looksObjectish(i+2)))for(F="OUTDENT"===T?1:0;y();)d(i+F);return m(1)})},e.prototype.addLocationDataToGeneratedTokens=function(){return this.scanTokens(function(e,t,n){var i,r,s,o,a,c;return e[2]?1:e.generated||e.explicit?("{"===e[0]&&(s=null!=(a=n[t+1])?a[2]:void 0)?(r=s.first_line,i=s.first_column):(o=null!=(c=n[t-1])?c[2]:void 0)?(r=o.last_line,i=o.last_column):r=i=0,e[2]={first_line:r,first_column:i,last_line:r,last_column:i},1):1})},e.prototype.normalizeLines=function(){var e,t,r,s,o;return o=r=s=null,t=function(e,t){var r,s,a,c;return";"!==e[1]&&(r=e[0],v.call(p,r)>=0)&&!("TERMINATOR"===e[0]&&(s=this.tag(t+1),v.call(i,s)>=0))&&!("ELSE"===e[0]&&"THEN"!==o)&&!!("CATCH"!==(a=e[0])&&"FINALLY"!==a||"->"!==o&&"=>"!==o)||(c=e[0],v.call(n,c)>=0&&this.tokens[t-1].newLine)},e=function(e,t){return this.tokens.splice(","===this.tag(t-1)?t-1:t,0,s)},this.scanTokens(function(n,a,c){var h,l,u,p,f,m;if(l=n[0],"TERMINATOR"===l){if("ELSE"===this.tag(a+1)&&"OUTDENT"!==this.tag(a-1))return c.splice.apply(c,[a,1].concat(w.call(this.indentation()))),1;if(p=this.tag(a+1),v.call(i,p)>=0)return c.splice(a,1),0}if("CATCH"===l)for(h=u=1;2>=u;h=++u)if("OUTDENT"===(f=this.tag(a+h))||"TERMINATOR"===f||"FINALLY"===f)return c.splice.apply(c,[a+h,0].concat(w.call(this.indentation()))),2+h;return v.call(d,l)>=0&&"INDENT"!==this.tag(a+1)&&("ELSE"!==l||"IF"!==this.tag(a+1))?(o=l,m=this.indentation(c[a]),r=m[0],s=m[1],"THEN"===o&&(r.fromThen=!0),c.splice(a+1,0,r),this.detectEnd(a+2,t,e),"THEN"===l&&c.splice(a,1),1):1})},e.prototype.tagPostfixConditionals=function(){var e,t,n;return n=null,t=function(e,t){var n,i;return i=e[0],n=this.tokens[t-1][0],"TERMINATOR"===i||"INDENT"===i&&0>v.call(d,n)},e=function(e){return"INDENT"!==e[0]||e.generated&&!e.fromThen?n[0]="POST_"+n[0]:void 0},this.scanTokens(function(i,r){return"IF"!==i[0]?1:(n=i,this.detectEnd(r+1,t,e),1)})},e.prototype.indentation=function(e){var t,n;return t=["INDENT",2],n=["OUTDENT",2],e?(t.generated=n.generated=!0,t.origin=n.origin=e):t.explicit=n.explicit=!0,[t,n]},e.prototype.generate=f,e.prototype.tag=function(e){var t;return null!=(t=this.tokens[e])?t[0]:void 0},e}(),t=[["(",")"],["[","]"],["{","}"],["INDENT","OUTDENT"],["CALL_START","CALL_END"],["PARAM_START","PARAM_END"],["INDEX_START","INDEX_END"]],e.INVERSES=l={},s=[],r=[],g=0,k=t.length;k>g;g++)y=t[g],m=y[0],b=y[1],s.push(l[b]=m),r.push(l[m]=b);i=["CATCH","THEN","ELSE","FINALLY"].concat(r),c=["IDENTIFIER","SUPER",")","CALL_END","]","INDEX_END","@","THIS"],o=["IDENTIFIER","NUMBER","STRING","JS","REGEX","NEW","PARAM_START","CLASS","IF","TRY","SWITCH","THIS","BOOL","NULL","UNDEFINED","UNARY","UNARY_MATH","SUPER","THROW","@","->","=>","[","(","{","--","++"],h=["+","-"],a=["POST_IF","FOR","WHILE","UNTIL","WHEN","BY","LOOP","TERMINATOR"],d=["ELSE","->","=>","TRY","FINALLY","THEN"],p=["TERMINATOR","CATCH","FINALLY","ELSE","OUTDENT","LEADING_WHEN"],u=["TERMINATOR","INDENT","OUTDENT"],n=[".","?.","::","?::"]}.call(this),t.exports}(),require["./lexer"]=function(){var e={},t={exports:e};return function(){var t,n,i,r,s,o,a,c,h,l,u,p,d,f,m,b,g,k,y,v,w,T,F,L,C,N,E,x,D,S,R,A,I,_,$,O,j,M,B,V,P,U,H,q,G,W,X,Y,z,K,J,Z,Q,et,tt,nt=[].indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(t in this&&this[t]===e)return t;return-1};et=require("./rewriter"),j=et.Rewriter,y=et.INVERSES,tt=require("./helpers"),W=tt.count,Z=tt.starts,G=tt.compact,z=tt.last,J=tt.repeat,X=tt.invertLiterate,K=tt.locationDataToString,Q=tt.throwSyntaxError,e.Lexer=N=function(){function e(){}return e.prototype.tokenize=function(e,t){var n,i,r,s;for(null==t&&(t={}),this.literate=t.literate,this.indent=0,this.baseIndent=0,this.indebt=0,this.outdebt=0,this.indents=[],this.ends=[],this.tokens=[],this.chunkLine=t.line||0,this.chunkColumn=t.column||0,e=this.clean(e),i=0;this.chunk=e.slice(i);)n=this.identifierToken()||this.commentToken()||this.whitespaceToken()||this.lineToken()||this.heredocToken()||this.stringToken()||this.numberToken()||this.regexToken()||this.jsToken()||this.literalToken(),s=this.getLineAndColumnFromChunk(n),this.chunkLine=s[0],this.chunkColumn=s[1],i+=n;return this.closeIndentation(),(r=this.ends.pop())&&this.error("missing "+r),t.rewrite===!1?this.tokens:(new j).rewrite(this.tokens)},e.prototype.clean=function(e){return e.charCodeAt(0)===t&&(e=e.slice(1)),e=e.replace(/\r/g,"").replace(P,""),q.test(e)&&(e="\n"+e,this.chunkLine--),this.literate&&(e=X(e)),e},e.prototype.identifierToken=function(){var e,t,n,i,r,c,h,l,u,p,d,f,m,g;return(h=b.exec(this.chunk))?(c=h[0],i=h[1],e=h[2],r=i.length,l=void 0,"own"===i&&"FOR"===this.tag()?(this.token("OWN",i),i.length):(n=e||(u=z(this.tokens))&&("."===(f=u[0])||"?."===f||"::"===f||"?::"===f||!u.spaced&&"@"===u[0]),p="IDENTIFIER",!n&&(nt.call(T,i)>=0||nt.call(a,i)>=0)&&(p=i.toUpperCase(),"WHEN"===p&&(m=this.tag(),nt.call(F,m)>=0)?p="LEADING_WHEN":"FOR"===p?this.seenFor=!0:"UNLESS"===p?p="IF":nt.call(U,p)>=0?p="UNARY":nt.call($,p)>=0&&("INSTANCEOF"!==p&&this.seenFor?(p="FOR"+p,this.seenFor=!1):(p="RELATION","!"===this.value()&&(l=this.tokens.pop(),i="!"+i)))),nt.call(w,i)>=0&&(n?(p="IDENTIFIER",i=new String(i),i.reserved=!0):nt.call(O,i)>=0&&this.error('reserved word "'+i+'"')),n||(nt.call(s,i)>=0&&(i=o[i]),p=function(){switch(i){case"!":return"UNARY";case"==":case"!=":return"COMPARE";case"&&":case"||":return"LOGIC";case"true":case"false":return"BOOL";case"break":case"continue":return"STATEMENT";default:return p}}()),d=this.token(p,i,0,r),l&&(g=[l[2].first_line,l[2].first_column],d[2].first_line=g[0],d[2].first_column=g[1]),e&&(t=c.lastIndexOf(":"),this.token(":",":",t,e.length)),c.length)):0},e.prototype.numberToken=function(){var e,t,n,i,r;return(n=A.exec(this.chunk))?(i=n[0],/^0[BOX]/.test(i)?this.error("radix prefix '"+i+"' must be lowercase"):/E/.test(i)&&!/^0x/.test(i)?this.error("exponential notation '"+i+"' must be indicated with a lowercase 'e'"):/^0\d*[89]/.test(i)?this.error("decimal literal '"+i+"' must not be prefixed with '0'"):/^0\d+/.test(i)&&this.error("octal literal '"+i+"' must be prefixed with '0o'"),t=i.length,(r=/^0o([0-7]+)/.exec(i))&&(i="0x"+parseInt(r[1],8).toString(16)),(e=/^0b([01]+)/.exec(i))&&(i="0x"+parseInt(e[1],2).toString(16)),this.token("NUMBER",i,0,t),t):0},e.prototype.stringToken=function(){var e,t,n,i,r,s,o,a;switch(s=this.chunk.charAt(0)){case"'":o=(B.exec(this.chunk)||[])[0];break;case'"':o=this.balancedString(this.chunk,'"')}if(!o)return 0;if(e=o.slice(1,-1),a=this.removeNewlines(e),'"'===s&&o.indexOf("#{",1)>0){for(n=r=0,t=e.length;"\n"===e.charAt(r++)&&t>r;)n++;this.interpolateString(a,{strOffset:1+n,lexedLength:o.length})}else this.token("STRING",s+this.escapeLines(a)+s,0,o.length);return(i=/^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test(o))&&this.error("octal escape sequences "+o+" are not allowed"),o.length},e.prototype.heredocToken=function(){var e,t,n,i,r;return(n=u.exec(this.chunk))?(t=n[0],i=t.charAt(0),e=this.sanitizeHeredoc(n[2],{quote:i,indent:null}),'"'===i&&e.indexOf("#{")>=0?(r="\n"===n[2].charAt(0)?4:3,this.interpolateString(e,{heredoc:!0,strOffset:r,lexedLength:t.length})):this.token("STRING",this.makeString(e,i,!0),0,t.length),t.length):0},e.prototype.commentToken=function(){var e,t,n;return(n=this.chunk.match(c))?(e=n[0],t=n[1],t&&this.token("HERECOMMENT",this.sanitizeHeredoc(t,{herecomment:!0,indent:J(" ",this.indent)}),0,e.length),e.length):0},e.prototype.jsToken=function(){var e,t;return"`"===this.chunk.charAt(0)&&(e=v.exec(this.chunk))?(this.token("JS",(t=e[0]).slice(1,-1),0,t.length),t.length):0},e.prototype.regexToken=function(){var e,t,n,i,r,s,o;return"/"!==this.chunk.charAt(0)?0:(t=this.heregexToken())?t:(i=z(this.tokens),i&&(s=i[0],nt.call(i.spaced?S:R,s)>=0)?0:(n=_.exec(this.chunk))?(o=n,n=o[0],r=o[1],e=o[2],"//"===r?0:("/*"===r.slice(0,2)&&this.error("regular expressions cannot begin with `*`"),this.token("REGEX",""+r+e,0,n.length),n.length)):0)},e.prototype.heregexToken=function(){var e,t,n,i,r,s,o,a,c,h,l,u,p,d,b,g,k;if(!(r=f.exec(this.chunk)))return 0;if(i=r[0],e=r[1],t=r[2],0>e.indexOf("#{"))return a=this.escapeLines(e.replace(m,"$1$2").replace(/\//g,"\\/"),!0),a.match(/^\*/)&&this.error("regular expressions cannot begin with `*`"),this.token("REGEX","/"+(a||"(?:)")+"/"+t,0,i.length),i.length;for(this.token("IDENTIFIER","RegExp",0,0),this.token("CALL_START","(",0,0),l=[],b=this.interpolateString(e,{regex:!0,strOffset:3}),p=0,d=b.length;d>p;p++){if(h=b[p],c=h[0],u=h[1],"TOKENS"===c)l.push.apply(l,u);else if("NEOSTRING"===c){if(!(u=u.replace(m,"$1$2")))continue;u=u.replace(/\\/g,"\\\\"),h[0]="STRING",h[1]=this.makeString(u,'"',!0),l.push(h)}else this.error("Unexpected "+c);o=z(this.tokens),s=["+","+"],s[2]=o[2],l.push(s)}return l.pop(),"STRING"!==(null!=(g=l[0])?g[0]:void 0)&&(this.token("STRING",'""',0,0),this.token("+","+",0,0)),(k=this.tokens).push.apply(k,l),t&&(n=i.lastIndexOf(t),this.token(",",",",n,0),this.token("STRING",'"'+t+'"',n,t.length)),this.token(")",")",i.length-1,0),i.length},e.prototype.lineToken=function(){var e,t,n,i,r;if(!(n=D.exec(this.chunk)))return 0;if(t=n[0],this.seenFor=!1,r=t.length-1-t.lastIndexOf("\n"),i=this.unfinished(),r-this.indebt===this.indent)return i?this.suppressNewlines():this.newlineToken(0),t.length;if(r>this.indent){if(i)return this.indebt=r-this.indent,this.suppressNewlines(),t.length;if(!this.tokens.length)return this.baseIndent=this.indent=r,t.length;e=r-this.indent+this.outdebt,this.token("INDENT",e,t.length-r,r),this.indents.push(e),this.ends.push("OUTDENT"),this.outdebt=this.indebt=0,this.indent=r}else this.baseIndent>r?this.error("missing indentation",t.length):(this.indebt=0,this.outdentToken(this.indent-r,i,t.length));return t.length},e.prototype.outdentToken=function(e,t,n){var i,r,s,o;for(i=this.indent-e;e>0;)s=this.indents[this.indents.length-1],s?s===this.outdebt?(e-=this.outdebt,this.outdebt=0):this.outdebt>s?(this.outdebt-=s,e-=s):(r=this.indents.pop()+this.outdebt,n&&(o=this.chunk[n],nt.call(g,o)>=0)&&(i-=r-e,e=r),this.outdebt=0,this.pair("OUTDENT"),this.token("OUTDENT",e,0,n),e-=r):e=0;for(r&&(this.outdebt-=e);";"===this.value();)this.tokens.pop();return"TERMINATOR"===this.tag()||t||this.token("TERMINATOR","\n",n,0),this.indent=i,this},e.prototype.whitespaceToken=function(){var e,t,n;return(e=q.exec(this.chunk))||(t="\n"===this.chunk.charAt(0))?(n=z(this.tokens),n&&(n[e?"spaced":"newLine"]=!0),e?e[0].length:0):0},e.prototype.newlineToken=function(e){for(;";"===this.value();)this.tokens.pop();return"TERMINATOR"!==this.tag()&&this.token("TERMINATOR","\n",e,0),this},e.prototype.suppressNewlines=function(){return"\\"===this.value()&&this.tokens.pop(),this},e.prototype.literalToken=function(){var e,t,n,s,o,a,c,u;if((e=I.exec(this.chunk))?(s=e[0],r.test(s)&&this.tagParameters()):s=this.chunk.charAt(0),n=s,t=z(this.tokens),"="===s&&t&&(!t[1].reserved&&(o=t[1],nt.call(w,o)>=0)&&this.error('reserved word "'+this.value()+"\" can't be assigned"),"||"===(a=t[1])||"&&"===a))return t[0]="COMPOUND_ASSIGN",t[1]+="=",s.length;if(";"===s)this.seenFor=!1,n="TERMINATOR";else if(nt.call(E,s)>=0)n="MATH";else if(nt.call(h,s)>=0)n="COMPARE";else if(nt.call(l,s)>=0)n="COMPOUND_ASSIGN";else if(nt.call(U,s)>=0)n="UNARY";else if(nt.call(H,s)>=0)n="UNARY_MATH";else if(nt.call(M,s)>=0)n="SHIFT";else if(nt.call(C,s)>=0||"?"===s&&(null!=t?t.spaced:void 0))n="LOGIC";else if(t&&!t.spaced)if("("===s&&(c=t[0],nt.call(i,c)>=0))"?"===t[0]&&(t[0]="FUNC_EXIST"),n="CALL_START";else if("["===s&&(u=t[0],nt.call(k,u)>=0))switch(n="INDEX_START",t[0]){case"?":t[0]="INDEX_SOAK"}switch(s){case"(":case"{":case"[":this.ends.push(y[s]);break;case")":case"}":case"]":this.pair(s)}return this.token(n,s),s.length},e.prototype.sanitizeHeredoc=function(e,t){var n,i,r,s,o;if(r=t.indent,i=t.herecomment){if(p.test(e)&&this.error('block comment cannot contain "*/", starting'),0>e.indexOf("\n"))return e}else for(;s=d.exec(e);)n=s[1],(null===r||(o=n.length)>0&&r.length>o)&&(r=n);return r&&(e=e.replace(RegExp("\\n"+r,"g"),"\n")),i||(e=e.replace(/^\n/,"")),e},e.prototype.tagParameters=function(){var e,t,n,i;if(")"!==this.tag())return this;for(t=[],i=this.tokens,e=i.length,i[--e][0]="PARAM_END";n=i[--e];)switch(n[0]){case")":t.push(n);break;case"(":case"CALL_START":if(!t.length)return"("===n[0]?(n[0]="PARAM_START",this):this;t.pop()}return this},e.prototype.closeIndentation=function(){return this.outdentToken(this.indent)},e.prototype.balancedString=function(e,t){var n,i,r,s,o,a,c,h;for(n=0,a=[t],i=c=1,h=e.length;h>=1?h>c:c>h;i=h>=1?++c:--c)if(n)--n;else{switch(r=e.charAt(i)){case"\\":++n;continue;case t:if(a.pop(),!a.length)return e.slice(0,+i+1||9e9);t=a[a.length-1];continue}"}"!==t||'"'!==r&&"'"!==r?"}"===t&&"/"===r&&(s=f.exec(e.slice(i))||_.exec(e.slice(i)))?n+=s[0].length-1:"}"===t&&"{"===r?a.push(t="}"):'"'===t&&"#"===o&&"{"===r&&a.push(t="}"):a.push(t=r),o=r}return this.error("missing "+a.pop()+", starting")},e.prototype.interpolateString=function(t,n){var i,r,s,o,a,c,h,l,u,p,d,f,m,b,g,k,y,v,w,T,F,L,C,N,E,x,D,S,R;for(null==n&&(n={}),o=n.heredoc,v=n.regex,b=n.offsetInChunk,T=n.strOffset,p=n.lexedLength,b||(b=0),T||(T=0),p||(p=t.length),C=[],g=0,a=-1;u=t.charAt(a+=1);)"\\"!==u?"#"===u&&"{"===t.charAt(a+1)&&(s=this.balancedString(t.slice(a+1),"}"))&&(a>g&&C.push(this.makeToken("NEOSTRING",t.slice(g,a),T+g)),r||(r=this.makeToken("","string interpolation",b+a+1,2)),c=s.slice(1,-1),c.length&&(D=this.getLineAndColumnFromChunk(T+a+2),d=D[0],i=D[1],m=(new e).tokenize(c,{line:d,column:i,rewrite:!1}),y=m.pop(),"TERMINATOR"===(null!=(S=m[0])?S[0]:void 0)&&(y=m.shift()),(l=m.length)&&(l>1&&(m.unshift(this.makeToken("(","(",T+a+1,0)),m.push(this.makeToken(")",")",T+a+1+c.length,0))),C.push(["TOKENS",m]))),a+=s.length,g=a+1):a+=1;if(a>g&&t.length>g&&C.push(this.makeToken("NEOSTRING",t.slice(g),T+g)),v)return C;if(!C.length)return this.token("STRING",'""',b,p);for("NEOSTRING"!==C[0][0]&&C.unshift(this.makeToken("NEOSTRING","",b)),(h=C.length>1)&&this.token("(","(",b,0,r),a=E=0,x=C.length;x>E;a=++E)L=C[a],F=L[0],N=L[1],a&&(a&&(k=this.token("+","+")),f="TOKENS"===F?N[0]:L,k[2]={first_line:f[2].first_line,first_column:f[2].first_column,last_line:f[2].first_line,last_column:f[2].first_column}),"TOKENS"===F?(R=this.tokens).push.apply(R,N):"NEOSTRING"===F?(L[0]="STRING",L[1]=this.makeString(N,'"',o),this.tokens.push(L)):this.error("Unexpected "+F);return h&&(w=this.makeToken(")",")",b+p,0),w.stringEnd=!0,this.tokens.push(w)),C},e.prototype.pair=function(e){var t;return e!==(t=z(this.ends))?("OUTDENT"!==t&&this.error("unmatched "+e),this.outdentToken(z(this.indents),!0),this.pair(e)):this.ends.pop()},e.prototype.getLineAndColumnFromChunk=function(e){var t,n,i,r;return 0===e?[this.chunkLine,this.chunkColumn]:(r=e>=this.chunk.length?this.chunk:this.chunk.slice(0,+(e-1)+1||9e9),n=W(r,"\n"),t=this.chunkColumn,n>0?(i=r.split("\n"),t=z(i).length):t+=r.length,[this.chunkLine+n,t])},e.prototype.makeToken=function(e,t,n,i){var r,s,o,a,c;return null==n&&(n=0),null==i&&(i=t.length),s={},a=this.getLineAndColumnFromChunk(n),s.first_line=a[0],s.first_column=a[1],r=Math.max(0,i-1),c=this.getLineAndColumnFromChunk(n+r),s.last_line=c[0],s.last_column=c[1],o=[e,t,s]},e.prototype.token=function(e,t,n,i,r){var s;return s=this.makeToken(e,t,n,i),r&&(s.origin=r),this.tokens.push(s),s},e.prototype.tag=function(e,t){var n;return(n=z(this.tokens,e))&&(t?n[0]=t:n[0])},e.prototype.value=function(e,t){var n;return(n=z(this.tokens,e))&&(t?n[1]=t:n[1])},e.prototype.unfinished=function(){var e;return L.test(this.chunk)||"\\"===(e=this.tag())||"."===e||"?."===e||"?::"===e||"UNARY"===e||"MATH"===e||"UNARY_MATH"===e||"+"===e||"-"===e||"**"===e||"SHIFT"===e||"RELATION"===e||"COMPARE"===e||"LOGIC"===e||"THROW"===e||"EXTENDS"===e},e.prototype.removeNewlines=function(e){return e.replace(/^\s*\n\s*/,"").replace(/([^\\]|\\\\)\s*\n\s*$/,"$1")},e.prototype.escapeLines=function(e,t){return e=e.replace(/\\[^\S\n]*(\n|\\)\s*/g,function(e,t){return"\n"===t?"":e}),t?e.replace(x,"\\n"):e.replace(/\s*\n\s*/g," ")},e.prototype.makeString=function(e,t,n){return e?(e=e.replace(RegExp("\\\\("+t+"|\\\\)","g"),function(e,n){return n===t?n:e}),e=e.replace(RegExp(""+t,"g"),"\\$&"),t+this.escapeLines(e,n)+t):t+t},e.prototype.error=function(e,t){var n,i,r;return null==t&&(t=0),r=this.getLineAndColumnFromChunk(t),i=r[0],n=r[1],Q(e,{first_line:i,first_column:n})},e}(),T=["true","false","null","this","new","delete","typeof","in","instanceof","return","throw","break","continue","debugger","if","else","switch","for","while","do","try","catch","finally","class","extends","super"],a=["undefined","then","unless","until","loop","of","by","when"],o={and:"&&",or:"||",is:"==",isnt:"!=",not:"!",yes:"true",no:"false",on:"true",off:"false"},s=function(){var e;e=[];for(Y in o)e.push(Y);return e}(),a=a.concat(s),O=["case","default","function","var","void","with","const","let","enum","export","import","native","__hasProp","__extends","__slice","__bind","__indexOf","implements","interface","package","private","protected","public","static","yield"],V=["arguments","eval"],w=T.concat(O).concat(V),e.RESERVED=O.concat(T).concat(a).concat(V),e.STRICT_PROSCRIBED=V,t=65279,b=/^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/,A=/^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i,u=/^("""|''')((?:\\[\s\S]|[^\\])*?)(?:\n[^\n\S]*)?\1/,I=/^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>*\/%])\2=?|\?(\.|::)|\.{2,3})/,q=/^[^\n\S]+/,c=/^###([^#][\s\S]*?)(?:###[^\n\S]*|###$)|^(?:\s*#(?!##[^#]).*)+/,r=/^[-=]>/,D=/^(?:\n[^\n\S]*)+/,B=/^'[^\\']*(?:\\[\s\S][^\\']*)*'/,v=/^`[^\\`]*(?:\\.[^\\`]*)*`/,_=/^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/,f=/^\/{3}((?:\\?[\s\S])+?)\/{3}([imgy]{0,4})(?!\w)/,m=/((?:\\\\)+)|\\(\s|\/)|\s+(?:#.*)?/g,x=/\n/g,d=/\n+([^\n\S]*)/g,p=/\*\//,L=/^\s*(?:,|\??\.(?![.\d])|::)/,P=/\s+$/,l=["-=","+=","/=","*=","%=","||=","&&=","?=","<<=",">>=",">>>=","&=","^=","|=","**=","//=","%%="],U=["NEW","TYPEOF","DELETE","DO"],H=["!","~"],C=["&&","||","&","|","^"],M=["<<",">>",">>>"],h=["==","!=","<",">","<=",">="],E=["*","/","%","//","%%"],$=["IN","OF","INSTANCEOF"],n=["TRUE","FALSE"],S=["NUMBER","REGEX","BOOL","NULL","UNDEFINED","++","--"],R=S.concat(")","}","THIS","IDENTIFIER","STRING","]"),i=["IDENTIFIER","STRING","REGEX",")","]","}","?","::","@","THIS","SUPER"],k=i.concat("NUMBER","BOOL","NULL","UNDEFINED"),F=["INDENT","OUTDENT","TERMINATOR"],g=[")","}","]"]}.call(this),t.exports}(),require["./parser"]=function(){var e={},t={exports:e},n=function(){function e(){this.yy={}}var t={trace:function(){},yy:{},symbols_:{error:2,Root:3,Body:4,Line:5,TERMINATOR:6,Expression:7,Statement:8,Return:9,Comment:10,STATEMENT:11,Value:12,Invocation:13,Code:14,Operation:15,Assign:16,If:17,Try:18,While:19,For:20,Switch:21,Class:22,Throw:23,Block:24,INDENT:25,OUTDENT:26,Identifier:27,IDENTIFIER:28,AlphaNumeric:29,NUMBER:30,STRING:31,Literal:32,JS:33,REGEX:34,DEBUGGER:35,UNDEFINED:36,NULL:37,BOOL:38,Assignable:39,"=":40,AssignObj:41,ObjAssignable:42,":":43,ThisProperty:44,RETURN:45,HERECOMMENT:46,PARAM_START:47,ParamList:48,PARAM_END:49,FuncGlyph:50,"->":51,"=>":52,OptComma:53,",":54,Param:55,ParamVar:56,"...":57,Array:58,Object:59,Splat:60,SimpleAssignable:61,Accessor:62,Parenthetical:63,Range:64,This:65,".":66,"?.":67,"::":68,"?::":69,Index:70,INDEX_START:71,IndexValue:72,INDEX_END:73,INDEX_SOAK:74,Slice:75,"{":76,AssignList:77,"}":78,CLASS:79,EXTENDS:80,OptFuncExist:81,Arguments:82,SUPER:83,FUNC_EXIST:84,CALL_START:85,CALL_END:86,ArgList:87,THIS:88,"@":89,"[":90,"]":91,RangeDots:92,"..":93,Arg:94,SimpleArgs:95,TRY:96,Catch:97,FINALLY:98,CATCH:99,THROW:100,"(":101,")":102,WhileSource:103,WHILE:104,WHEN:105,UNTIL:106,Loop:107,LOOP:108,ForBody:109,FOR:110,ForStart:111,ForSource:112,ForVariables:113,OWN:114,ForValue:115,FORIN:116,FOROF:117,BY:118,SWITCH:119,Whens:120,ELSE:121,When:122,LEADING_WHEN:123,IfBlock:124,IF:125,POST_IF:126,UNARY:127,UNARY_MATH:128,"-":129,"+":130,"--":131,"++":132,"?":133,MATH:134,"**":135,SHIFT:136,COMPARE:137,LOGIC:138,RELATION:139,COMPOUND_ASSIGN:140,$accept:0,$end:1},terminals_:{2:"error",6:"TERMINATOR",11:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"UNDEFINED",37:"NULL",38:"BOOL",40:"=",43:":",45:"RETURN",46:"HERECOMMENT",47:"PARAM_START",49:"PARAM_END",51:"->",52:"=>",54:",",57:"...",66:".",67:"?.",68:"::",69:"?::",71:"INDEX_START",73:"INDEX_END",74:"INDEX_SOAK",76:"{",78:"}",79:"CLASS",80:"EXTENDS",83:"SUPER",84:"FUNC_EXIST",85:"CALL_START",86:"CALL_END",88:"THIS",89:"@",90:"[",91:"]",93:"..",96:"TRY",98:"FINALLY",99:"CATCH",100:"THROW",101:"(",102:")",104:"WHILE",105:"WHEN",106:"UNTIL",108:"LOOP",110:"FOR",114:"OWN",116:"FORIN",117:"FOROF",118:"BY",119:"SWITCH",121:"ELSE",123:"LEADING_WHEN",125:"IF",126:"POST_IF",127:"UNARY",128:"UNARY_MATH",129:"-",130:"+",131:"--",132:"++",133:"?",134:"MATH",135:"**",136:"SHIFT",137:"COMPARE",138:"LOGIC",139:"RELATION",140:"COMPOUND_ASSIGN"},productions_:[0,[3,0],[3,1],[4,1],[4,3],[4,2],[5,1],[5,1],[8,1],[8,1],[8,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[24,2],[24,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[16,3],[16,4],[16,5],[41,1],[41,3],[41,5],[41,1],[42,1],[42,1],[42,1],[9,2],[9,1],[10,1],[14,5],[14,2],[50,1],[50,1],[53,0],[53,1],[48,0],[48,1],[48,3],[48,4],[48,6],[55,1],[55,2],[55,3],[55,1],[56,1],[56,1],[56,1],[56,1],[60,2],[61,1],[61,2],[61,2],[61,1],[39,1],[39,1],[39,1],[12,1],[12,1],[12,1],[12,1],[12,1],[62,2],[62,2],[62,2],[62,2],[62,1],[62,1],[70,3],[70,2],[72,1],[72,1],[59,4],[77,0],[77,1],[77,3],[77,4],[77,6],[22,1],[22,2],[22,3],[22,4],[22,2],[22,3],[22,4],[22,5],[13,3],[13,3],[13,1],[13,2],[81,0],[81,1],[82,2],[82,4],[65,1],[65,1],[44,2],[58,2],[58,4],[92,1],[92,1],[64,5],[75,3],[75,2],[75,2],[75,1],[87,1],[87,3],[87,4],[87,4],[87,6],[94,1],[94,1],[94,1],[95,1],[95,3],[18,2],[18,3],[18,4],[18,5],[97,3],[97,3],[97,2],[23,2],[63,3],[63,5],[103,2],[103,4],[103,2],[103,4],[19,2],[19,2],[19,2],[19,1],[107,2],[107,2],[20,2],[20,2],[20,2],[109,2],[109,2],[111,2],[111,3],[115,1],[115,1],[115,1],[115,1],[113,1],[113,3],[112,2],[112,2],[112,4],[112,4],[112,4],[112,6],[112,6],[21,5],[21,7],[21,4],[21,6],[120,1],[120,2],[122,3],[122,4],[124,3],[124,5],[17,1],[17,3],[17,3],[17,3],[15,2],[15,2],[15,2],[15,2],[15,2],[15,2],[15,2],[15,2],[15,2],[15,3],[15,3],[15,3],[15,3],[15,3],[15,3],[15,3],[15,3],[15,3],[15,5],[15,4],[15,3]],performAction:function(e,t,n,i,r,s,o){var a=s.length-1;switch(r){case 1:return this.$=i.addLocationDataFn(o[a],o[a])(new i.Block);case 2:return this.$=s[a];case 3:this.$=i.addLocationDataFn(o[a],o[a])(i.Block.wrap([s[a]]));break;case 4:this.$=i.addLocationDataFn(o[a-2],o[a])(s[a-2].push(s[a]));break;case 5:this.$=s[a-1];break;case 6:this.$=s[a];break;case 7:this.$=s[a];break;case 8:this.$=s[a];break;case 9:this.$=s[a];break;case 10:this.$=i.addLocationDataFn(o[a],o[a])(new i.Literal(s[a]));break;case 11:this.$=s[a];break;case 12:this.$=s[a];break;case 13:this.$=s[a];break;case 14:this.$=s[a];break;case 15:this.$=s[a];break;case 16:this.$=s[a];break;case 17:this.$=s[a];break;case 18:this.$=s[a];break;case 19:this.$=s[a];break;case 20:this.$=s[a];break;case 21:this.$=s[a];break;case 22:this.$=s[a];break;case 23:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Block);break;case 24:this.$=i.addLocationDataFn(o[a-2],o[a])(s[a-1]);break;case 25:this.$=i.addLocationDataFn(o[a],o[a])(new i.Literal(s[a]));break;case 26:this.$=i.addLocationDataFn(o[a],o[a])(new i.Literal(s[a]));break;case 27:this.$=i.addLocationDataFn(o[a],o[a])(new i.Literal(s[a]));break;case 28:this.$=s[a];break;case 29:this.$=i.addLocationDataFn(o[a],o[a])(new i.Literal(s[a]));break;case 30:this.$=i.addLocationDataFn(o[a],o[a])(new i.Literal(s[a]));
+break;case 31:this.$=i.addLocationDataFn(o[a],o[a])(new i.Literal(s[a]));break;case 32:this.$=i.addLocationDataFn(o[a],o[a])(new i.Undefined);break;case 33:this.$=i.addLocationDataFn(o[a],o[a])(new i.Null);break;case 34:this.$=i.addLocationDataFn(o[a],o[a])(new i.Bool(s[a]));break;case 35:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Assign(s[a-2],s[a]));break;case 36:this.$=i.addLocationDataFn(o[a-3],o[a])(new i.Assign(s[a-3],s[a]));break;case 37:this.$=i.addLocationDataFn(o[a-4],o[a])(new i.Assign(s[a-4],s[a-1]));break;case 38:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(s[a]));break;case 39:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Assign(i.addLocationDataFn(o[a-2])(new i.Value(s[a-2])),s[a],"object"));break;case 40:this.$=i.addLocationDataFn(o[a-4],o[a])(new i.Assign(i.addLocationDataFn(o[a-4])(new i.Value(s[a-4])),s[a-1],"object"));break;case 41:this.$=s[a];break;case 42:this.$=s[a];break;case 43:this.$=s[a];break;case 44:this.$=s[a];break;case 45:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Return(s[a]));break;case 46:this.$=i.addLocationDataFn(o[a],o[a])(new i.Return);break;case 47:this.$=i.addLocationDataFn(o[a],o[a])(new i.Comment(s[a]));break;case 48:this.$=i.addLocationDataFn(o[a-4],o[a])(new i.Code(s[a-3],s[a],s[a-1]));break;case 49:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Code([],s[a],s[a-1]));break;case 50:this.$=i.addLocationDataFn(o[a],o[a])("func");break;case 51:this.$=i.addLocationDataFn(o[a],o[a])("boundfunc");break;case 52:this.$=s[a];break;case 53:this.$=s[a];break;case 54:this.$=i.addLocationDataFn(o[a],o[a])([]);break;case 55:this.$=i.addLocationDataFn(o[a],o[a])([s[a]]);break;case 56:this.$=i.addLocationDataFn(o[a-2],o[a])(s[a-2].concat(s[a]));break;case 57:this.$=i.addLocationDataFn(o[a-3],o[a])(s[a-3].concat(s[a]));break;case 58:this.$=i.addLocationDataFn(o[a-5],o[a])(s[a-5].concat(s[a-2]));break;case 59:this.$=i.addLocationDataFn(o[a],o[a])(new i.Param(s[a]));break;case 60:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Param(s[a-1],null,!0));break;case 61:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Param(s[a-2],s[a]));break;case 62:this.$=i.addLocationDataFn(o[a],o[a])(new i.Expansion);break;case 63:this.$=s[a];break;case 64:this.$=s[a];break;case 65:this.$=s[a];break;case 66:this.$=s[a];break;case 67:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Splat(s[a-1]));break;case 68:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(s[a]));break;case 69:this.$=i.addLocationDataFn(o[a-1],o[a])(s[a-1].add(s[a]));break;case 70:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Value(s[a-1],[].concat(s[a])));break;case 71:this.$=s[a];break;case 72:this.$=s[a];break;case 73:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(s[a]));break;case 74:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(s[a]));break;case 75:this.$=s[a];break;case 76:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(s[a]));break;case 77:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(s[a]));break;case 78:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(s[a]));break;case 79:this.$=s[a];break;case 80:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Access(s[a]));break;case 81:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Access(s[a],"soak"));break;case 82:this.$=i.addLocationDataFn(o[a-1],o[a])([i.addLocationDataFn(o[a-1])(new i.Access(new i.Literal("prototype"))),i.addLocationDataFn(o[a])(new i.Access(s[a]))]);break;case 83:this.$=i.addLocationDataFn(o[a-1],o[a])([i.addLocationDataFn(o[a-1])(new i.Access(new i.Literal("prototype"),"soak")),i.addLocationDataFn(o[a])(new i.Access(s[a]))]);break;case 84:this.$=i.addLocationDataFn(o[a],o[a])(new i.Access(new i.Literal("prototype")));break;case 85:this.$=s[a];break;case 86:this.$=i.addLocationDataFn(o[a-2],o[a])(s[a-1]);break;case 87:this.$=i.addLocationDataFn(o[a-1],o[a])(i.extend(s[a],{soak:!0}));break;case 88:this.$=i.addLocationDataFn(o[a],o[a])(new i.Index(s[a]));break;case 89:this.$=i.addLocationDataFn(o[a],o[a])(new i.Slice(s[a]));break;case 90:this.$=i.addLocationDataFn(o[a-3],o[a])(new i.Obj(s[a-2],s[a-3].generated));break;case 91:this.$=i.addLocationDataFn(o[a],o[a])([]);break;case 92:this.$=i.addLocationDataFn(o[a],o[a])([s[a]]);break;case 93:this.$=i.addLocationDataFn(o[a-2],o[a])(s[a-2].concat(s[a]));break;case 94:this.$=i.addLocationDataFn(o[a-3],o[a])(s[a-3].concat(s[a]));break;case 95:this.$=i.addLocationDataFn(o[a-5],o[a])(s[a-5].concat(s[a-2]));break;case 96:this.$=i.addLocationDataFn(o[a],o[a])(new i.Class);break;case 97:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Class(null,null,s[a]));break;case 98:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Class(null,s[a]));break;case 99:this.$=i.addLocationDataFn(o[a-3],o[a])(new i.Class(null,s[a-1],s[a]));break;case 100:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Class(s[a]));break;case 101:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Class(s[a-1],null,s[a]));break;case 102:this.$=i.addLocationDataFn(o[a-3],o[a])(new i.Class(s[a-2],s[a]));break;case 103:this.$=i.addLocationDataFn(o[a-4],o[a])(new i.Class(s[a-3],s[a-1],s[a]));break;case 104:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Call(s[a-2],s[a],s[a-1]));break;case 105:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Call(s[a-2],s[a],s[a-1]));break;case 106:this.$=i.addLocationDataFn(o[a],o[a])(new i.Call("super",[new i.Splat(new i.Literal("arguments"))]));break;case 107:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Call("super",s[a]));break;case 108:this.$=i.addLocationDataFn(o[a],o[a])(!1);break;case 109:this.$=i.addLocationDataFn(o[a],o[a])(!0);break;case 110:this.$=i.addLocationDataFn(o[a-1],o[a])([]);break;case 111:this.$=i.addLocationDataFn(o[a-3],o[a])(s[a-2]);break;case 112:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(new i.Literal("this")));break;case 113:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(new i.Literal("this")));break;case 114:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Value(i.addLocationDataFn(o[a-1])(new i.Literal("this")),[i.addLocationDataFn(o[a])(new i.Access(s[a]))],"this"));break;case 115:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Arr([]));break;case 116:this.$=i.addLocationDataFn(o[a-3],o[a])(new i.Arr(s[a-2]));break;case 117:this.$=i.addLocationDataFn(o[a],o[a])("inclusive");break;case 118:this.$=i.addLocationDataFn(o[a],o[a])("exclusive");break;case 119:this.$=i.addLocationDataFn(o[a-4],o[a])(new i.Range(s[a-3],s[a-1],s[a-2]));break;case 120:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Range(s[a-2],s[a],s[a-1]));break;case 121:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Range(s[a-1],null,s[a]));break;case 122:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Range(null,s[a],s[a-1]));break;case 123:this.$=i.addLocationDataFn(o[a],o[a])(new i.Range(null,null,s[a]));break;case 124:this.$=i.addLocationDataFn(o[a],o[a])([s[a]]);break;case 125:this.$=i.addLocationDataFn(o[a-2],o[a])(s[a-2].concat(s[a]));break;case 126:this.$=i.addLocationDataFn(o[a-3],o[a])(s[a-3].concat(s[a]));break;case 127:this.$=i.addLocationDataFn(o[a-3],o[a])(s[a-2]);break;case 128:this.$=i.addLocationDataFn(o[a-5],o[a])(s[a-5].concat(s[a-2]));break;case 129:this.$=s[a];break;case 130:this.$=s[a];break;case 131:this.$=i.addLocationDataFn(o[a],o[a])(new i.Expansion);break;case 132:this.$=s[a];break;case 133:this.$=i.addLocationDataFn(o[a-2],o[a])([].concat(s[a-2],s[a]));break;case 134:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Try(s[a]));break;case 135:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Try(s[a-1],s[a][0],s[a][1]));break;case 136:this.$=i.addLocationDataFn(o[a-3],o[a])(new i.Try(s[a-2],null,null,s[a]));break;case 137:this.$=i.addLocationDataFn(o[a-4],o[a])(new i.Try(s[a-3],s[a-2][0],s[a-2][1],s[a]));break;case 138:this.$=i.addLocationDataFn(o[a-2],o[a])([s[a-1],s[a]]);break;case 139:this.$=i.addLocationDataFn(o[a-2],o[a])([i.addLocationDataFn(o[a-1])(new i.Value(s[a-1])),s[a]]);break;case 140:this.$=i.addLocationDataFn(o[a-1],o[a])([null,s[a]]);break;case 141:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Throw(s[a]));break;case 142:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Parens(s[a-1]));break;case 143:this.$=i.addLocationDataFn(o[a-4],o[a])(new i.Parens(s[a-2]));break;case 144:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.While(s[a]));break;case 145:this.$=i.addLocationDataFn(o[a-3],o[a])(new i.While(s[a-2],{guard:s[a]}));break;case 146:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.While(s[a],{invert:!0}));break;case 147:this.$=i.addLocationDataFn(o[a-3],o[a])(new i.While(s[a-2],{invert:!0,guard:s[a]}));break;case 148:this.$=i.addLocationDataFn(o[a-1],o[a])(s[a-1].addBody(s[a]));break;case 149:this.$=i.addLocationDataFn(o[a-1],o[a])(s[a].addBody(i.addLocationDataFn(o[a-1])(i.Block.wrap([s[a-1]]))));break;case 150:this.$=i.addLocationDataFn(o[a-1],o[a])(s[a].addBody(i.addLocationDataFn(o[a-1])(i.Block.wrap([s[a-1]]))));break;case 151:this.$=i.addLocationDataFn(o[a],o[a])(s[a]);break;case 152:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.While(i.addLocationDataFn(o[a-1])(new i.Literal("true"))).addBody(s[a]));break;case 153:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.While(i.addLocationDataFn(o[a-1])(new i.Literal("true"))).addBody(i.addLocationDataFn(o[a])(i.Block.wrap([s[a]]))));break;case 154:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.For(s[a-1],s[a]));break;case 155:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.For(s[a-1],s[a]));break;case 156:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.For(s[a],s[a-1]));break;case 157:this.$=i.addLocationDataFn(o[a-1],o[a])({source:i.addLocationDataFn(o[a])(new i.Value(s[a]))});break;case 158:this.$=i.addLocationDataFn(o[a-1],o[a])(function(){return s[a].own=s[a-1].own,s[a].name=s[a-1][0],s[a].index=s[a-1][1],s[a]}());break;case 159:this.$=i.addLocationDataFn(o[a-1],o[a])(s[a]);break;case 160:this.$=i.addLocationDataFn(o[a-2],o[a])(function(){return s[a].own=!0,s[a]}());break;case 161:this.$=s[a];break;case 162:this.$=s[a];break;case 163:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(s[a]));break;case 164:this.$=i.addLocationDataFn(o[a],o[a])(new i.Value(s[a]));break;case 165:this.$=i.addLocationDataFn(o[a],o[a])([s[a]]);break;case 166:this.$=i.addLocationDataFn(o[a-2],o[a])([s[a-2],s[a]]);break;case 167:this.$=i.addLocationDataFn(o[a-1],o[a])({source:s[a]});break;case 168:this.$=i.addLocationDataFn(o[a-1],o[a])({source:s[a],object:!0});break;case 169:this.$=i.addLocationDataFn(o[a-3],o[a])({source:s[a-2],guard:s[a]});break;case 170:this.$=i.addLocationDataFn(o[a-3],o[a])({source:s[a-2],guard:s[a],object:!0});break;case 171:this.$=i.addLocationDataFn(o[a-3],o[a])({source:s[a-2],step:s[a]});break;case 172:this.$=i.addLocationDataFn(o[a-5],o[a])({source:s[a-4],guard:s[a-2],step:s[a]});break;case 173:this.$=i.addLocationDataFn(o[a-5],o[a])({source:s[a-4],step:s[a-2],guard:s[a]});break;case 174:this.$=i.addLocationDataFn(o[a-4],o[a])(new i.Switch(s[a-3],s[a-1]));break;case 175:this.$=i.addLocationDataFn(o[a-6],o[a])(new i.Switch(s[a-5],s[a-3],s[a-1]));break;case 176:this.$=i.addLocationDataFn(o[a-3],o[a])(new i.Switch(null,s[a-1]));break;case 177:this.$=i.addLocationDataFn(o[a-5],o[a])(new i.Switch(null,s[a-3],s[a-1]));break;case 178:this.$=s[a];break;case 179:this.$=i.addLocationDataFn(o[a-1],o[a])(s[a-1].concat(s[a]));break;case 180:this.$=i.addLocationDataFn(o[a-2],o[a])([[s[a-1],s[a]]]);break;case 181:this.$=i.addLocationDataFn(o[a-3],o[a])([[s[a-2],s[a-1]]]);break;case 182:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.If(s[a-1],s[a],{type:s[a-2]}));break;case 183:this.$=i.addLocationDataFn(o[a-4],o[a])(s[a-4].addElse(i.addLocationDataFn(o[a-2],o[a])(new i.If(s[a-1],s[a],{type:s[a-2]}))));break;case 184:this.$=s[a];break;case 185:this.$=i.addLocationDataFn(o[a-2],o[a])(s[a-2].addElse(s[a]));break;case 186:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.If(s[a],i.addLocationDataFn(o[a-2])(i.Block.wrap([s[a-2]])),{type:s[a-1],statement:!0}));break;case 187:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.If(s[a],i.addLocationDataFn(o[a-2])(i.Block.wrap([s[a-2]])),{type:s[a-1],statement:!0}));break;case 188:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Op(s[a-1],s[a]));break;case 189:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Op(s[a-1],s[a]));break;case 190:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Op("-",s[a]));break;case 191:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Op("+",s[a]));break;case 192:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Op("--",s[a]));break;case 193:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Op("++",s[a]));break;case 194:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Op("--",s[a-1],null,!0));break;case 195:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Op("++",s[a-1],null,!0));break;case 196:this.$=i.addLocationDataFn(o[a-1],o[a])(new i.Existence(s[a-1]));break;case 197:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Op("+",s[a-2],s[a]));break;case 198:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Op("-",s[a-2],s[a]));break;case 199:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Op(s[a-1],s[a-2],s[a]));break;case 200:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Op(s[a-1],s[a-2],s[a]));break;case 201:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Op(s[a-1],s[a-2],s[a]));break;case 202:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Op(s[a-1],s[a-2],s[a]));break;case 203:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Op(s[a-1],s[a-2],s[a]));break;case 204:this.$=i.addLocationDataFn(o[a-2],o[a])(function(){return"!"===s[a-1].charAt(0)?new i.Op(s[a-1].slice(1),s[a-2],s[a]).invert():new i.Op(s[a-1],s[a-2],s[a])}());break;case 205:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Assign(s[a-2],s[a],s[a-1]));break;case 206:this.$=i.addLocationDataFn(o[a-4],o[a])(new i.Assign(s[a-4],s[a-1],s[a-3]));break;case 207:this.$=i.addLocationDataFn(o[a-3],o[a])(new i.Assign(s[a-3],s[a],s[a-2]));break;case 208:this.$=i.addLocationDataFn(o[a-2],o[a])(new i.Extends(s[a-2],s[a]))}},table:[{1:[2,1],3:1,4:2,5:3,7:4,8:5,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[3]},{1:[2,2],6:[1,73]},{1:[2,3],6:[2,3],26:[2,3],102:[2,3]},{1:[2,6],6:[2,6],26:[2,6],102:[2,6],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,7],6:[2,7],26:[2,7],102:[2,7],103:87,104:[1,64],106:[1,65],109:88,110:[1,67],111:68,126:[1,86]},{1:[2,11],6:[2,11],25:[2,11],26:[2,11],49:[2,11],54:[2,11],57:[2,11],62:90,66:[1,92],67:[1,93],68:[1,94],69:[1,95],70:96,71:[1,97],73:[2,11],74:[1,98],78:[2,11],81:89,84:[1,91],85:[2,108],86:[2,11],91:[2,11],93:[2,11],102:[2,11],104:[2,11],105:[2,11],106:[2,11],110:[2,11],118:[2,11],126:[2,11],129:[2,11],130:[2,11],133:[2,11],134:[2,11],135:[2,11],136:[2,11],137:[2,11],138:[2,11],139:[2,11]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],49:[2,12],54:[2,12],57:[2,12],62:100,66:[1,92],67:[1,93],68:[1,94],69:[1,95],70:96,71:[1,97],73:[2,12],74:[1,98],78:[2,12],81:99,84:[1,91],85:[2,108],86:[2,12],91:[2,12],93:[2,12],102:[2,12],104:[2,12],105:[2,12],106:[2,12],110:[2,12],118:[2,12],126:[2,12],129:[2,12],130:[2,12],133:[2,12],134:[2,12],135:[2,12],136:[2,12],137:[2,12],138:[2,12],139:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],49:[2,13],54:[2,13],57:[2,13],73:[2,13],78:[2,13],86:[2,13],91:[2,13],93:[2,13],102:[2,13],104:[2,13],105:[2,13],106:[2,13],110:[2,13],118:[2,13],126:[2,13],129:[2,13],130:[2,13],133:[2,13],134:[2,13],135:[2,13],136:[2,13],137:[2,13],138:[2,13],139:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],49:[2,14],54:[2,14],57:[2,14],73:[2,14],78:[2,14],86:[2,14],91:[2,14],93:[2,14],102:[2,14],104:[2,14],105:[2,14],106:[2,14],110:[2,14],118:[2,14],126:[2,14],129:[2,14],130:[2,14],133:[2,14],134:[2,14],135:[2,14],136:[2,14],137:[2,14],138:[2,14],139:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],49:[2,15],54:[2,15],57:[2,15],73:[2,15],78:[2,15],86:[2,15],91:[2,15],93:[2,15],102:[2,15],104:[2,15],105:[2,15],106:[2,15],110:[2,15],118:[2,15],126:[2,15],129:[2,15],130:[2,15],133:[2,15],134:[2,15],135:[2,15],136:[2,15],137:[2,15],138:[2,15],139:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],49:[2,16],54:[2,16],57:[2,16],73:[2,16],78:[2,16],86:[2,16],91:[2,16],93:[2,16],102:[2,16],104:[2,16],105:[2,16],106:[2,16],110:[2,16],118:[2,16],126:[2,16],129:[2,16],130:[2,16],133:[2,16],134:[2,16],135:[2,16],136:[2,16],137:[2,16],138:[2,16],139:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],49:[2,17],54:[2,17],57:[2,17],73:[2,17],78:[2,17],86:[2,17],91:[2,17],93:[2,17],102:[2,17],104:[2,17],105:[2,17],106:[2,17],110:[2,17],118:[2,17],126:[2,17],129:[2,17],130:[2,17],133:[2,17],134:[2,17],135:[2,17],136:[2,17],137:[2,17],138:[2,17],139:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],49:[2,18],54:[2,18],57:[2,18],73:[2,18],78:[2,18],86:[2,18],91:[2,18],93:[2,18],102:[2,18],104:[2,18],105:[2,18],106:[2,18],110:[2,18],118:[2,18],126:[2,18],129:[2,18],130:[2,18],133:[2,18],134:[2,18],135:[2,18],136:[2,18],137:[2,18],138:[2,18],139:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],49:[2,19],54:[2,19],57:[2,19],73:[2,19],78:[2,19],86:[2,19],91:[2,19],93:[2,19],102:[2,19],104:[2,19],105:[2,19],106:[2,19],110:[2,19],118:[2,19],126:[2,19],129:[2,19],130:[2,19],133:[2,19],134:[2,19],135:[2,19],136:[2,19],137:[2,19],138:[2,19],139:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],49:[2,20],54:[2,20],57:[2,20],73:[2,20],78:[2,20],86:[2,20],91:[2,20],93:[2,20],102:[2,20],104:[2,20],105:[2,20],106:[2,20],110:[2,20],118:[2,20],126:[2,20],129:[2,20],130:[2,20],133:[2,20],134:[2,20],135:[2,20],136:[2,20],137:[2,20],138:[2,20],139:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],49:[2,21],54:[2,21],57:[2,21],73:[2,21],78:[2,21],86:[2,21],91:[2,21],93:[2,21],102:[2,21],104:[2,21],105:[2,21],106:[2,21],110:[2,21],118:[2,21],126:[2,21],129:[2,21],130:[2,21],133:[2,21],134:[2,21],135:[2,21],136:[2,21],137:[2,21],138:[2,21],139:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],49:[2,22],54:[2,22],57:[2,22],73:[2,22],78:[2,22],86:[2,22],91:[2,22],93:[2,22],102:[2,22],104:[2,22],105:[2,22],106:[2,22],110:[2,22],118:[2,22],126:[2,22],129:[2,22],130:[2,22],133:[2,22],134:[2,22],135:[2,22],136:[2,22],137:[2,22],138:[2,22],139:[2,22]},{1:[2,8],6:[2,8],26:[2,8],102:[2,8],104:[2,8],106:[2,8],110:[2,8],126:[2,8]},{1:[2,9],6:[2,9],26:[2,9],102:[2,9],104:[2,9],106:[2,9],110:[2,9],126:[2,9]},{1:[2,10],6:[2,10],26:[2,10],102:[2,10],104:[2,10],106:[2,10],110:[2,10],126:[2,10]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],40:[1,101],49:[2,75],54:[2,75],57:[2,75],66:[2,75],67:[2,75],68:[2,75],69:[2,75],71:[2,75],73:[2,75],74:[2,75],78:[2,75],84:[2,75],85:[2,75],86:[2,75],91:[2,75],93:[2,75],102:[2,75],104:[2,75],105:[2,75],106:[2,75],110:[2,75],118:[2,75],126:[2,75],129:[2,75],130:[2,75],133:[2,75],134:[2,75],135:[2,75],136:[2,75],137:[2,75],138:[2,75],139:[2,75]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],49:[2,76],54:[2,76],57:[2,76],66:[2,76],67:[2,76],68:[2,76],69:[2,76],71:[2,76],73:[2,76],74:[2,76],78:[2,76],84:[2,76],85:[2,76],86:[2,76],91:[2,76],93:[2,76],102:[2,76],104:[2,76],105:[2,76],106:[2,76],110:[2,76],118:[2,76],126:[2,76],129:[2,76],130:[2,76],133:[2,76],134:[2,76],135:[2,76],136:[2,76],137:[2,76],138:[2,76],139:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],49:[2,77],54:[2,77],57:[2,77],66:[2,77],67:[2,77],68:[2,77],69:[2,77],71:[2,77],73:[2,77],74:[2,77],78:[2,77],84:[2,77],85:[2,77],86:[2,77],91:[2,77],93:[2,77],102:[2,77],104:[2,77],105:[2,77],106:[2,77],110:[2,77],118:[2,77],126:[2,77],129:[2,77],130:[2,77],133:[2,77],134:[2,77],135:[2,77],136:[2,77],137:[2,77],138:[2,77],139:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],49:[2,78],54:[2,78],57:[2,78],66:[2,78],67:[2,78],68:[2,78],69:[2,78],71:[2,78],73:[2,78],74:[2,78],78:[2,78],84:[2,78],85:[2,78],86:[2,78],91:[2,78],93:[2,78],102:[2,78],104:[2,78],105:[2,78],106:[2,78],110:[2,78],118:[2,78],126:[2,78],129:[2,78],130:[2,78],133:[2,78],134:[2,78],135:[2,78],136:[2,78],137:[2,78],138:[2,78],139:[2,78]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],49:[2,79],54:[2,79],57:[2,79],66:[2,79],67:[2,79],68:[2,79],69:[2,79],71:[2,79],73:[2,79],74:[2,79],78:[2,79],84:[2,79],85:[2,79],86:[2,79],91:[2,79],93:[2,79],102:[2,79],104:[2,79],105:[2,79],106:[2,79],110:[2,79],118:[2,79],126:[2,79],129:[2,79],130:[2,79],133:[2,79],134:[2,79],135:[2,79],136:[2,79],137:[2,79],138:[2,79],139:[2,79]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],49:[2,106],54:[2,106],57:[2,106],66:[2,106],67:[2,106],68:[2,106],69:[2,106],71:[2,106],73:[2,106],74:[2,106],78:[2,106],82:102,84:[2,106],85:[1,103],86:[2,106],91:[2,106],93:[2,106],102:[2,106],104:[2,106],105:[2,106],106:[2,106],110:[2,106],118:[2,106],126:[2,106],129:[2,106],130:[2,106],133:[2,106],134:[2,106],135:[2,106],136:[2,106],137:[2,106],138:[2,106],139:[2,106]},{6:[2,54],25:[2,54],27:108,28:[1,72],44:109,48:104,49:[2,54],54:[2,54],55:105,56:106,57:[1,107],58:110,59:111,76:[1,69],89:[1,112],90:[1,113]},{24:114,25:[1,115]},{7:116,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:118,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:119,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:120,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{12:122,13:123,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:124,44:62,58:46,59:47,61:121,63:23,64:24,65:25,76:[1,69],83:[1,26],88:[1,57],89:[1,58],90:[1,56],101:[1,55]},{12:122,13:123,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:124,44:62,58:46,59:47,61:125,63:23,64:24,65:25,76:[1,69],83:[1,26],88:[1,57],89:[1,58],90:[1,56],101:[1,55]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],40:[2,72],49:[2,72],54:[2,72],57:[2,72],66:[2,72],67:[2,72],68:[2,72],69:[2,72],71:[2,72],73:[2,72],74:[2,72],78:[2,72],80:[1,129],84:[2,72],85:[2,72],86:[2,72],91:[2,72],93:[2,72],102:[2,72],104:[2,72],105:[2,72],106:[2,72],110:[2,72],118:[2,72],126:[2,72],129:[2,72],130:[2,72],131:[1,126],132:[1,127],133:[2,72],134:[2,72],135:[2,72],136:[2,72],137:[2,72],138:[2,72],139:[2,72],140:[1,128]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],49:[2,184],54:[2,184],57:[2,184],73:[2,184],78:[2,184],86:[2,184],91:[2,184],93:[2,184],102:[2,184],104:[2,184],105:[2,184],106:[2,184],110:[2,184],118:[2,184],121:[1,130],126:[2,184],129:[2,184],130:[2,184],133:[2,184],134:[2,184],135:[2,184],136:[2,184],137:[2,184],138:[2,184],139:[2,184]},{24:131,25:[1,115]},{24:132,25:[1,115]},{1:[2,151],6:[2,151],25:[2,151],26:[2,151],49:[2,151],54:[2,151],57:[2,151],73:[2,151],78:[2,151],86:[2,151],91:[2,151],93:[2,151],102:[2,151],104:[2,151],105:[2,151],106:[2,151],110:[2,151],118:[2,151],126:[2,151],129:[2,151],130:[2,151],133:[2,151],134:[2,151],135:[2,151],136:[2,151],137:[2,151],138:[2,151],139:[2,151]},{24:133,25:[1,115]},{7:134,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,135],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,96],6:[2,96],12:122,13:123,24:136,25:[1,115],26:[2,96],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:124,44:62,49:[2,96],54:[2,96],57:[2,96],58:46,59:47,61:138,63:23,64:24,65:25,73:[2,96],76:[1,69],78:[2,96],80:[1,137],83:[1,26],86:[2,96],88:[1,57],89:[1,58],90:[1,56],91:[2,96],93:[2,96],101:[1,55],102:[2,96],104:[2,96],105:[2,96],106:[2,96],110:[2,96],118:[2,96],126:[2,96],129:[2,96],130:[2,96],133:[2,96],134:[2,96],135:[2,96],136:[2,96],137:[2,96],138:[2,96],139:[2,96]},{7:139,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,46],6:[2,46],7:140,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,26:[2,46],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],102:[2,46],103:38,104:[2,46],106:[2,46],107:39,108:[1,66],109:40,110:[2,46],111:68,119:[1,41],124:36,125:[1,63],126:[2,46],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,47],6:[2,47],25:[2,47],26:[2,47],54:[2,47],78:[2,47],102:[2,47],104:[2,47],106:[2,47],110:[2,47],126:[2,47]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],40:[2,73],49:[2,73],54:[2,73],57:[2,73],66:[2,73],67:[2,73],68:[2,73],69:[2,73],71:[2,73],73:[2,73],74:[2,73],78:[2,73],84:[2,73],85:[2,73],86:[2,73],91:[2,73],93:[2,73],102:[2,73],104:[2,73],105:[2,73],106:[2,73],110:[2,73],118:[2,73],126:[2,73],129:[2,73],130:[2,73],133:[2,73],134:[2,73],135:[2,73],136:[2,73],137:[2,73],138:[2,73],139:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],40:[2,74],49:[2,74],54:[2,74],57:[2,74],66:[2,74],67:[2,74],68:[2,74],69:[2,74],71:[2,74],73:[2,74],74:[2,74],78:[2,74],84:[2,74],85:[2,74],86:[2,74],91:[2,74],93:[2,74],102:[2,74],104:[2,74],105:[2,74],106:[2,74],110:[2,74],118:[2,74],126:[2,74],129:[2,74],130:[2,74],133:[2,74],134:[2,74],135:[2,74],136:[2,74],137:[2,74],138:[2,74],139:[2,74]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],49:[2,28],54:[2,28],57:[2,28],66:[2,28],67:[2,28],68:[2,28],69:[2,28],71:[2,28],73:[2,28],74:[2,28],78:[2,28],84:[2,28],85:[2,28],86:[2,28],91:[2,28],93:[2,28],102:[2,28],104:[2,28],105:[2,28],106:[2,28],110:[2,28],118:[2,28],126:[2,28],129:[2,28],130:[2,28],133:[2,28],134:[2,28],135:[2,28],136:[2,28],137:[2,28],138:[2,28],139:[2,28]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],49:[2,29],54:[2,29],57:[2,29],66:[2,29],67:[2,29],68:[2,29],69:[2,29],71:[2,29],73:[2,29],74:[2,29],78:[2,29],84:[2,29],85:[2,29],86:[2,29],91:[2,29],93:[2,29],102:[2,29],104:[2,29],105:[2,29],106:[2,29],110:[2,29],118:[2,29],126:[2,29],129:[2,29],130:[2,29],133:[2,29],134:[2,29],135:[2,29],136:[2,29],137:[2,29],138:[2,29],139:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],49:[2,30],54:[2,30],57:[2,30],66:[2,30],67:[2,30],68:[2,30],69:[2,30],71:[2,30],73:[2,30],74:[2,30],78:[2,30],84:[2,30],85:[2,30],86:[2,30],91:[2,30],93:[2,30],102:[2,30],104:[2,30],105:[2,30],106:[2,30],110:[2,30],118:[2,30],126:[2,30],129:[2,30],130:[2,30],133:[2,30],134:[2,30],135:[2,30],136:[2,30],137:[2,30],138:[2,30],139:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],49:[2,31],54:[2,31],57:[2,31],66:[2,31],67:[2,31],68:[2,31],69:[2,31],71:[2,31],73:[2,31],74:[2,31],78:[2,31],84:[2,31],85:[2,31],86:[2,31],91:[2,31],93:[2,31],102:[2,31],104:[2,31],105:[2,31],106:[2,31],110:[2,31],118:[2,31],126:[2,31],129:[2,31],130:[2,31],133:[2,31],134:[2,31],135:[2,31],136:[2,31],137:[2,31],138:[2,31],139:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],49:[2,32],54:[2,32],57:[2,32],66:[2,32],67:[2,32],68:[2,32],69:[2,32],71:[2,32],73:[2,32],74:[2,32],78:[2,32],84:[2,32],85:[2,32],86:[2,32],91:[2,32],93:[2,32],102:[2,32],104:[2,32],105:[2,32],106:[2,32],110:[2,32],118:[2,32],126:[2,32],129:[2,32],130:[2,32],133:[2,32],134:[2,32],135:[2,32],136:[2,32],137:[2,32],138:[2,32],139:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],49:[2,33],54:[2,33],57:[2,33],66:[2,33],67:[2,33],68:[2,33],69:[2,33],71:[2,33],73:[2,33],74:[2,33],78:[2,33],84:[2,33],85:[2,33],86:[2,33],91:[2,33],93:[2,33],102:[2,33],104:[2,33],105:[2,33],106:[2,33],110:[2,33],118:[2,33],126:[2,33],129:[2,33],130:[2,33],133:[2,33],134:[2,33],135:[2,33],136:[2,33],137:[2,33],138:[2,33],139:[2,33]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],49:[2,34],54:[2,34],57:[2,34],66:[2,34],67:[2,34],68:[2,34],69:[2,34],71:[2,34],73:[2,34],74:[2,34],78:[2,34],84:[2,34],85:[2,34],86:[2,34],91:[2,34],93:[2,34],102:[2,34],104:[2,34],105:[2,34],106:[2,34],110:[2,34],118:[2,34],126:[2,34],129:[2,34],130:[2,34],133:[2,34],134:[2,34],135:[2,34],136:[2,34],137:[2,34],138:[2,34],139:[2,34]},{4:141,5:3,7:4,8:5,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,142],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:143,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,147],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],57:[1,149],58:46,59:47,60:148,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],87:145,88:[1,57],89:[1,58],90:[1,56],91:[1,144],94:146,96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,112],6:[2,112],25:[2,112],26:[2,112],49:[2,112],54:[2,112],57:[2,112],66:[2,112],67:[2,112],68:[2,112],69:[2,112],71:[2,112],73:[2,112],74:[2,112],78:[2,112],84:[2,112],85:[2,112],86:[2,112],91:[2,112],93:[2,112],102:[2,112],104:[2,112],105:[2,112],106:[2,112],110:[2,112],118:[2,112],126:[2,112],129:[2,112],130:[2,112],133:[2,112],134:[2,112],135:[2,112],136:[2,112],137:[2,112],138:[2,112],139:[2,112]},{1:[2,113],6:[2,113],25:[2,113],26:[2,113],27:150,28:[1,72],49:[2,113],54:[2,113],57:[2,113],66:[2,113],67:[2,113],68:[2,113],69:[2,113],71:[2,113],73:[2,113],74:[2,113],78:[2,113],84:[2,113],85:[2,113],86:[2,113],91:[2,113],93:[2,113],102:[2,113],104:[2,113],105:[2,113],106:[2,113],110:[2,113],118:[2,113],126:[2,113],129:[2,113],130:[2,113],133:[2,113],134:[2,113],135:[2,113],136:[2,113],137:[2,113],138:[2,113],139:[2,113]},{25:[2,50]},{25:[2,51]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],40:[2,68],49:[2,68],54:[2,68],57:[2,68],66:[2,68],67:[2,68],68:[2,68],69:[2,68],71:[2,68],73:[2,68],74:[2,68],78:[2,68],80:[2,68],84:[2,68],85:[2,68],86:[2,68],91:[2,68],93:[2,68],102:[2,68],104:[2,68],105:[2,68],106:[2,68],110:[2,68],118:[2,68],126:[2,68],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[2,68],136:[2,68],137:[2,68],138:[2,68],139:[2,68],140:[2,68]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],40:[2,71],49:[2,71],54:[2,71],57:[2,71],66:[2,71],67:[2,71],68:[2,71],69:[2,71],71:[2,71],73:[2,71],74:[2,71],78:[2,71],80:[2,71],84:[2,71],85:[2,71],86:[2,71],91:[2,71],93:[2,71],102:[2,71],104:[2,71],105:[2,71],106:[2,71],110:[2,71],118:[2,71],126:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71],135:[2,71],136:[2,71],137:[2,71],138:[2,71],139:[2,71],140:[2,71]},{7:151,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:152,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:153,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:155,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:154,25:[1,115],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{27:160,28:[1,72],44:161,58:162,59:163,64:156,76:[1,69],89:[1,112],90:[1,56],113:157,114:[1,158],115:159},{112:164,116:[1,165],117:[1,166]},{6:[2,91],10:170,25:[2,91],27:171,28:[1,72],29:172,30:[1,70],31:[1,71],41:168,42:169,44:173,46:[1,45],54:[2,91],77:167,78:[2,91],89:[1,112]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],43:[2,26],49:[2,26],54:[2,26],57:[2,26],66:[2,26],67:[2,26],68:[2,26],69:[2,26],71:[2,26],73:[2,26],74:[2,26],78:[2,26],84:[2,26],85:[2,26],86:[2,26],91:[2,26],93:[2,26],102:[2,26],104:[2,26],105:[2,26],106:[2,26],110:[2,26],118:[2,26],126:[2,26],129:[2,26],130:[2,26],133:[2,26],134:[2,26],135:[2,26],136:[2,26],137:[2,26],138:[2,26],139:[2,26]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],43:[2,27],49:[2,27],54:[2,27],57:[2,27],66:[2,27],67:[2,27],68:[2,27],69:[2,27],71:[2,27],73:[2,27],74:[2,27],78:[2,27],84:[2,27],85:[2,27],86:[2,27],91:[2,27],93:[2,27],102:[2,27],104:[2,27],105:[2,27],106:[2,27],110:[2,27],118:[2,27],126:[2,27],129:[2,27],130:[2,27],133:[2,27],134:[2,27],135:[2,27],136:[2,27],137:[2,27],138:[2,27],139:[2,27]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],40:[2,25],43:[2,25],49:[2,25],54:[2,25],57:[2,25],66:[2,25],67:[2,25],68:[2,25],69:[2,25],71:[2,25],73:[2,25],74:[2,25],78:[2,25],80:[2,25],84:[2,25],85:[2,25],86:[2,25],91:[2,25],93:[2,25],102:[2,25],104:[2,25],105:[2,25],106:[2,25],110:[2,25],116:[2,25],117:[2,25],118:[2,25],126:[2,25],129:[2,25],130:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25],135:[2,25],136:[2,25],137:[2,25],138:[2,25],139:[2,25],140:[2,25]},{1:[2,5],5:174,6:[2,5],7:4,8:5,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,26:[2,5],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],102:[2,5],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,196],6:[2,196],25:[2,196],26:[2,196],49:[2,196],54:[2,196],57:[2,196],73:[2,196],78:[2,196],86:[2,196],91:[2,196],93:[2,196],102:[2,196],104:[2,196],105:[2,196],106:[2,196],110:[2,196],118:[2,196],126:[2,196],129:[2,196],130:[2,196],133:[2,196],134:[2,196],135:[2,196],136:[2,196],137:[2,196],138:[2,196],139:[2,196]},{7:175,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:176,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:177,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:178,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:179,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:180,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:181,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:182,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:183,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,150],6:[2,150],25:[2,150],26:[2,150],49:[2,150],54:[2,150],57:[2,150],73:[2,150],78:[2,150],86:[2,150],91:[2,150],93:[2,150],102:[2,150],104:[2,150],105:[2,150],106:[2,150],110:[2,150],118:[2,150],126:[2,150],129:[2,150],130:[2,150],133:[2,150],134:[2,150],135:[2,150],136:[2,150],137:[2,150],138:[2,150],139:[2,150]},{1:[2,155],6:[2,155],25:[2,155],26:[2,155],49:[2,155],54:[2,155],57:[2,155],73:[2,155],78:[2,155],86:[2,155],91:[2,155],93:[2,155],102:[2,155],104:[2,155],105:[2,155],106:[2,155],110:[2,155],118:[2,155],126:[2,155],129:[2,155],130:[2,155],133:[2,155],134:[2,155],135:[2,155],136:[2,155],137:[2,155],138:[2,155],139:[2,155]},{7:184,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],49:[2,149],54:[2,149],57:[2,149],73:[2,149],78:[2,149],86:[2,149],91:[2,149],93:[2,149],102:[2,149],104:[2,149],105:[2,149],106:[2,149],110:[2,149],118:[2,149],126:[2,149],129:[2,149],130:[2,149],133:[2,149],134:[2,149],135:[2,149],136:[2,149],137:[2,149],138:[2,149],139:[2,149]},{1:[2,154],6:[2,154],25:[2,154],26:[2,154],49:[2,154],54:[2,154],57:[2,154],73:[2,154],78:[2,154],86:[2,154],91:[2,154],93:[2,154],102:[2,154],104:[2,154],105:[2,154],106:[2,154],110:[2,154],118:[2,154],126:[2,154],129:[2,154],130:[2,154],133:[2,154],134:[2,154],135:[2,154],136:[2,154],137:[2,154],138:[2,154],139:[2,154]},{82:185,85:[1,103]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],40:[2,69],49:[2,69],54:[2,69],57:[2,69],66:[2,69],67:[2,69],68:[2,69],69:[2,69],71:[2,69],73:[2,69],74:[2,69],78:[2,69],80:[2,69],84:[2,69],85:[2,69],86:[2,69],91:[2,69],93:[2,69],102:[2,69],104:[2,69],105:[2,69],106:[2,69],110:[2,69],118:[2,69],126:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69],135:[2,69],136:[2,69],137:[2,69],138:[2,69],139:[2,69],140:[2,69]},{85:[2,109]},{27:186,28:[1,72]},{27:187,28:[1,72]},{1:[2,84],6:[2,84],25:[2,84],26:[2,84],27:188,28:[1,72],40:[2,84],49:[2,84],54:[2,84],57:[2,84],66:[2,84],67:[2,84],68:[2,84],69:[2,84],71:[2,84],73:[2,84],74:[2,84],78:[2,84],80:[2,84],84:[2,84],85:[2,84],86:[2,84],91:[2,84],93:[2,84],102:[2,84],104:[2,84],105:[2,84],106:[2,84],110:[2,84],118:[2,84],126:[2,84],129:[2,84],130:[2,84],131:[2,84],132:[2,84],133:[2,84],134:[2,84],135:[2,84],136:[2,84],137:[2,84],138:[2,84],139:[2,84],140:[2,84]},{27:189,28:[1,72]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],40:[2,85],49:[2,85],54:[2,85],57:[2,85],66:[2,85],67:[2,85],68:[2,85],69:[2,85],71:[2,85],73:[2,85],74:[2,85],78:[2,85],80:[2,85],84:[2,85],85:[2,85],86:[2,85],91:[2,85],93:[2,85],102:[2,85],104:[2,85],105:[2,85],106:[2,85],110:[2,85],118:[2,85],126:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85],135:[2,85],136:[2,85],137:[2,85],138:[2,85],139:[2,85],140:[2,85]},{7:191,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],57:[1,195],58:46,59:47,61:35,63:23,64:24,65:25,72:190,75:192,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],92:193,93:[1,194],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{70:196,71:[1,97],74:[1,98]},{82:197,85:[1,103]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],40:[2,70],49:[2,70],54:[2,70],57:[2,70],66:[2,70],67:[2,70],68:[2,70],69:[2,70],71:[2,70],73:[2,70],74:[2,70],78:[2,70],80:[2,70],84:[2,70],85:[2,70],86:[2,70],91:[2,70],93:[2,70],102:[2,70],104:[2,70],105:[2,70],106:[2,70],110:[2,70],118:[2,70],126:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70],135:[2,70],136:[2,70],137:[2,70],138:[2,70],139:[2,70],140:[2,70]},{6:[1,199],7:198,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,200],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,107],6:[2,107],25:[2,107],26:[2,107],49:[2,107],54:[2,107],57:[2,107],66:[2,107],67:[2,107],68:[2,107],69:[2,107],71:[2,107],73:[2,107],74:[2,107],78:[2,107],84:[2,107],85:[2,107],86:[2,107],91:[2,107],93:[2,107],102:[2,107],104:[2,107],105:[2,107],106:[2,107],110:[2,107],118:[2,107],126:[2,107],129:[2,107],130:[2,107],133:[2,107],134:[2,107],135:[2,107],136:[2,107],137:[2,107],138:[2,107],139:[2,107]},{7:203,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,147],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],57:[1,149],58:46,59:47,60:148,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],86:[1,201],87:202,88:[1,57],89:[1,58],90:[1,56],94:146,96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{6:[2,52],25:[2,52],49:[1,204],53:206,54:[1,205]},{6:[2,55],25:[2,55],26:[2,55],49:[2,55],54:[2,55]},{6:[2,59],25:[2,59],26:[2,59],40:[1,208],49:[2,59],54:[2,59],57:[1,207]},{6:[2,62],25:[2,62],26:[2,62],49:[2,62],54:[2,62]},{6:[2,63],25:[2,63],26:[2,63],40:[2,63],49:[2,63],54:[2,63],57:[2,63]},{6:[2,64],25:[2,64],26:[2,64],40:[2,64],49:[2,64],54:[2,64],57:[2,64]},{6:[2,65],25:[2,65],26:[2,65],40:[2,65],49:[2,65],54:[2,65],57:[2,65]},{6:[2,66],25:[2,66],26:[2,66],40:[2,66],49:[2,66],54:[2,66],57:[2,66]},{27:150,28:[1,72]},{7:203,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,147],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],57:[1,149],58:46,59:47,60:148,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],87:145,88:[1,57],89:[1,58],90:[1,56],91:[1,144],94:146,96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,49],6:[2,49],25:[2,49],26:[2,49],49:[2,49],54:[2,49],57:[2,49],73:[2,49],78:[2,49],86:[2,49],91:[2,49],93:[2,49],102:[2,49],104:[2,49],105:[2,49],106:[2,49],110:[2,49],118:[2,49],126:[2,49],129:[2,49],130:[2,49],133:[2,49],134:[2,49],135:[2,49],136:[2,49],137:[2,49],138:[2,49],139:[2,49]},{4:210,5:3,7:4,8:5,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,26:[1,209],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],49:[2,188],54:[2,188],57:[2,188],73:[2,188],78:[2,188],86:[2,188],91:[2,188],93:[2,188],102:[2,188],103:84,104:[2,188],105:[2,188],106:[2,188],109:85,110:[2,188],111:68,118:[2,188],126:[2,188],129:[2,188],130:[2,188],133:[1,74],134:[2,188],135:[2,188],136:[2,188],137:[2,188],138:[2,188],139:[2,188]},{103:87,104:[1,64],106:[1,65],109:88,110:[1,67],111:68,126:[1,86]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],49:[2,189],54:[2,189],57:[2,189],73:[2,189],78:[2,189],86:[2,189],91:[2,189],93:[2,189],102:[2,189],103:84,104:[2,189],105:[2,189],106:[2,189],109:85,110:[2,189],111:68,118:[2,189],126:[2,189],129:[2,189],130:[2,189],133:[1,74],134:[2,189],135:[1,78],136:[2,189],137:[2,189],138:[2,189],139:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],49:[2,190],54:[2,190],57:[2,190],73:[2,190],78:[2,190],86:[2,190],91:[2,190],93:[2,190],102:[2,190],103:84,104:[2,190],105:[2,190],106:[2,190],109:85,110:[2,190],111:68,118:[2,190],126:[2,190],129:[2,190],130:[2,190],133:[1,74],134:[2,190],135:[1,78],136:[2,190],137:[2,190],138:[2,190],139:[2,190]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],49:[2,191],54:[2,191],57:[2,191],73:[2,191],78:[2,191],86:[2,191],91:[2,191],93:[2,191],102:[2,191],103:84,104:[2,191],105:[2,191],106:[2,191],109:85,110:[2,191],111:68,118:[2,191],126:[2,191],129:[2,191],130:[2,191],133:[1,74],134:[2,191],135:[1,78],136:[2,191],137:[2,191],138:[2,191],139:[2,191]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],49:[2,192],54:[2,192],57:[2,192],66:[2,72],67:[2,72],68:[2,72],69:[2,72],71:[2,72],73:[2,192],74:[2,72],78:[2,192],84:[2,72],85:[2,72],86:[2,192],91:[2,192],93:[2,192],102:[2,192],104:[2,192],105:[2,192],106:[2,192],110:[2,192],118:[2,192],126:[2,192],129:[2,192],130:[2,192],133:[2,192],134:[2,192],135:[2,192],136:[2,192],137:[2,192],138:[2,192],139:[2,192]},{62:90,66:[1,92],67:[1,93],68:[1,94],69:[1,95],70:96,71:[1,97],74:[1,98],81:89,84:[1,91],85:[2,108]},{62:100,66:[1,92],67:[1,93],68:[1,94],69:[1,95],70:96,71:[1,97],74:[1,98],81:99,84:[1,91],85:[2,108]},{66:[2,75],67:[2,75],68:[2,75],69:[2,75],71:[2,75],74:[2,75],84:[2,75],85:[2,75]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],49:[2,193],54:[2,193],57:[2,193],66:[2,72],67:[2,72],68:[2,72],69:[2,72],71:[2,72],73:[2,193],74:[2,72],78:[2,193],84:[2,72],85:[2,72],86:[2,193],91:[2,193],93:[2,193],102:[2,193],104:[2,193],105:[2,193],106:[2,193],110:[2,193],118:[2,193],126:[2,193],129:[2,193],130:[2,193],133:[2,193],134:[2,193],135:[2,193],136:[2,193],137:[2,193],138:[2,193],139:[2,193]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],49:[2,194],54:[2,194],57:[2,194],73:[2,194],78:[2,194],86:[2,194],91:[2,194],93:[2,194],102:[2,194],104:[2,194],105:[2,194],106:[2,194],110:[2,194],118:[2,194],126:[2,194],129:[2,194],130:[2,194],133:[2,194],134:[2,194],135:[2,194],136:[2,194],137:[2,194],138:[2,194],139:[2,194]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],49:[2,195],54:[2,195],57:[2,195],73:[2,195],78:[2,195],86:[2,195],91:[2,195],93:[2,195],102:[2,195],104:[2,195],105:[2,195],106:[2,195],110:[2,195],118:[2,195],126:[2,195],129:[2,195],130:[2,195],133:[2,195],134:[2,195],135:[2,195],136:[2,195],137:[2,195],138:[2,195],139:[2,195]},{6:[1,213],7:211,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,212],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:214,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{24:215,25:[1,115],125:[1,216]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],49:[2,134],54:[2,134],57:[2,134],73:[2,134],78:[2,134],86:[2,134],91:[2,134],93:[2,134],97:217,98:[1,218],99:[1,219],102:[2,134],104:[2,134],105:[2,134],106:[2,134],110:[2,134],118:[2,134],126:[2,134],129:[2,134],130:[2,134],133:[2,134],134:[2,134],135:[2,134],136:[2,134],137:[2,134],138:[2,134],139:[2,134]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],49:[2,148],54:[2,148],57:[2,148],73:[2,148],78:[2,148],86:[2,148],91:[2,148],93:[2,148],102:[2,148],104:[2,148],105:[2,148],106:[2,148],110:[2,148],118:[2,148],126:[2,148],129:[2,148],130:[2,148],133:[2,148],134:[2,148],135:[2,148],136:[2,148],137:[2,148],138:[2,148],139:[2,148]},{1:[2,156],6:[2,156],25:[2,156],26:[2,156],49:[2,156],54:[2,156],57:[2,156],73:[2,156],78:[2,156],86:[2,156],91:[2,156],93:[2,156],102:[2,156],104:[2,156],105:[2,156],106:[2,156],110:[2,156],118:[2,156],126:[2,156],129:[2,156],130:[2,156],133:[2,156],134:[2,156],135:[2,156],136:[2,156],137:[2,156],138:[2,156],139:[2,156]},{25:[1,220],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{120:221,122:222,123:[1,223]},{1:[2,97],6:[2,97],25:[2,97],26:[2,97],49:[2,97],54:[2,97],57:[2,97],73:[2,97],78:[2,97],86:[2,97],91:[2,97],93:[2,97],102:[2,97],104:[2,97],105:[2,97],106:[2,97],110:[2,97],118:[2,97],126:[2,97],129:[2,97],130:[2,97],133:[2,97],134:[2,97],135:[2,97],136:[2,97],137:[2,97],138:[2,97],139:[2,97]},{7:224,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,100],6:[2,100],24:225,25:[1,115],26:[2,100],49:[2,100],54:[2,100],57:[2,100],66:[2,72],67:[2,72],68:[2,72],69:[2,72],71:[2,72],73:[2,100],74:[2,72],78:[2,100],80:[1,226],84:[2,72],85:[2,72],86:[2,100],91:[2,100],93:[2,100],102:[2,100],104:[2,100],105:[2,100],106:[2,100],110:[2,100],118:[2,100],126:[2,100],129:[2,100],130:[2,100],133:[2,100],134:[2,100],135:[2,100],136:[2,100],137:[2,100],138:[2,100],139:[2,100]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],49:[2,141],54:[2,141],57:[2,141],73:[2,141],78:[2,141],86:[2,141],91:[2,141],93:[2,141],102:[2,141],103:84,104:[2,141],105:[2,141],106:[2,141],109:85,110:[2,141],111:68,118:[2,141],126:[2,141],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,45],6:[2,45],26:[2,45],102:[2,45],103:84,104:[2,45],106:[2,45],109:85,110:[2,45],111:68,126:[2,45],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{6:[1,73],102:[1,227]},{4:228,5:3,7:4,8:5,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{6:[2,129],25:[2,129],54:[2,129],57:[1,230],91:[2,129],92:229,93:[1,194],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,115],6:[2,115],25:[2,115],26:[2,115],40:[2,115],49:[2,115],54:[2,115],57:[2,115],66:[2,115],67:[2,115],68:[2,115],69:[2,115],71:[2,115],73:[2,115],74:[2,115],78:[2,115],84:[2,115],85:[2,115],86:[2,115],91:[2,115],93:[2,115],102:[2,115],104:[2,115],105:[2,115],106:[2,115],110:[2,115],116:[2,115],117:[2,115],118:[2,115],126:[2,115],129:[2,115],130:[2,115],133:[2,115],134:[2,115],135:[2,115],136:[2,115],137:[2,115],138:[2,115],139:[2,115]},{6:[2,52],25:[2,52],53:231,54:[1,232],91:[2,52]},{6:[2,124],25:[2,124],26:[2,124],54:[2,124],86:[2,124],91:[2,124]},{7:203,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,147],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],57:[1,149],58:46,59:47,60:148,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],87:233,88:[1,57],89:[1,58],90:[1,56],94:146,96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{6:[2,130],25:[2,130],26:[2,130],54:[2,130],86:[2,130],91:[2,130]},{6:[2,131],25:[2,131],26:[2,131],54:[2,131],86:[2,131],91:[2,131]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],40:[2,114],43:[2,114],49:[2,114],54:[2,114],57:[2,114],66:[2,114],67:[2,114],68:[2,114],69:[2,114],71:[2,114],73:[2,114],74:[2,114],78:[2,114],80:[2,114],84:[2,114],85:[2,114],86:[2,114],91:[2,114],93:[2,114],102:[2,114],104:[2,114],105:[2,114],106:[2,114],110:[2,114],116:[2,114],117:[2,114],118:[2,114],126:[2,114],129:[2,114],130:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114],135:[2,114],136:[2,114],137:[2,114],138:[2,114],139:[2,114],140:[2,114]},{24:234,25:[1,115],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],49:[2,144],54:[2,144],57:[2,144],73:[2,144],78:[2,144],86:[2,144],91:[2,144],93:[2,144],102:[2,144],103:84,104:[1,64],105:[1,235],106:[1,65],109:85,110:[1,67],111:68,118:[2,144],126:[2,144],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],49:[2,146],54:[2,146],57:[2,146],73:[2,146],78:[2,146],86:[2,146],91:[2,146],93:[2,146],102:[2,146],103:84,104:[1,64],105:[1,236],106:[1,65],109:85,110:[1,67],111:68,118:[2,146],126:[2,146],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,152],6:[2,152],25:[2,152],26:[2,152],49:[2,152],54:[2,152],57:[2,152],73:[2,152],78:[2,152],86:[2,152],91:[2,152],93:[2,152],102:[2,152],104:[2,152],105:[2,152],106:[2,152],110:[2,152],118:[2,152],126:[2,152],129:[2,152],130:[2,152],133:[2,152],134:[2,152],135:[2,152],136:[2,152],137:[2,152],138:[2,152],139:[2,152]},{1:[2,153],6:[2,153],25:[2,153],26:[2,153],49:[2,153],54:[2,153],57:[2,153],73:[2,153],78:[2,153],86:[2,153],91:[2,153],93:[2,153],102:[2,153],103:84,104:[1,64],105:[2,153],106:[1,65],109:85,110:[1,67],111:68,118:[2,153],126:[2,153],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,157],6:[2,157],25:[2,157],26:[2,157],49:[2,157],54:[2,157],57:[2,157],73:[2,157],78:[2,157],86:[2,157],91:[2,157],93:[2,157],102:[2,157],104:[2,157],105:[2,157],106:[2,157],110:[2,157],118:[2,157],126:[2,157],129:[2,157],130:[2,157],133:[2,157],134:[2,157],135:[2,157],136:[2,157],137:[2,157],138:[2,157],139:[2,157]},{116:[2,159],117:[2,159]},{27:160,28:[1,72],44:161,58:162,59:163,76:[1,69],89:[1,112],90:[1,113],113:237,115:159},{54:[1,238],116:[2,165],117:[2,165]},{54:[2,161],116:[2,161],117:[2,161]},{54:[2,162],116:[2,162],117:[2,162]},{54:[2,163],116:[2,163],117:[2,163]},{54:[2,164],116:[2,164],117:[2,164]},{1:[2,158],6:[2,158],25:[2,158],26:[2,158],49:[2,158],54:[2,158],57:[2,158],73:[2,158],78:[2,158],86:[2,158],91:[2,158],93:[2,158],102:[2,158],104:[2,158],105:[2,158],106:[2,158],110:[2,158],118:[2,158],126:[2,158],129:[2,158],130:[2,158],133:[2,158],134:[2,158],135:[2,158],136:[2,158],137:[2,158],138:[2,158],139:[2,158]},{7:239,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:240,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{6:[2,52],25:[2,52],53:241,54:[1,242],78:[2,52]},{6:[2,92],25:[2,92],26:[2,92],54:[2,92],78:[2,92]},{6:[2,38],25:[2,38],26:[2,38],43:[1,243],54:[2,38],78:[2,38]},{6:[2,41],25:[2,41],26:[2,41],54:[2,41],78:[2,41]},{6:[2,42],25:[2,42],26:[2,42],43:[2,42],54:[2,42],78:[2,42]},{6:[2,43],25:[2,43],26:[2,43],43:[2,43],54:[2,43],78:[2,43]},{6:[2,44],25:[2,44],26:[2,44],43:[2,44],54:[2,44],78:[2,44]},{1:[2,4],6:[2,4],26:[2,4],102:[2,4]},{1:[2,197],6:[2,197],25:[2,197],26:[2,197],49:[2,197],54:[2,197],57:[2,197],73:[2,197],78:[2,197],86:[2,197],91:[2,197],93:[2,197],102:[2,197],103:84,104:[2,197],105:[2,197],106:[2,197],109:85,110:[2,197],111:68,118:[2,197],126:[2,197],129:[2,197],130:[2,197],133:[1,74],134:[1,77],135:[1,78],136:[2,197],137:[2,197],138:[2,197],139:[2,197]},{1:[2,198],6:[2,198],25:[2,198],26:[2,198],49:[2,198],54:[2,198],57:[2,198],73:[2,198],78:[2,198],86:[2,198],91:[2,198],93:[2,198],102:[2,198],103:84,104:[2,198],105:[2,198],106:[2,198],109:85,110:[2,198],111:68,118:[2,198],126:[2,198],129:[2,198],130:[2,198],133:[1,74],134:[1,77],135:[1,78],136:[2,198],137:[2,198],138:[2,198],139:[2,198]},{1:[2,199],6:[2,199],25:[2,199],26:[2,199],49:[2,199],54:[2,199],57:[2,199],73:[2,199],78:[2,199],86:[2,199],91:[2,199],93:[2,199],102:[2,199],103:84,104:[2,199],105:[2,199],106:[2,199],109:85,110:[2,199],111:68,118:[2,199],126:[2,199],129:[2,199],130:[2,199],133:[1,74],134:[2,199],135:[1,78],136:[2,199],137:[2,199],138:[2,199],139:[2,199]},{1:[2,200],6:[2,200],25:[2,200],26:[2,200],49:[2,200],54:[2,200],57:[2,200],73:[2,200],78:[2,200],86:[2,200],91:[2,200],93:[2,200],102:[2,200],103:84,104:[2,200],105:[2,200],106:[2,200],109:85,110:[2,200],111:68,118:[2,200],126:[2,200],129:[2,200],130:[2,200],133:[1,74],134:[2,200],135:[1,78],136:[2,200],137:[2,200],138:[2,200],139:[2,200]},{1:[2,201],6:[2,201],25:[2,201],26:[2,201],49:[2,201],54:[2,201],57:[2,201],73:[2,201],78:[2,201],86:[2,201],91:[2,201],93:[2,201],102:[2,201],103:84,104:[2,201],105:[2,201],106:[2,201],109:85,110:[2,201],111:68,118:[2,201],126:[2,201],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[2,201],137:[2,201],138:[2,201],139:[2,201]},{1:[2,202],6:[2,202],25:[2,202],26:[2,202],49:[2,202],54:[2,202],57:[2,202],73:[2,202],78:[2,202],86:[2,202],91:[2,202],93:[2,202],102:[2,202],103:84,104:[2,202],105:[2,202],106:[2,202],109:85,110:[2,202],111:68,118:[2,202],126:[2,202],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[2,202],138:[2,202],139:[1,82]},{1:[2,203],6:[2,203],25:[2,203],26:[2,203],49:[2,203],54:[2,203],57:[2,203],73:[2,203],78:[2,203],86:[2,203],91:[2,203],93:[2,203],102:[2,203],103:84,104:[2,203],105:[2,203],106:[2,203],109:85,110:[2,203],111:68,118:[2,203],126:[2,203],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[2,203],139:[1,82]},{1:[2,204],6:[2,204],25:[2,204],26:[2,204],49:[2,204],54:[2,204],57:[2,204],73:[2,204],78:[2,204],86:[2,204],91:[2,204],93:[2,204],102:[2,204],103:84,104:[2,204],105:[2,204],106:[2,204],109:85,110:[2,204],111:68,118:[2,204],126:[2,204],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[2,204],138:[2,204],139:[2,204]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],49:[2,187],54:[2,187],57:[2,187],73:[2,187],78:[2,187],86:[2,187],91:[2,187],93:[2,187],102:[2,187],103:84,104:[1,64],105:[2,187],106:[1,65],109:85,110:[1,67],111:68,118:[2,187],126:[2,187],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],49:[2,186],54:[2,186],57:[2,186],73:[2,186],78:[2,186],86:[2,186],91:[2,186],93:[2,186],102:[2,186],103:84,104:[1,64],105:[2,186],106:[1,65],109:85,110:[1,67],111:68,118:[2,186],126:[2,186],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,104],6:[2,104],25:[2,104],26:[2,104],49:[2,104],54:[2,104],57:[2,104],66:[2,104],67:[2,104],68:[2,104],69:[2,104],71:[2,104],73:[2,104],74:[2,104],78:[2,104],84:[2,104],85:[2,104],86:[2,104],91:[2,104],93:[2,104],102:[2,104],104:[2,104],105:[2,104],106:[2,104],110:[2,104],118:[2,104],126:[2,104],129:[2,104],130:[2,104],133:[2,104],134:[2,104],135:[2,104],136:[2,104],137:[2,104],138:[2,104],139:[2,104]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],40:[2,80],49:[2,80],54:[2,80],57:[2,80],66:[2,80],67:[2,80],68:[2,80],69:[2,80],71:[2,80],73:[2,80],74:[2,80],78:[2,80],80:[2,80],84:[2,80],85:[2,80],86:[2,80],91:[2,80],93:[2,80],102:[2,80],104:[2,80],105:[2,80],106:[2,80],110:[2,80],118:[2,80],126:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80],136:[2,80],137:[2,80],138:[2,80],139:[2,80],140:[2,80]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],40:[2,81],49:[2,81],54:[2,81],57:[2,81],66:[2,81],67:[2,81],68:[2,81],69:[2,81],71:[2,81],73:[2,81],74:[2,81],78:[2,81],80:[2,81],84:[2,81],85:[2,81],86:[2,81],91:[2,81],93:[2,81],102:[2,81],104:[2,81],105:[2,81],106:[2,81],110:[2,81],118:[2,81],126:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81],136:[2,81],137:[2,81],138:[2,81],139:[2,81],140:[2,81]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],40:[2,82],49:[2,82],54:[2,82],57:[2,82],66:[2,82],67:[2,82],68:[2,82],69:[2,82],71:[2,82],73:[2,82],74:[2,82],78:[2,82],80:[2,82],84:[2,82],85:[2,82],86:[2,82],91:[2,82],93:[2,82],102:[2,82],104:[2,82],105:[2,82],106:[2,82],110:[2,82],118:[2,82],126:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82],136:[2,82],137:[2,82],138:[2,82],139:[2,82],140:[2,82]},{1:[2,83],6:[2,83],25:[2,83],26:[2,83],40:[2,83],49:[2,83],54:[2,83],57:[2,83],66:[2,83],67:[2,83],68:[2,83],69:[2,83],71:[2,83],73:[2,83],74:[2,83],78:[2,83],80:[2,83],84:[2,83],85:[2,83],86:[2,83],91:[2,83],93:[2,83],102:[2,83],104:[2,83],105:[2,83],106:[2,83],110:[2,83],118:[2,83],126:[2,83],129:[2,83],130:[2,83],131:[2,83],132:[2,83],133:[2,83],134:[2,83],135:[2,83],136:[2,83],137:[2,83],138:[2,83],139:[2,83],140:[2,83]},{73:[1,244]},{57:[1,195],73:[2,88],92:245,93:[1,194],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{73:[2,89]},{7:246,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,73:[2,123],76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{11:[2,117],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],73:[2,117],76:[2,117],79:[2,117],83:[2,117],88:[2,117],89:[2,117],90:[2,117],96:[2,117],100:[2,117],101:[2,117],104:[2,117],106:[2,117],108:[2,117],110:[2,117],119:[2,117],125:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117],131:[2,117],132:[2,117]},{11:[2,118],28:[2,118],30:[2,118],31:[2,118],33:[2,118],34:[2,118],35:[2,118],36:[2,118],37:[2,118],38:[2,118],45:[2,118],46:[2,118],47:[2,118],51:[2,118],52:[2,118],73:[2,118],76:[2,118],79:[2,118],83:[2,118],88:[2,118],89:[2,118],90:[2,118],96:[2,118],100:[2,118],101:[2,118],104:[2,118],106:[2,118],108:[2,118],110:[2,118],119:[2,118],125:[2,118],127:[2,118],128:[2,118],129:[2,118],130:[2,118],131:[2,118],132:[2,118]},{1:[2,87],6:[2,87],25:[2,87],26:[2,87],40:[2,87],49:[2,87],54:[2,87],57:[2,87],66:[2,87],67:[2,87],68:[2,87],69:[2,87],71:[2,87],73:[2,87],74:[2,87],78:[2,87],80:[2,87],84:[2,87],85:[2,87],86:[2,87],91:[2,87],93:[2,87],102:[2,87],104:[2,87],105:[2,87],106:[2,87],110:[2,87],118:[2,87],126:[2,87],129:[2,87],130:[2,87],131:[2,87],132:[2,87],133:[2,87],134:[2,87],135:[2,87],136:[2,87],137:[2,87],138:[2,87],139:[2,87],140:[2,87]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],49:[2,105],54:[2,105],57:[2,105],66:[2,105],67:[2,105],68:[2,105],69:[2,105],71:[2,105],73:[2,105],74:[2,105],78:[2,105],84:[2,105],85:[2,105],86:[2,105],91:[2,105],93:[2,105],102:[2,105],104:[2,105],105:[2,105],106:[2,105],110:[2,105],118:[2,105],126:[2,105],129:[2,105],130:[2,105],133:[2,105],134:[2,105],135:[2,105],136:[2,105],137:[2,105],138:[2,105],139:[2,105]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],49:[2,35],54:[2,35],57:[2,35],73:[2,35],78:[2,35],86:[2,35],91:[2,35],93:[2,35],102:[2,35],103:84,104:[2,35],105:[2,35],106:[2,35],109:85,110:[2,35],111:68,118:[2,35],126:[2,35],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{7:247,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:248,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],49:[2,110],54:[2,110],57:[2,110],66:[2,110],67:[2,110],68:[2,110],69:[2,110],71:[2,110],73:[2,110],74:[2,110],78:[2,110],84:[2,110],85:[2,110],86:[2,110],91:[2,110],93:[2,110],102:[2,110],104:[2,110],105:[2,110],106:[2,110],110:[2,110],118:[2,110],126:[2,110],129:[2,110],130:[2,110],133:[2,110],134:[2,110],135:[2,110],136:[2,110],137:[2,110],138:[2,110],139:[2,110]},{6:[2,52],25:[2,52],53:249,54:[1,232],86:[2,52]},{6:[2,129],25:[2,129],26:[2,129],54:[2,129],57:[1,250],86:[2,129],91:[2,129],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{50:251,51:[1,59],52:[1,60]},{6:[2,53],25:[2,53],26:[2,53],27:108,28:[1,72],44:109,55:252,56:106,57:[1,107],58:110,59:111,76:[1,69],89:[1,112],90:[1,113]},{6:[1,253],25:[1,254]},{6:[2,60],25:[2,60],26:[2,60],49:[2,60],54:[2,60]},{7:255,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],49:[2,23],54:[2,23],57:[2,23],73:[2,23],78:[2,23],86:[2,23],91:[2,23],93:[2,23],98:[2,23],99:[2,23],102:[2,23],104:[2,23],105:[2,23],106:[2,23],110:[2,23],118:[2,23],121:[2,23],123:[2,23],126:[2,23],129:[2,23],130:[2,23],133:[2,23],134:[2,23],135:[2,23],136:[2,23],137:[2,23],138:[2,23],139:[2,23]},{6:[1,73],26:[1,256]},{1:[2,205],6:[2,205],25:[2,205],26:[2,205],49:[2,205],54:[2,205],57:[2,205],73:[2,205],78:[2,205],86:[2,205],91:[2,205],93:[2,205],102:[2,205],103:84,104:[2,205],105:[2,205],106:[2,205],109:85,110:[2,205],111:68,118:[2,205],126:[2,205],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{7:257,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:258,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,208],6:[2,208],25:[2,208],26:[2,208],49:[2,208],54:[2,208],57:[2,208],73:[2,208],78:[2,208],86:[2,208],91:[2,208],93:[2,208],102:[2,208],103:84,104:[2,208],105:[2,208],106:[2,208],109:85,110:[2,208],111:68,118:[2,208],126:[2,208],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],49:[2,185],54:[2,185],57:[2,185],73:[2,185],78:[2,185],86:[2,185],91:[2,185],93:[2,185],102:[2,185],104:[2,185],105:[2,185],106:[2,185],110:[2,185],118:[2,185],126:[2,185],129:[2,185],130:[2,185],133:[2,185],134:[2,185],135:[2,185],136:[2,185],137:[2,185],138:[2,185],139:[2,185]},{7:259,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],49:[2,135],54:[2,135],57:[2,135],73:[2,135],78:[2,135],86:[2,135],91:[2,135],93:[2,135],98:[1,260],102:[2,135],104:[2,135],105:[2,135],106:[2,135],110:[2,135],118:[2,135],126:[2,135],129:[2,135],130:[2,135],133:[2,135],134:[2,135],135:[2,135],136:[2,135],137:[2,135],138:[2,135],139:[2,135]},{24:261,25:[1,115]},{24:264,25:[1,115],27:262,28:[1,72],59:263,76:[1,69]},{120:265,122:222,123:[1,223]},{26:[1,266],121:[1,267],122:268,123:[1,223]},{26:[2,178],121:[2,178],123:[2,178]},{7:270,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],95:269,96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,98],6:[2,98],24:271,25:[1,115],26:[2,98],49:[2,98],54:[2,98],57:[2,98],73:[2,98],78:[2,98],86:[2,98],91:[2,98],93:[2,98],102:[2,98],103:84,104:[1,64],105:[2,98],106:[1,65],109:85,110:[1,67],111:68,118:[2,98],126:[2,98],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,101],6:[2,101],25:[2,101],26:[2,101],49:[2,101],54:[2,101],57:[2,101],73:[2,101],78:[2,101],86:[2,101],91:[2,101],93:[2,101],102:[2,101],104:[2,101],105:[2,101],106:[2,101],110:[2,101],118:[2,101],126:[2,101],129:[2,101],130:[2,101],133:[2,101],134:[2,101],135:[2,101],136:[2,101],137:[2,101],138:[2,101],139:[2,101]},{7:272,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],49:[2,142],54:[2,142],57:[2,142],66:[2,142],67:[2,142],68:[2,142],69:[2,142],71:[2,142],73:[2,142],74:[2,142],78:[2,142],84:[2,142],85:[2,142],86:[2,142],91:[2,142],93:[2,142],102:[2,142],104:[2,142],105:[2,142],106:[2,142],110:[2,142],118:[2,142],126:[2,142],129:[2,142],130:[2,142],133:[2,142],134:[2,142],135:[2,142],136:[2,142],137:[2,142],138:[2,142],139:[2,142]},{6:[1,73],26:[1,273]},{7:274,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{6:[2,67],11:[2,118],25:[2,67],28:[2,118],30:[2,118],31:[2,118],33:[2,118],34:[2,118],35:[2,118],36:[2,118],37:[2,118],38:[2,118],45:[2,118],46:[2,118],47:[2,118],51:[2,118],52:[2,118],54:[2,67],76:[2,118],79:[2,118],83:[2,118],88:[2,118],89:[2,118],90:[2,118],91:[2,67],96:[2,118],100:[2,118],101:[2,118],104:[2,118],106:[2,118],108:[2,118],110:[2,118],119:[2,118],125:[2,118],127:[2,118],128:[2,118],129:[2,118],130:[2,118],131:[2,118],132:[2,118]},{6:[1,276],25:[1,277],91:[1,275]},{6:[2,53],7:203,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[2,53],26:[2,53],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],57:[1,149],58:46,59:47,60:148,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],86:[2,53],88:[1,57],89:[1,58],90:[1,56],91:[2,53],94:278,96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{6:[2,52],25:[2,52],26:[2,52],53:279,54:[1,232]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],49:[2,182],54:[2,182],57:[2,182],73:[2,182],78:[2,182],86:[2,182],91:[2,182],93:[2,182],102:[2,182],104:[2,182],105:[2,182],106:[2,182],110:[2,182],118:[2,182],121:[2,182],126:[2,182],129:[2,182],130:[2,182],133:[2,182],134:[2,182],135:[2,182],136:[2,182],137:[2,182],138:[2,182],139:[2,182]},{7:280,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:281,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{116:[2,160],117:[2,160]},{27:160,28:[1,72],44:161,58:162,59:163,76:[1,69],89:[1,112],90:[1,113],115:282},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],49:[2,167],54:[2,167],57:[2,167],73:[2,167],78:[2,167],86:[2,167],91:[2,167],93:[2,167],102:[2,167],103:84,104:[2,167],105:[1,283],106:[2,167],109:85,110:[2,167],111:68,118:[1,284],126:[2,167],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,168],6:[2,168],25:[2,168],26:[2,168],49:[2,168],54:[2,168],57:[2,168],73:[2,168],78:[2,168],86:[2,168],91:[2,168],93:[2,168],102:[2,168],103:84,104:[2,168],105:[1,285],106:[2,168],109:85,110:[2,168],111:68,118:[2,168],126:[2,168],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{6:[1,287],25:[1,288],78:[1,286]},{6:[2,53],10:170,25:[2,53],26:[2,53],27:171,28:[1,72],29:172,30:[1,70],31:[1,71],41:289,42:169,44:173,46:[1,45],78:[2,53],89:[1,112]},{7:290,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,291],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,86],6:[2,86],25:[2,86],26:[2,86],40:[2,86],49:[2,86],54:[2,86],57:[2,86],66:[2,86],67:[2,86],68:[2,86],69:[2,86],71:[2,86],73:[2,86],74:[2,86],78:[2,86],80:[2,86],84:[2,86],85:[2,86],86:[2,86],91:[2,86],93:[2,86],102:[2,86],104:[2,86],105:[2,86],106:[2,86],110:[2,86],118:[2,86],126:[2,86],129:[2,86],130:[2,86],131:[2,86],132:[2,86],133:[2,86],134:[2,86],135:[2,86],136:[2,86],137:[2,86],138:[2,86],139:[2,86],140:[2,86]},{7:292,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,73:[2,121],76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{73:[2,122],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],49:[2,36],54:[2,36],57:[2,36],73:[2,36],78:[2,36],86:[2,36],91:[2,36],93:[2,36],102:[2,36],103:84,104:[2,36],105:[2,36],106:[2,36],109:85,110:[2,36],111:68,118:[2,36],126:[2,36],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{26:[1,293],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{6:[1,276],25:[1,277],86:[1,294]},{6:[2,67],25:[2,67],26:[2,67],54:[2,67],86:[2,67],91:[2,67]},{24:295,25:[1,115]},{6:[2,56],25:[2,56],26:[2,56],49:[2,56],54:[2,56]},{27:108,28:[1,72],44:109,55:296,56:106,57:[1,107],58:110,59:111,76:[1,69],89:[1,112],90:[1,113]},{6:[2,54],25:[2,54],26:[2,54],27:108,28:[1,72],44:109,48:297,54:[2,54],55:105,56:106,57:[1,107],58:110,59:111,76:[1,69],89:[1,112],90:[1,113]},{6:[2,61],25:[2,61],26:[2,61],49:[2,61],54:[2,61],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],49:[2,24],54:[2,24],57:[2,24],73:[2,24],78:[2,24],86:[2,24],91:[2,24],93:[2,24],98:[2,24],99:[2,24],102:[2,24],104:[2,24],105:[2,24],106:[2,24],110:[2,24],118:[2,24],121:[2,24],123:[2,24],126:[2,24],129:[2,24],130:[2,24],133:[2,24],134:[2,24],135:[2,24],136:[2,24],137:[2,24],138:[2,24],139:[2,24]},{26:[1,298],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,207],6:[2,207],25:[2,207],26:[2,207],49:[2,207],54:[2,207],57:[2,207],73:[2,207],78:[2,207],86:[2,207],91:[2,207],93:[2,207],102:[2,207],103:84,104:[2,207],105:[2,207],106:[2,207],109:85,110:[2,207],111:68,118:[2,207],126:[2,207],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{24:299,25:[1,115],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{24:300,25:[1,115]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],49:[2,136],54:[2,136],57:[2,136],73:[2,136],78:[2,136],86:[2,136],91:[2,136],93:[2,136],102:[2,136],104:[2,136],105:[2,136],106:[2,136],110:[2,136],118:[2,136],126:[2,136],129:[2,136],130:[2,136],133:[2,136],134:[2,136],135:[2,136],136:[2,136],137:[2,136],138:[2,136],139:[2,136]},{24:301,25:[1,115]},{24:302,25:[1,115]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],49:[2,140],54:[2,140],57:[2,140],73:[2,140],78:[2,140],86:[2,140],91:[2,140],93:[2,140],98:[2,140],102:[2,140],104:[2,140],105:[2,140],106:[2,140],110:[2,140],118:[2,140],126:[2,140],129:[2,140],130:[2,140],133:[2,140],134:[2,140],135:[2,140],136:[2,140],137:[2,140],138:[2,140],139:[2,140]},{26:[1,303],121:[1,304],122:268,123:[1,223]},{1:[2,176],6:[2,176],25:[2,176],26:[2,176],49:[2,176],54:[2,176],57:[2,176],73:[2,176],78:[2,176],86:[2,176],91:[2,176],93:[2,176],102:[2,176],104:[2,176],105:[2,176],106:[2,176],110:[2,176],118:[2,176],126:[2,176],129:[2,176],130:[2,176],133:[2,176],134:[2,176],135:[2,176],136:[2,176],137:[2,176],138:[2,176],139:[2,176]},{24:305,25:[1,115]},{26:[2,179],121:[2,179],123:[2,179]},{24:306,25:[1,115],54:[1,307]},{25:[2,132],54:[2,132],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,99],6:[2,99],25:[2,99],26:[2,99],49:[2,99],54:[2,99],57:[2,99],73:[2,99],78:[2,99],86:[2,99],91:[2,99],93:[2,99],102:[2,99],104:[2,99],105:[2,99],106:[2,99],110:[2,99],118:[2,99],126:[2,99],129:[2,99],130:[2,99],133:[2,99],134:[2,99],135:[2,99],136:[2,99],137:[2,99],138:[2,99],139:[2,99]},{1:[2,102],6:[2,102],24:308,25:[1,115],26:[2,102],49:[2,102],54:[2,102],57:[2,102],73:[2,102],78:[2,102],86:[2,102],91:[2,102],93:[2,102],102:[2,102],103:84,104:[1,64],105:[2,102],106:[1,65],109:85,110:[1,67],111:68,118:[2,102],126:[2,102],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{102:[1,309]},{91:[1,310],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,116],6:[2,116],25:[2,116],26:[2,116],40:[2,116],49:[2,116],54:[2,116],57:[2,116],66:[2,116],67:[2,116],68:[2,116],69:[2,116],71:[2,116],73:[2,116],74:[2,116],78:[2,116],84:[2,116],85:[2,116],86:[2,116],91:[2,116],93:[2,116],102:[2,116],104:[2,116],105:[2,116],106:[2,116],110:[2,116],116:[2,116],117:[2,116],118:[2,116],126:[2,116],129:[2,116],130:[2,116],133:[2,116],134:[2,116],135:[2,116],136:[2,116],137:[2,116],138:[2,116],139:[2,116]},{7:203,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],57:[1,149],58:46,59:47,60:148,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],94:311,96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:203,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,25:[1,147],27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],57:[1,149],58:46,59:47,60:148,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],87:312,88:[1,57],89:[1,58],90:[1,56],94:146,96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{6:[2,125],25:[2,125],26:[2,125],54:[2,125],86:[2,125],91:[2,125]},{6:[1,276],25:[1,277],26:[1,313]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],49:[2,145],54:[2,145],57:[2,145],73:[2,145],78:[2,145],86:[2,145],91:[2,145],93:[2,145],102:[2,145],103:84,104:[1,64],105:[2,145],106:[1,65],109:85,110:[1,67],111:68,118:[2,145],126:[2,145],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],49:[2,147],54:[2,147],57:[2,147],73:[2,147],78:[2,147],86:[2,147],91:[2,147],93:[2,147],102:[2,147],103:84,104:[1,64],105:[2,147],106:[1,65],109:85,110:[1,67],111:68,118:[2,147],126:[2,147],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{116:[2,166],117:[2,166]},{7:314,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:315,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:316,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,90],6:[2,90],25:[2,90],26:[2,90],40:[2,90],49:[2,90],54:[2,90],57:[2,90],66:[2,90],67:[2,90],68:[2,90],69:[2,90],71:[2,90],73:[2,90],74:[2,90],78:[2,90],84:[2,90],85:[2,90],86:[2,90],91:[2,90],93:[2,90],102:[2,90],104:[2,90],105:[2,90],106:[2,90],110:[2,90],116:[2,90],117:[2,90],118:[2,90],126:[2,90],129:[2,90],130:[2,90],133:[2,90],134:[2,90],135:[2,90],136:[2,90],137:[2,90],138:[2,90],139:[2,90]},{10:170,27:171,28:[1,72],29:172,30:[1,70],31:[1,71],41:317,42:169,44:173,46:[1,45],89:[1,112]},{6:[2,91],10:170,25:[2,91],26:[2,91],27:171,28:[1,72],29:172,30:[1,70],31:[1,71],41:168,42:169,44:173,46:[1,45],54:[2,91],77:318,89:[1,112]},{6:[2,93],25:[2,93],26:[2,93],54:[2,93],78:[2,93]},{6:[2,39],25:[2,39],26:[2,39],54:[2,39],78:[2,39],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{7:319,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{73:[2,120],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,37],6:[2,37],25:[2,37],26:[2,37],49:[2,37],54:[2,37],57:[2,37],73:[2,37],78:[2,37],86:[2,37],91:[2,37],93:[2,37],102:[2,37],104:[2,37],105:[2,37],106:[2,37],110:[2,37],118:[2,37],126:[2,37],129:[2,37],130:[2,37],133:[2,37],134:[2,37],135:[2,37],136:[2,37],137:[2,37],138:[2,37],139:[2,37]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],49:[2,111],54:[2,111],57:[2,111],66:[2,111],67:[2,111],68:[2,111],69:[2,111],71:[2,111],73:[2,111],74:[2,111],78:[2,111],84:[2,111],85:[2,111],86:[2,111],91:[2,111],93:[2,111],102:[2,111],104:[2,111],105:[2,111],106:[2,111],110:[2,111],118:[2,111],126:[2,111],129:[2,111],130:[2,111],133:[2,111],134:[2,111],135:[2,111],136:[2,111],137:[2,111],138:[2,111],139:[2,111]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],49:[2,48],54:[2,48],57:[2,48],73:[2,48],78:[2,48],86:[2,48],91:[2,48],93:[2,48],102:[2,48],104:[2,48],105:[2,48],106:[2,48],110:[2,48],118:[2,48],126:[2,48],129:[2,48],130:[2,48],133:[2,48],134:[2,48],135:[2,48],136:[2,48],137:[2,48],138:[2,48],139:[2,48]},{6:[2,57],25:[2,57],26:[2,57],49:[2,57],54:[2,57]},{6:[2,52],25:[2,52],26:[2,52],53:320,54:[1,205]},{1:[2,206],6:[2,206],25:[2,206],26:[2,206],49:[2,206],54:[2,206],57:[2,206],73:[2,206],78:[2,206],86:[2,206],91:[2,206],93:[2,206],102:[2,206],104:[2,206],105:[2,206],106:[2,206],110:[2,206],118:[2,206],126:[2,206],129:[2,206],130:[2,206],133:[2,206],134:[2,206],135:[2,206],136:[2,206],137:[2,206],138:[2,206],139:[2,206]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],49:[2,183],54:[2,183],57:[2,183],73:[2,183],78:[2,183],86:[2,183],91:[2,183],93:[2,183],102:[2,183],104:[2,183],105:[2,183],106:[2,183],110:[2,183],118:[2,183],121:[2,183],126:[2,183],129:[2,183],130:[2,183],133:[2,183],134:[2,183],135:[2,183],136:[2,183],137:[2,183],138:[2,183],139:[2,183]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],49:[2,137],54:[2,137],57:[2,137],73:[2,137],78:[2,137],86:[2,137],91:[2,137],93:[2,137],102:[2,137],104:[2,137],105:[2,137],106:[2,137],110:[2,137],118:[2,137],126:[2,137],129:[2,137],130:[2,137],133:[2,137],134:[2,137],135:[2,137],136:[2,137],137:[2,137],138:[2,137],139:[2,137]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],49:[2,138],54:[2,138],57:[2,138],73:[2,138],78:[2,138],86:[2,138],91:[2,138],93:[2,138],98:[2,138],102:[2,138],104:[2,138],105:[2,138],106:[2,138],110:[2,138],118:[2,138],126:[2,138],129:[2,138],130:[2,138],133:[2,138],134:[2,138],135:[2,138],136:[2,138],137:[2,138],138:[2,138],139:[2,138]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],49:[2,139],54:[2,139],57:[2,139],73:[2,139],78:[2,139],86:[2,139],91:[2,139],93:[2,139],98:[2,139],102:[2,139],104:[2,139],105:[2,139],106:[2,139],110:[2,139],118:[2,139],126:[2,139],129:[2,139],130:[2,139],133:[2,139],134:[2,139],135:[2,139],136:[2,139],137:[2,139],138:[2,139],139:[2,139]},{1:[2,174],6:[2,174],25:[2,174],26:[2,174],49:[2,174],54:[2,174],57:[2,174],73:[2,174],78:[2,174],86:[2,174],91:[2,174],93:[2,174],102:[2,174],104:[2,174],105:[2,174],106:[2,174],110:[2,174],118:[2,174],126:[2,174],129:[2,174],130:[2,174],133:[2,174],134:[2,174],135:[2,174],136:[2,174],137:[2,174],138:[2,174],139:[2,174]},{24:321,25:[1,115]},{26:[1,322]},{6:[1,323],26:[2,180],121:[2,180],123:[2,180]},{7:324,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{1:[2,103],6:[2,103],25:[2,103],26:[2,103],49:[2,103],54:[2,103],57:[2,103],73:[2,103],78:[2,103],86:[2,103],91:[2,103],93:[2,103],102:[2,103],104:[2,103],105:[2,103],106:[2,103],110:[2,103],118:[2,103],126:[2,103],129:[2,103],130:[2,103],133:[2,103],134:[2,103],135:[2,103],136:[2,103],137:[2,103],138:[2,103],139:[2,103]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],49:[2,143],54:[2,143],57:[2,143],66:[2,143],67:[2,143],68:[2,143],69:[2,143],71:[2,143],73:[2,143],74:[2,143],78:[2,143],84:[2,143],85:[2,143],86:[2,143],91:[2,143],93:[2,143],102:[2,143],104:[2,143],105:[2,143],106:[2,143],110:[2,143],118:[2,143],126:[2,143],129:[2,143],130:[2,143],133:[2,143],134:[2,143],135:[2,143],136:[2,143],137:[2,143],138:[2,143],139:[2,143]},{1:[2,119],6:[2,119],25:[2,119],26:[2,119],49:[2,119],54:[2,119],57:[2,119],66:[2,119],67:[2,119],68:[2,119],69:[2,119],71:[2,119],73:[2,119],74:[2,119],78:[2,119],84:[2,119],85:[2,119],86:[2,119],91:[2,119],93:[2,119],102:[2,119],104:[2,119],105:[2,119],106:[2,119],110:[2,119],118:[2,119],126:[2,119],129:[2,119],130:[2,119],133:[2,119],134:[2,119],135:[2,119],136:[2,119],137:[2,119],138:[2,119],139:[2,119]},{6:[2,126],25:[2,126],26:[2,126],54:[2,126],86:[2,126],91:[2,126]},{6:[2,52],25:[2,52],26:[2,52],53:325,54:[1,232]},{6:[2,127],25:[2,127],26:[2,127],54:[2,127],86:[2,127],91:[2,127]},{1:[2,169],6:[2,169],25:[2,169],26:[2,169],49:[2,169],54:[2,169],57:[2,169],73:[2,169],78:[2,169],86:[2,169],91:[2,169],93:[2,169],102:[2,169],103:84,104:[2,169],105:[2,169],106:[2,169],109:85,110:[2,169],111:68,118:[1,326],126:[2,169],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,171],6:[2,171],25:[2,171],26:[2,171],49:[2,171],54:[2,171],57:[2,171],73:[2,171],78:[2,171],86:[2,171],91:[2,171],93:[2,171],102:[2,171],103:84,104:[2,171],105:[1,327],106:[2,171],109:85,110:[2,171],111:68,118:[2,171],126:[2,171],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,170],6:[2,170],25:[2,170],26:[2,170],49:[2,170],54:[2,170],57:[2,170],73:[2,170],78:[2,170],86:[2,170],91:[2,170],93:[2,170],102:[2,170],103:84,104:[2,170],105:[2,170],106:[2,170],109:85,110:[2,170],111:68,118:[2,170],126:[2,170],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{6:[2,94],25:[2,94],26:[2,94],54:[2,94],78:[2,94]},{6:[2,52],25:[2,52],26:[2,52],53:328,54:[1,242]},{26:[1,329],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{6:[1,253],25:[1,254],26:[1,330]},{26:[1,331]},{1:[2,177],6:[2,177],25:[2,177],26:[2,177],49:[2,177],54:[2,177],57:[2,177],73:[2,177],78:[2,177],86:[2,177],91:[2,177],93:[2,177],102:[2,177],104:[2,177],105:[2,177],106:[2,177],110:[2,177],118:[2,177],126:[2,177],129:[2,177],130:[2,177],133:[2,177],134:[2,177],135:[2,177],136:[2,177],137:[2,177],138:[2,177],139:[2,177]},{26:[2,181],121:[2,181],123:[2,181]},{25:[2,133],54:[2,133],103:84,104:[1,64],106:[1,65],109:85,110:[1,67],111:68,126:[1,83],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{6:[1,276],25:[1,277],26:[1,332]},{7:333,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{7:334,8:117,9:18,10:19,11:[1,20],12:6,13:7,14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,27:61,28:[1,72],29:48,30:[1,70],31:[1,71],32:22,33:[1,49],34:[1,50],35:[1,51],36:[1,52],37:[1,53],38:[1,54],39:21,44:62,45:[1,44],46:[1,45],47:[1,27],50:28,51:[1,59],52:[1,60],58:46,59:47,61:35,63:23,64:24,65:25,76:[1,69],79:[1,42],83:[1,26],88:[1,57],89:[1,58],90:[1,56],96:[1,37],100:[1,43],101:[1,55],103:38,104:[1,64],106:[1,65],107:39,108:[1,66],109:40,110:[1,67],111:68,119:[1,41],124:36,125:[1,63],127:[1,29],128:[1,30],129:[1,31],130:[1,32],131:[1,33],132:[1,34]},{6:[1,287],25:[1,288],26:[1,335]},{6:[2,40],25:[2,40],26:[2,40],54:[2,40],78:[2,40]},{6:[2,58],25:[2,58],26:[2,58],49:[2,58],54:[2,58]},{1:[2,175],6:[2,175],25:[2,175],26:[2,175],49:[2,175],54:[2,175],57:[2,175],73:[2,175],78:[2,175],86:[2,175],91:[2,175],93:[2,175],102:[2,175],104:[2,175],105:[2,175],106:[2,175],110:[2,175],118:[2,175],126:[2,175],129:[2,175],130:[2,175],133:[2,175],134:[2,175],135:[2,175],136:[2,175],137:[2,175],138:[2,175],139:[2,175]},{6:[2,128],25:[2,128],26:[2,128],54:[2,128],86:[2,128],91:[2,128]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],49:[2,172],54:[2,172],57:[2,172],73:[2,172],78:[2,172],86:[2,172],91:[2,172],93:[2,172],102:[2,172],103:84,104:[2,172],105:[2,172],106:[2,172],109:85,110:[2,172],111:68,118:[2,172],126:[2,172],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],49:[2,173],54:[2,173],57:[2,173],73:[2,173],78:[2,173],86:[2,173],91:[2,173],93:[2,173],102:[2,173],103:84,104:[2,173],105:[2,173],106:[2,173],109:85,110:[2,173],111:68,118:[2,173],126:[2,173],129:[1,76],130:[1,75],133:[1,74],134:[1,77],135:[1,78],136:[1,79],137:[1,80],138:[1,81],139:[1,82]},{6:[2,95],25:[2,95],26:[2,95],54:[2,95],78:[2,95]}],defaultActions:{59:[2,50],60:[2,51],91:[2,109],192:[2,89]},parseError:function(e,t){if(!t.recoverable)throw Error(e);
+this.trace(e)},parse:function(e){function t(){var e;return e=n.lexer.lex()||p,"number"!=typeof e&&(e=n.symbols_[e]||e),e}var n=this,i=[0],r=[null],s=[],o=this.table,a="",c=0,h=0,l=0,u=2,p=1,d=s.slice.call(arguments,1);this.lexer.setInput(e),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,this.yy.parser=this,this.lexer.yylloc===void 0&&(this.lexer.yylloc={});var f=this.lexer.yylloc;s.push(f);var m=this.lexer.options&&this.lexer.options.ranges;this.parseError="function"==typeof this.yy.parseError?this.yy.parseError:Object.getPrototypeOf(this).parseError;for(var b,g,k,y,v,w,T,F,L,C={};;){if(k=i[i.length-1],this.defaultActions[k]?y=this.defaultActions[k]:((null===b||b===void 0)&&(b=t()),y=o[k]&&o[k][b]),y===void 0||!y.length||!y[0]){var N="";L=[];for(w in o[k])this.terminals_[w]&&w>u&&L.push("'"+this.terminals_[w]+"'");N=this.lexer.showPosition?"Parse error on line "+(c+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+L.join(", ")+", got '"+(this.terminals_[b]||b)+"'":"Parse error on line "+(c+1)+": Unexpected "+(b==p?"end of input":"'"+(this.terminals_[b]||b)+"'"),this.parseError(N,{text:this.lexer.match,token:this.terminals_[b]||b,line:this.lexer.yylineno,loc:f,expected:L})}if(y[0]instanceof Array&&y.length>1)throw Error("Parse Error: multiple actions possible at state: "+k+", token: "+b);switch(y[0]){case 1:i.push(b),r.push(this.lexer.yytext),s.push(this.lexer.yylloc),i.push(y[1]),b=null,g?(b=g,g=null):(h=this.lexer.yyleng,a=this.lexer.yytext,c=this.lexer.yylineno,f=this.lexer.yylloc,l>0&&l--);break;case 2:if(T=this.productions_[y[1]][1],C.$=r[r.length-T],C._$={first_line:s[s.length-(T||1)].first_line,last_line:s[s.length-1].last_line,first_column:s[s.length-(T||1)].first_column,last_column:s[s.length-1].last_column},m&&(C._$.range=[s[s.length-(T||1)].range[0],s[s.length-1].range[1]]),v=this.performAction.apply(C,[a,h,c,this.yy,y[1],r,s].concat(d)),v!==void 0)return v;T&&(i=i.slice(0,2*-1*T),r=r.slice(0,-1*T),s=s.slice(0,-1*T)),i.push(this.productions_[y[1]][0]),r.push(C.$),s.push(C._$),F=o[i[i.length-2]][i[i.length-1]],i.push(F);break;case 3:return!0}}return!0}};return e.prototype=t,t.Parser=e,new e}();return require!==void 0&&e!==void 0&&(e.parser=n,e.Parser=n.Parser,e.parse=function(){return n.parse.apply(n,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var n=require("fs").readFileSync(require("path").normalize(t[1]),"utf8");return e.parser.parse(n)},t!==void 0&&require.main===t&&e.main(process.argv.slice(1))),t.exports}(),require["./scope"]=function(){var e={},t={exports:e};return function(){var t,n,i,r;r=require("./helpers"),n=r.extend,i=r.last,e.Scope=t=function(){function e(t,n,i){this.parent=t,this.expressions=n,this.method=i,this.variables=[{name:"arguments",type:"arguments"}],this.positions={},this.parent||(e.root=this)}return e.root=null,e.prototype.add=function(e,t,n){return this.shared&&!n?this.parent.add(e,t,n):Object.prototype.hasOwnProperty.call(this.positions,e)?this.variables[this.positions[e]].type=t:this.positions[e]=this.variables.push({name:e,type:t})-1},e.prototype.namedMethod=function(){var e;return(null!=(e=this.method)?e.name:void 0)||!this.parent?this.method:this.parent.namedMethod()},e.prototype.find=function(e){return this.check(e)?!0:(this.add(e,"var"),!1)},e.prototype.parameter=function(e){return this.shared&&this.parent.check(e,!0)?void 0:this.add(e,"param")},e.prototype.check=function(e){var t;return!!(this.type(e)||(null!=(t=this.parent)?t.check(e):void 0))},e.prototype.temporary=function(e,t){return e.length>1?"_"+e+(t>1?t-1:""):"_"+(t+parseInt(e,36)).toString(36).replace(/\d/g,"a")},e.prototype.type=function(e){var t,n,i,r;for(r=this.variables,n=0,i=r.length;i>n;n++)if(t=r[n],t.name===e)return t.type;return null},e.prototype.freeVariable=function(e,t){var n,i;for(null==t&&(t=!0),n=0;this.check(i=this.temporary(e,n));)n++;return t&&this.add(i,"var",!0),i},e.prototype.assign=function(e,t){return this.add(e,{value:t,assigned:!0},!0),this.hasAssignments=!0},e.prototype.hasDeclarations=function(){return!!this.declaredVariables().length},e.prototype.declaredVariables=function(){var e,t,n,i,r,s;for(e=[],t=[],s=this.variables,i=0,r=s.length;r>i;i++)n=s[i],"var"===n.type&&("_"===n.name.charAt(0)?t:e).push(n.name);return e.sort().concat(t.sort())},e.prototype.assignedVariables=function(){var e,t,n,i,r;for(i=this.variables,r=[],t=0,n=i.length;n>t;t++)e=i[t],e.type.assigned&&r.push(""+e.name+" = "+e.type.value);return r},e}()}.call(this),t.exports}(),require["./nodes"]=function(){var e={},t={exports:e};return function(){var t,n,i,r,s,o,a,c,h,l,u,p,d,f,m,b,g,k,y,v,w,T,F,L,C,N,E,x,D,S,R,A,I,_,$,O,j,M,B,V,P,U,H,q,G,W,X,Y,z,K,J,Z,Q,et,tt,nt,it,rt,st,ot,at,ct,ht,lt,ut,pt,dt,ft,mt,bt,gt,kt,yt,vt,wt,Tt={}.hasOwnProperty,Ft=function(e,t){function n(){this.constructor=e}for(var i in t)Tt.call(t,i)&&(e[i]=t[i]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e},Lt=[].indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(t in this&&this[t]===e)return t;return-1},Ct=[].slice;Error.stackTraceLimit=1/0,H=require("./scope").Scope,vt=require("./lexer"),M=vt.RESERVED,U=vt.STRICT_PROSCRIBED,wt=require("./helpers"),nt=wt.compact,ot=wt.flatten,st=wt.extend,pt=wt.merge,it=wt.del,bt=wt.starts,rt=wt.ends,lt=wt.last,mt=wt.some,tt=wt.addLocationDataFn,ut=wt.locationDataToString,gt=wt.throwSyntaxError,e.extend=st,e.addLocationDataFn=tt,et=function(){return!0},A=function(){return!1},Y=function(){return this},R=function(){return this.negated=!this.negated,this},e.CodeFragment=h=function(){function e(e,t){var n;this.code=""+t,this.locationData=null!=e?e.locationData:void 0,this.type=(null!=e?null!=(n=e.constructor)?n.name:void 0:void 0)||"unknown"}return e.prototype.toString=function(){return""+this.code+(this.locationData?": "+ut(this.locationData):"")},e}(),at=function(e){var t;return function(){var n,i,r;for(r=[],n=0,i=e.length;i>n;n++)t=e[n],r.push(t.code);return r}().join("")},e.Base=r=function(){function e(){}return e.prototype.compile=function(e,t){return at(this.compileToFragments(e,t))},e.prototype.compileToFragments=function(e,t){var n;return e=st({},e),t&&(e.level=t),n=this.unfoldSoak(e)||this,n.tab=e.indent,e.level!==x&&n.isStatement(e)?n.compileClosure(e):n.compileNode(e)},e.prototype.compileClosure=function(e){var n,i,r,a,h;return(a=this.jumps())&&a.error("cannot use a pure statement in an expression"),e.sharedScope=!0,r=new c([],s.wrap([this])),n=[],((i=this.contains(ct))||this.contains(ht))&&(n=[new D("this")],i?(h="apply",n.push(new D("arguments"))):h="call",r=new Z(r,[new t(new D(h))])),new o(r,n).compileNode(e)},e.prototype.cache=function(e,t,n){var r,s;return this.isComplex()?(r=new D(n||e.scope.freeVariable("ref")),s=new i(r,this),t?[s.compileToFragments(e,t),[this.makeCode(r.value)]]:[s,r]):(r=t?this.compileToFragments(e,t):this,[r,r])},e.prototype.cacheToCodeFragments=function(e){return[at(e[0]),at(e[1])]},e.prototype.makeReturn=function(e){var t;return t=this.unwrapAll(),e?new o(new D(""+e+".push"),[t]):new V(t)},e.prototype.contains=function(e){var t;return t=void 0,this.traverseChildren(!1,function(n){return e(n)?(t=n,!1):void 0}),t},e.prototype.lastNonComment=function(e){var t;for(t=e.length;t--;)if(!(e[t]instanceof l))return e[t];return null},e.prototype.toString=function(e,t){var n;return null==e&&(e=""),null==t&&(t=this.constructor.name),n="\n"+e+t,this.soak&&(n+="?"),this.eachChild(function(t){return n+=t.toString(e+X)}),n},e.prototype.eachChild=function(e){var t,n,i,r,s,o,a,c;if(!this.children)return this;for(a=this.children,i=0,s=a.length;s>i;i++)if(t=a[i],this[t])for(c=ot([this[t]]),r=0,o=c.length;o>r;r++)if(n=c[r],e(n)===!1)return this;return this},e.prototype.traverseChildren=function(e,t){return this.eachChild(function(n){var i;return i=t(n),i!==!1?n.traverseChildren(e,t):void 0})},e.prototype.invert=function(){return new $("!",this)},e.prototype.unwrapAll=function(){var e;for(e=this;e!==(e=e.unwrap()););return e},e.prototype.children=[],e.prototype.isStatement=A,e.prototype.jumps=A,e.prototype.isComplex=et,e.prototype.isChainable=A,e.prototype.isAssignable=A,e.prototype.unwrap=Y,e.prototype.unfoldSoak=A,e.prototype.assigns=A,e.prototype.updateLocationDataIfMissing=function(e){return this.locationData?this:(this.locationData=e,this.eachChild(function(t){return t.updateLocationDataIfMissing(e)}))},e.prototype.error=function(e){return gt(e,this.locationData)},e.prototype.makeCode=function(e){return new h(this,e)},e.prototype.wrapInBraces=function(e){return[].concat(this.makeCode("("),e,this.makeCode(")"))},e.prototype.joinFragmentArrays=function(e,t){var n,i,r,s,o;for(n=[],r=s=0,o=e.length;o>s;r=++s)i=e[r],r&&n.push(this.makeCode(t)),n=n.concat(i);return n},e}(),e.Block=s=function(e){function t(e){this.expressions=nt(ot(e||[]))}return Ft(t,e),t.prototype.children=["expressions"],t.prototype.push=function(e){return this.expressions.push(e),this},t.prototype.pop=function(){return this.expressions.pop()},t.prototype.unshift=function(e){return this.expressions.unshift(e),this},t.prototype.unwrap=function(){return 1===this.expressions.length?this.expressions[0]:this},t.prototype.isEmpty=function(){return!this.expressions.length},t.prototype.isStatement=function(e){var t,n,i,r;for(r=this.expressions,n=0,i=r.length;i>n;n++)if(t=r[n],t.isStatement(e))return!0;return!1},t.prototype.jumps=function(e){var t,n,i,r,s;for(s=this.expressions,i=0,r=s.length;r>i;i++)if(t=s[i],n=t.jumps(e))return n},t.prototype.makeReturn=function(e){var t,n;for(n=this.expressions.length;n--;)if(t=this.expressions[n],!(t instanceof l)){this.expressions[n]=t.makeReturn(e),t instanceof V&&!t.expression&&this.expressions.splice(n,1);break}return this},t.prototype.compileToFragments=function(e,n){return null==e&&(e={}),e.scope?t.__super__.compileToFragments.call(this,e,n):this.compileRoot(e)},t.prototype.compileNode=function(e){var n,i,r,s,o,a,c,h,l;for(this.tab=e.indent,a=e.level===x,i=[],l=this.expressions,s=c=0,h=l.length;h>c;s=++c)o=l[s],o=o.unwrapAll(),o=o.unfoldSoak(e)||o,o instanceof t?i.push(o.compileNode(e)):a?(o.front=!0,r=o.compileToFragments(e),o.isStatement(e)||(r.unshift(this.makeCode(""+this.tab)),r.push(this.makeCode(";"))),i.push(r)):i.push(o.compileToFragments(e,C));return a?this.spaced?[].concat(this.joinFragmentArrays(i,"\n\n"),this.makeCode("\n")):this.joinFragmentArrays(i,"\n"):(n=i.length?this.joinFragmentArrays(i,", "):[this.makeCode("void 0")],i.length>1&&e.level>=C?this.wrapInBraces(n):n)},t.prototype.compileRoot=function(e){var t,n,i,r,s,o,a,c,h,u;for(e.indent=e.bare?"":X,e.level=x,this.spaced=!0,e.scope=new H(null,this,null),u=e.locals||[],c=0,h=u.length;h>c;c++)r=u[c],e.scope.parameter(r);return s=[],e.bare||(o=function(){var e,n,r,s;for(r=this.expressions,s=[],i=e=0,n=r.length;n>e&&(t=r[i],t.unwrap()instanceof l);i=++e)s.push(t);return s}.call(this),a=this.expressions.slice(o.length),this.expressions=o,o.length&&(s=this.compileNode(pt(e,{indent:""})),s.push(this.makeCode("\n"))),this.expressions=a),n=this.compileWithDeclarations(e),e.bare?n:[].concat(s,this.makeCode("(function() {\n"),n,this.makeCode("\n}).call(this);\n"))},t.prototype.compileWithDeclarations=function(e){var t,n,i,r,s,o,a,c,h,u,p,d,f,m;for(r=[],o=[],d=this.expressions,s=u=0,p=d.length;p>u&&(i=d[s],i=i.unwrap(),i instanceof l||i instanceof D);s=++u);return e=pt(e,{level:x}),s&&(a=this.expressions.splice(s,9e9),f=[this.spaced,!1],h=f[0],this.spaced=f[1],m=[this.compileNode(e),h],r=m[0],this.spaced=m[1],this.expressions=a),o=this.compileNode(e),c=e.scope,c.expressions===this&&(n=e.scope.hasDeclarations(),t=c.hasAssignments,n||t?(s&&r.push(this.makeCode("\n")),r.push(this.makeCode(""+this.tab+"var ")),n&&r.push(this.makeCode(c.declaredVariables().join(", "))),t&&(n&&r.push(this.makeCode(",\n"+(this.tab+X))),r.push(this.makeCode(c.assignedVariables().join(",\n"+(this.tab+X))))),r.push(this.makeCode(";\n"+(this.spaced?"\n":"")))):r.length&&o.length&&r.push(this.makeCode("\n"))),r.concat(o)},t.wrap=function(e){return 1===e.length&&e[0]instanceof t?e[0]:new t(e)},t}(r),e.Literal=D=function(e){function t(e){this.value=e}return Ft(t,e),t.prototype.makeReturn=function(){return this.isStatement()?this:t.__super__.makeReturn.apply(this,arguments)},t.prototype.isAssignable=function(){return b.test(this.value)},t.prototype.isStatement=function(){var e;return"break"===(e=this.value)||"continue"===e||"debugger"===e},t.prototype.isComplex=A,t.prototype.assigns=function(e){return e===this.value},t.prototype.jumps=function(e){return"break"!==this.value||(null!=e?e.loop:void 0)||(null!=e?e.block:void 0)?"continue"!==this.value||(null!=e?e.loop:void 0)?void 0:this:this},t.prototype.compileNode=function(e){var t,n,i;return n="this"===this.value?(null!=(i=e.scope.method)?i.bound:void 0)?e.scope.method.context:this.value:this.value.reserved?'"'+this.value+'"':this.value,t=this.isStatement()?""+this.tab+n+";":n,[this.makeCode(t)]},t.prototype.toString=function(){return' "'+this.value+'"'},t}(r),e.Undefined=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return Ft(t,e),t.prototype.isAssignable=A,t.prototype.isComplex=A,t.prototype.compileNode=function(e){return[this.makeCode(e.level>=F?"(void 0)":"void 0")]},t}(r),e.Null=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return Ft(t,e),t.prototype.isAssignable=A,t.prototype.isComplex=A,t.prototype.compileNode=function(){return[this.makeCode("null")]},t}(r),e.Bool=function(e){function t(e){this.val=e}return Ft(t,e),t.prototype.isAssignable=A,t.prototype.isComplex=A,t.prototype.compileNode=function(){return[this.makeCode(this.val)]},t}(r),e.Return=V=function(e){function t(e){this.expression=e}return Ft(t,e),t.prototype.children=["expression"],t.prototype.isStatement=et,t.prototype.makeReturn=Y,t.prototype.jumps=Y,t.prototype.compileToFragments=function(e,n){var i,r;return i=null!=(r=this.expression)?r.makeReturn():void 0,!i||i instanceof t?t.__super__.compileToFragments.call(this,e,n):i.compileToFragments(e,n)},t.prototype.compileNode=function(e){var t;return t=[],t.push(this.makeCode(this.tab+("return"+(this.expression?" ":"")))),this.expression&&(t=t.concat(this.expression.compileToFragments(e,E))),t.push(this.makeCode(";")),t},t}(r),e.Value=Z=function(e){function t(e,n,i){return!n&&e instanceof t?e:(this.base=e,this.properties=n||[],i&&(this[i]=!0),this)}return Ft(t,e),t.prototype.children=["base","properties"],t.prototype.add=function(e){return this.properties=this.properties.concat(e),this},t.prototype.hasProperties=function(){return!!this.properties.length},t.prototype.bareLiteral=function(e){return!this.properties.length&&this.base instanceof e},t.prototype.isArray=function(){return this.bareLiteral(n)},t.prototype.isRange=function(){return this.bareLiteral(B)},t.prototype.isComplex=function(){return this.hasProperties()||this.base.isComplex()},t.prototype.isAssignable=function(){return this.hasProperties()||this.base.isAssignable()},t.prototype.isSimpleNumber=function(){return this.bareLiteral(D)&&P.test(this.base.value)},t.prototype.isString=function(){return this.bareLiteral(D)&&y.test(this.base.value)},t.prototype.isRegex=function(){return this.bareLiteral(D)&&k.test(this.base.value)},t.prototype.isAtomic=function(){var e,t,n,i;for(i=this.properties.concat(this.base),t=0,n=i.length;n>t;t++)if(e=i[t],e.soak||e instanceof o)return!1;return!0},t.prototype.isNotCallable=function(){return this.isSimpleNumber()||this.isString()||this.isRegex()||this.isArray()||this.isRange()||this.isSplice()||this.isObject()},t.prototype.isStatement=function(e){return!this.properties.length&&this.base.isStatement(e)},t.prototype.assigns=function(e){return!this.properties.length&&this.base.assigns(e)},t.prototype.jumps=function(e){return!this.properties.length&&this.base.jumps(e)},t.prototype.isObject=function(e){return this.properties.length?!1:this.base instanceof _&&(!e||this.base.generated)},t.prototype.isSplice=function(){return lt(this.properties)instanceof q},t.prototype.looksStatic=function(e){var t;return this.base.value===e&&this.properties.length&&"prototype"!==(null!=(t=this.properties[0].name)?t.value:void 0)},t.prototype.unwrap=function(){return this.properties.length?this:this.base},t.prototype.cacheReference=function(e){var n,r,s,o;return s=lt(this.properties),2>this.properties.length&&!this.base.isComplex()&&!(null!=s?s.isComplex():void 0)?[this,this]:(n=new t(this.base,this.properties.slice(0,-1)),n.isComplex()&&(r=new D(e.scope.freeVariable("base")),n=new t(new j(new i(r,n)))),s?(s.isComplex()&&(o=new D(e.scope.freeVariable("name")),s=new T(new i(o,s.index)),o=new T(o)),[n.add(s),new t(r||n.base,[o||s])]):[n,r])},t.prototype.compileNode=function(e){var t,n,i,r,s;for(this.base.front=this.front,i=this.properties,t=this.base.compileToFragments(e,i.length?F:null),(this.base instanceof j||i.length)&&P.test(at(t))&&t.push(this.makeCode(".")),r=0,s=i.length;s>r;r++)n=i[r],t.push.apply(t,n.compileToFragments(e));return t},t.prototype.unfoldSoak=function(e){return null!=this.unfoldedSoak?this.unfoldedSoak:this.unfoldedSoak=function(n){return function(){var r,s,o,a,c,h,l,p,d,f;if(o=n.base.unfoldSoak(e))return(d=o.body.properties).push.apply(d,n.properties),o;for(f=n.properties,s=l=0,p=f.length;p>l;s=++l)if(a=f[s],a.soak)return a.soak=!1,r=new t(n.base,n.properties.slice(0,s)),h=new t(n.base,n.properties.slice(s)),r.isComplex()&&(c=new D(e.scope.freeVariable("ref")),r=new j(new i(c,r)),h.base=c),new v(new u(r),h,{soak:!0});return!1}}(this)()},t}(r),e.Comment=l=function(e){function t(e){this.comment=e}return Ft(t,e),t.prototype.isStatement=et,t.prototype.makeReturn=Y,t.prototype.compileNode=function(e,t){var n,i;return i=this.comment.replace(/^(\s*)#/gm,"$1 *"),n="/*"+dt(i,this.tab)+(Lt.call(i,"\n")>=0?"\n"+this.tab:"")+" */",(t||e.level)===x&&(n=e.indent+n),[this.makeCode("\n"),this.makeCode(n)]},t}(r),e.Call=o=function(e){function n(e,t,n){this.args=null!=t?t:[],this.soak=n,this.isNew=!1,this.isSuper="super"===e,this.variable=this.isSuper?null:e,e instanceof Z&&e.isNotCallable()&&e.error("literal is not a function")}return Ft(n,e),n.prototype.children=["variable","args"],n.prototype.newInstance=function(){var e,t;return e=(null!=(t=this.variable)?t.base:void 0)||this.variable,e instanceof n&&!e.isNew?e.newInstance():this.isNew=!0,this},n.prototype.superReference=function(e){var n,i;return i=e.scope.namedMethod(),(null!=i?i.klass:void 0)?(n=[new t(new D("__super__"))],i["static"]&&n.push(new t(new D("constructor"))),n.push(new t(new D(i.name))),new Z(new D(i.klass),n).compile(e)):(null!=i?i.ctor:void 0)?""+i.name+".__super__.constructor":this.error("cannot call super outside of an instance method.")},n.prototype.superThis=function(e){var t;return t=e.scope.method,t&&!t.klass&&t.context||"this"},n.prototype.unfoldSoak=function(e){var t,i,r,s,o,a,c,h,l;if(this.soak){if(this.variable){if(i=kt(e,this,"variable"))return i;h=new Z(this.variable).cacheReference(e),r=h[0],o=h[1]}else r=new D(this.superReference(e)),o=new Z(r);return o=new n(o,this.args),o.isNew=this.isNew,r=new D("typeof "+r.compile(e)+' === "function"'),new v(r,new Z(o),{soak:!0})}for(t=this,s=[];;)if(t.variable instanceof n)s.push(t),t=t.variable;else{if(!(t.variable instanceof Z))break;if(s.push(t),!((t=t.variable.base)instanceof n))break}for(l=s.reverse(),a=0,c=l.length;c>a;a++)t=l[a],i&&(t.variable instanceof n?t.variable=i:t.variable.base=i),i=kt(e,t,"variable");return i},n.prototype.compileNode=function(e){var t,n,i,r,s,o,a,c,h,l;if(null!=(h=this.variable)&&(h.front=this.front),r=G.compileSplattedArray(e,this.args,!0),r.length)return this.compileSplat(e,r);for(i=[],l=this.args,n=a=0,c=l.length;c>a;n=++a)t=l[n],n&&i.push(this.makeCode(", ")),i.push.apply(i,t.compileToFragments(e,C));return s=[],this.isSuper?(o=this.superReference(e)+(".call("+this.superThis(e)),i.length&&(o+=", "),s.push(this.makeCode(o))):(this.isNew&&s.push(this.makeCode("new ")),s.push.apply(s,this.variable.compileToFragments(e,F)),s.push(this.makeCode("("))),s.push.apply(s,i),s.push(this.makeCode(")")),s},n.prototype.compileSplat=function(e,t){var n,i,r,s,o,a;return this.isSuper?[].concat(this.makeCode(""+this.superReference(e)+".apply("+this.superThis(e)+", "),t,this.makeCode(")")):this.isNew?(s=this.tab+X,[].concat(this.makeCode("(function(func, args, ctor) {\n"+s+"ctor.prototype = func.prototype;\n"+s+"var child = new ctor, result = func.apply(child, args);\n"+s+"return Object(result) === result ? result : child;\n"+this.tab+"})("),this.variable.compileToFragments(e,C),this.makeCode(", "),t,this.makeCode(", function(){})"))):(n=[],i=new Z(this.variable),(o=i.properties.pop())&&i.isComplex()?(a=e.scope.freeVariable("ref"),n=n.concat(this.makeCode("("+a+" = "),i.compileToFragments(e,C),this.makeCode(")"),o.compileToFragments(e))):(r=i.compileToFragments(e,F),P.test(at(r))&&(r=this.wrapInBraces(r)),o?(a=at(r),r.push.apply(r,o.compileToFragments(e))):a="null",n=n.concat(r)),n=n.concat(this.makeCode(".apply("+a+", "),t,this.makeCode(")")))},n}(r),e.Extends=d=function(e){function t(e,t){this.child=e,this.parent=t}return Ft(t,e),t.prototype.children=["child","parent"],t.prototype.compileToFragments=function(e){return new o(new Z(new D(yt("extends"))),[this.child,this.parent]).compileToFragments(e)},t}(r),e.Access=t=function(e){function t(e,t){this.name=e,this.name.asKey=!0,this.soak="soak"===t}return Ft(t,e),t.prototype.children=["name"],t.prototype.compileToFragments=function(e){var t;return t=this.name.compileToFragments(e),b.test(at(t))?t.unshift(this.makeCode(".")):(t.unshift(this.makeCode("[")),t.push(this.makeCode("]"))),t},t.prototype.isComplex=A,t}(r),e.Index=T=function(e){function t(e){this.index=e}return Ft(t,e),t.prototype.children=["index"],t.prototype.compileToFragments=function(e){return[].concat(this.makeCode("["),this.index.compileToFragments(e,E),this.makeCode("]"))},t.prototype.isComplex=function(){return this.index.isComplex()},t}(r),e.Range=B=function(e){function t(e,t,n){this.from=e,this.to=t,this.exclusive="exclusive"===n,this.equals=this.exclusive?"":"="}return Ft(t,e),t.prototype.children=["from","to"],t.prototype.compileVariables=function(e){var t,n,i,r,s;return e=pt(e,{top:!0}),n=this.cacheToCodeFragments(this.from.cache(e,C)),this.fromC=n[0],this.fromVar=n[1],i=this.cacheToCodeFragments(this.to.cache(e,C)),this.toC=i[0],this.toVar=i[1],(t=it(e,"step"))&&(r=this.cacheToCodeFragments(t.cache(e,C)),this.step=r[0],this.stepVar=r[1]),s=[this.fromVar.match(I),this.toVar.match(I)],this.fromNum=s[0],this.toNum=s[1],this.stepVar?this.stepNum=this.stepVar.match(I):void 0},t.prototype.compileNode=function(e){var t,n,i,r,s,o,a,c,h,l,u,p,d,f;return this.fromVar||this.compileVariables(e),e.index?(a=this.fromNum&&this.toNum,s=it(e,"index"),o=it(e,"name"),h=o&&o!==s,p=""+s+" = "+this.fromC,this.toC!==this.toVar&&(p+=", "+this.toC),this.step!==this.stepVar&&(p+=", "+this.step),d=[""+s+" <"+this.equals,""+s+" >"+this.equals],c=d[0],r=d[1],n=this.stepNum?ft(this.stepNum[0])>0?""+c+" "+this.toVar:""+r+" "+this.toVar:a?(f=[ft(this.fromNum[0]),ft(this.toNum[0])],i=f[0],u=f[1],f,u>=i?""+c+" "+u:""+r+" "+u):(t=this.stepVar?""+this.stepVar+" > 0":""+this.fromVar+" <= "+this.toVar,""+t+" ? "+c+" "+this.toVar+" : "+r+" "+this.toVar),l=this.stepVar?""+s+" += "+this.stepVar:a?h?u>=i?"++"+s:"--"+s:u>=i?""+s+"++":""+s+"--":h?""+t+" ? ++"+s+" : --"+s:""+t+" ? "+s+"++ : "+s+"--",h&&(p=""+o+" = "+p),h&&(l=""+o+" = "+l),[this.makeCode(""+p+"; "+n+"; "+l)]):this.compileArray(e)},t.prototype.compileArray=function(e){var t,n,i,r,s,o,a,c,h,l,u,p,d;return this.fromNum&&this.toNum&&20>=Math.abs(this.fromNum-this.toNum)?(h=function(){d=[];for(var e=p=+this.fromNum,t=+this.toNum;t>=p?t>=e:e>=t;t>=p?e++:e--)d.push(e);return d}.apply(this),this.exclusive&&h.pop(),[this.makeCode("["+h.join(", ")+"]")]):(o=this.tab+X,s=e.scope.freeVariable("i"),l=e.scope.freeVariable("results"),c="\n"+o+l+" = [];",this.fromNum&&this.toNum?(e.index=s,n=at(this.compileNode(e))):(u=""+s+" = "+this.fromC+(this.toC!==this.toVar?", "+this.toC:""),i=""+this.fromVar+" <= "+this.toVar,n="var "+u+"; "+i+" ? "+s+" <"+this.equals+" "+this.toVar+" : "+s+" >"+this.equals+" "+this.toVar+"; "+i+" ? "+s+"++ : "+s+"--"),a="{ "+l+".push("+s+"); }\n"+o+"return "+l+";\n"+e.indent,r=function(e){return null!=e?e.contains(ct):void 0},(r(this.from)||r(this.to))&&(t=", arguments"),[this.makeCode("(function() {"+c+"\n"+o+"for ("+n+")"+a+"}).apply(this"+(null!=t?t:"")+")")])},t}(r),e.Slice=q=function(e){function t(e){this.range=e,t.__super__.constructor.call(this)}return Ft(t,e),t.prototype.children=["range"],t.prototype.compileNode=function(e){var t,n,i,r,s,o,a;return a=this.range,s=a.to,i=a.from,r=i&&i.compileToFragments(e,E)||[this.makeCode("0")],s&&(t=s.compileToFragments(e,E),n=at(t),(this.range.exclusive||-1!==+n)&&(o=", "+(this.range.exclusive?n:P.test(n)?""+(+n+1):(t=s.compileToFragments(e,F),"+"+at(t)+" + 1 || 9e9")))),[this.makeCode(".slice("+at(r)+(o||"")+")")]},t}(r),e.Obj=_=function(e){function t(e,t){this.generated=null!=t?t:!1,this.objects=this.properties=e||[]}return Ft(t,e),t.prototype.children=["properties"],t.prototype.compileNode=function(e){var t,n,r,s,o,a,c,h,u,p,d,f,m;if(u=this.properties,!u.length)return[this.makeCode(this.front?"({})":"{}")];if(this.generated)for(p=0,f=u.length;f>p;p++)c=u[p],c instanceof Z&&c.error("cannot have an implicit value in an implicit object");for(r=e.indent+=X,a=this.lastNonComment(this.properties),t=[],n=d=0,m=u.length;m>d;n=++d)h=u[n],o=n===u.length-1?"":h===a||h instanceof l?"\n":",\n",s=h instanceof l?"":r,h instanceof i&&h.variable instanceof Z&&h.variable.hasProperties()&&h.variable.error("Invalid object key"),h instanceof Z&&h["this"]&&(h=new i(h.properties[0].name,h,"object")),h instanceof l||(h instanceof i||(h=new i(h,h,"object")),(h.variable.base||h.variable).asKey=!0),s&&t.push(this.makeCode(s)),t.push.apply(t,h.compileToFragments(e,x)),o&&t.push(this.makeCode(o));return t.unshift(this.makeCode("{"+(u.length&&"\n"))),t.push(this.makeCode(""+(u.length&&"\n"+this.tab)+"}")),this.front?this.wrapInBraces(t):t},t.prototype.assigns=function(e){var t,n,i,r;for(r=this.properties,n=0,i=r.length;i>n;n++)if(t=r[n],t.assigns(e))return!0;return!1},t}(r),e.Arr=n=function(e){function t(e){this.objects=e||[]}return Ft(t,e),t.prototype.children=["objects"],t.prototype.compileNode=function(e){var t,n,i,r,s,o,a;if(!this.objects.length)return[this.makeCode("[]")];if(e.indent+=X,t=G.compileSplattedArray(e,this.objects),t.length)return t;for(t=[],n=function(){var t,n,i,r;for(i=this.objects,r=[],t=0,n=i.length;n>t;t++)s=i[t],r.push(s.compileToFragments(e,C));return r}.call(this),r=o=0,a=n.length;a>o;r=++o)i=n[r],r&&t.push(this.makeCode(", ")),t.push.apply(t,i);return at(t).indexOf("\n")>=0?(t.unshift(this.makeCode("[\n"+e.indent)),t.push(this.makeCode("\n"+this.tab+"]"))):(t.unshift(this.makeCode("[")),t.push(this.makeCode("]"))),t},t.prototype.assigns=function(e){var t,n,i,r;for(r=this.objects,n=0,i=r.length;i>n;n++)if(t=r[n],t.assigns(e))return!0;return!1},t}(r),e.Class=a=function(e){function n(e,t,n){this.variable=e,this.parent=t,this.body=null!=n?n:new s,this.boundFuncs=[],this.body.classBody=!0}return Ft(n,e),n.prototype.children=["variable","parent","body"],n.prototype.determineName=function(){var e,n;return this.variable?(e=(n=lt(this.variable.properties))?n instanceof t&&n.name.value:this.variable.base.value,Lt.call(U,e)>=0&&this.variable.error("class variable name may not be "+e),e&&(e=b.test(e)&&e)):null},n.prototype.setContext=function(e){return this.body.traverseChildren(!1,function(t){return t.classBody?!1:t instanceof D&&"this"===t.value?t.value=e:t instanceof c&&(t.klass=e,t.bound)?t.context=e:void 0})},n.prototype.addBoundFunctions=function(e){var n,i,r,s,o;for(o=this.boundFuncs,r=0,s=o.length;s>r;r++)n=o[r],i=new Z(new D("this"),[new t(n)]).compile(e),this.ctor.body.unshift(new D(""+i+" = "+yt("bind")+"("+i+", this)"))},n.prototype.addProperties=function(e,n,r){var s,o,a,h,l;return l=e.base.properties.slice(0),a=function(){var e;for(e=[];s=l.shift();)s instanceof i&&(o=s.variable.base,delete s.context,h=s.value,"constructor"===o.value?(this.ctor&&s.error("cannot define more than one constructor in a class"),h.bound&&s.error("cannot define a constructor as a bound function"),h instanceof c?s=this.ctor=h:(this.externalCtor=r.classScope.freeVariable("class"),s=new i(new D(this.externalCtor),h))):s.variable["this"]?h["static"]=!0:(s.variable=new Z(new D(n),[new t(new D("prototype")),new t(o)]),h instanceof c&&h.bound&&(this.boundFuncs.push(o),h.bound=!1))),e.push(s);return e}.call(this),nt(a)},n.prototype.walkBody=function(e,t){return this.traverseChildren(!1,function(r){return function(o){var a,c,h,l,u,p,d;if(a=!0,o instanceof n)return!1;if(o instanceof s){for(d=c=o.expressions,h=u=0,p=d.length;p>u;h=++u)l=d[h],l instanceof i&&l.variable.looksStatic(e)?l.value["static"]=!0:l instanceof Z&&l.isObject(!0)&&(a=!1,c[h]=r.addProperties(l,e,t));o.expressions=c=ot(c)}return a&&!(o instanceof n)}}(this))},n.prototype.hoistDirectivePrologue=function(){var e,t,n;for(t=0,e=this.body.expressions;(n=e[t])&&n instanceof l||n instanceof Z&&n.isString();)++t;return this.directives=e.splice(0,t)},n.prototype.ensureConstructor=function(e){return this.ctor||(this.ctor=new c,this.externalCtor?this.ctor.body.push(new D(""+this.externalCtor+".apply(this, arguments)")):this.parent&&this.ctor.body.push(new D(""+e+".__super__.constructor.apply(this, arguments)")),this.ctor.body.makeReturn(),this.body.expressions.unshift(this.ctor)),this.ctor.ctor=this.ctor.name=e,this.ctor.klass=null,this.ctor.noReturn=!0},n.prototype.compileNode=function(e){var t,n,r,a,h,l,u,p,f;return(a=this.body.jumps())&&a.error("Class bodies cannot contain pure statements"),(n=this.body.contains(ct))&&n.error("Class bodies shouldn't reference arguments"),u=this.determineName()||"_Class",u.reserved&&(u="_"+u),l=new D(u),r=new c([],s.wrap([this.body])),t=[],e.classScope=r.makeScope(e.scope),this.hoistDirectivePrologue(),this.setContext(u),this.walkBody(u,e),this.ensureConstructor(u),this.addBoundFunctions(e),this.body.spaced=!0,this.body.expressions.push(l),this.parent&&(p=new D(e.classScope.freeVariable("super",!1)),this.body.expressions.unshift(new d(l,p)),r.params.push(new O(p)),t.push(this.parent)),(f=this.body.expressions).unshift.apply(f,this.directives),h=new j(new o(r,t)),this.variable&&(h=new i(this.variable,h)),h.compileToFragments(e)},n}(r),e.Assign=i=function(e){function n(e,t,n,i){var r,s,o;this.variable=e,this.value=t,this.context=n,this.param=i&&i.param,this.subpattern=i&&i.subpattern,o=s=this.variable.unwrapAll().value,r=Lt.call(U,o)>=0,r&&"object"!==this.context&&this.variable.error('variable name may not be "'+s+'"')}return Ft(n,e),n.prototype.children=["variable","value"],n.prototype.isStatement=function(e){return(null!=e?e.level:void 0)===x&&null!=this.context&&Lt.call(this.context,"?")>=0},n.prototype.assigns=function(e){return this["object"===this.context?"value":"variable"].assigns(e)},n.prototype.unfoldSoak=function(e){return kt(e,this,"variable")},n.prototype.compileNode=function(e){var t,n,i,r,s,o,a,h,l,u,p;if(i=this.variable instanceof Z){if(this.variable.isArray()||this.variable.isObject())return this.compilePatternMatch(e);if(this.variable.isSplice())return this.compileSplice(e);if("||="===(h=this.context)||"&&="===h||"?="===h)return this.compileConditional(e);if("**="===(l=this.context)||"//="===l||"%%="===l)return this.compileSpecialMath(e)}return n=this.variable.compileToFragments(e,C),s=at(n),this.context||(a=this.variable.unwrapAll(),a.isAssignable()||this.variable.error('"'+this.variable.compile(e)+'" cannot be assigned'),("function"==typeof a.hasProperties?a.hasProperties():void 0)||(this.param?e.scope.add(s,"var"):e.scope.find(s))),this.value instanceof c&&(r=S.exec(s))&&(r[2]&&(this.value.klass=r[1]),this.value.name=null!=(u=null!=(p=r[3])?p:r[4])?u:r[5]),o=this.value.compileToFragments(e,C),"object"===this.context?n.concat(this.makeCode(": "),o):(t=n.concat(this.makeCode(" "+(this.context||"=")+" "),o),C>=e.level?t:this.wrapInBraces(t))
+},n.prototype.compilePatternMatch=function(e){var i,r,s,o,a,c,h,l,u,d,f,m,g,k,y,v,w,F,L,E,S,R,A,I,_,$,O,B;if(v=e.level===x,F=this.value,m=this.variable.base.objects,!(g=m.length))return s=F.compileToFragments(e),e.level>=N?this.wrapInBraces(s):s;if(l=this.variable.isObject(),v&&1===g&&!((f=m[0])instanceof G))return f instanceof n?(A=f,I=A.variable,h=I.base,f=A.value):h=l?f["this"]?f.properties[0].name:f:new D(0),i=b.test(h.unwrap().value||0),F=new Z(F),F.properties.push(new(i?t:T)(h)),_=f.unwrap().value,Lt.call(M,_)>=0&&f.error("assignment to a reserved word: "+f.compile(e)),new n(f,F,null,{param:this.param}).compileToFragments(e,x);for(L=F.compileToFragments(e,C),E=at(L),r=[],o=!1,(!b.test(E)||this.variable.assigns(E))&&(r.push([this.makeCode(""+(k=e.scope.freeVariable("ref"))+" = ")].concat(Ct.call(L))),L=[this.makeCode(k)],E=k),c=S=0,R=m.length;R>S;c=++S){if(f=m[c],h=c,l&&(f instanceof n?($=f,O=$.variable,h=O.base,f=$.value):f.base instanceof j?(B=new Z(f.unwrapAll()).cacheReference(e),f=B[0],h=B[1]):h=f["this"]?f.properties[0].name:f),!o&&f instanceof G)d=f.name.unwrap().value,f=f.unwrap(),w=""+g+" <= "+E+".length ? "+yt("slice")+".call("+E+", "+c,(y=g-c-1)?(u=e.scope.freeVariable("i"),w+=", "+u+" = "+E+".length - "+y+") : ("+u+" = "+c+", [])"):w+=") : []",w=new D(w),o=""+u+"++";else{if(!o&&f instanceof p){(y=g-c-1)&&(1===y?o=""+E+".length - 1":(u=e.scope.freeVariable("i"),w=new D(""+u+" = "+E+".length - "+y),o=""+u+"++",r.push(w.compileToFragments(e,C))));continue}d=f.unwrap().value,(f instanceof G||f instanceof p)&&f.error("multiple splats/expansions are disallowed in an assignment"),"number"==typeof h?(h=new D(o||h),i=!1):i=l&&b.test(h.unwrap().value||0),w=new Z(new D(E),[new(i?t:T)(h)])}null!=d&&Lt.call(M,d)>=0&&f.error("assignment to a reserved word: "+f.compile(e)),r.push(new n(f,w,null,{param:this.param,subpattern:!0}).compileToFragments(e,C))}return v||this.subpattern||r.push(L),a=this.joinFragmentArrays(r,", "),C>e.level?a:this.wrapInBraces(a)},n.prototype.compileConditional=function(e){var t,i,r,s;return s=this.variable.cacheReference(e),i=s[0],r=s[1],!i.properties.length&&i.base instanceof D&&"this"!==i.base.value&&!e.scope.check(i.base.value)&&this.variable.error('the variable "'+i.base.value+"\" can't be assigned with "+this.context+" because it has not been declared before"),Lt.call(this.context,"?")>=0?(e.isExistentialEquals=!0,new v(new u(i),r,{type:"if"}).addElse(new n(r,this.value,"=")).compileToFragments(e)):(t=new $(this.context.slice(0,-1),i,new n(r,this.value,"=")).compileToFragments(e),C>=e.level?t:this.wrapInBraces(t))},n.prototype.compileSpecialMath=function(e){var t,i,r;return r=this.variable.cacheReference(e),t=r[0],i=r[1],new n(t,new $(this.context.slice(0,-1),i,this.value)).compileToFragments(e)},n.prototype.compileSplice=function(e){var t,n,i,r,s,o,a,c,h,l,u,p;return l=this.variable.properties.pop().range,i=l.from,a=l.to,n=l.exclusive,o=this.variable.compile(e),i?(u=this.cacheToCodeFragments(i.cache(e,N)),r=u[0],s=u[1]):r=s="0",a?i instanceof Z&&i.isSimpleNumber()&&a instanceof Z&&a.isSimpleNumber()?(a=a.compile(e)-s,n||(a+=1)):(a=a.compile(e,F)+" - "+s,n||(a+=" + 1")):a="9e9",p=this.value.cache(e,C),c=p[0],h=p[1],t=[].concat(this.makeCode("[].splice.apply("+o+", ["+r+", "+a+"].concat("),c,this.makeCode(")), "),h),e.level>x?this.wrapInBraces(t):t},n}(r),e.Code=c=function(e){function t(e,t,n){this.params=e||[],this.body=t||new s,this.bound="boundfunc"===n}return Ft(t,e),t.prototype.children=["params","body"],t.prototype.isStatement=function(){return!!this.ctor},t.prototype.jumps=A,t.prototype.makeScope=function(e){return new H(e,this.body,this)},t.prototype.compileNode=function(e){var r,a,c,h,l,u,d,f,m,b,g,k,y,w,T,L,C,N,E,x,S,R,A,I,_,j,M,B,V,P,U,H,q;if(this.bound&&(null!=(B=e.scope.method)?B.bound:void 0)&&(this.context=e.scope.method.context),this.bound&&!this.context)return this.context="_this",T=new t([new O(new D(this.context))],new s([this])),a=new o(T,[new D("this")]),a.updateLocationDataIfMissing(this.locationData),a.compileNode(e);for(e.scope=it(e,"classScope")||this.makeScope(e.scope),e.scope.shared=it(e,"sharedScope"),e.indent+=X,delete e.bare,delete e.isExistentialEquals,m=[],h=[],V=this.params,L=0,x=V.length;x>L;L++)f=V[L],f instanceof p||e.scope.parameter(f.asReference(e));for(P=this.params,C=0,S=P.length;S>C;C++)if(f=P[C],f.splat||f instanceof p){for(U=this.params,N=0,R=U.length;R>N;N++)d=U[N].name,f instanceof p||(d["this"]&&(d=d.properties[0].name),d.value&&e.scope.add(d.value,"var",!0));g=new i(new Z(new n(function(){var t,n,i,r;for(i=this.params,r=[],t=0,n=i.length;n>t;t++)d=i[t],r.push(d.asReference(e));return r}.call(this))),new Z(new D("arguments")));break}for(H=this.params,E=0,A=H.length;A>E;E++)f=H[E],f.isComplex()?(y=b=f.asReference(e),f.value&&(y=new $("?",b,f.value)),h.push(new i(new Z(f.name),y,"=",{param:!0}))):(b=f,f.value&&(u=new D(b.name.value+" == null"),y=new i(new Z(f.name),f.value,"="),h.push(new v(u,y)))),g||m.push(b);for(w=this.body.isEmpty(),g&&h.unshift(g),h.length&&(q=this.body.expressions).unshift.apply(q,h),l=j=0,I=m.length;I>j;l=++j)d=m[l],m[l]=d.compileToFragments(e),e.scope.parameter(at(m[l]));for(k=[],this.eachParamName(function(e,t){return Lt.call(k,e)>=0&&t.error("multiple parameters named '"+e+"'"),k.push(e)}),w||this.noReturn||this.body.makeReturn(),c="function",this.ctor&&(c+=" "+this.name),c+="(",r=[this.makeCode(c)],l=M=0,_=m.length;_>M;l=++M)d=m[l],l&&r.push(this.makeCode(", ")),r.push.apply(r,d);return r.push(this.makeCode(") {")),this.body.isEmpty()||(r=r.concat(this.makeCode("\n"),this.body.compileWithDeclarations(e),this.makeCode("\n"+this.tab))),r.push(this.makeCode("}")),this.ctor?[this.makeCode(this.tab)].concat(Ct.call(r)):this.front||e.level>=F?this.wrapInBraces(r):r},t.prototype.eachParamName=function(e){var t,n,i,r,s;for(r=this.params,s=[],n=0,i=r.length;i>n;n++)t=r[n],s.push(t.eachName(e));return s},t.prototype.traverseChildren=function(e,n){return e?t.__super__.traverseChildren.call(this,e,n):void 0},t}(r),e.Param=O=function(e){function t(e,t,n){var i;this.name=e,this.value=t,this.splat=n,i=e=this.name.unwrapAll().value,Lt.call(U,i)>=0&&this.name.error('parameter name "'+e+'" is not allowed')}return Ft(t,e),t.prototype.children=["name","value"],t.prototype.compileToFragments=function(e){return this.name.compileToFragments(e,C)},t.prototype.asReference=function(e){var t;return this.reference?this.reference:(t=this.name,t["this"]?(t=t.properties[0].name,t.value.reserved&&(t=new D(e.scope.freeVariable(t.value)))):t.isComplex()&&(t=new D(e.scope.freeVariable("arg"))),t=new Z(t),this.splat&&(t=new G(t)),t.updateLocationDataIfMissing(this.locationData),this.reference=t)},t.prototype.isComplex=function(){return this.name.isComplex()},t.prototype.eachName=function(e,t){var n,r,s,o,a,c;if(null==t&&(t=this.name),n=function(t){var n;return n=t.properties[0].name,n.value.reserved?void 0:e(n.value,n)},t instanceof D)return e(t.value,t);if(t instanceof Z)return n(t);for(c=t.objects,o=0,a=c.length;a>o;o++)s=c[o],s instanceof i?this.eachName(e,s.value.unwrap()):s instanceof G?(r=s.name.unwrap(),e(r.value,r)):s instanceof Z?s.isArray()||s.isObject()?this.eachName(e,s.base):s["this"]?n(s):e(s.base.value,s.base):s instanceof p||s.error("illegal parameter "+s.compile())},t}(r),e.Splat=G=function(e){function t(e){this.name=e.compile?e:new D(e)}return Ft(t,e),t.prototype.children=["name"],t.prototype.isAssignable=et,t.prototype.assigns=function(e){return this.name.assigns(e)},t.prototype.compileToFragments=function(e){return this.name.compileToFragments(e)},t.prototype.unwrap=function(){return this.name},t.compileSplattedArray=function(e,n,i){var r,s,o,a,c,h,l,u,p,d;for(l=-1;(u=n[++l])&&!(u instanceof t););if(l>=n.length)return[];if(1===n.length)return u=n[0],c=u.compileToFragments(e,C),i?c:[].concat(u.makeCode(""+yt("slice")+".call("),c,u.makeCode(")"));for(r=n.slice(l),h=p=0,d=r.length;d>p;h=++p)u=r[h],o=u.compileToFragments(e,C),r[h]=u instanceof t?[].concat(u.makeCode(""+yt("slice")+".call("),o,u.makeCode(")")):[].concat(u.makeCode("["),o,u.makeCode("]"));return 0===l?(u=n[0],a=u.joinFragmentArrays(r.slice(1),", "),r[0].concat(u.makeCode(".concat("),a,u.makeCode(")"))):(s=function(){var t,i,r,s;for(r=n.slice(0,l),s=[],t=0,i=r.length;i>t;t++)u=r[t],s.push(u.compileToFragments(e,C));return s}(),s=n[0].joinFragmentArrays(s,", "),a=n[l].joinFragmentArrays(r,", "),[].concat(n[0].makeCode("["),s,n[l].makeCode("].concat("),a,lt(n).makeCode(")")))},t}(r),e.Expansion=p=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return Ft(t,e),t.prototype.isComplex=A,t.prototype.compileNode=function(){return this.error("Expansion must be used inside a destructuring assignment or parameter list")},t.prototype.asReference=function(){return this},t.prototype.eachName=function(){},t}(r),e.While=Q=function(e){function t(e,t){this.condition=(null!=t?t.invert:void 0)?e.invert():e,this.guard=null!=t?t.guard:void 0}return Ft(t,e),t.prototype.children=["condition","guard","body"],t.prototype.isStatement=et,t.prototype.makeReturn=function(e){return e?t.__super__.makeReturn.apply(this,arguments):(this.returns=!this.jumps({loop:!0}),this)},t.prototype.addBody=function(e){return this.body=e,this},t.prototype.jumps=function(){var e,t,n,i,r;if(e=this.body.expressions,!e.length)return!1;for(i=0,r=e.length;r>i;i++)if(n=e[i],t=n.jumps({loop:!0}))return t;return!1},t.prototype.compileNode=function(e){var t,n,i,r;return e.indent+=X,r="",n=this.body,n.isEmpty()?n=this.makeCode(""):(this.returns&&(n.makeReturn(i=e.scope.freeVariable("results")),r=""+this.tab+i+" = [];\n"),this.guard&&(n.expressions.length>1?n.expressions.unshift(new v(new j(this.guard).invert(),new D("continue"))):this.guard&&(n=s.wrap([new v(this.guard,n)]))),n=[].concat(this.makeCode("\n"),n.compileToFragments(e,x),this.makeCode("\n"+this.tab))),t=[].concat(this.makeCode(r+this.tab+"while ("),this.condition.compileToFragments(e,E),this.makeCode(") {"),n,this.makeCode("}")),this.returns&&t.push(this.makeCode("\n"+this.tab+"return "+i+";")),t},t}(r),e.Op=$=function(e){function n(e,t,n,i){if("in"===e)return new w(t,n);if("do"===e)return this.generateDo(t);if("new"===e){if(t instanceof o&&!t["do"]&&!t.isNew)return t.newInstance();(t instanceof c&&t.bound||t["do"])&&(t=new j(t))}return this.operator=r[e]||e,this.first=t,this.second=n,this.flip=!!i,this}var r,s;return Ft(n,e),r={"==":"===","!=":"!==",of:"in"},s={"!==":"===","===":"!=="},n.prototype.children=["first","second"],n.prototype.isSimpleNumber=A,n.prototype.isUnary=function(){return!this.second},n.prototype.isComplex=function(){var e;return!(this.isUnary()&&("+"===(e=this.operator)||"-"===e))||this.first.isComplex()},n.prototype.isChainable=function(){var e;return"<"===(e=this.operator)||">"===e||">="===e||"<="===e||"==="===e||"!=="===e},n.prototype.invert=function(){var e,t,i,r,o;if(this.isChainable()&&this.first.isChainable()){for(e=!0,t=this;t&&t.operator;)e&&(e=t.operator in s),t=t.first;if(!e)return new j(this).invert();for(t=this;t&&t.operator;)t.invert=!t.invert,t.operator=s[t.operator],t=t.first;return this}return(r=s[this.operator])?(this.operator=r,this.first.unwrap()instanceof n&&this.first.invert(),this):this.second?new j(this).invert():"!"===this.operator&&(i=this.first.unwrap())instanceof n&&("!"===(o=i.operator)||"in"===o||"instanceof"===o)?i:new n("!",this)},n.prototype.unfoldSoak=function(e){var t;return("++"===(t=this.operator)||"--"===t||"delete"===t)&&kt(e,this,"first")},n.prototype.generateDo=function(e){var t,n,r,s,a,h,l,u;for(s=[],n=e instanceof i&&(a=e.value.unwrap())instanceof c?a:e,u=n.params||[],h=0,l=u.length;l>h;h++)r=u[h],r.value?(s.push(r.value),delete r.value):s.push(r);return t=new o(e,s),t["do"]=!0,t},n.prototype.compileNode=function(e){var t,n,i,r,s,o;if(n=this.isChainable()&&this.first.isChainable(),n||(this.first.front=this.front),"delete"===this.operator&&e.scope.check(this.first.unwrapAll().value)&&this.error("delete operand may not be argument or var"),("--"===(s=this.operator)||"++"===s)&&(o=this.first.unwrapAll().value,Lt.call(U,o)>=0)&&this.error('cannot increment/decrement "'+this.first.unwrapAll().value+'"'),this.isUnary())return this.compileUnary(e);if(n)return this.compileChain(e);switch(this.operator){case"?":return this.compileExistence(e);case"**":return this.compilePower(e);case"//":return this.compileFloorDivision(e);case"%%":return this.compileModulo(e);default:return i=this.first.compileToFragments(e,N),r=this.second.compileToFragments(e,N),t=[].concat(i,this.makeCode(" "+this.operator+" "),r),N>=e.level?t:this.wrapInBraces(t)}},n.prototype.compileChain=function(e){var t,n,i,r;return r=this.first.second.cache(e),this.first.second=r[0],i=r[1],n=this.first.compileToFragments(e,N),t=n.concat(this.makeCode(" "+(this.invert?"&&":"||")+" "),i.compileToFragments(e),this.makeCode(" "+this.operator+" "),this.second.compileToFragments(e,N)),this.wrapInBraces(t)},n.prototype.compileExistence=function(e){var t,n;return this.first.isComplex()?(n=new D(e.scope.freeVariable("ref")),t=new j(new i(n,this.first))):(t=this.first,n=t),new v(new u(t),n,{type:"if"}).addElse(this.second).compileToFragments(e)},n.prototype.compileUnary=function(e){var t,i,r;return i=[],t=this.operator,i.push([this.makeCode(t)]),"!"===t&&this.first instanceof u?(this.first.negated=!this.first.negated,this.first.compileToFragments(e)):e.level>=F?new j(this).compileToFragments(e):(r="+"===t||"-"===t,("new"===t||"typeof"===t||"delete"===t||r&&this.first instanceof n&&this.first.operator===t)&&i.push([this.makeCode(" ")]),(r&&this.first instanceof n||"new"===t&&this.first.isStatement(e))&&(this.first=new j(this.first)),i.push(this.first.compileToFragments(e,N)),this.flip&&i.reverse(),this.joinFragmentArrays(i,""))},n.prototype.compilePower=function(e){var n;return n=new Z(new D("Math"),[new t(new D("pow"))]),new o(n,[this.first,this.second]).compileToFragments(e)},n.prototype.compileFloorDivision=function(e){var i,r;return r=new Z(new D("Math"),[new t(new D("floor"))]),i=new n("/",this.first,this.second),new o(r,[i]).compileToFragments(e)},n.prototype.compileModulo=function(e){var t;return t=new Z(new D(yt("modulo"))),new o(t,[this.first,this.second]).compileToFragments(e)},n.prototype.toString=function(e){return n.__super__.toString.call(this,e,this.constructor.name+" "+this.operator)},n}(r),e.In=w=function(e){function t(e,t){this.object=e,this.array=t}return Ft(t,e),t.prototype.children=["object","array"],t.prototype.invert=R,t.prototype.compileNode=function(e){var t,n,i,r,s;if(this.array instanceof Z&&this.array.isArray()&&this.array.base.objects.length){for(s=this.array.base.objects,i=0,r=s.length;r>i;i++)if(n=s[i],n instanceof G){t=!0;break}if(!t)return this.compileOrTest(e)}return this.compileLoopTest(e)},t.prototype.compileOrTest=function(e){var t,n,i,r,s,o,a,c,h,l,u,p;for(l=this.object.cache(e,N),o=l[0],s=l[1],u=this.negated?[" !== "," && "]:[" === "," || "],t=u[0],n=u[1],a=[],p=this.array.base.objects,i=c=0,h=p.length;h>c;i=++c)r=p[i],i&&a.push(this.makeCode(n)),a=a.concat(i?s:o,this.makeCode(t),r.compileToFragments(e,F));return N>e.level?a:this.wrapInBraces(a)},t.prototype.compileLoopTest=function(e){var t,n,i,r;return r=this.object.cache(e,C),i=r[0],n=r[1],t=[].concat(this.makeCode(yt("indexOf")+".call("),this.array.compileToFragments(e,C),this.makeCode(", "),n,this.makeCode(") "+(this.negated?"< 0":">= 0"))),at(i)===at(n)?t:(t=i.concat(this.makeCode(", "),t),C>e.level?t:this.wrapInBraces(t))},t.prototype.toString=function(e){return t.__super__.toString.call(this,e,this.constructor.name+(this.negated?"!":""))},t}(r),e.Try=K=function(e){function t(e,t,n,i){this.attempt=e,this.errorVariable=t,this.recovery=n,this.ensure=i}return Ft(t,e),t.prototype.children=["attempt","recovery","ensure"],t.prototype.isStatement=et,t.prototype.jumps=function(e){var t;return this.attempt.jumps(e)||(null!=(t=this.recovery)?t.jumps(e):void 0)},t.prototype.makeReturn=function(e){return this.attempt&&(this.attempt=this.attempt.makeReturn(e)),this.recovery&&(this.recovery=this.recovery.makeReturn(e)),this},t.prototype.compileNode=function(e){var t,n,r,s;return e.indent+=X,s=this.attempt.compileToFragments(e,x),t=this.recovery?(r=new D("_error"),this.errorVariable?this.recovery.unshift(new i(this.errorVariable,r)):void 0,[].concat(this.makeCode(" catch ("),r.compileToFragments(e),this.makeCode(") {\n"),this.recovery.compileToFragments(e,x),this.makeCode("\n"+this.tab+"}"))):this.ensure||this.recovery?[]:[this.makeCode(" catch (_error) {}")],n=this.ensure?[].concat(this.makeCode(" finally {\n"),this.ensure.compileToFragments(e,x),this.makeCode("\n"+this.tab+"}")):[],[].concat(this.makeCode(""+this.tab+"try {\n"),s,this.makeCode("\n"+this.tab+"}"),t,n)},t}(r),e.Throw=z=function(e){function t(e){this.expression=e}return Ft(t,e),t.prototype.children=["expression"],t.prototype.isStatement=et,t.prototype.jumps=A,t.prototype.makeReturn=Y,t.prototype.compileNode=function(e){return[].concat(this.makeCode(this.tab+"throw "),this.expression.compileToFragments(e),this.makeCode(";"))},t}(r),e.Existence=u=function(e){function t(e){this.expression=e}return Ft(t,e),t.prototype.children=["expression"],t.prototype.invert=R,t.prototype.compileNode=function(e){var t,n,i,r;return this.expression.front=this.front,i=this.expression.compile(e,N),b.test(i)&&!e.scope.check(i)?(r=this.negated?["===","||"]:["!==","&&"],t=r[0],n=r[1],i="typeof "+i+" "+t+' "undefined" '+n+" "+i+" "+t+" null"):i=""+i+" "+(this.negated?"==":"!=")+" null",[this.makeCode(L>=e.level?i:"("+i+")")]},t}(r),e.Parens=j=function(e){function t(e){this.body=e}return Ft(t,e),t.prototype.children=["body"],t.prototype.unwrap=function(){return this.body},t.prototype.isComplex=function(){return this.body.isComplex()},t.prototype.compileNode=function(e){var t,n,i;return n=this.body.unwrap(),n instanceof Z&&n.isAtomic()?(n.front=this.front,n.compileToFragments(e)):(i=n.compileToFragments(e,E),t=N>e.level&&(n instanceof $||n instanceof o||n instanceof f&&n.returns),t?i:this.wrapInBraces(i))},t}(r),e.For=f=function(e){function t(e,t){var n;this.source=t.source,this.guard=t.guard,this.step=t.step,this.name=t.name,this.index=t.index,this.body=s.wrap([e]),this.own=!!t.own,this.object=!!t.object,this.object&&(n=[this.index,this.name],this.name=n[0],this.index=n[1]),this.index instanceof Z&&this.index.error("index cannot be a pattern matching expression"),this.range=this.source instanceof Z&&this.source.base instanceof B&&!this.source.properties.length,this.pattern=this.name instanceof Z,this.range&&this.index&&this.index.error("indexes do not apply to range loops"),this.range&&this.pattern&&this.name.error("cannot pattern match over range loops"),this.own&&!this.object&&this.name.error("cannot use own with for-in"),this.returns=!1}return Ft(t,e),t.prototype.children=["body","source","guard","step"],t.prototype.compileNode=function(e){var t,n,r,o,a,c,h,l,u,p,d,f,m,g,k,y,w,T,F,L,N,E,S,R,A,_,$,O,M,B,P,U,H,q;return t=s.wrap([this.body]),T=null!=(H=lt(t.expressions))?H.jumps():void 0,T&&T instanceof V&&(this.returns=!1),$=this.range?this.source.base:this.source,_=e.scope,this.pattern||(L=this.name&&this.name.compile(e,C)),g=this.index&&this.index.compile(e,C),L&&!this.pattern&&_.find(L),g&&_.find(g),this.returns&&(A=_.freeVariable("results")),k=this.object&&g||_.freeVariable("i"),y=this.range&&L||g||k,w=y!==k?""+y+" = ":"",this.step&&!this.range&&(q=this.cacheToCodeFragments(this.step.cache(e,C)),O=q[0],B=q[1],M=B.match(I)),this.pattern&&(L=k),U="",d="",h="",f=this.tab+X,this.range?p=$.compileToFragments(pt(e,{index:k,name:L,step:this.step})):(P=this.source.compile(e,C),!L&&!this.own||b.test(P)||(h+=""+this.tab+(E=_.freeVariable("ref"))+" = "+P+";\n",P=E),L&&!this.pattern&&(N=""+L+" = "+P+"["+y+"]"),this.object||(O!==B&&(h+=""+this.tab+O+";\n"),this.step&&M&&(u=0>ft(M[0]))||(F=_.freeVariable("len")),a=""+w+k+" = 0, "+F+" = "+P+".length",c=""+w+k+" = "+P+".length - 1",r=""+k+" < "+F,o=""+k+" >= 0",this.step?(M?u&&(r=o,a=c):(r=""+B+" > 0 ? "+r+" : "+o,a="("+B+" > 0 ? ("+a+") : "+c+")"),m=""+k+" += "+B):m=""+(y!==k?"++"+k:""+k+"++"),p=[this.makeCode(""+a+"; "+r+"; "+w+m)])),this.returns&&(S=""+this.tab+A+" = [];\n",R="\n"+this.tab+"return "+A+";",t.makeReturn(A)),this.guard&&(t.expressions.length>1?t.expressions.unshift(new v(new j(this.guard).invert(),new D("continue"))):this.guard&&(t=s.wrap([new v(this.guard,t)]))),this.pattern&&t.expressions.unshift(new i(this.name,new D(""+P+"["+y+"]"))),l=[].concat(this.makeCode(h),this.pluckDirectCall(e,t)),N&&(U="\n"+f+N+";"),this.object&&(p=[this.makeCode(""+y+" in "+P)],this.own&&(d="\n"+f+"if (!"+yt("hasProp")+".call("+P+", "+y+")) continue;")),n=t.compileToFragments(pt(e,{indent:f}),x),n&&n.length>0&&(n=[].concat(this.makeCode("\n"),n,this.makeCode("\n"))),[].concat(l,this.makeCode(""+(S||"")+this.tab+"for ("),p,this.makeCode(") {"+d+U),n,this.makeCode(""+this.tab+"}"+(R||"")))},t.prototype.pluckDirectCall=function(e,t){var n,r,s,a,h,l,u,p,d,f,m,b,g,k,y,v;for(r=[],f=t.expressions,h=p=0,d=f.length;d>p;h=++p)s=f[h],s=s.unwrapAll(),s instanceof o&&(u=null!=(m=s.variable)?m.unwrapAll():void 0,(u instanceof c||u instanceof Z&&(null!=(b=u.base)?b.unwrapAll():void 0)instanceof c&&1===u.properties.length&&("call"===(g=null!=(k=u.properties[0].name)?k.value:void 0)||"apply"===g))&&(a=(null!=(y=u.base)?y.unwrapAll():void 0)||u,l=new D(e.scope.freeVariable("fn")),n=new Z(l),u.base&&(v=[n,u],u.base=v[0],n=v[1]),t.expressions[h]=new o(n,s.args),r=r.concat(this.makeCode(this.tab),new i(l,a).compileToFragments(e,x),this.makeCode(";\n"))));return r},t}(Q),e.Switch=W=function(e){function t(e,t,n){this.subject=e,this.cases=t,this.otherwise=n}return Ft(t,e),t.prototype.children=["subject","cases","otherwise"],t.prototype.isStatement=et,t.prototype.jumps=function(e){var t,n,i,r,s,o,a,c;for(null==e&&(e={block:!0}),o=this.cases,r=0,s=o.length;s>r;r++)if(a=o[r],n=a[0],t=a[1],i=t.jumps(e))return i;return null!=(c=this.otherwise)?c.jumps(e):void 0},t.prototype.makeReturn=function(e){var t,n,i,r,o;for(r=this.cases,n=0,i=r.length;i>n;n++)t=r[n],t[1].makeReturn(e);return e&&(this.otherwise||(this.otherwise=new s([new D("void 0")]))),null!=(o=this.otherwise)&&o.makeReturn(e),this},t.prototype.compileNode=function(e){var t,n,i,r,s,o,a,c,h,l,u,p,d,f,m,b;for(c=e.indent+X,h=e.indent=c+X,o=[].concat(this.makeCode(this.tab+"switch ("),this.subject?this.subject.compileToFragments(e,E):this.makeCode("false"),this.makeCode(") {\n")),f=this.cases,a=l=0,p=f.length;p>l;a=++l){for(m=f[a],r=m[0],t=m[1],b=ot([r]),u=0,d=b.length;d>u;u++)i=b[u],this.subject||(i=i.invert()),o=o.concat(this.makeCode(c+"case "),i.compileToFragments(e,E),this.makeCode(":\n"));if((n=t.compileToFragments(e,x)).length>0&&(o=o.concat(n,this.makeCode("\n"))),a===this.cases.length-1&&!this.otherwise)break;s=this.lastNonComment(t.expressions),s instanceof V||s instanceof D&&s.jumps()&&"debugger"!==s.value||o.push(i.makeCode(h+"break;\n"))}return this.otherwise&&this.otherwise.expressions.length&&o.push.apply(o,[this.makeCode(c+"default:\n")].concat(Ct.call(this.otherwise.compileToFragments(e,x)),[this.makeCode("\n")])),o.push(this.makeCode(this.tab+"}")),o},t}(r),e.If=v=function(e){function t(e,t,n){this.body=t,null==n&&(n={}),this.condition="unless"===n.type?e.invert():e,this.elseBody=null,this.isChain=!1,this.soak=n.soak}return Ft(t,e),t.prototype.children=["condition","body","elseBody"],t.prototype.bodyNode=function(){var e;return null!=(e=this.body)?e.unwrap():void 0},t.prototype.elseBodyNode=function(){var e;return null!=(e=this.elseBody)?e.unwrap():void 0},t.prototype.addElse=function(e){return this.isChain?this.elseBodyNode().addElse(e):(this.isChain=e instanceof t,this.elseBody=this.ensureBlock(e),this.elseBody.updateLocationDataIfMissing(e.locationData)),this},t.prototype.isStatement=function(e){var t;return(null!=e?e.level:void 0)===x||this.bodyNode().isStatement(e)||(null!=(t=this.elseBodyNode())?t.isStatement(e):void 0)},t.prototype.jumps=function(e){var t;return this.body.jumps(e)||(null!=(t=this.elseBody)?t.jumps(e):void 0)},t.prototype.compileNode=function(e){return this.isStatement(e)?this.compileStatement(e):this.compileExpression(e)},t.prototype.makeReturn=function(e){return e&&(this.elseBody||(this.elseBody=new s([new D("void 0")]))),this.body&&(this.body=new s([this.body.makeReturn(e)])),this.elseBody&&(this.elseBody=new s([this.elseBody.makeReturn(e)])),this},t.prototype.ensureBlock=function(e){return e instanceof s?e:new s([e])},t.prototype.compileStatement=function(e){var n,i,r,s,o,a,c;return r=it(e,"chainChild"),(o=it(e,"isExistentialEquals"))?new t(this.condition.invert(),this.elseBodyNode(),{type:"if"}).compileToFragments(e):(c=e.indent+X,s=this.condition.compileToFragments(e,E),i=this.ensureBlock(this.body).compileToFragments(pt(e,{indent:c})),a=[].concat(this.makeCode("if ("),s,this.makeCode(") {\n"),i,this.makeCode("\n"+this.tab+"}")),r||a.unshift(this.makeCode(this.tab)),this.elseBody?(n=a.concat(this.makeCode(" else ")),this.isChain?(e.chainChild=!0,n=n.concat(this.elseBody.unwrap().compileToFragments(e,x))):n=n.concat(this.makeCode("{\n"),this.elseBody.compileToFragments(pt(e,{indent:c}),x),this.makeCode("\n"+this.tab+"}")),n):a)},t.prototype.compileExpression=function(e){var t,n,i,r;return i=this.condition.compileToFragments(e,L),n=this.bodyNode().compileToFragments(e,C),t=this.elseBodyNode()?this.elseBodyNode().compileToFragments(e,C):[this.makeCode("void 0")],r=i.concat(this.makeCode(" ? "),n,this.makeCode(" : "),t),e.level>=L?this.wrapInBraces(r):r},t.prototype.unfoldSoak=function(){return this.soak&&this},t}(r),J={"extends":function(){return"function(child, parent) { for (var key in parent) { if ("+yt("hasProp")+".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }"},bind:function(){return"function(fn, me){ return function(){ return fn.apply(me, arguments); }; }"},indexOf:function(){return"[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"},modulo:function(){return"function(a, b) { return (+a % (b = +b) + b) % b; }"},hasProp:function(){return"{}.hasOwnProperty"},slice:function(){return"[].slice"}},x=1,E=2,C=3,L=4,N=5,F=6,X="  ",g="[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*",b=RegExp("^"+g+"$"),P=/^[+-]?\d+$/,m=/^[+-]?0x[\da-f]+/i,I=/^[+-]?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)$/i,S=RegExp("^("+g+")(\\.prototype)?(?:\\.("+g+")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\])$"),y=/^['"]/,k=/^\//,yt=function(e){var t;return t="__"+e,H.root.assign(t,J[e]()),t},dt=function(e,t){return e=e.replace(/\n/g,"$&"+t),e.replace(/\s+$/,"")},ft=function(e){return null==e?0:e.match(m)?parseInt(e,16):parseFloat(e)},ct=function(e){return e instanceof D&&"arguments"===e.value&&!e.asKey},ht=function(e){return e instanceof D&&"this"===e.value&&!e.asKey||e instanceof c&&e.bound||e instanceof o&&e.isSuper},kt=function(e,t,n){var i;if(i=t[n].unfoldSoak(e))return t[n]=i.body,i.body=new Z(t),i}}.call(this),t.exports}(),require["./sourcemap"]=function(){var e={},t={exports:e};return function(){var e,n;e=function(){function e(e){this.line=e,this.columns=[]}return e.prototype.add=function(e,t,n){var i,r;return r=t[0],i=t[1],null==n&&(n={}),this.columns[e]&&n.noReplace?void 0:this.columns[e]={line:this.line,column:e,sourceLine:r,sourceColumn:i}},e.prototype.sourceLocation=function(e){for(var t;!((t=this.columns[e])||0>=e);)e--;return t&&[t.sourceLine,t.sourceColumn]},e}(),n=function(){function t(){this.lines=[]}var n,i,r,s;return t.prototype.add=function(t,n,i){var r,s,o,a;return null==i&&(i={}),s=n[0],r=n[1],o=(a=this.lines)[s]||(a[s]=new e(s)),o.add(r,t,i)},t.prototype.sourceLocation=function(e){var t,n,i;for(n=e[0],t=e[1];!((i=this.lines[n])||0>=n);)n--;return i&&i.sourceLocation(t)},t.prototype.generate=function(e,t){var n,i,r,s,o,a,c,h,l,u,p,d,f,m,b,g;for(null==e&&(e={}),null==t&&(t=null),u=0,i=0,s=0,r=0,h=!1,n="",b=this.lines,a=p=0,f=b.length;f>p;a=++p)if(o=b[a])for(g=o.columns,d=0,m=g.length;m>d;d++)if(c=g[d]){for(;c.line>u;)i=0,h=!1,n+=";",u++;h&&(n+=",",h=!1),n+=this.encodeVlq(c.column-i),i=c.column,n+=this.encodeVlq(0),n+=this.encodeVlq(c.sourceLine-s),s=c.sourceLine,n+=this.encodeVlq(c.sourceColumn-r),r=c.sourceColumn,h=!0}return l={version:3,file:e.generatedFile||"",sourceRoot:e.sourceRoot||"",sources:e.sourceFiles||[""],names:[],mappings:n},e.inline&&(l.sourcesContent=[t]),JSON.stringify(l,null,2)},r=5,i=1<<r,s=i-1,t.prototype.encodeVlq=function(e){var t,n,o,a;for(t="",o=0>e?1:0,a=(Math.abs(e)<<1)+o;a||!t;)n=a&s,a>>=r,a&&(n|=i),t+=this.encodeBase64(n);return t},n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",t.prototype.encodeBase64=function(e){return n[e]||function(){throw Error("Cannot Base64 encode value: "+e)}()},t}(),t.exports=n}.call(this),t.exports}(),require["./coffee-script"]=function(){var e={},t={exports:e};return function(){var t,n,i,r,s,o,a,c,h,l,u,p,d,f,m,b,g,k,y={}.hasOwnProperty,v=[].indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(t in this&&this[t]===e)return t;return-1};if(o=require("fs"),d=require("vm"),u=require("path"),t=require("./lexer").Lexer,l=require("./parser").parser,c=require("./helpers"),n=require("./sourcemap"),e.VERSION="1.8.0",e.FILE_EXTENSIONS=[".coffee",".litcoffee",".coffee.md"],e.helpers=c,f=function(e){return function(t,n){var i;null==n&&(n={});try{return e.call(this,t,n)}catch(r){throw i=r,c.updateSyntaxError(i,t,n.filename)}}},e.compile=i=f(function(e,t){var i,r,s,o,a,u,p,d,f,m,b,g,k;for(m=c.merge,o=c.extend,t=o({},t),t.sourceMap&&(f=new n),u=l.parse(h.tokenize(e,t)).compileToFragments(t),s=0,t.header&&(s+=1),t.shiftLine&&(s+=1),r=0,d="",g=0,k=u.length;k>g;g++)a=u[g],t.sourceMap&&(a.locationData&&f.add([a.locationData.first_line,a.locationData.first_column],[s,r],{noReplace:!0}),b=c.count(a.code,"\n"),s+=b,b?r=a.code.length-(a.code.lastIndexOf("\n")+1):r+=a.code.length),d+=a.code;return t.header&&(p="Generated by CoffeeScript "+this.VERSION,d="// "+p+"\n"+d),t.sourceMap?(i={js:d},i.sourceMap=f,i.v3SourceMap=f.generate(t,e),i):d}),e.tokens=f(function(e,t){return h.tokenize(e,t)}),e.nodes=f(function(e,t){return"string"==typeof e?l.parse(h.tokenize(e,t)):l.parse(e)}),e.run=function(e,t){var n,r,s,a;return null==t&&(t={}),s=require.main,s.filename=process.argv[1]=t.filename?o.realpathSync(t.filename):".",s.moduleCache&&(s.moduleCache={}),r=t.filename?u.dirname(o.realpathSync(t.filename)):o.realpathSync("."),s.paths=require("module")._nodeModulePaths(r),(!c.isCoffee(s.filename)||require.extensions)&&(n=i(e,t),e=null!=(a=n.js)?a:n),s._compile(e,s.filename)},e.eval=function(e,t){var n,r,s,o,a,c,h,l,p,f,m,b,g,k;if(null==t&&(t={}),e=e.trim()){if(r=d.Script){if(null!=t.sandbox){if(t.sandbox instanceof r.createContext().constructor)h=t.sandbox;else{h=r.createContext(),b=t.sandbox;for(o in b)y.call(b,o)&&(l=b[o],h[o]=l)}h.global=h.root=h.GLOBAL=h}else h=global;if(h.__filename=t.filename||"eval",h.__dirname=u.dirname(h.__filename),h===global&&!h.module&&!h.require){for(n=require("module"),h.module=m=new n(t.modulename||"eval"),h.require=k=function(e){return n._load(e,m,!0)},m.filename=h.__filename,g=Object.getOwnPropertyNames(require),p=0,f=g.length;f>p;p++)c=g[p],"paths"!==c&&(k[c]=require[c]);k.paths=m.paths=n._nodeModulePaths(process.cwd()),k.resolve=function(e){return n._resolveFilename(e,m)}}}a={};for(o in t)y.call(t,o)&&(l=t[o],a[o]=l);return a.bare=!0,s=i(e,a),h===global?d.runInThisContext(s):d.runInContext(s,h)}},e.register=function(){return require("./register")},require.extensions)for(k=this.FILE_EXTENSIONS,b=0,g=k.length;g>b;b++)r=k[b],null==(m=require.extensions)[r]&&(m[r]=function(){throw Error("Use CoffeeScript.register() or require the coffee-script/register module to require "+r+" files.")});e._compileFile=function(e,t){var n,r,s,a;
+null==t&&(t=!1),s=o.readFileSync(e,"utf8"),a=65279===s.charCodeAt(0)?s.substring(1):s;try{n=i(a,{filename:e,sourceMap:t,literate:c.isLiterate(e)})}catch(h){throw r=h,c.updateSyntaxError(r,a,e)}return n},h=new t,l.lexer={lex:function(){var e,t;return t=this.tokens[this.pos++],t?(e=t[0],this.yytext=t[1],this.yylloc=t[2],this.errorToken=t.origin||t,this.yylineno=this.yylloc.first_line):e="",e},setInput:function(e){return this.tokens=e,this.pos=0},upcomingInput:function(){return""}},l.yy=require("./nodes"),l.yy.parseError=function(e,t){var n,i,r,s,o,a,h;return o=t.token,h=l.lexer,s=h.errorToken,a=h.tokens,i=s[0],r=s[1],n=s[2],r=s===a[a.length-1]?"end of input":"INDENT"===i||"OUTDENT"===i?"indentation":c.nameWhitespaceCharacter(r),c.throwSyntaxError("unexpected "+r,n)},s=function(e,t){var n,i,r,s,o,a,c,h,l,u,p,d;return s=void 0,r="",e.isNative()?r="native":(e.isEval()?(s=e.getScriptNameOrSourceURL(),s||(r=""+e.getEvalOrigin()+", ")):s=e.getFileName(),s||(s="<anonymous>"),h=e.getLineNumber(),i=e.getColumnNumber(),u=t(s,h,i),r=u?""+s+":"+u[0]+":"+u[1]:""+s+":"+h+":"+i),o=e.getFunctionName(),a=e.isConstructor(),c=!(e.isToplevel()||a),c?(l=e.getMethodName(),d=e.getTypeName(),o?(p=n="",d&&o.indexOf(d)&&(p=""+d+"."),l&&o.indexOf("."+l)!==o.length-l.length-1&&(n=" [as "+l+"]"),""+p+o+n+" ("+r+")"):""+d+"."+(l||"<anonymous>")+" ("+r+")"):a?"new "+(o||"<anonymous>")+" ("+r+")":o?""+o+" ("+r+")":r},p={},a=function(t){var n,i;if(p[t])return p[t];if(i=null!=u?u.extname(t):void 0,!(0>v.call(e.FILE_EXTENSIONS,i)))return n=e._compileFile(t,!0),p[t]=n.sourceMap},Error.prepareStackTrace=function(t,n){var i,r,o;return o=function(e,t,n){var i,r;return r=a(e),r&&(i=r.sourceLocation([t-1,n-1])),i?[i[0]+1,i[1]+1]:null},r=function(){var t,r,a;for(a=[],t=0,r=n.length;r>t&&(i=n[t],i.getFunction()!==e.run);t++)a.push("  at "+s(i,o));return a}(),""+(""+t)+"\n"+r.join("\n")+"\n"}}.call(this),t.exports}(),require["./browser"]=function(){var exports={},module={exports:exports};return function(){var CoffeeScript,compile,runScripts,__indexOf=[].indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(t in this&&this[t]===e)return t;return-1};CoffeeScript=require("./coffee-script"),CoffeeScript.require=require,compile=CoffeeScript.compile,CoffeeScript.eval=function(code,options){return null==options&&(options={}),null==options.bare&&(options.bare=!0),eval(compile(code,options))},CoffeeScript.run=function(e,t){return null==t&&(t={}),t.bare=!0,t.shiftLine=!0,Function(compile(e,t))()},"undefined"!=typeof window&&null!==window&&("undefined"!=typeof btoa&&null!==btoa&&"undefined"!=typeof JSON&&null!==JSON&&"undefined"!=typeof unescape&&null!==unescape&&"undefined"!=typeof encodeURIComponent&&null!==encodeURIComponent&&(compile=function(e,t){var n,i,r;return null==t&&(t={}),t.sourceMap=!0,t.inline=!0,r=CoffeeScript.compile(e,t),n=r.js,i=r.v3SourceMap,""+n+"\n//# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(i)))+"\n//# sourceURL=coffeescript"}),CoffeeScript.load=function(e,t,n,i){var r;return null==n&&(n={}),null==i&&(i=!1),n.sourceFiles=[e],r=window.ActiveXObject?new window.ActiveXObject("Microsoft.XMLHTTP"):new window.XMLHttpRequest,r.open("GET",e,!0),"overrideMimeType"in r&&r.overrideMimeType("text/plain"),r.onreadystatechange=function(){var s,o;if(4===r.readyState){if(0!==(o=r.status)&&200!==o)throw Error("Could not load "+e);if(s=[r.responseText,n],i||CoffeeScript.run.apply(CoffeeScript,s),t)return t(s)}},r.send(null)},runScripts=function(){var e,t,n,i,r,s,o,a,c,h,l;for(a=window.document.getElementsByTagName("script"),t=["text/coffeescript","text/literate-coffeescript"],e=function(){var e,n,i,r;for(r=[],e=0,n=a.length;n>e;e++)s=a[e],i=s.type,__indexOf.call(t,i)>=0&&r.push(s);return r}(),r=0,n=function(){var t;return t=e[r],t instanceof Array?(CoffeeScript.run.apply(CoffeeScript,t),r++,n()):void 0},c=function(i,r){var s;return s={literate:i.type===t[1]},i.src?CoffeeScript.load(i.src,function(t){return e[r]=t,n()},s,!0):(s.sourceFiles=["embedded"],e[r]=[i.innerHTML,s])},i=h=0,l=e.length;l>h;i=++h)o=e[i],c(o,i);return n()},window.addEventListener?window.addEventListener("DOMContentLoaded",runScripts,!1):window.attachEvent("onload",runScripts))}.call(this),module.exports}(),require["./coffee-script"]}();"function"==typeof define&&define.amd?define(function(){return CoffeeScript}):root.CoffeeScript=CoffeeScript})(this);
\ No newline at end of file
diff --git a/tools/coffee/coffee.cmd b/tools/coffee/coffee.cmd
new file mode 100644
index 00000000..d912965c
--- /dev/null
+++ b/tools/coffee/coffee.cmd
@@ -0,0 +1,2 @@
+::For convenience
+@cscript //nologo "%~dp0coffee.wsf" %*
diff --git a/tools/coffee/coffee.wsf b/tools/coffee/coffee.wsf
new file mode 100644
index 00000000..1ffb1f9a
--- /dev/null
+++ b/tools/coffee/coffee.wsf
@@ -0,0 +1,93 @@
+<job>
+<!-- https://github.com/jashkenas/coffee-script/raw/master/extras/coffee-script.js -->
+<script src="coffee-script.js" language="JScript" />
+<script language="JScript">
+(function() {
+
+    var args = [];
+    for (var i = 0; i < WScript.Arguments.Length; i++) {
+        args.push(WScript.Arguments.Item(i));
+    }
+
+    // FileSystemObject: http://msdn.microsoft.com/en-us/library/bkx696eh.aspx
+    var fso = new ActiveXObject("Scripting.FileSystemObject");
+
+    var isfolder = (args[0] && fso.folderExists(args[0]));
+
+    if (isfolder) {
+        f = fso.getFolder(args[0]);
+        e = new Enumerator(f.files);
+        for (; !e.atEnd(); e.moveNext()) {
+            if (e.item().path.toLowerCase().lastIndexOf('.coffee') != -1) {
+                convert(e.item(), args[1]);
+            }
+        }
+    }
+    else {
+        convert(args[0], args[1])
+    }
+
+})();
+
+
+function convert(input, output) {
+
+    var fso = new ActiveXObject("Scripting.FileSystemObject");
+
+    if (output) {
+        // if output specifies a folder name, output filename is same as input filename with .coffee extension
+        if (fso.folderExists(output)) {
+            output = output + '\\' + fso.getFile(input).name.replace('\.coffee', '.js')
+        }
+    }
+
+    var coffee;
+    if (!input) { 
+        // Read all input data from STDIN
+        var chunks = [];
+        while (!WScript.StdIn.AtEndOfStream)
+            chunks.push(WScript.StdIn.ReadAll());
+        coffee = chunks.join('');
+    }
+    else {
+        coffee = readUtf8(input);
+    }
+
+    try {
+        var js = CoffeeScript.compile(coffee);
+        
+        if (!output) {
+            WScript.StdOut.Write(js);
+        }
+        else {
+            writeUtf8(output, js);
+        }
+    }
+    catch (err) {
+        WScript.StdErr.WriteLine(err.message);
+        WScript.Quit(1);
+    }
+}
+
+function readUtf8(filename) {
+	var stream = new ActiveXObject("ADODB.Stream");
+	stream.Open();
+	stream.Type = 2; // Text
+	stream.Charset = 'utf-8';
+	stream.LoadFromFile(filename);
+	var text = stream.ReadText();
+	stream.Close();
+	return text;
+}
+
+function writeUtf8(filename, text) {
+	var stream = new ActiveXObject("ADODB.Stream");
+	stream.Open();
+	stream.Type = 2; // Text
+	stream.Charset = 'utf-8';
+	stream.WriteText(text);
+	stream.SaveToFile(filename, 2);
+	stream.Close();
+}
+</script>
+</job>
\ No newline at end of file
diff --git a/tools/upnpc/Changelog.txt b/tools/upnpc/Changelog.txt
new file mode 100644
index 00000000..f09215cd
--- /dev/null
+++ b/tools/upnpc/Changelog.txt
@@ -0,0 +1,585 @@
+$Id: Changelog.txt,v 1.193 2014/02/05 17:26:45 nanard Exp $
+miniUPnP client Changelog.
+
+2014/02/05:
+  handle EINPROGRESS after connect()
+
+2014/02/03:
+  minixml now handle XML comments
+
+VERSION 1.9 : released 2014/01/31
+
+2014/01/31:
+  added argument remoteHost to UPNP_GetSpecificPortMappingEntry()
+  increment API_VERSION to 10
+
+2013/12/09:
+  --help and -h arguments in upnpc.c
+
+2013/10/07:
+  fixed potential buffer overrun in miniwget.c
+  Modified UPNP_GetValidIGD() to check for ExternalIpAddress
+
+2013/08/01:
+  define MAXHOSTNAMELEN if not already done
+
+2013/06/06:
+  update upnpreplyparse to allow larger values (128 chars instead of 64)
+
+2013/05/14:
+  Update upnpreplyparse to take into account "empty" elements
+  validate upnpreplyparse.c code with "make check"
+
+2013/05/03:
+  Fix Solaris build thanks to Maciej Małecki
+
+2013/04/27:
+  Fix testminiwget.sh for BSD
+
+2013/03/23:
+  Fixed Makefile for *BSD
+
+2013/03/11:
+  Update Makefile to use JNAerator version 0.11
+
+2013/02/11:
+  Fix testminiwget.sh for use with dash
+  Use $(DESTDIR) in Makefile
+
+VERSION 1.8 : released 2013/02/06
+
+2012/10/16:
+  fix testminiwget with no IPv6 support
+
+2012/09/27:
+  Rename all include guards to not clash with C99
+  (7.1.3 Reserved identifiers).
+
+2012/08/30:
+  Added -e option to upnpc program (set description for port mappings)
+
+2012/08/29:
+  Python 3 support (thanks to Christopher Foo)
+
+2012/08/11:
+  Fix a memory link in UPNP_GetValidIGD()
+  Try to handle scope id in link local IPv6 URL under MS Windows
+
+2012/07/20:
+  Disable HAS_IP_MREQN on DragonFly BSD
+
+2012/06/28:
+  GetUPNPUrls() now inserts scope into link-local IPv6 addresses
+
+2012/06/23:
+  More error return checks in upnpc.c
+  #define MINIUPNPC_GET_SRC_ADDR enables receivedata() to get scope_id
+  parseURL() now parses IPv6 addresses scope
+  new parameter for miniwget() : IPv6 address scope
+  increment API_VERSION to 9
+
+2012/06/20:
+  fixed CMakeLists.txt
+
+2012/05/29
+  Improvements in testminiwget.sh
+
+VERSION 1.7 : released 2012/05/24
+
+2012/05/01:
+  Cleanup settings of CFLAGS in Makefile
+  Fix signed/unsigned integer comparaisons
+
+2012/04/20:
+  Allow to specify protocol with TCP or UDP for -A option
+
+2012/04/09:
+  Only try to fetch XML description once in UPNP_GetValidIGD()
+  Added -ansi flag to compilation, and fixed C++ comments to ANSI C comments.
+
+2012/04/05:
+  minor improvements to minihttptestserver.c
+
+2012/03/15:
+  upnperrors.c returns valid error string for unrecognized error codes
+
+2012/03/08:
+  make minihttptestserver listen on loopback interface instead of 0.0.0.0
+
+2012/01/25:
+  Maven installation thanks to Alexey Kuznetsov
+
+2012/01/21:
+  Replace WIN32 macro by _WIN32
+
+2012/01/19:
+  Fixes in java wrappers thanks to Alexey Kuznetsov :
+    https://github.com/axet/miniupnp/tree/fix-javatest/miniupnpc
+  Make and install .deb packages (python) thanks to Alexey Kuznetsov :
+    https://github.com/axet/miniupnp/tree/feature-debbuild/miniupnpc
+
+2012/01/07:
+  The multicast interface can now be specified by name with IPv4.
+
+2012/01/02:
+  Install man page
+
+2011/11/25:
+  added header to Port Mappings list in upnpc.c
+
+2011/10/09:
+  Makefile : make clean now removes jnaerator generated files.
+  MINIUPNPC_VERSION in miniupnpc.h (updated by make)
+
+2011/09/12:
+  added rootdescURL to UPNPUrls structure.
+
+VERSION 1.6 : released 2011/07/25
+
+2011/07/25:
+  Update doc for version 1.6 release
+
+2011/06/18:
+  Fix for windows in miniwget.c
+
+2011/06/04:
+  display remote host in port mapping listing
+
+2011/06/03:
+  Fix in make install : there were missing headers
+
+2011/05/26:
+  Fix the socket leak in miniwget thanks to Richard Marsh.
+  Permit to add leaseduration in -a command. Display lease duration.
+
+2011/05/15:
+  Try both LinkLocal and SiteLocal multicast address for SSDP in IPv6
+
+2011/05/09:
+  add a test in testminiwget.sh.
+  more error checking in miniwget.c
+
+2011/05/06:
+  Adding some tool to test and validate miniwget.c
+  simplified and debugged miniwget.c
+
+2011/04/11:
+  moving ReceiveData() to a receivedata.c file.
+  parsing presentation url
+  adding IGD v2 WANIPv6FirewallControl commands
+
+2011/04/10:
+  update of miniupnpcmodule.c
+  comments in miniwget.c, update in testminiwget
+  Adding errors codes from IGD v2
+  new functions in upnpc.c for IGD v2
+
+2011/04/09:
+  Support for litteral ip v6 address in miniwget
+
+2011/04/08:
+  Adding support for urn:schemas-upnp-org:service:WANIPv6FirewallControl:1
+  Updating APIVERSION
+  Supporting IPV6 in upnpDiscover()
+  Adding a -6 option to upnpc command line tool
+
+2011/03/18:
+  miniwget/parseURL() : return an error when url param is null.
+  fixing GetListOfPortMappings()
+
+2011/03/14:
+  upnpDiscover() now reporting an error code.
+  improvements in comments.
+
+2011/03/11:
+  adding miniupnpcstrings.h.cmake and CMakeLists.txt files.
+
+2011/02/15:
+  Implementation of GetListOfPortMappings()
+
+2011/02/07:
+  updates to minixml to support character data starting with spaces
+  minixml now support CDATA
+  upnpreplyparse treats <NewPortListing> specificaly
+  change in simpleUPnPcommand to return the buffer (simplification)
+
+2011/02/06:
+  Added leaseDuration argument to AddPortMapping()
+  Starting to implement GetListOfPortMappings()
+
+2011/01/11:
+  updating wingenminiupnpcstrings.c
+
+2011/01/04:
+  improving updateminiupnpcstrings.sh
+
+VERSION 1.5 : released 2011/01/01
+
+2010/12/21:
+  use NO_GETADDRINFO macro to disable the use of getaddrinfo/freeaddrinfo
+
+2010/12/11:
+  Improvements on getHTTPResponse() code.
+
+2010/12/09:
+  new code for miniwget that handle Chunked transfer encoding
+  using getHTTPResponse() in SOAP call code
+  Adding MANIFEST.in for 'python setup.py bdist_rpm'
+
+2010/11/25:
+  changes to minissdpc.c to compile under Win32.
+  see http://miniupnp.tuxfamily.org/forum/viewtopic.php?t=729
+
+2010/09/17:
+  Various improvement to Makefile from Michał Górny
+
+2010/08/05:
+  Adding the script "external-ip.sh" from Reuben Hawkins
+
+2010/06/09:
+  update to python module to match modification made on 2010/04/05
+  update to Java test code to match modification made on 2010/04/05
+  all UPNP_* function now return an error if the SOAP request failed
+  at HTTP level.
+
+2010/04/17:
+  Using GetBestRoute() under win32 in order to find the
+  right interface to use.
+
+2010/04/12:
+  Retrying with HTTP/1.1 if HTTP/1.0 failed. see
+  http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1703
+
+2010/04/07:
+  avoid returning duplicates in upnpDiscover()
+
+2010/04/05:
+  Create a connecthostport.h/.c with connecthostport() function
+  and use it in miniwget and miniupnpc.
+  Use getnameinfo() instead of inet_ntop or inet_ntoa
+  Work to make miniupnpc IPV6 compatible...
+  Add java test code.
+  Big changes in order to support device having both WANIPConnection
+  and WANPPPConnection.
+
+2010/04/04:
+  Use getaddrinfo() instead of gethostbyname() in miniwget.
+
+2010/01/06:
+  #define _DARWIN_C_SOURCE for Mac OS X
+
+2009/12/19:
+  Improve MinGW32 build
+
+2009/12/11:
+  adding a MSVC9 project to build the static library and executable
+
+2009/12/10:
+  Fixing some compilation stuff for Windows/MinGW
+
+2009/12/07:
+  adaptations in Makefile and updateminiupnpcstring.sh for AmigaOS
+  some fixes for Windows when using virtual ethernet adapters (it is the
+  case with VMWare installed).
+
+2009/12/04:
+  some fixes for AmigaOS compilation
+  Changed HTTP version to HTTP/1.0 for Soap too (to prevent chunked
+  transfer encoding)
+
+2009/12/03:
+  updating printIDG and testigddescparse.c for debug.
+  modifications to compile under AmigaOS
+  adding a testminiwget program
+  Changed miniwget to advertise itself as HTTP/1.0 to prevent chunked
+  transfer encoding
+
+2009/11/26:
+  fixing updateminiupnpcstrings.sh to take into account
+  which command that does not return an error code.
+
+VERSION 1.4 : released 2009/10/30
+
+2009/10/16:
+  using Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS in python module.
+
+2009/10/10:
+  Some fixes for compilation under Solaris
+  compilation fixes : http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1464
+
+2009/09/21:
+  fixing the code to ignore EINTR during connect() calls.
+
+2009/08/07:
+  Set socket timeout for connect()
+  Some cleanup in miniwget.c
+
+2009/08/04:
+  remove multiple redirections with -d in upnpc.c
+  Print textual error code in upnpc.c
+  Ignore EINTR during the connect() and poll() calls.
+
+2009/07/29:
+  fix in updateminiupnpcstrings.sh if OS name contains "/"
+  Sending a correct value for MX: field in SSDP request
+
+2009/07/20:
+  Change the Makefile to compile under Mac OS X
+  Fixed a stackoverflow in getDevicesFromMiniSSDPD()
+
+2009/07/09:
+  Compile under Haiku
+  generate miniupnpcstrings.h.in from miniupnpcstrings.h
+
+2009/06/04:
+  patching to compile under CygWin and cross compile for minGW
+
+VERSION 1.3 :
+
+2009/04/17:
+  updating python module
+  Use strtoull() when using C99
+
+2009/02/28:
+  Fixed miniwget.c for compiling under sun
+
+2008/12/18:
+  cleanup in Makefile (thanks to Paul de Weerd)
+  minissdpc.c : win32 compatibility
+  miniupnpc.c : changed xmlns prefix from 'm' to 'u'
+  Removed NDEBUG (using DEBUG)
+
+2008/10/14:
+  Added the ExternalHost argument to DeletePortMapping()
+
+2008/10/11:
+  Added the ExternalHost argument to AddPortMapping()
+  Put a correct User-Agent: header in HTTP requests.
+
+VERSION 1.2 :
+
+2008/10/07:
+  Update docs
+
+2008/09/25:
+  Integrated sameport patch from Dario Meloni : Added a "sameport"
+  argument to upnpDiscover().
+
+2008/07/18:
+  small modif to make Clang happy :)
+
+2008/07/17:
+  #define SOAPPREFIX "s" in miniupnpc.c in order to remove SOAP-ENV...
+
+2008/07/14:
+  include declspec.h in installation (to /usr/include/miniupnpc)
+
+VERSION 1.1 :
+
+2008/07/04:
+  standard options for install/ln instead of gnu-specific stuff.
+
+2008/07/03:
+  now builds a .dll and .lib with win32. (mingw32)
+
+2008/04/28:
+  make install now install the binary of the upnpc tool
+
+2008/04/27:
+  added testupnpigd.py
+  added error strings for miniupnpc "internal" errors
+  improved python module error/exception reporting.
+
+2008/04/23:
+  Completely rewrite igd_desc_parse.c in order to be compatible with
+  Linksys WAG200G
+  Added testigddescparse
+  updated python module
+
+VERSION 1.0 :
+
+2008/02/21:
+  put some #ifdef DEBUG around DisplayNameValueList()
+
+2008/02/18:
+  Improved error reporting in upnpcommands.c
+  UPNP_GetStatusInfo() returns LastConnectionError
+
+2008/02/16:
+  better error handling in minisoap.c
+  improving display of "valid IGD found" in upnpc.c
+
+2008/02/03:
+  Fixing UPNP_GetValidIGD()
+  improved make install :)
+
+2007/12/22:
+  Adding upnperrors.c/h to provide a strupnperror() function
+  used to translate UPnP error codes to string.
+
+2007/12/19:
+  Fixing getDevicesFromMiniSSDPD()
+  improved error reporting of UPnP functions
+
+2007/12/18:
+  It is now possible to specify a different location for MiniSSDPd socket.
+  working with MiniSSDPd is now more efficient.
+  python module improved.
+
+2007/12/16:
+  improving error reporting
+
+2007/12/13:
+  Try to improve compatibility by using HTTP/1.0 instead of 1.1 and
+  XML a bit different for SOAP.
+
+2007/11/25:
+  fixed select() call for linux
+
+2007/11/15:
+  Added -fPIC to CFLAG for better shared library code.
+
+2007/11/02:
+  Fixed a potential socket leak in miniwget2()
+
+2007/10/16:
+  added a parameter to upnpDiscover() in order to allow the use of another
+  interface than the default multicast interface.
+
+2007/10/12:
+  Fixed the creation of symbolic link in Makefile
+
+2007/10/08:
+  Added man page
+
+2007/10/02:
+  fixed memory bug in GetUPNPUrls()
+
+2007/10/01:
+  fixes in the Makefile
+  Added UPNP_GetIGDFromUrl() and adapted the sample program accordingly.
+  Added SONAME in the shared library to please debian :)
+  fixed MS Windows compilation (minissdpd is not available under MS Windows).
+
+2007/09/25:
+  small change to Makefile to be able to install in a different location
+  (default is /usr)
+
+2007/09/24:
+  now compiling both shared and static library
+
+2007/09/19:
+  Cosmetic changes on upnpc.c
+
+2007/09/02:
+  adapting to new miniSSDPd (release version ?)
+
+2007/08/31:
+  Usage of miniSSDPd to skip discovery process.
+
+2007/08/27:
+  fixed python module to allow compilation with Python older than Python 2.4
+
+2007/06/12:
+  Added a python module.
+
+2007/05/19:
+  Fixed compilation under MinGW
+
+2007/05/15:
+  fixed a memory leak in AddPortMapping()
+  Added testupnpreplyparse executable to check the parsing of
+  upnp soap messages
+  minixml now ignore namespace prefixes.
+
+2007/04/26:
+  upnpc now displays external ip address with -s or -l
+
+2007/04/11:
+  changed MINIUPNPC_URL_MAXSIZE to 128 to accomodate the "BT Voyager 210"
+
+2007/03/19:
+  cleanup in miniwget.c
+
+2007/03/01:
+  Small typo fix...
+
+2007/01/30:
+  Now parsing the HTTP header from SOAP responses in order to
+  get content-length value.
+
+2007/01/29:
+  Fixed the Soap Query to speedup the HTTP request.
+  added some Win32 DLL stuff...
+
+2007/01/27:
+  Fixed some WIN32 compatibility issues
+
+2006/12/14:
+  Added UPNPIGD_IsConnected() function in miniupnp.c/.h
+  Added UPNP_GetValidIGD() in miniupnp.c/.h
+  cleaned upnpc.c main(). now using UPNP_GetValidIGD()
+
+2006/12/07:
+  Version 1.0-RC1 released
+
+2006/12/03:
+  Minor changes to compile under SunOS/Solaris
+
+2006/11/30:
+  made a minixml parser validator program
+  updated minixml to handle attributes correctly
+
+2006/11/22:
+  Added a -r option to the upnpc sample thanks to Alexander Hubmann.
+
+2006/11/19:
+  Cleanup code to make it more ANSI C compliant
+
+2006/11/10:
+  detect and display local lan address.
+
+2006/11/04:
+  Packets and Bytes Sent/Received are now unsigned int.
+
+2006/11/01:
+  Bug fix thanks to Giuseppe D'Angelo
+
+2006/10/31:
+  C++ compatibility for .h files.
+  Added a way to get ip Address on the LAN used to reach the IGD.
+
+2006/10/25:
+  Added M-SEARCH to the services in the discovery process.
+
+2006/10/22:
+  updated the Makefile to use makedepend, added a "make install"
+  update Makefile
+
+2006/10/20:
+  fixing the description url parsing thanks to patch sent by
+  Wayne Dawe.
+  Fixed/translated some comments.
+  Implemented a better discover process, first looking
+  for IGD then for root devices (as some devices only reply to
+  M-SEARCH for root devices).
+
+2006/09/02:
+  added freeUPNPDevlist() function.
+
+2006/08/04:
+  More command line arguments checking
+
+2006/08/01:
+  Added the .bat file to compile under Win32 with minGW32
+
+2006/07/31:
+  Fixed the rootdesc parser (igd_desc_parse.c)
+
+2006/07/20:
+  parseMSEARCHReply() is now returning the ST: line as well
+  starting changes to detect several UPnP devices on the network
+
+2006/07/19:
+  using GetCommonLinkProperties to get down/upload bitrate
+
diff --git a/tools/upnpc/LICENSE b/tools/upnpc/LICENSE
new file mode 100644
index 00000000..240857fc
--- /dev/null
+++ b/tools/upnpc/LICENSE
@@ -0,0 +1,27 @@
+MiniUPnPc
+Copyright (c) 2005-2011, Thomas BERNARD
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * The name of the author may not be used to endorse or promote products
+	  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/tools/upnpc/README b/tools/upnpc/README
new file mode 100644
index 00000000..74306055
--- /dev/null
+++ b/tools/upnpc/README
@@ -0,0 +1,66 @@
+Project: miniupnp
+Project web page: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
+github: https://github.com/miniupnp/miniupnp
+freecode: http://freecode.com/projects/miniupnp
+Author: Thomas Bernard
+Copyright (c) 2005-2012 Thomas Bernard
+This software is subject to the conditions detailed in the
+LICENSE file provided within this distribution.
+
+
+For the comfort of Win32 users, bsdqueue.h is included in the distribution.
+Its licence is included in the header of the file.
+bsdqueue.h is a copy of the sys/queue.h of an OpenBSD system.
+
+
+* miniUPnP Client - miniUPnPc *
+
+To compile, simply run 'gmake' (could be 'make' on your system).
+Under win32, to compile with MinGW, type "mingw32make.bat".
+MS Visual C solution and project files are supplied in the msvc/ subdirectory.
+
+The compilation is known to work under linux, FreeBSD,
+OpenBSD, MacOS X, AmigaOS and cygwin.
+The official AmigaOS4.1 SDK was used for AmigaOS4 and GeekGadgets for AmigaOS3.
+upx (http://upx.sourceforge.net) is used to compress the win32 .exe files.
+
+To install the library and headers on the system use :
+> su
+> make install
+> exit
+
+alternatively, to install into a specific location, use :
+> INSTALLPREFIX=/usr/local make install
+
+upnpc.c is a sample client using the libminiupnpc.
+To use the libminiupnpc in your application, link it with
+libminiupnpc.a (or .so) and use the following functions found in miniupnpc.h,
+upnpcommands.h and miniwget.h :
+- upnpDiscover()
+- miniwget()
+- parserootdesc()
+- GetUPNPUrls()
+- UPNP_* (calling UPNP methods)
+
+Note : use #include <miniupnpc/miniupnpc.h> etc... for the includes
+and -lminiupnpc for the link
+
+Discovery process is speeded up when MiniSSDPd is running on the machine.
+
+
+* Python module *
+
+you can build a python module with 'make pythonmodule'
+and install it with 'make installpythonmodule'.
+setup.py (and setupmingw32.py) are included in the distribution.
+
+
+Feel free to contact me if you have any problem :
+e-mail : miniupnp@free.fr
+
+If you are using libminiupnpc in your application, please
+send me an email !
+
+For any question, you can use the web forum :
+http://miniupnp.tuxfamily.org/forum/
+
diff --git a/tools/upnpc/libminiupnpc.a b/tools/upnpc/libminiupnpc.a
new file mode 100644
index 00000000..63c1f171
Binary files /dev/null and b/tools/upnpc/libminiupnpc.a differ
diff --git a/tools/upnpc/miniupnpc.def b/tools/upnpc/miniupnpc.def
new file mode 100644
index 00000000..5a9f9e20
--- /dev/null
+++ b/tools/upnpc/miniupnpc.def
@@ -0,0 +1,43 @@
+LIBRARY
+; miniupnpc library
+   miniupnpc
+
+EXPORTS
+; miniupnpc
+   upnpDiscover
+   freeUPNPDevlist
+   parserootdesc
+   UPNP_GetValidIGD
+   UPNP_GetIGDFromUrl
+   GetUPNPUrls
+   FreeUPNPUrls
+; miniwget
+   miniwget
+   miniwget_getaddr
+; upnpcommands
+   UPNP_GetTotalBytesSent
+   UPNP_GetTotalBytesReceived
+   UPNP_GetTotalPacketsSent
+   UPNP_GetTotalPacketsReceived
+   UPNP_GetStatusInfo
+   UPNP_GetConnectionTypeInfo
+   UPNP_GetExternalIPAddress
+   UPNP_GetLinkLayerMaxBitRates
+   UPNP_AddPortMapping
+   UPNP_DeletePortMapping
+   UPNP_GetPortMappingNumberOfEntries
+   UPNP_GetSpecificPortMappingEntry
+   UPNP_GetGenericPortMappingEntry
+   UPNP_GetListOfPortMappings
+   UPNP_AddPinhole
+   UPNP_CheckPinholeWorking
+   UPNP_UpdatePinhole
+   UPNP_GetPinholePackets
+   UPNP_DeletePinhole
+   UPNP_GetFirewallStatus
+   UPNP_GetOutboundPinholeTimeout
+; upnperrors
+   strupnperror
+; portlistingparse
+   ParsePortListing
+   FreePortListing
diff --git a/tools/upnpc/miniupnpc.dll b/tools/upnpc/miniupnpc.dll
new file mode 100644
index 00000000..a5ae0667
Binary files /dev/null and b/tools/upnpc/miniupnpc.dll differ
diff --git a/tools/upnpc/miniupnpc.lib b/tools/upnpc/miniupnpc.lib
new file mode 100644
index 00000000..4e8ee76c
Binary files /dev/null and b/tools/upnpc/miniupnpc.lib differ
diff --git a/tools/upnpc/upnpc-shared.exe b/tools/upnpc/upnpc-shared.exe
new file mode 100644
index 00000000..b3cfc2d3
Binary files /dev/null and b/tools/upnpc/upnpc-shared.exe differ
diff --git a/tools/upnpc/upnpc-static.exe b/tools/upnpc/upnpc-static.exe
new file mode 100644
index 00000000..7b315990
Binary files /dev/null and b/tools/upnpc/upnpc-static.exe differ
diff --git a/zeronet.py b/zeronet.py
new file mode 100644
index 00000000..d0b0cf79
--- /dev/null
+++ b/zeronet.py
@@ -0,0 +1,7 @@
+from src import main
+
+action_func = getattr(main, main.config.action)
+action_kwargs = main.config.getActionArguments()
+
+action_func(**action_kwargs)
+