diff --git a/README b/README deleted file mode 100644 index f06c9e78..00000000 --- a/README +++ /dev/null @@ -1,112 +0,0 @@ -Requirements: -------------------------- -Generic: -* Bitcoin >=0.11.1 -* Python >=2.6 -* Twisted >=10.0.0 - -Linux: -* sudo apt-get install python-rrdtool python-pygame python-scipy python-twisted python-twisted-web python-pil - -Windows: -* Install Python 2.7: http://www.python.org/getit/ -* Install Twisted: http://twistedmatrix.com/trac/wiki/Downloads -* Install Zope.Interface: http://pypi.python.org/pypi/zope.interface/3.8.0 -* Install python win32 api: http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/ -* Install python win32 api wmi wrapper: https://pypi.python.org/pypi/WMI/#downloads -* Unzip the files into C:\Python27\Lib\site-packages - -Running P2Pool: -------------------------- -To use P2Pool, you must be running your own local bitcoind. For standard -configurations, using P2Pool should be as simple as: - - cd lyra2re-hash-python - git submodule init - git submodule update - sudo python setup.py install - cd ../ - python run_p2pool.py --net vertcoin - -Then run your miner program, connecting to 127.0.0.1 on port 9171 with any -username and password. - -If you are behind a NAT, you should enable TCP port forwarding on your -router. Forward port 9346 to the host running P2Pool. - -Run for additional options. - - python run_p2pool.py --help - -Donations towards further development: -------------------------- - 1HNeqi3pJRNvXybNX4FKzZgYJsdTSqJTbk - -Official wiki: -------------------------- -https://en.bitcoin.it/wiki/P2Pool - -Alternate web frontend: -------------------------- -* https://github.com/hardcpp/P2PoolExtendedFrontEnd - -Notes for Litecoin: -========================= -Requirements: -------------------------- -In order to run P2Pool with the Litecoin network, you would need to build and install the -ltc_scrypt module that includes the scrypt proof of work code that Litecoin uses for hashes. - -Linux: - - cd litecoin_scrypt - sudo python setup.py install - -Windows (mingw): -* Install MinGW: http://www.mingw.org/wiki/Getting_Started -* Install Python 2.7: http://www.python.org/getit/ - -In bash type this: - - cd litecoin_scrypt - C:\Python27\python.exe setup.py build --compile=mingw32 install - -Windows (Microsoft Visual C++) -* Open visual studio console - -In bash type this: - - SET VS90COMNTOOLS=%VS110COMNTOOLS% # For visual c++ 2012 - SET VS90COMNTOOLS=%VS100COMNTOOLS% # For visual c++ 2010 - cd litecoin_scrypt - C:\Python27\python.exe setup.py build --compile=mingw32 install - -If you run into an error with unrecognized command line option '-mno-cygwin', see this: -http://stackoverflow.com/questions/6034390/compiling-with-cython-and-mingw-produces-gcc-error-unrecognized-command-line-o - -Running P2Pool: -------------------------- -Run P2Pool with the "--net litecoin" option. -Run your miner program, connecting to 127.0.0.1 on port 9327. -Forward port 9338 to the host running P2Pool. - -Litecoin's use of ports 9333 and 9332 conflicts with P2Pool running on -the Bitcoin network. To avoid problems, add these lines to litecoin.conf -and restart litecoind: - - rpcport=10332 - port=10333 - -Sponsors: -------------------------- - -Thanks to: -* The Bitcoin Foundation for its generous support of P2Pool -* The Litecoin Project for its generous donations to P2Pool - -License: -------------------------- - -[Available here](COPYING) - - diff --git a/README.md b/README.md index f06c9e78..d7e9de5e 100644 --- a/README.md +++ b/README.md @@ -1,112 +1,91 @@ -Requirements: -------------------------- -Generic: -* Bitcoin >=0.11.1 -* Python >=2.6 -* Twisted >=10.0.0 - -Linux: -* sudo apt-get install python-rrdtool python-pygame python-scipy python-twisted python-twisted-web python-pil - -Windows: -* Install Python 2.7: http://www.python.org/getit/ -* Install Twisted: http://twistedmatrix.com/trac/wiki/Downloads -* Install Zope.Interface: http://pypi.python.org/pypi/zope.interface/3.8.0 -* Install python win32 api: http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/ -* Install python win32 api wmi wrapper: https://pypi.python.org/pypi/WMI/#downloads -* Unzip the files into C:\Python27\Lib\site-packages +**P2pool installation with pypy -- Windows** -Running P2Pool: -------------------------- -To use P2Pool, you must be running your own local bitcoind. For standard -configurations, using P2Pool should be as simple as: - cd lyra2re-hash-python - git submodule init - git submodule update - sudo python setup.py install - cd ../ - python run_p2pool.py --net vertcoin +On Windows, pypy is only supported via the Windows Subsystem for Linux (WSL). P2pool on pypy on WSL is much faster than P2pool on +CPython on native Windows. To install WSL, first follow the steps outlined here: -Then run your miner program, connecting to 127.0.0.1 on port 9171 with any -username and password. -If you are behind a NAT, you should enable TCP port forwarding on your -router. Forward port 9346 to the host running P2Pool. +https://msdn.microsoft.com/en-us/commandline/wsl/install_guide -Run for additional options. - python run_p2pool.py --help +Once you've done that, run bash and follow the rest of the steps below. -Donations towards further development: -------------------------- - 1HNeqi3pJRNvXybNX4FKzZgYJsdTSqJTbk -Official wiki: -------------------------- -https://en.bitcoin.it/wiki/P2Pool +**P2pool installation with pypy -- Linux and Windows** -Alternate web frontend: -------------------------- -* https://github.com/hardcpp/P2PoolExtendedFrontEnd -Notes for Litecoin: -========================= -Requirements: -------------------------- -In order to run P2Pool with the Litecoin network, you would need to build and install the -ltc_scrypt module that includes the scrypt proof of work code that Litecoin uses for hashes. +Copy and paste the following commands into a bash shell in order to install p2pool on Windows or Linux. -Linux: +>sudo apt-get update - cd litecoin_scrypt - sudo python setup.py install +>sudo apt-get install pypy pypy-dev pypy-setuptools gcc build-essential git -Windows (mingw): -* Install MinGW: http://www.mingw.org/wiki/Getting_Started -* Install Python 2.7: http://www.python.org/getit/ -In bash type this: +>wget https://bootstrap.pypa.io/ez_setup.py -O - | sudo pypy +>sudo rm setuptools-*.zip - cd litecoin_scrypt - C:\Python27\python.exe setup.py build --compile=mingw32 install -Windows (Microsoft Visual C++) -* Open visual studio console +>wget https://files.pythonhosted.org/packages/84/21/80cdc749908ebf2719a9063eddcc02b668fbc62d200c1f1a4d92aaaba76b/zope.interface-5.2.0.tar.gz +tar zxf zope.interface-5.2.0.tar.gz -In bash type this: +>cd zope.interface-5.2.0/ - SET VS90COMNTOOLS=%VS110COMNTOOLS% # For visual c++ 2012 - SET VS90COMNTOOLS=%VS100COMNTOOLS% # For visual c++ 2010 - cd litecoin_scrypt - C:\Python27\python.exe setup.py build --compile=mingw32 install - -If you run into an error with unrecognized command line option '-mno-cygwin', see this: -http://stackoverflow.com/questions/6034390/compiling-with-cython-and-mingw-produces-gcc-error-unrecognized-command-line-o +>sudo pypy setup.py install -Running P2Pool: -------------------------- -Run P2Pool with the "--net litecoin" option. -Run your miner program, connecting to 127.0.0.1 on port 9327. -Forward port 9338 to the host running P2Pool. +>cd .. -Litecoin's use of ports 9333 and 9332 conflicts with P2Pool running on -the Bitcoin network. To avoid problems, add these lines to litecoin.conf -and restart litecoind: +>sudo rm -r zope.interface-5.2.0* - rpcport=10332 - port=10333 -Sponsors: -------------------------- +>wget https://files.pythonhosted.org/packages/4a/b4/4973c7ccb5be2ec0abc779b7d5f9d5f24b17b0349e23240cfc9dc3bd83cc/Twisted-20.3.0.tar.bz2 -Thanks to: -* The Bitcoin Foundation for its generous support of P2Pool -* The Litecoin Project for its generous donations to P2Pool - -License: -------------------------- +>tar jxf Twisted-20.3.0.tar.bz2 -[Available here](COPYING) +>cd Twisted-20.3.0 +>sudo pypy setup.py install +>cd .. + +>sudo rm -r Twisted-20.3.0* + + +>git clone https://github.com/vertcoin-project/p2pool-vtc + + +You'll also need to install and run your vertcoind, and edit ~/.vertcoin/vertcoin.conf with your vertcoind's RPC username and password. Launch your vertcoind, and after it has finished downloading blocks and syncing, go to your p2pool directory and run + + +>pypy run_p2pool.py + + +**Miner setup** + + +P2pool communicates with miners via the stratum protocol. For VTC, configure your miners with the following information: + + +>URL: stratum+tcp://(Your node's IP address or hostname):9171 + +>Worker: (Your bitcoin address) + +>Password: x + + +For Litecoin, replace 9332 with 9327. For Bitcoin Cash, use 9348. + + +Mining to Legacy (P2PKH), SegWit/MultiSig (P2SH) and Bech32 addresses are supported for the following coins with the specified address prefixes: + +|Coin |P2PKH |P2SH |Bech32 | +|---------------|-------|-------|-------------------------------| +|Vertcoin |`V...` |`3...` |`vtc...` | + + +If you wish to modify the mining difficulty, you may add something like "address+1" after your mining address to set the pseudoshare difficulty to 1, or "address/10" to set the actual share difficulty to 10 or the p2pool minimum share difficulty, whichever is higher. Pseudoshares only affect hashrate statistics, whereas actual shares affect revenue variance and efficiency. + + +**Firewall considerations** + + +If your node is behind a firewall or behind NAT (i.e. on a private IP address), you may want to forward ports to your p2pool server. P2pool uses two ports: one for p2p communication with the p2pool network, and another for both the web UI and for stratum communication with workers. For Vertcoin, those ports are 9346 (p2p) and 9171 (stratum/web). diff --git a/p2pool/bitcoin/data.py b/p2pool/bitcoin/data.py index a897d7a7..73e3ef78 100644 --- a/p2pool/bitcoin/data.py +++ b/p2pool/bitcoin/data.py @@ -3,13 +3,30 @@ import hashlib import random import warnings +import binascii import p2pool -from p2pool.util import math, pack, segwit_addr +from p2pool.util import math, pack, segwit_addr, cash_addr +import struct + +mask = (1<<64) - 1 def hash256(data): return pack.IntType(256).unpack(hashlib.sha256(hashlib.sha256(data).digest()).digest()) +def pack256(data): + if data is None: + data = 0 + return struct.pack(">64 & mask, data>>128 & mask, + data>>192 & mask) + +def unpack256(data): + raw = struct.unpack(" 1: - hash_list = [ - ( - lambda _left=left, _right=right: hash256(merkle_record_type.pack(dict(left=_left(), right=_right()))), - left_f or right_f, - (left_l if left_f else right_l) + [dict(side=1, hash=right) if left_f else dict(side=0, hash=left)], - ) - for (left, left_f, left_l), (right, right_f, right_l) in - zip(hash_list[::2], hash_list[1::2] + [hash_list[::2][-1]]) - ] - - res = [x['hash']() for x in hash_list[0][2]] - - assert hash_list[0][1] - if p2pool.DEBUG: - new_hashes = [random.randrange(2**256) if x is None else x - for x in hashes] - assert check_merkle_link(new_hashes[index], dict(branch=res, index=index)) == merkle_hash(new_hashes) - assert index == sum(k*2**i for i, k in enumerate([1-x['side'] for x in hash_list[0][2]])) - - return dict(branch=res, index=index) + assert index < len(hashes) + merkle_nodes = [MerkleNode(pack256(x)) for x in hashes] + merkle_tree = build_merkle_tree(merkle_nodes) + merkle_branch = [] + index_node = merkle_nodes[index] + while index_node.parent: + merkle_branch.append(unpack256(index_node.get_sibling().hash)) + index_node = index_node.parent + return {'index': index, 'branch': merkle_branch} def check_merkle_link(tip_hash, link): if link['index'] >= 2**len(link['branch']): @@ -294,16 +378,6 @@ def difficulty_to_target(difficulty): assert difficulty >= 0 if difficulty == 0: return 2**256-1 return min(int((0xffff0000 * 2**(256-64) + 1)/difficulty - 1 + 0.5), 2**256-1) - -def target_to_difficulty_alt(target, modifier): - assert 0 <= target and isinstance(target, (int, long)), target - if target >= 2**256: warnings.warn('target >= 2**256!') - return ((0xffff0000 * 2**(256-64) + 1)/(target + 1)) * modifier - -def difficulty_to_target_alt(difficulty, modifier): - assert difficulty >= 0 - if difficulty == 0: return 2**256-1 - return min(int((0xffff0000 * 2**(256-64) + 1)/(difficulty / modifier) - 1 + 0.5), 2**256-1) # human addresses @@ -322,31 +396,80 @@ def base58_decode(b58data): ('pubkey_hash', pack.IntType(160)), ])) -def pubkey_hash_to_address(pubkey_hash, net, version=None): - if version == None: - version = net.ADDRESS_VERSION - - if version == 0: - return segwit_addr.encode(net.HUMAN_READABLE_PART, 0, [int(x) for x in bytearray.fromhex(hex(pubkey_hash)[2:-1])]) - return base58_encode(human_address_type.pack(dict(version=version, pubkey_hash=pubkey_hash))) +def pubkey_hash_to_address(pubkey_hash, addr_ver, bech32_ver, net): + if addr_ver == -1: + if hasattr(net, 'padding_bugfix') and net.padding_bugfix: + thash = '{:040x}'.format(pubkey_hash) + else: + thash = '{:x}'.format(pubkey_hash) + if len(thash) % 2 == 1: + thash = '0%s' % thash + data = [int(x) for x in bytearray.fromhex(thash)] + if net.SYMBOL.lower() in ['bch', 'tbch', 'bsv', 'tbsv']: + return cash_addr.encode(net.HUMAN_READABLE_PART, bech32_ver, data) + else: + return segwit_addr.encode(net.HUMAN_READABLE_PART, bech32_ver, data) + return base58_encode(human_address_type.pack(dict(version=addr_ver, pubkey_hash=pubkey_hash))) def pubkey_to_address(pubkey, net): - return pubkey_hash_to_address(hash160(pubkey), net) + return pubkey_hash_to_address(hash160(pubkey), net.ADDRESS_VERSION, -1, net) + +class AddrError(Exception): + __slots__ = () + +def address_to_script2(address, net): + res = address_to_pubkey_hash(address, net) + return pubkey_hash_to_script2(res[0], res[1], res[2], net) def address_to_pubkey_hash(address, net): + try: + return get_legacy_pubkey_hash(address, net) + except AddrError: + pass + + if net.SYMBOL.lower() not in ['bch', 'tbch', 'bsv', 'tbsv']: + try: + return get_bech32_pubkey_hash(address, net) + except AddrError: + pass + else: + try: + return get_cashaddr_pubkey_hash(address, net) + except AddrError: + pass + raise ValueError('invalid addr') + +def get_legacy_pubkey_hash(address, net): + # P2PKH or P2SH address try: base_decode = base58_decode(address) x = human_address_type.unpack(base_decode) - if x['version'] != net.ADDRESS_VERSION and x['version'] != net.SEGWIT_ADDRESS_VERSION: + except Exception as e: + raise AddrError + else: + if x['version'] != net.ADDRESS_VERSION and x['version'] != net.ADDRESS_P2SH_VERSION: raise ValueError('address not for this net!') - return x['pubkey_hash'], x['version'] - except Exception, e: - try: - hrp, pubkey_hash = segwit_addr.bech32_decode(address) - witver, witprog = segwit_addr.decode(net.HUMAN_READABLE_PART, address) - return int(''.join('{:02x}'.format(x) for x in witprog), 16), 0 - except Exception, e: - raise ValueError('invalid addr') + return x['pubkey_hash'], x['version'], -1 + +def get_bech32_pubkey_hash(address, net): + try: + witver, witprog = segwit_addr.decode(net.HUMAN_READABLE_PART, address) + if witver is None or witprog is None: + raise ValueError + except Exception as e: + raise AddrError + else: + return int(''.join('{:02x}'.format(x) for x in witprog), 16), -1, witver + +def get_cashaddr_pubkey_hash(address, net): + try: + ver, data = cash_addr.decode(net.HUMAN_READABLE_PART, address) + if ver is None or data is None: + raise ValueError + except Exception as e: + raise AddrError + else: + return int(''.join('{:02x}'.format(x) for x in data), 16), -1, ver # transactions @@ -370,49 +493,104 @@ def pubkey_to_script2(pubkey): assert len(pubkey) <= 75 return (chr(len(pubkey)) + pubkey) + '\xac' -def pubkey_hash_to_script2(pubkey_hash, version, net): - if version == 0: - return '\x00\x14' + hex(pubkey_hash)[2:-1].decode("hex") - if version == net.SEGWIT_ADDRESS_VERSION: +def pubkey_hash_to_script2(pubkey_hash, version, bech32_version, net): + if version == -1 and bech32_version >= 0: + if hasattr(net, 'padding_bugfix') and net.padding_bugfix: + decoded = '{:040x}'.format(pubkey_hash) + else: + decoded = '{:x}'.format(pubkey_hash) + ehash = binascii.unhexlify(decoded) + size = '{:x}'.format(len(decoded) // 2) + if len(size) % 2 == 1: + size = '0%s' % size + hsize = binascii.unhexlify(size) + if net.SYMBOL.lower() in ['bch', 'tbch', 'bsv', 'tbsv']: + # CashAddrs can be longer than 20 bytes + # TODO: Check the version and restrict the bytes. + if bech32_version == 0: + # P2KH + return '\x76\xa9%s%s\x88\xac' % (hsize, ehash) + elif bech32_version == 1: + # P2SH + return '\xa9%s%s\x87' % (hsize, ehash) + else: + raise NotImplementedError("Invalid cashaddr type %d" % bech32_version) + else: + return '\x00%s%s' % (hsize, ehash) + if version == net.ADDRESS_P2SH_VERSION: return ('\xa9\x14' + pack.IntType(160).pack(pubkey_hash)) + '\x87' - return '\x76\xa9' + ('\x14' + pack.IntType(160).pack(pubkey_hash)) + '\x88\xac' + return '\x76\xa9' + ('\x14' + pack.IntType(160).pack(pubkey_hash)) + '\x88\xac' -def script2_to_address(script2, net): +def script2_to_address(script2, addr_ver, bech32_ver, net): + try: + return script2_to_pubkey_address(script2, net) + except AddrError: + pass + for func in [script2_to_pubkey_hash_address, script2_to_bech32_address, + script2_to_p2sh_address, script2_to_cashaddress]: + try: + return func(script2, addr_ver, bech32_ver, net) + except AddrError: + pass + raise ValueError("Invalid script2 hash %s" % binascii.hexlify(script2)) + +def script2_to_pubkey_address(script2, net): try: pubkey = script2[1:-1] - script2_test = pubkey_to_script2(pubkey) + res = pubkey_to_script2(pubkey) + if res != script2: + raise ValueError except: - pass - else: - if script2_test == script2: - return pubkey_to_address(pubkey, net) + raise AddrError + return pubkey_to_address(pubkey, net) +def script2_to_pubkey_hash_address(script2, addr_ver, bech32_ver, net): + # TODO: Check for BCH and BSV length, could be longer than 20 bytes try: pubkey_hash = pack.IntType(160).unpack(script2[3:-2]) - script2_test2 = pubkey_hash_to_script2(pubkey_hash, net.ADDRESS_VERSION, net) - except: - pass - else: - if script2_test2 == script2: - return pubkey_hash_to_address(pubkey_hash, net) - + res = pubkey_hash_to_script2(pubkey_hash, addr_ver, bech32_ver, net) + if res != script2: + raise ValueError + except Exception as e: + raise AddrError + return pubkey_hash_to_address(pubkey_hash, addr_ver, bech32_ver, net) + +def script2_to_cashaddress(script2, addr_ver, ca_ver, net): + try: + if ca_ver == 0: + sub_hash = script2[3:-2] + elif ca_ver == 1: + sub_hash = script2[2:-1] + else: + raise ValueError + pubkey_hash = int(sub_hash.encode('hex'), 16) + res = pubkey_hash_to_script2(pubkey_hash, addr_ver, ca_ver, net) + if res != script2: + raise ValueError + except Exception as e: + raise AddrError + return pubkey_hash_to_address(pubkey_hash, addr_ver, ca_ver, net) + +def script2_to_bech32_address(script2, addr_ver, bech32_ver, net): try: pubkey_hash = int(script2[2:].encode('hex'), 16) - script2_test3 = pubkey_hash_to_script2(pubkey_hash, 0, net) - except: - pass - else: - if script2_test3 == script2: - return pubkey_hash_to_address(pubkey_hash, net, 0) - + res = pubkey_hash_to_script2(pubkey_hash, addr_ver, bech32_ver, net) + if res != script2: + raise ValueError + except Exception as e: + raise AddrError + return pubkey_hash_to_address(pubkey_hash, addr_ver, bech32_ver, net) + +def script2_to_p2sh_address(script2, addr_ver, bech32_ver, net): + # TODO: Check for BCH and BSV length, could be longer than 20 bytes try: pubkey_hash = pack.IntType(160).unpack(script2[2:-1]) - script2_test4 = pubkey_hash_to_script2(pubkey_hash, net.SEGWIT_ADDRESS_VERSION, net) - except: - pass - else: - if script2_test4 == script2: - return pubkey_hash_to_address(pubkey_hash, net, net.SEGWIT_ADDRESS_VERSION) + res = pubkey_hash_to_script2(pubkey_hash, addr_ver, bech32_ver, net) + if res != script2: + raise ValueError + except Exception as e: + raise AddrError + return pubkey_hash_to_address(pubkey_hash, addr_ver, bech32_ver, net) def script2_to_human(script2, net): try: diff --git a/p2pool/bitcoin/height_tracker.py b/p2pool/bitcoin/height_tracker.py index 28a20119..bbeae014 100644 --- a/p2pool/bitcoin/height_tracker.py +++ b/p2pool/bitcoin/height_tracker.py @@ -87,30 +87,39 @@ def get_height_rel_highest(self, block_hash): if last != best_last: return -1000000000 # XXX hack return height - best_height + def get_height(self, block_hash): + # callers: highest height can change during yields! + height, last = self._tracker.get_height_and_last(block_hash) + return height @defer.inlineCallbacks -def get_height_rel_highest_func(bitcoind, factory, best_block_func, net): - if '\ngetblock ' in (yield deferral.retry()(bitcoind.rpc_help)()): +def get_height_funcs(bitcoind, factory, best_block_func, net): + cached_heights = {} + if '\ngetblockheader ' in (yield deferral.retry()(bitcoind.rpc_help)()): @deferral.DeferredCacher @defer.inlineCallbacks def height_cacher(block_hash): - try: - block_hash_str = '%x' % (block_hash,) - if len(block_hash_str) != 64: - block_hash_str = '0' * (64 - len(block_hash_str)) + block_hash_str - x = yield bitcoind.rpc_getblock(block_hash_str) - except jsonrpc.Error_for_code(-5): # Block not found - if not p2pool.DEBUG: - raise deferral.RetrySilentlyException() - else: - raise - defer.returnValue(x['blockcount'] if 'blockcount' in x else x['height']) + if not block_hash in cached_heights: + try: + x = yield bitcoind.rpc_getblockheader('%064x' % (block_hash,)) + except jsonrpc.Error_for_code(-5): # Block not found + if not p2pool.DEBUG: + raise deferral.RetrySilentlyException() + else: + raise + cached_heights[block_hash] = x['blockcount'] if 'blockcount' in x else x['height'] + defer.returnValue(cached_heights[block_hash]) best_height_cached = variable.Variable((yield deferral.retry()(height_cacher)(best_block_func()))) def get_height_rel_highest(block_hash): this_height = height_cacher.call_now(block_hash, 0) best_height = height_cacher.call_now(best_block_func(), 0) best_height_cached.set(max(best_height_cached.value, this_height, best_height)) return this_height - best_height_cached.value + def get_height(block_hash): + this_height = height_cacher.call_now(block_hash, 0) + return this_height else: get_height_rel_highest = HeightTracker(best_block_func, factory, 5*net.SHARE_PERIOD*net.CHAIN_LENGTH/net.PARENT.BLOCK_PERIOD).get_height_rel_highest - defer.returnValue(get_height_rel_highest) + get_height = HeightTracker(best_block_func, factory, 5*net.SHARE_PERIOD*net.CHAIN_LENGTH/net.PARENT.BLOCK_PERIOD).get_height + defer.returnValue((get_height_rel_highest, get_height)) + diff --git a/p2pool/bitcoin/helper.py b/p2pool/bitcoin/helper.py index aab27ea0..6255d1e5 100644 --- a/p2pool/bitcoin/helper.py +++ b/p2pool/bitcoin/helper.py @@ -6,12 +6,13 @@ import p2pool from p2pool.bitcoin import data as bitcoin_data from p2pool.util import deferral, jsonrpc +txlookup = {} @deferral.retry('Error while checking Bitcoin connection:', 1) @defer.inlineCallbacks -def check(bitcoind, net): +def check(bitcoind, net, args): if not (yield net.PARENT.RPC_CHECK(bitcoind)): - print >>sys.stderr, " Check failed! Make sure that you're connected to the right bitcoind with --bitcoind-rpc-port!" + print >>sys.stderr, " Check failed! Make sure that you're connected to the right bitcoind with --bitcoind-rpc-port, and that it has finished syncing!" raise deferral.RetrySilentlyException() version_check_result = net.VERSION_CHECK((yield bitcoind.rpc_getnetworkinfo())['version']) @@ -23,20 +24,31 @@ def check(bitcoind, net): try: blockchaininfo = yield bitcoind.rpc_getblockchaininfo() - softforks_supported = set(item['id'] for item in blockchaininfo.get('softforks', [])) + try: + softforks_supported = set(item['id'] for item in blockchaininfo.get('softforks', [])) # not working with 0.19.0.1 + except TypeError: + softforks_supported = set(item for item in blockchaininfo.get('softforks', [])) # fix for https://github.com/jtoomim/p2pool/issues/38 try: softforks_supported |= set(item['id'] for item in blockchaininfo.get('bip9_softforks', [])) except TypeError: # https://github.com/bitcoin/bitcoin/pull/7863 softforks_supported |= set(item for item in blockchaininfo.get('bip9_softforks', [])) except jsonrpc.Error_for_code(-32601): # Method not found softforks_supported = set() - if getattr(net, 'SOFTFORKS_REQUIRED', set()) - softforks_supported: - print 'Coin daemon too old! Upgrade!' - raise deferral.RetrySilentlyException() + unsupported_forks = getattr(net, 'SOFTFORKS_REQUIRED', set()) - softforks_supported + if unsupported_forks: + print "You are running a coin daemon that does not support all of the " + print "forking features that have been activated on this blockchain." + print "Consequently, your node may mine invalid blocks or may mine blocks that" + print "are not part of the Nakamoto consensus blockchain.\n" + print "Missing fork features:", ', '.join(unsupported_forks) + if not args.allow_obsolete_bitcoind: + print "\nIf you know what you're doing, this error may be overridden by running p2pool" + print "with the '--allow-obsolete-bitcoind' command-line option.\n\n\n" + raise deferral.RetrySilentlyException() @deferral.retry('Error getting work from bitcoind:', 3) @defer.inlineCallbacks -def getwork(bitcoind, use_getblocktemplate=False): +def getwork(bitcoind, use_getblocktemplate=False, txidcache={}, feecache={}, feefifo=[], known_txs={}): def go(): if use_getblocktemplate: return bitcoind.rpc_getblocktemplate(dict(mode='template', rules=['segwit'])) @@ -55,16 +67,66 @@ def go(): except jsonrpc.Error_for_code(-32601): # Method not found print >>sys.stderr, 'Error: Bitcoin version too old! Upgrade to v0.5 or newer!' raise deferral.RetrySilentlyException() - packed_transactions = [(x['data'] if isinstance(x, dict) else x).decode('hex') for x in work['transactions']] + + if not 'start' in txidcache: # we clear it every 30 min + txidcache['start'] = time.time() + + t0 = time.time() + unpacked_transactions = [] + txhashes = [] + cachehits = 0 + cachemisses = 0 + knownhits = 0 + knownmisses = 0 + for x in work['transactions']: + fee = x['fee'] + x = x['data'] if isinstance(x, dict) else x + packed = None + if x in txidcache: + cachehits += 1 + txid = (txidcache[x]) + txhashes.append(txid) + else: + cachemisses += 1 + packed = x.decode('hex') + txid = bitcoin_data.hash256(packed) + txidcache[x] = txid + txhashes.append(txid) + if txid in known_txs: + knownhits += 1 + unpacked = known_txs[txid] + else: + knownmisses += 1 + if not packed: + packed = x.decode('hex') + unpacked = bitcoin_data.tx_type.unpack(packed) + unpacked_transactions.append(unpacked) + # The only place where we can get information on transaction fees is in GBT results, so we need to store those + # for a while so we can spot shares that miscalculate the block reward + if not txid in feecache: + feecache[txid] = fee + feefifo.append(txid) + + if time.time() - txidcache['start'] > 30*60.: + keepers = {(x['data'] if isinstance(x, dict) else x):txid for x, txid in zip(work['transactions'], txhashes)} + txidcache.clear() + txidcache.update(keepers) + # limit the fee cache to 100,000 entries, which should be about 10-20 MB + fum = 100000 + while len(feefifo) > fum: + del feecache[feefifo.pop(0)] if 'height' not in work: work['height'] = (yield bitcoind.rpc_getblock(work['previousblockhash']))['height'] + 1 elif p2pool.DEBUG: assert work['height'] == (yield bitcoind.rpc_getblock(work['previousblockhash']))['height'] + 1 + + t1 = time.time() + if p2pool.BENCH: print "%8.3f ms for helper.py:getwork(). Cache: %i hits %i misses, %i known_tx %i unknown %i cached" % ((t1 - t0)*1000., cachehits, cachemisses, knownhits, knownmisses, len(txidcache)) defer.returnValue(dict( version=work['version'], previous_block=int(work['previousblockhash'], 16), - transactions=map(bitcoin_data.tx_type.unpack, packed_transactions), - transaction_hashes=map(bitcoin_data.hash256, packed_transactions), + transactions=unpacked_transactions, + transaction_hashes=txhashes, transaction_fees=[x.get('fee', None) if isinstance(x, dict) else None for x in work['transactions']], subsidy=work['coinbasevalue'], time=work['time'] if 'time' in work else work['curtime'], @@ -102,14 +164,15 @@ def submit_block_rpc(block, ignore_failure, bitcoind, bitcoind_work, net): if (not success and success_expected and not ignore_failure) or (success and not success_expected): print >>sys.stderr, 'Block submittal result: %s (%r) Expected: %s' % (success, result, success_expected) -def submit_block(block, ignore_failure, factory, bitcoind, bitcoind_work, net): - submit_block_p2p(block, factory, net) - submit_block_rpc(block, ignore_failure, bitcoind, bitcoind_work, net) +def submit_block(block, ignore_failure, node): + submit_block_p2p(block, node.factory, node.net) + submit_block_rpc(block, ignore_failure, node.bitcoind, node.bitcoind_work, + node.net) @defer.inlineCallbacks -def check_genesis_block(bitcoind, genesis_block_hash): +def check_block_header(bitcoind, block_hash): try: - yield bitcoind.rpc_getblock(genesis_block_hash) + yield bitcoind.rpc_getblockheader(block_hash) except jsonrpc.Error_for_code(-5): defer.returnValue(False) else: diff --git a/p2pool/bitcoin/networks/vertcoin.py b/p2pool/bitcoin/networks/vertcoin.py index 51993fc7..1655cd03 100644 --- a/p2pool/bitcoin/networks/vertcoin.py +++ b/p2pool/bitcoin/networks/vertcoin.py @@ -20,22 +20,26 @@ def verthash_hash(dat): return verthash.getPoWHash(dat, verthash_data) - -P2P_PREFIX='fabfb5da'.decode('hex') -P2P_PORT=5889 -ADDRESS_VERSION=71 -SEGWIT_ADDRESS_VERSION=5 -RPC_PORT=5888 -RPC_CHECK=lambda bitcoind: True -SUBSIDY_FUNC=lambda height: 50*100000000 >> (height + 1)//840000 -POW_FUNC=lambda data: pack.IntType(256).unpack(verthash_hash(data)) -BLOCK_PERIOD=150 # s +P2P_PREFIX = 'fabfb5da'.decode('hex') # new net magic +P2P_PORT = 5889 +ADDRESS_VERSION = 71 +ADDRESS_P2SH_VERSION = 5 +HUMAN_READABLE_PART = 'vtc' +RPC_PORT = 5888 +RPC_CHECK = defer.inlineCallbacks(lambda bitcoind: defer.returnValue( + (yield helper.check_block_header(bitcoind, '4d96a915f49d40b1e5c2844d1ee2dccb90013a990ccea12c492d22110489f0c4')) and + (yield bitcoind.rpc_getblockchaininfo())['chain'] == 'main' + )) +SUBSIDY_FUNC = lambda height: 50*100000000 >> (height + 1)//840000 +POW_FUNC = lambda data: pack.IntType(256).unpack(verthash_hash(data)) +BLOCK_PERIOD = 150 # s SYMBOL='VTC' CONF_FILE_FUNC=lambda: os.path.join(os.path.join(os.environ['APPDATA'], 'Vertcoin') if platform.system() == 'Windows' else os.path.expanduser('~/Library/Application Support/Vertcoin/') if platform.system() == 'Darwin' else os.path.expanduser('~/.vertcoin'), 'vertcoin.conf') -BLOCK_EXPLORER_URL_PREFIX='https://insight.vertcoin.org/block/' -ADDRESS_EXPLORER_URL_PREFIX='https://insight.vertcoin.org/address/' -TX_EXPLORER_URL_PREFIX='https://insight.vertcoin.org/tx/' -SANE_TARGET_RANGE=(2**256//1000000000000000000 - 1, 2**256//100000 - 1) -DUMB_SCRYPT_DIFF=16 -DUST_THRESHOLD=0.03e8 -HUMAN_READABLE_PART = 'vtc' +BLOCK_EXPLORER_URL_PREFIX = 'https://chainz.cryptoid.info/vtc/block.dws?' +ADDRESS_EXPLORER_URL_PREFIX = 'https://chainz.cryptoid.info/vtc/address.dws?' +TX_EXPLORER_URL_PREFIX = 'https://chainz.cryptoid.info/vtc/tx.dws?' +#SANE_TARGET_RANGE = (2**256//2**32//100000000 - 1, 2**256//2**32 - 1) +SANE_TARGET_RANGE = (2**256//100000000000000000 - 1, 2**256//100000 - 1) +DUMB_SCRYPT_DIFF = 256 +DUST_THRESHOLD = 0.001e8 +#SANE_TARGET_RANGE = (2**256//1000000000000000000 - 1, 2**256//100000 - 1) diff --git a/p2pool/bitcoin/p2p.py b/p2pool/bitcoin/p2p.py index c59d796c..038b1c47 100644 --- a/p2pool/bitcoin/p2p.py +++ b/p2pool/bitcoin/p2p.py @@ -14,11 +14,11 @@ class Protocol(p2protocol.Protocol): def __init__(self, net): - p2protocol.Protocol.__init__(self, net.P2P_PREFIX, 1000000, ignore_trailing_payload=True) + p2protocol.Protocol.__init__(self, net.P2P_PREFIX, 32000000, ignore_trailing_payload=True) def connectionMade(self): self.send_version( - version=70002, + version=70015, services=1, time=int(time.time()), addr_to=dict( diff --git a/p2pool/bitcoin/script.py b/p2pool/bitcoin/script.py index 3931c92a..c4bdd1c8 100644 --- a/p2pool/bitcoin/script.py +++ b/p2pool/bitcoin/script.py @@ -1,15 +1,16 @@ from p2pool.util import math, pack +import cStringIO as StringIO def reads_nothing(f): return None, f def protoPUSH(length): - return lambda f: pack.read(f, length) + return lambda f: f.read(length) def protoPUSHDATA(size_len): def _(f): - length_str, f = pack.read(f, size_len) + length_str = f.read(size_len) length = math.string_to_natural(length_str[::-1].lstrip(chr(0))) - data, f = pack.read(f, length) - return data, f + data = f.read(length) + return data return _ opcodes = {} @@ -32,12 +33,12 @@ def _(f): opcodes[175] = 'CHECKMULTISIGVERIFY', reads_nothing def parse(script): - f = script, 0 - while pack.size(f): - opcode_str, f = pack.read(f, 1) + f = StringIO.StringIO(script) + while pack.remaining(f): + opcode_str = f.read(1) opcode = ord(opcode_str) opcode_name, read_func = opcodes[opcode] - opcode_arg, f = read_func(f) + opcode_arg = read_func(f) yield opcode_name, opcode_arg def get_sigop_count(script): diff --git a/p2pool/bitcoin/stratum.py b/p2pool/bitcoin/stratum.py index 34fff1bf..6fe9c3bd 100644 --- a/p2pool/bitcoin/stratum.py +++ b/p2pool/bitcoin/stratum.py @@ -1,5 +1,6 @@ import random import sys +import time from twisted.internet import protocol, reactor from twisted.python import log @@ -7,9 +8,12 @@ from p2pool.bitcoin import data as bitcoin_data, getwork from p2pool.util import expiring_dict, jsonrpc, pack +def clip(num, bot, top): + return min(top, max(bot, num)) class StratumRPCMiningProvider(object): def __init__(self, wb, other, transport): + self.pool_version_mask = 0x1fffe000 self.wb = wb self.other = other self.transport = transport @@ -18,8 +22,15 @@ def __init__(self, wb, other, transport): self.handler_map = expiring_dict.ExpiringDict(300) self.watch_id = self.wb.new_work_event.watch(self._send_work) + + self.recent_shares = [] + self.target = None + self.share_rate = wb.share_rate + self.fixed_target = False + self.desired_pseudoshare_target = None + - def rpc_subscribe(self, miner_version=None, session_id=None): + def rpc_subscribe(self, miner_version=None, session_id=None, *args): reactor.callLater(0, self._send_work) return [ @@ -29,10 +40,36 @@ def rpc_subscribe(self, miner_version=None, session_id=None): ] def rpc_authorize(self, username, password): - self.username = username + if not hasattr(self, 'authorized'): # authorize can be called many times in one connection + print '>>>Authorize: %s from %s' % (username, self.transport.getPeer().host) + self.authorized = username + self.username = username.strip() + self.user, self.address, self.desired_share_target, self.desired_pseudoshare_target = self.wb.get_user_details(username) reactor.callLater(0, self._send_work) - + return True + + def rpc_configure(self, extensions, extensionParameters): + #extensions is a list of extension codes defined in BIP310 + #extensionParameters is a dict of parameters for each extension code + if 'version-rolling' in extensions: + #mask from miner is mandatory but we dont use it + miner_mask = extensionParameters['version-rolling.mask'] + #min-bit-count from miner is mandatory but we dont use it + try: + minbitcount = extensionParameters['version-rolling.min-bit-count'] + except: + log.err("A miner tried to connect with a malformed version-rolling.min-bit-count parameter. This is probably a bug in your mining software. Braiins OS is known to have this bug. You should complain to them.") + minbitcount = 2 # probably not needed + #according to the spec, pool should return largest mask possible (to support mining proxies) + return {"version-rolling" : True, "version-rolling.mask" : '{:08x}'.format(self.pool_version_mask&(int(miner_mask,16)))} + #pool can send mining.set_version_mask at any time if the pool mask changes + + if 'minimum-difficulty' in extensions: + print 'Extension method minimum-difficulty not implemented' + if 'subscribe-extranonce' in extensions: + print 'Extension method subscribe-extranonce not implemented' + def _send_work(self): try: x, got_response = self.wb.get_work(*self.wb.preprocess_request('' if self.username is None else self.username)) @@ -40,8 +77,15 @@ def _send_work(self): log.err() self.transport.loseConnection() return + if self.desired_pseudoshare_target: + self.fixed_target = True + self.target = self.desired_pseudoshare_target + self.target = max(self.target, int(x['bits'].target)) + else: + self.fixed_target = False + self.target = x['share_target'] if self.target == None else max(x['min_share_target'], self.target) jobid = str(random.randrange(2**128)) - self.other.svc_mining.rpc_set_difficulty(bitcoin_data.target_to_difficulty_alt(x['share_target'], self.wb.net.DUMB_SCRYPT_DIFF) * self.wb.net.DUMB_SCRYPT_DIFF).addErrback(lambda err: None) + self.other.svc_mining.rpc_set_difficulty(bitcoin_data.target_to_difficulty(self.target)*self.wb.net.DUMB_SCRYPT_DIFF).addErrback(lambda err: None) self.other.svc_mining.rpc_notify( jobid, # jobid getwork._swap4(pack.IntType(256).pack(x['previous_block'])).encode('hex'), # prevhash @@ -55,36 +99,59 @@ def _send_work(self): ).addErrback(lambda err: None) self.handler_map[jobid] = x, got_response - def rpc_submit(self, worker_name, job_id, extranonce2, ntime, nonce): + def rpc_submit(self, worker_name, job_id, extranonce2, ntime, nonce, version_bits = None, *args): + #asicboost: version_bits is the version mask that the miner used + worker_name = worker_name.strip() if job_id not in self.handler_map: print >>sys.stderr, '''Couldn't link returned work's job id with its handler. This should only happen if this process was recently restarted!''' + #self.other.svc_client.rpc_reconnect().addErrback(lambda err: None) return False x, got_response = self.handler_map[job_id] coinb_nonce = extranonce2.decode('hex') assert len(coinb_nonce) == self.wb.COINBASE_NONCE_LENGTH new_packed_gentx = x['coinb1'] + coinb_nonce + x['coinb2'] + + job_version = x['version'] + nversion = job_version + #check if miner changed bits that they were not supposed to change + if version_bits: + if ((~self.pool_version_mask) & int(version_bits,16)) != 0: + #todo: how to raise error back to miner? + #protocol does not say error needs to be returned but ckpool returns + #{"error": "Invalid version mask", "id": "id", "result":""} + raise ValueError("Invalid version mask {0}".format(version_bits)) + nversion = (job_version & ~self.pool_version_mask) | (int(version_bits,16) & self.pool_version_mask) + #nversion = nversion & int(version_bits,16) + header = dict( - version=x['version'], + version=nversion, previous_block=x['previous_block'], merkle_root=bitcoin_data.check_merkle_link(bitcoin_data.hash256(new_packed_gentx), x['merkle_link']), # new_packed_gentx has witness data stripped timestamp=pack.IntType(32).unpack(getwork._swap4(ntime.decode('hex'))), bits=x['bits'], nonce=pack.IntType(32).unpack(getwork._swap4(nonce.decode('hex'))), ) + result = got_response(header, worker_name, coinb_nonce, self.target) - # Disconnect miners with large DOA rates to prevent DoS - res = got_response(header, worker_name, coinb_nonce) - if len(self.wb._inner.my_share_hashes) > 20: - if float(len(self.wb._inner.my_doa_share_hashes)) / float(len(self.wb._inner.my_share_hashes)) > 0.60: - self.transport.loseConnection() + # adjust difficulty on this stratum to target ~10sec/pseudoshare + if not self.fixed_target: + self.recent_shares.append(time.time()) + if len(self.recent_shares) > 12 or (time.time() - self.recent_shares[0]) > 10*len(self.recent_shares)*self.share_rate: + old_time = self.recent_shares[0] + del self.recent_shares[0] + olddiff = bitcoin_data.target_to_difficulty(self.target) + self.target = int(self.target * clip((time.time() - old_time)/(len(self.recent_shares)*self.share_rate), 0.5, 2.) + 0.5) + newtarget = clip(self.target, self.wb.net.SANE_TARGET_RANGE[0], self.wb.net.SANE_TARGET_RANGE[1]) + if newtarget != self.target: + print "Clipping target from %064x to %064x" % (self.target, newtarget) + self.target = newtarget + self.target = max(x['min_share_target'], self.target) + self.recent_shares = [time.time()] + self._send_work() - # Disconnect miners with large hash > target to prevent DoS - if self.wb._inner.total_hashes > 20: - if float(self.wb._inner.invalid_hashes) / float(self.wb._inner.total_hashes) > 0.05: - self.transport.loseConnection() - - return res + return result + def close(self): self.wb.new_work_event.unwatch(self.watch_id) diff --git a/p2pool/bitcoin/worker_interface.py b/p2pool/bitcoin/worker_interface.py index 7ae19511..39dd9c29 100644 --- a/p2pool/bitcoin/worker_interface.py +++ b/p2pool/bitcoin/worker_interface.py @@ -120,23 +120,28 @@ def __init__(self, inner): self._cache = {} self._times = None - def get_work(self, *args): + def get_work(self, user, address, desired_share_target, + desired_pseudoshare_target, worker_ip=None, *args): if self._times != self.new_work_event.times: self._cache = {} self._times = self.new_work_event.times - if args not in self._cache: - x, handler = self._inner.get_work(*args) - self._cache[args] = x, handler, 0 + cachekey = (address, desired_share_target, args) + if cachekey not in self._cache: + x, handler = self._inner.get_work(user, address, desired_share_target, + desired_pseudoshare_target, worker_ip, *args) + self._cache[cachekey] = x, handler, 0 - x, handler, nonce = self._cache.pop(args) + x, handler, nonce = self._cache.pop(cachekey) res = ( dict(x, coinb1=x['coinb1'] + pack.IntType(self._my_bits).pack(nonce)), - lambda header, user, coinbase_nonce: handler(header, user, pack.IntType(self._my_bits).pack(nonce) + coinbase_nonce), + lambda header, user, coinbase_nonce, pseudoshare_target: handler(header, user, pack.IntType(self._my_bits).pack(nonce) + coinbase_nonce, pseudoshare_target), ) if nonce + 1 != 2**self._my_bits: - self._cache[args] = x, handler, nonce + 1 + self._cache[cachekey] = x, handler, nonce + 1 return res + def __getattr__(self, attr): + return getattr(self._inner, attr) diff --git a/p2pool/data.py b/p2pool/data.py index d7558259..2eaa335c 100644 --- a/p2pool/data.py +++ b/p2pool/data.py @@ -5,6 +5,8 @@ import random import sys import time +import array +import traceback from twisted.python import log @@ -48,13 +50,13 @@ def check_hash_link(hash_link, data, const_ending=''): def load_share(share, net, peer_addr): assert peer_addr is None or isinstance(peer_addr, tuple) - if share['type'] < Share.VERSION: + if share['type'] in share_versions: + net.PARENT.padding_bugfix = (share['type'] >= 35) + return share_versions[share['type']](net, peer_addr, share_versions[share['type']].get_dynamic_types(net)['share_type'].unpack(share['contents'])) + + elif share['type'] < Share.VERSION: from p2pool import p2p raise p2p.PeerMisbehavingError('sent an obsolete share') - elif share['type'] == Share.VERSION: - return Share(net, peer_addr, Share.get_dynamic_types(net)['share_type'].unpack(share['contents'])) - elif share['type'] == NewShare.VERSION: - return NewShare(net, peer_addr, NewShare.get_dynamic_types(net)['share_type'].unpack(share['contents'])) else: raise ValueError('unknown share type: %r' % (share['type'],)) @@ -63,16 +65,21 @@ def is_segwit_activated(version, net): segwit_activation_version = getattr(net, 'SEGWIT_ACTIVATION_VERSION', 0) return version >= segwit_activation_version and segwit_activation_version > 0 -DONATION_SCRIPT = '410418a74130b2f4fad899d8ed2bff272bc43a03c8ca72897ae3da584d7a770b5a9ea8dd1b37a620d27c6cf6d5a7a9bbd6872f5981e95816d701d94f201c5d093be6ac'.decode('hex') +DONATION_SCRIPT = '410440F12D23D1936729D7A27AD3915FD94F38A995B1EBBF327F3CAB14367497DCD04545C207EEC3E757E56542493CD64AAD9CC61605DF29F1DA0E0FBFF4747D27FAAC'.decode('hex') +def donation_script_to_address(net): + try: + return bitcoin_data.script2_to_address( + DONATION_SCRIPT, net.PARENT.ADDRESS_VERSION, -1, net.PARENT) + except ValueError: + return bitcoin_data.script2_to_address( + DONATION_SCRIPT, net.PARENT.ADDRESS_P2SH_VERSION, -1, net.PARENT) class BaseShare(object): VERSION = 0 VOTING_VERSION = 0 SUCCESSOR = None - - MAX_BLOCK_WEIGHT = 4000000 - MAX_NEW_TXS_SIZE = 50000 - + MINIMUM_PROTOCOL_VERSION = 3500 + small_block_header_type = pack.ComposedType([ ('version', pack.VarIntType()), ('previous_block', pack.PossiblyNoneType(0, pack.IntType(256))), @@ -86,8 +93,13 @@ class BaseShare(object): gentx_before_refhash = pack.VarStrType().pack(DONATION_SCRIPT) + pack.IntType(64).pack(0) + pack.VarStrType().pack('\x6a\x28' + pack.IntType(256).pack(0) + pack.IntType(64).pack(0))[:3] + gentx_size = 50000 # conservative estimate, will be overwritten during execution + gentx_weight = 200000 + cached_types = None @classmethod def get_dynamic_types(cls, net): + if not cls.cached_types == None: + return cls.cached_types t = dict(share_info_type=None, share_type=None, ref_type=None) segwit_data = ('segwit_data', pack.PossiblyNoneType(dict(txid_merkle_link=dict(branch=[], index=0), wtxid_merkle_root=2**256-1), pack.ComposedType([ ('txid_merkle_link', pack.ComposedType([ @@ -101,15 +113,17 @@ def get_dynamic_types(cls, net): ('previous_share_hash', pack.PossiblyNoneType(0, pack.IntType(256))), ('coinbase', pack.VarStrType()), ('nonce', pack.IntType(32)), - ('pubkey_hash', pack.IntType(160)), - ('pubkey_hash_version', pack.IntType(8)), + ] + ([('address', pack.VarStrType())] + if cls.VERSION >= 34 + else [('pubkey_hash', pack.IntType(160))]) + [ ('subsidy', pack.IntType(64)), ('donation', pack.IntType(16)), - ('stale_info', pack.StaleInfoEnumType()), + ('stale_info', pack.EnumType(pack.IntType(8), dict((k, {0: None, 253: 'orphan', 254: 'doa'}.get(k, 'unk%i' % (k,))) for k in xrange(256)))), ('desired_version', pack.VarIntType()), - ]))] + ([segwit_data] if is_segwit_activated(cls.VERSION, net) else []) + [ + ]))] + ([segwit_data] if is_segwit_activated(cls.VERSION, net) else []) + ([ ('new_transaction_hashes', pack.ListType(pack.IntType(256))), ('transaction_hash_refs', pack.ListType(pack.VarIntType(), 2)), # pairs of share_count, tx_count + ] if cls.VERSION < 34 else []) + [ ('far_share_hash', pack.PossiblyNoneType(0, pack.IntType(256))), ('max_bits', bitcoin_data.FloatingIntegerType()), ('bits', bitcoin_data.FloatingIntegerType()), @@ -135,10 +149,12 @@ def get_dynamic_types(cls, net): ('identifier', pack.FixedStrType(64//8)), ('share_info', t['share_info_type']), ]) + cls.cached_types = t return t @classmethod def generate_transaction(cls, tracker, share_data, block_target, desired_timestamp, desired_target, ref_merkle_link, desired_other_transaction_hashes_and_fees, net, known_txs=None, last_txout_nonce=0, base_subsidy=None, segwit_data=None): + t0 = time.time() previous_share = tracker.items[share_data['previous_share_hash']] if share_data['previous_share_hash'] is not None else None height, last = tracker.get_height_and_last(share_data['previous_share_hash']) @@ -154,30 +170,78 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta bits = bitcoin_data.FloatingInteger.from_target_upper_bound(math.clip(desired_target, (pre_target3//30, pre_target3))) new_transaction_hashes = [] - new_transaction_size = 0 + new_transaction_size = 0 # including witnesses + all_transaction_stripped_size = 0 # stripped size + all_transaction_real_size = 0 # including witnesses, for statistics + new_transaction_weight = 0 + all_transaction_weight = 0 transaction_hash_refs = [] other_transaction_hashes = [] - - past_shares = list(tracker.get_chain(share_data['previous_share_hash'], min(height, 100))) + t1 = time.time() tx_hash_to_this = {} - for i, share in enumerate(past_shares): - for j, tx_hash in enumerate(share.new_transaction_hashes): - if tx_hash not in tx_hash_to_this: - tx_hash_to_this[tx_hash] = [1+i, j] # share_count, tx_count + if cls.VERSION < 34: + past_shares = list(tracker.get_chain(share_data['previous_share_hash'], min(height, 100))) + for i, share in enumerate(past_shares): + for j, tx_hash in enumerate(share.new_transaction_hashes): + if tx_hash not in tx_hash_to_this: + tx_hash_to_this[tx_hash] = [1+i, j] # share_count, tx_count + + t2 = time.time() for tx_hash, fee in desired_other_transaction_hashes_and_fees: + if known_txs is not None: + this_stripped_size = bitcoin_data.get_stripped_size(known_txs[tx_hash]) + this_real_size = bitcoin_data.get_size(known_txs[tx_hash]) + this_weight = this_real_size + 3*this_stripped_size + else: # we're just verifying someone else's share. We'll calculate sizes in should_punish_reason() + this_stripped_size = 0 + this_real_size = 0 + this_weight = 0 + + if all_transaction_stripped_size + this_stripped_size + 80 + cls.gentx_size + 500 > net.BLOCK_MAX_SIZE: + break + if all_transaction_weight + this_weight + 4*80 + cls.gentx_weight + 2000 > net.BLOCK_MAX_WEIGHT: + break + if tx_hash in tx_hash_to_this: this = tx_hash_to_this[tx_hash] + if known_txs is not None: + all_transaction_stripped_size += this_stripped_size + all_transaction_real_size += this_real_size + all_transaction_weight += this_weight else: if known_txs is not None: - this_size = bitcoin_data.tx_type.packed_size(known_txs[tx_hash]) - if new_transaction_size + this_size > cls.MAX_NEW_TXS_SIZE: # limit the size of new txns/share - break - new_transaction_size += this_size + new_transaction_size += this_real_size + all_transaction_stripped_size += this_stripped_size + all_transaction_real_size += this_real_size + new_transaction_weight += this_weight + all_transaction_weight += this_weight new_transaction_hashes.append(tx_hash) this = [0, len(new_transaction_hashes)-1] transaction_hash_refs.extend(this) other_transaction_hashes.append(tx_hash) + t3 = time.time() + if transaction_hash_refs and max(transaction_hash_refs) < 2**16: + transaction_hash_refs = array.array('H', transaction_hash_refs) + elif transaction_hash_refs and max(transaction_hash_refs) < 2**32: # in case we see blocks with more than 65536 tx + transaction_hash_refs = array.array('L', transaction_hash_refs) + t4 = time.time() + + if all_transaction_stripped_size and p2pool.DEBUG: + print "Generating a share with %i bytes, %i WU (new: %i B, %i WU) in %i tx (%i new), plus est gentx of %i bytes/%i WU" % ( + all_transaction_real_size, + all_transaction_weight, + new_transaction_size, + new_transaction_weight, + len(other_transaction_hashes), + len(new_transaction_hashes), + cls.gentx_size, + cls.gentx_weight) + print "Total block stripped size=%i B, full size=%i B, weight: %i WU" % ( + 80+all_transaction_stripped_size+cls.gentx_size, + 80+all_transaction_real_size+cls.gentx_size, + 3*80+all_transaction_weight+cls.gentx_weight) + included_transactions = set(other_transaction_hashes) removed_fees = [fee for tx_hash, fee in desired_other_transaction_hashes_and_fees if tx_hash not in included_transactions] definite_fees = sum(0 if fee is None else fee for tx_hash, fee in desired_other_transaction_hashes_and_fees if tx_hash in included_transactions) @@ -192,16 +256,38 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta 65535*net.SPREAD*bitcoin_data.target_to_average_attempts(block_target), ) assert total_weight == sum(weights.itervalues()) + donation_weight, (total_weight, sum(weights.itervalues()) + donation_weight) + + worker_payout = share_data['subsidy'] - amounts = dict((script, share_data['subsidy']*(199*weight)//(200*total_weight)) for script, weight in weights.iteritems()) # 99.5% goes according to weights prior to this share - this_script = bitcoin_data.pubkey_hash_to_script2(share_data['pubkey_hash'], share_data['pubkey_hash_version'], net.PARENT) - amounts[this_script] = amounts.get(this_script, 0) + share_data['subsidy']//200 # 0.5% goes to block finder - amounts[DONATION_SCRIPT] = amounts.get(DONATION_SCRIPT, 0) + share_data['subsidy'] - sum(amounts.itervalues()) # all that's left over is the donation weight and some extra satoshis due to rounding + amounts = dict((script, worker_payout*(199*weight)//(200*total_weight)) for script, weight in weights.iteritems()) # 99.5% goes according to weights prior to this share + if 'address' not in share_data: + this_address = bitcoin_data.pubkey_hash_to_address( + share_data['pubkey_hash'], net.PARENT.ADDRESS_VERSION, + -1, net.PARENT) + else: + this_address = share_data['address'] + donation_address = donation_script_to_address(net) + # 0.5% goes to block finder + amounts[this_address] = amounts.get(this_address, 0) \ + + worker_payout//200 + # all that's left over is the donation weight and some extra + # satoshis due to rounding + amounts[donation_address] = amounts.get(donation_address, 0) \ + + worker_payout \ + - sum(amounts.itervalues()) + if cls.VERSION < 34 and 'pubkey_hash' not in share_data: + share_data['pubkey_hash'], _, _ = bitcoin_data.address_to_pubkey_hash( + this_address, net.PARENT) + del(share_data['address']) - if sum(amounts.itervalues()) != share_data['subsidy'] or any(x < 0 for x in amounts.itervalues()): + if sum(amounts.itervalues()) != worker_payout or any(x < 0 for x in amounts.itervalues()): raise ValueError() - - dests = sorted(amounts.iterkeys(), key=lambda script: (script == DONATION_SCRIPT, amounts[script], script))[-4000:] # block length limit, unlikely to ever be hit + + # block length limit, unlikely to ever be hit + dests = sorted(amounts.iterkeys(), key=lambda address: ( + address == donation_address, amounts[address], address))[-4000:] + if len(dests) >= 200: + print "found %i payment dests. Antminer S9s may crash when this is close to 226." % len(dests) segwit_activated = is_segwit_activated(cls.VERSION, net) if segwit_data is None and known_txs is None: @@ -221,18 +307,37 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta far_share_hash=None if last is None and height < 99 else tracker.get_nth_parent_hash(share_data['previous_share_hash'], 99), max_bits=max_bits, bits=bits, - timestamp=math.clip(desired_timestamp, ( - (previous_share.timestamp + net.SHARE_PERIOD) - (net.SHARE_PERIOD - 1), # = previous_share.timestamp + 1 - (previous_share.timestamp + net.SHARE_PERIOD) + (net.SHARE_PERIOD - 1), - )) if previous_share is not None else desired_timestamp, - new_transaction_hashes=new_transaction_hashes, - transaction_hash_refs=transaction_hash_refs, + + timestamp=(math.clip(desired_timestamp, ( + (previous_share.timestamp + net.SHARE_PERIOD) - (net.SHARE_PERIOD - 1), # = previous_share.timestamp + 1 + (previous_share.timestamp + net.SHARE_PERIOD) + (net.SHARE_PERIOD - 1),)) if previous_share is not None else desired_timestamp + ) if cls.VERSION < 32 else + max(desired_timestamp, (previous_share.timestamp + 1)) if previous_share is not None else desired_timestamp, absheight=((previous_share.absheight if previous_share is not None else 0) + 1) % 2**32, abswork=((previous_share.abswork if previous_share is not None else 0) + bitcoin_data.target_to_average_attempts(bits.target)) % 2**128, ) + if cls.VERSION < 34: + share_info['new_transaction_hashes'] = new_transaction_hashes + share_info['transaction_hash_refs'] = transaction_hash_refs + + if previous_share != None and desired_timestamp > previous_share.timestamp + 180: + print "Warning: Previous share's timestamp is %i seconds old." % int(desired_timestamp - previous_share.timestamp) + print "Make sure your system clock is accurate, and ensure that you're connected to decent peers." + print "If your clock is more than 300 seconds behind, it can result in orphaned shares." + print "(It's also possible that this share is just taking a long time to mine.)" + if previous_share != None and previous_share.timestamp > int(time.time()) + 3: + print "WARNING! Previous share's timestamp is %i seconds in the future. This is not normal." % \ + int(previous_share.timestamp - (int(time.time()))) + print "Make sure your system clock is accurate. Errors beyond 300 sec result in orphaned shares." + if segwit_activated: share_info['segwit_data'] = segwit_data + payouts = [dict(value=amounts[addr], + script=bitcoin_data.address_to_script2(addr, net.PARENT) + ) for addr in dests if amounts[addr] and addr != donation_address] + payouts.append({'script': DONATION_SCRIPT, 'value': amounts[donation_address]}) + gentx = dict( version=1, tx_ins=[dict( @@ -240,9 +345,14 @@ def generate_transaction(cls, tracker, share_data, block_target, desired_timesta sequence=None, script=share_data['coinbase'], )], - tx_outs=([dict(value=0, script='\x6a\x24\xaa\x21\xa9\xed' + pack.IntType(256).pack(witness_commitment_hash))] if segwit_activated else []) + - [dict(value=amounts[script], script=script) for script in dests if amounts[script] or script == DONATION_SCRIPT] + - [dict(value=0, script='\x6a\x28' + cls.get_ref_hash(net, share_info, ref_merkle_link) + pack.IntType(64).pack(last_txout_nonce))], + tx_outs=([dict(value=0, script='\x6a\x24\xaa\x21\xa9\xed' \ + + pack.IntType(256).pack( + witness_commitment_hash))] + if segwit_activated else []) \ + + payouts \ + + [dict(value=0, script='\x6a\x28' + cls.get_ref_hash( + net, share_info, ref_merkle_link) \ + + pack.IntType(64).pack(last_txout_nonce))], lock_time=0, ) if segwit_activated: @@ -262,7 +372,14 @@ def get_share(header, last_txout_nonce=last_txout_nonce): )) assert share.header == header # checks merkle_root return share - + t5 = time.time() + if p2pool.BENCH: print "%8.3f ms for data.py:generate_transaction(). Parts: %8.3f %8.3f %8.3f %8.3f %8.3f " % ( + (t5-t0)*1000., + (t1-t0)*1000., + (t2-t1)*1000., + (t3-t2)*1000., + (t4-t3)*1000., + (t5-t4)*1000.) return share_info, gentx, other_transaction_hashes, get_share @classmethod @@ -288,15 +405,21 @@ def __init__(self, net, peer_addr, contents): self.share_info = contents['share_info'] self.hash_link = contents['hash_link'] self.merkle_link = contents['merkle_link'] + self.naughty = 0 + + # save some memory if we can + if self.VERSION < 34: + txrefs = self.share_info['transaction_hash_refs'] + if txrefs and max(txrefs) < 2**16: + self.share_info['transaction_hash_refs'] = array.array('H', txrefs) + elif txrefs and max(txrefs) < 2**32: # in case we see blocks with more than 65536 tx in the future + self.share_info['transaction_hash_refs'] = array.array('L', txrefs) segwit_activated = is_segwit_activated(self.VERSION, net) if not (2 <= len(self.share_info['share_data']['coinbase']) <= 100): raise ValueError('''bad coinbase size! %i bytes''' % (len(self.share_info['share_data']['coinbase']),)) - if len(self.merkle_link['branch']) > 16 or (segwit_activated and len(self.share_info['segwit_data']['txid_merkle_link']['branch']) > 16): - raise ValueError('merkle branch too long!') - assert not self.hash_link['extra_data'], repr(self.hash_link['extra_data']) self.share_data = self.share_info['share_data'] @@ -304,17 +427,30 @@ def __init__(self, net, peer_addr, contents): self.target = self.share_info['bits'].target self.timestamp = self.share_info['timestamp'] self.previous_hash = self.share_data['previous_share_hash'] - self.new_script = bitcoin_data.pubkey_hash_to_script2(self.share_data['pubkey_hash'], self.share_data['pubkey_hash_version'], net.PARENT) + if self.VERSION >= 34: + self.new_script = bitcoin_data.address_to_script2( + self.share_data['address'], net.PARENT) + self.address = self.share_data['address'] + else: + self.new_script = bitcoin_data.pubkey_hash_to_script2( + self.share_data['pubkey_hash'], + net.PARENT.ADDRESS_VERSION, -1, net.PARENT) + self.address = bitcoin_data.pubkey_hash_to_address( + self.share_data['pubkey_hash'], + net.PARENT.ADDRESS_VERSION, -1, net.PARENT) self.desired_version = self.share_data['desired_version'] self.absheight = self.share_info['absheight'] self.abswork = self.share_info['abswork'] + if net.NAME == 'bitcoin' and self.absheight > 3927800 and self.desired_version == 16: + raise ValueError("This is not a hardfork-supporting share!") - n = set() - for share_count, tx_count in self.iter_transaction_hash_refs(): - assert share_count < 110 - if share_count == 0: - n.add(tx_count) - assert n == set(range(len(self.share_info['new_transaction_hashes']))) + if self.VERSION < 34: + n = set() + for share_count, tx_count in self.iter_transaction_hash_refs(): + assert share_count < 110 + if share_count == 0: + n.add(tx_count) + assert n == set(range(len(self.share_info['new_transaction_hashes']))) self.gentx_hash = check_hash_link( self.hash_link, @@ -334,7 +470,8 @@ def __init__(self, net, peer_addr, contents): from p2pool import p2p raise p2p.PeerMisbehavingError('share PoW invalid') - self.new_transaction_hashes = self.share_info['new_transaction_hashes'] + if self.VERSION < 34: + self.new_transaction_hashes = self.share_info['new_transaction_hashes'] # XXX eww self.time_seen = time.time() @@ -346,12 +483,20 @@ def as_share(self): return dict(type=self.VERSION, contents=self.share_type.pack(self.contents)) def iter_transaction_hash_refs(self): - return zip(self.share_info['transaction_hash_refs'][::2], self.share_info['transaction_hash_refs'][1::2]) - - def check(self, tracker, other_txs=None): + try: + return zip(self.share_info['transaction_hash_refs'][::2], self.share_info['transaction_hash_refs'][1::2]) + except AttributeError: + return zip() + except KeyError: + return zip() + + def check(self, tracker, known_txs=None, block_abs_height_func=None, feecache=None): from p2pool import p2p + if self.timestamp > int(time.time()) + 600: + raise ValueError("Share timestamp is %i seconds in the future! Check your system clock." % \ + self.timestamp - int(time.time())) counts = None - if self.share_data['previous_share_hash'] is not None: + if self.share_data['previous_share_hash'] is not None and block_abs_height_func is not None: previous_share = tracker.items[self.share_data['previous_share_hash']] if tracker.get_height(self.share_data['previous_share_hash']) >= self.net.CHAIN_LENGTH: counts = get_desired_version_counts(tracker, tracker.get_nth_parent_hash(previous_share.hash, self.net.CHAIN_LENGTH*9//10), self.net.CHAIN_LENGTH//10) @@ -366,31 +511,88 @@ def check(self, tracker, other_txs=None): elif type(self) is type(previous_share).SUCCESSOR: raise p2p.PeerMisbehavingError('switch without enough history') - other_tx_hashes = [tracker.items[tracker.get_nth_parent_hash(self.hash, share_count)].share_info['new_transaction_hashes'][tx_count] for share_count, tx_count in self.iter_transaction_hash_refs()] - if other_txs is not None and not isinstance(other_txs, dict): other_txs = dict((bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx)), tx) for tx in other_txs) + if self.VERSION < 34: + other_tx_hashes = [tracker.items[tracker.get_nth_parent_hash(self.hash, share_count)].share_info['new_transaction_hashes'][tx_count] for share_count, tx_count in self.iter_transaction_hash_refs()] + else: + other_tx_hashes = [] + if known_txs is not None and not isinstance(known_txs, dict): + print "Performing maybe-unnecessary packing and hashing" + known_txs = dict((bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx)), tx) for tx in known_txs) share_info, gentx, other_tx_hashes2, get_share = self.generate_transaction(tracker, self.share_info['share_data'], self.header['bits'].target, self.share_info['timestamp'], self.share_info['bits'].target, self.contents['ref_merkle_link'], [(h, None) for h in other_tx_hashes], self.net, - known_txs=other_txs, last_txout_nonce=self.contents['last_txout_nonce'], segwit_data=self.share_info.get('segwit_data', None)) - + known_txs=None, last_txout_nonce=self.contents['last_txout_nonce'], segwit_data=self.share_info.get('segwit_data', None)) + + if self.VERSION < 34: + # check for excessive fees + if self.share_data['previous_share_hash'] is not None and block_abs_height_func is not None: + height = (block_abs_height_func(self.header['previous_block'])+1) + base_subsidy = self.net.PARENT.SUBSIDY_FUNC(height) + fees = [feecache[x] for x in other_tx_hashes if x in feecache] + missing = sum([1 for x in other_tx_hashes if not x in feecache]) + if missing == 0: + max_subsidy = sum(fees) + base_subsidy + details = "Max allowed = %i, requested subsidy = %i, share hash = %064x, miner = %s" % ( + max_subsidy, self.share_data['subsidy'], self.hash, + self.address) + if self.share_data['subsidy'] > max_subsidy: + self.naughty = 1 + print "Excessive block reward in share! Naughty. " + details + elif self.share_data['subsidy'] < max_subsidy: + print "Strange, we received a share that did not include as many coins in the block reward as was allowed. " + print "While permitted by the protocol, this causes coins to be lost forever if mined as a block, and costs us money." + print details + + if self.share_data['previous_share_hash'] and tracker.items[self.share_data['previous_share_hash']].naughty: + print "naughty ancestor found %i generations ago" % tracker.items[self.share_data['previous_share_hash']].naughty + # I am not easily angered ... + print "I will not fail to punish children and grandchildren to the third and fourth generation for the sins of their parents." + self.naughty = 1 + tracker.items[self.share_data['previous_share_hash']].naughty + if self.naughty > 6: + self.naughty = 0 + assert other_tx_hashes2 == other_tx_hashes if share_info != self.share_info: raise ValueError('share_info invalid') if bitcoin_data.get_txid(gentx) != self.gentx_hash: + print bitcoin_data.get_txid(gentx), self.gentx_hash + print gentx raise ValueError('''gentx doesn't match hash_link''') - if bitcoin_data.calculate_merkle_link([None] + other_tx_hashes, 0) != self.merkle_link: # the other hash commitments are checked in the share_info assertion - raise ValueError('merkle_link and other_tx_hashes do not match') + if self.VERSION < 34: + if bitcoin_data.calculate_merkle_link([None] + other_tx_hashes, 0) != self.merkle_link: # the other hash commitments are checked in the share_info assertion + raise ValueError('merkle_link and other_tx_hashes do not match') update_min_protocol_version(counts, self) + self.gentx_size = len(bitcoin_data.tx_id_type.pack(gentx)) + self.gentx_weight = len(bitcoin_data.tx_type.pack(gentx)) + 3*self.gentx_size + + type(self).gentx_size = self.gentx_size # saving this share's gentx size as a class variable is an ugly hack, and you're welcome to hate me for doing it. But it works. + type(self).gentx_weight = self.gentx_weight + + _diff = self.net.PARENT.DUMB_SCRYPT_DIFF*float( + bitcoin_data.target_to_difficulty(self.target)) + if not self.naughty: + print("Received good share: diff=%.2e hash=%064x miner=%s" % + (_diff, self.hash, self.address)) + else: + print("Received naughty=%i share: diff=%.2e hash=%064x miner=%s" % + (self.naughty, _diff, self.hash, self.address)) return gentx # only used by as_block def get_other_tx_hashes(self, tracker): - parents_needed = max(share_count for share_count, tx_count in self.iter_transaction_hash_refs()) if self.share_info['transaction_hash_refs'] else 0 + parents_needed = max(share_count for share_count, tx_count in self.iter_transaction_hash_refs()) if self.share_info.get('transaction_hash_refs', None) else 0 parents = tracker.get_height(self.hash) - 1 if parents < parents_needed: return None last_shares = list(tracker.get_chain(self.hash, parents_needed + 1)) - return [last_shares[share_count].share_info['new_transaction_hashes'][tx_count] for share_count, tx_count in self.iter_transaction_hash_refs()] + ret = [] + for share_count, tx_count in self.iter_transaction_hash_refs(): + try: + ret.append(last_shares[share_count] + .share_info['new_transaction_hashes'][tx_count]) + except AttributeError: + continue + return ret def _get_other_txs(self, tracker, known_txs): other_tx_hashes = self.get_other_tx_hashes(tracker) @@ -403,24 +605,26 @@ def _get_other_txs(self, tracker, known_txs): return [known_txs[tx_hash] for tx_hash in other_tx_hashes] def should_punish_reason(self, previous_block, bits, tracker, known_txs): - if (self.header['previous_block'], self.header['bits']) != (previous_block, bits) and self.header_hash != previous_block and self.peer_addr is not None: - return True, 'Block-stale detected! height(%x) < height(%x) or %08x != %08x' % (self.header['previous_block'], previous_block, self.header['bits'].bits, bits.bits) - if self.pow_hash <= self.header['bits'].target: return -1, 'block solution' - - other_txs = self._get_other_txs(tracker, known_txs) + if self.naughty == 1: + return self.naughty, 'naughty share (excessive block reward or otherwise would make an invalid block)' + if self.naughty: + return self.naughty, 'descendent of naughty share ' + if self.VERSION < 34: + other_txs = self._get_other_txs(tracker, known_txs) + else: + other_txs = None if other_txs is None: pass else: - all_txs_size = sum(bitcoin_data.tx_type.packed_size(tx) for tx in other_txs) - stripped_txs_size = sum(bitcoin_data.tx_id_type.packed_size(tx) for tx in other_txs) - if all_txs_size + 3 * stripped_txs_size > self.MAX_BLOCK_WEIGHT: + if not hasattr(self, 'all_tx_size'): + self.all_txs_size = sum(bitcoin_data.get_size(tx) for tx in other_txs) + self.stripped_txs_size = sum(bitcoin_data.get_stripped_size(tx) for tx in other_txs) + if self.all_txs_size + 3 * self.stripped_txs_size + 4*80 + self.gentx_weight > tracker.net.BLOCK_MAX_WEIGHT: + return True, 'txs over block weight limit' + if self.stripped_txs_size + 80 + self.gentx_size > tracker.net.BLOCK_MAX_SIZE: return True, 'txs over block size limit' - - new_txs_size = sum(bitcoin_data.tx_type.packed_size(known_txs[tx_hash]) for tx_hash in self.share_info['new_transaction_hashes']) - if new_txs_size > self.MAX_NEW_TXS_SIZE: - return True, 'new txs over limit' return False, None @@ -430,17 +634,13 @@ def as_block(self, tracker, known_txs): return None # not all txs present return dict(header=self.header, txs=[self.check(tracker, other_txs)] + other_txs) -class NewShare(BaseShare): - VERSION = 17 - VOTING_VERSION = 17 +class Share(BaseShare): + VERSION = 35 + VOTING_VERSION = 35 SUCCESSOR = None - MAX_NEW_TXS_SIZE = 100000 -class Share(BaseShare): - VERSION = 16 - VOTING_VERSION = 16 - SUCCESSOR = NewShare +share_versions = {s.VERSION:s for s in [Share]} class WeightsSkipList(forest.TrackerSkipList): # share_count, weights, total_weight @@ -449,7 +649,8 @@ def get_delta(self, element): from p2pool.bitcoin import data as bitcoin_data share = self.tracker.items[element] att = bitcoin_data.target_to_average_attempts(share.target) - return 1, {share.new_script: att*(65535-share.share_data['donation'])}, att*65535, att*share.share_data['donation'] + return (1, {share.address: att*(65535-share.share_data['donation'])}, + att*65535, att*share.share_data['donation']) def combine_deltas(self, (share_count1, weights1, total_weight1, total_donation_weight1), (share_count2, weights2, total_weight2, total_donation_weight2)): return share_count1 + share_count2, math.add_dicts(weights1, weights2), total_weight1 + total_weight2, total_donation_weight1 + total_donation_weight2 @@ -490,15 +691,15 @@ def __init__(self, net): work=lambda share: bitcoin_data.target_to_average_attempts(share.target), )), subset_of=self) self.get_cumulative_weights = WeightsSkipList(self) - - def attempt_verify(self, share): + + def attempt_verify(self, share, block_abs_height_func, known_txs, feecache): if share.hash in self.verified.items: return True height, last = self.get_height_and_last(share.hash) if height < self.net.CHAIN_LENGTH + 1 and last is not None: raise AssertionError() try: - share.check(self) + share.gentx = share.check(self, known_txs, block_abs_height_func=block_abs_height_func, feecache=feecache) except: log.err(None, 'Share check failed: %064x -> %064x' % (share.hash, share.previous_hash if share.previous_hash is not None else 0)) return False @@ -506,7 +707,7 @@ def attempt_verify(self, share): self.verified.add(share) return True - def think(self, block_rel_height_func, previous_block, bits, known_txs): + def think(self, block_rel_height_func, block_abs_height_func, previous_block, bits, known_txs, feecache): desired = set() bad_peer_addresses = set() @@ -520,7 +721,7 @@ def think(self, block_rel_height_func, previous_block, bits, known_txs): head_height, last = self.get_height_and_last(head) for share in self.get_chain(head, head_height if last is None else min(5, max(0, head_height - self.net.CHAIN_LENGTH))): - if self.attempt_verify(share): + if self.attempt_verify(share, block_abs_height_func, known_txs, feecache): break bads.append(share.hash) else: @@ -554,7 +755,7 @@ def think(self, block_rel_height_func, previous_block, bits, known_txs): get = min(want, can) #print 'Z', head_height, last_hash is None, last_height, last_last_hash is None, want, can, get for share in self.get_chain(last_hash, get): - if not self.attempt_verify(share): + if not self.attempt_verify(share, block_abs_height_func, known_txs, feecache): break if head_height < self.net.CHAIN_LENGTH and last_last_hash is not None: desired.add(( @@ -574,26 +775,62 @@ def think(self, block_rel_height_func, previous_block, bits, known_txs): # decide best verified head decorated_heads = sorted((( - self.verified.get_work(self.verified.get_nth_parent_hash(h, min(5, self.verified.get_height(h)))), + self.verified.get_work(self.verified.get_nth_parent_hash(h, min(5, self.verified.get_height(h)))) - + min(self.items[h].should_punish_reason(previous_block, bits, self, known_txs)[0], 1) * bitcoin_data.target_to_average_attempts(self.items[h].target), #self.items[h].peer_addr is None, -self.items[h].should_punish_reason(previous_block, bits, self, known_txs)[0], + #-self.items[h].should_punish_reason(previous_block, bits, self, known_txs)[0] * bitcoin_data.target_to_average_attempts(self.items[h].target), -self.items[h].time_seen, ), h) for h in self.verified.tails.get(best_tail, [])) + traditional_sort = sorted((( + self.verified.get_work(self.verified.get_nth_parent_hash(h, min(5, self.verified.get_height(h)))), + #self.items[h].peer_addr is None, + -self.items[h].time_seen, # assume they can't tell we should punish this share and will be sorting based on time + -self.items[h].should_punish_reason(previous_block, bits, self, known_txs)[0], + ), h) for h in self.verified.tails.get(best_tail, [])) + punish_aggressively = traditional_sort[-1][0][2] if traditional_sort else False + if p2pool.DEBUG: print len(decorated_heads), 'heads. Top 10:' for score, head_hash in decorated_heads[-10:]: print ' ', format_hash(head_hash), format_hash(self.items[head_hash].previous_hash), score + print "Traditional sort:" + for score, head_hash in traditional_sort[-10:]: + print ' ', format_hash(head_hash), format_hash(self.items[head_hash].previous_hash), score best_head_score, best = decorated_heads[-1] if decorated_heads else (None, None) - + + punish = 0 if best is not None: best_share = self.items[best] punish, punish_reason = best_share.should_punish_reason(previous_block, bits, self, known_txs) - if punish > 0: + while punish > 0: print 'Punishing share for %r! Jumping from %s to %s!' % (punish_reason, format_hash(best), format_hash(best_share.previous_hash)) best = best_share.previous_hash + best_share = self.items[best] + punish, punish_reason = best_share.should_punish_reason(previous_block, bits, self, known_txs) + if not punish: + def best_descendent(hsh, limit=20): + child_hashes = self.reverse.get(hsh, set()) + best_kids = sorted((best_descendent(child, limit-1) for child in child_hashes if not self.items[child].naughty)) + if not best_kids or limit<0: # in case the only children are naughty + return 0, hsh + return (best_kids[-1][0]+1, best_kids[-1][1]) + try: + gens, hsh = best_descendent(best) + if p2pool.DEBUG: print "best_descendent went %i generations for share %s from %s" % (gens, format_hash(hsh), format_hash(best)) + best = hsh + best_share = self.items[best] + except: + traceback.print_exc() timestamp_cutoff = min(int(time.time()), best_share.timestamp) - 3600 target_cutoff = int(2**256//(self.net.SHARE_PERIOD*best_tail_score[1] + 1) * 2 + .5) if best_tail_score[1] is not None else 2**256-1 + + # Hard fork logic: + # If our best share is v34 or higher, we will correctly zero-pad output scripts + # Otherwise, we preserve a bug in order to avoid a chainsplit + self.net.PARENT.padding_bugfix = (best_share.VERSION >= 35) + else: timestamp_cutoff = int(time.time()) - 24*60*60 target_cutoff = 2**256-1 @@ -603,7 +840,7 @@ def think(self, block_rel_height_func, previous_block, bits, known_txs): for peer_addr, hash, ts, targ in desired: print ' ', None if peer_addr is None else '%s:%i' % peer_addr, format_hash(hash), math.format_dt(time.time() - ts), bitcoin_data.target_to_difficulty(targ), ts >= timestamp_cutoff, targ <= target_cutoff - return best, [(peer_addr, hash) for peer_addr, hash, ts, targ in desired if ts >= timestamp_cutoff], decorated_heads, bad_peer_addresses + return best, [(peer_addr, hash) for peer_addr, hash, ts, targ in desired if ts >= timestamp_cutoff], decorated_heads, bad_peer_addresses, punish_aggressively def score(self, share_hash, block_rel_height_func): # returns approximate lower bound on chain's hashrate in the last self.net.CHAIN_LENGTH*15//16*self.net.SHARE_PERIOD time @@ -621,8 +858,8 @@ def score(self, share_hash, block_rel_height_func): def update_min_protocol_version(counts, share): minpver = getattr(share.net, 'MINIMUM_PROTOCOL_VERSION', 1400) - newminpver = getattr(share.net, 'NEW_MINIMUM_PROTOCOL_VERSION', minpver) - if (counts is not None) and (type(share) is NewShare) and (minpver < newminpver): + newminpver = share.MINIMUM_PROTOCOL_VERSION + if (counts is not None) and (minpver < newminpver): if counts.get(share.VERSION, 0) >= sum(counts.itervalues())*95//100: share.net.MINIMUM_PROTOCOL_VERSION = newminpver # Reject peers running obsolete nodes print 'Setting MINIMUM_PROTOCOL_VERSION = %d' % (newminpver) @@ -655,21 +892,29 @@ def get_stale_counts(tracker, share_hash, lookbehind, rates=False): res = dict((k, v/dt) for k, v in res.iteritems()) return res -def get_user_stale_props(tracker, share_hash, lookbehind): +def get_user_stale_props(tracker, share_hash, lookbehind, net): res = {} for share in tracker.get_chain(share_hash, lookbehind - 1): - stale, total = res.get(share.share_data['pubkey_hash'], (0, 0)) + if share.VERSION < 34: + stale, total = res.get(share.share_data['pubkey_hash'], (0, 0)) + key = bitcoin_data.pubkey_hash_to_address( + share.share_data['pubkey_hash'], net.ADDRESS_VERSION, -1, + net) + else: + key = share.share_data['address'] + stale, total = res.get(key, (0, 0)) total += 1 if share.share_data['stale_info'] is not None: stale += 1 total += 1 - res[share.share_data['pubkey_hash']] = stale, total + res[key] = stale, total return dict((pubkey_hash, stale/total) for pubkey_hash, (stale, total) in res.iteritems()) def get_expected_payouts(tracker, best_share_hash, block_target, subsidy, net): weights, total_weight, donation_weight = tracker.get_cumulative_weights(best_share_hash, min(tracker.get_height(best_share_hash), net.REAL_CHAIN_LENGTH), 65535*net.SPREAD*bitcoin_data.target_to_average_attempts(block_target)) res = dict((script, subsidy*weight//total_weight) for script, weight in weights.iteritems()) - res[DONATION_SCRIPT] = res.get(DONATION_SCRIPT, 0) + subsidy - sum(res.itervalues()) + donation_addr = donation_script_to_address(net) + res[donation_addr] = res.get(donation_addr, 0) + subsidy - sum(res.itervalues()) return res def get_desired_version_counts(tracker, best_share_hash, dist): @@ -684,9 +929,9 @@ def get_warnings(tracker, best_share, net, bitcoind_getinfo, bitcoind_work_value desired_version_counts = get_desired_version_counts(tracker, best_share, min(net.CHAIN_LENGTH, 60*60//net.SHARE_PERIOD, tracker.get_height(best_share))) majority_desired_version = max(desired_version_counts, key=lambda k: desired_version_counts[k]) - if majority_desired_version > (Share.SUCCESSOR if Share.SUCCESSOR is not None else Share).VOTING_VERSION and desired_version_counts[majority_desired_version] > sum(desired_version_counts.itervalues())/2: + if majority_desired_version not in share_versions and desired_version_counts[majority_desired_version] > sum(desired_version_counts.itervalues())/2: res.append('A MAJORITY OF SHARES CONTAIN A VOTE FOR AN UNSUPPORTED SHARE IMPLEMENTATION! (v%i with %i%% support)\n' - 'An upgrade is likely necessary. Check http://p2pool.forre.st/ for more information.' % ( + 'An upgrade is likely necessary. Check https://github.com/jtoomim/p2pool/tree/1mb_segwit or https://forum.bitcoin.com/pools/p2pool-decentralized-dos-resistant-trustless-censorship-resistant-pool-t69932-99999.html for more information.' % ( majority_desired_version, 100*desired_version_counts[majority_desired_version]/sum(desired_version_counts.itervalues()))) if bitcoind_getinfo['warnings'] != '': @@ -712,6 +957,8 @@ def __init__(self, prefix, net, share_cb, verified_hash_cb): self.dirname = os.path.dirname(os.path.abspath(prefix)) self.filename = os.path.basename(os.path.abspath(prefix)) self.net = net + + start = time.time() known = {} filenames, next = self.get_filenames_and_next() @@ -744,6 +991,8 @@ def __init__(self, prefix, net, share_cb, verified_hash_cb): self.known = known # filename -> (set of share hashes, set of verified hashes) self.known_desired = dict((k, (set(a), set(b))) for k, (a, b) in known.iteritems()) + + print "Share loading took %.3f seconds" % (time.time() - start) def _add_line(self, line): filenames, next = self.get_filenames_and_next() diff --git a/p2pool/main.py b/p2pool/main.py index af823d4e..818c58cb 100644 --- a/p2pool/main.py +++ b/p2pool/main.py @@ -64,13 +64,17 @@ def updatestamp(self, n): def paytotal(self): self.payouttotal = 0.0 + print("pubkeys.keys: %s" % pubkeys.keys) for i in range(len(pubkeys.keys)): - self.payouttotal += node.get_current_txouts().get(bitcoin_data.pubkey_hash_to_script2(pubkeys.keys[i]['hash'], pubkeys.keys[i]['version'], net), 0)*1e-8 + self.payouttotal += node.get_current_txouts().get( + pubkeys.keys[i]['address'], 0) * 1e-8 return self.payouttotal def getpaytotal(self): return self.payouttotal +gnode = None # for debugging via rconsole/rfoo only + @defer.inlineCallbacks def main(args, net, datadir_path, merged_urls, worker_endpoint): try: @@ -99,13 +103,13 @@ def long(): url = '%s://%s:%i/' % ('https' if args.bitcoind_rpc_ssl else 'http', args.bitcoind_address, args.bitcoind_rpc_port) print '''Testing bitcoind RPC connection to '%s' with username '%s'...''' % (url, args.bitcoind_rpc_username) bitcoind = jsonrpc.HTTPProxy(url, dict(Authorization='Basic ' + base64.b64encode(args.bitcoind_rpc_username + ':' + args.bitcoind_rpc_password)), timeout=30) - yield helper.check(bitcoind, net) + yield helper.check(bitcoind, net, args) temp_work = yield helper.getwork(bitcoind) bitcoind_getinfo_var = variable.Variable(None) @defer.inlineCallbacks def poll_warnings(): - bitcoind_getinfo_var.set((yield deferral.retry('Error while calling getnetworkinfo:')(bitcoind.rpc_getnetworkinfo)())) + bitcoind_getinfo_var.set((yield deferral.retry('Error while calling getinfo:')(bitcoind.rpc_getnetworkinfo)())) yield poll_warnings() deferral.RobustLoopingCall(poll_warnings).start(20*60) @@ -134,25 +138,25 @@ def poll_warnings(): if not res['ismine']: print ' Cached address is either invalid or not controlled by local bitcoind!' address = None - + if address is None: print ' Getting payout address from bitcoind...' - address = yield deferral.retry('Error getting payout address from bitcoind:', 5)(lambda: bitcoind.rpc_getnewaddress('p2pool', 'legacy'))() - + address = yield deferral.retry('Error getting payout address from bitcoind:', 5)(lambda: bitcoind.rpc_getaccountaddress('p2pool'))() + with open(address_path, 'wb') as f: f.write(address) - - my_pubkey_hash, my_pubkey_hash_version = bitcoin_data.address_to_pubkey_hash(address, net.PARENT) - print ' ...success! Payout address:', bitcoin_data.pubkey_hash_to_address(my_pubkey_hash, net.PARENT, my_pubkey_hash_version) - print - - pubkeys.addkey({'hash': my_pubkey_hash, 'version': my_pubkey_hash_version}) + + my_address = address + print(' ...success! Payout address: %s' % my_address) + print() + + pubkeys.addkey({'address': my_address}) elif args.address != 'dynamic': - my_pubkey_hash = args.pubkey_hash - my_pubkey_hash_version = args.pubkey_hash_version - print ' ...success! Payout address:', bitcoin_data.pubkey_hash_to_address(my_pubkey_hash, net.PARENT, my_pubkey_hash_version) - print - pubkeys.addkey({'hash': my_pubkey_hash, 'version': my_pubkey_hash_version}) + my_address = args.address + print(' ...success! Payout address: %s' % my_address) + print() + + pubkeys.addkey({'address': my_address}) else: print ' Entering dynamic address mode.' @@ -160,17 +164,15 @@ def poll_warnings(): print ' ERROR: Can not use fewer than 2 addresses in dynamic mode. Resetting to 2.' args.numaddresses = 2 for i in range(args.numaddresses): - address = yield deferral.retry('Error getting a dynamic address from bitcoind:', 5)(lambda: bitcoind.rpc_getnewaddress('p2pool'))() - new_pubkey, pubkey_version = bitcoin_data.address_to_pubkey_hash(address, net.PARENT) - pubkeys.addkey({'hash': new_pubkey, 'version': pubkey_version}) + address = yield deferral.retry('Error getting a dynamic address from bitcoind:', 5)(lambda: bitcoind.rpc_getnewaddress('p2pool', 'legacy'))() + pubkeys.addkey({'address': address}) pubkeys.updatestamp(time.time()) - my_pubkey_hash = pubkeys.keys[0]['hash'] - my_pubkey_hash_version = pubkeys.keys[0]['version'] + my_address = pubkeys.keys[0]['address'] for i in range(len(pubkeys.keys)): - print ' ...payout %d: %s' % (i, bitcoin_data.pubkey_hash_to_address(pubkeys.keys[i]['hash'], net.PARENT, pubkeys.keys[i]['version']),) + print(' ...payout %d: %s' % (i, pubkeys[i]['address'])) print "Loading shares..." shares = {} @@ -187,7 +189,8 @@ def share_cb(share): print 'Initializing work...' - node = p2pool_node.Node(factory, bitcoind, shares.values(), known_verified, net) + global gnode + gnode = node = p2pool_node.Node(factory, bitcoind, shares.values(), known_verified, net) yield node.start() for share_hash in shares: @@ -288,14 +291,9 @@ def upnp_thread(): print 'Listening for workers on %r port %i...' % (worker_endpoint[0], worker_endpoint[1]) - #wb = work.WorkerBridge(node, my_pubkey_hash, args.donation_percentage, merged_urls, args.worker_fee, args, pubkeys, bitcoind) - if args.address_share_rate is not None: - share_rate_type = 'address' - share_rate = args.address_share_rate - else: - share_rate_type = 'miner' - share_rate = args.miner_share_rate - wb = work.WorkerBridge(node, my_pubkey_hash, my_pubkey_hash_version, 0.0, merged_urls, args.worker_fee, args, pubkeys, bitcoind, args.min_difficulty, share_rate, share_rate_type) + wb = work.WorkerBridge(node, my_address, 0.0, + merged_urls, args.worker_fee, args, pubkeys, + bitcoind, args.share_rate) web_root = web.get_web_root(wb, datadir_path, bitcoind_getinfo_var, static_dir=args.web_static) caching_wb = worker_interface.CachingWorkerBridge(wb) worker_interface.WorkerInterface(caching_wb).attach_to(web_root, get_handler=lambda request: request.redirect('/static/')) @@ -344,7 +342,15 @@ def new_share(share): return if share.pow_hash <= share.header['bits'].target and abs(share.timestamp - time.time()) < 10*60: yield deferral.sleep(random.expovariate(1/60)) - message = '\x02%s BLOCK FOUND by %s! %s%064x' % (net.NAME.upper(), bitcoin_data.script2_to_address(share.new_script, net.PARENT), net.PARENT.BLOCK_EXPLORER_URL_PREFIX, share.header_hash) + message = '\x02%s BLOCK FOUND by %s! %s%064x' % ( + net.NAME.upper(), + bitcoin_data.script2_to_address( + share.new_script, net.ADDRESS_VERSION, + -1, net.PARENT) if + share.VERSION < 34 else + share.address, + net.PARENT.BLOCK_EXPLORER_URL_PREFIX, + share.header_hash) if all('%x' % (share.header_hash,) not in old_message for old_message in self.recent_messages): self.say(self.channel, message) self._remember_message(message) @@ -373,7 +379,7 @@ def status_thread(): last_str = None last_time = 0 while True: - yield deferral.sleep(3) + yield deferral.sleep(30) try: height = node.tracker.get_height(node.best_share_var.value) this_str = 'P2Pool: %i shares in chain (%i verified/%i total) Peers: %i (%i incoming)' % ( @@ -402,7 +408,8 @@ def status_thread(): paystr = '' paytot = 0.0 for i in range(len(pubkeys.keys)): - curtot = node.get_current_txouts().get(bitcoin_data.pubkey_hash_to_script2(pubkeys.keys[i]['hash'], pubkeys.keys[i]['version'], net.PARENT), 0) + curtot = node.get_current_txouts().get( + pubkeys.keys[i]['address'], 0) paytot += curtot*1e-8 paystr += "(%.4f)" % (curtot*1e-8,) paystr += "=%.4f" % (paytot,) @@ -456,6 +463,13 @@ def run(): parser.add_argument('--debug', help='enable debugging mode', action='store_const', const=True, default=False, dest='debug') + parser.add_argument('--bench', + help='enable CPU performance profiling mode', + action='store_const', const=True, default=False, dest='bench') + parser.add_argument('--rconsole', + help='enable rconsole debugging mode (requires rfoo)', + action='store_const', const=True, default=False, dest='rconsole') + parser.add_argument('-a', '--address', help='generate payouts to this address (default:
), or (dynamic)', type=str, action='store', default=None, dest='address') @@ -477,6 +491,9 @@ def run(): parser.add_argument('--merged', help='call getauxblock on this url to get work for merged mining (example: http://ncuser:ncpass@127.0.0.1:10332/)', type=str, action='append', default=[], dest='merged_urls') + parser.add_argument('--coinbtext', + help='append this text to the coinbase', + type=str, action='append', default=[], dest='coinb_texts') parser.add_argument('--iocp', help='use Windows IOCP API in order to avoid errors due to large number of sockets being open', action='store_true', default=False, dest='iocp') @@ -517,16 +534,9 @@ def run(): worker_group.add_argument('-f', '--fee', metavar='FEE_PERCENTAGE', help='''charge workers mining to their own bitcoin address (by setting their miner's username to a bitcoin address) this percentage fee to mine on your p2pool instance. Amount displayed at http://127.0.0.1:WORKER_PORT/fee (default: 0)''', type=float, action='store', default=0, dest='worker_fee') - - worker_group.add_argument('--miner-share-rate', metavar='SHARES_PER_MINUTE', - help='number of psuedoshares per minute for each miner', - type=float, action='store', default=None, dest='miner_share_rate') - worker_group.add_argument('--address-share-rate', metavar='SHARES_PER_MINUTE', - help='number of psuedoshares per minute for each address', - type=float, action='store', default=None, dest='address_share_rate') - worker_group.add_argument('--min-difficulty', metavar='DIFFICULTY', - help='minium difficulty for miners', - type=float, action='store', default=1.0, dest='min_difficulty') + worker_group.add_argument('-s', '--share-rate', metavar='SECONDS_PER_SHARE', + help='Auto-adjust mining difficulty on each connection to target this many seconds per pseudoshare (default: %3.0f)' % 3., + type=float, action='store', default=3., dest='share_rate') bitcoind_group = parser.add_argument_group('bitcoind interface') bitcoind_group.add_argument('--bitcoind-config-path', metavar='BITCOIND_CONFIG_PATH', @@ -547,6 +557,9 @@ def run(): bitcoind_group.add_argument(metavar='BITCOIND_RPCUSERPASS', help='bitcoind RPC interface username, then password, space-separated (only one being provided will cause the username to default to being empty, and none will cause P2Pool to read them from bitcoin.conf)', type=str, action='store', default=[], nargs='*', dest='bitcoind_rpc_userpass') + bitcoind_group.add_argument('--allow-obsolete-bitcoind', + help='allow the use of coin daemons (bitcoind) that do not support all of the required softforks for this network (e.g. Bitcoin Core and segwit2x)', + action='store_const', const=True, default=False, dest='allow_obsolete_bitcoind') args = parser.parse_args() @@ -555,12 +568,11 @@ def run(): defer.setDebugging(True) else: p2pool.DEBUG = False + p2pool.BENCH = args.bench net_name = args.net_name + ('_testnet' if args.testnet else '') net = networks.nets[net_name] - args.min_difficulty /= net.PARENT.DUMB_SCRYPT_DIFF - datadir_path = os.path.join((os.path.join(os.path.dirname(sys.argv[0]), 'data') if args.datadir is None else args.datadir), net_name) if not os.path.exists(datadir_path): os.makedirs(datadir_path) @@ -626,7 +638,8 @@ def run(): if args.address is not None and args.address != 'dynamic': try: - args.pubkey_hash, args.pubkey_hash_version = bitcoin_data.address_to_pubkey_hash(args.address, net.PARENT) + _ = bitcoin_data.address_to_pubkey_hash(args.address, net.PARENT) + args.pubkey_hash = True except Exception, e: parser.error('error parsing address: ' + repr(e)) else: @@ -682,6 +695,9 @@ def emit(self, eventDict): ).addBoth(lambda x: None) if not args.no_bugreport: log.addObserver(ErrorReporter().emit) - + if args.rconsole: + from rfoo.utils import rconsole + rconsole.spawn_server() + reactor.callWhenRunning(main, args, net, datadir_path, merged_urls, worker_endpoint) reactor.run() diff --git a/p2pool/networks/vertcoin.py b/p2pool/networks/vertcoin.py index 59a64997..92ddd6af 100644 --- a/p2pool/networks/vertcoin.py +++ b/p2pool/networks/vertcoin.py @@ -1,21 +1,29 @@ from p2pool.bitcoin import networks -PARENT=networks.nets['vertcoin'] -SHARE_PERIOD=15 # seconds -CHAIN_LENGTH=24*60*60//10 # shares -REAL_CHAIN_LENGTH=24*60*60//10 # shares -TARGET_LOOKBEHIND=200 # shares -SPREAD=12 # blocks -IDENTIFIER='a06a81c827cab983'.decode('hex') -PREFIX='7c3614a6bcdcf784'.decode('hex') -P2P_PORT=9346 -MIN_TARGET=4 -MAX_TARGET=2**256//2**20 - 1 -PERSIST=False -WORKER_PORT=9171 -BOOTSTRAP_ADDRS='fr1.vtconline.org p2proxy.vertcoin.org vtc.consumableresources.com'.split(' ') -ANNOUNCE_CHANNEL='#p2pool-vtc' -VERSION_CHECK=lambda v: True +PARENT = networks.nets['vertcoin'] +SHARE_PERIOD = 30 +CHAIN_LENGTH=24*60*60//30 # shares +REAL_CHAIN_LENGTH=24*60*60//30 # shares +TARGET_LOOKBEHIND = 100 # shares +SPREAD = 12 # blocks +IDENTIFIER = '4B62545B1A631A5C'.decode('hex') +PREFIX = '1c0c1c71cc197bc1'.decode('hex') +P2P_PORT = 9346 +MIN_TARGET = 0 +MAX_TARGET = 2**256//2**20 - 1 +PERSIST = True # Set to False for solo mining or starting a new chain +WORKER_PORT = 9171 +BOOTSTRAP_ADDRS = [ + 'p2p-south.xyz', + 'p2p-ekb.xyz', + 'p2p-usa.xyz', + 'p2p-spb.xyz', + ] +ANNOUNCE_CHANNEL = '#p2pool' +VERSION_CHECK = lambda v: True +VERSION_WARNING = lambda v: None SOFTFORKS_REQUIRED = set(['bip34', 'bip66', 'bip65', 'csv', 'segwit']) -SEGWIT_ACTIVATION_VERSION = 16 -MINIMUM_PROTOCOL_VERSION = 1800 +MINIMUM_PROTOCOL_VERSION = 3501 +SEGWIT_ACTIVATION_VERSION = 35 +BLOCK_MAX_SIZE = 8000000 +BLOCK_MAX_WEIGHT = 32000000 diff --git a/p2pool/node.py b/p2pool/node.py index 4a91620d..debc3989 100644 --- a/p2pool/node.py +++ b/p2pool/node.py @@ -17,7 +17,8 @@ def __init__(self, node, **kwargs): best_share_hash_func=lambda: node.best_share_var.value, net=node.net, known_txs_var=node.known_txs_var, - mining_txs_var=node.mining_txs_var, + mining_txs_var=node.mining_txs_var, # transactions from getblocktemplate + mining2_txs_var=node.mining2_txs_var, # transactions sent to miners **kwargs) def handle_shares(self, shares, peer): @@ -40,9 +41,7 @@ def handle_shares(self, shares, peer): self.node.tracker.add(share) - new_known_txs = dict(self.node.known_txs_var.value) - new_known_txs.update(all_new_txs) - self.node.known_txs_var.set(new_known_txs) + self.node.known_txs_var.add(all_new_txs) if new_count: self.node.set_best_share() @@ -63,6 +62,7 @@ def handle_share_hashes(self, hashes, peer): ) except: log.err(None, 'in handle_share_hashes:') + peer.badPeerHappened(30) else: self.handle_shares([(share, []) for share in shares], peer) @@ -127,6 +127,7 @@ def download_shares(): continue except: log.err(None, 'in download_shares:') + peer.badPeerHappened(30) continue if not shares: @@ -161,9 +162,21 @@ def __init__(self, factory, bitcoind, shares, known_verified_share_hashes, net): self.factory = factory self.bitcoind = bitcoind self.net = net - + self.cur_share_ver = None + + self.known_txs_var = variable.VariableDict({}) # hash -> tx + self.mining_txs_var = variable.Variable({}) # hash -> tx + self.mining2_txs_var = variable.Variable({}) # hash -> tx + self.best_share_var = variable.Variable(None) + self.desired_var = variable.Variable(None) + self.txidcache = {} + self.feecache = {} + self.feefifo = [] + self.punish = False + self.tracker = p2pool_data.OkayTracker(self.net) + for share in shares: self.tracker.add(share) @@ -172,7 +185,18 @@ def __init__(self, factory, bitcoind, shares, known_verified_share_hashes, net): self.tracker.verified.add(self.tracker.items[share_hash]) self.p2p_node = None # overwritten externally - + + def check_and_purge_txs(self): + if self.cur_share_ver < 34: + return + best_share = self.tracker.items.get( + self.best_share_var.value, None) + if not best_share: + return + prev_block = best_share.header['previous_block'] + if prev_block != self.bitcoind_work.value['previous_block']: + self.known_txs_var.set({}) + @defer.inlineCallbacks def start(self): stop_signal = variable.Event() @@ -181,12 +205,14 @@ def start(self): # BITCOIND WORK self.bitcoind_work = variable.Variable((yield helper.getwork(self.bitcoind))) + @defer.inlineCallbacks def work_poller(): while stop_signal.times == 0: flag = self.factory.new_block.get_deferred() try: - self.bitcoind_work.set((yield helper.getwork(self.bitcoind, self.bitcoind_work.value['use_getblocktemplate']))) + self.bitcoind_work.set((yield helper.getwork(self.bitcoind, self.bitcoind_work.value['use_getblocktemplate'], self.txidcache, self.feecache, self.feefifo, self.known_txs_var.value))) + self.check_and_purge_txs() except: log.err() yield defer.DeferredList([flag, deferral.sleep(15)], fireOnOneCallback=True) @@ -211,6 +237,7 @@ def handle_header(new_header): )): # new is current and previous is not a child of current self.best_block_header.set(new_header) self.handle_header = handle_header + @defer.inlineCallbacks def poll_header(): if self.factory.conn.value is None: @@ -221,12 +248,7 @@ def poll_header(): # BEST SHARE - self.known_txs_var = variable.Variable({}) # hash -> tx - self.mining_txs_var = variable.Variable({}) # hash -> tx - self.get_height_rel_highest = yield height_tracker.get_height_rel_highest_func(self.bitcoind, self.factory, lambda: self.bitcoind_work.value['previous_block'], self.net) - - self.best_share_var = variable.Variable(None) - self.desired_var = variable.Variable(None) + self.get_height_rel_highest, self.get_height = yield height_tracker.get_height_funcs(self.bitcoind, self.factory, lambda: self.bitcoind_work.value['previous_block'], self.net) self.bitcoind_work.changed.watch(lambda _: self.set_best_share()) self.set_best_share() @@ -235,67 +257,83 @@ def poll_header(): # update mining_txs according to getwork results @self.bitcoind_work.changed.run_and_watch def _(_=None): - new_mining_txs = {} - new_known_txs = dict(self.known_txs_var.value) - for tx_hash, tx in zip(self.bitcoind_work.value['transaction_hashes'], self.bitcoind_work.value['transactions']): - new_mining_txs[tx_hash] = tx - new_known_txs[tx_hash] = tx + new_mining_txs = dict(zip(self.bitcoind_work.value['transaction_hashes'], self.bitcoind_work.value['transactions'])) + added_known_txs = {hsh:tx for hsh,tx in new_mining_txs.iteritems() if not hsh in self.known_txs_var.value} self.mining_txs_var.set(new_mining_txs) - self.known_txs_var.set(new_known_txs) + self.known_txs_var.add(added_known_txs) # add p2p transactions from bitcoind to known_txs @self.factory.new_tx.watch def _(tx): - new_known_txs = dict(self.known_txs_var.value) - new_known_txs[bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx))] = tx - self.known_txs_var.set(new_known_txs) - # forward transactions seen to bitcoind - @self.known_txs_var.transitioned.watch - @defer.inlineCallbacks - def _(before, after): - yield deferral.sleep(random.expovariate(1/1)) - if self.factory.conn.value is None: - return - for tx_hash in set(after) - set(before): - self.factory.conn.value.send_tx(tx=after[tx_hash]) + self.known_txs_var.add({ + bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx)): tx, + }) + + if self.cur_share_ver < 34: + # forward transactions seen to bitcoind + @self.known_txs_var.transitioned.watch + @defer.inlineCallbacks + def _(before, after): + yield deferral.sleep(random.expovariate(1/1)) + if self.factory.conn.value is None: + return + for tx_hash in set(after) - set(before): + self.factory.conn.value.send_tx(tx=after[tx_hash]) @self.tracker.verified.added.watch def _(share): if not (share.pow_hash <= share.header['bits'].target): return + if share.VERSION >= 34: + print 'GOT BLOCK FROM PEER! %s %s%064x' % ( + p2pool_data.format_hash(share.hash), + self.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, + share.header_hash) + return block = share.as_block(self.tracker, self.known_txs_var.value) if block is None: print >>sys.stderr, 'GOT INCOMPLETE BLOCK FROM PEER! %s bitcoin: %s%064x' % (p2pool_data.format_hash(share.hash), self.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, share.header_hash) return - helper.submit_block(block, True, self.factory, self.bitcoind, self.bitcoind_work, self.net) + helper.submit_block(block, True, self) print print 'GOT BLOCK FROM PEER! Passing to bitcoind! %s bitcoin: %s%064x' % (p2pool_data.format_hash(share.hash), self.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, share.header_hash) print - + def forget_old_txs(): new_known_txs = {} if self.p2p_node is not None: for peer in self.p2p_node.peers.itervalues(): new_known_txs.update(peer.remembered_txs) new_known_txs.update(self.mining_txs_var.value) + new_known_txs.update(self.mining2_txs_var.value) for share in self.tracker.get_chain(self.best_share_var.value, min(120, self.tracker.get_height(self.best_share_var.value))): + if share.VERSION >= 34: + continue for tx_hash in share.new_transaction_hashes: if tx_hash in self.known_txs_var.value: new_known_txs[tx_hash] = self.known_txs_var.value[tx_hash] self.known_txs_var.set(new_known_txs) - t = deferral.RobustLoopingCall(forget_old_txs) - t.start(10) - stop_signal.watch(t.stop) + if self.cur_share_ver < 34: + t = deferral.RobustLoopingCall(forget_old_txs) + t.start(10) + stop_signal.watch(t.stop) t = deferral.RobustLoopingCall(self.clean_tracker) t.start(5) stop_signal.watch(t.stop) def set_best_share(self): - best, desired, decorated_heads, bad_peer_addresses = self.tracker.think(self.get_height_rel_highest, self.bitcoind_work.value['previous_block'], self.bitcoind_work.value['bits'], self.known_txs_var.value) - + oldpunish = self.punish + best, desired, decorated_heads, bad_peer_addresses, self.punish= self.tracker.think(self.get_height_rel_highest, self.get_height, self.bitcoind_work.value['previous_block'], self.bitcoind_work.value['bits'], self.known_txs_var.value, self.feecache) + if self.punish and not oldpunish and best == self.best_share_var.value: # need to reissue work with lower difficulty + self.best_share_var.changed.happened(best) # triggers wb.new_work_event to reissue work + self.best_share_var.set(best) self.desired_var.set(desired) + try: + self.cur_share_ver = self.tracker.items[best].VERSION + except KeyError: + self.cur_share_ver = p2pool_data.BaseShare.VERSION if self.p2p_node is not None: for bad_peer_address in bad_peer_addresses: # XXX O(n) @@ -304,11 +342,12 @@ def set_best_share(self): peer.badPeerHappened() break + def get_current_txouts(self): return p2pool_data.get_expected_payouts(self.tracker, self.best_share_var.value, self.bitcoind_work.value['bits'].target, self.bitcoind_work.value['subsidy'], self.net) def clean_tracker(self): - best, desired, decorated_heads, bad_peer_addresses = self.tracker.think(self.get_height_rel_highest, self.bitcoind_work.value['previous_block'], self.bitcoind_work.value['bits'], self.known_txs_var.value) + best, desired, decorated_heads, bad_peer_addresses, self.punish = self.tracker.think(self.get_height_rel_highest, self.get_height, self.bitcoind_work.value['previous_block'], self.bitcoind_work.value['bits'], self.known_txs_var.value, self.feecache) # eat away at heads if decorated_heads: diff --git a/p2pool/p2p.py b/p2pool/p2p.py index de164f5f..b79c5425 100644 --- a/p2pool/p2p.py +++ b/p2pool/p2p.py @@ -5,7 +5,7 @@ import sys import time -from twisted.internet import defer, protocol, reactor +from twisted.internet import defer, protocol, reactor, task from twisted.python import failure, log import p2pool @@ -25,12 +25,12 @@ def fragment(f, **kwargs): fragment(f, **dict((k, v[len(v)//2:]) for k, v in kwargs.iteritems())) class Protocol(p2protocol.Protocol): - VERSION = 1800 + VERSION = 3501 - max_remembered_txs_size = 2500000 + max_remembered_txs_size = 25000000 def __init__(self, node, incoming): - p2protocol.Protocol.__init__(self, node.net.PREFIX, 1000000, node.traffic_happened) + p2protocol.Protocol.__init__(self, node.net.PREFIX, 32000000, node.traffic_happened) self.node = node self.incoming = incoming @@ -93,11 +93,16 @@ def packetReceived(self, command, payload2): print 'Peer %s:%i misbehaving, will drop and ban. Reason:' % self.addr, e.message self.badPeerHappened() - def badPeerHappened(self): + def badPeerHappened(self, bantime=3600): print "Bad peer banned:", self.addr self.disconnect() if self.transport.getPeer().host != '127.0.0.1': # never ban localhost - self.node.bans[self.transport.getPeer().host] = time.time() + 60*60 + host = self.transport.getPeer().host + if not host in self.node.banscores: + self.node.banscores[host] = 1 + else: + self.node.banscores[host] += 1 + self.node.bans[self.transport.getPeer().host] = time.time() + bantime * self.node.banscores[host]**2 def _timeout(self): self.timeout_delayed = None @@ -142,6 +147,7 @@ def sendAdvertisement(self): ('best_share_hash', pack.PossiblyNoneType(0, pack.IntType(256))), ]) def handle_version(self, version, services, addr_to, addr_from, nonce, sub_version, mode, best_share_hash): + print "Peer %s:%s says protocol version is %s, client version %s" % (addr_from['address'], addr_from['port'], version, sub_version) if self.other_version is not None: raise PeerMisbehavingError('more than one version message') if version < getattr(self.node.net, 'MINIMUM_PROTOCOL_VERSION', 1400): @@ -186,7 +192,29 @@ def new_dataReceived(data): if best_share_hash is not None: self.node.handle_share_hashes([best_share_hash], self) + if self.node.node.cur_share_ver >= 34: + return + + def add_to_remote_view_of_my_known_txs(added): + if added: + self.send_have_tx(tx_hashes=list(added.keys())) + + watch_id0 = self.node.known_txs_var.added.watch(add_to_remote_view_of_my_known_txs) + self.connection_lost_event.watch(lambda: self.node.known_txs_var.added.unwatch(watch_id0)) + + def remove_from_remote_view_of_my_known_txs(removed): + if removed: + self.send_losing_tx(tx_hashes=list(removed.keys())) + + # cache forgotten txs here for a little while so latency of "losing_tx" packets doesn't cause problems + key = max(self.known_txs_cache) + 1 if self.known_txs_cache else 0 + self.known_txs_cache[key] = removed #dict((h, before[h]) for h in removed) + reactor.callLater(20, self.known_txs_cache.pop, key) + watch_id1 = self.node.known_txs_var.removed.watch(remove_from_remote_view_of_my_known_txs) + self.connection_lost_event.watch(lambda: self.node.known_txs_var.removed.unwatch(watch_id1)) + def update_remote_view_of_my_known_txs(before, after): + t0 = time.time() added = set(after) - set(before) removed = set(before) - set(after) if added: @@ -198,12 +226,15 @@ def update_remote_view_of_my_known_txs(before, after): key = max(self.known_txs_cache) + 1 if self.known_txs_cache else 0 self.known_txs_cache[key] = dict((h, before[h]) for h in removed) reactor.callLater(20, self.known_txs_cache.pop, key) - watch_id = self.node.known_txs_var.transitioned.watch(update_remote_view_of_my_known_txs) - self.connection_lost_event.watch(lambda: self.node.known_txs_var.transitioned.unwatch(watch_id)) + t1 = time.time() + if p2pool.BENCH and (t1-t0) > .01: print "%8.3f ms for update_remote_view_of_my_known_txs" % ((t1-t0)*1000.) + watch_id2 = self.node.known_txs_var.transitioned.watch(update_remote_view_of_my_known_txs) + self.connection_lost_event.watch(lambda: self.node.known_txs_var.transitioned.unwatch(watch_id2)) self.send_have_tx(tx_hashes=self.node.known_txs_var.value.keys()) def update_remote_view_of_my_mining_txs(before, after): + t0 = time.time() added = set(after) - set(before) removed = set(before) - set(after) if removed: @@ -213,6 +244,9 @@ def update_remote_view_of_my_mining_txs(before, after): self.remote_remembered_txs_size += sum(100 + bitcoin_data.tx_type.packed_size(after[x]) for x in added) assert self.remote_remembered_txs_size <= self.max_remembered_txs_size fragment(self.send_remember_tx, tx_hashes=[x for x in added if x in self.remote_tx_hashes], txs=[after[x] for x in added if x not in self.remote_tx_hashes]) + t1 = time.time() + if p2pool.BENCH and (t1-t0) > .01: print "%8.3f ms for update_remote_view_of_my_mining_txs" % ((t1-t0)*1000.) + watch_id2 = self.node.mining_txs_var.transitioned.watch(update_remote_view_of_my_mining_txs) self.connection_lost_event.watch(lambda: self.node.mining_txs_var.transitioned.unwatch(watch_id2)) @@ -281,11 +315,12 @@ def handle_getaddrs(self, count): ('shares', pack.ListType(p2pool_data.share_type)), ]) def handle_shares(self, shares): + t0 = time.time() result = [] for wrappedshare in shares: if wrappedshare['type'] < p2pool_data.Share.VERSION: continue share = p2pool_data.load_share(wrappedshare, self.node.net, self.addr) - if wrappedshare['type'] >= 13: + if 13 <= wrappedshare['type'] < 34: txs = [] for tx_hash in share.share_info['new_transaction_hashes']: if tx_hash in self.node.known_txs_var.value: @@ -294,7 +329,8 @@ def handle_shares(self, shares): for cache in self.known_txs_cache.itervalues(): if tx_hash in cache: tx = cache[tx_hash] - print 'Transaction %064x rescued from peer latency cache!' % (tx_hash,) + if p2pool.DEBUG: + print 'Transaction %064x rescued from peer latency cache!' % (tx_hash,) break else: print >>sys.stderr, 'Peer referenced unknown transaction %064x, disconnecting' % (tx_hash,) @@ -307,13 +343,25 @@ def handle_shares(self, shares): result.append((share, txs)) self.node.handle_shares(result, self) + t1 = time.time() + if p2pool.BENCH: print "%8.3f ms for %i shares in handle_shares (%3.3f ms/share)" % ((t1-t0)*1000., len(shares), (t1-t0)*1000./ max(1, len(shares))) + def sendShares(self, shares, tracker, known_txs, include_txs_with=[]): + t0 = time.time() tx_hashes = set() + hashes_to_send = [] for share in shares: - if share.VERSION >= 13: + if share.VERSION >= 34: + continue + elif share.VERSION >= 13: # send full transaction for every new_transaction_hash that peer does not know for tx_hash in share.share_info['new_transaction_hashes']: + if not tx_hash in known_txs: + newset = set(share.share_info['new_transaction_hashes']) + ktxset = set(known_txs) + missing = newset - ktxset + print "Missing %i of %i transactions for broadcast" % (len(missing), len(newset)) assert tx_hash in known_txs, 'tried to broadcast share without knowing all its new transactions' if tx_hash not in self.remote_tx_hashes: tx_hashes.add(tx_hash) @@ -323,20 +371,32 @@ def sendShares(self, shares, tracker, known_txs, include_txs_with=[]): if x is not None: tx_hashes.update(x) - hashes_to_send = [x for x in tx_hashes if x not in self.node.mining_txs_var.value and x in known_txs] - - new_remote_remembered_txs_size = self.remote_remembered_txs_size + sum(100 + bitcoin_data.tx_type.packed_size(known_txs[x]) for x in hashes_to_send) - if new_remote_remembered_txs_size > self.max_remembered_txs_size: - raise ValueError('shares have too many txs') - self.remote_remembered_txs_size = new_remote_remembered_txs_size - - fragment(self.send_remember_tx, tx_hashes=[x for x in hashes_to_send if x in self.remote_tx_hashes], txs=[known_txs[x] for x in hashes_to_send if x not in self.remote_tx_hashes]) - + hashes_to_send = [x for x in tx_hashes if x not in self.node.mining_txs_var.value and x in known_txs] + all_hashes = share.share_info['new_transaction_hashes'] + new_tx_size = sum(100 + bitcoin_data.tx_type.packed_size(known_txs[x]) for x in hashes_to_send) + all_tx_size = sum(100 + bitcoin_data.tx_type.packed_size(known_txs[x]) for x in all_hashes) + print "Sending a share with %i txs (%i new) totaling %i msg bytes (%i new)" % (len(all_hashes), len(hashes_to_send), all_tx_size, new_tx_size) + + if tx_hashes: + hashes_to_send = [x for x in tx_hashes if x not in self.node.mining_txs_var.value and x in known_txs] + new_tx_size = sum(100 + bitcoin_data.tx_type.packed_size(known_txs[x]) for x in hashes_to_send) + + new_remote_remembered_txs_size = self.remote_remembered_txs_size + new_tx_size + if new_remote_remembered_txs_size > self.max_remembered_txs_size: + raise ValueError('shares have too many txs') + self.remote_remembered_txs_size = new_remote_remembered_txs_size + + fragment(self.send_remember_tx, tx_hashes=[x for x in hashes_to_send if x in self.remote_tx_hashes], txs=[known_txs[x] for x in hashes_to_send if x not in self.remote_tx_hashes]) + fragment(self.send_shares, shares=[share.as_share() for share in shares]) - - self.send_forget_tx(tx_hashes=hashes_to_send) - - self.remote_remembered_txs_size -= sum(100 + bitcoin_data.tx_type.packed_size(known_txs[x]) for x in hashes_to_send) + + if hashes_to_send: + self.send_forget_tx(tx_hashes=hashes_to_send) + + self.remote_remembered_txs_size -= new_tx_size + t1 = time.time() + if p2pool.BENCH: print "%8.3f ms for %i shares in sendShares (%3.3f ms/share)" % ((t1-t0)*1000., len(shares), (t1-t0)*1000./ max(1, len(shares))) + message_sharereq = pack.ComposedType([ @@ -385,8 +445,12 @@ def handle_have_tx(self, tx_hashes): ('tx_hashes', pack.ListType(pack.IntType(256))), ]) def handle_losing_tx(self, tx_hashes): + t0 = time.time() #assert self.remote_tx_hashes.issuperset(tx_hashes) self.remote_tx_hashes.difference_update(tx_hashes) + t1 = time.time() + if p2pool.BENCH and (t1-t0) > .01: print "%8.3f ms for %i txs in handle_losing_tx (%3.3f ms/tx)" % ((t1-t0)*1000., len(tx_hashes), (t1-t0)*1000./ max(1, len(tx_hashes))) + message_remember_tx = pack.ComposedType([ @@ -394,6 +458,7 @@ def handle_losing_tx(self, tx_hashes): ('txs', pack.ListType(bitcoin_data.tx_type)), ]) def handle_remember_tx(self, tx_hashes, txs): + t0 = time.time() for tx_hash in tx_hashes: if tx_hash in self.remembered_txs: print >>sys.stderr, 'Peer referenced transaction twice, disconnecting' @@ -415,7 +480,7 @@ def handle_remember_tx(self, tx_hashes, txs): self.remembered_txs[tx_hash] = tx self.remembered_txs_size += 100 + bitcoin_data.tx_type.packed_size(tx) - new_known_txs = dict(self.node.known_txs_var.value) + added_known_txs = {} warned = False for tx in txs: tx_hash = bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx)) @@ -424,16 +489,18 @@ def handle_remember_tx(self, tx_hashes, txs): self.disconnect() return - if tx_hash in self.node.known_txs_var.value and not warned: + if tx_hash in self.node.known_txs_var.value and not warned and p2pool.DEBUG: print 'Peer sent entire transaction %064x that was already received' % (tx_hash,) warned = True self.remembered_txs[tx_hash] = tx self.remembered_txs_size += 100 + bitcoin_data.tx_type.packed_size(tx) - new_known_txs[tx_hash] = tx - self.node.known_txs_var.set(new_known_txs) + added_known_txs[tx_hash] = tx + self.node.known_txs_var.add(added_known_txs) if self.remembered_txs_size >= self.max_remembered_txs_size: raise PeerMisbehavingError('too much transaction data stored') + t1 = time.time() + if p2pool.BENCH and (t1-t0) > .01: print "%8.3f ms for %i txs in p2p.py:handle_remember_tx (%3.3f ms/tx)" % ((t1-t0)*1000., len(tx_hashes), ((t1-t0)*1000. / max(1,len(tx_hashes)) )) message_forget_tx = pack.ComposedType([ ('tx_hashes', pack.ListType(pack.IntType(256))), ]) @@ -609,7 +676,7 @@ def proto_disconnected(self, proto, reason): self.node.lost_conn(proto, reason) class Node(object): - def __init__(self, best_share_hash_func, port, net, addr_store={}, connect_addrs=set(), desired_outgoing_conns=10, max_outgoing_attempts=30, max_incoming_conns=50, preferred_storage=1000, known_txs_var=variable.Variable({}), mining_txs_var=variable.Variable({}), advertise_ip=True, external_ip=None): + def __init__(self, best_share_hash_func, port, net, addr_store={}, connect_addrs=set(), desired_outgoing_conns=10, max_outgoing_attempts=30, max_incoming_conns=50, preferred_storage=1000, known_txs_var=variable.VariableDict({}), mining_txs_var=variable.VariableDict({}), mining2_txs_var=variable.VariableDict({}), advertise_ip=True, external_ip=None): self.best_share_hash_func = best_share_hash_func self.port = port self.net = net @@ -618,6 +685,7 @@ def __init__(self, best_share_hash_func, port, net, addr_store={}, connect_addrs self.preferred_storage = preferred_storage self.known_txs_var = known_txs_var self.mining_txs_var = mining_txs_var + self.mining2_txs_var = mining2_txs_var self.advertise_ip = advertise_ip self.external_ip = external_ip @@ -625,6 +693,7 @@ def __init__(self, best_share_hash_func, port, net, addr_store={}, connect_addrs self.nonce = random.randrange(2**64) self.peers = {} self.bans = {} # address -> end_time + self.banscores = {} # address -> how naughty this peer has been recently self.clientfactory = ClientFactory(self, desired_outgoing_conns, max_outgoing_attempts) self.serverfactory = ServerFactory(self, max_incoming_conns) self.running = False @@ -640,6 +709,14 @@ def start(self): self.running = True self._stop_thinking = deferral.run_repeatedly(self._think) + self.forgiveness_task = task.LoopingCall(self.forgive_transgressions) + self.forgiveness_task.start(3600.) + + def forgive_transgressions(self): + for host in self.banscores: + self.banscore[host] -= 1 + if self.banscore[host] < 0: + self.banscore[host] = 0 def _think(self): try: diff --git a/p2pool/test/bitcoin/test_data.py b/p2pool/test/bitcoin/test_data.py index 9e145369..285a282b 100644 --- a/p2pool/test/bitcoin/test_data.py +++ b/p2pool/test/bitcoin/test_data.py @@ -1,8 +1,16 @@ import unittest +import mock +from random import randint +from binascii import hexlify, unhexlify from p2pool.bitcoin import data, networks from p2pool.util import pack +def randgen(num=1000): + cnt = 0 + while cnt < num: + cnt += 1 + yield randint(0, 1<<256) class Test(unittest.TestCase): def test_header_hash(self): @@ -35,13 +43,13 @@ def test_tx_hash(self): )], tx_outs=[dict( value=5003880250, - script=data.pubkey_hash_to_script2(pack.IntType(160).unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex'))), + script=data.pubkey_hash_to_script2(pack.IntType(160).unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex')), networks.nets['bitcoin'].ADDRESS_VERSION, -1, networks.nets['bitcoin']), )], lock_time=0, )) == 0xb53802b2333e828d6532059f46ecf6b313a42d79f97925e457fbbfda45367e5c def test_address_to_pubkey_hash(self): - assert data.address_to_pubkey_hash('1KUCp7YP5FP8ViRxhfszSUJCTAajK6viGy', networks.nets['bitcoin']) == pack.IntType(160).unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex')) + assert data.address_to_pubkey_hash('1KUCp7YP5FP8ViRxhfszSUJCTAajK6viGy', networks.nets['bitcoin'])[0] == pack.IntType(160).unpack('ca975b00a8c203b8692f5a18d92dc5c2d2ebc57b'.decode('hex')) def test_merkle_hash(self): assert data.merkle_hash([ @@ -76,3 +84,3562 @@ def test_merkle_hash(self): 0x13375a426de15631af9afdf00c490e87cc5aab823c327b9856004d0b198d72db, 0x67d76a64fa9b6c5d39fde87356282ef507b3dec1eead4b54e739c74e02e81db4, ]) == 0x37a43a3b812e4eb665975f46393b4360008824aab180f27d642de8c28073bc44 + +class UnitTests(unittest.TestCase): + + class btcnet(object): + SYMBOL = 'btc' + HUMAN_READABLE_PART = 'bc' + ADDRESS_VERSION = 0 + ADDRESS_P2SH_VERSION = 3 + + class ltcnet(object): + SYMBOL = 'ltc' + HUMAN_READABLE_PART = 'ltc' + ADDRESS_VERSION = 48 + ADDRESS_P2SH_VERSION = 50 + + class bchnet(object): + SYMBOL = 'bch' + HUMAN_READABLE_PART = 'bitcoincash' + ADDRESS_VERSION = 0 + ADDRESS_P2SH_VERSION = 3 + + def test_pack256(self): + res = unhexlify('0100000000000000000000000000000000000000000000000000000000000000') + self.assertEqual(res, data.pack256(1)) + res = unhexlify('a65eca63d46a38919454e69b2c7870aad67ec760895c32620d9fabb632d26497') + value = 68477375576518660443919654926385967974392894630013268634844705859790497799846 + self.assertEqual(res, data.pack256(value)) + + def test_unpack256(self): + value = unhexlify('0100000000000000000000000000000000000000000000000000000000000000') + self.assertEqual(1, data.unpack256(value)) + value = unhexlify('a65eca63d46a38919454e69b2c7870aad67ec760895c32620d9fabb632d26497') + res = 68477375576518660443919654926385967974392894630013268634844705859790497799846 + self.assertEqual(res, data.unpack256(value)) + + def test_hash256d(self): + res = unhexlify('3f2c7ccae98af81e44c0ec419659f50d8b7d48c681e5d57fc747d0461e42dda1') + self.assertEqual(res, data.hash256d("foobar")) + res = unhexlify('522ce8431fa64392b98edd1d3f5334d44a503b39c273a70eef53ffe0eb017c7c') + self.assertEqual(res, data.hash256d("The quick brown fox jumped over the lazy dog.")) + + def test_MerkleNode(self): + mn = data.MerkleNode(None) + self.assertEqual('0', mn.hash) + self.assertEqual(None, mn.parent) + self.assertEqual(None, mn.left) + self.assertEqual(None, mn.right) + mn = data.MerkleNode(hash='moo', right='rhand', parent='mom', left='lhand') + self.assertEqual('moo', mn.hash) + self.assertEqual('lhand', mn.left) + self.assertEqual('rhand', mn.right) + self.assertEqual('mom', mn.parent) + lc = data.MerkleNode('left') + rc = data.MerkleNode('right') + pn = data.MerkleNode('parent') + pn.left = lc + pn.right = rc + lc.parent = pn + rc.parent = pn + self.assertEqual('left', pn.left.hash) + self.assertEqual('right', pn.right.hash) + self.assertEqual('parent', lc.parent.hash) + self.assertEqual('parent', lc.parent.hash) + self.assertEqual('right', lc.get_sibling().hash) + self.assertEqual('left', rc.get_sibling().hash) + + @mock.patch.object(data, 'hash256d', spec=data.hash256d) + def test_build_merkle_tree(self, mh): + mh.side_effect = lambda x: x + self.assertRaises(ValueError, data.build_merkle_tree, []) + self.assertEqual(0, mh.call_count) + self.assertEqual('1', data.build_merkle_tree([data.MerkleNode(hash='1')]).hash) + self.assertEqual(0, mh.call_count) + nodes = [data.MerkleNode(hash=str(x)) for x in range(1, 3)] + res = data.build_merkle_tree(nodes) + mh.assert_called_once_with("12") + self.assertEqual('1', res.left.hash) + self.assertEqual('2', res.right.hash) + self.assertEqual('12', res.hash) + mh.reset_mock() + nodes.append(data.MerkleNode(hash='3')) + res = data.build_merkle_tree(nodes) + mh.assert_has_calls([mock.call('12'), mock.call('33'), mock.call('1233')]) + self.assertEqual('1', res.left.left.hash) + self.assertEqual('2', res.left.right.hash) + self.assertEqual('3', res.right.left.hash) + self.assertEqual('3', res.right.right.hash) + self.assertEqual('12', res.left.hash) + self.assertEqual('33', res.right.hash) + self.assertEqual('1233', res.hash) + mh.reset_mock() + nodes.append(data.MerkleNode(hash='4')) + res = data.build_merkle_tree(nodes) + mh.assert_has_calls([mock.call('12'), mock.call('34'), mock.call('1234')]) + self.assertEqual('1', res.left.left.hash) + self.assertEqual('2', res.left.right.hash) + self.assertEqual('3', res.right.left.hash) + self.assertEqual('4', res.right.right.hash) + self.assertEqual('12', res.left.hash) + self.assertEqual('34', res.right.hash) + self.assertEqual('1234', res.hash) + mh.reset_mock() + nodes.append(data.MerkleNode(hash='5')) + res = data.build_merkle_tree(nodes) + calls = [mock.call('12'), mock.call('34'), mock.call('55'), + mock.call('1234'), mock.call('5555'), mock.call('12345555')] + mh.assert_has_calls(calls) + self.assertEqual('1', res.left.left.left.hash) + self.assertEqual('2', res.left.left.right.hash) + self.assertEqual('3', res.left.right.left.hash) + self.assertEqual('4', res.left.right.right.hash) + self.assertEqual('5', res.right.left.left.hash) + self.assertEqual('5', res.right.left.right.hash) + self.assertEqual('5', res.right.right.left.hash) + self.assertEqual('5', res.right.right.right.hash) + self.assertEqual('12', res.left.left.hash) + self.assertEqual('34', res.left.right.hash) + self.assertEqual('55', res.right.left.hash) + self.assertEqual('55', res.right.right.hash) + self.assertEqual('1234', res.left.hash) + self.assertEqual('5555', res.right.hash) + self.assertEqual('12345555', res.hash) + + @mock.patch.object(data, 'pack256', spec=data.pack256) + @mock.patch.object(data, 'unpack256', spec=data.unpack256) + @mock.patch.object(data, 'build_merkle_tree', spec=data.build_merkle_tree) + def test_calculate_merkle_link(self, mbmt, mu, mp): + mp.side_effect = lambda x: x + mu.side_effect = lambda x: x + def m_tree(hashes): + if len(hashes) == 1: + return hashes[0] + new_nodes = [] + for i in range(0, len(hashes), 2): + try: + r = hashes[i+1] + except IndexError: + r = hashes[i] + nn = data.MerkleNode(hash="%s%s" % (hashes[i].hash, r.hash), + left=hashes[i], right=r) + hashes[i].parent = nn + try: + hashes[i+1].parent = nn + except IndexError: + pass + new_nodes.append(nn) + return m_tree(new_nodes) + mbmt.side_effect = m_tree + self.assertRaises(AssertionError, data.calculate_merkle_link, [], 0) + self.assertDictEqual({'index': 0, 'branch': []}, + data.calculate_merkle_link([None], 0)) + self.assertRaises(AssertionError, data.calculate_merkle_link, [None], 1) + n11 = data.MerkleNode('12', left=data.MerkleNode('1'), + right=data.MerkleNode('2')) + n11.left.parent = n11 + n11.right.parent = n11 + mbmt.return_value = n11 + self.assertDictEqual({'index': 0, 'branch': ['2']}, + data.calculate_merkle_link(['1', '2'], 0)) + self.assertDictEqual({'index': 1, 'branch': ['1']}, + data.calculate_merkle_link(['1', '2'], 1)) + self.assertDictEqual({'index': 0, 'branch': ['2', '33']}, + data.calculate_merkle_link(['1', '2', '3'], 0)) + self.assertDictEqual({'index': 0, 'branch': ['2', '34']}, + data.calculate_merkle_link(['1', '2', '3', '4'], 0)) + self.assertDictEqual({'index': 0, 'branch': ['2', '34', '5555']}, + data.calculate_merkle_link( + ['1', '2', '3', '4', '5'], 0)) + self.assertDictEqual({'index': 0, 'branch': ['2', '34', '5656']}, + data.calculate_merkle_link( + ['1', '2', '3', '4', '5', '6'], 0)) + + @mock.patch.object(data, 'human_address_type', spec=data.human_address_type) + @mock.patch.object(data, 'base58_encode', spec=data.base58_encode) + @mock.patch.object(data.segwit_addr, 'encode', spec=data.segwit_addr.encode) + @mock.patch.object(data.cash_addr, 'encode', spec=data.cash_addr.encode) + def test_pubkey_hash_to_address(self, mce, mse, mbe, mhat): + # Test legacy addresses + mbe.return_value = 'foobar' + mhat.pack.return_value = 'foo' + self.assertEqual('foobar', + data.pubkey_hash_to_address('bar', 0, 0, self.btcnet)) + self.assertEqual(0, mce.call_count) + self.assertEqual(0, mse.call_count) + mbe.assert_called_once_with('foo') + mhat.pack.assert_called_once_with({'version': 0, 'pubkey_hash': 'bar'}) + mhat.reset_mock() + self.assertEqual('foobar', + data.pubkey_hash_to_address('moo', 1, -1, self.btcnet)) + mhat.pack.assert_called_once_with({'version': 1, 'pubkey_hash': 'moo'}) + # Test segwit addresses + mse.return_value = 'moobar' + hash1 = 123486153218641351641531321856105641635163813486135131313818612456474534165 + ret1 = [69, 228, 3, 253, 141, 6, 177, 99, 120, 131, 105, 238, 19, 236, + 234, 73, 29, 205, 107, 201, 9, 238, 81, 64, 21, 78, 5, 81, 3, + 225, 21] + mhat.reset_mock() + mbe.reset_mock() + self.assertEqual('moobar', + data.pubkey_hash_to_address(hash1, -1, 0, self.btcnet)) + self.assertEqual(0, mbe.call_count) + self.assertEqual(0, mhat.call_count) + self.assertEqual(0, mce.call_count) + mse.assert_called_once_with('bc', 0, ret1) + mse.reset_mock() + hash2 = 4328719365 + ret2 = [1, 2, 3, 4, 5] + self.assertEqual('moobar', + data.pubkey_hash_to_address(hash2, -1, 1, self.ltcnet)) + mse.assert_called_once_with('ltc', 1, ret2) + # Test cashaddr addresses + mce.return_value = 'fumbar' + mse.reset_mock() + self.assertEqual('fumbar', + data.pubkey_hash_to_address(hash1, -1, 0, self.bchnet)) + self.assertEqual(0, mbe.call_count) + self.assertEqual(0, mhat.call_count) + self.assertEqual(0, mse.call_count) + mce.assert_called_once_with('bitcoincash', 0, ret1) + mce.reset_mock() + self.assertEqual('fumbar', + data.pubkey_hash_to_address(hash2, -1, 1, self.bchnet)) + mce.assert_called_once_with('bitcoincash', 1, ret2) + + @mock.patch.object(data, 'pubkey_hash_to_address', + spec=data.pubkey_hash_to_address) + @mock.patch.object(data, 'hash160', spec=data.hash160) + def test_pubkey_to_address(self, mh, mphta): + mphta.return_value = 'foobar' + mh.return_value = 'foo' + self.assertEqual('foobar', data.pubkey_to_address('bar', self.btcnet)) + mh.assert_called_once_with('bar') + mphta.assert_called_once_with('foo', 0, -1, self.btcnet) + mphta.reset_mock() + mh.reset_mock() + self.assertEqual('foobar', data.pubkey_to_address('moo', self.ltcnet)) + mh.assert_called_once_with('moo') + mphta.assert_called_once_with('foo', 48, -1, self.ltcnet) + + @mock.patch.object(data, 'address_to_pubkey_hash', + spec=data.address_to_pubkey_hash) + @mock.patch.object(data, 'pubkey_hash_to_script2', + spec=data.pubkey_hash_to_script2) + def test_address_to_script2(self, mphts, matph): + matph.return_value = ('foo', 'moobar', 'meh') + mphts.return_value = 'bar' + self.assertEqual('bar', data.address_to_script2('moo', self.btcnet)) + matph.assert_called_once_with('moo', self.btcnet) + mphts.assert_called_once_with('foo', 'moobar', 'meh', self.btcnet) + + @mock.patch.object(data, 'get_legacy_pubkey_hash', + spec=data.get_legacy_pubkey_hash) + @mock.patch.object(data, 'get_bech32_pubkey_hash', + spec=data.get_bech32_pubkey_hash) + @mock.patch.object(data, 'get_cashaddr_pubkey_hash', + spec=data.get_cashaddr_pubkey_hash) + def test_address_to_pubkey_hash(self, mgcph, mgbph, mglph): + def reset_mocks(): + for i in mglph, mgbph, mgcph: + i.reset_mock() + + mglph.return_value = 'legacy' + mgbph.return_value = 'bech32' + mgcph.return_value = 'cashaddr' + self.assertEqual('legacy', + data.address_to_pubkey_hash('foo', self.btcnet)) + mglph.assert_called_once_with('foo', self.btcnet) + reset_mocks() + mglph.side_effect = [ValueError] + self.assertRaises(ValueError, data.address_to_pubkey_hash, 'bar', + self.ltcnet) + mglph.assert_called_once_with('bar', self.ltcnet) + reset_mocks() + mglph.side_effect = data.AddrError + self.assertEqual('bech32', + data.address_to_pubkey_hash('foo', self.ltcnet)) + mgbph.assert_called_once_with('foo', self.ltcnet) + reset_mocks() + self.assertEqual('cashaddr', + data.address_to_pubkey_hash('bar', self.bchnet)) + mgcph.assert_called_once_with('bar', self.bchnet) + reset_mocks() + mgbph.side_effect = data.AddrError + self.assertRaises(ValueError, data.address_to_pubkey_hash, 'moo', + self.btcnet) + mgbph.assert_called_once_with('moo', self.btcnet) + reset_mocks() + mgcph.side_effect = data.AddrError + self.assertRaises(ValueError, data.address_to_pubkey_hash, 'foo', + self.bchnet) + mgcph.assert_called_once_with('foo', self.bchnet) + + @mock.patch.object(data, 'base58_decode', spec=data.base58_decode) + @mock.patch.object(data, 'human_address_type', spec=data.human_address_type) + def test_get_legacy_pubkey_hash(self, mhat, mbd): + mbd.side_effect = ValueError + mhat.unpack.return_value = {'version': 0, 'pubkey_hash': 'foo'} + self.assertRaises(data.AddrError, data.get_legacy_pubkey_hash, 'bar', + self.btcnet) + mbd.side_effect = None + mbd.return_value = 'moo' + mhat.unpack.side_effect = ValueError + self.assertRaises(data.AddrError, data.get_legacy_pubkey_hash, 'bar', + self.btcnet) + mhat.unpack.side_effect = None + for t in self.bchnet, self.ltcnet: + netvers = [t.ADDRESS_VERSION, t.ADDRESS_P2SH_VERSION] + for v in range(256): + mbd.reset_mock() + mhat.reset_mock() + mhat.unpack.return_value['version'] = v + if v in netvers: + self.assertTupleEqual(('foo', v, -1), + data.get_legacy_pubkey_hash('foobar', t)) + else: + self.assertRaises(ValueError, data.get_legacy_pubkey_hash, + 'foobar', t) + + + @mock.patch.object(data.segwit_addr, 'decode', spec=data.segwit_addr.decode) + def test_get_bech32_pubkey_hash(self, msd): + msd.return_value = None, 'bar' + self.assertRaises(data.AddrError, data.get_bech32_pubkey_hash, 'foo', + self.btcnet) + msd.return_value = 0, None + self.assertRaises(data.AddrError, data.get_bech32_pubkey_hash, 'foo', + self.btcnet) + msd.side_effect = ValueError + self.assertRaises(data.AddrError, data.get_bech32_pubkey_hash, 'foo', + self.btcnet) + msd.side_effect = None + msd.return_value = 3, [1, 2, 3, 4, 5] + msd.reset_mock() + self.assertTupleEqual((4328719365, -1, 3), + data.get_bech32_pubkey_hash('foo', self.btcnet)) + msd.assert_called_once_with('bc', 'foo') + msd.reset_mock() + msd.return_value = 7, [5, 4, 3, 2, 1] + self.assertTupleEqual((21542142465, -1, 7), + data.get_bech32_pubkey_hash('moo', self.ltcnet)) + msd.assert_called_once_with('ltc', 'moo') + + @mock.patch.object(data.cash_addr, 'decode', spec=data.cash_addr.decode) + def test_get_cashaddr_pubkey_hash(self, mcd): + mcd.return_value = None, 'bar' + self.assertRaises(data.AddrError, data.get_cashaddr_pubkey_hash, 'foo', + self.bchnet) + mcd.return_value = 0, None + self.assertRaises(data.AddrError, data.get_cashaddr_pubkey_hash, 'foo', + self.bchnet) + mcd.side_effect = ValueError + self.assertRaises(data.AddrError, data.get_cashaddr_pubkey_hash, 'foo', + self.bchnet) + mcd.side_effect = None + mcd.return_value = 1, [1, 2, 3, 4, 5] + mcd.reset_mock() + self.assertTupleEqual((4328719365, -1, 1), + data.get_cashaddr_pubkey_hash('foo', self.bchnet)) + mcd.assert_called_once_with('bitcoincash', 'foo') + mcd.reset_mock() + mcd.return_value = 7, [5, 4, 3, 2, 1] + self.assertTupleEqual((21542142465, -1, 7), + data.get_cashaddr_pubkey_hash('moo', self.bchnet)) + mcd.assert_called_once_with('bitcoincash', 'moo') + + @mock.patch.object(data, 'pack', spec=data.pack) + def test_pubkey_hash_to_script2(self, mp): + mp.IntType().pack.return_value = '\xde\xad\xbe\xef' + legacy_out = '\x76\xa9\x14\xde\xad\xbe\xef\x88\xac' + self.assertEqual(legacy_out, data.pubkey_hash_to_script2(1234, 0, -1, + self.btcnet)) + mp.IntType().pack.assert_called_once_with(1234) + mp.reset_mock() + p2sh_out = '\xa9\x14\xde\xad\xbe\xef\x87' + self.assertEqual(p2sh_out, data.pubkey_hash_to_script2(1234, 3, -1, + self.btcnet)) + mp.IntType().pack.assert_called_once_with(1234) + mp.reset_mock() + phash = int('deadbeef', 16) + bech32_out = '\x00\x04\xde\xad\xbe\xef' + self.assertEqual(bech32_out, data.pubkey_hash_to_script2(phash, -1, 2, + self.ltcnet)) + self.assertEqual(0, mp.IntType().pack.call_count) + # Cashaddr test version 0 (P2KH) + cashaddr_out = '\x76\xa9\x04\xde\xad\xbe\xef\x88\xac' + mp.reset_mock() + self.assertEqual(cashaddr_out, data.pubkey_hash_to_script2(phash, -1, 0, + self.bchnet)) + self.assertEqual(0, mp.IntType().pack.call_count) + # Cashaddr test version 1 (P2SH) + cashaddr_out = '\xa9\x04\xde\xad\xbe\xef\x87' + self.assertEqual(cashaddr_out, data.pubkey_hash_to_script2(phash, -1, 1, + self.bchnet)) + for i in range(2, 16): + self.assertRaises(NotImplementedError, data.pubkey_hash_to_script2, + phash, -1, i, self.bchnet) + # Max cashaddr hash size. + phash2 = int('deadbeef' * 16, 16) + mp.IntType().pack.return_value = '\xde\xad\xbe\xef' * 16 + mp.reset_mock() + cashaddr_out2 = '\x76\xa9\x40%s\x88\xac' % ('\xde\xad\xbe\xef' * 16) + self.assertEqual(cashaddr_out2, data.pubkey_hash_to_script2(phash2, -1, 0, + self.bchnet)) + cashaddr_out2 = '\xa9\x40%s\x87' % ('\xde\xad\xbe\xef' * 16) + self.assertEqual(cashaddr_out2, data.pubkey_hash_to_script2(phash2, -1, 1, + self.bchnet)) + + @mock.patch.object(data, 'script2_to_pubkey_address', + spec=data.script2_to_pubkey_address) + @mock.patch.object(data, 'script2_to_pubkey_hash_address', + spec=data.script2_to_pubkey_hash_address) + @mock.patch.object(data, 'script2_to_bech32_address', + spec=data.script2_to_bech32_address) + @mock.patch.object(data, 'script2_to_cashaddress', + spec=data.script2_to_cashaddress) + @mock.patch.object(data, 'script2_to_p2sh_address', + spec=data.script2_to_p2sh_address) + def test_script2_to_address(self, mstpa, mstca, mstba, mstpha, mstpka): + mstpa.side_effect = data.AddrError + mstpa.return_value = 'P2SH' + mstba.side_effect = data.AddrError + mstba.return_value = 'Bech32' + mstca.side_effect = data.AddrError + mstca.return_value = 'CashAddr' + mstpha.side_effect = data.AddrError + mstpha.return_value = 'Hash' + mstpka.side_effect = data.AddrError + mstpka.return_value = 'Pubkey' + self.assertRaises(ValueError, data.script2_to_address, 'foobar', 1, -1, + self.btcnet) + mstpa.assert_called_once_with('foobar', 1, -1, self.btcnet) + mstca.assert_called_once_with('foobar', 1, -1, self.btcnet) + mstba.assert_called_once_with('foobar', 1, -1, self.btcnet) + mstpha.assert_called_once_with('foobar', 1, -1, self.btcnet) + mstpka.assert_called_once_with('foobar', self.btcnet) + mstpka.side_effect = None + self.assertEqual('Pubkey', data.script2_to_address('foobar', 1, -1, + self.btcnet)) + mstpka.side_effect = data.AddrError + mstpha.side_effect = None + self.assertEqual('Hash', data.script2_to_address('foobar', 1, -1, + self.btcnet)) + mstpha.side_effect = data.AddrError + mstba.side_effect = None + self.assertEqual('Bech32', data.script2_to_address('foobar', 1, -1, + self.btcnet)) + mstba.side_effect = data.AddrError + mstpa.side_effect = None + self.assertEqual('P2SH', data.script2_to_address('foobar', 1, -1, + self.btcnet)) + mstpa.side_effect = data.AddrError + mstca.side_effect = None + self.assertEqual('CashAddr', data.script2_to_address('foobar', -1, 0, + self.btcnet)) + + @mock.patch.object(data, 'pubkey_to_script2', spec=data.pubkey_to_script2) + @mock.patch.object(data, 'pubkey_to_address', spec=data.pubkey_to_address) + def test_script2_to_pubkey_address(self, mpta, mpts): + mpts.side_effect = ValueError + self.assertRaises(data.AddrError, data.script2_to_pubkey_address, 'foo', + self.btcnet) + mpts.side_effect = None + mpts.return_value = 'moobar' + mpts.reset_mock() + self.assertRaises(data.AddrError, data.script2_to_pubkey_address, + 'foobar', self.btcnet) + mpts.assert_called_once_with('ooba') + mpta.return_value = 'foo' + self.assertEqual('foo', data.script2_to_pubkey_address('moobar', + self.btcnet)) + + @mock.patch.object(data, 'pack', spec=data.pack) + @mock.patch.object(data, 'pubkey_hash_to_script2', + spec=data.pubkey_hash_to_script2) + @mock.patch.object(data, 'pubkey_hash_to_address', + spec=data.pubkey_hash_to_address) + def test_script2_to_pubkey_hash_address(self, mphta, mphts, mp): + mp.IntType().unpack.side_effect = ValueError + mphts.return_value = 'foo' + self.assertRaises(data.AddrError, data.script2_to_pubkey_hash_address, + 'bar', 1, -1, self.btcnet) + mp.IntType().unpack.side_effect = None + mp.IntType().unpack.return_value = 'moo' + mphts.side_effect = ValueError + self.assertRaises(data.AddrError, data.script2_to_pubkey_hash_address, + 'bar', 1, -1, self.btcnet) + mphts.side_effect = None + mp.reset_mock() + mphts.reset_mock() + self.assertRaises(data.AddrError, data.script2_to_pubkey_hash_address, + 'foobar', 1, -1, self.btcnet) + mp.IntType.assert_called_once_with(160) + mp.IntType().unpack.assert_called_once_with('b') + mphts.assert_called_once_with('moo', 1, -1, self.btcnet) + mphta.return_value = 'moobar' + self.assertEqual('moobar', + data.script2_to_pubkey_hash_address('foo', 1, -1, + self.btcnet)) + + @mock.patch.object(data, 'pubkey_hash_to_script2', + spec=data.pubkey_hash_to_script2) + @mock.patch.object(data, 'pubkey_hash_to_address', + spec=data.pubkey_hash_to_address) + def test_script2_to_cashaddress(self, mphta, mphts): + phash = '\xde\xad\xbe\xef' * 2 + for i in range(2, 16): + self.assertRaises(data.AddrError, data.script2_to_cashaddress, + phash, -1, i, self.bchnet) + self.assertEqual(0, mphts.call_count) + mphts.side_effect = ValueError + self.assertRaises(data.AddrError, data.script2_to_cashaddress, + phash, -1, 0, self.bchnet) + mphts.reset_mock() + mphts.side_effect = None + mphts.return_value = 'bar' + self.assertRaises(data.AddrError, data.script2_to_cashaddress, + phash, -1, 0, self.bchnet) + mphts.assert_called_once_with(15720109, -1, 0, self.bchnet) + mphts.return_value = phash + mphta.return_value = 'foobar' + self.assertEqual('foobar', data.script2_to_cashaddress(phash, -1, 0, + self.bchnet)) + mphts.reset_mock() + self.assertEqual('foobar', data.script2_to_cashaddress(phash, -1, 1, + self.bchnet)) + mphts.assert_called_once_with(820068134334, -1, 1, self.bchnet) + + @mock.patch.object(data, 'pubkey_hash_to_script2', + spec=data.pubkey_hash_to_script2) + @mock.patch.object(data, 'pubkey_hash_to_address', + spec=data.pubkey_hash_to_address) + def test_script2_to_bech32_address(self, mphta, mphts): + phash = '\xde\xad\xbe\xef' + mphts.side_effect = ValueError + self.assertRaises(data.AddrError, data.script2_to_bech32_address, + phash, 1, -1, self.btcnet) + mphts.reset_mock() + mphts.side_effect = None + mphts.return_value = 'bar' + self.assertRaises(data.AddrError, data.script2_to_bech32_address, + phash, 1, -1, self.btcnet) + mphts.assert_called_once_with(48879, 1, -1, self.btcnet) + mphts.return_value = phash + mphta.return_value = 'foobar' + self.assertEqual('foobar', data.script2_to_bech32_address(phash, 1, -1, + self.btcnet)) + + @mock.patch.object(data, 'pack', spec=data.pack) + @mock.patch.object(data, 'pubkey_hash_to_script2', + spec=data.pubkey_hash_to_script2) + @mock.patch.object(data, 'pubkey_hash_to_address', + spec=data.pubkey_hash_to_address) + def test_script2_to_p2sh_address(self, mphta, mphts, mp): + mp.IntType().unpack.side_effect = ValueError + mphts.return_value = 'foo' + self.assertRaises(data.AddrError, data.script2_to_p2sh_address, + 'bar', 1, -1, self.btcnet) + mp.IntType().unpack.side_effect = None + mp.IntType().unpack.return_value = 'moo' + mphts.side_effect = ValueError + self.assertRaises(data.AddrError, data.script2_to_p2sh_address, + 'bar', 1, -1, self.btcnet) + mphts.side_effect = None + mp.IntType().unpack.reset_mock() + mphts.reset_mock() + self.assertRaises(data.AddrError, data.script2_to_p2sh_address, + 'foobar', 1, -1, self.btcnet) + mp.IntType.called_once_with(160) + mp.IntType().unpack.assert_called_once_with('oba') + mphts.assert_called_once_with('moo', 1, -1, self.btcnet) + mphts.return_value = 'moo' + mphta.return_value = 'moobar' + self.assertEqual('moobar', data.script2_to_p2sh_address('moo', 1, -1, + self.btcnet)) + +class IntegrationTests(unittest.TestCase): + + merkle_links1 = [None] + merkle_result1 = {'index': 0, 'branch': []} + + merkle_links2 = [None, 1] + merkle_result2 = {'index': 0, 'branch': [1]} + + merkle_links3 = [1] + merkle_result3 = {'index': 0, 'branch': []} + + merkle_links4 = [1, 2] + merkle_result4 = {'index': 0, 'branch': [2]} + + merkle_links5 = [None, 1, 2, 3, 4, 5] + merkle_result5 = {'index': 0, + 'branch': [1, + 94864150206590526235965722633721835315983130322594944160453736056914236592459L, + 59849171046155764382219583444308915046617550355436344310681675321029813555762L]} + + merkle_links6 = [None, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + merkle_result6 = {'index': 0, + 'branch': [1, + 94864150206590526235965722633721835315983130322594944160453736056914236592459L, + 72494757060291235084519934761016282559218743148805001002098588078214939771139L, + 18012755156996779427190686631173143337082707813254112256638152524170454035843L]} + + merkle_links10 = [None, + 112016540517777279124582056964762882775092635530152119738265592842063160830965L, + 56016915772221477937604398882069387632763464690103128956960662776002935411782L, + 27489797435812445852286074542232496823045696260790971196874895068817967327914L, + 29231458257536678058796531788726312001828885265742980097893645233605822098575L, + 109621318833012795682402637604567380346073503361634966798913016745742953699966L, + 24909319073749908615499772821230754597736318049326474726843859675116381978383L, + 73116838412628052670152025319686481320276280169380738966717514804364097533428L, + 80886863176958214668563050365622560907514596142176225339217204583899265998125L, + 41589402369775626260554332252036838054298791596933198958489513673258971505130L, + 90207124876116528982898796178611787615303549079587054631783065386394107105504L, + 114354507635998358018416447246810731083459038073523320387363301795032648400355L, + 3468633635759129348396311811642141059611148041398510578008184000944189646411L, + 17514043107330244526426315235805045874023023428775112862062056950974122062033L, + 53259785307043432607139655762614467196491065248189533004175348159284660172869L, + 52620393715353636218560129188772966967309800948433722877797002054186316980514L, + 81916037529722914583852010621426568426887061600075613109986180610980935124387L, + 28887865002743070237254048932842508376262793422026358600329002055567891885209L, + 26911650718246041071462711157596525307850141815199918550035772490323117482977L, + 98782771420179306759562155487949995386960639005911027478989653998061955681574L, + 21385446635146895191163854777028162803169770223985713636865070264449808450295L, + 115312282836937207946894229413241455580662549241543640118420474329115656990460L, + 8038616326053636715857944728508909614506215005454136641706259209707589435714L, + 115648774472085869829557067749566131339376972955485372286312437113097810332113L, + 89977569599113102467001097812324253681742984229238600181917861256506653234721L, + 48924912067861623118041172086475435793443440679010754712941941116717440634853L, + 36587039210909234246472793549041156245733357108593864427518986567710598392952L, + 46109624864431307857770609789747492326638809391439411091696680294058837799477L, + 16046121833973661809951046995227302935987263834895748044292415373871029012138L, + 87103134101714405379218872339020541911369109388829618784084371041796944430262L, + 71849222861024798916155067399910267006659711014200840638927330075305001351870L, + 70844616719056711586280497702324062435759674335122542937012422880906044773779L, + 9335799715313274697512042344496215317099396583298735675248312763375363020532L, + 96310452005589395003812166209756935214142758015493698798130407204945344186095L, + 81905963287417508258305936184419375724301111181318778863757865663441633463111L, + 92370163495579471744030437129029154007365623200242295216366697364220099495719L, + 36375283506059775931024155362654312316148209788950930164000462865078958359360L, + 88726230387220372332073897600804273225361892039757582601238798806528910444882L, + 6070129213356042314691499461742835393224940498627879606963066377266801299612L, + 58583931103886568102124231505465601207272863084913352879958978958829547119677L, + 57463926047214227742724634341326914848675917055176191431046747377307567352099L, + 27012546757231614922088904355562654115959540651898947136364052388242505768569L, + 99433045653889563967150006921846226712363259667263341416016685182002637504325L, + 98930772562583899742647561893951122857272411004257815634561920125860196333333L, + 50108682577013406020347739879562585417576253647642773177726545361365392252368L, + 64685183169410827677125410208853885791480988563246282885484253607919434869157L, + 63831879829294080751777051276131359248834082161927565636980809995812441758198L, + 88444488165896703625205363380828907087113537711070698319237824422865316278850L, + 72159984086399288134669843460215053409686501596375218830869388391271515007149L, + 93923006498599762246269011802512049338272400480966002367955078528607110984351L, + 56582486764232203710657643460558786621824618256032901506993654680411374403506L, + 27247248238300328134410397652427878380336360748128996791026616325378108504335L, + 49761339576008033226113121759699928068150081352868219274106736813953326265638L, + 9161675158558004739448120378002634293608802907093779336873863369459008891019L, + 93461397760483743306132919367837003785210423820141031416311717270390284637122L, + 62900762991748812547111882734991529379973619367968883782425707337170895993596L, + 32757595965065373444083144038461103402985094949819621309996011288543377384235L, + 103960048224805408775641108708179160892191001524201247681388380155314536724637L, + 53456560041009681567044041341204706503806618637681525958328705890594461717036L, + 77717709415749147611975161379861131154824772698687245241144493306107366243712L, + 74890197579975358597780466905530025112143596353512857089470046812806235935743L, + 24637040035557619748551503164358139880147695176857752327797598473320679714713L, + 12816399163497874874824956046851796108049172420116309081964631263041327964849L, + 74494961293884467664954304349698851458635838653133923701487804959710521062367L, + 90993195954149572297606851545725050698910241708435138297753626520345755984107L, + 58215138150929360293081719766024706035215643415428831405694694330692503719259L, + 89956111261673835060385930154948690999626591425223630675807002157058238821032L, + 96913445328851719786024423266233282775668924616055488595011129416530218434040L, + 112072065079699680359500521368330428382079803608836130990153785318838270149395L, + 14850098647561667617732277867245347785629166243871670796634517953513118025474L, + 52051372518516601581864957765692485097071703085140267671692394559015291978948L, + 22428334879466085092832984704566361590992480397962998571491363448424996051481L, + 83668121237531480514218115266149211167088412945398880150294279995083596674859L, + 57326589617037353335933101525368632749804298967102525145907702271743943446814L, + 88632149646179999179343911262867363834501950399527016409018248336659121987348L, + 103513396087040744916176505331390959339760897230049404623861598220178425365949L, + 59405515372488566742785411177582096185006244999302269156531451569770912827320L, + 94410488185034888630546519641288768107950043015563130381678422847498960827496L, + 92917043115324816161356018866304701890979909198500356250790217418537154937706L, + 28387412679588455802257935903781479441774758695531218575255221599977885477398L, + 45345338964765670288443753460668457262803572116668804743820613946584039806468L, + 17554385903835687117359760867293914739385241051772405021245097638788516398348L, + 146704054663283934711294565066041188709559059689193984271952431577139905378L, + 55534501706042922186966773974076149855785615244193978550637186387298665233797L, + 12402292003490764097291803996915545804946326347843103552862034174944187019226L, + 33927279023744526352720281963382595793226423508933214565592188289555773451285L, + 28674729283795803892989231482389874960373994212629043184176027814493098577767L, + 62979428877521372940895063007616268821966798956402214474988446361024679512490L, + 58059928852559648909397597332991639414174241397379900252886480855366523869880L, + 23149549033567608603378576763933536979652221515126523824297157005037634154491L, + 31331785003632325691521049665971090873036911275170678595855097146136857650528L, + 69805883028197720252962280781148286012966422594772335803511661210608982041459L, + 90136259271208036140807781305121794369112527230665007487380885920988164491980L, + 108284363538516685124971597472434350564615615957983267557967320689537268236763L, + 103872916138223246484444709027601996626359494810040925740369292169665090170821L, + 20163745130684015554427748135506154842279311229136081884933763731166339971930L, + 38861078160039252718353485169669430755389752224759618377580811463418472015059L, + 106492657875624040584059066389441241595276994256407827006904008468691816706346L, + 9776670813106470420023500205860682589193759333647761957028971310568162594911L, + 95547750627942877263332803284960121334737730663663425653187528890288840934155L, + 24595691744900522268361546496044420497232882656768597381664524102565879647753L, + 20560951005227323016094269978149633908118400347609938515652741873881000822274L, + 97538994901021840060915370027943000291340661051520734452728118980746955504134L, + 3206096951624214679035489155064291884200717537349225004749377469262758264168L, + 87213128872816361850234696481403629146111393159791555573774379367698747440969L, + 52492154392359966513135657643612646077062522044723689819581548433266475660167L, + 57874848912728677019093831563261174317645429492784161819476727716797103478980L, + 34617353845582173186339818095469634689208812124426987406603484565520843863162L, + 63352994991869902985863831141264774104112904508101336521440783817476166378616L, + 24896526347641187332629740257374236902537250311446894531290446029320129805493L, + 34763391532733369762581513657392564500863299511718590960540820980612119494337L, + 56490223225145450506626693194447650046194222302382964227296839561606036891082L, + 36970817473630539387769860171583437005195045204732265535515596613775570972383L, + 87053185231976002982248680324703214694723208963143948890114515885935043320397L, + 29847036569571379084663465808018400062560795577661654153597262068169908014170L, + 18988090895065615698635043358038852667590102293148566014706810260439102513807L, + 64469609724802831866389115122647676877222365077735069104786062834889597393919L, + 83556789821922402798488159552377663265175622639952608675121508387029580871368L, + 109936006775042091714841318781806779763941627558694342588009783709013194834414L, + 22968733154639340981140430196449031182859954403940180947419570045659083407700L, + 17789275781319118050581425161808713092125058324692136001600328252471260119734L, + 25745380119689470807209093393218039737578393498273708320349637209328821820318L, + 61641607478575128527700451527718093807683009050940235589813631356624939032595L, + 47110848145937746368414424058821501259911814303529144556069358271853914032200L, + 41533909436391753047012504052982996026827131975414910405032096368886062826129L, + 13054948048121635721506270513359775546141300282536389803702833848405874430279L, + 16080681035777294584165123624695238589201445166830763492914391196185304360703L, + 81299539459149782016401935277584722958566375743744658185491349417910196375678L, + 18945061964739542292675224703307880535444665336511089699084814584597438298960L, + 112797159538436039343555668735819394839428598748222619016939149100522384391054L, + 73300295966858556355393607143518982906893794572692795215344888739320658186069L, + 4041434409204542945242581084870345689830618454597899093695016513143642290802L, + 97508794687679881071902975234200563849411621855344235991749755970686207161839L, + 15282141413086994702794900287401256763476842815020057731420569793924926978911L, + 99728292502384296296228667181892942533052936791849702203347135028416281206377L, + 3411041873042499785540450848806342320912326049804985044239917476630471753169L, + 4048033594044406973983364298209147826637114833783700079142995185645222879854L, + 101860405294836197506128289253832975563582041161562488561533643193912164273168L, + 78905877433925568584515437130206044862818139296717285038469191868676799310061L, + 18775690530628442604546733798201529558056066835322234540392467080880913809254L, + 82947397524614988691926143062900829869324231456303333360721539341888846038725L, + 42694379073331099052172297715130893406380955641898301659263525140461504293047L, + 14442033767533181542149794383759150549978335385330888902568884429150620610599L, + 93313581709603325926029120119082923112988831425916606563484732721238387656810L, + 72801205216710264428360436666267791931111107489657889310598331480989588029387L, + 67672324229006698997429333430044401253111346908650081260433438623710584187265L, + 70772702159994604749028832792273009568408747593795621407790253945395559706842L, + 29729304049522432818646784254663965006745767318792991694212308384739446301778L, + 84627931201730893564670832781378984288443711600180448657831065852784023499012L, + 5341943877865281034686860324729716028225611069848222572406801055229289775947L, + 29363932365380673199419088786644528126811770594253361078602977419321774803891L, + 9004928131838813677658487282066233255501121930576377831608071926739686700330L, + 105136954397546093563754645032958827106234484325609968808287454474846711319990L, + 99816460821225201342714853579093969388961697645623860806505884442477625580990L, + 106681508148883422742224326307154802018855256554317516173086564531286716004164L, + 7006763686362832983859018353853556207867301220635874533560223129687398063238L, + 14321478981818480518746074874714729340600984755356898480669110575494399252101L, + 20175260458757597605277157497724495661959897504305393475703533111106974204442L, + 111769254449605230052328802781178889903176520895536759727961315714921223704351L, + 36426670645651890452930640114977419417665421141639862712468284926884279415361L, + 109432460300382670484067214653957247313416883180489696636197853559990484030609L, + 7520403297596573819592781546673822831071168643752348400012072445764927721892L, + 73196937925500377714455439113432849037994391890274802433562823511838920107695L, + 36752755571095894428029260872947166518412591768027342056659080137127900826464L, + 99995344805296217510853913486463991681280426231577702483100113184040494219000L, + 112420429371656727207370103196793504245398270791446904347278453314283313337871L, + 47191946582297313211416991922641768931234133845492807678047578621589626189485L, + 109778423006027852506893839915943588591107046052313487963867787449068930618840L, + 10345675446434556619929989818962829290520520574227315805411995298022315933978L, + 97692937909469320640194638870172745072367628197340418062076997031203937194269L, + 18683260981785212200820959138526719721818988710798906741300704329047908844217L, + 6892696773191096918392700093236074630398023141032592274451349049962035542623L, + 60564427846980699670576108199909223771359549125660413891296955825422714914983L, + 38785763103128427613833647061323411816642055799472850145381412858873101474209L, + 10266092268719998396552723710961267337810574916933175583941362520043487533883L, + 52632148605242242206734320602317136445314295285812595150816657145404960256128L, + 86430865182180102182285826479504223564509795487884784384886813129147931898614L, + 109654073516008488670419221955708597615091266827715478203469017337766287849746L, + 81026678297990230131216764193661112039622434667965493171991305981991014657474L, + 82622748792598278407144966529781092604914661332588100202486823117756878578049L, + 25507322366608129176928204743509962836694925557984874383693252038444933529306L, + 51980179894131690770292900838955321107735899831146194979127760708884582438956L, + 39893713525243360628219119209298547936570206617596529159668900841315961417217L, + 14387364924292276198604346380005369236826342347182298818726067797096427891678L, + 80725549608704072432582752894272065317134564903036018699016358034851243292524L, + 57931677269404600136349629037176710293905732342675570761221364386370582050657L, + 108241043767163664167205246362258726108503618735082308459850286665596958398812L, + 27041560631327932383266441142102307786246412560862312846135065301507337248992L, + 34625690239551233696337914812047380316989766280990608029448299992841381318556L, + 13597595180205500577632878824504131058343151112673827495505944816766119242943L, + 68657989526988390460365803072516350579228727483683299855487425203740805321173L, + 68128720652325683666418891539682215901319669332175011784422584094377594552002L, + 104041769249150650432713286188297298874807527317507734388055926579788565698935L, + 17506611583023822782703007270314878467544710450669560774683033677129500120696L, + 79876035561916781816687040564988738579362298771175915576172207704762733629456L, + 82330566824257956442496960295477270673561486600504288976568497333939224637217L, + 10998126045115673379715696210992497023523769066924127029147032066105877814739L, + 6134205546032008896024930332940593161437017366857148587377265090739938507808L, + 11583121769842881304585057168682659884964100675720338197866411629831388260593L, + 47948467738357486329944891563527055069643980603315028338968162313802724094371L, + 11215667885570749573396172846938492308466387752575072442893328939856592581070L, + 9534445050215996549574184314121246759691522074947006611864912586114253182980L, + 26960993245824579668286903301462553933094711257295314684210187284207914046917L, + 42268713249784757565602219772893477530395402041957575219491013329425037932834L, + 18253096826887824215101051821620413966925375390818892158612837687736493874269L, + 32647453224566146209026428358709030929789472415884155623819230563509430098873L, + 287767308279396009793123999269205094524894944712599136360128064711797483633L, + 34729615465854230937966579696686155883411529356665280280028584403769296316609L, + 68281051772180230242281621506957421090373838565755113033691729820708913107414L, + 99139670525431256093001603279585358199342573071415589508037259484090669834518L, + 91267441814111668449455789360877685829217853601929030146847181639079805725296L, + 112331375053079340953180040166784320778361475210237842930567257762115150453895L, + 28371709961045497162723804260663265229524852382382390971491630999701617194893L, + 74287814005325706960840114010406717339638651149367996645855364919384064717234L, + 62813730919553857955038486382168764703884469040420815758550554930257596578121L, + 105545450997141255192635926957785838960634589257071510058148660009878001071768L, + 41327280573876048725438022338561500502955010393411792104623229499363429415913L, + 85305487863348628556082654688864393129756375287687859474166404086269915423521L, + 36217864842258952910470692818799400265537629839424907972768337859708224272429L, + 27039273786118956176256074242317720472159292773454814400065255644876377528081L, + 28257168443684587877664745623305158713429464605548802435968837515560446426794L, + 68860966611758451913434265377941548143707704988022881496208085576333989847578L, + 50407008970923325200185226986886055210151299406994703375093867352751009080672L, + 43833750391299030896607810025375205862164543819507809304552665996364584049181L, + 47517341024382467669841982663807010004070648542247729079498904960356542542124L, + 59501796603968326047997181784800665294370948166459642689928940044827716558887L, + 109356913084047950264750047637950104857997683486400548504377705982514288943104L, + 108764899133114175375894919353622844771053823794722043622829189650510861136931L, + 99702504117576275465334878690444650629284364394408283363533027878927080352437L, + 70841547470305287589274784901197362472932969076958924125873672199972429659380L, + 19614776128064776638184459221726965378454315076371196529553499930811313773642L, + 98079213119433189881285407717482612916878647506982538998109042938607065006624L, + 112302150976513929199789954934292839584625436975546042670097483152919172778948L, + 101270511568225377472511122900933114546675915482267160241459205096142886966303L, + 92601020688553922078305762385834063943477781040884163604477818272829952897893L, + 106516807503153752241651444005385814426259174908471724892260099441760067584006L, + 59558617948858154025583492179361041670311410135471546029253455165957065077880L, + 34589958509803762243288779574845189860253197080624774122757136677990409899676L, + 28956991241739635872887354391751915589336163031718370818567680713934561473546L, + 76284552793775899952782267192739926313427643498917773454793559446244711464210L, + 15169808245466745617655858126391662017843438763733740347957895786030136159686L, + 91303837629389982299584271607446771694386497564892828967340596042435535849746L, + 76706271293505348906195831263098926710454398027822085522661720229864395551030L, + 81385857155455424676782786224373024348911426134535495090280538905769333221176L, + 114027723567722411367125115195503223432492147480300914967916421352243226160863L, + 58683566049686664716231137094943841721169978722173124650775160588312999544064L, + 47636821537401183076676334731710145678811127526881622883432088094747228792951L, + 91536282035304813234567796434364946910865772878331169793296557113000386367870L, + 56229624882039089131852205427165270210088805730464734083125360041622328297139L, + 97669934343014072373530806803228099401901106327901588136030333298365599485060L, + 53610175098509849726221624535924354414085033990383931412157822600931356912963L, + 8456028367645624034579366182003257637590273712555737187498744052364695741913L, + 13590227372717901967224485586122763093032532664741134262481610836479299684660L, + 79363333042777866174143261304028217995231430841620433630348966723071049374254L, + 80310669348385703633478885178056527674053360397404660465646404494861426931512L, + 76053449640184337682215337408166493809582813223481816798649267699315054787614L, + 49557524797100181322234668564746448411465269913248832928539280364244877291571L, + 31349668130482234266895705887351848689030288515397213507254429683422494453226L, + 100523078506928710661710840376918307325379729091199276698426711431092321097251L, + 27321541552954853256201290168037140371906027004144414749507597003937123653687L, + 2631189220012736809936028959130414511579464458347740950181563826394086700286L, + 37707599701619752022054658444093282978945371896935011773965043895870793891121L, + 45394733945061302000923340867791152664821559733507222856568779530413756014405L, + 95340874961247979683533214972331081503913736359038376005637154187518984386867L, + 88761528612866195484152119688406674192445577846014439797767556449630773022806L, + 36135078039044087803749644587304316979939253848565308604143673942545508786330L, + 108170833529393902283960998731357956456749612811200500384024666342150739083393L, + 47512502507757503875846460116015295158758283453564371558196514794284165616746L, + 21507325004620818719248930115081453354560870683510626857344667716802398423589L, + 99684522227981982474613932478640264245627478765595518455357931316430023823495L, + 91539177891906741755261397047769750765528783737254354701533514995475896738514L, + 111129281145592623960314201429479518089274650176023170447570611164057042267360L, + 22578859183323245626833259777830627448647768500237823313657823977240236412741L, + 10349676642954124319464106128855803407368741329325517831607597138586570370450L, + 75813035507443498537723420624776215351694467717077489892101531934015707573318L, + 97594492003050383323388967820362561331982781928579140428340544398792480580522L, + 84556662590705018272581684903772636103662143419126207773614399679368447253016L, + 57438562249538101497765961483071062601181323207590598012932050384594326670864L, + 42369525618969729821281192750986928123562580701994358465110068123545593923346L, + 15631178904228263960240009595109284018356032359409694306860390850287169084700L, + 77010475411668698882543270552280721918070811228191463399116907778221183212574L, + 15413551241691563916071223025427025890072141513575960221673968406988693415755L, + 3886635086355795958441009792222975023324676133650112900867529851708672954448L, + 73012476638251310907687233534174360901505256204961617624515953950293599750069L, + 3722822644273822339360433160044015759398827051858643263577138590741753934176L, + 80408423812406792073723049542224711512546383585571999932848110527229812679010L, + 95727805294873918079320757434531209634714565678497703702813927918339782560622L, + 16089981349149755158831064243309353835117501894530652592287993704563215911068L, + 93181713378293406240141116118372622123133778817521454218943819809275284420273L, + 9073415722502328216365879393933068130631879884724670922841802060437301096372L, + 93517519773643331571375204738306910084371612303010400324402128977187968977848L, + 105094715911488287236836140179095673404733767807464456430714007607658401214137L, + 112024396687943913146262498005010531235678882540698412132370591267309885962221L, + 37165995241123181677724541737159514391850143080304163810158263549467466680559L, + 61968583687972759389885948258239494882619324802275296237733196640628370858735L, + 63829405995677144318484221414124274002955652352509310923559860713163722856947L, + 98532673930518295340902238602168289554424153910232929900036974384290255073529L, + 85997627804527857570889685520722152596798858230903042330943741382704463195389L, + 91215913435294163483873667979004310085424847448801135410605514096401666218327L, + 76227221506957628957308362003009905875501659532083775433150630010718621705923L, + 19195017703426046951233699673722502733267585758017903840970278708816922827617L, + 105129253587366388020090858980091040319396738451908098974287286821774711695811L, + 22781834725370441481771875988115741479803940767486902303521722492815410363472L, + 83195080117942179663592464716172666739649362186378211516611789972838421162501L, + 86594886402366270550826764806089860917730898934318005632123043261335819892530L, + 83097351296768607442750079314496113785526355672285553689112761857786549765444L, + 100851987071723593535660952515023915930748460098144529099521019911796498728056L, + 29042120456464831028285966716896898582592761151226643297300308103175984272554L, + 56883443662087622362160331291011107290929701370651644081822008095958676071604L, + 50508584653566925697655566823622736349705765459212244663848880793217444659655L, + 75831090901176908887931690796034589711040965462782105686888900253525610531547L, + 11323562829041465752257738545564075178220860053461170862535572762094853821959L, + 5217823388742578674217850823134011496634030019904331757976562616609709361164L, + 82174942362135905037353353709043782001314603797222727559986134053342781187860L, + 50202630649501021671704278043532121482846273707780410024950587977821359472153L, + 3324209706684823637468553443562813490050945432671016742542032334965381665098L, + 4740060306871125788724607025640175962029290860483506225787759615413578438990L, + 66756383172477268799988778531049589331084006212114401164616926079777855044701L, + 83247041555794071645514293521408585641895568480433766852375217524052544918626L, + 64541219727160203814701276749279883931437393757546403279238766945040313755497L, + 100963507275073289619694246177466848460225709327667594121286073708287464725661L, + 26318972549610462498778216602226802420225960415781019953778522488339924158401L, + 99012221291939162309007280658070035717355324092069715622838077145257927103682L, + 92091797836947203259213765762741251602220686559266784005426706139740459141585L, + 566796505847571272464524383407843341080331238468413785758834675896402367196L, + 103374921238374169420375942200248561514811450987014707811049404971341441272037L, + 71305169363493275648250184362479744655365934928015625437582365751156384329615L, + 107205417221582744390211344577307126967827612893837438184727896737548023950882L, + 92441154917234429638228535136154961872027655587283604258871139699670937581874L, + 84140778256663318467116520240058290998668299902088911664587745367709172336743L, + 45556845552016678147898181410667713972502449643588537645594148304307860456075L, + 98113204640413555142202002286205408580623426788130742652307101656799772050073L, + 111799582795648235049116568249188571666873753213621452178599923815977556575921L, + 3042745249238721747695258464570962925050325502231269880406471834698690245832L, + 79260931570753127951538043100557443222802554197894319158635554110571800139727L, + 48702562806629641894403284159379781964963463868578074138953921518729881897431L, + 537996483305687316813696733498511854451212769284793136798416670104206068964L, + 45276599793096426247844394503795241641541521518296716355002195232712186494981L, + 4711833054533598595597708926805930010573801678420856245651307107366104375822L, + 97959533653164703009028487058357458563569018661009994100670383461131095168534L, + 56124016112344825540146770224663139087319680635554267370628216094675068256283L, + 71388779211443877362892849696115871962852377897600069938201061972182558679838L, + 114814453627856262931674961995498158354061768715887759155072831158860551322403L, + 65127402122408243624228517277824006852940650639347380715847184158968045247524L, + 1229056862661197769327296679752341218679776095210307284806779517414384801320L, + 88972395288849790723139133497080910399041124169028974570218083938890114004777L, + 6417453592935644328519665655589014205209280966147780959484836123702535239210L, + 56638073514396757799909911152303525501958212228412740313805086645241850996013L, + 102579127893915729546257461329702255407926414660089770043815514719934869948974L, + 20052431404475309206985582743289944850004744789499061844247836954142431470639L, + 68972067553519121689794584486338374542497793488247844436269266153426384773936L, + 96254500393585373611088611894723205133243393228141813526638537758161133409852L, + 80604912450770836457589058367594765669839829467281569025199209131769915023420L, + 40557914330758410323049101458954929392166012791964555533532404907549224133950L, + 102924567605188907865161299769801785501600541170723406168868563766023720606017L, + 40986531312936695996240272556535388723561976353121061639925326611244396991048L, + 28844823668885701249680419649255648386959547672924676354836558450976588992597L, + 42076520546468627288297575294464954056406207503095735542678160715511123561313L, + 94876977270169549606488747653929487420735806539860621916222965017197647068258L, + 1260266738845674456679509616730441729777121674928342543364246627967833933416L, + 4523993849979047481739506944107708609384274326378844553994163227711790536816L, + 21431759397973169356219560894746023951943840789713921880195064784534930889845L, + 108821013162731753851414548436779028343880653825788920240350346162479970834805L, + 17906353290681234638813612028432794825791013736587994117250116787654462521721L, + 112736826194075300427719713325582084166039134281584305446092387153477526778234L, + 107984435224618494468183066425582748291745849218527044060754498637893340408708L, + 107611717886305319460852919775001524194407688118585221081009301252444206524552L, + 31954918240493906832747929653137205316197877563475871197676620430438989407116L, + 77294555680991456511548367452653169657122746699638304443667609185820666636173L, + 19208527960490820332864206665914487032201955968257931377530926839178302803854L, + 47154831783488794566405507384999216172663640884519299346477725192479294180496L, + 36423542791664575997770771722288221039652387193653371043205717125378764567191L, + 77555976342427942058170549023956985435812144640382949629341651348262760703138L, + 43412768734709911583567081706048412075584631674582341311496091557570021430187L, + 21959336236996441015148717897872088078662058498333610499842166795787287723L, + 63538326993401217866500688544194665721345933982165421139569219846509127908016L, + 79905845359365877877977624880233920057502841691739504437421524898586928213681L, + 10681792139241101858432940958581751179421847022560211889898357291399318170290L, + 112260621524927562855578944812289876926535469187048546674396920462184750797235L, + 88165566912353893589942666346863387620695272982391966569779494467819900828598L, + 52862665349173572715756317207877669753232762053342595347846461744880907785143L, + 71358808321103202914714309465454097348521307041367555204585916320180062656951L, + 93235845147880238951137684176889200233801378964276260704523792127410129667002L, + 72718808086725231119910981405922538172045185301228107871813451017267501324734L, + 100667480493446758970550426412588176704820604183058808112051923130687851060417L, + 110775042139845391601861530470426219464494762269966163468273769019688062035653L, + 6766593846697232623171307629298150462867897707371440407908986231567520535493L, + 12014347130699256114344244004512473658069924388663013028615566904229193256134L, + 27825969965105678940460966110158495152943605697219083763059951984078990520011L, + 96435523890332143175359238075473964932141166205743687936858586223483767233740L, + 102847003350359276120002279360870264522047980390554207969181636483503095996625L, + 42632940521258859773147600430080503936968451360493233839016831022987058093266L, + 19571300828974450772611380433683631913081195861922411543580528176815568926419L, + 111434655731367993894950670902059551750517417974415170312236407315260290389462L, + 23608235690717222095431745605482011235852604694934703409773120155291836044504L, + 106017757556879327169455640610201808008611274941425491584640844534727352975071L, + 100194237331574385430116872964535571014096315483635839836478381542863902431208L, + 92713684320292866626136347893934030297322201773422349467326040890402300878056L, + 58846607406140216612620045773658739808395681978926887219599326204302567728361L, + 80320823438646334388944027405481388252815446922782408490922543251513074510569L, + 30088741070680259716939238344801295759478996236886884148932817972902909245931L, + 102456232221700541259096693281931704007044911964379487697537170726371186702827L, + 72013500902968439013009687254900905169470508758023366846525128188789265135853L, + 106985170799722298842517273574171215868269301677890670174617203613091093254649L, + 77997640775942562320971444102112760963667113775720082983332959043367735711227L, + 62683654055983657992170448747531715227967029489145137570086335419775873779452L, + 75730785749340338179389112993153891613304743397576005533979099055998292284413L, + 66762291762568193891644841951279936563042785960280188860221342501381190300925L, + 56280313917343127517410849379001990997102543396430104866007467738343225409664L, + 59324467591512799624869384909984173499050034803780230329333867633862365756418L, + 1683044441174010502621700456254295998648099133489320724296168910612291517957L, + 88147253662322403593684832253266581017635988274298267439887723370830751451921L, + 58343716962123094353217839136626066057811742662832209148417055342402360726551L, + 102042089450135571288922375868967077092525830608023966680006742666402948847384L, + 8877283783700618681680100555294742645257799463038156608677788927594556549403L, + 23603148240625376790483040108047997409689131038732623508816589309969692005150L, + 45015696176505669695533330960506968194871235432630036247404021112955562173216L, + 27273242071094864677506735514648924422422353640301315884299919790802198722080L, + 62678209183628422275371869480260753311103544944645063056338863808623721685285L, + 11923803399857345669089076785461272716003074233828906615691242807109868335655L, + 95420412784378862133673297170980411225412791573819301925339594272229792658217L, + 17242422577646832103051643021716840952370970640892134824779146297889642365746L, + 76855577286732301379172865713619652579012237579727566874656827498872644015159L, + 96726325685354130145050911060879275730162214936626524357987449789504855781432L, + 50745123236844673747407500019857240986658479523835409288316425468889488181049L, + 59608141320400525935940756103659561296276824613682462900519909091472268126521L, + 74882687980309051986643522889218926141822412835990533021799272338776009053754L, + 37859908444522631436936741182357425966710844086898180834365036809567321014587L, + 1087203752576771943069656551595484272469990338994559269489909016589514126652L, + 60991521814750599780727542170354024457607925232661659210215919494766881930053L, + 64453051011344733857015590621639093213503986155441055021177965898233993175376L, + 77377955478500669379169781583746316561065084791761434771728115325544750893909L, + 115326776852904211740113046848936493585624387044642876008916017320233794968670L, + 66843638661901395342217121671364591758871761375478716017443685647803085332321L, + 76387522032998444590998554577947521953962127682731686273317708994350303287398L, + 100509585420698840447268897418682940179825506131319550264533306588834528678763L, + 102377125275632046267335597508238894551107275260674055251955140441510121413999L, + 36110335244868694900388842961776862479127814736923771794282870914687512014449L, + 48087901527306675458708724967244354205948260975796662098779427969098790475382L, + 26119165494218941379201102037784208684098799025173516959855235591131867261046L, + 67086317163668808852789730141898373404855391395159096739380812113635207695994L, + 115168997510970741273100147764087527929755242529074042878380720661984664186493L, + 71535154458377942923293268040443538978433844030766213484797279484920033289087L, + 74490351607525076344048122662784676925669814471098066911158732124307598110594L, + 95439581330187916957676081877421602929486334373742119907277873013637003421577L, + 87656814270301577281831314214475467755247771966329097774569394359651653327245L, + 81443161254179142501416466831321807477101179745994194567006581832939242932109L, + 54885804727455974455027736324678176988523863264697016122398430190356272496015L, + 106282862423962463801232566002528433716003843973088523363294352394910521613455L, + 74867103562016151054298336491250814339466536972863952799828325501346473267099L, + 35136655267440539281917001436812264484530523764622204463869657683025401996705L, + 114542145761998514467316137164479580426564663277916826776976176241309854292901L, + 114149603230109641409300300317765387311421041280449018556882166752625241532070L, + 22647598703536487002308745223680732687562703621499663807315267259473542957737L, + 45267848095711354051242143972062700550237336594373265586388322482699877540522L, + 37825297758958875478292750297344134694893802502002915810386272456730388494252L, + 76481269729086848596168842665464734492043245153991095180531790034161352572085L, + 107707648591247717508601437529840582949327190645047841981368706376540258461110L, + 40819894040158651744374093809592828959931640536131204592389598534102797112503L, + 59838558611940351927330467880089282310889795164199406620582423258897569518776L, + 88131656420112027093931319604678436950372558469915672228896966267905920349641L, + 76928539760456696194165042654470297096029479697948934824843832220438705590987L, + 62168541405737812225774170936595749260003015142194074807536949077284496093645L, + 82355551589038236450671947962490907589266314215583786237831900265624228666064L, + 91040078168525896186995537827257061882913779922844500756638496647089649182672L, + 106710078268466423920902446391414721044408430843209044367846557222141269618911L, + 8295944548002166402926075220981155129901615305773735264509560278371576354533L, + 32348596508610154850455749911780223725761145130705214865401572962784236696550L, + 92625991916613363364099403897508115714291540494878622711747426375003813151719L, + 22579452154116011806600193670899805077492814094240764086078790176929517654760L, + 61501673693710664558466566656679485767427270786661384288828507176068731874794L, + 54673841047622207097241337143648657461679490594088615644422753114290872923379L, + 99978210348430706642339409751264239100280674966640993530444682285055126424312L, + 77497348920315250447640649448270009364667831704951223117844325527179785810683L, + 44696363875663259716003609140601027659047948267389412486743757199567011857917L, + 100580552325682292262365631780644228565307253846729715876945147438523292289410L, + 11518861677132083256648844750152763986628976608478800601214858206199205313024L, + 62264363214572670209945783622006803827142264044650362355019724123136265172741L, + 33230973733442066812841097555869412305470922004648204666631516339173994362885L, + 99622694327542991641172302475186123081603436578607813888441614484377927724293L, + 102417455616494351577269429386609166099735639986419056945044716149347214777607L, + 64390549037290695081029250664557746977094876129261502170393311974899571876873L, + 4971884117270309347183734480578381967398702549340681853078909666997516183307L, + 102449383389506438850158445094726115013107692321577632033000101955980429851662L, + 77032065671909070527193774031803934854547369734395171920960771534661333256720L, + 51427001524546076067275517116230075777739059442665380893299690996681123652882L, + 57846707658031795839501691960956691748675157963351582448198375141276585300760L, + 3207400714205273428098068317265434706725664575349062007860014575398316976155L, + 48996192045666860806356015189011849203805311725988819243808235919973651832863L, + 104835176291815910614168078170778570188425290392670660463751413530619922189858L, + 14981119087540252574734932626534306481790846972083978190235605830727577496610L, + 63010711061850779941155020043897322102881519569558009332207660668803951977251L, + 81690223776687823440667971909822413569894292161339595790524996391870114827301L, + 58960316867947445772617227827225977131637752082183015768746567093022707191337L, + 20014782447901262411771703924763542338641386402379396629574630005982997966380L, + 40322371483089115316966842850857881228052744149017987508932980653077287822382L, + 75225266479277326265034150495327075359004964339592640634194742539303882532659L, + 1360427873648916040478677598931434689696693619539492831713328152985548642875L, + 102682486285577705635701705175111253737654165729779553084925758407023923315518L, + 112134468104068695940005782500350643375308818145271418444665998130374311921732L, + 65346288658858844548100134545139308403909249070489810100763409995477238532420L, + 45118385594713970159090523089169565316532036698798054140271220483524531336009L, + 97476029759653028058062317315042925637551962120190446234623575312461737374538L, + 10065604931768692054377094739162892613194529191136102644454214890555337922379L, + 51553786030402063061700254827386386701080790101951499376167131293753402321999L, + 80597011256255237792858049009205213538457159347705673937143882448274035124817L, + 33844272053464645237023714379137059342202186464203853865794780890067672118609L, + 81205844186930169830914915295886776634252574020398512386640220917751422229332L, + 55618115254902954328799563061770051404707267477826050932521018559065029105496L, + 72561727906788411099387267207379154973461292291399988323244582016927347227225L, + 38200302126249889943153227138035137817990392515788356056607004367257772863324L, + 40512699025239178899189201917599830173998902277981571855357988350276694199133L, + 72852130373113254447550573789839549535122462986768199497118255107335826856543L, + 21556543496705918692009455279894741802994438873807382234282828641568574702944L, + 94910435199430807117493052677366099392273747913236237307831525304532287282531L, + 75861377249331562077017399628408234437628214897939132885265899294794269531247L, + 30876075781213658129907831810717284861780673483216317641763733274897623510641L, + 20703967708517858057303822389608487644244865221307109638361146216007403372403L, + 75484464698550708496430527575646346430950676445134417683713610303229079110261L, + 87129729198669339702782235251703596679641140877606117618734732225582949267063L, + 21266603676197216321600718008268210400030243356122680120555563896175222459514L, + 63415715438466196790578746287176311213905572186996635167094209280910967331710L, + 40720368057718102298431544796123435043114356544273008650218191651074186725758L, + 112712268248652359734080083582461538637344066407845029243721092493183497206142L, + 114937114775233845143486959600340076179533032756834814512468454080273362545535L, + 36512901579603557913193537689480903094184396356981067116060536144286700842623L, + 56411560426836146870951539885920526009324584091242151784611722979698021316224L, + 16698912456783170995326467336104513767160540663058718259277822376227672090500L, + 106066760722965292194719041696986145324409579006780335464791791351475409133705L, + 104207962904909832816216631384017349780647804676862987772215854348086512657034L, + 69243961841176518549263230888469400531404144027167071188890585689044072806794L, + 51253655298165523882286604420161472846136153868591164972577972118747996841358L, + 57522621367187189331324803586575115229510487362376403257825249297783421645198L, + 14008691686569941249702994950556981918752597678869294675116218434795486754192L, + 17559590831409421526199061660667061847018920246172867120529710154254038520982L, + 62030850813603681661213529210192297536410672609839415084110307444989808291479L, + 39483769639853010170216670313190346123132594269609674789398817914937545130137L, + 27373432150674246539366656193993633656856212404804434949408972838465544294041L, + 80515524415230956277423458011407925895348914691856987154482076010610066957723L, + 49603749491658761343063310147446444301134076709989236516539085749722917173407L, + 4638234616841955479208035396665903927460428545633473766627229552734393840033L, + 64407677702144975949151853501065869572610657480257459923595074962489696100514L, + 113729063033800538237563507194947437935179109496004542295476338932824489294756L, + 27559869753538413456779817442066339470743784389895941011935964995056981446309L, + 33384381289532990083476970734483649138372535104356143628107394996921728224933L, + 16207109765807602992397132829767586006453433292590664044414937271538578787238L, + 37996198627725162202981310547747180578940010211813882018801070905394782922923L, + 24628564513391374841142496199906953696196889294968272338406815750563978886574L, + 77311986397370469321099234043385939709573400347645098238364769839769499352239L, + 101459630443329721289871636542291648339599060924804682699203278554752463558831L, + 11458472762629511670071313487968925641575058276033733567554002191834171792815L, + 91390821097036566407235558097405985046641826208230501464531008191101542628783L, + 88524914862823500026206667566397083358529858623465072900012276950788691297970L, + 47781205217992275185276602931233775137652615298547884028338694579101702392758L, + 107336460889271365479382359792329448251372014941188862765727741363490731115713L, + 13683491250017276293402705979452529337188096939209334955030433229234688947905L, + 5985774502351629175676960426324333914303410190559821961461920762704934667459L, + 23304448933988759752992693834848658743002695800222397537634383934483905592268L, + 37564289103624408045017967248710953371026230579918885993454830860061146739410L, + 93440226217921584938869887668526350605552124529469174921820542544604456138451L, + 35976156482283765832545022774001668880213841650251182381063592287413945396696L, + 57297350844970429984695678794987814945484137417192146181343109118733204280547L, + 53078088315412211833793751124187365422715677410329852285061982688379219527395L, + 4620670977723745073636505024767100328367801928808682752786389987771180617957L, + 61803525948465253364619959990876209602238139167016879456633670301134189240552L, + 46585052829677515250319943717834196659280187016435597500044886010686587628012L, + 91743224621411738136401680004986839707449070953296895944081573638514545794541L, + 15610234236458785326957282756613241231461484896412468404866135527865235041775L, + 94701869446822483372701416835685032588722414109357932060106387983998248530160L, + 75638383867886646067851120099891468008833811906034441039017079502899866891760L, + 109323217313071505720530793462159030982066925855329700973555314076623421322997L, + 86842647332705482807195494061715107567592560678052902441669254344785129577974L, + 34022377235592061794214362952580373770895570995095680439673944392845030735350L, + 95953533733989408445261475890619634519580457917243229943281863657327054532088L, + 26422928960874356778655042269888582567356205407018615492158941838555144306425L, + 18967698604142970614994714313564229649235700012432985379836668529749470929145L, + 63892359660797867642513857940530011048856439862103598115303570201290361878010L, + 74588898331913850583986198817678327719748410068857456293342190987907207856891L, + 1891303523949303133994914040695860991496422858712772749043232242469596454907L, + 113555415921895241105938811571952390824966743626599165941730396114135776754684L, + 52531601946134219932308041725442066030140304634172421470280771996149298830846L, + 32638282716726954532165110313232679865817254425127224461225107497334788167167L, + 80840014404821550722694570450507044048598523598329185386887679198829878334464L, + 93645004356397514961947862340688942736458020763991484114338872125689456535300L, + 1472416534300792912775421675541677859235555728416376093465195351989356744453L, + 18117018437999600723844152703648593933015731624364436216442596645224534012167L, + 38755468804570185370691489631181112753516875613651439286270705031137197580809L, + 100715082849109534526089419466115812821340513907905118566143241487861302468106L, + 92098448699173499615912973532879395459946025134630609083709282508755477552395L, + 111550391766917064883209636905511974883811737658416504517110617588211693661198L, + 32590990884507149788797018565535314787256008527518350785763118765435090357011L, + 38181426751227898716885399497713675463479498492439859204929263568713129655317L, + 107065502437416259973837742628429643307293123668177644997591368635511427025432L, + 102057799846669375009489265342522217091426916766438742908452443895711329210136L, + 23472322632338496027637669774186145868837209896740446601934999472619109133595L, + 54101142996391643743621251953151149918206740135985052202976824025819666034459L, + 82460774504538637863049867790099375227234890471300564145128882983342803542300L, + 70948468164177177761098584483928896319724434505662727209543615378741024192029L, + 33320553469317264567053573050009719096602040446852816915845293451211202605096L, + 33341836337609530655545263682386433268227320320366701976523152771764387320876L, + 26832722136611840332586354012095781711272330756674126314113044937848293234735L, + 69354984871910123412344914828142550027389971844247803142882539980451463733296L, + 38887218044895438528977498335219550982795547502506023717328967765626818401329L, + 107798852115196024784748025278489888281525855258344453618798858457928346979635L, + 99869280657090254472597381392765515587357272194286676483834483257630760565045L, + 1150972596982422542285349832340838048711887764822274317800353265301858729270L, + 76377579111292113222500505883636325603958491053990945762690246057076144688192L, + 18688447831653735278420733874064402883741520741110564341076606483438814241602L, + 61229082344798583966128461730723769513868549112845325753229329289005961153351L, + 53704530304758293508517397341653702649777610155695564065012810155341918026824L, + 69672085999224845630835786708571653616226767123886631733530421027118690179402L, + 104228058758416623080861378964448311854955016876464394251376949850452541418062L, + 69861378734358355516299556986446323876811798280712171940673944522961928182867L, + 50903666105609535885983150746311206289999522994573939931085951723263504210006L, + 69762411846342189978617721366439039456328223786210517096429517225270053858904L, + 96785295693675954518102108713098751227477969718126822490988190873035929951833L, + 53902883677242743134794950840131929111141762734886047716628834964250614593625L, + 13628634261468974632639423922822047532604745471344190636598823923634914237023L, + 105452706964076144192933322428871834424779481173006000018659835215130331082080L, + 68824702000389919294367590560891160312350680290197141749599999274678668891235L, + 107609796248259641295614822376326549134793895930280222093108768885474705237091L, + 17806410755485799985163149261014742382557649011328574576946479857183305924707L, + 80007950390934227990091902500313518817123793596835360540614202062387629313891L, + 57047043109144241791334156670491897780217521286517046751569717659939230041956L, + 22794699983082178924910854965780938016993946962403974783953812352356032881765L, + 91880390829879836574992268062426895025565288343047524546899311051396352657767L, + 24705349683829662791049355586479945768768745480311908459758516972931716053864L, + 28545444886607560846867534556715623648900007232552276819418615066865497912938L, + 84368788466806781207329001318048580816467702441792122148092700034070300901484L, + 19817770163640889510029214040635317313099932200316047934680130517821060351858L, + 87805468381594296285408693509948150567016409818567107939512282924564188137587L, + 26449397396497515260596530903090322378234325869858244148315111808400524166772L, + 91146992636787877641545809782917382766985304095181848259100686451357469554810L, + 68715426009894030818044978141743928912101323309208159313960265269320869827710L, + 18040473385285586900378723202640495963593962530797220344080340777191012984958L, + 39275664807235457103450939776074687460408340433109552545236608964230082437758L, + 45010170468168442348096414353924442562300445083918439509650577849987595206785L, + 99879829272458403583514272136956716403150130902119831861390384493801483015043L, + 35376889736154427903457914694629675374773640299681275927534732356185078510467L, + 87403267383558378895382345674614868515698911467377552912077501940526884632199L, + 109908987783177734919635133225811271606397029398938708298511253484148973027208L, + 17295173665271586512698645247530859200557285101599023956986141259468312403592L, + 21496543647128813611837541425310251098581298051727650082921765810637490227593L, + 73924679330956858959462999425158452737576816314412552159708766718249552631433L, + 53384497678887864522475977345281785491278676926191527209728092457073607815820L, + 14370611267386563421622036936506899557654641367326539546895441154821988158355L, + 111107545720208053555132620274411952639184732975950045885811881349875589168275L, + 63911110056340508982724335631458613598435755978305300013119800762745751222164L, + 4991172388731658875474305317575165618935711992108917888386354041964307307423L, + 21176876470041110100700684587046880911769841360105649899082567843002481283488L, + 74776329531575971143272497818603797944162195101266803339847407068460367192736L, + 15972742698609831215845555456389847006456706745673491891035631526317253802660L, + 80767473484885926201446229963118832797391190102702298632676421820670824097445L, + 77635205730391155379004464305903567091707977567941142496628511694966092103340L, + 11406599509413455790469570789130258223474549240858015981787947665751680818610L, + 96083529219145290605954079034682972299178843718214603389887111115574190137778L, + 104182749557752609588066266373190615208480722850768531026125751278015041103544L, + 48631184147785440090049279800185073974284491295936065880067181420459954812348L, + 41623436996314670663601629719379360870057342449489798887029141584109168613308L, + 86601098079032759868258107257839306539563142953815642076039395625817415854016L, + 105563939493052531934014237726522354074579599535236523608564993934980248877506L, + 50848326516601423461822147317609300665761371880723719335691811236205966272452L, + 53443239328296388634032728319465566355172671311595650926236448987473879053508L, + 30110729293997667786865555990487461290947942687167400634833810419675629426629L, + 70614983488614829546558717115340990183273642848289705990085731487163494754764L, + 89024264216765437369979043502108523385158180365027814309471804683407653556180L, + 115548456861997880437700681078370418758203326265657797575702284309135822057942L, + 112898553218512376742308538661783506627001284418604607767529974448192381368278L, + 109432813267443533585437973840676971983433963567786192632155786340553107824601L, + 2662704726986836670271768579907165881708722419900219067428758353742850375642L, + 13613520122626383917675800206671181232214326649155827042925689433090213323994L, + 83951988661545836264706075188513666042462298465297935608985505609887277022428L, + 81975715382817024762173756105467480535625820756145068878263626750270374605021L, + 33997601865631325889191208753159898949487673964493425383191044088181413836510L, + 33488295268844659105032035017240770147984662735095586450543153485248709891809L, + 27897772709719653846193537544497924350188353304930329345920284332030672261091L, + 103238249936633036841613509228020446121198544683486725789653177543671611484901L, + 15221234255475442610452844759838468002249815991530457101462023560018655644135L, + 17374917198965396359597519847766098730144580751652864844888052673202112933099L, + 8453689025481713885958764231345740830096722466471336992142774209143222748396L, + 87435019133094385353914686858439226234011979874934283937402214350771309380333L, + 30093263016783185690488553559991952213412981757409197134146673791181871176688L, + 105801262676376315091269117615337342244583356570492008726505273535486858061809L, + 42199981988483184642320328432699178004289296046138328468300467526183146227702L, + 24808975952702810597769395794187108416393214214233361021554486032419759604217L, + 84120069830680241121422959140358303947709189290291804052804239677555153714682L, + 57145075288344878951245955904237169364079244068759619386581476461806309049596L, + 87037046752894812688116764896029579808521078387282643645990731265108120107518L, + 53833716710984099268840341191170265452631444148382059443690844846479300578103L, + 60433892667251911178190082663895913801033234243285558434565454351653288706673L, + 7637894742751632937036126902481741313410477934705839951387925907797272353418L, + 28569702262874571106266993749405212812150257672385615282012173882373397380508L, + 107293178132644939554701238383356912595689041895825953526773070844500251747242L, + 18692107709494833026133957730323867060831844188841832042897420729557773016764L, + 105215836386255858696570193840069945162296319710058502813576963156340050516978L, + 109640003434925005994749370852914721031598383660045299893366311313447339993673L, + 106102241749728113753317719222455613176545485853188672515226171948431738326324L, + 87967514603464604336907917322902677786986284949310789742480895118474916781293L, + 10452097529658641654898343046410822952471479992533447520610095024013678943251L, + 23998548314685811912152945805085035389917998668934352311929808572528389431896L, + 25939865866010035882167964456470371600163942045972853680854911794476690635624L, + 53536172862391339437029795049857615030014626954364478815337794278161579085454L, + 24964604048144863368823580632207625813548165209250855284071966109033283731090L, + 52287877752354792178225670823552022200923488758331256946005040333293056268993L, + 96364922991497529805531577328219502400267879296003605669407596718895309312833L, + 61165071124090622680837349796264330231271014144745669869678812170302746438904L, + 9862529443171077075599421597487817548148389090427391749462809411148822924295L, + 75677951243046792472455949187424104363526002297883608938230835512231614460344L, + 20163041695099153318595027251967745914329198374871561563937490346110992293826L, + 4157835572607732630870554716292314261800050096614393441327328109790858960534L, + 234905883427193112047074061162947269770600226722370798297521202217780089105L, + 91529499029030045728854142855955178901186723463577650890340040626063925568268L, + 53064575229034380164833917313889589009225952735529633244690296853431154256230L, + 71892978348861232155473269601937640066130013123066638628775441335656959331296L, + 40998639209287247912295936589461636559410311612976640996950055711787143531252L, + 74374227204789972278808498765271912946485755525825491620610959018166890338045L, + 62451921477571070161755657423071910758989601872448563362100668997102713530293L, + 32134737138246725932856372118303955100968116041295195433870841168959896235470L, + 14190585998210682942717510078458953206645440166185429761253301462636372114475L, + 79474335301119452810238376391469807601074622440831977333649965428730079239176L, + 109567049092477471774993763016826103256542113119281030515153187392993745961610L, + 71418646896161860312481461467422529279350093001628823852273582513872656562972L, + 41392339283265326163133896826928004235033698573178712532596038286942483842323L, + 18532945973520998179912609429658373546802263504125602083549893779219578139579L, + 23502144262977761670759481544729389592488156074598394643273279227888279825422L, + 83046195510510798713138622300841149569770856741428985034371033319940242464301L, + 23317281782700035804616836877354302486621457146647933488477033449530725207908L, + 40206452017693607115032426904290824747142352947913355465262447954871640645456L, + 53163461084033728365981239326186532325844271665541815079115687724016913988956L, + 90965467319718316905273128864160965695596596780960242040099814032727903699091L, + 24734798197013628509636652015719753306714635092667911866378518743709796261090L, + 37433959738761870117015745949755180738344986700115614650383604888597901882339L, + 96646475389668069819458453779252760710336863933494930937260323864991302234708L, + 63952408163647557708732940735667268573608342775050439763837379155559584330654L, + 35844370870822577464809521336934643034645139191512223195918819231967528273209L, + 89048024331773490818384593068703118412135203188376388473438110057526922667796L, + 78113748600148180492734505349333372472964024933653400767458434453974032635824L, + 54173776002260823255859915512510128977943917299469817997380229925381045687010L, + 883432050479911142807166205485507168437530802395363642851350109882719118561L, + 53485353294057357820057190873528970994022313820577768050270880081771824850957L, + 1376947404935534290290878709800598865563628523586336626789091230720889887532L, + 54782114845126438876586530210393782366489074178219614384072439562477141776451L, + 37861199306489999468439170251565816928427173812130674532522879137489546050394L, + 53640132153877617295148818056655406698667002755494762787727014438853749152110L, + 36094520090494132568726788901733125729887512412738145324559488327331435071209L, + 47708537139701186414364911096104061211191086914223449210282658811429201866114L, + 44642009019249741536518128251511543839799104615312192651332257099676514463852L, + 87290192662809247283905546878108315691917779968148474260664182424127696884795L, + 97671292518018682890893268494597883645013579196143231920993066499185701120805L, + 13691409391483500819401386629732148379513193717278663452790161368555897957557L, + 61144617532654697585779294384326603485860537145081158448917611664126233388396L, + 68193985570254974036684107457627664520913551894845023070425351866316352884045L, + 35186058029995664124689643983995007874332255773767997499577488346513719121213L, + 115257539531614541222503830830159607117913671948645429228004653119055141552616L, + 74108023471371767946328733814543864504216020164356715756271718337888099957251L, + 50699915395557109958628796848153707137790179197796094586999504919502748430036L, + 77098747316761893952761000882437066900927643357092640800471523098528858444741L, + 44196706823041307166630159413528024217064296070484564708314234712750074312552L, + 54311600462392327021859357736603954008201712037004116839763570346563191882613L, + 4712645262686969075341091045084853692873346753675156591723064046102802703035L, + 52633358246598132500454344861267240274924230486539615588687078210860399265530L, + 38428397862610980636995024113151064406919418462458968489360301281168699108774L, + 65770083666590557138121223737091159168021553714387718826049997301601143959193L, + 108783332248779216345938909800809951905550875303335887996223250993612985109020L, + 67541554565935595782234506279937914447172413779479709071277571759315214810553L, + 45528057480829729537027883221412675091168280876932366391030724386747243695450L, + 48574723508575577074482350565172348685996516743512538163088285343250059087877L, + 9595676212719659333705612367115264818901075522839724031540792598785517533717L, + 59222796090174566623152004867125933154676846013253132266547265719068942874438L, + 28479106166280290479941097145545460264531379215822491299649689124114882347783L, + 115221963463389482008089037619913365807148966626978913613183808690538393935135L, + 101487675421171222328197615408486453515275049269610846629698626471597817468619L, + 11861229503001181872799219422814386750646316223301525603925541253591330339851L, + 96655017127890694119104679709472928946428042193874408633126399252134207784565L, + 11246562242800184036344964010942066327949582707661185521174872759601179948207L, + 54766903279946870433142580654753133656570753651046881012055208086423906484859L, + 12192385043177507341587627086564649875670041135249486182299191259186947947309L, + 33889531687457105202492185235855624065169098231120588348582196414732626535731L, + 2702104856154794760471215991723866354322572371902534169880991721008960334465L, + 68399366990142009038460674908987124974500851011439562754022428310012312459736L, + 78108361281240995542833859700117440464383194760701784594883633821430667130670L, + 20035281797630887972432431961122297110119895828130977481522636878664781657816L, + 13736069344130597091646675811814843306462843438451714675670050863189721631975L, + 32797729242950926186099069834265616197055885262156260473288373265286966785666L, + 7176087548488327762842449594330860235875811675839995669904883805237403372677L, + 113919392582812074400730572616241013136099488419784443992170205486316725802184L, + 6715092456584007985435621264275230946247108351204840102696310162955301713392L, + 25855087501533639303583124882822163677359861627083537912598182866705764685815L, + 73934603666361975032570131227835167994759894693957111126295581402147687386059L, + 13155636084969680059396242142814026699440156979544128067323264470699500335748L, + 42306337368511321037651705965062931061532427873546337575440482816973756453706L, + 43179078116044711766386466429804449951992950924570899179710697254606382745875L, + 34589225484126804958636126788397727945345620051478889688357109997109890005014L, + 81931093869411066216897619171196290190324526017703113902729211983823973198308L, + 100801062496088586609073355121887698810253404134289205529785971351082004400626L, + 99269301541754630549915461021109784052069747562594797681818988947004492282033L, + 61431623606091659417184920719838855026021341187124428079635438195442467589773L, + 9519969107896444550582618655543816405745746174812287787612255552324868264143L, + 108303744709536731848858243495069052456568556669038315047210235861188168386162L, + 17605988239301767548253595490806242996920114264054495381453921195513354999860L, + 23513923262061982218339986786461381461131246534613851254442803506567387541335L, + 70320038567705804654621831197499164818764202927326234150367518419292464747401L, + 61770709396189132856751404198972986135331105234997307478609738138959714680310L, + 111407271105634327977613271210808817656742352508264185802621981796146688951099L, + 15954738196663214636264590882028009749755310783326530535915292337735383603085L, + 109086491948127246516313897338785542867893034038519662369776732342690211551400L, + 22416782135059375987641999873907617075278492784876893764069641551099207960272L, + 107190810929285648335320627529686263179826994927201194238265606988725047028872L, + 47810903731926258316473414112936857581544784502116140622649113458343351162853L, + 14454090390604916607961786668722881948090859391738149034831583240117470604831L, + 80666783391091672187446797184315344472571236464839098416522221749649677801945L, + 23585443718157415684307873337161851844207024662853153813554868062732814732990L, + 27775727080975118707880751458940094087572807407477642227664452738359631508370L, + 22354007203029985550445000393366637942734285325695079942493657830869029668598L, + 24464348418592982883315752347111913022278560091043014074779583772448662366752L, + 106481239012883339270648085769617156311063292444742859382987025194184948418926L, + 39011227711841896540196435699763946582967257133741224577226414069292244419921L, + 75596650937734374746478074849258927780055535729028164467001982844458079870248L, + 88162372027313872123663368261082673963273796229751284714193546223272846212213L, + 2576040472443446723468928690754824660481396613576535456145099796125956902445L, + 95649859930869763777362274239913473448995731775502386044062500006671888513755L, + 23725060470714314999599710406296489493250175197054609214912167919579998507169L, + 49555424134665943820304057631658137318054740093228750126361525347694586145134L, + 44501457404504533569101232018780451136332705470598006749312845628972786270466L, + 100795118997594249476658996026745105980251851253722641580769711477747550208479L, + 52747201652346084586405369953639735566684715221741890642605754187445529566660L, + 15680619346733759700182666282587216548584469338339459683294440044467091673631L, + 68505014731494649040515369252814152095031304372285998550214915975944235191441L, + 56366185904135320986610028835710099815916974781671600220135407206376964487938L, + 105321308694088112597872430790563332351422354737991856346326629773665525386705L, + 61278886852279108332938535370025837653652736250991006419628139504400281796611L, + 28953313899949437588722414376475346673461869492846759563387769216822610712214L, + 28663118357329139790106382764693217907262920349622948757012124192236390817438L, + 21039077739131275359790923848462140922244215451512024187049160113337117620791L, + 54889718246598634522108317610961305620004833993443435630553026048923012178008L, + 90874603760301401413929288679885214040045826428675227957098967087132935830117L, + 112920631033471745311323794101261642576610674750854945256558164996387712631992L, + 111963032704632250385492393582328571618828927494502871768426528581215908256143L, + 51274066318211493418085421333723782799031831706515873891234805824063678178014L, + 30258011402192701880534182314866634113801183941256349214452534369042216349987L, + 54681898988358136071780093135450779338110800786503156323504807233876629268293L, + 52116004686547134015512079196737968242196127056558021115790624820932553017441L, + 109513064700864368200790843893897908604544097571420991817771435722981765661285L, + 58488394191083420053831021890307144018799701571894914444409455704836690297967L, + 62092454581727457732790593578509538844015144815933957266786304773060873782649L, + 14368297750194560111165577701486485277892655455414407596509400442670064486023L, + 67269488270555162552654401829506802539249729946556386383844397948411601017492L, + 88377116761526687308883019385729653416563320981418855150352008673734620992416L, + 53028559510875446303088848877733416279134739545287887275996211473197952858536L, + 18170944619136371204284994471814938841783677453339517631096364967572114396852L, + 2059644653191624483771262513065435276723804841147324755869599281586451784121L, + 67005151150252609617525866625502990805012970844697359601920455075585694928057L, + 108445302124264084923797508969188019268300509993700767586409058734506501816026L, + 31825975368442157656648045088070797333742837391042415004089769634419342157546L, + 92373133245786521768072671120807298020874152547973833174760183943173402771443L, + 20288281055571831952965968033892228523356643855585483236574844945395093559189L, + 105647291748962183726252681179938945648788659297315616260960540621695497879605L, + 37833694536671453212494333478156156499705175090441264557352190244699875139348L, + 102602930401694946546947058823975116987885575233548964388547148483039393577630L, + 17986089761536074808296642067282970280697535186488892744151942385581010099201L, + 68302507041169065371244854845092650671048888830947577079872550921188098246733L, + 103723227189535347897681598138697061790401969590975977817284610334967586624371L, + 85601933490467107005659057944158927790168058335522482015593505983064091002688L, + 72566572839803178961075260801968244942124210943021330655184096386449590375522L, + 35059921056683300948407515200145646684406772201818796747803118929279743459461L, + 110175048830391929923807192301406443121803247399292272801332112057564703231241L, + 89882285710142524187416311971836674082740664835810560379381270807979647760647L, + 70399401443372985077677851434886144983714060812456753675306983539671260338480L, + 94184317541206020457753610078145103270501645532598184588800128385125278401946L, + 104314965088674766481912048088686697905047754561911560292135031019128925521909L, + 16759208768307130872010233216200768925859942429678535169150770158493348620840L, + 13312049214029984094125277617043550651736083619871827277320968871324596984413L, + 57772980362021788072324853329424041285142553464137832050079118990473332575549L, + 69375733674087675844485774733379151295737062349294143700229381969561369710274L, + 74182466324362383312773623566448418316679680460167345042228292669832757876448L, + 102551475084433340433597725405003482858429650260736516785950146965463760130080L, + 87871859628381700091124119902940792161691323803993634475404190944633451471207L, + 2271931461440553944924676609864205915472545722242321043389109755049110980703L, + 79159816565443796059736871395004807034524018072484301692430191707423760150320L, + 29883226291024495072614404351628092395902350071825263946645968892560207990766L, + 115120985130692563114301206512024055186792485071581230311061507127951583633034L, + 65575467306404035265299368906717521523933770838335685501468397360739564342250L, + 42205652281356366407511084862172573538584011195306289505538491848403141436696L, + 80956675972222351626548870352985655925726199776618815554949057515111559885624L, + 106838054064585501497489884559010507476859749974884867124569682177542395636357L, + 58508613315380006091312439893090755459648238433588983488046836958077836737962L, + 56148822318227387858840396109889610931297126924790256588515075449476241527368L, + 87943746830857581847154346372383846697749344328106573109857573515682121822367L, + 96523912520065820718774993637097552798296898412284402472198573038137304590111L, + 359683682346866350672530414988029153152780243662150094655719975922703921067L, + 20653639768030400341518830556816476408986031232568656102751458314632334992472L, + 43741907665130124851875589584874693089547759382726615954038820251232049326509L, + 37602134064186142569024483775410247813923563006964949437626361768237954885625L, + 28319089020767397392393687573389812686784796486679445318554621348732771061676L, + 77246899118638359174675247864166883750187313215548163645424934342464850069490L, + 51416646531409586193575382020640831077354780179380885705693619583419896628285L, + 9530718880612395598296191543657574992246299996911703966657028659200776742208L, + 60075035395757026542736716551158662576872365983788226206193619250298945833195L, + 100042375575081934061659861835216643653798304415561784355714218575018603177373L, + 65280708434371170784603853111027779811634446129501474686503326478617370733569L, + 36082491953381980967358850906638601152925053882808553201819544090274971464190L, + 55038301814136661088634961160554105058230388568456004416928702345321148540302L, + 81148342511575768823385245247395685982245196252288670733274133346415300143012L, + 62080887902672390781432753313761551609714174003612865233793627417270483286982L, + 90578703271753009632879728735384597245850512229571538778074284994607743071518L, + 11920275443785083579547863592574994475431467374061276954952200960834359779284L, + 7901870192306432837816630504620172895333432875298603507830571901927621351928L, + 64620902328386916608189819363308224701333637778025950310007247161243381930720L, + 14902225266028720042380084120086803828537629249534266721931268127595544410505L, + 3011605234853758422230399637839989432595388927734475258720799035294793988797L, + 62520715887062371683474293194758668293503352226300290954191460249653358455165L, + 109449423401707713638949069954372475340901757609906893414045046366250410887842L, + 65974474648235806363505863545271426056265018043065296667037687570697194645520L, + 78525856195119157844801092033893631866360334827506128936210376962749108345401L, + 70525687758401237580803794876205413841795807333861929519952792049645580777583L, + 97952100411220391333417229298712459908053373138048531526005534270083998312321L, + 69482302697726023028500675325521804008063245604738851814471767661199529941929L, + 36996168631023473249056962961772045554540227552693956887219738140514501713089L, + 93939398376370462515305712120711503754068326322098998720488107315540935981941L, + 92811710090398157690207572646387238821209630261125711411677156614949689675192L, + 18834793150066231989363619595201423057509694963201888288496365825037060604758L, + 106508534598402557052256441317317198663098123351872314746403469913152131748542L, + 68522515409348199421798410175290099384706005335340883038949614431817306224878L, + 62056677592132596903749111258191415116948937518303008459322737884771944599453L, + 75008671987138723041813528774734130483329012087779153368244930953066728755167L, + 25846618857014646943662784856228290889267917537184350552103409496789701481086L, + 25790780303502933878708389860107244416128741360072781451027326248893088259707L, + 86875321517220196586131106365815943863232969130696292969809460985631264761642L, + 99520552726149464340676459841037055051665646298827646711852273930103091648025L, + 28302633324103476432059489855553140037931375716779079709591381558250668123793L, + 16413483725800636879585566339979225218650831073900754551215329181184498261405L, + 5834089563252237195293366572204070003116504012683549677285781788725993972990L, + 35905663211833345298444865971856108258053566719588841426933466057767703473670L, + 42906799631117753263723316951849157590527745414511096962646744155280717111546L, + 113670886560446927486126023588018623266901616824365249620085243678045044523580L, + 25525758440992399567030267413743803341303454964963442669812892814158222062282L, + 104441409846129220251060822845729677685228867748033158812417230194198574238533L, + 106926133638744077158340790093952487284445071012880267650762665555269754374498L, + 37777827102888811508047114457204124487000904404039738423689478126649282839504L, + 51858935644246862204293187403674270409729920230211975583979198407701235735521L, + 56677604980298282251218999943872661748831571233436439285726091418251163563349L, + 11310141567806595553122776509434966668730767143112763614244324266096150340396L, + 59568236466598403304367610877197823731593346955230100312347937134124139658515L, + 332686942346604243797197324078593908184771416824239020666066869442498248085L, + 101184157155811626748420360485115445073052410011352426753492759316284346161562L, + 115094616142259749323636183065876615795354632139540977617593311052542877457287L, + 66300571744633578417215135324779936328456592743715185456673735987112942424605L, + 48613583719208218896022351529040027028353166267451589591626141321431999840359L, + 45070517798055973346480716269485737939145848218807134819900436803766392242105L, + 18266861866071039658603879196433265099201917997393304488121681245291543324416L, + 52949442752612150788933147633704799723834836139570886640702983283974722895359L, + 106873847237792435016827377973268501512512482320890214232588930141196288884343L, + 15569634565317975671895423006707547283207063591263118835559221760770692076397L, + 90410110389444957150115334781777775354854962401059551674224262867875151944330L, + 98759087287127560374112096364011567243755138613650190558293039088068825947972L, + 1287633407928248584990208256896924805269922037761331075659055166636156115579L, + 22643922918408084792057622355331184265168520123778802808674980998986152545614L, + 102677598412504156466181238289651366875920363577612196890121675411616205869266L, + 19140515938422692005504349297136392120094231942932381661045006694294659348157L, + 47479392819189321863253918556058608916166486549752862534298736674771025808601L, + 13428886889019792224212350792850118124090630647372479978118330056662258502463L, + 68571236458166791056101358438734290027379299621943855185416588699972634133780L, + 4633337738236570848343873069653422967090076837450676791156853186692050402794L, + 32382211421012107606460976657528067674979613660057986786543262682245644259590L, + 49639024571546822434524105347091704925075399249527661103359511686788829885196L, + 79150125805409043239175151923323021000363071231306074866016474509777361482770L, + 46020124799831855390812128987233512854385899496185315940524095352093195890971L, + 42200218224318860824812897583916208482127750284199576543492190147676370417951L, + 64700565615105284242392888668153133511395198324059560256734863083190822363501L, + 59145319234225054834945074280096748257562105951751962357531680354887635001400L, + 109370459247823410861206598303258770585360943296040735774085402452631141651780L, + 99481385472715246129926858424348527055022021148459424355992992054695772159341L, + 106443499252933322798773565879555301129880638649751583766224653285758031752820L, + 48322095229054470062821743113612945636849765668600709958419576797966085161570L, + 33515809494782069567661160659390787788200157314799375723046535826284168620654L, + 41773109623016210625345820625587661213509285213374502863725211353920331959319L, + 32596302442968981956571340635208447066531220945981080109400249909883451742829L, + 50293273819739386025452529051468445849720809167855795456149610014885010486032L, + 6910633429019905036432475110661116328818994641038989881657155395188306704390L, + 36739677912617989818047420712503342474631017220638134413720724315512974000159L, + 3964263570883415651111729390801978904288959584848347710021696283687789159623L, + 76838244100886277189026448893466799361279981208788651739691518178972257722132L, + 92524917854272347189223844521544945952894951731953465698994423607211481407873L, + 1094849487752948258678172481737220834950670442465200017592137082345698226431L, + 3596236676932905175558069277075687614251277541835254759691559615596064312685L, + 56005578839865927004448053246743798933430710945010825095181046140154895131866L, + 1314127155138080693497666074353154060396713254293604808680984177855232304261L, + 36079022347925238197361912803669504456936416755264778056013696625210364374000L, + 79928239193218591378736729828916925283195818566702883627512029456337551009455L, + 87280873763535086276579332440354325979085979245763538853389996108825086763328L, + 79088598451415009995545325883504732536821464222073838688397002320856965960467L, + 29529206497868610658911692751520344135841581721873597197167956508451037256464L, + 68962738620795461680733506696324122017627315086893424184557692404464821111592L, + 93572497740197828471049179646299056635884123543357390488670201160087939843899L, + 109112927198443847769716053669067351023083576209487571197569706896608310925118L, + 78320138979699033593001420093104880827612562754837671875766294555309495104202L, + 95892698234673850732008345163508421145472860369307879265917900554439055906261L, + 52508743067911278204516869676571318573056040990507652640289868030751665490151L, + 56994997415220046511429900048521489214694637343423249626411942011111939288506L, + 71574140278649739406151462243925929626255276234777571372081177974273056292218L, + 57977933207626507502343730286904755443422417664609976290856101067259261389718L, + 30725858941570916315616848092815937606144309685272835634213112076952585877767L, + 110473526277817823493675607940407425195035436651994426913113113990131038771594L, + 105339752952469208380404795676091420067960822602777471440244189030880744525350L, + 60412306346911354225557884409801026607941275825059578233151896523412434667888L, + 64762896208805433524854274168206836106667758808610346128969223715455926942062L, + 114121970583461064873502887345233051121046760719381233728555193955719803766740L, + 22466369798521351869094158272110843558129416676735676800948475727909144865782L, + 1273143111631474652637353240638822545534481239484935749829192671246967606089L, + 39377944484720355113556279550540837896684650949388624339305746596010745626909L, + 63079304104722256955147865058876316182244124456443107773876720891861784821084L, + 33221257928046204557801831132902516455160914036846369006425441924291607025375L, + 80679899250014086830309864555340554281732747123983833428628620753799828044171L, + 5520825008571730037184139397180716999457189530901529770850492308003578875767L, + 59694340447804748768906699434149795298842348528160974268732147404640124393210L, + 452563556894037949847124302231763919722502556228150568682921788421243334751L, + 83854452012839253111626789157033805803261637170087741884414752071471826558651L, + 283272991722506593509965059184081095348010472560457003520196925295875056666L, + 59350272485483507974402333665923264559817712090262181583567887818422454308664L, + 16338840576891551738619490263301906938135318609839255904209395903360130014526L, + 46887472068834101766737497605695900287149077542777324401279045289085727998308L, + 27174317468173438847162307838360842277547238744619453235356053140862073414260L, + 112575472680252768107064569686641717727552530114258489447701964544612039691469L, + 43063725488321823412272058651233665663191029952662442943522280495342602080041L, + 90830677820996662813354986968787850850731704888547154385037797274293046703638L, + 70047206624525168690255326916881812569905906194673856593528183032623465434742L, + 71932800557222775253672430273153491950688623401220405561142140951028444404099L, + 3524882399256427360585197251246913676161052633148576017242006325063275126755L, + 84915443337732578818997000978842662417557339117578770822366157872988174094364L, + 102232608410210054811388604493718844283297081753473792064431359920776022339902L, + 11882496039470984872154583878418111610653426303980401438591456011459127971244L, + 27070654687706280950633862831653465867665464018299863662869902069164060373468L, + 59282461672939092456574734414184106943172040535313215840942116814265767233014L, + 39322449749557599925777702791134894551704245880064456282757223026426700817213L, + 84409894515543743365133360610171100432700100978076876962858654568459632558541L, + 70410397268065594155629455621579409449732600786692188366223472666803032234736L, + 86437295053666828368055440450007075213754895898533783771617866512671397744683L, + 86384600756600571727069592190350822580086961094261465255184942610917254056508L, + 4169531244596552262243178471088999423056390095652168598109446883464017011602L, + 86603605855539825936467660126213888629382588181317117671233455664505351619526L, + 25878096712841480688730079454202227773191841010361550139385684121332714629463L, + 99813837622569325637706593871916293083064808065063361750746121189938957277689L, + 14956623686382273272615490920074162785270993021184365086380120813298528059035L, + 93908520539656727693859962706714600909136420168083833827053820488142240463583L, + 83081019211385062731225376037722543708554737255330978950713306087481031283567L, + 36815584092143113621447019134638924615387138159781448150874431541732703251995L, + 27767427697076154124730046958859599439717449798059676397788989550469671949780L, + 53600549360476208788118667076969768573563511569083599363977385485736870317987L, + 40069546660661468479507161040144333240272420504696612481157064445735524256694L, + 64349920087048287004064232121909162159550862928450387719558872044596012144788L, + 25013984982049649107171523463463889703338165256520376243160360152675368481526L, + 56530789998533237811002520653364573824966959264503360163423839174743884244110L, + 89406926438927534192610084006478320830683811663693612304775430631620411804801L, + 55574766621966719960163780039456412444050688884284171043913720122255495107796L, + 33020279523875150194000155658408234335900802700471563888608219712097607743977L, + 39498198091413081719576717245537304877776071588314076270987466307013267227910L, + 70681075792817924907613405300595003622717961584972201658078688437473039265438L, + 48951085699919588601707434724938021996754135624356894480749596446244429933265L, + 46076452959520639654741492991168821701045167530336503508712707346240564741218L, + 8728181522716895277616722691463990661112351314732695827427219145365995323248L, + 19242851635027303632228665680918645839152069598195025604323474183363371673284L, + 25966598671941504091044550838540299535978523911690095545251052079003170032500L, + 71133170285960273109650294555239514035629927341569053089582833944222072014831L, + 30435235918882008095386416250838409184026844557375343024273010676275207110067L, + 104562805601059808628406233133505378432310209782968933305541489051827992880492L, + 91277304545170701366302646927851740938169501660880043983344902890228057721474L, + 72968288915422114488753941134393719877980024150813811771584482481396265125949L, + 50190389952851782334476549812324728201959717776585754131252432379408670884706L, + 53714686822709417243703749183305098173984141991560038668837805048340367561590L, + 13019991109569669604370656032243178191139406686858546771510153010511250838270L, + 67191821789817756119878795240970869267796221550236335817460044506254776968216L, + 89413994372950940556769387668380627891258272606614021693905340703246441021190L, + 3238798850498286807700621225209517329350934282288143100877405970636083894028L, + 40280480816202472888365258789002776543316182588753634995486654906107679474981L, + 100948637697121602892593946642196415807276046745009059316006093188332302195851L, + 59549093972846780800207597390208066964914903435241152123606789627760509502894L, + 56236214012501625186577071933242555430237150566129745066454391719068199835078L, + 15312458892596540523573781893452331775717723839950029000658676210347347105776L, + 15065967432271076782208794251450447638704140909495321523677229697077825888248L, + 81462686679992445078195460793727301193796564055826032266815725029072364753429L, + 31004446882658229570973377729390630349014033711496954983225868580115438114327L, + 60881893889918255607808992891845327895300679183604457662116021281288533703990L, + 97792511094095955002259897688952303128451022225469644595824040325459774067007L, + 85913628620745056720111254267901487607688940204230673170586457241362558878343L, + 93647134651574147110255208072279336751625499609376994365444326737671287302291L, + 95297138551582102493747902466790249344233763330665546307118323022618048561591L, + 108463575541952340309096840275345034615524455193912269881763882512567995129048L, + 63752885008263504388047741845098568103563297786649728967903987339414173639912L, + 51652681214709060534046883217927679865702663716840951262115852661229709210049L, + 25666020547072989328764514449251093742665833312099176399036564710247119178076L, + 105269705630708453158082837912213449941815841741276439302485601620747579775816L, + 65617932013055493829408883154321843518026745982706002591323727944029169432460L, + 94643632652344258820199676940750707745466458768098493560902616544464843965760L, + 49809197967029981470578121511861493072658984885955900534570018643169459879500L, + 102662538334700555252622216842908651775931234046909341778615018802143214957476L, + 113970501048318453425661260937695608103427766826948186238861232440963627235790L, + 97357434013974794220454749439782687637175698528098099543305920220485529874907L, + 103359508964986835222997521952836123858692215225816927552645056779369173307125L, + 104648991169616025859256185054957149293934618168732324711445261097281286483384L, + 29389896106165793254800955426429904448077276420102833967961101728159111496532L, + 17397917556551293611662477830858792324055081846212709299057150741059732651921L, + 50788640561521879066172340254498727900679747579755154172014511851379974458947L, + 43965205532676500510494796343253490918535053747950216680447581669069174426591L, + 100561339115325893421374415912582953869602487255513883614209616721298762293250L, + 66562569251191910581855009906754258851096490437585719106689692764515165118239L, + 67070916062081221710677371810255878781339891113828513253753023678578232819493L, + 52415447518906441393794278066188435528329456347676300491553094758338552659004L, + 17009851482897642242445115289124882968359106779691578713402357833717216053836L, + 61968470418522694182319110141621058714670097444452023370385834134761702338776L, + 27439043782857531293775514029155149364935936471052539789861552445308867719563L, + 30218119149287409542698267261174862353671414654735376656319890010900661088921L, + 83722683198541680548895201973968476637707037053891833391243959378912592800774L, + 19652496154790936363470942073050420903905231179229766615335909262494502477191L, + 23969602441427232334456125239419063180005947434249931440170057765321521250792L, + 90618151362150405843626387583735913551480244697966345084341144901688604590826L, + 27676891003614533451066859478651393460424961724309167669813674464058417433664L, + 48885749436680584753253699027466567472476019950871823824817684140175042353781L, + 13267791426425915825084467964002602513349413057053642731529682261674822047612L, + 100956069784946398219932550061775672758363289794138417517773642672184160729734L, + 40333404357937385101624655022577772019936956721874332897672372735097268448719L, + 112458551997636897766716155683532996884022983846949842366437224888526599748808L, + 23316998467946250104913668497817687100083031851500104547322812301787623570579L, + 114394200509243537380938016740401885361078260317260020773041307235661790091892L, + 99719653520966822770708772752147805183461502263709831815266009451647654614292L, + 80463081199638265711615126414788957383015583042168341270906917065212011993945L, + 50926914333690872697842264658756713296670371241774121393831877283526588419443L, + 100062544342282326069874559551624201016023530655383269001194311119868943621261L, + 68068020862521353358271257272528432308814754476130540913318084327101476116934L, + 89713823805042130782951935424222440168641332400199911482603719331288815293140L, + 86663612340636044221653557765291814987022783456558531881892865420940708049900L, + 97012438822187244992111487410059814894762267734855323936613215189062559355135L, + 115456008377472687851341171402794820555293289595636141868079756635653218048019L, + 81637305032596027004552048722644010360182923840044995348167774103369285666664L, + 97121760667459148346469656712964477195431899223427151445530984851020542596352L, + 6578517421505427291741521771648219090909965045148358527570559142102824534423L, + 23086743857819326290801520016575031684614920494950123918961905329612171231094L, + 23628162222808960592749692098872758091298189792059288171046583885877037641335L, + 101388589635381044996545324324358828419653240720043387756210449566569798752243L, + 19620842733350906207666446984047918346475081206033132332574377900120947277685L, + 58850961459606306328454345527935376781678482106551478360041198414567673137778L, + 43698525283886526392550172261457716557843922626739855384146946891975974274489L, + 33442616784854796480120127349523708269380041829170238927409871884711003926345L, + 31440958616586333198744531091618349581229397477920961786477030476125699377203L, + 44037228979451760962709036660497370545619138069963535388089488696166164155925L, + 23590773350114689007036710853590152873533078071389046302374175660283306490466L, + 18131169300372102223943835158584186528386930775158492999096691428947406557415L, + 39927655185828305299260927622503627720853145613611115731691007206417703553425L, + 11424009611604260676731914046838190987741247394671748550647759787863888855045L, + 106023534126028046641732471111988021743803815895465330462725283504186924886296L, + 68648138318007149508312965301811805457613385583647580389322272105745929897884L, + 35861285852404043153958153302267356973075068570728747603030615815307744210613L, + 106692958162079488264120234780830351073717987694440147487544240096771860117721L, + 35352165220882402184782264824036691776623462733023306250733408557343340031618L, + 14822282545311489372618874096495046863376384328360624764062544361258616982209L, + 90058495310599262422511117754339705110389948235968347407889592750909695010887L, + 21259014153908036079063449386092480951127340321580415067545014550208450347867L, + 49578982519822747108721142362544198831986643922392137320722032016810156482162L, + 65665457104798265380017369229106214332204544903481853344404382438501436156569L, + 46018977419201235627988083346481532946551841328607691952313437865601296427242L, + 113416128614229392197633061170738475687415527961785321345301343863175386165517L, + 72463005488702624466473135908636810035589105683486970959068404622715441569172L, + 59228871780580991287064899135413738163280222266776423016341942379142878232367L, + 101201352577621865867741734209721921320372326316364435635877898695764520096810L, + 66116563724113303807752208614578289149445196066311339830443507231280061604629L, + 13321204435294557952842567742569975996115680491875120393306454427480274484373L, + 36529495391678241787355855199218483020906667770134006834459752188063285439610L, + 35393105095199709649781810185938664796603926906726475046005623027995804964106L, + 113361361018964027876841710235293117483566240411336430409058248094509057834062L, + 56058022706730182635086646281026455259878455394424198569146889542596113129821L, + 66753929570993866861390801432055977675383761839911477726742625804552736120589L, + 74152311818771099103314467028135724751017489427625904392334704355210509580327L, + 31198424329271660749070167123360180921447024387653094853673347433987050304147L, + 22161946701832864123687613890591146417821146631382982059389586208424000204466L, + 94967039535410902433511564054776055297924708482731388778074270625836429181955L, + 101475833650921340211888028594926417400342939939712197963470191975265029710193L, + 79962135740629681563625093810301473611526352358650698543209321831966059946624L, + 56272682759487817327630201911621468568787831319876560851355108886611853690280L, + 16207947677319863057883738635880375181098797652544932176091223066346375051490L, + 12460144515649247367915525233698250971185931821776303597267414038731840286158L, + 51054786755897257128286507633905426324682484384053936277176197456512130390304L, + 10703878109914147630505465569165181194027864988338264878868171200825538401849L, + 115685353756232495339217522336126365180680521522774025001885108695820705688417L, + 83226966733874965537402061370252269001515863926279260739350326649028536299415L, + 77938744096446474082267536742558675453940850900461721849890994416621104090335L, + 10633870472986141781476912229206066131123339936733321854914824362473808144140L, + 113510575592024639046669896504932402330073924767594979636394504576918529901216L, + 28379840589037358195922115459139921091333875451323683305010087241069639779529L, + 68908866292479473675358078430426242309570647071553534729550787498549388810019L, + 85064447307132871909177013858601355916860955316576015102216104307635029791583L, + 77186435129631197486790630771123285886766192713169155391189231991556959095716L, + 60414018856458490333814081994581651087732522729798276054216916727420669351085L, + 15212960114472650545070192717970430908214794269081770422708773881411744953726L, + 91224252022784031862609153680374804011878245543758948021324002141712805960126L, + 32852025867914048360009115451838876000739199003298617884603266303681339764885L, + 90430620054982219798453934435971461264346611664955594662891046662935943479733L, + 13338386818121995340931685371910002793929630655642421076019735160380543781323L, + 40653500667926695898384831471872360638429317201349831757934492645361540497806L, + 67321568092347244312715622868186600495817055327877174732272932813970025865221L, + 70715000708627427291622464491836570367362782168418821476624235419363483259945L, + 84043980417318042435355782997773720153113022161240961471727136125668369238963L, + 29798594605740778420056358126875423873995928394755977101680155850123119250391L, + 64002739827413206738226844763112689896661441411156309137061786336417769703477L, + 3588603057028759016516615905510790682984328594608376145047909364187513464636L, + 3640113849242551147598436231961262195794557060841458006515147063563330050926L, + 1640132195779173611440482231813667282421653121121602402434590945825472442840L, + 49068472178525986111154992744775813894727777720616888679062692031878337421358L, + 96192283625043345803403853295797930138631783468065211663912714475454912223870L, + 6954971225007597775332578994474487107224665847376481897752901005026393306331L, + 97393736206168610177884752596730102881738900341429244953817508235326571383796L, + 94909591388534814899291820790552061136385772226849013926462603889535592881658L, + 97674360923933849538463126507677339914984305763250246342376050684551898242883L, + 32326926938638905804883899181301661258230876915152258405205012996608416781550L, + 75390581215090777419512899469184817486741500441160386876671097045280744103963L, + 28804629663351536283608294940890058716535755608630490430113412747955228667658L, + 60447958849385594887539070469446902724535183262968852417615873607098806913852L, + 8125208983647045861984897883686502701322221318693649876878694074186762628187L, + 36321868365872483629445089690287082140134307447167490214574356871622219403958L, + 57709458796817421581094858125640847564231293595234253030255350196483238510592L, + 91095279696055361262251522830528584660460437046515798029216072868459979120103L, + 44532164232708863754616743805204681846712941356107405206330557447816291011231L, + 82208417295733503059286375823323713635312814599695203151770014470900456987599L, + 53218356925724630008953848654076130625327239502715186839430988002470436174754L, + 103554102753645173083230160287208141011684313770251269836708493649081752862464L, + 72287395332613701308297970061776214857593209467851071250674303651221966830038L, + 112865201218690365602584250859438997853312303007342038664127484151947604421851L, + 41291838747727535371059951015751018368504265132868457130021365214694571571467L, + 92321496241942947597791657750257580964557018699552530794530263121140397570216L, + 37515108533270448750288663012299557149226500210493523635452776907623328856429L, + 37214105745309188663227709885588423990475595550200641028725694288049442381499L, + 66026046826623319583285558889237767047321089955197672372001047479175205896446L, + 86009085237117764324645317760115874450966674584814179702294705584255233604565L, + 33185045770056932059592647392427809676918726541992147755240707155667223682899L, + 46023623848314803736144086547851606591564509262002830448897260077561784218820L, + 42523124325040682188734262163872238263680769760068502922583738355277833409027L, + 43707136259254660167975670736625147170919263966206567519289343836142728631399L, + 21521825441002412494075821461882476872411719294243082231960424810761025191406L, + 48122500507820495999476353174639285803696600339217273502305348939825292700219L, + 49878520275844083983319755300791139094738827955932471155805551241054438329047L, + 2805019867980114693815396887224782179488381114608760082927920707778360709391L, + 105889067420694513962034831440622840599026391402123723795085189461218881974289L, + 102558012501655260354950544752269559998052103195524742467138368293898237029032L, + 16045802253454647592499420910737935432914631479977716060114384687065678301780L, + 80694383907286799753016956692597880457418319936546114189777042852889181009843L, + 45850888441967478025176403282980379370302486077816358544941791347388762431349L, + 9822479882591964996717128488720209197592583016104263091855355188495072624739L, + 41490103892755957014843857901396132258425254981457143869266365008399083279040L, + 34519981273367805712892296713884551032214931453997316756563875546090058443001L, + 2204281960270913078934060534754054590010912521750041700731012295673872332773L, + 92879205321717292296810987177742604902961904529684091274391960440163557121327L, + 41403519020039174258858740326538709320397612146458889978862506507151277422131L, + 111947766000272845386624725317499390083375963268740317913926980175304352248010L, + 44798112599245343572207281516281531139050763947036736697165944844889144497323L, + 102928340995534633866971381779815005780491954768232728403102468494951518351494L, + 66337378476294102778291887843438742910413779900212622781148464034568280254968L, + 56039934765763148611871383231487354654011870687696514609659661607478831015720L, + 7243934517681747968364197778847060066342821260703071558226452908378440385078L, + 43364489650928129730233785795919833617213540527726447567395441755408708398916L, + 16933912852581238794524291841725428888822250244726609065961340398924870949717L, + 54768614708066909525315386122663122276375311305049103019748441649763658994275L, + 84729924206104494740489514335112458905233956780655780501973210222476988806778L, + 29277322938893302888357826868792039003063313376342436323759513526491001984139L, + 33678771073152611527552742313583324855195425614537548275601462267609589426650L, + 40480447890208441323168952362583473949174442538879435603137691975180301383746L, + 65210427913223998114073591571054279597918449996368085666409957302627619255436L, + 111284762645559333229566598767525655137451767251557700547569492602611598002069L, + 50665611021509129153232399523138139121727712951188291590955745185443078240605L, + 86931224979232700964367085464905271967542987118370864162794587044708482189147L, + 92693707272386441235566687750404882227556963036584756954337957832491130977997L, + 70894179854964118329416027715184058487050172319260701857034205839242947658113L, + 20513835149287058783883311526714694783960711471827520770677981391121169168188L, + 37103649878375472784485755998128283116660545800082210023430808909026154302526L, + 74614844021522220679243984385072619161892523493843700560224775866754791981920L, + 97311144748272583637604206920752738211872018258123062151560689856785735825863L, + 97282949503352293360803097343846237726987612672755574861990237772557028505976L, + 59608183641235251570641614121211116914759763966651068525325858377448039839390L, + 41425581102453324286811424366295817652848042620102193704137772391802937357490L, + 91727177117026636081336266391338970810553560215502305083610747696747683685793L, + 68439194926538401577683867233319787531164608915005784342794051150521461201527L, + 26655576452391615777326024672685686800005203134710901209242934284945454570702L, + 31143473283240774865431214789334098152628855471357068527866219002194338185533L, + 43767943504780320684924240111007984914196536241705792566933468927031866775345L, + 11283889953365847458363049262619110738826915372417900452192942436343871320790L, + 974565422135080726870643057160743950307503695746121908539734697315502472220L, + 94062505243292442540029663203966839941224750263267455031867783142742670480440L, + 78569047934219441892890028502182108887887232992809410286724319457974676246343L, + 20570672053778381542185367122111196326110468346235368248193378711812323865668L, + 35891241806860952479960032306262991307022140205471781583482653582223995413261L, + 35151043765988565325231303273718710458180489642575355611039393162107912168489L, + 13516481613278628333357957526837653942837798816895627584645924375527859723467L, + 34469930884670250090266784851545679585931608749135259869539338790142549281813L, + 39226231188171088174526313909055943501898474232244682466949149864418497268943L, + 54615970833110299035691143075517066092024314562334728541220099178048293031173L, + 32112512508947520360789081302708296505473974754959805858145203408010165306517L, + 85823074697072165443604848224465370037251188633431788581582515681368854801201L, + 31114787763081247662741790576136049613765531079439068967943198919548089945587L, + 63717636094936942215167694521013396640695049671398758505544873002956659018795L, + 46914261527557896290966299653166097704478129043511948482391200512036428481288L, + 58923411056640153904729588987353811241292425582618364248734832424160839974386L, + 50179833858476307391456910536402872857772226397005827658938467543897282451575L, + 7399171788955838786742152597854977502050982099899715132733135899052117217545L, + 93872684832704986670149158334194509247022010222886860168702211704099201069352L, + 49687140203619698793673849263115576429481975552290236422892493685164901278792L, + 106273531460025463668310324173446244018738894282871539525215762780591291706155L, + 78923513349831944924537330470080754191114080083149247605929918579383623068456L, + 50243690472052874553737143971668585250777706389716966541123706593833557464197L, + 14928097276738110931661959936750002490113274595862260538156282115884646749788L, + 97636173389356917548748277423523694672226762969414452501536910222011959459104L, + 38744780619051080555509054290722104884136581161684592091596609542691541950131L, + 76305797460097674690462320779275684579026918868641674002970602312667876025735L, + 99319412254964041675502828069665819342149052987152987392086750651676744471964L, + 107366432170606397254180573522955903423026319357594955180473440028782517094811L, + 60344379454835700583625574565166971955283221980442020016988265483327836660340L, + 95273062361487489226108456769564185591569827803892488719352432327283707461867L, + 73877209629254278089333997149988436753355233586765712584450550875195469403371L, + 38331123804163560494485279204166810888417461933985250355314098023958239314736L, + 106556711876247251021682631221360850922372713031667061589770635089283360994173L, + 102890474760259854630170581840930262487721108245862113115575459773534870169628L, + 10877466614767430581872310973382352169813318491535129598341036958018579500908L, + 15132085524877042223936003242005723023770131695295306170112330353422335928637L, + 3408214602678813270177848587974025101499057941607729407576635677028440290643L, + 22831370693433669028556328612098143404459453567000719312466316131142036071459L, + 74211345545461458944362705130817924114329322029498646950905451251295568342426L, + 94895738810491560992102232998379123954726818134284590088519056362101447835763L, + 64506315879394373126856628745726235941054214495972234400483028618989952757987L, + 106930502633370520988542875453726404799932590091198881910056842282511120061402L, + 63059265553965330371504563689275766573397530656579610486037010959773696718956L, + 31512172698707291596500870726909806676259139754688878095971669931502804321283L, + 93031196312652451383813928381228909877151502052237064392916714826509373089585L, + 82724472015882148694886881638447653377563068883520170787685590352921926596050L, + 78121869861392699423387129877415553564692968777285986403673962560019302484340L, + 20258020069777856163090242646144629794277057648649514391298447286083285034755L, + 32973811953722044083062761445188979149444368409290717867611463700154466899554L, + 100967605565380205645936381274506567491641207181843358499345916305538920337268L, + 72390949360272585354558305064341289855739955365721481655730333617637799338135L, + 78596368190128155349530458347836368925860306679224721978650253671304172715997L, + 64558599892689557707415227444937142675646389328776207164588655540569754417692L, + 69890750668381984505944991731554411154122182634278802023177924155853842361584L, + 75213803206394369769719191236935557715315228259768150739077153503198332841035L, + 713865771311928611559082824635799123841148346944239416389783564059397504708L, + 4217795646636310578015247225747573138661168845810261717953458054214996036225L, + 14223818603976320398373336938059290367291506650169228998269707219657657502998L, + 44533811145809402876828177271382335586411109486962835140128777341409519124066L, + 56478819008987592389931597077140177544234702081912837289515448214765496735886L, + 41258256854642400777318742135929865726252276026583411020939043927579371704001L, + 32535465328823065094547672642752747105689591965757061603966987782796974127350L, + 23434894256690473532436335396098545716482453326684491095059454432435759938252L, + 4515178580927686433863854609466342253346350175973565061169476933553924807288L, + 65770803916636481644628148613372261887549160616947240346727958158444755593659L, + 114798502242093794221481920571539075400854081537219790402383806659924239244922L, + 103466805083180111290955563590402548161602269088414100675034153636453982865616L, + 66361002558103463011373871292547992240921236981981800156173849080633424047414L, + 90150266278052170098912652741812718604491081514435199062728898334011964228224L, + 36567956334608768029893876357995916604172470588123723310113672944970409924185L, + 46650860437157018357739959743023898085493491236908063185519299139520792639406L, + 113978114883605403381413308200143069475162868763769589424052527057919562649859L, + 14571193172626764868769895240295272901205374509807718235249232780047466971143L, + 111659244927862512621498176100521641413222297574328242618976729145778411664511L, + 82034860778342408421882094700961549400046231575887188360865160569029015368325L, + 10986581324857748680434572967584355674417783647660484243309314356294235419564L, + 92858537763245692873202265086076587568238962903876900745338895179532119508522L, + 18339610539274968865123664850767402285705195044427828900485970443286417207220L, + 13538034569168160542835032989304290525603956489730090399726793567665517412863L, + 87337008194997323770465815106329850019371469234027785444177768809208013119159L, + 112125623929639326154462925416473189479530717874389249773728934274872083539360L, + 61811828574222500034860293512459035118173463561779508177733222650147479627330L, + 70625019741896412319666161595692255408223851946053030491711034192625695311154L, + 31114107047925640925691588320620064382112493361732342885797955717132599150912L, + 70525362769848742843404668520081397515062752648420532788584164390189894512990L, + 108287759814593544590262575481791776872680324980407117552849781196331047384599L, + 85387852113504375586844599166186916406411052267265654527897135913950060156638L, + 40134198285988487818395286719554733436191219534549769841212811939461508995568L, + 69806395930233422010938395428540531695508125391128576669383501857429014956937L, + 44383692378809958030463149383028662193648870703734337280232496838471404247085L, + 37833558523062077358848765137334633785118860579595709545998045785130920980485L, + 3268293153421591881795839414598389483173330552458107165658729486103728565214L, + 77951073855122558364387084673085953939719040770257045049299878073346449873028L, + 76984991608538690954688115855190325839694754137431141187376382430106543868181L, + 93615355202516268803076921422310991177683947384769878854894366353714252044126L, + 60234877428817903309190508886460324009733004937113526208989019315210791944330L, + 33927171987103289784332757937408397612271411032618895616710265773785239274493L, + 62751586340416939520022904096477984413978099039576677831404761995575552315844L, + 79096845625634241486337000390213892498887026547983695606552343643993944205508L, + 56607277381466759972527220638522037041585786602990954025182664870898055166046L, + 105099214982421911456533751426434700095520255776676657271423129923536054520832L, + 29582307170920269245836667040710117212364910971553902349708895690518740962757L, + 51525428900100125428338361910656641381520344565592714922493084097344073408068L, + 73323090782644445487360500184647646874013297352287052267419439034447355313955L, + 42074869647782598060314873644565016035441665324811197181005830202139356631768L, + 49516601016421746490828567320796527574863065300399590108648952143654685296842L, + 101314357451866153975039589602508192430740189705116816076869220828467268315913L, + 88980923090328250648862355979591435016413649386480432455268529739504295345776L, + 15707128794614645030714351199307318033849401835667149765610375924999588869883L, + 77511917891799010985827235351236384467882281290686256570463416416104546138427L, + 27943387849678302292044484398402168990691301596538116310444055545884976771013L, + 19749168743340741306635090410006638912945188174485211732216568263415920341373L, + 110789801144406654444181504369931261651183190658803897486643694522318446568384L, + 111910951285111471303966439319667616844668129429657794435170356211919277579869L, + 64147784543118635414563383484030167666202507166484036570675270255297126165260L, + 99913572267196567877319742365398686938289096843502998402751838938328273984887L, + 61912678161667434462636754144422785653695352053266328100030124472361121727010L, + 12299820910982805096697839779225272595462474269921644240369174382745979084779L, + 80008737233047206717240240077776181123924502441138518168275632598548473290921L, + 6684578692884812110830772551575493594375150652729291190368776629426171995494L, + 80133188578788653578983640222626744956569177797805198417065918779464192766695L, + 57942453413835213225435448672981881534592741151757201589563305307336621432435L, + 87685211353117027234090822097140469947198214797865560071601838941294973153202L, + 7547796482819319598121012311536540374463683191931557261758758530851465076359L, + 54060890438191534474558742520648986937754275778265604066368599326973622569689L, + 78357711406267871216257348186633230496936120953321466832769258350299271104052L, + 72208899450897039911453923106460555945446631019167927879457798069485436071614L, + 86994295236717513157031581145699694598783814912966809088491089396659163682924L, + 97244105930727320030735077718524611223480015127922147743806741309675521879079L, + 46821515488587058205364014839711589321117284967092038043247007816710617728693L, + 82315402245454235277239179882713578934450718774877171286651269842515546478132L, + 55355121149793329341491568922859810743076027837495668746928753313320784028442L, + 42221834724290400485539396543033664771532182150925832325958854155795366523478L, + 87249997762767830341600338935741630869825543641091056050376516048003954742924L, + 58558417182931840799015706010437816068003141871832295684836511897319630625377L, + 90646689685247775188276308153618129893731239475659232289832005405515669988326L, + 63683910656135883846693664354006872928429289660323804927116553890410402744276L, + 73646744644242548749883175466483401844333446237506988919813083538330014578910L, + 85919627442938766454979481519476484600102963398676046674149532757672136761149L, + 64957081418575043979714297341612993135633790903778335261242655622165156332212L, + 29283238504458590433727764033703034539298186204430885648887030958624101078615L, + 50598790870845205532351724958280411560891250360617652734747758016988149198171L, + 10306946966828842793988543700100474093954288222334589458433870591473447195363L, + 93383782227644581114167680223172364202388922104372471669591829069905858397958L, + 82966873968832985802244497000030550194805538422317370276494899473213646851979L, + 4027642553970535969311123433477994982343525472269994271857098984287380720120L, + 64932250603442933539699423260361937248779103514954901344147579197676217756640L, + 63381364269661782217446841274244572801089064751400868471443219719117302379478L, + 89337765166828711465072824407846271739115759092046994775855761829607340698291L, + 37157897758371600825668509176880331562987468607783977443610366189220797974197L, + 41534934721634715930611008172599711544497734643155781372014343681790669364258L, + 112735375116638787844782315517638234687460168051981878310975790323286363026088L, + 44815892726968755143968284781276350856920407289787182546753769254711106115218L, + 73765220109154434663293010450222677595849326210282420822914450455411937218591L, + 19046147831205526962143235015097089305983840736658408039985872584514849628852L, + 31753560382955274777878729452469734519263341263905703152652424047617012910493L, + 56528025820440181696825070057657365283122302389065973072494098663897292594161L, + 41066471144730765134600137862832271630122062375243402496719925662898072198693L, + 108851329254976771349627232810962078381505305529587704183132855479691338712848L, + 45782657390386471176610468297528047836250202785736711627364068797589681138163L, + 13769034627836120844100658009617426562555329579887732814047250887775448863280L, + 91886422773794532801222091625683935487344783841540159553327484687000636325716L, + 70938338241174470130225413153663707473714753847467789419746515939387842634852L, + 5081470653650919697032287018044092084092842228152722277640491736952861518287L, + 87384224223795844281156267148828305127744906809784439076782484004066862869869L, + 83135611780027591027682274456558526274255537793123206046910850760235880941791L, + 26743961105136074430834051214103958003960563505905839817476457138423173675682L, + 22532030310824157473834189040749196884472319625276013760738464337151683132120L, + 9223359857298668416480913604076640217732278101804339064756632068747169056686L, + 43412394511915951857863635554194292193503187659320950873874888169969934606567L, + 19540647784236022954078780536334098246701450053639191959885522181851578280143L, + 71587401330535943733922874821763431990405754036794794138238438292733445233699L, + 103790307236613919508929772229700629005668617988873224466508371105117012562987L, + 89116229333069611662836452246834379761276878778773993046975813349301975642089L, + 60047475482079971862702861973547277445273443433938108001179616873639206191099L, + 105237746554462793613846056861019686105800551554072941029028992382625121556795L, + 108391064994861542098103057536170382703463232050039865861210830246886064642840L, + 110383719200324290778877899200827280537419832857090151213029275153174188328612L, + 56369802721495976759703590739732925453003019836218073381299943293726210959561L, + 67824664024071866060860723203033616624610241498079726646141225934231284489040L, + 45159812622314756489071056435012747197513643947726183348977174794660175401921L, + 29296954400904356672668069693952291315485556260607296282533960483836433979890L, + 76106615054094606689894451859423809759777243569958547825532072698676714040418L, + 5517992596372205135413284455502946396874073843593485016177731091209621874839L, + 9724201821967171817778477679164357954891718482431336993565761149726302114836L, + 45542554343757874556691080182439354069259169845263357645941920619074512124227L, + 79059911237787761355786142449084721324880577341618157694256750391350537062486L, + 115786316403345951187691814407840538704442194426719706382741211660595173475920L, + 105687268163191512547271109273471750962837412332239380776346295964553305976497L, + 641258152423358607374245087436094702887710998998879657218575138866179694170L, + 34918116761157411029029681750290380087959536589760031623593631605070011836982L, + 86733179478836654074634035858255743097571821664563540316458099385240257035481L, + 113086666043116430399253835601479039094312618322742825628481191177379738660202L, + 103301498851231514835967626096243756844549852791107967107923613754526980379538L, + 1651919439985859444491408709564730224223820746948125282880693118387650876117L, + 80269411800902188931573551003528315954909340244161255641481971716807067432738L, + 103187269017000460087939889423990743627681184005670557263265110388521169879892L, + 27385560509092500720395856130598082707942600977300912640432654141228655178445L, + 107652647931294956586290584221071654371666328241876406501118657506007254046943L, + 109383960812021608113740637890792861947378602118253651071418735979014605169061L, + 24473638831899701011565294289730402096556538818403721088526153883042840554535L, + 9846224173247720118208988355886449746221404346771257873203847593754202649381L, + 102662655145442873782814840517129831550928080840160897718839099050785781175135L, + 24769028559101252337658335936502954359630879554079148605126140767727901283670L, + 102821123227610042686764153690522375182677506827827832342000174379234062178744L, + 60538888992399585100188494834855797182490850730309328816036386231345644229215L, + 56747790988637790596587979176209917702739680389556019048562115837953952267398L, + 9224557252190335845864472186397193775037369708890663500594671214088086824396L, + 58089046639627170807553197583490632702317744454629453559915943786066251486257L, + 74949361634317882616197100154818029751641075065519686630245499728723502225663L, + 105545398481725748667686070344023456127053912307622115118349194570728151561119L, + 96294784607579792305326288940729254458275562685216135309295354370964466029600L, + 34328922589712547669094465607489877401482600620030853266258077636447981546356L, + 18110461155777227445374994029850716211448646774400881505953510470384215199053L, + 78537434946813056541168915993760737477882442677466379329177719239172423182692L, + 111106804033498663019660817034212500168436030590578934575114513900954089486870L, + 20543778763384287988255356980462999591217639906342191122936886104376666865277L, + 69979944623130434564811529245979905974313299607865406688863390911620650257910L, + 88614609534752528145316409849545368978458252813231050595082528618337797076735L, + 7995464870181106459552493232604981462677493629412316765483289847351235347265L, + 100192274241892552681190226484205380391922603818121665463215615979772537115864L, + 30847471440132562192014233925845021842448082053920988531492175687183917968074L, + 106009185612771953580724677639158743261086614185589474477921583095102317131789L, + 49735300414964737529491213716306437700529673700238380306699221823733303723174L, + 42296385484964299260902884207793819465227119884367106359772287942267145073536L, + 93593304161408139774523640635460792414857614919210610480868549384197419330447L, + 7307278256192250911523652383382664203801884378859697798524144209347411695562L, + 18934939823841293868681632502455986241698102383548884630270722263874880398705L, + 43283869834883514902972824061825697765239546801239960953793806213312596802825L, + 107888776586099030304117156182622666349074642635491167423219807486571909525778L, + 19948679973004498477207834586951113443324398857053845225583222119183232046870L, + 50305572885024780377252640298448269964041958825899848189464836005752312581326L, + 17957692981886673636454232993276843374119256753359106269322222189831856113863L, + 111422691829901377404737395845927346210827807226636799443579882624708609365647L, + 35057558979908802301149297993008625690553232451739489974030332712652372942428L, + 8271418085423819013964698074529169854775001702800643323022906177424203703083L, + 95776783826327761194533189686403822667566952732273808389244803324783559110250L, + 55822732767027188710611079562737037991442760661059919562757495979770070666144L, + 103614045145995991890236468704385440365125497675629655757612419615576150527791L, + 87513741783132396068713089588620948980723488867680227376787276852526192933443L, + 55552929424659084882785912106713339977120404300237157542683068762661378293553L, + 84664683864569336797064920623351348778513486903342749721000288115697128471386L, + 104361585239922573268411896468856061370967679820339291656804345380123294060172L, + 46822832815505211740572070976737690066327407879609766293770252440181868527692L, + 88470610429889848909371987571202519929606149566353623979633232649819391839491L, + 21217767838674031593209000030922624021864035273440757623029183032373951859918L, + 39042335512346489471717361398437756204636323437411437537189789423683761561710L, + 86442774758568312656401659509053290041123867274913356674473628038417414829493L, + 113806448666308018747966264668211386340372262071098026619512205348392151088141L, + 45153806677195857979510903836363840677463048472110015455406459480723140223725L, + 97334203216670484425268039816716055393857356067821621681894285069289537669509L, + 67193255267112054349760010507498744752198692106570527636339214097464687827537L, + 81185334980593365913398292815226546600884118367183289558160087849132791424244L, + 12921122705733458236412898300226456271149442787043645595882704362635257990521L, + 110055998335300512236087341926352379950960601501991014010099184622406481793585L, + 77139483211748002386028346276011723994405859115530932359608253990088367613167L, + 865625561970301391434196309728509123451610413634540227535321268004076433672L, + 108754612635541080639882990556158702758706205788981100657043890206061298924142L, + 86496620785020440462916059088633665849539823972244049253964132681259815145822L, + 73752785340032369597592046414242059481288944280197119431162690355293187577921L, + 76333812509898319452265571776088275942948075256656811503062171691465792579689L, + 18845650409398669124009722455618374943009112428972476564130209535570391768764L, + 43511659326057468625602972503578453064018125560338912679073995154067283138008L, + 64270851568812346119372921352206304177423772039374360571692446205558560424316L, + 48189501702687951961851261342991672185479431528996475565083904793743302483895L, + 51652448170417401985758269959496462088808587633362570683411562516282339723663L, + 86183630114394770772835958503974162466656890874954444443342810473800261348359L, + 98585705806522812032842297868214539650203262095642521648895956808352467765267L, + 59410890204389510036140216042252448504493477335011524938179497971199717305547L, + 79692516469537176955017944775787893146924076162153293307063191658453502741472L, + 12432710324347237284896617988789981712783547199850940338980122961502346647L, + 49592934995857332651759267474856443132519544418352754847288367996356656691937L, + 63468479982956839729212721587679969020632022261218715793449791969059912616587L, + 79726775435156236958035748237207339224635083220013141836013794482812664174893L, + 97439345351107479101311900679824742011570195518527030936093022736134075877223L, + 61439533978052825633404164344305939269052214769581290601237619818703134422539L, + 65925646375200235135034156136282711234867299866000891109079493439328470795047L, + 92647022735627851948294852752752098294773762350452912414771473196540818369499L, + 53400774345197286237183566296721826734794479119161252505898756075092325583570L, + 18549628192384656385867793408043562242534554119928007805043907299301292851757L, + 45924414799022304950097724824274324379367943084065939452653667451362043712158L, + 110368172458658774534367668868855149355835365633017730507261220602074136357580L, + 55356767012696396487888840708634740714627097581716711294537656522453810654192L, + 83416396599254060146049838691316246058574249801635121553905647193061068866458L, + 110441512115054554323328435082029553243998576227583907858301500757366120475425L, + 5164266238799687044525084398880093204493750009620562934380079626078590439263L, + 62112452133361441117532405096833208471426063825484850899602116494310825198459L, + 52389563076184118231866178069377019525451392209944527621243747405999119881158L, + 77471837700672776462143670534678094168615286917735022997553045888835689474044L, + 97248062251206783328422303190498256046114164902336901334927638079052337150453L, + 44557364878670238484551439989433283624658758938335690573618524717659008860008L, + 22845430661687852453692201570370974035118060832596493006725109692601228195123L, + 101774671819854099857301702937453537028276907591416223309013262298077545882301L, + 115424369238578734392390181363816162554914372861226537640100957340983063792061L, + 65338990673211792003751730933129632843822135869185645371725904873020174573629L, + 114366266324461572987645959226855826836558496449355152538893794925039413357908L, + 38290463890585456589610194511923849736640531333686863956945526584298699155634L, + 7104380315235996039834757743773937751945660895522076520018612543110852786459L, + 34063076360765794300903320551561479083798148054160557055090751714448348977580L, + 88515727367536907576580039700060644168096251873610359912666009463379104930336L, + 85688099884478097401412463010714767804521859141166118376027704285006781806478L, + 14445723047504895678503624598372731567242295091642621226825454965131390083795L, + 105307177643870861376704975142705763093068186022149591472400706068356332439472L, + 12181198007331198915733875662579743177739833828445541594284924339103615308304L, + 62933037901514195978439869420541917885790480592974041452836435712764159078101L, + 52555289574484375459494295200716138077661544231852518075468094221843139579759L, + 86408859083267213849608593421889984462632203882937681896919607104631355327432L, + 70051205085977014123218344822140748695927537067367675872085026215066718894743L, + 50797171048465065012378418419172514464250671715708065222018882517586360384952L, + 1874317888706801165225424155060739439373484623144774569528888912338861648442L, + 38874893955970871201241959699801474013365631094709837269682371327988779676411L, + 104322546406750040921614923005640070242124422454480957460434283544970707542352L, + 23147399194890360754983100314529471966962125675439669012987512541660909601887L, + 113716952306498842347322645003014352390572038776176836124593516338466562712247L, + 36491396924188980583576281527414767595941752681245588892480488446261854718575L, + 38216976432626963996039883979812057589159795992093245757044926702099226967348L, + 85587142213637727516383870845271383623475010977583594130085419463009564864338L, + 35533148518664300451429836377972871634877828724353146250247780775257353422007L, + 113707210930207064201021028732858411605515726532230715404906758865563077234074L, + 75824923843135090956145055465695508337185470645181390611498070674519003917260L, + 517810143330059297111726991869775122342471182773654878085285132699610899L, + 50861474394015924342453430596667275885104852995589344919703556856402567899764L, + 49128412736542266992374724288983384107547040346367154413952434327740311640374L, + 47543645103034546966956344310497478320796706577135425732862193708438183083055L, + 104362722607070431239825878525881711307409736427324214678751128935605816076393L, + 80901019799692946784836164248044967464623235366342139951562029269656667432776L, + 110624134448533690643403812634937132348892276454673187051666134504903397472437L, + 11332041837814640069950573118531582178208987766303950473353104817780737513431L, + 114511557839319259473147664196208197224825143530034423580198024049395329172086L, + 24477487820919013861878492454371985336148887712503686787747853806123463883383L, + 74040016346037455510908086012289778987837758722229815721408903133181977325126L, + 96749297847359416454833866356682485133755505677563601198251552625663438440432L, + 105430261721149398447580765021122166604918996215042858470481616269905803048056L, + 79791601172505672167793297591283334154149075873735960889429812469226954026924L, + 105202723479492288927374257344836310443937408752137121233450227157560518344862L, + 55234807745596018650242903018904912018598184333302650803122102037867969201617L, + 56423886371978150980154069718343902250360154531587393738217763986684950825660L, + 88632533967648931361876213430954972474334291020155125072956484147361066869548L, + 41540602080447885068364895020121589125387302152191845916811236111088863892018L, + 95866258397646314612666598700519648912023398181779402139994107785390987444312L, + 27628687861999017469863173929132991859361239157743671136807907482842484525757L, + 22955560086190754038224423146795686308407664057168960419442490764595085154106L, + 65789816766575105386987428306722263967996208491478635414490253295806677267237L, + 82684435593876653391617483275086404180129265328752928074553653452882266716384L, + 72237491753010540389666548672706287377763382539591172617435007730770942255029L, + 91236125982365567095084044215283415421174038922356284420876986552831895925029L, + 38797497641204948824685934977074563130952656775734483696648184436815878338395L, + 29450032252377291876076927760824111963477380682854888797165017462555096944777L, + 56730302001559397227949378973374467269278644362656612891556529840301717911829L, + 98242189100315465844672884345381556806359119306380506851927541428933452924066L, + 28677972722989033022627551059078009839201978571186307987703270591903667393859L, + 99738128485488861889095050115251628549635211973689063501970159747511621921740L, + 30997311945733736603873632098585356219772217871223883018619638323654487757602L, + 28224354554309048810328838069554720792169684263283916760516197294490610224088L, + 85124825409286476718381863601395474198658538100703311299861597204493450641541L, + 33495241866568199932364800498179948306100803665579334596416761183215430930567L, + 93748165502429540390752326809177733395625010372302844333039023440166033586473L, + 55324812000863319402611450577106072802300534535282967325048243381567366931526L, + 80357114434371146887628065499243008165063530763945754592622384417840027467965L, + 107865294290004154300446549420262135970395626999303173983646891465019259411900L, + 5508815310611955958841554110831533001923895400754839050062910862461100459301L, + 110628211683082298216277468869689191392002603451165823050580500240786687598409L, + 55985642162590842695604595049296570925761414222698667870879574427317007197666L, + 97764919624729977852728415456251595728184019866527129367997851555640066937264L, + 74643707599685076167689738607577307206746099799250672992619750183209913242853L, + 49133405248477455105183361148964553976430211270825632762949204776004710322794L, + 37230040854747304562375397764365441637954424575214865336492538924135663966611L, + 63747437736511981100055958734032121409103137779784520500023115828550548157803L, + 92465863715828612410373874850044721058409898660141083488253065869311301451090L, + 6351072607009588886312852820229505037726353682229809706757173440945171422619L, + 9838929347538877170506725037253611521513180438396714957522150626475756420461L, + 99204566522761543817262712571166152669532726633519888841909895085964712336655L, + 69918315505074486879510735964313251337723667425098772438138374615816323649757L, + 22681711155652187343546055126161350570283330104128570540811080279694440822143L, + 21750456202431669808487018168451361794307926238637912778044917235186332446479L, + 30519570078854889369012242379857888860540880339074771627807263792784619013620L, + 20376068409590712757607835967606049587305403398114621126642144077359498527634L, + 57816154972820637842015295227302274063569924591337076444074648595872211158951L, + 95691029341486059200249030288647234422421749471197931071422339405240735862309L, + 11519542049335586856333108489270183185166357336465460680941349039750739928735L, + 22783439924801660726284099891229570248136801431901846601891271372699792905284L, + 70729988904710801782067722428323428729842006762136396716832906516070438688711L, + 768552533597076344166841212199031455655598934592602393555086804800112774869L, + 98831924163537997575724098258335467593562129475748349635164470060889590458882L, + 37382848764098449827367408283658574687701088781678841348230180499498878655729L, + 53826850050413005822237153286307533863893346772982720285374142965133922653879L, + 25951810197328049743686791099294062865971179361142244965197955644658101600157L, + 95474384724371876447009575826440626126046120241573648796622832772631585264496L, + 70476826338218251611930664176436683399501082487873755494166711051527638761783L, + 76923865001237318302242629280930995101767102325750980390341316214129992580813L, + 40956221428999184253153145344417098366615680167022358702893001610164574343901L, + 91258443117772646022741710991832326954876277981466384820051070056034422875382L, + 2480557044803086659730155829638171859667302394336109731251787909625140565271L, + 61639252942303938393953410722684371324573405948544383860756787815149743841457L, + 98914761414072197737759435974083305544825672459974434243172911974632891210585L, + 29288287586124734903823974425198481871396075964331854237020621667490857027993L, + 81096783908540223370427893690448374939257060429500261220346276552248672456700L, + 74747676270852284893146081460311377544280534136250755452302483452475496380216L, + 63033053896061914085783155702720696714750947306037038383801589545505815881432L, + 94880829835360619082014919456168353457187296887555045263008281138204580283367L, + 86243603393894632034932094738373100868235939788410709773198835748922138060758L, + 67131877324481198083331599258988391019642445909308522741466882560005818253968L, + 102683920792339364282974702901715431944837387943507388228071841895827490267651L, + 67912889912992465913671388521556367869860832024272229385213244739156885723035L, + 110551344711509013940497589490244356994772645505463674067940200925529505761908L, + 104422433462351861857430424561648719344140239925429049064348391098425777060514L, + 100603579863145210162568134411179495346102952400578060579232432345328678086454L, + 17710591727487898159028074633066319868136748315666602801147712313056885200186L, + 53732990047516765000084978562862022705259609372298873348902438890119898623374L, + 16063942819871515158604960419497507463530060358628017675103659556150568988243L, + 13585242300922194490912783518156384483056462406554099581421313205860094128821L, + 76994709296314604651310848255466212541642242689150752484555866697766091663044L, + 33296060443744609438007182562715573632713908461562972975440130123920242597757L, + 29823994004951149189184908981344484820146203926650734339978490701532207194556L, + 103776639447780865799844373251019648483604076101633302998164136777107089845724L, + 27990243782682546566545330419534660325166080888765328331520724576716550919124L, + 113681986404859899855489671628136330088521242944577866066930355758292916513082L, + 45480499601746912260141581373860143599455659573335060265126978654014754221255L, + 17167575884693203444847451450046828526150267046959529487681959810698891407385L, + 17232940152909869508566737574957302716450723866625646764381462079454170596871L, + 24214206196439198683369378114670659640997897837434151686387225792702458393845L, + 55183796882852678728455807147620724129591397410719508810015917859305209452709L, + 92370933471589006522196319239737831765721169148478103724946044654059765601417L, + 17522830276676507022127809210712926924538214418291549746406033322309804857129L, + 87667408077498737584593526761134529744998243816543685429013918180276747535564L, + 35876311000604112586101254886917742346936145381127393394295529620071642297812L, + 64014796749105076572734082259912640230298578835394516523304221995273728541304L, + 109135151229310736573817700892379334871732763504302882245459230784275778553575L, + 16595347687222128839702418478080362109719600628112118618015869217388018348883L, + 27921579396834813549066464299860827161466322958768833372792240664949404130922L, + 35216545495698359652086372205977503250042279321493167643258328475141020214977L, + 77117275761337491903648618157611979840190321352254166350918569716805510962886L, + 3512462062819212238377009967268608332372746022904412658531847429663264146953L, + 213044529585981392974692935043822025246812794554747287575324449148243168071L, + 90614765757064420969737750920642735373288480403571675818369451509266111313712L, + 43010469421403140310031850131592004520255679316973656230812272291852743048436L, + 17874078946148102948854789032214343103123833912541908620511389535466184704924L, + 76374819091154956586181248706405676913767641045061029782061788515868087538531L, + 91564172717501273329995063951618906528857595075266378905429418245106395050386L, + 58789505790452834130580711788253867271536111224105841840343521525916385542461L, + 94823773647415317483248568929403137504875117257673993971772751795386631246368L, + 31071978519068803513374467918831947899554357997409504867413818015530559683839L, + 109592819189390091395615159423891840082650968805821245525286882876892630923722L, + 80616066711957337978951763597092204520874538220618039320146978247698657786081L, + 64203516468165822104466698698828118320320864571064924456056450888616400337511L, + 103067832985679360302134342271731680480045309368319718638093837086698631245958L, + 30994341470584926691685619262200638787457244500478165297574371511860341551214L, + 43059466595763778882700729036090686919073527598798723058851954243437716781460L, + 1693610051920013413013260181546765312124540120437967991917459665994774806656L, + 29747748984588778023562256318712123283140459273364657199320201305598273808458L, + 2226019244043447714854361308099740688341176962586376492892706683593154499175L, + 111825037103273707978537161414761443953313270130816743531156536888415537666187L, + 57012205858056204387551272724902421605062503962555598394289313492857917886835L, + 73396140276984806244229093480477275338765263475608983452937019244211554654915L, + 52185746418253605003953484521693480852645094839324127943959781713020251566259L, + 50505675019443410862922296532230977928239665449385358680361802744120140462921L, + 103527676053816135570616835980879956268458289266085079078826558654717425055498L, + 37617128485103969063185558784266247787128354307686582970131100302629254527846L, + 3949720678750428446742361510648883442144623585510859201354543637462177325467L, + 8377131978218315616004054453094037374246718190084282403194726043647197331954L, + 98499196443008033569836737659884708297867418596615891296810167773834208174281L, + 42121509521270915625563632437621319638187814758192852640255865671287440139483L, + 54521620577162531111131330281903686807795468830466555651310259043543872094360L, + 66064747392912446974895440619261318611730429489615281970747108278167294355782L, + 15861793885995247826508971849873138627436785517062019866020823181933822773077L, + 50417649252747305086029996312270159725838959845251999690819139767623694163939L, + 60967184333674743131822441242997898492742767225047179691417061973722239944947L, + 73565820995570455127474583774784016066992595310121051611101407971504048052224L, + 47717427458146179166467332999539387013301359408189577401273175767693692453323L, + 35573979916120244358355161246610600681290513341867535117841606123840359214158L, + 55465053138138231865871429602166148592952938948327069774639169783483929311911L, + 89922242028593373850468806452435133814895318351027088363939566549861423260982L, + 7260051358784579178211291605910298603242692991248241261024859891086923720596L, + 50317517160556980163700750490597405064413342021023424187016993522719004120455L, + 87371270432617946363711807507156078446234415221813830125207964609863093118621L, + 27000773119819018574170640928922861914753074552580644933183545957332034747811L, + 42744032928437813310951510403245788701064218473001042858648361006941304001965L, + 76198115222883112855784539112917622084905060815328285716682730794880576768334L, + 114932917350143510828430027883300271265708086718065058264252705465767116470282L, + 9610974877671120553866505474605601682004052160358709919274483117463311190651L, + 92474887406473624527438845790946877750741294442993385940737555271563845356352L, + 95819697123437827240587022445477470694580782453486472141994789896836183073008L, + 82576926300800526546816921752229648351862505582178910495285630906170828895289L, + 36331361540866341658048510064579643468711158646220392124923553254704291134611L, + 46706376926626599549529540821623039003107481030515487331363332254949059300295L, + 24353324713995083211377472060712587339255670962552600293093997177370010283872L, + 17744557414274810664273678005082172557385527892208091029498867778266373488849L, + 56066104524526790445623264175822473453166467950159100460795504735296451738899L, + 40071689527430667542335410521584503230790415282110381507426618602815016600595L, + 97068851296966062329360158937101699476338603966675190512721689359550742961475L, + 13969867861865221931999418683636285972452065394091786729793578646408460767223L, + 13402549437974009817308837850617256407627963323533150555689533553100160454642L, + 23169130976851413575920663428801683336183202112522615818530455538814681264920L, + 73126837115915344741919698095460455134836574049715878677508376002500599470046L, + 51710669535427444724897929166023883778940757809780776797890510762630448624310L, + 65459597945614518793759359804869521417840631665365659577536148549160988012759L, + 99536540797642825729053298966404765630223414089769399041907943006297494502254L, + 7231784615563341371222177706031919697765617500669178646820618965091525245269L, + 64122892575584255333550310043295962304217347702067254836758984377389312146209L, + 69248968822867743402900338268396936215300699222302567510938706021051626135289L, + 64459909137581310426551257040551710383071141138993080363067287522213927798621L, + 14742948626675895933533391365441723565532113660732414550931873522030034019512L, + 101026147667033095088031322524669123897108657000068395582372759819856524166100L, + 97132283027374971785455860106820479123230279733803926192840002003879833286015L, + 48174593663265457342497520933640892306528134783146005057970749272631234283734L, + 74551484614022999820896938159235147290009705262572638175995362448915115498394L, + 81601548335524309052698158698589563941353346599566891312827725647743560184478L, + 73116932619185543409919325389077397889594304746432961767623869175317287185372L, + 78451402876589854041503318631172224868580679846789904044103380578733159665917L, + 25278739790620556963219300167564212870292271442363451960486351820583837139810L, + 54024414835705416394037079934860587885462867299076814905051498941170825925535L, + 12709638555468534409074810722501233896922211667428202064180614948548059924987L, + 109281347151792376395175929897929142137597742009438761488009676534981761856468L, + 16470158444709895683826130913545011787920959743525928742480188668207944219469L, + 33406377458500154516670820483669335835293085173957908437058831034560493583766L, + 70651281087265592816851172939542041804024378961122348021431916454524247790489L, + 15011995722660902024441911053627059714343883973195603000940078283702110970661L, + 60427227238830697144277240793209456816279000880530019187076244777817884523535L, + 73198894917046063685454861451165348985337783045276609752624079662516919395132L, + 52648112848562399965004618163424195062430864847411322395474185938980291731L, + 46952045577128128984196543819547138980588172892696841047616483711048800831812L, + 38909633917723662403734030142535327200838258593674509362814721541421705653523L, + 36951437270215461622576063193731153491767942719073115216210481817146240857984L, + 92822503191844212655463849745092161447288970592157336557684564917523937215336L, + 84480307232364796251559974103849511575079628779655490273875109276765190178723L, + 106057656691067284889710670931617111774869892493222578009285738015216104199486L, + 50285055439186252264142373037616465668991452296519079373148506341919008268750L, + 78003171201677677069703279513949889987108271075069361566266810859043252937983L, + 64453673133771094732624316824642625674863019043565952757271988552769922400941L, + 29805577196918899769094433216516624649076210170142890295156230438586048629104L, + 50610652056964241897013258015357131289798599874450894042464476448686702359961L, + 10024375724653269362076861050490688019867324376431134908728274873640299983107L, + 20099480645892697329859357230912484796162440474084031441826835523655027693529L, + 100792873803969996263214820952884165824106259429335511491915347262961892880508L, + 86443050097462445856293470117100998266448796130220785484639349760511085234485L, + 62493564312100186064427427417117666594707205791525662548029251711951566036866L, + 60815635553906897843786462875595869090330869400668845634096204596758855111587L, + 54281424165775245149047042922146082135949549572932079829465992045937393672669L, + 74021344817398757290513151277223087668710121503273636682391094231782749770700L, + 16222693587880103215091267709100201935033204551967066566340174152337034953321L, + 64854495973466647368119047189801005714647298965547779804728922234754460334115L, + 66156422490209642024390094889796380116453699147039750930384800064026934138365L, + 59162561901138024440671086229264803242477291850185999106080419650007825378512L, + 113428284036516428934053001628874526792165406098429275385198763774522401427944L, + 111140673486972944751467248651865505957171579227015974964548148491340094995994L, + 90432726771831661687839542256693210493875909818720677153929560601908121383500L, + 2390919648734978074097981145050547615724582463369080238376044032599650107614L, + 49332193518446776132944417804065758531799919519408365833179026382028719983520L, + 16844021875070676344672196613674464028860686904528695438809665425388692369173L, + 22208903991552428459206403129446096484807223815807553864934395942832909219895L, + 8470667490115807139655695206731499698365090407835540156609649204316736630681L, + 29607486220536299908185616788433675853306188898233656208864422976785534500767L, + 55118842515725647019019878765585413332594787746027915581881910388738408646424L, + 31910033873055731616439342645926302105855563249650949524593687360947729789548L, + 15249004806671842399815833602781130699951102693998767469481749653230294593874L, + 85097158794392283171134330003436945020524999931707164209325774911384422465861L, + 92337636780391123093193065736517181950044874147359453864596941896834587479688L, + 81770882671219571269201880802795916873693733809261256550764580716448072120657L, + 109583447871166176511030634751251665357804926356882348916566457471791219148698L, + 33041073929036620922360347074319390103534684016051600747456031455430385017729L, + 108424534147165186079145303073847199616635687885160726047462790685870976681748L, + 65466602632971100068355288774598280106426058641124876268394001659223836069645L, + 107641753986594632525502111115099769636983568416823019234524819230100469522603L, + 92547027142788556353581494504297445272586237217296313499446131893737076379384L, + 69541455046268708819437791119267330009898994511210767829863401709512584810458L, + 20683825595930889143744204778164811636370929774430171382638817741714146646945L, + 68959317146250332731579840421564642471623237343260120632739135572400765771872L, + 75136672680989279656751656653469346757264616237780764363366620630149278561860L, + 65274157817701127289444792569660195555080921351115383684189138252807150175533L, + 5671810715501868418714897235974689704610658721161649160921276576457817696398L, + 32568801760929610669780246928825630234306103465559662342639770719943071342978L, + 31899447127694546827922655815214626986764525342903626632184418123093532656512L, + 63003141567059498680563562093390845575545068586635328388915837737844428759540L, + 70087956425710666655344186549677283948431739775064934115249294220789854801496L, + 96881713732723589740390122209289842484955185396098544778614220722895740850551L, + 89237512955632773061271413557901783236118038302561303247107569459787144818073L, + 112118405390625361521548464552534195496997945375550852266100803525541201727785L, + 33904857415053067229197139510264516938417331929376843105857293570196041520971L, + 48522847509609438313128709265627345451710945368961593399628287664898038164824L, + 91056620479732242278474722192940264910288151744095649278941504581401540449953L, + 42454405296693924745760817549955507790390623134504450887729884356981838532961L, + 35030768339325008940202682440941830086788807713862271459455227060337963697143L, + 76921540239373072453559061952320735174206639807330899944744976047937876699873L, + 87313302559766459446612529641999212574650068965120597614758044727899601126563L, + 85948403720638571645843862057038267931439810108286533704380282114389769690937L, + 102712334707504592210422830464242789803304045340009355833863840935355054281233L, + 94470218809718120080570248674808928917664121326980896607385772596791210451951L, + 96714874093759650815767707274474804647436412655194229889130027830810105566348L, + 90560653385295469951283340686561937543329860648565143016813141347608348309770L, + 97278756244816945769091623157631764025785549528861744690219325787907757258583L, + 12787384876026770751311821152285407097958609676209647525714649917996657137791L, + 111365386353352057081142976967121545231460934814610163846838785509473478412523L, + 15855654177408095839420876568842174725956725477718681446815705857360133039548L, + 13613067531464775022897443935245026219078965310211939257939155377034750399483L, + 53599180093597527139803296608347730592900213586810074862762070055923081925887L, + 109874297062501167725957708311475864732403598441326553362751272707261568662384L, + 62026410132917555004142622013490428434559262880726789688913922211434254293678L, + 69990878268615015540850257545647020092925950033932397468539774269767930535788L, + 46148111074747174985444160627533010103111238143005508215961769040553351778998L, + 23993026969283007462891903025371029530657636041776082074957040840681347062672L, + 62723723611957826574595272650561099300243361574943730452358922191121111061674L, + 76340649745758155554625149618785305464754542824525250122399731297158354264663L, + 15837561555738656065767725180400482404681801919913975045773939318745845984263L, + 105119521829476483933530638019437870029370019711702822008898832331289067484392L, + 7291749539674147019747062201586411084842572291128907423952995408405892100963L, + 65013291183221361739104571406600258574431018032115683832998746110848663431012L, + 74416822669806249454905354579497934095659080083745742323521762825978234983069L, + 70217915801415324814036558083191157011253178132273839677239217929046681111383L, + 52822571979686773549263007153634661328724765101960886598181125802824843744692L, + 85084540761085038167328810682153785502187359953023443483659246715433874377435L, + 17919493739690550119173011906396520738790100449060828636904189737675067753013L, + 8753055507807332329092024422759223028946116610837360212572206564324859497192L, + 101442777402520754988049398976065637522779631216807807980617705038535932675933L, + 93613042346895423070777734295453195501234828548390083832828585777394921975624L, + 115679083135995843528428655785554265543348465123557615743425866085657195630772L, + 85006051186273983656712317133303577235830200124189978238717084236218090367799L, + 34333573637219205118420094443995074034493561802092461779027403313373099601691L, + 35189022959577001573805734144369663325019195000227392065871711185529124943225L, + 32689872839747969623098377119527495462616398137669607462373350312515229991731L, + 103745258912467430098305432326720007810839825724431256975721435465827854704696L, + 111225344560598664648051279891010744012128492170821826558713137813157281434239L, + 3466886922840330421443444212104214765524780073349638551662327285414226854534L, + 7946315494471381810555577128618511422384327737049853483679549354788468130213L, + 3076724494501994539266352909036638114646061933241823745589772797079417802097L, + 80201445786202863305009838285176241856966733784843008991995734719279416808953L, + 8112902368594797931221819200919292221021772941918237295784918701063234565200L, + 15011316795691089479720529488623729771501984477270295019597053341404102052683L, + 14531308717016851912522270687986348621938782352029325259261451363753331798064L, + 14475543381502739866650612835155797140849324779223382420456476543541914007157L, + 34250879873249948376780103739612546234429458040921383053109198787687516563242L, + 21132301512997263058260097006372649706666831671215239991570848647957174616799L, + 77966727789626456653703890909082745388036860307486696786258643979395477862903L, + 48348599032496065689789046447495164129294029601311550101881502246726053044881L, + 30591585628473853387107376937243281713490713265803514876892851595162308216107L, + 71738225032601406785775004217101075055854433856894013548057305624203466443543L, + 27217229884517976935899785988505853584828688257347597962188032829364968170938L, + 44756840659025885296126961117384530731317800298202182960176805351569228854286L, + 38668580781907195245542626308359941894176998299710914697165283563516778207207L, + 43693964395969386392964155926684449859875865222048362674249498822011082820656L, + 80461938315975545512173828261970891228241326895564251202546405808916150483297L, + 45432269566872848767641908318861074801627514223856906024230905187766701717465L, + 12678521597571020971780057618300692180983344253909210537250788727290096554978L, + 97409418157538176229864525559359313733999642795465001194416903811362627615593L, + 17666883743653414392559150083937046549092823963784149243759424141836210233910L, + 96782625814774464062993476868578132781345525016849135775601050656059041410584L, + 2589884068630509097550648194665847101140988344084741061970648890085736538515L, + 58488365439641276883795150591910380251526838715002588792626138011101348675288L, + 1813293167819395115836130599948938455484084779362371406466311001918030964005L, + 35340220851947076236063886985035545280799271738054743782918773396002557344778L, + 80163356255106591665286360265413448326273305137096780883148926687597663905577L, + 49801921889865181447751677663987234697606127697886569264700309057813207631711L, + 59894875910103667367409317643259441162201665326496448852510137372381968995716L, + 87469288780169906217585293668973559107829939167624410352054240605037124036000L, + 65416999407884660802908802332759099117091753912680717604556155547914616943818L, + 33543113511755320947035734241812378346692006754388632274310122264159183686133L, + 6989834185236560473590886201989903335709920654637458336580794634454864779353L, + 9453561663620506951490984040430770639868514448821537257271793950020777271020L, + 105062194568187351926318870584626853622541986915663690777614658033338966643115L, + 65905392114908010515935577424561787413515312201266618394119529564572597370853L, + 61522471806184297068444697896474869845301165432237624155233522574862888263839L, + 65082189782883353413832260729892578207198876064116884181613458383803356186631L, + 55398095354679161133669588425385416998485439302343789152075296268507284135371L, + 13018671651929370889661237502802954643194745186030256377106894194985175920719L, + 96154415633980356153660997875529716848632792795013003883875081002686931112788L, + 93139410818081574961854973782340701603283319444130717937000321633720917307669L, + 74982635088784842541527066797261617026977713638310182525162946945256591745055L, + 40862289967799826228545391981178363057389423168913946439484036341887370282888L, + 115470852263677408358942349816123249977382801878297678823132394197567085154385L, + 35897816581846152143635977795416125182617662098748809515257511460935868885146L, + 61988263153194461099176854937541307276819945276535646700336661490807805382556L, + 93891412733270087417761433122770674128749014393484622769741056647992441829292L, + 63363889674615416185536434160470933196244381606602233633288614871350958608504L, + 57953588880482920105228087436042056269218205544984405688887514341233961288312L, + 37202716535882957410130484132420426975239211348162703069752022374055651765109L, + 59958078232814986757506823520029439210847472575998198149597771923729988334392L, + 73560225664101637419846250616223941610802361458139353280488006007864786858384L, + 81381083859887868238086072685326819996965414457869357163869779792123472412145L, + 7085157882501413219812434835854687065900159933181862064353013336638344373447L, + 96323965032233713206686700414364668247910934428106349399130592377824653246232L, + 109910000529236051040407434199551066023563179445669697010121447722899830279198L, + 29188016024553324107045322080633386051187027206810697421409137837163892129804L, + 69051366764640468571833531247770505999662252760133413951635904163640777044146L, + 58560547696548319526612391997822952465186480118537362269015526826027757417740L, + 22275095446365462043728943933714148759928743432954182246695721705534082344697L, + 32440427492278481575108223374055567802781007843970704532426169346764205187443L, + 41556024815868951360471047174340574741453577779166316317557158788820660359372L, + 61661933840312781492274315958954278472042150432717237773790461095548575693145L, + 6137370242550349594245563032374046320144928809115178447381366073042770592892L, + 10784033868363152271525359654516206764188060950961748694215913733347737194708L, + 93458426197448767708968587401734206036890706232650366929251257287232932093955L, + 32182467509803439353060788902721293308799800424277552498919236591376797449692L, + 19905311904012949311946045324734835900907829038092268103727592712825419198393L, + 81349670002808635614408479409192446726446433374714920809694925383765045053588L, + 25112713878147477692953589488753271343242533609759111433667358427542542008198L, + 60019911613653811171605697997215853912977083567615046627768945974967091633369L, + 110060553792790452991226553887730741239931728059117544299208218340355194120899L, + 52472093447443104162058607107887554229116455033002880481336298766763597174398L, + 16018921466897698896156081392704882247066006769479130883817841930714591042055L, + 75074666851877113899616333515338055571471639917059500598430590967335041000483L, + 107829759140907569121705481139140786708243601909904041925571380978266885881015L, + 110203864258910767650677989801220374978575649078213706976487950103512413007872L, + 33249993498895082693761709690886961413973170394967421765825300309291439473141L, + 33599956176531937878455156018238941038814691588379287252798756848228642505392L, + 19100199957826794651029234724727734792825020228073638641069144245982458822183L, + 60121413197680311130470905036256694688241753904073246384310947441968611565234L, + 80645344121742080353214519933523794213979070171462352629383436979802761952708L, + 98351881265043784186559710632543399429272683613985605391421284117545858542139L, + 14017433979803198226154330856830790332261264890698482665375720508339161035991L, + 30516489360385339243081132091198892165384226000774481543306716914568057465886L, + 97262268011116201032870333958564942189735389039959597184902148026269190625323L, + 44302058790028060916126872364366042291348234243300830403542701853910262565263L, + 100126191029254623002799581013043940654677772195235073918460201407296040680690L, + 113612569986669295254547518177010746360552558111270202623088663779762845091534L, + 79338999083369807218098838241712623564953252458898876987930131393363981132533L, + 81807534317337842862569492328339540959987672906429139903192484831200709514072L, + 69099350832806607094526178983385753179896696665355438989566508005886743564803L, + 104259526504989324371680245291688817485009636865282319690324704259405386257323L, + 46048548168319243519174905186864753621453350991053076001561241537699241451608L, + 66640009876573485928514453698651726041930085834893369045270051012573764107562L, + 95531661476915771479769287984347060951383321441714868684347591823941686092603L, + 36621915424047154550909586666586526731143413141205089696432779807915110104143L, + 25500685371009586014518949017154447180688166852684264562707954581065369462252L, + 59850567117714407775930240974346637073681921343555100772661936520702888306819L, + 115240343733804709663552973618107878245728084071234565876664228408998144978871L, + 75977065295485323432275465827564116229512558339547601200993934982654176176682L, + 67106553301726645936161667104383224711510817789237945465187962215825839722899L, + 15052746491449311800683700291988067594040431185050499702507607734364951905357L, + 77228459676908565530579109017013955701427426823980882226769852055847968646873L, + 28481534507829921014499911445631371835270965059049968012173586442641858927952L, + 27655343420845351169311232623978922158364959548141208019319314427965146860850L, + 61390729924093182415849764127651822560510081296074798219284080141718724008037L, + 88129944448482016453604390978413099869373896352594669526016264003367026195399L, + 38820696845826898829976095148404250957464753986673114269538352848960231325444L, + 104864171396750025491806631675409842204085024417616047758696760234858107920399L, + 29863292310431477550036730221574081680999194850430672446200391363561085417234L, + 108934618562963817298313547225211668640768732952641926484962109008979027015980L, + 41160261084770991353568707663278346821082281639019262987685055833901457412654L, + 23902699369871836004147116325299221152105461157750810215575910523519613918256L, + 57114879668068671783566032963607014449535061298073571460193859097850285363274L, + 37740277704857454409433323326798536839332127662247774735096314702899351447384L, + 39914634986182851804611052974947659631845131120833743915944769240870362593379L, + 22965980825421074760380373511994945118819421738400198826034975683511728924290L, + 73619859307004883133329724216060887068813702155629102968658791645311681234318L, + 42626616499504872195860607227372694794739202104648805507402666216755461948821L, + 27180887820987086213590533893445179350362971981710837961686002209737537212844L, + 12547893500051955564697063098116328089916920751126177272831111779806370819273L, + 6383124061192694324327191518704951714003591914147776609778722446554041043444L, + 89411656982600583277095337085872844640689672310374820842567348576660511067132L, + 4931640018542825079475053288396739880495257267545752981767551051947673810942L, + 80248612782720605198488022986328769667781816440810765901226254387763015785345L, + 12092028429774224084710381054351226042549085986572748481457195842303445170944L, + 26146229475813700978605757401016468603312254089417985071251062419204372869133L, + 2255026428176704188457961449019441350458062228079742175788548046834027109457L, + 30641380654182036069530143269080252118551203033739743249775363571491017684138L, + 44132536981272426733250999775220364339758797280204604071812543124861398018806L, + 97024751195532280486870245916635903805436538356870918818446669289591316332013L, + 4810943785165798842561294064990846266172612239112183384692997244675590825324L, + 60594647937573463378142351679499462396718637663411923885077728572312508937315L, + 106092534838894147114435074387638776799689173170382306928669206389784540697869L, + 100350214583612771332744853931993730296314280302784006748300068964803633975616L, + 25710297987605883256119632828274987784677421689316367238798477028078257694760L, + 29123071143314070212924653332015086436019595290116122837247518928607737843641L, + 37069274845961702330619935671375654808915261415409206654572437315129646216159L, + 2103163731858609902987804239281112140757230958868454407748185686103644104654L, + 91719028230181448577144939867970479811949564076488402186589520277249859672867L, + 45391342576703074661603595308417176373809749380471106452418335380970183750772L, + 50417836443890530817649488762692685498657632698803055765969038288656593393888L, + 34993633927197235881176833068161353999691277150832894468130305354530984616662L, + 23534323466104975762076177772455333857141585658769252118576206968469709039438L, + 39190055558058842754394430495897983372596751221323760953254502173782252535142L, + 5617230096167612764248946716702642502766239621115392206755049019979230559644L, + 32624233651603541264283870096797526990159646990330514664119567353196848504711L, + 21363196553685646388482503553351021443836786242107559712907126251012523897415L, + 42112366171549880891784673677527916736324180967747066190759040259635872089427L, + 31712983983859822934236230461736938375537587184471429809349770647766964613362L, + 74651608828926796831778724801848604143193793124412646850410456430951695800169L, + 31502721543493790295404111094528405894067828931947636951691670700174890250826L, + 102574444995694059195989875942166747896686576241543887339972917475254377264441L, + 58923697429970839605545650361257859389315238453492910577737280661934024153811L, + 16221053517648313779827464398992879024760686223416307556464055966113117947553L, + 109701043134056293739478294456803747863765083543565182448038033479701054048528L, + 65816269916986847737385553699150904532407302373423496719383228101901272943934L, + 70001928020787580403762358730682449600681762898554760863881455775439041137303L, + 92835367615230954932800230862822592318664461839493603556446445656699449453378L, + 93409393995636902222277907243315184462474445317717554777742524489810073788186L, + 44944993053488547857105740048665806597453515566906605777139078245225097180433L, + 93147772939600424893831062804221581869839889700389384361883509030083325459072L, + 93699923460095428776239408139222448679391585676571354740183685749691866973106L, + 28313899678800266849949575207359059769753981681483869123271093014071444124871L, + 61980149181396054245246180188404056134144458238839049042934740845836722322193L, + 83761141920500308170795379388798930091217620626009308983653555795715338404376L, + 77583463966607201364140641884271595665228078550964189961365384033866394446111L, + 80177055029944784643184325870695103284420396003327948777031706405120637762L, + 42302991430237898859125813865021036118673882270642203528092518119294645903684L, + 4649467931816382483273696026378785302400244682811030991459498686575099150156L, + 78548973939426759637134164945491298621159043871261650725671742941506653898601L, + 9051589590564582504749773754686840417554590132961904954760198468987586822006L, + 77803423932364165861392412958113594976070611557518916054916203199233755060600L, + 26046137849807276252157032709063139003783870331993295994337272937649474571460L, + 6806190578010603245277071337490254136831601647535271379706078675914970059991L, + 16981720309854773294680220969620151753458051082222505206356213090810615697908L, + 73621371017082581941086697199063866558700710317876168463219943638793043525611L, + 5952160277770873279520267042269542633750554504802687675616904371318313037651L, + 52265032098720508825832900808795289730022498334923517214767581511816371160360L, + 64203215183045625683829538324346545730789123127866404225520269502345859682640L, + 61977029726438030483088364022031817298674742428501177198938113200147052841179L, + 63873459224412672703987885635119052772459003219750133619548346313457608388807L, + 2626598937072069170981383608611653141972138783930451201089190662220200167801L, + 105014669327949873689179545239646646974007368914386147379235001429273363142787L, + 11058529282049329098457406723662177612408721530338848074206127378504846492509L, + 44749368542125353666772469444721723570482557168039493611180344700250046286426L, + 82636319376686946962602756101799261516414332824933119808265360381269983331970L, + 13088270297708329492219842466712903674306400272058781766367139492318558196219L, + 11591604651699081578146653012861739738078724779779787286542890320841633665451L, + 97519884363160378542487802378317147290010864449964759770643202943420127802264L, + 103765153602223202941810462552259746944903813443024472202605276597249915550516L, + 32600862571473499155120994502986447984301774518748393315923072385051983867738L, + 64338343114782119882494380267000892758659016560115644027856295197639197948121L, + 70304745803552289295010000663269329670062399995172397487425903556106015777747L, + 87347608635951993976054878729536381464515997284559134215265552082827409594709L, + 24760837937750392637884760244568573306303303059586669681982903741732781839222L, + 68020556769566088130464495831741210649627126271195366251054339005471380772233L, + 86590404461941557319594983758896584682276289501907160003869380343558807853496L, + 94630469610568401285910552228574044151085286499697244331788352911775713556752L, + 83822984587785436336173127551996786655166471356009859192359391421830649825006L, + 71650994979519660718419404000182451979557170967460452856442793385735816213520L, + 60034133458392675961813041938242460116247157326651441051172749157474680023596L, + 10660815632412363754925154884806582403128772462046713154365199157403468694836L, + 57343971592477554658280327617393743085274397711175189009881604060525070733420L, + 73136733094148658877333160562415430650644927143105773716954983060143555464306L, + 85440404039981866230662121118907356481404696270556642000862520918533196511366L, + 54186828323348403871069766176623160867804111384527021970525712913574837990790L, + 32861639005228661799058532545666296094313263213354030663415414372379631425417L, + 62435477407429153105556804571106761272657217234349922083765158636344368857752L, + 94926996881981248755683541557619155057867208528997836939147133929580669784745L, + 27273317232039193629074002897322973019198533330295869185646245861510825302456L, + 31726650026399007682055306299222171571994609109467630721479608436601166965718L, + 85013291104442307260009017660850455440506230923010172390105254539733688893930L, + 84688515467817936667035613961749011469178113827874947947379728678073706146566L, + 8000043581903044187626831087385233308531161560821002291292997344514542574861L, + 10728274265650945123021280257565412765339875792613316790968277574570999446809L, + 111135492659042640357368642438991986111591796443110514832717954055225841917978L, + 6236940258597480569622393766940064897052031664905049950316462273891076916773L, + 58417064614006717254677727841191592439764295565971175433684326510821412906023L, + 70012991223690604574612562233920263463367959170941379143744868125063733461799L, + 17553430856785112551823227172546504414011567388464825466464197810448732447528L, + 75196746683260204555069821976970306322235611913986704735160941551727952033066L, + 4177972925249999774044507880679510925550422339555421875354512693137551690541L, + 27448422819485949892314642973888660461231831322749289073425574105469045850930L, + 27112620315203548630765711479115662240898743220222720489250776217163293899317L, + 26134395304252433927428638508624421444181051640605704105587542606157063995449L, + 48055323471155904642836017878381028173995433638774830311507610768180329654595L, + 70141232116639303275594215341122469578214451440984676820315708818941014992455L, + 97362039991400118937375759014771301617335051074072313576160597167578291390798L, + 59498744397496254750667205892414552312610986306068383637013423466785034099790L, + 55044250507270497890576271409360951399826457451259584081702979748858005203540L, + 86460171717901445827863985929268084902846893704625439056276885241262726292821L, + 23317071379891553315536795196696703048777217042495816527324818815408066653789L, + 69890525662715194049154543702027410940146763855258347319639321748735889979497L, + 807754007251343896556493206120078763843560177950734372358432427844496623722L, + 77424154811568910487481703168165337863100562624125855039718328432698503749486L, + 93949479019947052516081318035249182358122773984752884230110312207153366729333L, + 97760211342925377297437825666192384623290098931846409798755562000376733120128L, + 77181003455755887222976169144131126435281559444659146032283108699843332894598L, + 50997274636133212992178205232269582410770523045049817158913788640979779352714L, + 61231394068599753397319023567451156377698547296646407938855024402620131810189L, + 46310914417223978908533423400825451583213902177986242878236812611298604355472L, + 78888942326033681852705394726853367790161963641378980320379968016449930685335L, + 90151588908348778869041727455142325010460208866421868063206862658979874948265L, + 101238573938475264930714769670270045927562839001970232615122789155233670330549L, + 83652134723285667921458928125975232181677272064498439631790176512445454644410L, + 61468550413865472928942441294978158372461565592774474901910649619331836187067L, + 68968765571686686397063145320479094890030143916895297753270420895004404993476L, + 61798872554856153172882074877619765904740475127065862941126349793363494166468L, + 46573338659142703050162402964081032893158138933434106948619884258857294581189L, + 76821769459519910456910493244642048141126524599000215211005977027890045356229L, + 89086634531739016620632886341299561732233750668263297234175608574626121396169L, + 18269148541058486241010937897742237182199410971901533756451007075618937411273L, + 76923947773185174765057467292696242693333690444075916837651017268597779815634L, + 62695560569368951962459199106700268385861406656184888348015970603993321745363L, + 26832497031250022393767443558295003607600636870355540101612314164483985398494L, + 84500534994186893964493029171522541229852180881150794942307211861255304189665L, + 44285508261404030081594397671657378017322357155781010987117103200851080243425L, + 25196615663499142674509946643517325695854942451182260008714651637872065420777L, + 99305442900943338519472778437924071503211993055069645190669845163220239479033L, + 85805364957344632634503891932617006982380155923881856744098377218203920005626L, + 22003381338649782334514084338378593509593067056870368289820493521776668981292L, + 26683687105195595843237580804763455823398788251332890875215104940188091381305L, + 110464050858264031539622445239391998647121739765959319356287939977867756583210L, + 7471593350788657207469280053433570067608276131171165125985695259621860735775L, + 7072736435435639398038184766439270954408782138488579773109528448839765061925L, + 91915806855501146789139310965134211526570393731188376833859398667377284243750L, + 99943867953856063709009671783646897434699022116226004816229108766854572108352L, + 112512909775115735554911667864282563207101882551451616049056831921300839997939L, + 89811407047407829555624895871864026223819909399804432889050602539801401778700L, + 9783936934062210669870013025405367475847037992961269431928666557105333563721L, + 17689031339513906290935146137191811608520752036415931065520192894550435528269L, + 74506200654851987166002021578306575647964038829730730235301577986725269609295L, + 29375611824092877766836458231480909424396049346662276819264199216780614622064L, + 111182298710139321563429299459765615479697973255643684101123508918407911950721L, + 4294505797147786823273071195005043753762920020598557544942753458123114846075L, + 57275241925930861287940759914062157843551774344909399581448062686591181552526L, + 41739812182070654271446030749818843305078439752905007960302736948968768527279L, + 100388248499073296003495049107965689661715991201892422837884938420800455401908L, + 94647112259790764004341239190106536582922466276741897004777141745122827893692L, + 27446994966727462152927989428229968706010108700258464710153635664447896532671L, + 103373964168408557192568459497755505893114456181120018252418821037265999834056L, + 603593167867271518491104108137635331738625984832948984670941407502421070068L, + 32482470803410666246991240533581465544766721670327269586518246785064239341341L, + 15478306694515520528408137981305949551146588074589891340158266407120269983585L, + 109697884910557339350000389307898510984056547954200064982219359838158244450424L, + 96778364314892915288067907539120948802273189980642443672533483697868422413249L, + 100813271987197293905436808180399861301221576585368731570245700083531204773003L, + 9848580500683416928405022232606276693901753536749519022578044851207387657060L, + 73523051401127073155274337744466609879882552549678863351677289698080754673835L, + 62012384606146752910447709580267400389050652975786343740374267007192517899887L, + 6329346062960593046227575807350591579764645666581841805906036452574243008636L, + 29583010969615540826792019459651511509381447857198039888276001242967767234916L, + 65835705131934183080553848663343278612885924692142996907910714583672555845377L, + 4364909788959277766712217703804484155156260164483696706579821797787137363172L, + 112610231123167259542597130270426227120989272677945330157706925167429173140529L, + 107693949755472457951745837658200211100579646605318103464779275189662278470233L, + 53338620743491463081500010144251879985952578124463654647813503945567112458709L, + 60069833177830629042515976514509458207591731897826645444119853240467445435959L, + 80011918027478292382958888691939134014729035069284567739709264874848025331642L, + 693516542070478331317581801443570898445939579828262533667011598135337800866L, + 52273809695441166643905208660760083039527258194483886293511034201908954878996L, + 48840733848173156679330379150877002447700620824155961692002854641298012804735L, + 57177651229823916846632576714273702678467236897696718891161348734004407812481L, + 59394243546052552355200754776478221651851463486911732831269290583482857321475L, + 16550719962956545897901372302476500994527294219803046882654724802025294071205L, + 103573320409090652734324495377610928985983385722787900423283112507251713261092L, + 33259673518751152602505157075003093660493455933849778537815986914270085152394L, + 74697264217938195805376402721144297590227837706586684301299004109144351872828L, + 57387628008782592076131064352669617337376803473279453333601127767137583857477L, + 90422943937783965896251880446521463249223856747181789740898758791488438837484L, + 113188214051724646646456570193904272345906028281841758217826198787143028495469L, + 4725842050268204896602970921870440551872346835384443987009524265770910466024L, + 4778857974002036103638830854878962023487637980147632054374917120421147120458L, + 71182355475849174278623329984818066985224976641858783457500578440294279148410L, + 72094742982743112683755179909216029882769719959110477054673870672995765541751L, + 75741926097018879807801122021779641641562337391714906414741504113426658853579L, + 76126900933152711297871037994157121871573845125038375622160747593285279534261L, + 19830826319186275635688571464121512174409870248240482681104224344061615797680L, + 64573166387796849563286812336358178156005102893400560929809779223903861483443L, + 101097866236081389888098000095331715828027273652681294902448980739269851411008L, + 52162381067850701656566498610323832776957726621962737317455499639791958990412L, + 94082137239985688188363912099465534831440190635458223532770690103361964844013L, + 115652444030331992062393380162120316167274799004276617977305614784404324860459L, + 48239714105427667448028676320558629477947116995528830707706487783344070508841L, + 18298742473303593403190358887380999495268221015304085069258395387129220030773L, + 89419164611619560895129488892753456065378884899899321136201939028192506686435L, + 46512579469931031012454561431577598449179436511765097562464071037556392173159L, + 11365130369903604063701150118354634945169822928467615495117669802645927944576L, + 90296872880306319520426117190162644370735495254783860509181863060854358311328L, + 3064805101495055213296802278482194523432209139269798785583154428719886535606L, + 112510516323184654550370145031913966115886561142387688498612170316060493612773L, + 65799272257840358508972376212059939632458511650405519990658343838813041991930L, + 104469330504384979723835167750074174595011007208572690780514408491293026170337L, + 44097538443652398316024901024621650082431061306706863983908612088229385740399L, + 28168711387058383734069740442192452959396267560259894904955433799272947786897L, + 76673831642747694309752168954866945349512011868688362715231305509609849727884L, + 72440938281741438731682859404930699562374425734631837607004099593809295051580L, + 49618858294338560068114914330057108682505743160850176669629454424505174616346L, + 51238128137426358668925849219007726695779985737877829986685740285562359544792L, + 10449463158360741808383631154708379943574507465797386131598764949138172699572L, + 24787230318545162296239661395115840747564078510007070819457101050783164233636L, + 43738608852046525353044056554316319515407993225683285250641284054665952152168L, + 87308324767480248378827366446197165365680286184097744194620305788730928305516L, + 68467423757054223744534485288056970030507932912656868536126222694537999843935L, + 99551305565430698469897528692615525808389688973499743484191509164464808554608L, + 2805794391190892615517138450112964718804088830954071044888071981444981842272L, + 67462544854592285234311676075848013111822062648791501445495208766715408210452L, + 90362569237855451876768483574628188017104635283145505301524182249740503473110L, + 37739346114138090521447256475932887661950965608832859320789365081682214187788L, + 4499714811554158216842822430945649787280447854769752290740438437966466559531L, + 102369149248015131943645007413780706509197937636266855825431159592883576061213L, + 22179530984562929628384070687261456333567726884427550471714078080277228065658L, + 3397034101705588119837422265366311030004336547608067328525989607785074936400L, + 44487665660362560575633525987282110179252707591470599866380025044957848994002L, + 95049251801876739675358915317357015643829756121158870062343404958137371541194L, + 42228188721118081080597415253758205887654404769736840376732244792357168117892L, + 113757043780032994609345712507472572974091505003593717775470795421675541262984L, + 23615244247918703049546704460060439462953967155462759139128539501350473155914L, + 53243534348195532076957598606114144129249355968988626098408703360652154766187L, + 115618204587893893274359016327918209112806924602727398122553782591435225035373L, + 56068952059157442208361930215025005045212063250457549369355174758845097644389L, + 40201472928718222686247967989618662911095902396540675751803899004449543422269L, + 97262537493909608971879260716928796376441056682079966774415185189313950580892L, + 101040102522021954144496233388048838908914985541201524245964512290152093595016L, + 104065213343612462433668547993058893155143062558205030417481907250861051160711L, + 54164051333323392018264807122286881007819610004544290318301784699782740494727L, + 17178322845420293670506479478095862935525147906371352990015630951354405204117L, + 24207403759043941550002622245810099448988169647987358910264658566113023673284L, + 97893275948646750795844075314867713251431667911688752825572392821935831477894L, + 24290317215173540311007859893908168241331987929867467279934345912742952377984L, + 53926347079284540925311991363289237894705847069184254052331319117054041254217L, + 105313882509607236215732282457558953935794770549701506139173735884175592666982L, + 6944139113409158320640054982157829153153522415230203410215931075104241813254L, + 37602684865240322276075958512543936825387414551722232012809254570964990054622L, + 60777986907418238537483961852631560251113922012380595581132011431647836278021L, + 34682873899123282659618414278813954580989931945082638940334336276199402331913L, + 42540704749490734548590151557974200445555615150336999427394356713934282075421L, + 53153299501808942899564651629912059037225396769177138834993594973053736210974L, + 105585869386527149056716157859521172100198094195959299023871299766026342650917L, + 113354363915282766977203322855279352763821991138523752496747739793548582262822L, + 75424532118741279363488252023911767554618840529965130939740366448758875782184L, + 4439807482980730374510298496665716914334305620630331412903993034913165146925L, + 30727541097153828201764723553842993115169070897950012909388868542573666385716L, + 103008362554072140466700303831958932797234997992982263819180187677186817085249L, + 80623908296799616999777507864282843681124042363433810574152577763469061324867L, + 28349169669479822483205562367414202996330892888199332220395572806735555461703L, + 113900912792872040410403240577674873719477013178903869199323606604923093571405L, + 30224379048730325693410919508581304622475560029506816828601176685784678795346L, + 72234046861066491457723789293052688074676341089098656700220717628125173853779L, + 99546892349044656661121257122995679014477835381889737006814891893958202957655L, + 15512267973694783353132493188406085596362132876448796928946116997366462809691L, + 9400778046273479327502093151284276664010884959994675621166361747318350952804L, + 89592060439404733259888376435645892280562212771881972933721903148652308071017L, + 102450428168216917531418362005063954636205790831228589315712731489113501024618L, + 107909987869703865839335914478906554575900715925121263447699091776556670058351L, + 86676645246010272085840970316089310876993969523858851107540147645044216163952L, + 68336252452515937317782368891663662686785200662516138809513057864607989318778L, + 91831508704716131412917103553270414899872728809070184327717851660212196843644L, + 109786828933144432394911478009316869552352130265579777491349261143926213918079L, + 5595010113556280475032918723136883910299867363479473841458733665179864671872L, + 113525351160122475410136007145101573235710105026277540925591288138447129819522L, + 72910725461368390546014551887660947465949313131976256229881696474765928389004L, + 26428119304350087877144913825220295517930917969594874106702876047575509972366L, + 198177523344743488276673986937791356115006214012642934810979910453327806351L, + 48210866776355476814452613006576792095963994031606832413694934914351729124760L, + 26677926086622761684169705546666844986337774654988886790683004025979772638371L, + 92518787491651627474392478627710856396394429876911284908743156322317642012325L, + 91148179121452220792707220064146355596329082424267274836845689871494110759845L, + 86073495203265901224224453161153256631957850927927122103143994329144122822566L, + 12818795288132231462950399347694153302566589430553387001242182514527626170790L, + 62248068059723875437012723520034795174125562260402110125826038812872187643832L, + 110608982670103182042242482032427610844240076839950365573606079223328409355195L, + 78167635377618814110162347981498721934361620232397571224907504845957748542909L, + 36338691029869568447029221322780901417127869777942839657962807528707077256896L, + 108699759920792964189987548117378027407499105148697934363241941477702931245249L, + 16501203186381799715338918455483551022902482956994606572128593664442966612430L, + 39762259881604660299365909279205844700068157653159841986142539057335531674576L, + 10046537791435493051792504559145384185910998025953759563594074132236799421656L, + 86671159097820686680968230014125883092833903842098905694626907991871547633368L, + 57301915970888906063733515432406843374394059767651437471805332230536909958362L, + 93426904697748347827965222855341808166178565952737098583583475462462536167900L, + 44350928168303253623722781745633905147882532565092969224150452809748996280036L, + 93173086301410035717634339585647580002113016622861296627516167981780551746555L, + 8366781001499557370550533591839340293544024363456523122072215160112880257750L, + 12329685773447802271549583850493254475069810991867526934039869397849222349L, + 16230538461811379350348469588059499176574348370854304599112241163870553864602L, + 92816429693561262818114877682147382548868326562423812288663776263628024148012L, + 87852900148887772390342327105836793287541385667129345364350246742366296779346L, + 51326750497837373912478505248289974534244719139966156370298656826530185589980L, + 3499816569314049891236325912108479431434735029203016711694324294681015204840L, + 26457404095845529330854346025893590159277804369550628148623786950648477003773L, + 24926174935336091420837850673329234888823523744709807086598558364417822275875L, + 16803731629740620024725898830951457486274852852760429791276542893422716678225L, + 3948832460210106619389041757945994063963159033606770467334190977972829030183L, + 85049526100537084877505077761714489555701405265805842660811985317669527871989L, + 25350582102996927026689430448224301392957308891921472951735335493635866336407L, + 60537844500584773305641630171984978784790470400724362271769965237701900174567L, + 45022750508048122815744181661326097297262276140979586253963643761974079717981L, + 57140965077109190670829356615466111731338865349736559658058205897145616370408L, + 80015762649333825816661151111873034959017000295095618003179484989143516884891L, + 68458710222209214842506394075028919042188476751929762393792318510421683095271L, + 43645007422496087334663760197741967172320853484122496653182376185495576899204L, + 112003393994827276244773756218471185967512084571340799773689817573306469206263L, + 7658030109408667297131882809581532208521574379621079898151516389976382653625L, + 14928682774251926156428882795050052778567869666299635936211771282087482553942L, + 114390663543914230432905108462616961558054356210675761103139443219584438688615L, + 10972878399642611296660015200978592680579107224306326398185282296885436061006L, + 9007342991680696392504229398589165234312778605628039875895507877324685092363L, + 30475420419978535023920151069170547102259590228374616250418624757282282195735L, + 33667010784226657661673564383234981410444047229057340678787668226330667886055L, + 18833587012287161637687679698523713776296844817374046619083388409086608511690L, + 83329756202690734392712012887878306217569821435251530250203721296593615124218L, + 55742993096306032911508957718152700960657218300662938540716065232756052886868L, + 59069738496199852357888488504496837524707245944979831886538683727461765837572L, + 76692315097894461904905712237862355556684996581605859275773671781648633239531L, + 102311518815104786513438877425696349895244416443761384391746812515891354901663L, + 108292848623501996568777474118124492675956835236996846394287840959461359892533L, + 66846077633165686389225967668667732771800880086241059086489464057674986005059L, + 22335298303919535970984936536522839718167799493003678860350198818295075465738L, + 2088697474239766820326139473680869686396348464276988437478814345420083505818L, + 9800257844942895221705227904598166674104099914828570293509530196452825545504L, + 84283096978529678101470952352414822239619478167556858308263226683711074772777L, + 35646898143459950642531227649203826514534211024922557008822990314034309304433L, + 68915930166816467711824489388113659827317973854400695237936435184043391478328L, + 56786622094195026554749982293266861483291312099436126378785512576413836585289L, + 52986120986935921545838191743970961171986680075760259417072169853574832864665L, + 55730199715094414714886285920916344245810582363662181367565129139346775272249L, + 28013911804949354618732433403226606802345188396893083812221407974635820017527L, + 84362723691744973839838972125261811295443192909309835617607294104927003952936L, + 18663696167800267373969633524123621566457528201764664569269468800461253546977L, + 95006906185000498991255962130538001031712321341351425677969542483421002146191L, + 5298440261353315066653747668512592893807787544136161589618108501962462817514L, + 38859838558420878293396896040655765820066194302595304614249299799701969873194L, + 62289993275906160934056920090330345027894665501715138137507968483175261858487L, + 54327880052340833269705542570479360069680899057285136322248724902866351935413L, + 51589366609300817829884327471651091087876029045952488993924436150453442479962L, + 26921021563144202460027521541302976097726425054221581760939871319832557643863L, + 101477144862558339592010201891329191270629339715062256088293623057030867348979L, + 67901316707740887510310995207708798642284386699689148075505836704418407485069L, + 96718178609507532031066376256798405052465386662125419099155741693554343774050L, + 26057346807973776004736732145629815785971179124940162688537365590581469134766L, + 26770976915973141876303489733568808500475934582010853170967171874980845098246L, + 90537729648129293845193643651455395479833726477469470782714543127473429100348L, + 78719234803528776224284174552393513450742431864330850991766081667160518666329L, + 115741964230218343116772577584589437166858663623766911355333279349212378134179L, + 60736666566738901086957520290853833532308103148114718279563506956913408659154L, + 84824674252182552088479543210900337519198211029548558621905965950134454374603L, + 108698872909488424998665637094840058468812393615025954637639908183042354360600L, + 54146613227259189275128214044106391528698365412789978664946702873429739984637L, + 19190887228990422929580223605469121255650473937306765963637636391220651049472L, + 31605008932610104655767242657796968638230499973988956357574853626591971480779L, + 21103212080963866244523528876877494131679414677588148235986943988755883248080L, + 114433155435970775041646627039729981953845379846848605819115413366608262825881L, + 12726589349335878729249976242215037847246102781344349200442775736571617727558L, + 16348031017487936874087593829569595549359699409440681460000690670264945676325L, + 8079418078298720650319255840051391336673776121792199200691556022312641097491L, + 49016412610833629546076523881989632302516443801870284008552322936908913276281L, + 48108164327189276601708754200109210550466531982179750884137124604620310192671L, + 33323785856914934052554007066896820682065933988796788273060445714801110487215L, + 55980415036549356073951832253654659224774915615566934805570347344702524747730L, + 48834300971025104683284825297084497636993068991657920535339159305238900570088L, + 50066304004711728127351550601173794580986385856635071793333988822495730607725L, + 70184281603894380046704481689884562737604128791797582166531084708793507801120L, + 103740314900311257783843055667868990009195980840809088897105849628760722031759L, + 19130793700542452310802196566561977019324274086824135479591721613945804942848L, + 54590768665000126682694282951395760648682789569338177215520354887037069453620L, + 50868057716401903309161037229172724679957323003493534436996695949002302698299L, + 36781356459191931011600117685830070874073058722198240004696684668583145145326L, + 43557711700151059594566785929505872853275997468603754860423133239299703134109L, + 70405173861222214879721853552636256016629983385583392200333832768240706755239L, + 20602869602080648291256883292015993801819651681435012039740250944363000867500L, + 45506777931975876010479331290127536397930187117281747538274184363845795563139L, + 73270206960413761329060196522798466140994226053167164073699349402732976355898L, + 10274987270816121282125090703863593180533037743998837798294992210631156864964L, + 87879131351137173809037376974459187218923500439497420833727325550562921766961L, + 50500649920892909656581358369272905405509859712585197222619060367145853591930L, + 60002540843130784915238777242828345941657276753823987721511537115805772233966L, + 17876170006535450045595809605004023872066609387627296872289556538768974728940L, + 90126356835141450793793547926498707574717345260769659813421525345098587452928L, + 112944503501188873438274931598670061856218197700070555795176334769848830361786L, + 81344765621859749512418566552971466151256463347262095479995394806870250601473L, + 34985812588638590340101846738441452101844632705556866640691680099130705768521L, + 94315112519297120008255853383632882596162459211449976831118989248914689025991L, + 86042187705584591024459410832934257357435022905972134758608851702942264805202L, + 2821114061220849213085489316613766784410642518139164250358498114064425922217L, + 83805514533090333581662989229422579908672469271335615753129023089921408578636L, + 32469432841958529172977693130360061887717363260734452190518999882773889459568L, + 69836311334757211631915702001143378378952602813636255147052862837655873207666L, + 114341316793003925518903877654831341272002262827385568726522400658279073969977L, + 42036575077054530678636585677127203560811102811633788713639445775098950827890L, + 85024910361862565336099650819774287102166807753378096928032881329427815521769L, + 55324226505217249310091374352904161647977647990440486665314182718184535148848L, + 23774778001643343109035069197094064479934349580513929703915702361582199771099L, + 36135572570758544226449039845346088053007954845788478796484389702665205938997L, + 104622322503420343506071899107410854115368216537400932667643945873586388988474L, + 389281662728734117438239273197528971901632440354548723962746311938389643353L, + 13887266920459997663758749023053891008408327262864848553695117135139951924070L, + 113398698433123266112256228684235751911280685076715238906090483706357974168771L, + 41418884883552210730285397107293628512937328351920791008272399625649916279934L, + 63699551918624295606055691752881366993635727303118120108439597851383005453287L, + 50154599554853174485564607391603409580529574992148828368548193179539679674909L, + 51703605626896590030046618010369360687957477624327788169856216005448479387131L, + 4254159162821452371420317804393480625942943403575549832090888849849889918055L, + 15994248797720315522494478793549468351058780330046780693018975672663231539965L, + 44913976651579429253078278262016794427101984405074296648368178922249612290679L, + 55662236854568822130536931586799458576438744718846422902642897867994969412235L, + 60593956633691922365055386174888982322636015875495123255951932272851240046423L, + 79840315755370384435368745515780152703826574510631894136049959024831792794703L, + 48644766712239836359694119014710616190157901341207003336118677673407448688923L, + 100612379279849216310165116354954973678629607402136409286521772357575945971148L, + 59994648821001237513756641873976607150726605608960199640918238245215509648308L, + 48712470416113843103136163865510682111313459152099075206858086723443199273005L, + 95821167575999367493941993342990442968534950462811882584888797462476089447849L, + 33570276304028281823882462087420012695341222883505352567736372456364999970213L, + 99191846026210766831404978275719005046516500614621590164715392217051244166376L, + 109610567663228431015302456984255778900920308033165954585745352621200067331765L, + 31032627033603205165834722286199725602157845358281914391605244950018749496299L, + 7063528408033626067363446944124854257162281483962217036269600681339714787775L, + 7318697804418930338469979084221440770838906114098018890045696421115636529913L, + 108303941675744539461697768033562059126012241267783838357006066216166416041781L, + 103236756975627192725277761755162659731457044329436581638688108553215730186833L, + 20596951972290376704311532635663539108148915164977357699006051363295112367206L, + 104536807628201476731998394098514135063083330141521028296049251912857238440272L, + 38065964407284187458617688532213103578907361788934199049541867476852212335869L, + 75191038560850565714894322679218775253538355739973723428850602904090007279728L, + 72648426849031778232845605485771163272744424442086663449190842694864645857666L, + 35718436397479589196342813536603814186576810029069519027097936562708510815018L, + 35441616456217063002811486804112246378753603347110016969586504782096378776683L, + 36552949537513875964367615978283214397350720512954261656001869636744696854711L, + 66230245543721501499347494133332683934585182720290106391160704649591126983909L, + 92401348466732404649752976519802259664760098700303490488817623837298318673652L, + 26992406869008023043647847129537166411932602578575016857893104760230396453136L, + 51221845871734479006818602103550380559586000811487750582760158347253561072325L, + 75485133178739805765053595064186644875798231775269982191276342775641707240237L, + 88811591798079582527046453990811302455289778782185134732740829452542340519670L, + 26225704416619357441596521658519323507514175989981185058236712931341096746136L, + 78782982165736229551869135568277406074490791528493343242322082273563321652016L, + 60359811765908282755511626114780393416610047871673899143332664498746264076298L, + 15274724303609579349356745665791547953979631067956604423502076684098487327403L, + 71281087229709837015183351813981496389569989054420770291787547655194554690751L, + 98825830315893142240400255914954806230312123977694093794622783773073061745342L, + 81218102972290087186618612391371696647175536205476846499197960517743584691989L, + 59079349608768172644060026122257405757661335559716972006510889173341302488322L, + 58259135880071943941673098258960167125954215539989132287883961865838366311966L, + 72588412345101524408679765726619301630933571308028841224460292037914734277432L, + 69777632434818220447028556774052215998833067070441864447454250502953724668784L, + 69515308394164181697305216564141988818540471859544560239873847691984914307981L, + 7538376676383976207567498462364717279572775093710341794352790939328588648176L, + 9803392422766580525157619117624375849814736097370242762134772309051722811027L, + 27130139643102436431038936912152291983027488837782003210295257396052409809950L, + 77650526933463086890153450013608988112919204054815839999502568215562887434230L, + 94674203144743741514864160727398774240888824698818486470696961375689358528652L, + 93770165091863769227788806398663206386083827550581044563606731066480269358829L, + 111378765033993484391882337707422953321277694203406660477324298951102613825734L, + 39809193796622332440293870438058332217694944250206080134289520062428343001737L, + 110870634040500564945971057237575762714154979673916904401552546154172138615045L, + 8851591404930274221548347869361746554959861627955494892882847992678154891937L, + 6397420782027027462379873995946346804165115556775281463749093738526431115982L, + 55704567981532789275534204705754990135998505407557369403373317053732745273564L, + 8138117798159946842967048834635783117780956760913983284463438018081785732656L, + 75207222606857282113674665116246272876796696875090278021343263631087734013534L, + 12543847255758777525431737763032947657720105489722930407956988066841287650624L, + 78327321252130535570250911410466280437144972998159516285164686828945050773948L, + 90196389423575822520118171822181490354156852650241068673543270798740759570959L, + 60670122714012186216557490273944849058369509679550006105881736692248220097574L, + 10232203056784253994937591704858661588355868348916079002690715804987716383826L, + 56250443820912421779940932299238540687284557162371086043710647395166341689424L, + 106745151287508984114611432352663460679320831899507458596226828448613433574629L, + 70711680571992803186174027940849656610654068847875181643669226730609160665543L, + 47838106257302756155005461503289142780947408144101902856502705120104859749974L, + 24941360228300096083350701077862032603070060851245288110063415582770095103463L, + 25700025266950766720457426715819491124434076610164997964285411086712832180087L, + 107105239401310902784345766590657302797260120893605526156704024791074790374486L, + 46185480896420842135218739225912740102667560536884160717641823450312574499972L, + 76998048126760891745588080774341297240858572011912680574454836643717168013962L, + 33808836046696640438659929011730514035734389148647466846824484796567750758787L, + 18996931853760987572934181889690919742941525826610089655395851453039249508242L, + 56604122983388823053785197845481098255785257267522212256255952697702335462767L, + 44492985817019328377489391042409249255481209488552954877743884032952084108568L, + 60262700527314881511672082853298753610747395905734558549210201078525650794369L, + 69279306977580749647980374713849506038229420028933569196853781248094801112495L, + 56195902117233403955930282133702481708365531910713600561984930561415179141605L, + 47314831690761571391132666893984250546663032935010391247733227625093836049663L, + 10812783025036209706047425037985337032725721168017483330083142580280303327499L, + 53162496752508809045501362001473691445566319961581721263708067457905101215933L, + 58945457420632645086059903599934816006401780540563391798565832004056019028674L, + 73919100242037593331579812218634568218168417235823351457219323808566405869284L, + 52403495269684702131086435910831711916163695522829566636660560660799048967805L, + 13278812163520552951184294461865367827589507065203666088515419774920490046846L, + 16362695154562914334155901193231892822961192810812064385472498730784665801421L, + 3517056216483029262257506847130510185029740665166150468006894224027844758082L, + 106493755768367304437249140676246166044758096968225683795417475315940492882512L, + 76108738678107595032074077639412467077253203334192002336836719868953673062592L, + 24636115565757631437667031550958535438978674430521834147987218537021781123234L, + 25741695857057356211640713390935410123855223996729071384196495225008418025128L, + 19955118751219367788486540195772941722619062836730568279729801630161390967599L, + 50727362120812021647921340345708573849532470529549431357712839661035232260499L, + 115008990003359379169498136566608005415041400711302906652756982799431888611581L, + 76011030665703432674887267454022929576997959526321421566956239532190756808010L, + 43241178286167700202427095152526401603732039957292715002566291226481343605762L, + 102116375477349183975745809892072191840693105552331542023102178483468604884270L, + 2367482012407755484187720340622873573623580517843674370407488519063191397691L, + 111361344211502819366872854692911530822999459773812287285457324369283709635699L, + 109657494092569138881317447671628359243100703575477818863540322790386549722230L, + 7109401893987191796852399187756624249465539674575008049772377454960266500911L, + 62109127966662221855456045871471976300684717590594143452168774326137424630915L, + 21215429047648886881079414922583785408461108666443625793715979556096401731625L, + 19279814532392817913943697877621536160592294051765916138025545274590518161014L, + 7059996909933719857026691582224036233378957254796742907276770679435914795575L, + 42259543559452493904761078751431150845991251989321528250253410612380573321732L, + 86565632998965501509262078248502654145399501775070068265403951188763891315010L, + 31945957244800771720929732584726907607349704858229698053899900669252052622291L, + 33092687574736978943259443103172536628775258103460837384587272224669777291246L, + 49991423183781203023419136847708046249824217732070381815053725604886162286791L, + 67696544473506340614845249586113063722931832682767051358934753387764790299157L, + 44300165309779156455215620752097569573691489863138402159754167727039908383175L, + 76858130805950970498647404197161756362591695546650290097815117903992974846379L, + 53276036540992571104528236913288618220936509140158418588609708019288597985187L, + 28836557358889989094439138775987779139189528452622475804026978942568149457238L, + 50644949972958677693536850596115077476481883558935180276892583079964074035276L, + 4313035479479260652957532662237992841202310127861671108799014761208414897840L, + 74980974204719065713949925256433789927275757602890792189077543891295362364291L, + 31221916081651421283201076921082457505494774434921329664641908873546309091178L, + 25462244836002487199485405445806588780879544203146092339551376405142372822334L, + 3482999242917196361310871854038227752332154051569125713305221689612101519921L, + 49649109741645026225189814305214367307422381752801210793812082736369288961982L, + 114342386537218413877218058901138371235899462628051411191197914515720248423341L, + 18244185134630746982865432082289142945107926531633581824930025314084943124989L, + 9665298437683704295641756074486242506598006561010687667829341839141938852852L, + 91836819741188398512794812056612855114211149643842653549306158789633836413366L, + 57810787294785367000539906087988355564561182541447677614819545817922883191528L, + 85477736256329482640831710125138739960164891241946693192003483355122399931470L, + 115588965459262364728375262949658522780633344307835283517036286921264684089297L, + 103260352544636963665161503752217973936299959481004422664857988702309622109391L, + 107574880423637027149194310946125447078638778251855934418764355834865906839141L, + 38988557583051884992589337804370923392967342739458652510352831410409331956778L, + 39591776179706661567132036672004460722863449502638455439206618051085740669736L, + 17295299718391811533844201860737415438218877987077723172426193442926174384820L, + 94322782843392951587915185212638734339638010622233846794995601632684618885460L, + 107541695690889810178451969317913054918582980088580045884174219118960727155090L, + 24433009999316283894057987656228233755881297257138490518346832470476102407067L, + 64913204017500537734788292080991565393911137003526637813960355193901612144235L, + 115739811155188017616770707442608984663061587821428694051419951407332221405139L, + 93268006609628413900343026290606426540202253537136988008591079738656031181746L, + 13590790537658288260517954266302244984073327090302715612632694655517502725700L, + 9498887082168469013904002090047017291677776306533899049946867646338221837834L, + 20985918901466134918911053217454386226167289283904644490924463147213654696049L, + 108491228858878295885197481281971955944345047178278524028275614393817966339188L, + 110455899523979317579311443631776197076040047784034262076820899919827473519107L, + 6844215318841599774529444511351358879098255296841141296301492647973263268428L, + 65682796126283140741520637070656076629243815753310091189872944625436827968376L, + 23517150246395086433614856150225290129244330727029257108964098352151836879094L, + 26047331263994186391482269519815462872757319506074471845037389898789825875247L, + 62205044018158822229377151454547290134230969846786281526843611718601819536542L, + 66160405117911721687124720428207854312139716610213208728467032646776645997376L, + 89866281829404081780535119126058454023598298022311318229115957056736118948204L, + 97205043720275181149133603109928920179681558801849363897295499342651072536519L, + 108224954134926014239321602285859868141619691513421327461634944098887365621534L, + 62127427428237051674420339353192007342916027118439813622162390804228610889186L, + 57893944818747416682894353987640739673658057551300981538784349653023861351437L, + 107011232727952378470666194813019614835857006938192015800662810852391320603663L, + 89838837943621207939392244168865315732107983537751534574579886291497141924371L, + 54632573359551426723243036703760553108536426479720114683903078151290806006296L, + 20738611782374605156646956064605162095779086604063221130932249292604798904608L, + 16350363247384903293056062323455724399281244734754303492438311847607498851127L, + 55070254729385682469339142212209832394927084852791974237827777250490914753097L, + 70055365590940376112291979561642970183096463801380594679980002124302391877728L, + 15817205455682046340394432642972339132738094355192512023066776236228524938855L, + 15040978696204192679398805504602074348777447046879772840279566034525028940426L, + 108792775256107403391456813738746267828500095466992838148489801045427465606822L, + 114140463922141397718650461353581416960441573637400625636182861671768677438889L, + 9266792816924420616455524252906093074312617869373528239786435567511909850584L, + 97488859087996168454354238919383087328089783573229831853115198044932227680474L, + 3306941597490810404824812394266973664265011528485160051134428993448930071057L, + 27016887126238838335087822685515964453061603198222243802559900884953482302042L, + 97101633243587215197612635088560080796283971276295720139023256646675270471260L, + 25761660448050799443702883851485246968893581735447113348244062051810472315861L, + 96251340403079234568523076954219291233649081305077170874462689405885368052190L, + 75368196346776588329316860276886265399075152883748080407426829578422175435129L, + 91108890034381164604848107828959181618294467488462096583429208296553396043494L, + 18383384042495707683433916491880915065880560710098616373862311370236787240918L, + 44789830627835059483221298616711282663434668638226788590848493956012207964209L, + 38153747047003712884045129440118737151596726392380182899055728495102932659985L, + 90925175232108580050872154670675943004849067464852756622340307812594900959940L, + 29597858466294747689192446973316153084480675933662710109785528207120195200469L, + 30968239515894501488693884336782052877086193232886478078956587970878260034042L, + 59826399967474621112539680250762484645711532878507177809792747649555312814580L, + 40402883816060368873826918443535580421498743432306583826516865452640652948322L, + 103109304131739697403920071232053479325353382647749396046095727994357758653158L, + 113907958699654324296036491251366551291536643809192490851021647257172722312741L, + 79076197470325995404429433846475816380495936868943975590060606361744446919928L, + 52531615235368617688492296476022505542606817220887394120841707850740416286419L, + 30664922842482873679297001457676095151872007267296250671933573720922787459336L, + 30338238369716210451901275376355753739782785259557498904281326087027882772736L, + 107608350383853963907659536716445700493759943543416131734911204634602117385813L, + 65958965586872418238783384214584168006245471907166614590353170781284445954796L, + 80100118013905022223143324948397185079833858834625716770701184726442665663404L, + 753530398879515371191977801468379293063900654445395626327580672606054877507L, + 98346097904140024964664837653986502379950088691600210302337297775169440639538L, + 68460124867614206585581761966234598146096085494429653172723430586270068231542L, + 10156644715043863684754272020547715914552869529746645671847735023231474881787L, + 50037510783686993668491424242622645275356136505150554174611012370627318553265L, + 46635569144774414838714487804389576990391955732471735046915355826842511298703L, + 11331911067863218893379169383664565180878880913796054989967284257140363619882L, + 38431294446985987431601905683782568620167714717333814578413045166534585452311L, + 44398384057199342152223969332814986205258828369979802367663368416306336770085L, + 67122871004391847638552204302083639336767183534269367207129447715800509018682L, + 3185747797477333309165013849816031863402475405227910777645999204588338374694L, + 20212423021896630323680720693447115890743243190987789155927280923344887433011L, + 113041857669352149316452161645207210759507019267113009449613325743667591164470L, + 90089900835203336560391195533592788756531865029726231487722601178812519556153L, + 46284131926838691930664774155938163805065005910783958732358715540938183409978L, + 85040548258253186425024226442365679373979881285185303165972206176571521063490L, + 49181137362332369980594604018187366669178450916134692029234819013234711506547L, + 13457800508316250378270810188212591389582022611819870961872314725573569742709L, + 28310457312048552763922552235973792458586658559020099776560334928303823615104L, + 91802058223571710415618380655206945885744903142322074359852783750098855244202L, + 1458357324379714821644206493939764731936748367480744939372106599086073017803L, + 63702161321507657016183298112199231445184857557781471811164211011615511339748L, + 55190937570062919240127539671282073297739632266328637800033009517383010297911L, + 94277248020362510715582054891654760276529287046778461621178691119693563583975L, + 82859741372764296636768241929911801196238429127180592114320811090384150685430L, + 104562860753267784619445400790772714882729078394982823289975936490331272791548L, + 16889624196322371361266895699658135728060861265972295698439575298043018913798L, + 34479797656774547066878888197995074225619744124907080334510867912345784550424L, + 80387078517716327864546305704044833524499425210992332886027138566405211949138L, + 37549033433004244794842287776531066340633053426769345268287856569678436114386L, + 60316902522755554226756020982946012648154833857999156815198525382516758499558L, + 10143956916498717878031035057356220149570716018384658787517849952091665062748L, + 3912509644482855673597958622581443601329189689401725406963587135080599187065L, + 50430800078500925926672261287243186812393870674856580679176377598337931348098L, + 80833354465541234648807619310308615804391105320459261341970413653583833113533L, + 53863620091753446321119113825771322976178950096485580378658224965753322915403L, + 34029141710705938408243180450001896394916135191279220565382517565616904896359L, + 110854352538937945899668215350440452593413490541522697725121447074200141851200L, + 81046774007854559953999197808086686539317219540931646384361653602077060041223L, + 107687652164547475479236163744753167668835962743928369818083365194585087015543L, + 58823056910078960427905691862445249644862136913115302747303130775438455735056L, + 64778828223477209419076856275481409064383004061886208433177545609448634696126L, + 30173966981334520079423222215487422166896399915962359334610255417081222799465L, + 2340646407364631466381505408539285802787096947595343952239785490644612934384L, + 26475480720325421705921984788405401195876336116695776091373708687906144742488L, + 34606822859413066968238325944878055764810284482770801054372683400600651526057L, + 9871410681115479619283048859281220153931475276229831902121199950676477832267L, + 8769623409176998516065671597586972387597796975533092120484096420203928746136L, + 13544498690312614332166725673893888577247744865804701623207685161160253505761L, + 5306151177942053484126937889717689408884966428672822323845525566148989756444L, + 28025201307098835479206645219070345873102513040684754347962573977234053211580L, + 25143765306193849064256195119390421696760090467999556182038230913063376614600L, + 63784280865426840029958873741062502952909156932939012297017563642120915436814L, + 13569651136871605558107219756231189260242924214757216499556800924663989415245L, + 19844149102409145164899383702905431874294284279975799650463349302848431722345L, + 8085702973244851511749511458252001251656396567279831753386435292626763485519L, + 7228553768733225658404951895408814447072687956541829973973278098033771266133L, + 105596656275798929748166863934885182363689635847234124436621303088018075316318L, + 38676776859894327439306496331637879961583690003149963151737467525103054120562L, + 85477686937823419543333196992932299365632271007320851702648643772402369864328L, + 22229920646492402606981052724637320840692349558623293033865697366530470978486L, + 112072965867338239573889213937723730433670062735410160872920205584142628381373L, + 88467625016731521493423548833553071825397026551739211671998589112975698905278L, + 25992504298006565830470368312378721049979960036048125625454280742210714251460L, + 110617272903019771469499444823257727911904694075232295617275982602998246137287L, + 94505591102923281633582187298665869748706738506552940726297726697376921139940L, + 61045622704434071646267219815056009885098917557981157258992889212955684204266L, + 13211097245463234511960758135014635595928033177520118564099801801920862689783L, + 31074512854902337288625257590954829730900652551161723130126776340859848806649L, + 44538331896767374738844648938521484715615151697818866991405461337364931895882L, + 3786568789660403200852996085367121779229835783673034074459126889865476618736L, + 72424083303309042927901775547713806199923926084563159364314982079354479060001L, + 69591869790363947775648315338788856147382399631102361163617626569778221519868L, + 106509905815215444060470900722560683767640278101044067202990911217013896112782L, + 75058175866682352019928692868488216877528414265350511354981207385403679685195L, + 109283868054331544143387891859529236421627373812326736608285770178840546643871L, + 39542883202479093211584799838746667716395625614225499740058888501390961106452L, + 94595752330744041906541122701037256583611801936861866206832963585263438630784L, + 34480068985205214181016984831940818548407005320799816662621545126994276346383L, + 114416879116659179519307017042905732586005243477405363334331745379987475067267L, + 93554579979664800565805397539022039007161035481361397011797715647990161496531L, + 37458354615498032052130382782686290665116597801796388569749611201056898324191L, + 78211335442859054923244898760943187603468759051592897374525429261348823850504L, + 104588047790860320948508463604431631555273959929178380837535562211583725095865L, + 88533984364671327208043309765991916410177054136632659494361043900096687170520L, + 74588505857600708421962930087161186000599018292750334781125400525294975481762L, + 112752987453712306641220876847544811759380413999723354584980558175049754432795L, + 111842592677353494948943759638834566424266950480736197950303220951311759187720L, + 87665696940715095017967264494167805840067603241734544580898800636588266337037L, + 1090280637203525009115725313643458642172735305034978144675368327513392247829L, + 21753965389658242894657840187609862990171336384073809699643086551343848128137L, + 37267372813267449023828933209579531160284908765644872895890883410796155625935L, + 20525524186444105429231410481483640675344979756404898092376935063963326256122L, + 17829422600439756392151953943391238535480033142831909162778609983726106228512L, + 41303271138985816303296672094245939680365497185281926261467432770171849579687L, + 82823394409558916672640587646663901611551822982421273865503472173163167718999L, + 89478479736184744977933126085668082981809605801479155792211982965923398348835L, + 72802133526370933145427659656755439051538517225580881768607137090961663653241L, + 56795692519940407526356010151860193442211997985387315152113952611744213237658L, + 65045391625118939077142106477324833186625602113180931858323879876662297724336L, + 60215294995007274230208134932676628315723527736391064120561973669174161015242L, + 102384662082935928315339426378370186792048305200094289382112523702987931678926L, + 86368559242380026121168902695823179093385498595197919919615211855084622239196L, + 76235896788712829841923795664649145649147848714227066730165805925937789379638L, + 72992440794182055655060490731957945978590420791714748896924137659543510472586L, + 15723779340218563391801553289451295401220280130193367650215088217189526768359L, + 30603739299926735280879233651788480382377350858560583934915975115996384292593L, + 8101282996304339298994017877392052576046111197701926575394135086300838023721L, + 69033295643745724490836407920021999057814583179181837046014642230728249600037L, + 28592965524777064039257774571078878759841665290321422900007794665753963209279L, + 95154479716567613162081487366086494132497147280317769959985517566899309948498L, + 108553069643570880564956047611599133271427665479694942397557048791568628806341L, + 69224388903325553975837255173974350182140940603228387437579339810084845588140L, + 69488977682955929391489137768839210032315303077149524445308821275179637103618L, + 103550700012517797839435246873195350567462382035099666630363804973887578951682L, + 80470716205192474589208272562729613877970764510034314437155960568801829613842L, + 112583208063995304540833406455352374509563782461174974145340713205469621096979L, + 21235325283616647578043866271225113202675335195508649707145172457286606141984L, + 13232627578013637215675687823934034972596548934524658253356832731455209989160L, + 80784032631716142178242469184070553027785085685565997102326912501697626517313L, + 7294942691445791409321257747702350408857270500228961118000714872988950089560L, + 100772570340278999113223280379402631778048062948247847159753669667008184399193L, + 93587022358381030729294375674433618701473827243484730592562292037522832295003L, + 12737685905656421304213895995337275908318404485567864095208751640392542517598L, + 81233734395237990325768449723927093657671481576169330485233345190291219225952L, + 69512778664259522863106646708774602335322872849219726033944719523744694631269L, + 36669514952127528526341931671493672830634333916199618253712407351482889565809L, + 97346345178315596579217753012380963130055862224614585562240721150355306874228L, + 13449222348375695803892334533135453122514801303614797298523227568622555689334L, + 111794849936821285647563352046412563483827277208655139522183147941449043408758L, + 25187687048590001973910956793862908958872565981170214377638157852182312571777L, + 55862026463301963985147590306728434778192433670354908742622764392746031586460L, + 107785046518206050102103260006811728039839192809289141151521472969098636975265L, + 41274859515500512327009467093125014649563642645719036935586636904971032950437L, + 10299670577090336347573507076381569009327310672260051284732727198668044375733L, + 18740447824932021856268111049021888133877431116345567968724621857825852217796L, + 4200073393579074662096737509517039478021146153843100404002844295789247718888L, + 115576924713829251952645859333145965259890905433609922733592169128194952064495L, + 87425681026423479946473975739545745299695172284233174785085304201530867212284L, + 65736003615206120019604160931933626146807817697708257905273663093461844861061L, + 68698660336679412340895678893606703366897742543340702318992030146867902614180L, + 44400381641247529974285344732897027714954070929727664425687199824471755385014L, + 46555944721400572748889917900484247677570522028454099304526874957996228277640L, + 56052117678289692910179076027864117534973430091370827276740312219466644295458L, + 51748509441971377338792270423435778413464548039401662932068905447231552317480L, + 53395434963484081809584000769248080961201539725305176110314209609198276843005L, + 102434000750709668610540259777148461533918495390223949486442439090058827800013L, + 96141612716022589616404985290434799930705037276016344215415912879442379598580L, + 96591358795046026482098529344557085339678356537480328665895473626353390068389L, + 112104425472056185088019792401011431491830983633283699577373234088114766893436L, + 51780038800394905147287732963986021681826029961029983295292280356900630107293L, + 90468410940773955762555388721724170986097417025247277612326047693927134761732L, + 113787635886243420042401677550920536626562907700369504319047304745280100901418L, + 111779868770549036631826184857346768528115424108766292718925491951245933743262L, + 1383125703245276385224109432750410273570943264665440273972968132086223737228L, + 10134161562116399785048841072740269155277614330172394008099010154300508745698L, + 85359232392513032206474801086296076557552199612332987313423759360551941365878L, + 69985192971521624329386000344285194632994126063400847362182991679001359572122L, + 72339149377714492859924370474917145875893849616485364424005757780516635362611L, + 56503123851498363828048317347521935671181721935176822509117384860437039033081L, + 69126853016586767696897188960560669018253492992061804151504417258940449344728L, + 39330299812728222053701305104575256287844208382743784690202813602370359607539L, + 61409899640378687296788156525781772854856509888081169135029103081562169908862L, + 44269150079628873845638315214130972701808044677291019812697071769115672935826L, + 56056168260782053795842288560576748699255446589292665370729220513400153079489L, + 94019538583512079156144786365665989285876713092214620288958055665535262050530L, + 6834852430700466562127587266714618514791343291417644589017511016990783355745L, + 1084959959337983669962278498441227418643027543409497426675351029330200853686L, + 64821350110428042832338872266823351253349947620020469893450914763400045302935L, + 22204946803601127399408985692110346044027239156293394966858530118282477639552L, + 36613852788587714200712041764597325017119186926330078817308927114268321888408L, + 26739566197878673394088065441468330922752350618279648337693390784942075313366L, + 109670313816477888214462529089772292089024783630384470625837201599719593046890L, + 9085296185093309738730942628356656484204324720627282267824811810925662595035L, + 67276382158235748718561293466013901431928725764841701443046468437965051147045L, + 115445059586456935708290213758207585365166442358212557650034476554494941939444L, + 34033762681336554454951042883589284119297586773260294008883858312798983889577L, + 83866729665675158021340977072788355765911500343677100521455474728603516009255L, + 26788652676730796537917986715149006710765916810187150134747966504780018211344L, + 112795501658550766885671569168821667620039498129435866835194249729273062173932L, + 81689027014275899003176195182576649880349411490162790721514953337217510955511L, + 23104687795143537561327142876926268973710826452557480157496720794591031951797L, + 79090184824195591405644231645740858320626756246048056690624496761396450959013L, + 75123652463963764877061425990770347795868876195886491732787070736510177074581L, + 77091020794518126957007731150277876565087725347784962070706816290965708714058L, + 31114546311402643974968758145439532479304783698429893469155806120143455812451L, + 16341484285447878518397457523390367190854409959942210272347307256339882781267L, + 98181118887583940465875837223088150093242984007371151495130338967180219414272L, + 87592008363538304439079982818695061454989580615310070537839242259041736713907L, + 106075531380976054958175634829001075730548704272684079170264173702598392530682L, + 96922583627707115101968615484176462533918860323875268927225616132861429195662L] + + merkle_result10 = {'index': 0, + 'branch': [112016540517777279124582056964762882775092635530152119738265592842063160830965L, + 62231928775068700080431948595462536614853790863928672793937605905628779077362L, + 66845773887633903347836703158453493147168582880683740028512657283249821141943L, + 35413163942878321560196331591707630100515321374497280195772377329676459355434L, + 37851594145648910699702693859865698208518005761671890323995855296534963936331L, + 28759311701621210466484794525788189825744427228601794119000934510434164460269L, + 97476705517834473337408303529983274958448413857287704280133965753400514958554L, + 68709175280440923495943620591462095299071313388291609998098828869440974122048L, + 90452556609198907126320948644677435183782764187784779734668365678190851346616L, + 28184584189148850026532617133186243317996955074357809484626968557003017476239L, + 85372773260251254820744582777693887589760420918467118545746250872540123696352L, + 37908227336857066813559922943461275161094662141899261190542805345063102028920L]} + + btc_addrs = [ + 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4', + 'bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3', + '3P14159f73E4gFr7JterCCQh9QjiTjiZrG', + '1LR4dmTSS2BV7yrMKKv2SwYBGWhtEGCU29', + ] + + tbtc_addrs = [ + 'mtXWDB6k5yC5v7TcwKZHB89SUp85yCKshy', + '2MzQwSSnBHWHqSAqtTVQ6v47XtaisrJa1Vc', + 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx', + 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7', + ] + + ltc_addrs = [ + 'Lf3iRHmfbLcZry4Y28esSJ9ASAfGJtBiyf', + 'MJVQisa7ragNAvfEMw3Khf5qUDiWQuFtq5', + 'ltc1q5z36sntfrnd2us8aphw6tmk6ywl49r3q0vk2fm', + 'ltc1q77e48sy8er43smx84n6ykmxn8p7d7qxdxk5u5xkz98kamlqyrlmsezxv5d', + ] + + tltc_addrs = [ + 'QfznDEYLScMQokgvUAU8xiGvATevxMfyxy', + 'tltc1q7jvs3ar80xxexedkrehya6f6jlqqmwdpw8pxrq', + 'mmkeFSjuEyD5QdnciN4iAHoQuG3rcxnArW', + ] + + bch_addrs = [ + '35qL43qYwLdKtnR7yMfGNDvzv6WyZ8yT2n', + 'bitcoincash:pqkh9ahfj069qv8l6eysyufazpe4fdjq3u4hna323j', + '1D573bqaDiGvMxMRXWoJ6G8yhz9sLs9Z82', + 'bitcoincash:qzzxswqlwze7c0gj8mwel8l4q3wqk0krlu7jch88gv', + ] + + bch_addrs2 = [ + 'pqkh9ahfj069qv8l6eysyufazpe4fdjq3u4hna323j', + 'qzzxswqlwze7c0gj8mwel8l4q3wqk0krlu7jch88gv', + ] + + tbch_addrs = [ + '2MzQwSSnBHWHqSAqtTVQ6v47XtaisrJa1Vc', + 'mtXWDB6k5yC5v7TcwKZHB89SUp85yCKshy', + 'bchtest:pp8f7ww2g6y07ypp9r4yendrgyznysc9kqxh6acwu3', + 'bchtest:qz8tg3hcp86jd7ehqkdr9nuz2hzvks7jmg6lv9mkup', + 'bchtest:qr2a38zyjmjz7jayf5ne98l3j348e35cw5w49dje2l', + 'bchtest:pradvyw424yn9a4me27jggcsml47wxznhcp6u5rqak', + ] + + tbch_addrs2 = [ + 'pp8f7ww2g6y07ypp9r4yendrgyznysc9kqxh6acwu3', + 'qz8tg3hcp86jd7ehqkdr9nuz2hzvks7jmg6lv9mkup', + 'qr2a38zyjmjz7jayf5ne98l3j348e35cw5w49dje2l', + 'pradvyw424yn9a4me27jggcsml47wxznhcp6u5rqak', + ] + + def test_pack_unpack(self): + for i in randgen(10000): + res = data.unpack256(data.pack256(i)) + self.assertEqual(i, res, "Value %s did not pack/unpack correctly, got %s." % ( + i, res)) + + def test_calculate_merkle_link(self): + self.assertDictEqual(self.merkle_result1, + data.calculate_merkle_link(self.merkle_links1, 0)) + self.assertDictEqual(self.merkle_result2, + data.calculate_merkle_link(self.merkle_links2, 0)) + self.assertDictEqual(self.merkle_result3, + data.calculate_merkle_link(self.merkle_links3, 0)) + self.assertDictEqual(self.merkle_result4, + data.calculate_merkle_link(self.merkle_links4, 0)) + self.assertDictEqual(self.merkle_result5, + data.calculate_merkle_link(self.merkle_links5, 0)) + self.assertDictEqual(self.merkle_result6, + data.calculate_merkle_link(self.merkle_links6, 0)) + self.assertDictEqual(self.merkle_result10, + data.calculate_merkle_link(self.merkle_links10, 0)) + + def addr_test(self, addresses, net, prefix=""): + for addr in addresses: + script = data.address_to_pubkey_hash(addr, net) + res = data.pubkey_hash_to_script2(script[0], script[1], script[2], net) + com_addr = data.script2_to_address(res, script[1], script[2], net) + self.assertEqual(com_addr, prefix + addr) + + def test_btc_addresses(self): + self.addr_test(self.btc_addrs, networks.nets['bitcoin']) + + def test_tbtc_addresses(self): + self.addr_test(self.tbtc_addrs, networks.nets['bitcoin_testnet']) + + def test_ltc_addresses(self): + self.addr_test(self.ltc_addrs, networks.nets['litecoin']) + + def test_tltc_addresses(self): + self.addr_test(self.tltc_addrs, networks.nets['litecoin_testnet']) + + def test_bch_addresses(self): + self.addr_test(self.bch_addrs, networks.nets['bitcoincash']) + self.addr_test(self.bch_addrs2, networks.nets['bitcoincash'], + 'bitcoincash:') + + def test_tbch_addresses(self): + self.addr_test(self.tbch_addrs, networks.nets['bitcoincash_testnet']) + self.addr_test(self.tbch_addrs2, networks.nets['bitcoincash_testnet'], + 'bchtest:') diff --git a/p2pool/test/util/test_cash_addr.py b/p2pool/test/util/test_cash_addr.py new file mode 100644 index 00000000..73f2230b --- /dev/null +++ b/p2pool/test/util/test_cash_addr.py @@ -0,0 +1,404 @@ +# Copyright (c) 2018 Robert LeBlanc +# Copyright (c) 2017 Pieter Wuille +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import unittest +import mock + +from p2pool.util import cash_addr +from p2pool.bitcoin import data + +class UnitTest(unittest.TestCase): + + def setUp(self): + self.longMessage = True + + def test_polymod(self): + data = [([2, 9, 20, 3, 15, 9, 14, 3, 1, 19, 8, 0, 0, 2, 2, 6, 16, 14, 0, + 31, 14, 2, 25, 30, 24, 15, 8, 18, 7, 27, 14, 25, 31, 7, 31, + 21, 0, 17, 14, 0, 22, 15, 22, 3, 31, 28, 30, 18, 24, 23, 7, 7, + 8, 12], 0), + ([2, 9, 20, 3, 15, 9, 14, 3, 1, 19, 8, 0, 0, 2, 2, 6, 16, 14, 0, + 31, 14, 2, 25, 30, 24, 15, 8, 18, 7, 27, 14, 25, 31, 7, 31, + 21, 0, 17, 14, 0, 22, 15, 22, 3, 31, 28, 0, 0, 0, 0, 0, 0, 0, + 0], 1050949164300), + ([2, 9, 20, 3, 15, 9, 14, 3, 1, 19, 8, 0, 1, 0, 22, 23, 5, 29, + 23, 9, 18, 15, 26, 5, 0, 12, 7, 31, 26, 25, 4, 16, 4, 28, 9, + 29, 2, 1, 25, 21, 9, 13, 18, 0, 17, 28, 21, 23, 19, 29, 17, + 10, 17, 18], 0), + ([2, 9, 20, 3, 15, 9, 14, 3, 1, 19, 8, 0, 1, 0, 22, 23, 5, 29, + 23, 9, 18, 15, 26, 5, 0, 12, 7, 31, 26, 25, 4, 16, 4, 28, 9, + 29, 2, 1, 25, 21, 9, 13, 18, 0, 17, 28, 0, 0, 0, 0, 0, 0, 0, + 0], 746919078450) + ] + for d, r in data: + self.assertEqual(r, cash_addr.polymod(d)) + + def test_expand_prefix(self): + data = [('bitcoincash', [2, 9, 20, 3, 15, 9, 14, 3, 1, 19, 8, 0]), + ('bchtest', [2, 3, 8, 20, 5, 19, 20, 0]), + ('perf', [16, 5, 18, 6, 0]), + ('bc', [2, 3, 0]), + ] + for d, r in data: + self.assertEqual(r, cash_addr.expand_prefix(d), + "Prefix %s failed." % d) + + @mock.patch.object(cash_addr, 'expand_prefix', spec=cash_addr.expand_prefix) + @mock.patch.object(cash_addr, 'polymod', spec=cash_addr.polymod) + def test_verify_checksum(self, mp, mep): + mep.return_value = ['foo'] + mp.return_value = 1 + data = [('bitcoincash', [0, 14, 20, 15, 7, 13, 26, 0, 25, 18, 6, 11, 13, + 8, 21, 4, 20, 3, 17, 2, 29, 3, 12, 29, 3, 4, + 15, 24, 20, 6, 14, 30, 22, 12, 7, 9, 17, 11, 21]), + ('bchtest', [0, 30, 18, 12, 16, 17, 29, 3, 7, 15, 6, 6, 25, 6, + 25, 13, 22, 3, 25, 23, 4, 29, 26, 9, 26, 18, 31, 0, + 0, 27, 14, 13, 1, 14, 7, 1, 6, 3, 0]), + ] + self.assertFalse(cash_addr.verify_checksum(*data[0])) + mep.assert_called_once_with(data[0][0]) + mp.assert_called_once_with(['foo'] + data[0][1]) + mep.reset_mock() + mp.reset_mock() + mep.return_value = ['bar'] + mp.return_value = 0 + self.assertTrue(cash_addr.verify_checksum(*data[1])) + mep.assert_called_once_with(data[1][0]) + mp.assert_called_once_with(['bar'] + data[1][1]) + mp.return_value = 2 + self.assertFalse(cash_addr.verify_checksum(*data[1])) + + @mock.patch.object(cash_addr, 'expand_prefix', spec=cash_addr.expand_prefix) + @mock.patch.object(cash_addr, 'polymod', spec=cash_addr.polymod) + def test_create_checksum(self, mp, mep): + mep.return_value = ['foo'] + data = [('bitcoincash', 1, [0, 0, 0, 0, 0, 0, 0, 1]), + ('bchtest', 0, [0, 0, 0, 0, 0, 0, 0, 0]), + ('perf', 410305908, [0, 0, 12, 7, 9, 17, 11, 20]), + ('junk', 309275181844, [9, 0, 1, 3, 25, 16, 24, 20]), + ] + for p, d, r in data: + mep.reset_mock() + mp.reset_mock() + mp.return_value = d + self.assertListEqual(r, cash_addr.create_checksum(p, ['bar']), + "%s, %s failed." % (p, d)) + mep.assert_called_once_with(p) + mp.assert_called_once_with(['foo'] + ['bar'] + [0] * 8) + + @mock.patch.object(cash_addr, 'create_checksum', spec=cash_addr.create_checksum) + def test_assemble(self, mcc): + data = [('bitcoincash', [0, 2, 2, 6, 16, 14, 0, 31, 14, 2, 25, 30, 24, + 15, 8, 18, 7, 27, 14, 25, 31, 7, 31, 21, 0, 17, + 14, 0, 22, 15, 22, 3, 31, 28], + [30, 18, 24, 23, 7, 7, 8, 12], + 'bitcoincash:qzzxswqlwze7c0gj8mwel8l4q3wqk0krlu7jch88gv', + ), + ('bitcoincash', [1, 0, 22, 23, 5, 29, 23, 9, 18, 15, 26, 5, 0, + 12, 7, 31, 26, 25, 4, 16, 4, 28, 9, 29, 2, 1, + 25, 21, 9, 13, 18, 0, 17, 28], + [21, 23, 19, 29, 17, 10, 17, 18], + 'bitcoincash:pqkh9ahfj069qv8l6eysyufazpe4fdjq3u4hna323j', + ), + ] + for p, d, c, r in data: + mcc.reset_mock() + mcc.return_value = c + self.assertEqual(r, cash_addr.assemble(p, d)) + mcc.assert_called_once_with(p, d) + + @mock.patch.object(cash_addr, 'convertbits', spec=cash_addr.convertbits) + def test_valid_version(self, mcb): + mcb.return_value = None + self.assertFalse(cash_addr.valid_version([1, 2, 3, 4])) + mcb.reset_mock() + mcb.return_value = [1<<8, 0] + self.assertFalse(cash_addr.valid_version([1, 2, 3, 4])) + mcb.assert_called_once_with([1, 2, 3, 4], 5, 8, False) + for ver in range(1<<4 - 1): + for i in range(100): + mcb.return_value = [ver] + [0] * i + if ver == 0 and i == 20: + self.assertTrue(cash_addr.valid_version([0]), + "Failed for version %s and %d bytes." % (ver, i)) + elif ver == 1 and i == 24: + self.assertTrue(cash_addr.valid_version([0]), + "Failed for version %s and %d bytes." % (ver, i)) + elif ver == 2 and i == 28: + self.assertTrue(cash_addr.valid_version([0]), + "Failed for version %s and %d bytes." % (ver, i)) + elif ver == 3 and i == 32: + self.assertTrue(cash_addr.valid_version([0]), + "Failed for version %s and %d bytes." % (ver, i)) + elif ver == 4 and i == 40: + self.assertTrue(cash_addr.valid_version([0]), + "Failed for version %s and %d bytes." % (ver, i)) + elif ver == 5 and i == 48: + self.assertTrue(cash_addr.valid_version([0]), + "Failed for version %s and %d bytes." % (ver, i)) + elif ver == 6 and i == 56: + self.assertTrue(cash_addr.valid_version([0]), + "Failed for version %s and %d bytes." % (ver, i)) + elif ver == 7 and i == 64: + self.assertTrue(cash_addr.valid_version([0]), + "Failed for version %s and %d bytes." % (ver, i)) + else: + self.assertFalse(cash_addr.valid_version([0]), + "Failed for version %s and %d bytes." % (ver, i)) + + @mock.patch.object(cash_addr, 'valid_version', spec=cash_addr.valid_version) + @mock.patch.object(cash_addr, 'verify_checksum', spec=cash_addr.verify_checksum) + def test_disassemble(self, mvc, mvv): + mvv.return_value = False + def_prefix = 'bitcoincash' + # Test non-numeric and non-alpha range + for i in range(33): + self.assertTupleEqual((None, None), + cash_addr.disassemble(chr(i), def_prefix)) + for i in range(127, 256): + self.assertTupleEqual((None, None), + cash_addr.disassemble(chr(i), def_prefix)) + # Test mixed case + self.assertTupleEqual((None, None), + cash_addr.disassemble('acDefghjk', def_prefix)) + # Test address too short + self.assertTupleEqual((None, None), + cash_addr.disassemble('bitcoincash:acdefghj', def_prefix)) + # Test address too long + addr = 'bitcoincash:' + 'a' * 113 + self.assertTupleEqual((None, None), + cash_addr.disassemble(addr, def_prefix)) + # Test illegal characters + addr = 'bitcoincash:bcdefghjklm' + self.assertTupleEqual((None, None), + cash_addr.disassemble(addr, def_prefix)) + addr = 'bitcoincash:acdefghijklm' + self.assertTupleEqual((None, None), + cash_addr.disassemble(addr, def_prefix)) + addr = 'bitcoincash:acdefghijklm1' + self.assertTupleEqual((None, None), + cash_addr.disassemble(addr, def_prefix)) + # Check that bech32_verify_checksum hasn't been called. + self.assertEqual(0, mvc.call_count) + addr = 'bitcoincash:pqkh9ahfj069qv8l6eysyufazpe4fdjq3u4hna323j' + # Test that the header check failed + self.assertTupleEqual((None, None), + cash_addr.disassemble(addr, def_prefix)) + mvv.return_value = True + # Test that the checksum failed + mvc.return_value = 0 + mvv.reset_mock() + data = [1, 0, 22, 23, 5, 29, 23, 9, 18, 15, 26, 5, 0, 12, 7, 31, 26, 25, + 4, 16, 4, 28, 9, 29, 2, 1, 25, 21, 9, 13, 18, 0, 17, 28, 21, 23, + 19, 29, 17, 10, 17, 18] + self.assertTupleEqual((None, None), + cash_addr.disassemble(addr, def_prefix)) + mvc.assert_called_once_with('bitcoincash', data) + mvv.assert_called_once_with(data[:-8]) + mvc.reset_mock() + # Test address without prefix + srt_addr = addr[12:] + self.assertTupleEqual((None, None), + cash_addr.disassemble(srt_addr, def_prefix)) + mvc.assert_called_once_with('bitcoincash', data) + mvc.return_value = 1 + self.assertTupleEqual(('bitcoincash', data[:-8]), + cash_addr.disassemble(addr, def_prefix)) + # Test with different prefix + mvc.reset_mock() + self.assertTupleEqual(('bchtest', data[:-8]), + cash_addr.disassemble(srt_addr, 'bchtest')) + mvc.assert_called_once_with('bchtest', data) + + @mock.patch.object(cash_addr, 'disassemble', spec=cash_addr.disassemble) + @mock.patch.object(cash_addr, 'convertbits', spec=cash_addr.convertbits) + def test_decode(self, mcb, md): + data = [0, 1, 2, 3, 4, 5] + md.return_value = ('bchtest', data) + addr = 'bitcoincash:qzzxswqlwze7c0gj8mwel8l4q3wqk0krlu7jch88gv' + pfix = 'bitcoincash' + # Test wrong prefix + self.assertTupleEqual((None, None), cash_addr.decode(pfix, addr)) + md.assert_called_once_with(addr, pfix) + md.reset_mock() + self.assertTupleEqual((None, None), cash_addr.decode(pfix, addr[12:])) + md.assert_called_once_with(addr[12:], pfix) + self.assertEqual(0, mcb.call_count) + # Test bad convertbits + mcb.return_value = None + md.return_value = (pfix, data) + self.assertTupleEqual((None, None), cash_addr.decode(pfix, addr)) + mcb.assert_called_once_with(data, 5, 8, False) + mcb.return_value = [] + self.assertTupleEqual((None, None), cash_addr.decode(pfix, addr)) + # Test version + mcb.return_value = [0, 5, 4, 3] + self.assertTupleEqual((0, [5, 4, 3]), cash_addr.decode(pfix, addr)) + mcb.return_value = [8, 1, 2, 3] + self.assertTupleEqual((1, [1, 2, 3]), cash_addr.decode(pfix, addr)) + + @mock.patch.object(cash_addr, 'convertbits', spec=cash_addr.convertbits) + @mock.patch.object(cash_addr, 'assemble', spec=cash_addr.assemble) + @mock.patch.object(cash_addr, 'decode', spec=cash_addr.decode) + def test_encode(self, md, mba, mcb): + mcb.return_value = ['foo'] + mba.return_value = 'bar' + md.return_value = (None, None) + # Test for invalid data lengths. + valid_lengths = [20, 24, 28, 32, 40, 48, 56, 64] + data = [] + self.assertEqual(None, cash_addr.encode('bchtest', 0, data)) + for i in range(1, 129): + data.append(i) + if i in valid_lengths: + continue + self.assertEqual(None, cash_addr.encode('bchtest', 0, data)) + # Test unsupported versions. + data = [x for x in range(20)] + for i in range(2, 15): + self.assertEqual(None, cash_addr.encode('bchtest', i, [0])) + self.assertEqual(None, cash_addr.encode('bitcoincash', 0, data)) + mcb.assert_called_once_with([0] + data, 8, 5) + mba.assert_called_once_with('bitcoincash', ['foo']) + md.assert_called_once_with('bitcoincash', 'bar') + mcb.reset_mock() + mba.reset_mock() + md.reset_mock() + md.return_value = (3, [6, 7, 8]) + self.assertEqual('bar', cash_addr.encode('bchtest', 1, data)) + mcb.assert_called_once_with([8] + data, 8, 5) + mba.assert_called_once_with('bchtest', ['foo']) + md.assert_called_once_with('bchtest', 'bar') + mcb.reset_mock() + self.assertEqual('bar', cash_addr.encode('bchtest', 15, data)) + mcb.assert_called_once_with([120] + data, 8, 5) + for i in range(8): + mcb.reset_mock() + data = [x for x in range(valid_lengths[i])] + self.assertEqual('bar', cash_addr.encode('bchtest', 0, data)) + mcb.assert_called_once_with([i] + data, 8, 5) + +class IntegrationTest(unittest.TestCase): + OLD_NEW_ADDRESS = [ + ('1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu', + 'bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a'), + ('1KXrWXciRDZUpQwQmuM1DbwsKDLYAYsVLR', + 'bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy'), + ('16w1D5WRVKJuZUsSRzdLp9w3YGcgoxDXb', + 'bitcoincash:qqq3728yw0y47sqn6l2na30mcw6zm78dzqre909m2r'), + ('3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC', + 'bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq'), + ('3LDsS579y7sruadqu11beEJoTjdFiFCdX4', + 'bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e'), + ('31nwvkZwyPdgzjBJZXfDmSWsC4ZLKpYyUw', + 'bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37'), + ] + + VALID_ADDRESS = [ + ['bitcoincash:qr6m7j9njldwwzlg9v7v53unlr4jkmx6eylep8ekg2', 'F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9'], + ['bchtest:pr6m7j9njldwwzlg9v7v53unlr4jkmx6eyvwc0uz5t', 'F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9'], + ['pref:pr6m7j9njldwwzlg9v7v53unlr4jkmx6ey65nvtks5', 'F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9'], + ['prefix:0r6m7j9njldwwzlg9v7v53unlr4jkmx6ey3qnjwsrf', 'F5BF48B397DAE70BE82B3CCA4793F8EB2B6CDAC9'], + ['bitcoincash:q9adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2ws4mr9g0', '7ADBF6C17084BC86C1706827B41A56F5CA32865925E946EA'], + ['bchtest:p9adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2u94tsynr', '7ADBF6C17084BC86C1706827B41A56F5CA32865925E946EA'], + ['pref:p9adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2khlwwk5v', '7ADBF6C17084BC86C1706827B41A56F5CA32865925E946EA'], + ['prefix:09adhakpwzztepkpwp5z0dq62m6u5v5xtyj7j3h2p29kc2lp', '7ADBF6C17084BC86C1706827B41A56F5CA32865925E946EA'], + ['bitcoincash:qgagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkcw59jxxuz', '3A84F9CF51AAE98A3BB3A78BF16A6183790B18719126325BFC0C075B'], + ['bchtest:pgagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkcvs7md7wt', '3A84F9CF51AAE98A3BB3A78BF16A6183790B18719126325BFC0C075B'], + ['pref:pgagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkcrsr6gzkn', '3A84F9CF51AAE98A3BB3A78BF16A6183790B18719126325BFC0C075B'], + ['prefix:0gagf7w02x4wnz3mkwnchut2vxphjzccwxgjvvjmlsxqwkc5djw8s9g', '3A84F9CF51AAE98A3BB3A78BF16A6183790B18719126325BFC0C075B'], + ['bitcoincash:qvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq5nlegake', '3173EF6623C6B48FFD1A3DCC0CC6489B0A07BB47A37F47CFEF4FE69DE825C060'], + ['bchtest:pvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq7fqng6m6', '3173EF6623C6B48FFD1A3DCC0CC6489B0A07BB47A37F47CFEF4FE69DE825C060'], + ['pref:pvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq4k9m7qf9', '3173EF6623C6B48FFD1A3DCC0CC6489B0A07BB47A37F47CFEF4FE69DE825C060'], + ['prefix:0vch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxqsh6jgp6w', '3173EF6623C6B48FFD1A3DCC0CC6489B0A07BB47A37F47CFEF4FE69DE825C060'], + ['bitcoincash:qnq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklv39gr3uvz', 'C07138323E00FA4FC122D3B85B9628EA810B3F381706385E289B0B25631197D194B5C238BEB136FB'], + ['bchtest:pnq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklvmgm6ynej', 'C07138323E00FA4FC122D3B85B9628EA810B3F381706385E289B0B25631197D194B5C238BEB136FB'], + ['pref:pnq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklv0vx5z0w3', 'C07138323E00FA4FC122D3B85B9628EA810B3F381706385E289B0B25631197D194B5C238BEB136FB'], + ['prefix:0nq8zwpj8cq05n7pytfmskuk9r4gzzel8qtsvwz79zdskftrzxtar994cgutavfklvwsvctzqy', 'C07138323E00FA4FC122D3B85B9628EA810B3F381706385E289B0B25631197D194B5C238BEB136FB'], + ['bitcoincash:qh3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqex2w82sl', 'E361CA9A7F99107C17A622E047E3745D3E19CF804ED63C5C40C6BA763696B98241223D8CE62AD48D863F4CB18C930E4C'], + ['bchtest:ph3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqnzf7mt6x', 'E361CA9A7F99107C17A622E047E3745D3E19CF804ED63C5C40C6BA763696B98241223D8CE62AD48D863F4CB18C930E4C'], + ['pref:ph3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqjntdfcwg', 'E361CA9A7F99107C17A622E047E3745D3E19CF804ED63C5C40C6BA763696B98241223D8CE62AD48D863F4CB18C930E4C'], + ['prefix:0h3krj5607v3qlqh5c3wq3lrw3wnuxw0sp8dv0zugrrt5a3kj6ucysfz8kxwv2k53krr7n933jfsunqakcssnmn', 'E361CA9A7F99107C17A622E047E3745D3E19CF804ED63C5C40C6BA763696B98241223D8CE62AD48D863F4CB18C930E4C'], + ['bitcoincash:qmvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqscw8jd03f', 'D9FA7C4C6EF56DC4FF423BAAE6D495DBFF663D034A72D1DC7D52CBFE7D1E6858F9D523AC0A7A5C34077638E4DD1A701BD017842789982041'], + ['bchtest:pmvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqs6kgdsg2g', 'D9FA7C4C6EF56DC4FF423BAAE6D495DBFF663D034A72D1DC7D52CBFE7D1E6858F9D523AC0A7A5C34077638E4DD1A701BD017842789982041'], + ['pref:pmvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqsammyqffl', 'D9FA7C4C6EF56DC4FF423BAAE6D495DBFF663D034A72D1DC7D52CBFE7D1E6858F9D523AC0A7A5C34077638E4DD1A701BD017842789982041'], + ['prefix:0mvl5lzvdm6km38lgga64ek5jhdl7e3aqd9895wu04fvhlnare5937w4ywkq57juxsrhvw8ym5d8qx7sz7zz0zvcypqsgjrqpnw8', 'D9FA7C4C6EF56DC4FF423BAAE6D495DBFF663D034A72D1DC7D52CBFE7D1E6858F9D523AC0A7A5C34077638E4DD1A701BD017842789982041'], + ['bitcoincash:qlg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96mtky5sv5w', 'D0F346310D5513D9E01E299978624BA883E6BDA8F4C60883C10F28C2967E67EC77ECC7EEEAEAFC6DA89FAD72D11AC961E164678B868AEEEC5F2C1DA08884175B'], + ['bchtest:plg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96mc773cwez', 'D0F346310D5513D9E01E299978624BA883E6BDA8F4C60883C10F28C2967E67EC77ECC7EEEAEAFC6DA89FAD72D11AC961E164678B868AEEEC5F2C1DA08884175B'], + ['pref:plg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96mg7pj3lh8', 'D0F346310D5513D9E01E299978624BA883E6BDA8F4C60883C10F28C2967E67EC77ECC7EEEAEAFC6DA89FAD72D11AC961E164678B868AEEEC5F2C1DA08884175B'], + ['prefix:0lg0x333p4238k0qrc5ej7rzfw5g8e4a4r6vvzyrcy8j3s5k0en7calvclhw46hudk5flttj6ydvjc0pv3nchp52amk97tqa5zygg96ms92w6845', 'D0F346310D5513D9E01E299978624BA883E6BDA8F4C60883C10F28C2967E67EC77ECC7EEEAEAFC6DA89FAD72D11AC961E164678B868AEEEC5F2C1DA08884175B'], + ] + + INVALID_ADDRESS = [ + 'bitcoincash1qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a', + 'bitcoincash:qr95sy3j9xwd2Ap32xkykttr4cvcu7as4y0qverfuy', + 'bitcoincash:qqq3728yw0y57sqn6l2na30mcw6zm78dzqre909m2r', + 'bitcoincash:ppm2qsznhks2z7629mms6s4cwef74vcwvn0h829pq', + 'bitcoincash:pr95sy3j9xwd2ap32xkykettr4cvcu7as4yc93ky28e', + ] + + def setUp(self): + self.longMessage = True + + @staticmethod + def get_prefix(addr): + try: + return ''.join(addr[:addr.find(':')]).lower() + except TypeError: + return 'bitcoincash' + + @staticmethod + def to_byte_array(data): + return [ord(x) for x in data] + + def test_old_and_new_addresses_match(self): + for oaddr, naddr in self.OLD_NEW_ADDRESS: + # Base58 has 4 bytes of checksum + odata = self.to_byte_array(data.base58_decode(oaddr))[:-4] + for prefix in [True, False]: + addr = naddr if prefix else naddr[12:] + # cashaddr.decode already removes the 5 bytes of checksum + nver, ndata = cash_addr.decode('bitcoincash', naddr) + self.assertTrue(odata[0] in [0, 5], + "Old address %s is not a valid version" % oaddr) + self.assertTrue(ndata[0] & 8 in [0, 8], + "New address %s in not a valid type" % naddr) + if odata[0] == 0: + self.assertEqual(0, nver, "Bad version for %s" % naddr) + elif odata[0] == 5: + self.assertEqual(1, nver, "Bad version for %s" % naddr) + self.assertListEqual(odata[1:], ndata, + "Old address %s and new address %s don't have the same payload." + % (oaddr, naddr)) + + def test_valid_addresses(self): + for addr, script in self.VALID_ADDRESS: + prefix = self.get_prefix(addr) + ver, data = cash_addr.decode(prefix, addr) + self.assertEqual(addr.lower(), + cash_addr.encode(prefix, ver, data), + "Address %s failed." % addr) + + def test_invalid_addresess(self): + for addr in self.INVALID_ADDRESS: + prefix = self.get_prefix(addr) + self.assertEqual((None, None), cash_addr.decode(prefix, addr), + "Address %s failed." % addr) diff --git a/p2pool/test/util/test_math.py b/p2pool/test/util/test_math.py index 226b8e5a..a37e5696 100644 --- a/p2pool/test/util/test_math.py +++ b/p2pool/test/util/test_math.py @@ -36,3 +36,22 @@ def test_binom(self): for x in xrange(n + 1): left, right = math.binomial_conf_interval(x, n) assert 0 <= left <= x/n <= right <= 1, (left, right, x, n) + + def test_convertbits(self): + self.assertListEqual([0], math.convertbits([0], 8, 16, True)) + self.assertEqual(None, math.convertbits([0], 8, 16, False)) + self.assertListEqual([0], math.convertbits([0, 0], 8, 16, False)) + self.assertListEqual([0, 0], math.convertbits([0], 16, 8, False)) + self.assertListEqual([255], math.convertbits([0, 255], 8, 16, False)) + self.assertListEqual([65280], math.convertbits([255], 8, 16, True)) + self.assertListEqual([65535], math.convertbits([255, 255], 8, 16, True)) + self.assertListEqual([0, 255], math.convertbits([255], 16, 8, False)) + self.assertListEqual([255, 0], math.convertbits([65280], 16, 8, False)) + self.assertListEqual([255, 255], math.convertbits([65535], 16, 8, False)) + self.assertListEqual([4, 11, 13, 2, 16], math.convertbits([34, 218, 40], 8, 5, True)) + self.assertListEqual([34, 218, 40, 0], math.convertbits([4, 11, 13, 2, 16], 5, 8, True)) + self.assertListEqual([34, 218, 40], math.convertbits([4, 11, 13, 2, 16], 5, 8, False)) + self.assertListEqual([3, 82, 34, 218, 40], math.convertbits([0, 13, 9, 2, 5, 22, 17, 8], 5, 8, True)) + self.assertListEqual([3, 82, 34, 218, 40], math.convertbits([0, 13, 9, 2, 5, 22, 17, 8], 5, 8, False)) + self.assertListEqual([0, 13, 9, 2, 5, 22, 17, 8], math.convertbits([3, 82, 34, 218, 40], 8, 5, True)) + self.assertListEqual([0, 13, 9, 2, 5, 22, 17, 8], math.convertbits([3, 82, 34, 218, 40], 8, 5, False)) diff --git a/p2pool/test/util/test_segwit_addr.py b/p2pool/test/util/test_segwit_addr.py new file mode 100644 index 00000000..e17ace94 --- /dev/null +++ b/p2pool/test/util/test_segwit_addr.py @@ -0,0 +1,267 @@ +# Copyright (c) 2018 Robert LeBlanc +# Copyright (c) 2017 Pieter Wuille +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import unittest +import mock + +from p2pool.util import segwit_addr + +class UnitTest(unittest.TestCase): + + def setUp(self): + self.longMessage = True + + def test_bech32_polymod(self): + data = [([3, 3, 0, 2, 3, 0, 14, 20, 15, 7, 13, 26, 0, 25, 18, 6, 11, 13, + 8, 21, 4, 20, 3, 17, 2, 29, 3, 12, 29, 3, 4, 15, 24, 20, 6, 14, + 30, 22, 12, 7, 9, 17, 11, 21], 1), + ([3, 3, 3, 3, 0, 20, 12, 20, 3, 0, 30, 18, 12, 16, 17, 29, 3, 7, + 15, 6, 6, 25, 6, 25, 13, 22, 3, 25, 23, 4, 29, 26, 9, 26, 18, + 31, 0, 0, 27, 14, 13, 1, 0, 0, 0, 0, 0, 0], 477141089), + ([3, 3, 0, 2, 3, 0, 14, 20, 15, 7, 13, 26, 0, 25, 18, 6, 11, 13, + 8, 21, 4, 20, 3, 17, 2, 29, 3, 12,29, 3, 4, 15, 24, 20, 6, 14, + 30, 22, 12, 7, 9, 17, 11, 21], 1), + ([3, 3, 0, 2, 3, 0, 14, 20, 15, 7, 13, 26, 0, 25, 18, 6, 11, 13, + 8, 21, 4, 20, 3, 17, 2, 29, 3, 12,29, 3, 4, 15, 24, 20, 6, 14, + 30, 22, 0, 0, 0, 0, 0, 0], 410305908), + ] + for d, r in data: + self.assertEqual(r, segwit_addr.bech32_polymod(d)) + + def test_bech32_hrp_expand(self): + data = [('bc', [3, 3, 0, 2, 3]), + ('tltc', [3, 3, 3, 3, 0, 20, 12, 20, 3]), + ] + for d, r in data: + self.assertEqual(r, segwit_addr.bech32_hrp_expand(d), + "HRP %s failed." % d) + + @mock.patch.object(segwit_addr, 'bech32_hrp_expand', + spec=segwit_addr.bech32_hrp_expand) + @mock.patch.object(segwit_addr, 'bech32_polymod', + spec=segwit_addr.bech32_polymod) + def test_bech_32_verify_checksum(self, mbp, mbhe): + mbhe.return_value = ['foo'] + mbp.return_value = 0 + data = [('bc', [0, 14, 20, 15, 7, 13, 26, 0, 25, 18, 6, 11, 13, 8, 21, + 4, 20, 3, 17, 2, 29, 3, 12, 29, 3, 4, 15, 24, 20, 6, 14, + 30, 22, 12, 7, 9, 17, 11, 21]), + ('ltc', [0, 30, 18, 12, 16, 17, 29, 3, 7, 15, 6, 6, 25, 6, 25, + 13, 22, 3, 25, 23, 4, 29, 26, 9, 26, 18, 31, 0, 0, 27, + 14, 13, 1, 14, 7, 1, 6, 3, 0]), + ] + self.assertFalse(segwit_addr.bech32_verify_checksum(*data[0])) + mbhe.assert_called_once_with(data[0][0]) + mbp.assert_called_once_with(['foo'] + data[0][1]) + mbhe.reset_mock() + mbp.reset_mock() + mbhe.return_value = ['bar'] + mbp.return_value = 1 + self.assertTrue(segwit_addr.bech32_verify_checksum(*data[1])) + mbhe.assert_called_once_with(data[1][0]) + mbp.assert_called_once_with(['bar'] + data[1][1]) + mbp.return_value = 2 + self.assertFalse(segwit_addr.bech32_verify_checksum(*data[1])) + + @mock.patch.object(segwit_addr, 'bech32_hrp_expand', + spec=segwit_addr.bech32_hrp_expand) + @mock.patch.object(segwit_addr, 'bech32_polymod', + spec=segwit_addr.bech32_polymod) + def test_bech32_create_checksum(self, mbp, mbhe): + mbhe.return_value = ['foo'] + data = [('bc', 0, [0, 0, 0, 0, 0, 1]), + ('tb', 1, [0, 0, 0, 0, 0, 0]), + ('ltc', 410305908, [12, 7, 9, 17, 11, 21]), + ('tltc', 477141089, [14, 7, 1, 6, 3, 0]), + ] + for h, d, r in data: + mbhe.reset_mock() + mbp.reset_mock() + mbp.return_value = d + self.assertListEqual(r, segwit_addr.bech32_create_checksum(h, ['bar'])) + mbhe.assert_called_once_with(h) + mbp.assert_called_once_with(['foo'] + ['bar'] + [0] * 6) + + @mock.patch.object(segwit_addr, 'bech32_create_checksum', + spec=segwit_addr.bech32_create_checksum) + def test_bech32_encode(self, mbcc): + data = [('bc', [0, 14, 20, 15, 7, 13, 26, 0, 25, 18, 6, 11, 13, 8, 21, + 4, 20, 3, 17, 2, 29, 3, 12, 29, 3, 4, 15, 24, 20, 6, 14, + 30, 22], + [12, 7, 9, 17, 11, 21], + 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4'), + ('tltc', [0, 30, 18, 12, 16, 17, 29, 3, 7, 15, 6, 6, 25, 6, 25, + 13, 22, 3, 25, 23, 4, 29, 26, 9, 26, 18, 31, 0, 0, 27, + 14, 13, 1], + [14, 7, 1, 6, 3, 0], + 'tltc1q7jvs3ar80xxexedkrehya6f6jlqqmwdpw8pxrq'), + ] + for h, d, c, r in data: + mbcc.reset_mock() + mbcc.return_value = c + self.assertEqual(r, segwit_addr.bech32_encode(h, d)) + mbcc.assert_called_once_with(h, d) + + @mock.patch.object(segwit_addr, 'bech32_verify_checksum', + spec=segwit_addr.bech32_verify_checksum) + def test_bech32_decode(self, mvc): + # Test non-numeric and non-alpha range + for i in range(33): + self.assertTupleEqual((None, None), segwit_addr.bech32_decode(chr(i))) + for i in range(127, 256): + self.assertTupleEqual((None, None), segwit_addr.bech32_decode(chr(i))) + # Test mixed case + self.assertTupleEqual((None, None), segwit_addr.bech32_decode('abcDef')) + # Test missing HRP + self.assertTupleEqual((None, None), segwit_addr.bech32_decode('abcdef')) + # Test address too short + self.assertTupleEqual((None, None), segwit_addr.bech32_decode('bc1ab')) + # Test address too long + addr = 'bc1acdefghjklmnpqrstuvwxyz234567890acdefghjklmnpqrstuvwxyz234567890acdefghjklmnpqrstuvwxyz2' + self.assertTupleEqual((None, None), segwit_addr.bech32_decode(addr)) + # Test illegal characters + addr = 'bc1bcdefghjklm' + self.assertTupleEqual((None, None), segwit_addr.bech32_decode(addr)) + addr = 'bc1acdefghijklm' + self.assertTupleEqual((None, None), segwit_addr.bech32_decode(addr)) + addr = 'bc1acdefghijklm1' + self.assertTupleEqual((None, None), segwit_addr.bech32_decode(addr)) + # Check that bech32_verify_checksum hasn't been called. + self.assertEqual(0, mvc.call_count) + # Test that the checksum failed + mvc.return_value = 0 + addr = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4' + data = [0, 14, 20, 15, 7, 13, 26, 0, 25, 18, 6, 11, 13, 8, 21, 4, 20, 3, + 17, 2, 29, 3, 12, 29, 3, 4, 15, 24, 20, 6, 14, 30, 22, 12, 7, 9, + 17, 11, 21] + self.assertTupleEqual((None, None), segwit_addr.bech32_decode(addr)) + mvc.assert_called_once_with('bc', data) + mvc.return_value = 1 + self.assertTupleEqual(('bc', data[:-6]), segwit_addr.bech32_decode(addr)) + + @mock.patch.object(segwit_addr, 'bech32_decode', + spec=segwit_addr.bech32_decode) + @mock.patch.object(segwit_addr, 'convertbits', spec=segwit_addr.convertbits) + def test_decode(self, mcb, mbd): + self.longMessage = True + data = [0, 1, 2, 3, 4, 5] + mbd.return_value = ('bc', data) + addr = 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4' + # Test wrong hrp + self.assertTupleEqual((None, None), segwit_addr.decode('tltc', addr)) + self.assertEqual(0, mcb.call_count) + mbd.assert_called_once_with(addr) + # Test bad convertbits + mcb.return_value = None + self.assertTupleEqual((None, None), segwit_addr.decode('bc', addr)) + mcb.assert_called_once_with(data[1:], 5, 8, False) + mcb.return_value = [0] + self.assertTupleEqual((None, None), segwit_addr.decode('bc', addr)) + mcb.return_value = [0] * 41 + self.assertTupleEqual((None, None), segwit_addr.decode('bc', addr)) + # Test bad version + mcb.return_value = [17] + [0] * 20 + self.assertTupleEqual((None, None), segwit_addr.decode('bc', addr)) + # Version 0: Test bad lengths and correct returns + ret = [] + for i in range (1, 42): + ret.append(i) + mcb.return_value = ret + if i == 20 or i == 32: + self.assertTupleEqual((0, ret), + segwit_addr.decode('bc', addr), + "Failed with length %d" % i) + else: + self.assertTupleEqual((None, None), + segwit_addr.decode('bc', addr), + "Failed with length %d" % i) + + @mock.patch.object(segwit_addr, 'convertbits', + spec=segwit_addr.convertbits) + @mock.patch.object(segwit_addr, 'bech32_encode', + spec=segwit_addr.bech32_encode) + @mock.patch.object(segwit_addr, 'decode', + spec=segwit_addr.decode) + def test_encode(self, md, mbe, mcb): + mcb.return_value = ['foo'] + mbe.return_value = 'bar' + md.return_value = (None, None) + self.assertEqual(None, segwit_addr.encode('bc', 5, [0, 1, 2])) + mcb.assert_called_once_with([0, 1, 2], 8, 5) + mbe.assert_called_once_with('bc', [5, 'foo']) + md.assert_called_once_with('bc', 'bar') + mcb.reset_mock() + mbe.reset_mock() + md.reset_mock() + md.return_value = (3, [6, 7, 8]) + self.assertEqual('bar', segwit_addr.encode('ltc', 9, [3, 2, 1])) + mcb.assert_called_once_with([3, 2, 1], 8, 5) + mbe.assert_called_once_with('ltc', [9, 'foo']) + md.assert_called_once_with('ltc', 'bar') + +class IntegrationTest(unittest.TestCase): + VALID_ADDRESS = [ + ["BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", + "0014751e76e8199196d454941c45d1b3a323f1433bd6"], + ["tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", + "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262"], + ["bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx", + "5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6"], + ["BC1SW50QA3JX3S", "6002751e"], + ["bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", + "5210751e76e8199196d454941c45d1b3a323"], + ["tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy", + "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433"], + ] + + INVALID_ADDRESS = [ + "tc1qw508d6qejxtdg4y5r3zarvbry0c5xw7kg3g4ty", + "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", + "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2", + "bc1rw5uspcuh", + "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90", + "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P", + "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7", + "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du", + "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv", + "bc1gmk9yu", + ] + + def setUp(self): + self.longMessage = True + + @staticmethod + def get_hrp(addr): + return ''.join(addr[:addr.find('1')]).lower() + + def test_valid_addresses(self): + for addr, script in self.VALID_ADDRESS: + hrp = self.get_hrp(addr) + witver, witprog = segwit_addr.decode(hrp, addr) + self.assertEqual(addr.lower(), + segwit_addr.encode(hrp, witver, witprog), + "Address %s failed." % addr) + + def test_invalid_addresess(self): + for addr in self.INVALID_ADDRESS: + hrp = self.get_hrp(addr) + self.assertEqual((None, None), segwit_addr.decode(hrp, addr), + "Address %s failed." % addr) diff --git a/p2pool/util/cash_addr.py b/p2pool/util/cash_addr.py new file mode 100644 index 00000000..3ba96e10 --- /dev/null +++ b/p2pool/util/cash_addr.py @@ -0,0 +1,178 @@ +# Copyright (c) 2018 Robert LeBlanc +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +from math import convertbits + +CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" + +# Cashaddr format +# +# : +# +# Unlike bech32, cashaddr stores it's header in an 8-bit byte instead of 5 bits. +# You have to convert the 5-bit bech32 to bytes in order to read the header. +# The checksum for cashaddr is 40 bits so it makes it a nice round number for +# both 8-bit (5 values) and 5-bit (8 values) values. When converting the payload +# verify the checksum, then drop the checksum when converting from 5-bits to +# 8-bits. Since the payload is padded, if you try to convert the payload and +# checksum at the same time and then drop the last 5 bytes, you will get an +# incorrect payload. +# +# The expanded format is as follows: +# +# : +# +# Header: +# +# The most significant bit is reserved and must be 0. +# The next four bits are the type bits. Only the following is valid: +# 0: PUBKEY Type +# 1: SCRIPT Type +# 15: UNKNOWN (not listed in the spec, but the spec includes valid addresses +# with type 15) +# The last three bits indicate the hash size excluding the header and the checksum. +# +-----------+-----------+ +# | Size bits | Hash bits | +# +-----------+-----------+ +# | 0 | 160 | +# | 1 | 192 | +# | 2 | 224 | +# | 3 | 256 | +# | 4 | 320 | +# | 5 | 384 | +# | 6 | 448 | +# | 7 | 512 | +# +-----------+-----------+ +# +# Payload: +# +# The payload length is specified by the size in the header and must match. +# +# Checksum: +# +# The 40-bits of checksum are only used in validating the bech32 hash. Although +# the checksum is powerful enough to fix minor errors, since we are dealing +# with money, it is best to just error if the checksum does not match and have +# the hash manually verified to find the error. + +def polymod(values): + """Internal function that computes the cashaddr checksum.""" + generator = [0x98f2bc8e61, 0x79b76d99e2, 0xf33e5fb3c4, 0xae2eabe2a8, 0x1e4f43e470] + chk = 1 + for value in values: + top = chk >> 35 + chk = ((chk & 0x07ffffffff) << 5) ^ value + for i in range(5): + chk ^= generator[i] if ((top >> i) & 1) else 0 + return chk ^ 1 + +def expand_prefix(prefix): + """Expand the address prefix into values for checksum computation.""" + data = [ord(x) & 31 for x in prefix] + [0] + return [ord(x) & 31 for x in prefix] + [0] + +def verify_checksum(prefix, data): + """Verify a checksum given prefix and converted data characters.""" + return polymod(expand_prefix(prefix) + data) == 0 + +def create_checksum(prefix, data): + """Compute the checksum values given prefix and data.""" + values = expand_prefix(prefix) + data + out = polymod(values + [0, 0, 0, 0, 0, 0, 0, 0]) + return [(out >> 5 * (7 - i)) & 31 for i in range(8)] + +def assemble(prefix, data): + """Compute a cashaddr string given prefix and data values.""" + combined = data + create_checksum(prefix, data) + return prefix + ':' + ''.join([CHARSET[d] for d in combined]) + +def valid_version(data): + """Check that the version is correct for the data. + Do not include the checksum.""" + converted = convertbits(data, 5, 8, False) + if converted == None: + return False + ver = converted[0] + # First bit is reserved + if ver & (1 << 8): + return False + # Last three bits specify the length we expect + bits = 160 + (ver & 3) * 32 + # Bit six is a multiplier + if ver & 4: + bits *= 2 + if (len(converted) - 1) != (bits / 8): + return False + return True + +def disassemble(cashaddr, default_prefix): + """Validate a cashaddr string, and determine prefix and data.""" + if ((any(ord(x) < 33 or ord(x) > 126 for x in cashaddr)) or + (cashaddr.lower() != cashaddr and cashaddr.upper() != cashaddr)): + return (None, None) + cashaddr = cashaddr.lower() + pos = cashaddr.rfind(':') + if pos < 0: + cashaddr = "%s:%s" % (default_prefix.lower(), cashaddr) + pos = len(default_prefix) + if len(cashaddr) - pos - 1 <= 8 or len(cashaddr) - pos - 1 > 112: + return (None, None) + if not all(x in CHARSET for x in cashaddr[pos+1:]): + return (None, None) + prefix = cashaddr[:pos] + data = [CHARSET.find(x) for x in cashaddr[pos+1:]] + if not valid_version(data[:-8]): + return (None, None) + if not verify_checksum(prefix, data): + return (None, None) + return (prefix, data[:-8]) + +def decode(prefix, addr): + """Decode a cashaddr address.""" + prefixgot, data = disassemble(addr, prefix) + if prefixgot != prefix: + return (None, None) + decoded = convertbits(data, 5, 8, False) + if decoded is None or not len(decoded): + return (None, None) + ver = (decoded[0] & 0x78) >> 3 + return (ver, decoded[1:]) + +def encode(prefix, ver, data): + """Encode a cashaddr address.""" + if not len(data) in [20, 24, 28, 32, 40, 48, 56, 64]: + # Make sure length is valid. + return None + if not (0 <= ver <= 1 or ver == 15): + # Only versions (type) 1,2 and 15 are supported. + return None + ver <<= 3 + dlen = 0 + tmp = len(data) * 8 + if tmp > 256: + dlen ^= 0x04 + tmp /= 2 + dlen += (tmp - 160) / 32 + ver += dlen + bits = convertbits([ver] + data, 8, 5) + ret = assemble(prefix, bits) + if decode(prefix, ret) == (None, None): + return None + return ret diff --git a/p2pool/util/expiring_dict.py b/p2pool/util/expiring_dict.py index 8a3c9eed..c61ab381 100644 --- a/p2pool/util/expiring_dict.py +++ b/p2pool/util/expiring_dict.py @@ -106,7 +106,7 @@ def __init__(self, expiry_time, get_touches=True): self.d = dict() # key -> node, value self_ref = weakref.ref(self, lambda _: expire_loop.stop() if expire_loop.running else None) - self._expire_loop = expire_loop = deferral.RobustLoopingCall(lambda: self_ref().expire()) + self._expire_loop = expire_loop = deferral.RobustLoopingCall(lambda: self_ref().expire() if isinstance(self_ref(),ExpiringDict) else None) expire_loop.start(1) def stop(self): diff --git a/p2pool/util/jsonrpc.py b/p2pool/util/jsonrpc.py index d810adaa..8ae781d9 100644 --- a/p2pool/util/jsonrpc.py +++ b/p2pool/util/jsonrpc.py @@ -156,7 +156,7 @@ def __init__(self): 'jsonrpc': '2.0', 'method': method, 'params': params, - 'id': id, +# 'id': id, }))) self.other = Proxy(self._matcher) diff --git a/p2pool/util/logging.py b/p2pool/util/logging.py index 698a39de..d1b17779 100644 --- a/p2pool/util/logging.py +++ b/p2pool/util/logging.py @@ -3,6 +3,9 @@ import os import sys +reload(sys) +sys.setdefaultencoding('utf8') + from twisted.python import log class EncodeReplacerPipe(object): diff --git a/p2pool/util/math.py b/p2pool/util/math.py index 8b2d9d84..5e892f37 100644 --- a/p2pool/util/math.py +++ b/p2pool/util/math.py @@ -220,7 +220,7 @@ def _prune(self): start_time = time.time() - self.max_lookback_time for i, (ts, datum) in enumerate(self.datums): if ts > start_time: - self.datums[:] = self.datums[i:] + del self.datums[:i] return def get_datums_in_last(self, dt=None): @@ -243,3 +243,25 @@ def merge_dicts(*dicts): res = {} for d in dicts: res.update(d) return res + +def convertbits(data, frombits, tobits, pad=True): + """General power-of-2 base conversion.""" + acc = 0 + bits = 0 + ret = [] + maxv = (1 << tobits) - 1 + max_acc = (1 << (frombits + tobits - 1)) - 1 + for value in data: + if value < 0 or (value >> frombits): + return None + acc = ((acc << frombits) | value) & max_acc + bits += frombits + while bits >= tobits: + bits -= tobits + ret.append((acc >> bits) & maxv) + if pad: + if bits: + ret.append((acc << (tobits - bits)) & maxv) + elif bits >= frombits or ((acc << (tobits - bits)) & maxv): + return None + return ret diff --git a/p2pool/util/pack.py b/p2pool/util/pack.py index bf9fe2f4..7fbf8bd2 100644 --- a/p2pool/util/pack.py +++ b/p2pool/util/pack.py @@ -1,5 +1,7 @@ import binascii import struct +import cStringIO as StringIO +import os import p2pool from p2pool.util import memoize @@ -10,14 +12,12 @@ class EarlyEnd(Exception): class LateEnd(Exception): pass -def read((data, pos), length): - data2 = data[pos:pos + length] - if len(data2) != length: - raise EarlyEnd() - return data2, (data, pos + length) - -def size((data, pos)): - return len(data) - pos +def remaining(sio): + here = sio.tell() + sio.seek(0, os.SEEK_END) + end = sio.tell() + sio.seek(here) + return end - here class Type(object): __slots__ = [] @@ -39,34 +39,26 @@ def __ne__(self, other): return not (self == other) def _unpack(self, data, ignore_trailing=False): - obj, (data2, pos) = self.read((data, 0)) - - assert data2 is data - - if pos != len(data) and not ignore_trailing: + obj = self.read(data) + if not ignore_trailing and remaining(data): raise LateEnd() - return obj def _pack(self, obj): - f = self.write(None, obj) - - res = [] - while f is not None: - res.append(f[1]) - f = f[0] - res.reverse() - return ''.join(res) - + f = StringIO.StringIO() + self.write(f, obj) + return f.getvalue() def unpack(self, data, ignore_trailing=False): + if not type(data) == StringIO.InputType: + data = StringIO.StringIO(data) obj = self._unpack(data, ignore_trailing) if p2pool.DEBUG: packed = self._pack(obj) - good = data.startswith(packed) if ignore_trailing else data == packed + good = data.getvalue().startswith(packed) if ignore_trailing else data.getvalue() == packed if not good: - raise AssertionError() + raise AssertionError(ignore_trailing, packed, data.getvalue()) return obj @@ -89,10 +81,10 @@ def packed_size(self, obj): class VarIntType(Type): def read(self, file): - data, file = read(file, 1) + data = file.read(1) first = ord(data) if first < 0xfd: - return first, file + return first if first == 0xfd: desc, length, minimum = '= self.field_names for key, type_ in self.fields: - file = type_.write(file, item[key]) - return file + type_.write(file, item[key]) class PossiblyNoneType(Type): def __init__(self, none_value, inner): @@ -323,22 +291,22 @@ def __init__(self, none_value, inner): self.inner = inner def read(self, file): - value, file = self.inner.read(file) - return None if value == self.none_value else value, file + value = self.inner.read(file) + return None if value == self.none_value else value def write(self, file, item): if item == self.none_value: raise ValueError('none_value used') - return self.inner.write(file, self.none_value if item is None else item) + self.inner.write(file, self.none_value if item is None else item) class FixedStrType(Type): def __init__(self, length): self.length = length def read(self, file): - return read(file, self.length) + return file.read(self.length) def write(self, file, item): if len(item) != self.length: raise ValueError('incorrect length item!') - return file, item + file.write(item) diff --git a/p2pool/util/segwit_addr.py b/p2pool/util/segwit_addr.py index d450080c..a50a29f2 100644 --- a/p2pool/util/segwit_addr.py +++ b/p2pool/util/segwit_addr.py @@ -20,6 +20,7 @@ """Reference implementation for Bech32 and segwit addresses.""" +from math import convertbits CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" @@ -76,30 +77,6 @@ def bech32_decode(bech): return (None, None) return (hrp, data[:-6]) - -def convertbits(data, frombits, tobits, pad=True): - """General power-of-2 base conversion.""" - acc = 0 - bits = 0 - ret = [] - maxv = (1 << tobits) - 1 - max_acc = (1 << (frombits + tobits - 1)) - 1 - for value in data: - if value < 0 or (value >> frombits): - return None - acc = ((acc << frombits) | value) & max_acc - bits += frombits - while bits >= tobits: - bits -= tobits - ret.append((acc >> bits) & maxv) - if pad: - if bits: - ret.append((acc << (tobits - bits)) & maxv) - elif bits >= frombits or ((acc << (tobits - bits)) & maxv): - return None - return ret - - def decode(hrp, addr): """Decode a segwit address.""" hrpgot, data = bech32_decode(addr) diff --git a/p2pool/util/variable.py b/p2pool/util/variable.py index 0050b0d3..47256e92 100644 --- a/p2pool/util/variable.py +++ b/p2pool/util/variable.py @@ -83,3 +83,22 @@ def get_when_satisfies(self, func): def get_not_none(self): return self.get_when_satisfies(lambda val: val is not None) + +class VariableDict(Variable): + def __init__(self, value): + Variable.__init__(self, value) + self.added = Event() + self.removed = Event() + + def add(self, values): + new_items = dict([item for item in values.iteritems() if not item[0] in self.value or self.value[item[0]] != item[1]]) + self.value.update(values) + self.added.happened(new_items) + # XXX call self.changed and self.transitioned + + def remove(self, values): + gone_items = dict([item for item in values.iteritems() if item[0] in self.value]) + for key in gone_keys: + del self.values[key] + self.removed.happened(new_items) + # XXX call self.changed and self.transitioned diff --git a/p2pool/web.py b/p2pool/web.py index 67082644..0ab337eb 100644 --- a/p2pool/web.py +++ b/p2pool/web.py @@ -55,14 +55,14 @@ def get_users(): height, last = node.tracker.get_height_and_last(node.best_share_var.value) weights, total_weight, donation_weight = node.tracker.get_cumulative_weights(node.best_share_var.value, min(height, 720), 65535*2**256) res = {} - for script in sorted(weights, key=lambda s: weights[s]): - res[bitcoin_data.script2_to_address(script, node.net.PARENT)] = weights[script]/total_weight + for addr in sorted(weights, key=lambda s: weights[s]): + res[addr] = weights[addr]/total_weight return res def get_current_scaled_txouts(scale, trunc=0): txouts = node.get_current_txouts() total = sum(txouts.itervalues()) - results = dict((script, value*scale//total) for script, value in txouts.iteritems()) + results = dict((addr, value*scale//total) for addr, value in txouts.iteritems()) if trunc > 0: total_random = 0 random_set = set() @@ -72,9 +72,9 @@ def get_current_scaled_txouts(scale, trunc=0): total_random += results[s] random_set.add(s) if total_random: - winner = math.weighted_choice((script, results[script]) for script in random_set) - for script in random_set: - del results[script] + winner = math.weighted_choice((addr, results[script]) for addr in random_set) + for addr in random_set: + del results[addr] results[winner] = total_random if sum(results.itervalues()) < int(scale): results[math.weighted_choice(results.iteritems())] += int(scale) - sum(results.itervalues()) @@ -203,10 +203,13 @@ def decent_height(): web_root.putChild('rate', WebInterface(lambda: p2pool_data.get_pool_attempts_per_second(node.tracker, node.best_share_var.value, decent_height())/(1-p2pool_data.get_average_stale_prop(node.tracker, node.best_share_var.value, decent_height())))) web_root.putChild('difficulty', WebInterface(lambda: bitcoin_data.target_to_difficulty(node.tracker.items[node.best_share_var.value].max_target))) web_root.putChild('users', WebInterface(get_users)) - web_root.putChild('user_stales', WebInterface(lambda: dict((bitcoin_data.pubkey_hash_to_address(ph, node.net.PARENT), prop) for ph, prop in - p2pool_data.get_user_stale_props(node.tracker, node.best_share_var.value, node.tracker.get_height(node.best_share_var.value)).iteritems()))) + web_root.putChild('user_stales', WebInterface(lambda: + p2pool_data.get_user_stale_props(node.tracker, node.best_share_var.value, + node.tracker.get_height(node.best_share_var.value), node.net.PARENT))) web_root.putChild('fee', WebInterface(lambda: wb.worker_fee)) - web_root.putChild('current_payouts', WebInterface(lambda: dict((bitcoin_data.script2_to_address(script, node.net.PARENT), value/1e8) for script, value in node.get_current_txouts().iteritems()))) + web_root.putChild('current_payouts', WebInterface(lambda: dict( + (address, value/1e8) for address, value + in node.get_current_txouts().iteritems()))) web_root.putChild('patron_sendmany', WebInterface(get_patron_sendmany, 'text/plain')) web_root.putChild('global_stats', WebInterface(get_global_stats)) web_root.putChild('local_stats', WebInterface(get_local_stats)) @@ -223,14 +226,15 @@ def decent_height(): ]) )))) web_root.putChild('peer_versions', WebInterface(lambda: dict(('%s:%i' % peer.addr, peer.other_sub_version) for peer in node.p2p_node.peers.itervalues()))) - web_root.putChild('payout_addr', WebInterface(lambda: bitcoin_data.pubkey_hash_to_address(wb.my_pubkey_hash, node.net.PARENT, wb.my_pubkey_hash_version))) - web_root.putChild('payout_addrs', WebInterface(lambda: list(('%s' % bitcoin_data.pubkey_hash_to_address(add['hash'], node.net.PARENT, add['version'])) for add in wb.pubkeys.keys))) + web_root.putChild('payout_addr', WebInterface(lambda: wb.address)) + web_root.putChild('payout_addrs', WebInterface( + lambda: list(add['address'] for add in wb.pubkeys.keys))) web_root.putChild('recent_blocks', WebInterface(lambda: [dict( ts=s.timestamp, hash='%064x' % s.header_hash, number=p2pool_data.parse_bip0034(s.share_data['coinbase'])[0], share='%064x' % s.hash, - ) for s in node.tracker.get_chain(node.best_share_var.value, min(node.tracker.get_height(node.best_share_var.value), 24*60*60//node.net.SHARE_PERIOD)) if s.pow_hash <= s.header['bits'].target])) + ) for s in node.tracker.get_chain(node.best_share_var.value, min(node.tracker.get_height(node.best_share_var.value), node.net.CHAIN_LENGTH)) if s.pow_hash <= s.header['bits'].target])) web_root.putChild('uptime', WebInterface(lambda: time.time() - start_time)) web_root.putChild('stale_rates', WebInterface(lambda: p2pool_data.get_stale_counts(node.tracker, node.best_share_var.value, decent_height(), rates=True))) @@ -258,7 +262,8 @@ def update_stat_log(): my_current_payout=0.0 for add in wb.pubkeys.keys: - my_current_payout+=node.get_current_txouts().get(bitcoin_data.pubkey_hash_to_script2(add['hash'], add['version'], node.net.PARENT), 0)*1e-8 + my_current_payout += node.get_current_txouts().get( + add['address'], 0)*1e-8 stat_log.append(dict( time=time.time(), pool_hash_rate=p2pool_data.get_pool_attempts_per_second(node.tracker, node.best_share_var.value, lookbehind)/(1-global_stale_prop), @@ -291,8 +296,8 @@ def get_share(share_hash_str): share = node.tracker.items[int(share_hash_str, 16)] return dict( - parent='%064x' % share.previous_hash, - far_parent='%064x' % share.share_info['far_share_hash'], + parent='%064x' % share.previous_hash if share.previous_hash else "None", + far_parent='%064x' % share.share_info['far_share_hash'] if share.share_info['far_share_hash'] else "None", children=['%064x' % x for x in sorted(node.tracker.reverse.get(share.hash, set()), key=lambda sh: -len(node.tracker.reverse.get(sh, set())))], # sorted from most children to least children type_name=type(share).__name__, local=dict( @@ -304,7 +309,11 @@ def get_share(share_hash_str): timestamp=share.timestamp, target=share.target, max_target=share.max_target, - payout_address=bitcoin_data.script2_to_address(share.new_script, node.net.PARENT), + payout_address=share.address if share.address else + bitcoin_data.script2_to_address( + share.new_script, + node.net.PARENT.ADDRESS_VERSION, + node.net.PARENT), donation=share.share_data['donation']/65535, stale_info=share.share_data['stale_info'], nonce=share.share_data['nonce'], @@ -324,6 +333,7 @@ def get_share(share_hash_str): ), gentx=dict( hash='%064x' % share.gentx_hash, + raw=bitcoin_data.tx_id_type.pack(share.gentx).encode('hex') if hasattr(share, 'gentx') else "unknown", coinbase=share.share_data['coinbase'].ljust(2, '\x00').encode('hex'), value=share.share_data['subsidy']*1e-8, last_txout_nonce='%016x' % share.contents['last_txout_nonce'], @@ -336,7 +346,12 @@ def get_share_address(share_hash_str): if int(share_hash_str, 16) not in node.tracker.items: return None share = node.tracker.items[int(share_hash_str, 16)] - return bitcoin_data.script2_to_address(share.new_script, node.net.PARENT) + try: + return share.address + except AttributeError: + return bitcoin_data.script2_to_address(share.new_script, + node.net.ADDRESS_VERSION, -1, + node.net.PARENT) new_root.putChild('payout_address', WebInterface(lambda share_hash_str: get_share_address(share_hash_str))) new_root.putChild('share', WebInterface(lambda share_hash_str: get_share(share_hash_str))) @@ -346,6 +361,7 @@ def get_share_address(share_hash_str): new_root.putChild('verified_tails', WebInterface(lambda: ['%064x' % x for t in node.tracker.verified.tails for x in node.tracker.verified.reverse.get(t, set())])) new_root.putChild('best_share_hash', WebInterface(lambda: '%064x' % node.best_share_var.value)) new_root.putChild('my_share_hashes', WebInterface(lambda: ['%064x' % my_share_hash for my_share_hash in wb.my_share_hashes])) + new_root.putChild('my_share_hashes50', WebInterface(lambda: ['%064x' % my_share_hash for my_share_hash in list(wb.my_share_hashes)[:50]])) def get_share_data(share_hash_str): if int(share_hash_str, 16) not in node.tracker.items: return '' @@ -387,8 +403,8 @@ def get_share_data(share_hash_str): 'current_payout': graph.DataStreamDescription(dataview_descriptions), 'current_payouts': graph.DataStreamDescription(dataview_descriptions, multivalues=True), 'peers': graph.DataStreamDescription(dataview_descriptions, multivalues=True, default_func=graph.make_multivalue_migrator(dict(incoming='incoming_peers', outgoing='outgoing_peers'))), - 'miner_hash_rates': graph.DataStreamDescription(dataview_descriptions, is_gauge=False, multivalues=True), - 'miner_dead_hash_rates': graph.DataStreamDescription(dataview_descriptions, is_gauge=False, multivalues=True), + 'miner_hash_rates': graph.DataStreamDescription(dataview_descriptions, is_gauge=False, multivalues=True, multivalues_keep=10000), + 'miner_dead_hash_rates': graph.DataStreamDescription(dataview_descriptions, is_gauge=False, multivalues=True, multivalues_keep=10000), 'desired_version_rates': graph.DataStreamDescription(dataview_descriptions, multivalues=True, multivalue_undefined_means_0=True), 'traffic_rate': graph.DataStreamDescription(dataview_descriptions, is_gauge=False, multivalues=True), @@ -441,10 +457,11 @@ def add_point(): current_txouts = node.get_current_txouts() my_current_payouts = 0.0 for add in wb.pubkeys.keys: - my_current_payouts += current_txouts.get(bitcoin_data.pubkey_hash_to_script2(add['hash'], add['version'], node.net.PARENT), 0)*1e-8 + my_current_payouts += current_txouts.get( + add['address'], 0) * 1e-8 hd.datastreams['current_payout'].add_datum(t, my_current_payouts) miner_hash_rates, miner_dead_hash_rates = wb.get_local_rates() - current_txouts_by_address = dict((bitcoin_data.script2_to_address(script, node.net.PARENT), amount) for script, amount in current_txouts.iteritems()) + current_txouts_by_address = current_txouts hd.datastreams['current_payouts'].add_datum(t, dict((user, current_txouts_by_address[user]*1e-8) for user in miner_hash_rates if user in current_txouts_by_address)) hd.datastreams['peers'].add_datum(t, dict( diff --git a/p2pool/work.py b/p2pool/work.py index 8cb6a045..a2b9513a 100644 --- a/p2pool/work.py +++ b/p2pool/work.py @@ -20,7 +20,8 @@ class WorkerBridge(worker_interface.WorkerBridge): COINBASE_NONCE_LENGTH = 8 - def __init__(self, node, my_pubkey_hash, my_pubkey_hash_version, donation_percentage, merged_urls, worker_fee, args, pubkeys, bitcoind, min_difficulty, share_rate, share_rate_type): + def __init__(self, node, my_address, donation_percentage, merged_urls, + worker_fee, args, pubkeys, bitcoind, share_rate): worker_interface.WorkerBridge.__init__(self) self.recent_shares_ts_work = [] @@ -29,16 +30,11 @@ def __init__(self, node, my_pubkey_hash, my_pubkey_hash_version, donation_percen self.bitcoind = bitcoind self.pubkeys = pubkeys self.args = args - self.my_pubkey_hash = my_pubkey_hash - self.my_pubkey_hash_version = my_pubkey_hash_version + self.address = my_address self.donation_percentage = 0.0 self.worker_fee = args.worker_fee - self.min_difficulty = min_difficulty - self.share_rate = share_rate - self.share_rate_type = share_rate_type - self.net = self.node.net.PARENT self.running = True self.pseudoshare_received = variable.Event() @@ -52,12 +48,9 @@ def __init__(self, node, my_pubkey_hash, my_pubkey_hash_version, donation_percen self.last_work_shares = variable.Variable( {} ) self.my_share_hashes = set() self.my_doa_share_hashes = set() - - self.invalid_hashes = 0 - self.total_hashes = 0 self.address_throttle = 0 - + self.share_rate = share_rate self.tracker_view = forest.TrackerView(self.node.tracker, forest.get_attributedelta_type(dict(forest.AttributeDelta.attrs, my_count=lambda share: 1 if share.hash in self.my_share_hashes else 0, my_doa_count=lambda share: 1 if share.hash in self.my_doa_share_hashes else 0, @@ -115,8 +108,9 @@ def compute_work(): bits=bb['bits'], # not always true coinbaseflags='', height=t['height'] + 1, - time=bb['timestamp'] + 600, # better way? + time=max(int(time.time() + 0.5), bb['timestamp'] + 1), transactions=[], + transaction_hashes=[], transaction_fees=[], merkle_link=bitcoin_data.calculate_merkle_link([None], 0), subsidy=self.node.net.PARENT.SUBSIDY_FUNC(self.node.bitcoind_work.value['height']), @@ -129,6 +123,7 @@ def compute_work(): compute_work() self.new_work_event = variable.Event() + @self.current_work.transitioned.watch def _(before, after): # trigger LP if version/previous_block/bits changed or transactions changed from nothing @@ -163,12 +158,12 @@ def freshen_addresses(self, c): self.address_throttle=time.time() print "ATTEMPTING TO FRESHEN ADDRESS." self.address = yield deferral.retry('Error getting a dynamic address from bitcoind:', 5)(lambda: self.bitcoind.rpc_getnewaddress('p2pool'))() - new_pubkey, new_pubkey_version = bitcoin_data.address_to_pubkey_hash(self.address, self.net) self.pubkeys.popleft() - self.pubkeys.addkey({ 'hash': new_pubkey, 'version': new_pubkey_version }) + self.pubkeys.addkey({'address': self.address}) print " Updated payout pool:" for i in range(len(self.pubkeys.keys)): - print ' ...payout %d: %s(%f)' % (i, bitcoin_data.pubkey_hash_to_address(self.pubkeys.keys[i], self.net),self.pubkeys.keyweights[i],) + print(' ...payout %d: %s(%f)' % + (i, self.address, self.pubkeys.keyweights[i])) self.pubkeys.updatestamp(c) print " Next address rotation in : %fs" % (time.time()-c+self.args.timeaddresses) @@ -177,52 +172,67 @@ def get_user_details(self, username): assert len(contents) % 2 == 1 user, contents2 = contents[0], contents[1:] - + worker = '' + if '_' in user: + worker = user.split('_')[1] + user = user.split('_')[0] + elif '.' in user: + worker = user.split('.')[1] + user = user.split('.')[0] + desired_pseudoshare_target = None desired_share_target = None - '''for symbol, parameter in zip(contents2[::2], contents2[1::2]): + for symbol, parameter in zip(contents2[::2], contents2[1::2]): if symbol == '+': try: - desired_pseudoshare_target = bitcoin_data.difficulty_to_target_alt(float(parameter), self.node.net.PARENT.DUMB_SCRYPT_DIFF) + desired_pseudoshare_target = bitcoin_data.difficulty_to_target(float(parameter)) except: if p2pool.DEBUG: log.err() elif symbol == '/': try: - desired_share_target = bitcoin_data.difficulty_to_target_alt(float(parameter), self.node.net.PARENT.DUMB_SCRYPT_DIFF) + desired_share_target = bitcoin_data.difficulty_to_target(float(parameter)) except: if p2pool.DEBUG: log.err() - ''' if self.args.address == 'dynamic': i = self.pubkeys.weighted() - pubkey_hash = self.pubkeys.keys[i]['hash'] - pubkey_hash_version = self.pubkeys.keys[i]['version'] + address = self.pubkeys.keys[i]['address'] c = time.time() if (c - self.pubkeys.stamp) > self.args.timeaddresses: self.freshen_addresses(c) if random.uniform(0, 100) < self.worker_fee: - pubkey_hash = hash=self.my_pubkey_hash - pubkey_hash_version = self.my_pubkey_hash_version + address = self.address + else: try: - pubkey_hash, pubkey_hash_version = bitcoin_data.address_to_pubkey_hash(user, self.node.net.PARENT) + if self.node.best_share_var.value is not None: + share_type = type(self.node.tracker.items[self.node.best_share_var.value]) + else: + share_type = p2pool_data.Share + + ret = bitcoin_data.address_to_pubkey_hash(user, self.node.net.PARENT) + if share_type.VERSION < 34 and ret[1] != self.node.net.PARENT.ADDRESS_VERSION: + print("not supporting %s yet, share version needs to be 34, but is %s." + % (user, share_type.VERSION)) + raise ValueError + address = user except Exception: # XXX blah if self.args.address != 'dynamic': - pubkey_hash = hash=self.my_pubkey_hash - pubkey_hash_version = self.my_pubkey_hash_version - return user, pubkey_hash, pubkey_hash_version, desired_share_target, desired_pseudoshare_target + address = self.address + if worker: + user = user + '.' + worker + return (user, address, desired_share_target, desired_pseudoshare_target) def preprocess_request(self, user): if (self.node.p2p_node is None or len(self.node.p2p_node.peers) == 0) and self.node.net.PERSIST: raise jsonrpc.Error_for_code(-12345)(u'p2pool is not connected to any peers') if time.time() > self.current_work.value['last_update'] + 60: raise jsonrpc.Error_for_code(-12345)(u'lost contact with bitcoind') - user, pubkey_hash, pubkey_hash_version, desired_share_target, desired_pseudoshare_target = self.get_user_details(user) - return user, pubkey_hash, pubkey_hash_version, desired_share_target, desired_pseudoshare_target + return self.get_user_details(user) def _estimate_local_hash_rate(self): if len(self.recent_shares_ts_work) == 50: @@ -245,31 +255,22 @@ def get_local_addr_rates(self): addr_hash_rates = {} datums, dt = self.local_addr_rate_monitor.get_datums_in_last() for datum in datums: - addr_hash_rates[datum['pubkey_hash']] = addr_hash_rates.get(datum['pubkey_hash'], 0) + datum['work']/dt + addr_hash_rates[datum['address']] = \ + addr_hash_rates.get(datum['address'], 0) + datum['work']/dt return addr_hash_rates - - def get_local_addr_rate(self, pubkey_hash): - addr_hash_rate = 0 - datums, dt = self.local_addr_rate_monitor.get_datums_in_last() - for datum in datums: - addr_hash_rate = addr_hash_rate + datum['work']/dt - return addr_hash_rate - - def get_miner_rate(self, miner): - miner_hash_rate = 0 - datums, dt = self.local_rate_monitor.get_datums_in_last() - for datum in datums: - if datum['user'] == miner: - miner_hash_rate = miner_hash_rate + datum['work']/dt - return miner_hash_rate - def get_work(self, user, pubkey_hash, pubkey_hash_version, desired_share_target, desired_pseudoshare_target): + def get_work(self, user, address, desired_share_target, + desired_pseudoshare_target, worker_ip=None): global print_throttle + t0 = time.time() if (self.node.p2p_node is None or len(self.node.p2p_node.peers) == 0) and self.node.net.PERSIST: raise jsonrpc.Error_for_code(-12345)(u'p2pool is not connected to any peers') if self.node.best_share_var.value is None and self.node.net.PERSIST: raise jsonrpc.Error_for_code(-12345)(u'p2pool is downloading shares') - if set(r[1:] if r.startswith('!') else r for r in self.node.bitcoind_work.value['rules']) - set(getattr(self.node.net, 'SOFTFORKS_REQUIRED', [])): + unknown_rules = set(r[1:] if r.startswith('!') else r for r in self.node.bitcoind_work.value['rules'] if r) - set(getattr(self.node.net, 'SOFTFORKS_REQUIRED', [])) + if unknown_rules: + print "Unknown softforks found: ", unknown_rules + print "Required softforks: ", self.node.bitcoind_work.value['rules'], "\tKnown: ", getattr(self.node.net, 'SOFTFORKS_REQUIRED', []) raise jsonrpc.Error_for_code(-12345)(u'unknown rule activated') if self.merged_work.value: @@ -285,8 +286,10 @@ def get_work(self, user, pubkey_hash, pubkey_hash_version, desired_share_target, mm_data = '' mm_later = [] - tx_hashes = [bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx)) for tx in self.current_work.value['transactions']] + tx_hashes = self.current_work.value['transaction_hashes'] tx_map = dict(zip(tx_hashes, self.current_work.value['transactions'])) + + self.node.mining2_txs_var.set(tx_map) # let node.py know not to evict these transactions previous_share = self.node.tracker.items[self.node.best_share_var.value] if self.node.best_share_var.value is not None else None if previous_share is None: @@ -309,19 +312,25 @@ def get_work(self, user, pubkey_hash, pubkey_hash_version, desired_share_target, share_type = successor_type else: share_type = previous_share_type + + local_addr_rates = self.get_local_addr_rates() if desired_share_target is None: desired_share_target = 2**256-1 - local_hash_rate = self._estimate_local_hash_rate() - if local_hash_rate is not None: + #local_hash_rate = self._estimate_local_hash_rate() + local_hash_rate = local_addr_rates.get(address, 0) + if local_hash_rate > 0.0: desired_share_target = min(desired_share_target, bitcoin_data.average_attempts_to_target(local_hash_rate * self.node.net.SHARE_PERIOD / 0.0167)) # limit to 1.67% of pool shares by modulating share difficulty +# if self.node.punish: +# print "trying to punish a share by mining a low-diff share" +# desired_share_target = bitcoin_data.difficulty_to_target(1.) local_addr_rates = self.get_local_addr_rates() lookbehind = 3600//self.node.net.SHARE_PERIOD block_subsidy = self.node.bitcoind_work.value['subsidy'] if previous_share is not None and self.node.tracker.get_height(previous_share.hash) > lookbehind: - expected_payout_per_block = local_addr_rates.get(pubkey_hash, 0)/p2pool_data.get_pool_attempts_per_second(self.node.tracker, self.node.best_share_var.value, lookbehind) \ + expected_payout_per_block = local_addr_rates.get(address, 0)* self.node.net.PARENT.DUMB_SCRYPT_DIFF / p2pool_data.get_pool_attempts_per_second(self.node.tracker, self.node.best_share_var.value, lookbehind) \ * block_subsidy*(1-self.donation_percentage/100) # XXX doesn't use global stale rate to compute pool hash if expected_payout_per_block < self.node.net.PARENT.DUST_THRESHOLD: desired_share_target = min(desired_share_target, @@ -336,10 +345,9 @@ def get_work(self, user, pubkey_hash, pubkey_hash_version, desired_share_target, coinbase=(script.create_push_script([ self.current_work.value['height'], ] + ([mm_data] if mm_data else []) + [ - ]) + self.current_work.value['coinbaseflags'])[:100], + ]) + 'p2p-spb.xyz')[:100], nonce=random.randrange(2**32), - pubkey_hash=pubkey_hash, - pubkey_hash_version=pubkey_hash_version, + address=address, subsidy=self.current_work.value['subsidy'], donation=math.perfect_round(65535*(0.0/100)), stale_info=(lambda (orphans, doas), total, (orphans_recorded_in_chain, doas_recorded_in_chain): @@ -361,42 +369,28 @@ def get_work(self, user, pubkey_hash, pubkey_hash_version, desired_share_target, packed_gentx = bitcoin_data.tx_id_type.pack(gentx) # stratum miners work with stripped transactions other_transactions = [tx_map[tx_hash] for tx_hash in other_transaction_hashes] - + + del tx_hashes + if self.node.cur_share_ver >= 34: + tx_map = {} # we can free up this memory now + mm_later = [(dict(aux_work, target=aux_work['target'] if aux_work['target'] != 'p2pool' else share_info['bits'].target), index, hashes) for aux_work, index, hashes in mm_later] if desired_pseudoshare_target is None: - #target = 2**256-1 - #DUMB_SCR - #target = bitcoin_data.difficulty_to_target(float(1.0 / self.node.net.PARENT.DUMB_SCRYPT_DIFF)) - #local_hash_rate = self._estimate_local_hash_rate() - #if local_hash_rate is not None: - #target = min(target, bitcoin_data.average_attempts_to_target(local_hash_rate * 1)) # limit to 1 share response every second by modulating pseudoshare difficulty - #target = bitcoin_data.average_attempts_to_target(local_hash_rate * 1) # limit to 1 share response every second by modulating pseudoshare difficulty - target = bitcoin_data.difficulty_to_target_alt(self.min_difficulty, self.node.net.PARENT.DUMB_SCRYPT_DIFF) - if self.share_rate is not None: - if self.share_rate_type == 'address': # per-address - if local_addr_rates is not None: - local_rate = local_addr_rates.get(pubkey_hash, 0) - else: - local_rate = self.get_local_addr_rate(pubkey_hash) - else: # per-miner - local_rate = self.get_miner_rate(user) - if local_rate > 0: - target = min(target, bitcoin_data.average_attempts_to_target(local_rate * 60 / self.share_rate)) - else: # per-node - local_hash_rate = self._estimate_local_hash_rate() - if local_hash_rate is not None: - target = min(target, - bitcoin_data.average_attempts_to_target(local_hash_rate * 1)) # limit to 1 share response every second by modulating pseudoshare difficulty - difficulty = bitcoin_data.target_to_difficulty_alt(target, self.node.net.PARENT.DUMB_SCRYPT_DIFF) - rounded_difficulty = 1 - if difficulty >= 1: - while (rounded_difficulty + rounded_difficulty * 2) / 2 < difficulty: - rounded_difficulty = rounded_difficulty * 2 + target = 2**256-1 + local_hash_rate = self._estimate_local_hash_rate() + if local_hash_rate is not None: + target = min(target, + bitcoin_data.average_attempts_to_target(local_hash_rate / 10)) # target no more than 10 share responses every second node-wide by modulating min pseudoshare difficulty else: - while (rounded_difficulty + rounded_difficulty / 2) / 2 >= difficulty: - rounded_difficulty = rounded_difficulty / 2 - target = bitcoin_data.difficulty_to_target_alt(rounded_difficulty, self.node.net.PARENT.DUMB_SCRYPT_DIFF) + # If we don't yet have an estimated node hashrate, then we still need to not undershoot the difficulty. + # Otherwise, we might get 1 PH/s of hashrate on difficulty settings appropriate for 1 GH/s. + # 1/3000th the difficulty of a full share should be a reasonable upper bound. That way, if + # one node has the whole p2pool hashrate, it will still only need to process one pseudoshare + # every ~0.01 seconds. + block_subsidy = self.node.bitcoind_work.value['subsidy'] + target = min(target, 3000 * bitcoin_data.average_attempts_to_target((bitcoin_data.target_to_average_attempts( + self.node.bitcoind_work.value['bits'].target)*self.node.net.SPREAD)*self.node.net.PARENT.DUST_THRESHOLD/block_subsidy)) else: target = desired_pseudoshare_target target = max(target, share_info['bits'].target) @@ -407,22 +401,24 @@ def get_work(self, user, pubkey_hash, pubkey_hash_version, desired_share_target, getwork_time = time.time() lp_count = self.new_work_event.times merkle_link = bitcoin_data.calculate_merkle_link([None] + other_transaction_hashes, 0) if share_info.get('segwit_data', None) is None else share_info['segwit_data']['txid_merkle_link'] - + + del other_transaction_hashes + if print_throttle is 0.0: print_throttle = time.time() else: current_time = time.time() if (current_time - print_throttle) > 5.0: - print 'New work for worker! Difficulty: %.06f Share difficulty: %.06f Total block value: %.6f %s including %i transactions' % ( - bitcoin_data.target_to_difficulty_alt(target, self.node.net.PARENT.DUMB_SCRYPT_DIFF), - bitcoin_data.target_to_difficulty_alt(share_info['bits'].target, self.node.net.PARENT.DUMB_SCRYPT_DIFF), + print 'New work! Share diff: %.02f Block value: %.2f %s (%i tx, %.0f kB)' % ( + bitcoin_data.target_to_difficulty(share_info['bits'].target), self.current_work.value['subsidy']*1e-8, self.node.net.PARENT.SYMBOL, len(self.current_work.value['transactions']), + sum((bitcoin_data.get_size(tx) for tx in self.current_work.value['transactions']))/1000., ) print_throttle = time.time() #need this for stats - self.last_work_shares.value[bitcoin_data.pubkey_hash_to_address(pubkey_hash, self.node.net.PARENT, pubkey_hash_version)]=share_info['bits'] + self.last_work_shares.value[address] = share_info['bits'] ba = dict( version=max(self.current_work.value['version'], 0x20000000), @@ -432,12 +428,14 @@ def get_work(self, user, pubkey_hash, pubkey_hash_version, desired_share_target, coinb2=packed_gentx[-4:], timestamp=self.current_work.value['time'], bits=self.current_work.value['bits'], + min_share_target=share_info['bits'].target, share_target=target, ) received_header_hashes = set() - def got_response(header, user, coinbase_nonce): + def got_response(header, username, coinbase_nonce, pseudoshare_target): + t0 = time.time() assert len(coinbase_nonce) == self.COINBASE_NONCE_LENGTH new_packed_gentx = packed_gentx[:-self.COINBASE_NONCE_LENGTH-4] + coinbase_nonce + packed_gentx[-4:] if coinbase_nonce != '\0'*self.COINBASE_NONCE_LENGTH else packed_gentx new_gentx = bitcoin_data.tx_type.unpack(new_packed_gentx) if coinbase_nonce != '\0'*self.COINBASE_NONCE_LENGTH else gentx @@ -450,15 +448,16 @@ def got_response(header, user, coinbase_nonce): pow_hash = self.node.net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(header)) try: if pow_hash <= header['bits'].target or p2pool.DEBUG: - helper.submit_block(dict(header=header, txs=[new_gentx] + other_transactions), False, self.node.factory, self.node.bitcoind, self.node.bitcoind_work, self.node.net) + if pow_hash <= header['bits'].target: print print 'GOT BLOCK FROM MINER! Passing to bitcoind! %s%064x' % (self.node.net.PARENT.BLOCK_EXPLORER_URL_PREFIX, header_hash) print + helper.submit_block(dict(header=header, txs=[new_gentx] + other_transactions), False, self.node) except: log.err(None, 'Error while processing potential block:') - user, _, _, _, _ = self.get_user_details(user) + username, _, _, _ = self.get_user_details(username) assert header['previous_block'] == ba['previous_block'] assert header['merkle_root'] == bitcoin_data.check_merkle_link(bitcoin_data.hash256(new_packed_gentx), merkle_link) assert header['bits'] == ba['bits'] @@ -497,18 +496,37 @@ def _(err): share = get_share(header, last_txout_nonce) print 'GOT SHARE! %s %s prev %s age %.2fs%s' % ( - user, + username, p2pool_data.format_hash(share.hash), p2pool_data.format_hash(share.previous_hash), time.time() - getwork_time, ' DEAD ON ARRIVAL' if not on_time else '', ) + + if self.node.cur_share_ver < 34: + # node.py will sometimes forget transactions if bitcoind's work has changed since this stratum + # job was assigned. Fortunately, the tx_map is still in in our scope from this job, so we can use that + # to refill it if needed. + + known_txs = self.node.known_txs_var.value + missing = {hsh:val for (hsh, val) in tx_map.iteritems() if not hsh in known_txs} + if missing: + print "Warning: %i transactions were erroneously evicted from known_txs_var. Refilling now." % len(missing) + self.node.known_txs_var.add(missing) + self.my_share_hashes.add(share.hash) if not on_time: self.my_doa_share_hashes.add(share.hash) - self.node.tracker.add(share) - self.node.set_best_share() + sibling_count = len(self.node.tracker.reverse.get(share.previous_hash, set())) + if on_time or sibling_count < 4: + self.node.tracker.add(share) + else: + print "Already have %i DOA shares with this parent. Not adding more." % sibling_count + if on_time: + self.node.set_best_share() + else: + print "Not considering work switching to DOA share" try: if (pow_hash <= header['bits'].target or p2pool.DEBUG) and self.node.p2p_node is not None: @@ -517,26 +535,26 @@ def _(err): log.err(None, 'Error forwarding block solution:') self.share_received.happened(bitcoin_data.target_to_average_attempts(share.target), not on_time, share.hash) - - self.total_hashes += 1 - - if pow_hash > target: - print 'Worker %s submitted share with hash > target:' % (user,) - print ' Hash: %56x' % (pow_hash,) - print ' Target: %56x' % (target,) - self.invalid_hashes += 1 + + if pow_hash > pseudoshare_target: + print 'Worker %s submitted share with hash > target:' % (username,) + print ' Hash: %064x' % (pow_hash,) + print ' Target: %064x' % (pseudoshare_target,) elif header_hash in received_header_hashes: - print >>sys.stderr, 'Worker %s submitted share more than once!' % (user,) + print >>sys.stderr, 'Worker %s submitted share more than once!' % (username,) else: received_header_hashes.add(header_hash) - self.pseudoshare_received.happened(bitcoin_data.target_to_average_attempts(target), not on_time, user) - self.recent_shares_ts_work.append((time.time(), bitcoin_data.target_to_average_attempts(target))) + self.pseudoshare_received.happened(bitcoin_data.target_to_average_attempts(pseudoshare_target), not on_time, username) + self.recent_shares_ts_work.append((time.time(), bitcoin_data.target_to_average_attempts(pseudoshare_target))) while len(self.recent_shares_ts_work) > 50: self.recent_shares_ts_work.pop(0) - self.local_rate_monitor.add_datum(dict(work=bitcoin_data.target_to_average_attempts(target), dead=not on_time, user=user, share_target=share_info['bits'].target)) - self.local_addr_rate_monitor.add_datum(dict(work=bitcoin_data.target_to_average_attempts(target), pubkey_hash=pubkey_hash)) - + self.local_rate_monitor.add_datum(dict(work=bitcoin_data.target_to_average_attempts(pseudoshare_target), dead=not on_time, user=username, share_target=share_info['bits'].target)) + self.local_addr_rate_monitor.add_datum(dict(work=bitcoin_data.target_to_average_attempts(pseudoshare_target), address=address)) + t1 = time.time() + if p2pool.BENCH and (t1-t0) > .01: print "%8.3f ms for work.py:got_response(%s)" % ((t1-t0)*1000., username) + return on_time - + t1 = time.time() + if p2pool.BENCH: print "%8.3f ms for work.py:get_work(%s, %s)" % ((t1-t0)*1000., user, address) return ba, got_response diff --git a/web-static/d3.js b/web-static/d3.js new file mode 100644 index 00000000..834c48af --- /dev/null +++ b/web-static/d3.js @@ -0,0 +1,5704 @@ +(function() { + function e(a, b) { + try { + for (var c in b) Object.defineProperty(a.prototype, c, { + value: b[c], + enumerable: !1 + }) + } catch (d) { + a.prototype = b + } + } + + function g(a) { + var b = -1, + c = a.length, + d = []; + while (++b < c) d.push(a[b]); + return d + } + + function h(a) { + return Array.prototype.slice.call(a) + } + + function k() {} + + function n(a) { + return a + } + + function o() { + return this + } + + function p() { + return !0 + } + + function q(a) { + return typeof a == "function" ? a : function() { + return a + } + } + + function r(a, b, c) { + return function() { + var d = c.apply(b, arguments); + return arguments.length ? a : d + } + } + + function s(a) { + return a != null && !isNaN(a) + } + + function t(a) { + return a.length + } + + function v(a) { + return a == null + } + + function w(a) { + return a.replace(/(^\s+)|(\s+$)/g, "").replace(/\s+/g, " ") + } + + function x(a) { + var b = 1; + while (a * b % 1) b *= 10; + return b + } + + function A() {} + + function B(a) { + function d() { + var c = b, + d = -1, + e = c.length, + f; + while (++d < e)(f = c[d].on) && f.apply(this, arguments); + return a + } + var b = [], + c = new k; + return d.on = function(d, e) { + var f = c.get(d), + g; + return arguments.length < 2 ? f && f.on : (f && (f.on = null, b = b.slice(0, g = b.indexOf(f)).concat(b.slice(g + 1)), c.remove(d)), e && b.push(c.set(d, { + on: e + })), a) + }, d + } + + function E(a, b) { + return b - (a ? 1 + Math.floor(Math.log(a + Math.pow(10, 1 + Math.floor(Math.log(a) / Math.LN10) - b)) / Math.LN10) : 1) + } + + function F(a) { + return a + "" + } + + function G(a) { + var b = a.lastIndexOf("."), + c = b >= 0 ? a.substring(b) : (b = a.length, ""), + d = []; + while (b > 0) d.push(a.substring(b -= 3, b + 3)); + return d.reverse().join(",") + c + } + + function I(a, b) { + return { + scale: Math.pow(10, (8 - b) * 3), + symbol: a + } + } + + function O(a) { + return function(b) { + return b <= 0 ? 0 : b >= 1 ? 1 : a(b) + } + } + + function P(a) { + return function(b) { + return 1 - a(1 - b) + } + } + + function Q(a) { + return function(b) { + return .5 * (b < .5 ? a(2 * b) : 2 - a(2 - 2 * b)) + } + } + + function R(a) { + return a + } + + function S(a) { + return function(b) { + return Math.pow(b, a) + } + } + + function T(a) { + return 1 - Math.cos(a * Math.PI / 2) + } + + function U(a) { + return Math.pow(2, 10 * (a - 1)) + } + + function V(a) { + return 1 - Math.sqrt(1 - a * a) + } + + function W(a, b) { + var c; + return arguments.length < 2 && (b = .45), arguments.length < 1 ? (a = 1, c = b / 4) : c = b / (2 * Math.PI) * Math.asin(1 / a), + function(d) { + return 1 + a * Math.pow(2, 10 * -d) * Math.sin((d - c) * 2 * Math.PI / b) + } + } + + function X(a) { + return a || (a = 1.70158), + function(b) { + return b * b * ((a + 1) * b - a) + } + } + + function Y(a) { + return a < 1 / 2.75 ? 7.5625 * a * a : a < 2 / 2.75 ? 7.5625 * (a -= 1.5 / 2.75) * a + .75 : a < 2.5 / 2.75 ? 7.5625 * (a -= 2.25 / 2.75) * a + .9375 : 7.5625 * (a -= 2.625 / 2.75) * a + .984375 + } + + function Z() { + d3.event.stopPropagation(), d3.event.preventDefault() + } + + function $() { + var a = d3.event, + b; + while (b = a.sourceEvent) a = b; + return a + } + + function _(a) { + var b = new A, + c = 0, + d = arguments.length; + while (++c < d) b[arguments[c]] = B(b); + return b.of = function(c, d) { + return function(e) { + try { + var f = e.sourceEvent = d3.event; + e.target = a, d3.event = e, b[e.type].apply(c, d) + } finally { + d3.event = f + } + } + }, b + } + + function bb(a) { + return a == "transform" ? d3.interpolateTransform : d3.interpolate + } + + function bc(a, b) { + return b = b - (a = +a) ? 1 / (b - a) : 0, + function(c) { + return (c - a) * b + } + } + + function bd(a, b) { + return b = b - (a = +a) ? 1 / (b - a) : 0, + function(c) { + return Math.max(0, Math.min(1, (c - a) * b)) + } + } + + function be(a, b, c) { + return new bf(a, b, c) + } + + function bf(a, b, c) { + this.r = a, this.g = b, this.b = c + } + + function bg(a) { + return a < 16 ? "0" + Math.max(0, a).toString(16) : Math.min(255, a).toString(16) + } + + function bh(a, b, c) { + var d = 0, + e = 0, + f = 0, + g, h, i; + g = /([a-z]+)\((.*)\)/i.exec(a); + if (g) { + h = g[2].split(","); + switch (g[1]) { + case "hsl": + return c(parseFloat(h[0]), parseFloat(h[1]) / 100, parseFloat(h[2]) / 100); + case "rgb": + return b(bj(h[0]), bj(h[1]), bj(h[2])) + } + } + return (i = bk.get(a)) ? b(i.r, i.g, i.b) : (a != null && a.charAt(0) === "#" && (a.length === 4 ? (d = a.charAt(1), d += d, e = a.charAt(2), e += e, f = a.charAt(3), f += f) : a.length === 7 && (d = a.substring(1, 3), e = a.substring(3, 5), f = a.substring(5, 7)), d = parseInt(d, 16), e = parseInt(e, 16), f = parseInt(f, 16)), b(d, e, f)) + } + + function bi(a, b, c) { + var d = Math.min(a /= 255, b /= 255, c /= 255), + e = Math.max(a, b, c), + f = e - d, + g, h, i = (e + d) / 2; + return f ? (h = i < .5 ? f / (e + d) : f / (2 - e - d), a == e ? g = (b - c) / f + (b < c ? 6 : 0) : b == e ? g = (c - a) / f + 2 : g = (a - b) / f + 4, g *= 60) : h = g = 0, bl(g, h, i) + } + + function bj(a) { + var b = parseFloat(a); + return a.charAt(a.length - 1) === "%" ? Math.round(b * 2.55) : b + } + + function bl(a, b, c) { + return new bm(a, b, c) + } + + function bm(a, b, c) { + this.h = a, this.s = b, this.l = c + } + + function bn(a, b, c) { + function f(a) { + return a > 360 ? a -= 360 : a < 0 && (a += 360), a < 60 ? d + (e - d) * a / 60 : a < 180 ? e : a < 240 ? d + (e - d) * (240 - a) / 60 : d + } + + function g(a) { + return Math.round(f(a) * 255) + } + var d, e; + return a %= 360, a < 0 && (a += 360), b = b < 0 ? 0 : b > 1 ? 1 : b, c = c < 0 ? 0 : c > 1 ? 1 : c, e = c <= .5 ? c * (1 + b) : c + b - c * b, d = 2 * c - e, be(g(a + 120), g(a), g(a - 120)) + } + + function bo(a) { + return j(a, bu), a + } + + function bv(a) { + return function() { + return bp(a, this) + } + } + + function bw(a) { + return function() { + return bq(a, this) + } + } + + function by(a, b) { + function f() { + if (b = this.classList) return b.add(a); + var b = this.className, + d = b.baseVal != null, + e = d ? b.baseVal : b; + c.lastIndex = 0, c.test(e) || (e = w(e + " " + a), d ? b.baseVal = e : this.className = e) + } + + function g() { + if (b = this.classList) return b.remove(a); + var b = this.className, + d = b.baseVal != null, + e = d ? b.baseVal : b; + e = w(e.replace(c, " ")), d ? b.baseVal = e : this.className = e + } + + function h() { + (b.apply(this, arguments) ? f : g).call(this) + } + var c = new RegExp("(^|\\s+)" + d3.requote(a) + "(\\s+|$)", "g"); + if (arguments.length < 2) { + var d = this.node(); + if (e = d.classList) return e.contains(a); + var e = d.className; + return c.lastIndex = 0, c.test(e.baseVal != null ? e.baseVal : e) + } + return this.each(typeof b == "function" ? h : b ? f : g) + } + + function bz(a) { + return { + __data__: a + } + } + + function bA(a) { + return function() { + return bt(this, a) + } + } + + function bB(a) { + return arguments.length || (a = d3.ascending), + function(b, c) { + return a(b && b.__data__, c && c.__data__) + } + } + + function bD(a) { + return j(a, bE), a + } + + function bF(a, b, c) { + j(a, bJ); + var d = new k, + e = d3.dispatch("start", "end"), + f = bR; + return a.id = b, a.time = c, a.tween = function(b, c) { + return arguments.length < 2 ? d.get(b) : (c == null ? d.remove(b) : d.set(b, c), a) + }, a.ease = function(b) { + return arguments.length ? (f = typeof b == "function" ? b : d3.ease.apply(d3, arguments), a) : f + }, a.each = function(b, c) { + return arguments.length < 2 ? bS.call(a, b) : (e.on(b, c), a) + }, d3.timer(function(g) { + return a.each(function(h, i, j) { + function p(a) { + return o.active > b ? r() : (o.active = b, d.forEach(function(a, b) { + (b = b.call(l, h, i)) && k.push(b) + }), e.start.call(l, h, i), q(a) || d3.timer(q, 0, c), 1) + } + + function q(a) { + if (o.active !== b) return r(); + var c = (a - m) / n, + d = f(c), + g = k.length; + while (g > 0) k[--g].call(l, d); + if (c >= 1) return r(), bL = b, e.end.call(l, h, i), bL = 0, 1 + } + + function r() { + return --o.count || delete l.__transition__, 1 + } + var k = [], + l = this, + m = a[j][i].delay, + n = a[j][i].duration, + o = l.__transition__ || (l.__transition__ = { + active: 0, + count: 0 + }); + ++o.count, m <= g ? p(g) : d3.timer(p, m, c) + }), 1 + }, 0, c), a + } + + function bH(a, b, c) { + return c != "" && bG + } + + function bI(a, b) { + function d(a, d, e) { + var f = b.call(this, a, d); + return f == null ? e != "" && bG : e != f && c(e, f) + } + + function e(a, d, e) { + return e != b && c(e, b) + } + var c = bb(a); + return typeof b == "function" ? d : b == null ? bH : (b += "", e) + } + + function bS(a) { + var b = bL, + c = bR, + d = bP, + e = bQ; + bL = this.id, bR = this.ease(); + for (var f = 0, g = this.length; f < g; f++) + for (var h = this[f], i = 0, j = h.length; i < j; i++) { + var k = h[i]; + k && (bP = this[f][i].delay, bQ = this[f][i].duration, a.call(k = k.node, k.__data__, i, f)) + } + return bL = b, bR = c, bP = d, bQ = e, this + } + + function bW() { + var a, b = Date.now(), + c = bT; + while (c) a = b - c.then, a >= c.delay && (c.flush = c.callback(a)), c = c.next; + var d = bX() - b; + d > 24 ? (isFinite(d) && (clearTimeout(bV), bV = setTimeout(bW, d)), bU = 0) : (bU = 1, bY(bW)) + } + + function bX() { + var a = null, + b = bT, + c = Infinity; + while (b) b.flush ? b = a ? a.next = b.next : bT = b.next : (c = Math.min(c, b.then + b.delay), b = (a = b).next); + return c + } + + function bZ(a) { + var b = [a.a, a.b], + c = [a.c, a.d], + d = b_(b), + e = b$(b, c), + f = b_(ca(c, b, -e)) || 0; + b[0] * c[1] < c[0] * b[1] && (b[0] *= -1, b[1] *= -1, d *= -1, e *= -1), this.rotate = (d ? Math.atan2(b[1], b[0]) : Math.atan2(-c[0], c[1])) * cb, this.translate = [a.e, a.f], this.scale = [d, f], this.skew = f ? Math.atan2(e, f) * cb : 0 + } + + function b$(a, b) { + return a[0] * b[0] + a[1] * b[1] + } + + function b_(a) { + var b = Math.sqrt(b$(a, a)); + return b && (a[0] /= b, a[1] /= b), b + } + + function ca(a, b, c) { + return a[0] += c * b[0], a[1] += c * b[1], a + } + + function cd(a, b) { + var c = a.ownerSVGElement || a; + if (c.createSVGPoint) { + var d = c.createSVGPoint(); + if (cc < 0 && (window.scrollX || window.scrollY)) { + c = d3.select(document.body).append("svg").style("position", "absolute").style("top", 0).style("left", 0); + var e = c[0][0].getScreenCTM(); + cc = !e.f && !e.e, c.remove() + } + return cc ? (d.x = b.pageX, d.y = b.pageY) : (d.x = b.clientX, d.y = b.clientY), d = d.matrixTransform(a.getScreenCTM().inverse()), [d.x, d.y] + } + var f = a.getBoundingClientRect(); + return [b.clientX - f.left - a.clientLeft, b.clientY - f.top - a.clientTop] + } + + function ce() {} + + function cf(a) { + var b = a[0], + c = a[a.length - 1]; + return b < c ? [b, c] : [c, b] + } + + function cg(a) { + return a.rangeExtent ? a.rangeExtent() : cf(a.range()) + } + + function ch(a, b) { + var c = 0, + d = a.length - 1, + e = a[c], + f = a[d], + g; + f < e && (g = c, c = d, d = g, g = e, e = f, f = g); + if (g = f - e) b = b(g), a[c] = b.floor(e), a[d] = b.ceil(f); + return a + } + + function ci() { + return Math + } + + function cj(a, b, c, d) { + function g() { + var g = Math.min(a.length, b.length) > 2 ? cq : cp, + i = d ? bd : bc; + return e = g(a, b, i, c), f = g(b, a, i, d3.interpolate), h + } + + function h(a) { + return e(a) + } + var e, f; + return h.invert = function(a) { + return f(a) + }, h.domain = function(b) { + return arguments.length ? (a = b.map(Number), g()) : a + }, h.range = function(a) { + return arguments.length ? (b = a, g()) : b + }, h.rangeRound = function(a) { + return h.range(a).interpolate(d3.interpolateRound) + }, h.clamp = function(a) { + return arguments.length ? (d = a, g()) : d + }, h.interpolate = function(a) { + return arguments.length ? (c = a, g()) : c + }, h.ticks = function(b) { + return cn(a, b) + }, h.tickFormat = function(b) { + return co(a, b) + }, h.nice = function() { + return ch(a, cl), g() + }, h.copy = function() { + return cj(a, b, c, d) + }, g() + } + + function ck(a, b) { + return d3.rebind(a, b, "range", "rangeRound", "interpolate", "clamp") + } + + function cl(a) { + return a = Math.pow(10, Math.round(Math.log(a) / Math.LN10) - 1), { + floor: function(b) { + return Math.floor(b / a) * a + }, + ceil: function(b) { + return Math.ceil(b / a) * a + } + } + } + + function cm(a, b) { + var c = cf(a), + d = c[1] - c[0], + e = Math.pow(10, Math.floor(Math.log(d / b) / Math.LN10)), + f = b / d * e; + return f <= .15 ? e *= 10 : f <= .35 ? e *= 5 : f <= .75 && (e *= 2), c[0] = Math.ceil(c[0] / e) * e, c[1] = Math.floor(c[1] / e) * e + e * .5, c[2] = e, c + } + + function cn(a, b) { + return d3.range.apply(d3, cm(a, b)) + } + + function co(a, b) { + return d3.format(",." + Math.max(0, -Math.floor(Math.log(cm(a, b)[2]) / Math.LN10 + .01)) + "f") + } + + function cp(a, b, c, d) { + var e = c(a[0], a[1]), + f = d(b[0], b[1]); + return function(a) { + return f(e(a)) + } + } + + function cq(a, b, c, d) { + var e = [], + f = [], + g = 0, + h = Math.min(a.length, b.length) - 1; + a[h] < a[0] && (a = a.slice().reverse(), b = b.slice().reverse()); + while (++g <= h) e.push(c(a[g - 1], a[g])), f.push(d(b[g - 1], b[g])); + return function(b) { + var c = d3.bisect(a, b, 1, h) - 1; + return f[c](e[c](b)) + } + } + + function cr(a, b) { + function d(c) { + return a(b(c)) + } + var c = b.pow; + return d.invert = function(b) { + return c(a.invert(b)) + }, d.domain = function(e) { + return arguments.length ? (b = e[0] < 0 ? cu : ct, c = b.pow, a.domain(e.map(b)), d) : a.domain().map(c) + }, d.nice = function() { + return a.domain(ch(a.domain(), ci)), d + }, d.ticks = function() { + var d = cf(a.domain()), + e = []; + if (d.every(isFinite)) { + var f = Math.floor(d[0]), + g = Math.ceil(d[1]), + h = c(d[0]), + i = c(d[1]); + if (b === cu) { + e.push(c(f)); + for (; f++ < g;) + for (var j = 9; j > 0; j--) e.push(c(f) * j) + } else { + for (; f < g; f++) + for (var j = 1; j < 10; j++) e.push(c(f) * j); + e.push(c(f)) + } + for (f = 0; e[f] < h; f++); + for (g = e.length; e[g - 1] > i; g--); + e = e.slice(f, g) + } + return e + }, d.tickFormat = function(a, e) { + arguments.length < 2 && (e = cs); + if (arguments.length < 1) return e; + var f = a / d.ticks().length, + g = b === cu ? (h = -1e-12, Math.floor) : (h = 1e-12, Math.ceil), + h; + return function(a) { + return a / c(g(b(a) + h)) < f ? e(a) : "" + } + }, d.copy = function() { + return cr(a.copy(), b) + }, ck(d, a) + } + + function ct(a) { + return Math.log(a < 0 ? 0 : a) / Math.LN10 + } + + function cu(a) { + return -Math.log(a > 0 ? 0 : -a) / Math.LN10 + } + + function cv(a, b) { + function e(b) { + return a(c(b)) + } + var c = cw(b), + d = cw(1 / b); + return e.invert = function(b) { + return d(a.invert(b)) + }, e.domain = function(b) { + return arguments.length ? (a.domain(b.map(c)), e) : a.domain().map(d) + }, e.ticks = function(a) { + return cn(e.domain(), a) + }, e.tickFormat = function(a) { + return co(e.domain(), a) + }, e.nice = function() { + return e.domain(ch(e.domain(), cl)) + }, e.exponent = function(a) { + if (!arguments.length) return b; + var f = e.domain(); + return c = cw(b = a), d = cw(1 / b), e.domain(f) + }, e.copy = function() { + return cv(a.copy(), b) + }, ck(e, a) + } + + function cw(a) { + return function(b) { + return b < 0 ? -Math.pow(-b, a) : Math.pow(b, a) + } + } + + function cx(a, b) { + function f(b) { + return d[((c.get(b) || c.set(b, a.push(b))) - 1) % d.length] + } + + function g(b, c) { + return d3.range(a.length).map(function(a) { + return b + c * a + }) + } + var c, d, e; + return f.domain = function(d) { + if (!arguments.length) return a; + a = [], c = new k; + var e = -1, + g = d.length, + h; + while (++e < g) c.has(h = d[e]) || c.set(h, a.push(h)); + return f[b.t](b.x, b.p) + }, f.range = function(a) { + return arguments.length ? (d = a, e = 0, b = { + t: "range", + x: a + }, f) : d + }, f.rangePoints = function(c, h) { + arguments.length < 2 && (h = 0); + var i = c[0], + j = c[1], + k = (j - i) / (a.length - 1 + h); + return d = g(a.length < 2 ? (i + j) / 2 : i + k * h / 2, k), e = 0, b = { + t: "rangePoints", + x: c, + p: h + }, f + }, f.rangeBands = function(c, h) { + arguments.length < 2 && (h = 0); + var i = c[1] < c[0], + j = c[i - 0], + k = c[1 - i], + l = (k - j) / (a.length + h); + return d = g(j + l * h, l), i && d.reverse(), e = l * (1 - h), b = { + t: "rangeBands", + x: c, + p: h + }, f + }, f.rangeRoundBands = function(c, h) { + arguments.length < 2 && (h = 0); + var i = c[1] < c[0], + j = c[i - 0], + k = c[1 - i], + l = Math.floor((k - j) / (a.length + h)), + m = k - j - (a.length - h) * l; + return d = g(j + Math.round(m / 2), l), i && d.reverse(), e = Math.round(l * (1 - h)), b = { + t: "rangeRoundBands", + x: c, + p: h + }, f + }, f.rangeBand = function() { + return e + }, f.rangeExtent = function() { + return cf(b.x) + }, f.copy = function() { + return cx(a, b) + }, f.domain(a) + } + + function cC(a, b) { + function d() { + var d = 0, + f = a.length, + g = b.length; + c = []; + while (++d < g) c[d - 1] = d3.quantile(a, d / g); + return e + } + + function e(a) { + return isNaN(a = +a) ? NaN : b[d3.bisect(c, a)] + } + var c; + return e.domain = function(b) { + return arguments.length ? (a = b.filter(function(a) { + return !isNaN(a) + }).sort(d3.ascending), d()) : a + }, e.range = function(a) { + return arguments.length ? (b = a, d()) : b + }, e.quantiles = function() { + return c + }, e.copy = function() { + return cC(a, b) + }, d() + } + + function cD(a, b, c) { + function f(b) { + return c[Math.max(0, Math.min(e, Math.floor(d * (b - a))))] + } + + function g() { + return d = c.length / (b - a), e = c.length - 1, f + } + var d, e; + return f.domain = function(c) { + return arguments.length ? (a = +c[0], b = +c[c.length - 1], g()) : [a, b] + }, f.range = function(a) { + return arguments.length ? (c = a, g()) : c + }, f.copy = function() { + return cD(a, b, c) + }, g() + } + + function cE(a) { + function b(a) { + return +a + } + return b.invert = b, b.domain = b.range = function(c) { + return arguments.length ? (a = c.map(b), b) : a + }, b.ticks = function(b) { + return cn(a, b) + }, b.tickFormat = function(b) { + return co(a, b) + }, b.copy = function() { + return cE(a) + }, b + } + + function cH(a) { + return a.innerRadius + } + + function cI(a) { + return a.outerRadius + } + + function cJ(a) { + return a.startAngle + } + + function cK(a) { + return a.endAngle + } + + function cL(a) { + function h(e) { + function o() { + h.push("M", f(a(i), g)) + } + var h = [], + i = [], + j = -1, + k = e.length, + l, m = q(b), + n = q(c); + while (++j < k) d.call(this, l = e[j], j) ? i.push([+m.call(this, l, j), +n.call(this, l, j)]) : i.length && (o(), i = []); + return i.length && o(), h.length ? h.join("") : null + } + var b = cM, + c = cN, + d = p, + e = cO, + f = cQ, + g = .7; + return h.x = function(a) { + return arguments.length ? (b = a, h) : b + }, h.y = function(a) { + return arguments.length ? (c = a, h) : c + }, h.defined = function(a) { + return arguments.length ? (d = a, h) : d + }, h.interpolate = function(a) { + return arguments.length ? (cP.has(a += "") || (a = cO), f = cP.get(e = a), h) : e + }, h.tension = function(a) { + return arguments.length ? (g = a, h) : g + }, h + } + + function cM(a) { + return a[0] + } + + function cN(a) { + return a[1] + } + + function cQ(a) { + var b = 0, + c = a.length, + d = a[0], + e = [d[0], ",", d[1]]; + while (++b < c) e.push("L", (d = a[b])[0], ",", d[1]); + return e.join("") + } + + function cR(a) { + var b = 0, + c = a.length, + d = a[0], + e = [d[0], ",", d[1]]; + while (++b < c) e.push("V", (d = a[b])[1], "H", d[0]); + return e.join("") + } + + function cS(a) { + var b = 0, + c = a.length, + d = a[0], + e = [d[0], ",", d[1]]; + while (++b < c) e.push("H", (d = a[b])[0], "V", d[1]); + return e.join("") + } + + function cT(a, b) { + return a.length < 4 ? cQ(a) : a[1] + cW(a.slice(1, a.length - 1), cX(a, b)) + } + + function cU(a, b) { + return a.length < 3 ? cQ(a) : a[0] + cW((a.push(a[0]), a), cX([a[a.length - 2]].concat(a, [a[1]]), b)) + } + + function cV(a, b, c) { + return a.length < 3 ? cQ(a) : a[0] + cW(a, cX(a, b)) + } + + function cW(a, b) { + if (b.length < 1 || a.length != b.length && a.length != b.length + 2) return cQ(a); + var c = a.length != b.length, + d = "", + e = a[0], + f = a[1], + g = b[0], + h = g, + i = 1; + c && (d += "Q" + (f[0] - g[0] * 2 / 3) + "," + (f[1] - g[1] * 2 / 3) + "," + f[0] + "," + f[1], e = a[1], i = 2); + if (b.length > 1) { + h = b[1], f = a[i], i++, d += "C" + (e[0] + g[0]) + "," + (e[1] + g[1]) + "," + (f[0] - h[0]) + "," + (f[1] - h[1]) + "," + f[0] + "," + f[1]; + for (var j = 2; j < b.length; j++, i++) f = a[i], h = b[j], d += "S" + (f[0] - h[0]) + "," + (f[1] - h[1]) + "," + f[0] + "," + f[1] + } + if (c) { + var k = a[i]; + d += "Q" + (f[0] + h[0] * 2 / 3) + "," + (f[1] + h[1] * 2 / 3) + "," + k[0] + "," + k[1] + } + return d + } + + function cX(a, b) { + var c = [], + d = (1 - b) / 2, + e, f = a[0], + g = a[1], + h = 1, + i = a.length; + while (++h < i) e = f, f = g, g = a[h], c.push([d * (g[0] - e[0]), d * (g[1] - e[1])]); + return c + } + + function cY(a) { + if (a.length < 3) return cQ(a); + var b = 1, + c = a.length, + d = a[0], + e = d[0], + f = d[1], + g = [e, e, e, (d = a[1])[0]], + h = [f, f, f, d[1]], + i = [e, ",", f]; + de(i, g, h); + while (++b < c) d = a[b], g.shift(), g.push(d[0]), h.shift(), h.push(d[1]), de(i, g, h); + b = -1; + while (++b < 2) g.shift(), g.push(d[0]), h.shift(), h.push(d[1]), de(i, g, h); + return i.join("") + } + + function cZ(a) { + if (a.length < 4) return cQ(a); + var b = [], + c = -1, + d = a.length, + e, f = [0], + g = [0]; + while (++c < 3) e = a[c], f.push(e[0]), g.push(e[1]); + b.push(da(dd, f) + "," + da(dd, g)), --c; + while (++c < d) e = a[c], f.shift(), f.push(e[0]), g.shift(), g.push(e[1]), de(b, f, g); + return b.join("") + } + + function c$(a) { + var b, c = -1, + d = a.length, + e = d + 4, + f, g = [], + h = []; + while (++c < 4) f = a[c % d], g.push(f[0]), h.push(f[1]); + b = [da(dd, g), ",", da(dd, h)], --c; + while (++c < e) f = a[c % d], g.shift(), g.push(f[0]), h.shift(), h.push(f[1]), de(b, g, h); + return b.join("") + } + + function c_(a, b) { + var c = a.length - 1, + d = a[0][0], + e = a[0][1], + f = a[c][0] - d, + g = a[c][1] - e, + h = -1, + i, j; + while (++h <= c) i = a[h], j = h / c, i[0] = b * i[0] + (1 - b) * (d + j * f), i[1] = b * i[1] + (1 - b) * (e + j * g); + return cY(a) + } + + function da(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] + } + + function de(a, b, c) { + a.push("C", da(db, b), ",", da(db, c), ",", da(dc, b), ",", da(dc, c), ",", da(dd, b), ",", da(dd, c)) + } + + function df(a, b) { + return (b[1] - a[1]) / (b[0] - a[0]) + } + + function dg(a) { + var b = 0, + c = a.length - 1, + d = [], + e = a[0], + f = a[1], + g = d[0] = df(e, f); + while (++b < c) d[b] = g + (g = df(e = f, f = a[b + 1])); + return d[b] = g, d + } + + function dh(a) { + var b = [], + c, d, e, f, g = dg(a), + h = -1, + i = a.length - 1; + while (++h < i) c = df(a[h], a[h + 1]), Math.abs(c) < 1e-6 ? g[h] = g[h + 1] = 0 : (d = g[h] / c, e = g[h + 1] / c, f = d * d + e * e, f > 9 && (f = c * 3 / Math.sqrt(f), g[h] = f * d, g[h + 1] = f * e)); + h = -1; + while (++h <= i) f = (a[Math.min(i, h + 1)][0] - a[Math.max(0, h - 1)][0]) / (6 * (1 + g[h] * g[h])), b.push([f || 0, g[h] * f || 0]); + return b + } + + function di(a) { + return a.length < 3 ? cQ(a) : a[0] + cW(a, dh(a)) + } + + function dj(a) { + var b, c = -1, + d = a.length, + e, f; + while (++c < d) b = a[c], e = b[0], f = b[1] + cF, b[0] = e * Math.cos(f), b[1] = e * Math.sin(f); + return a + } + + function dk(a) { + function l(g) { + function y() { + l.push("M", h(a(n), k), j, i(a(m.reverse()), k), "Z") + } + var l = [], + m = [], + n = [], + o = -1, + p = g.length, + r, s = q(b), + t = q(d), + u = b === c ? function() { + return w + } : q(c), + v = d === e ? function() { + return x + } : q(e), + w, x; + while (++o < p) f.call(this, r = g[o], o) ? (m.push([w = +s.call(this, r, o), x = +t.call(this, r, o)]), n.push([+u.call(this, r, o), +v.call(this, r, o)])) : m.length && (y(), m = [], n = []); + return m.length && y(), l.length ? l.join("") : null + } + var b = cM, + c = cM, + d = 0, + e = cN, + f = p, + g = cO, + h = cQ, + i = cQ, + j = "L", + k = .7; + return l.x = function(a) { + return arguments.length ? (b = c = a, l) : c + }, l.x0 = function(a) { + return arguments.length ? (b = a, l) : b + }, l.x1 = function(a) { + return arguments.length ? (c = a, l) : c + }, l.y = function(a) { + return arguments.length ? (d = e = a, l) : e + }, l.y0 = function(a) { + return arguments.length ? (d = a, l) : d + }, l.y1 = function(a) { + return arguments.length ? (e = a, l) : e + }, l.defined = function(a) { + return arguments.length ? (f = a, l) : f + }, l.interpolate = function(a) { + return arguments.length ? (cP.has(a += "") || (a = cO), h = cP.get(g = a), i = h.reverse || h, j = /-closed$/.test(a) ? "M" : "L", l) : g + }, l.tension = function(a) { + return arguments.length ? (k = a, l) : k + }, l + } + + function dl(a) { + return a.source + } + + function dm(a) { + return a.target + } + + function dn(a) { + return a.radius + } + + function dp(a) { + return a.startAngle + } + + function dq(a) { + return a.endAngle + } + + function dr(a) { + return [a.x, a.y] + } + + function ds(a) { + return function() { + var b = a.apply(this, arguments), + c = b[0], + d = b[1] + cF; + return [c * Math.cos(d), c * Math.sin(d)] + } + } + + function dt() { + return 64 + } + + function du() { + return "circle" + } + + function dv(a) { + var b = Math.sqrt(a / Math.PI); + return "M0," + b + "A" + b + "," + b + " 0 1,1 0," + -b + "A" + b + "," + b + " 0 1,1 0," + b + "Z" + } + + function dz(a, b) { + a.attr("transform", function(a) { + return "translate(" + b(a) + ",0)" + }) + } + + function dA(a, b) { + a.attr("transform", function(a) { + return "translate(0," + b(a) + ")" + }) + } + + function dB(a, b, c) { + e = []; + if (c && b.length > 1) { + var d = cf(a.domain()), + e, f = -1, + g = b.length, + h = (b[1] - b[0]) / ++c, + i, j; + while (++f < g) + for (i = c; --i > 0;)(j = +b[f] - i * h) >= d[0] && e.push(j); + for (--f, i = 0; ++i < c && (j = +b[f] + i * h) < d[1];) e.push(j) + } + return e + } + + function dG() { + dE || (dE = d3.select("body").append("div").style("visibility", "hidden").style("top", 0).style("height", 0).style("width", 0).style("overflow-y", "scroll").append("div").style("height", "2000px").node().parentNode); + var a = d3.event, + b; + try { + dE.scrollTop = 1e3, dE.dispatchEvent(a), b = 1e3 - dE.scrollTop + } catch (c) { + b = a.wheelDelta || -a.detail * 5 + } + return b + } + + function dH(a) { + var b = a.source, + c = a.target, + d = dJ(b, c), + e = [b]; + while (b !== d) b = b.parent, e.push(b); + var f = e.length; + while (c !== d) e.splice(f, 0, c), c = c.parent; + return e + } + + function dI(a) { + var b = [], + c = a.parent; + while (c != null) b.push(a), a = c, c = c.parent; + return b.push(a), b + } + + function dJ(a, b) { + if (a === b) return a; + var c = dI(a), + d = dI(b), + e = c.pop(), + f = d.pop(), + g = null; + while (e === f) g = e, e = c.pop(), f = d.pop(); + return g + } + + function dM(a) { + a.fixed |= 2 + } + + function dN(a) { + a !== dL && (a.fixed &= 1) + } + + function dO() { + dL.fixed &= 1, dK = dL = null + } + + function dP() { + dL.px = d3.event.x, dL.py = d3.event.y, dK.resume() + } + + function dQ(a, b, c) { + var d = 0, + e = 0; + a.charge = 0; + if (!a.leaf) { + var f = a.nodes, + g = f.length, + h = -1, + i; + while (++h < g) { + i = f[h]; + if (i == null) continue; + dQ(i, b, c), a.charge += i.charge, d += i.charge * i.cx, e += i.charge * i.cy + } + } + if (a.point) { + a.leaf || (a.point.x += Math.random() - .5, a.point.y += Math.random() - .5); + var j = b * c[a.point.index]; + a.charge += a.pointCharge = j, d += j * a.point.x, e += j * a.point.y + } + a.cx = d / a.charge, a.cy = e / a.charge + } + + function dR(a) { + return 20 + } + + function dS(a) { + return 1 + } + + function dU(a) { + return a.x + } + + function dV(a) { + return a.y + } + + function dW(a, b, c) { + a.y0 = b, a.y = c + } + + function dZ(a) { + return d3.range(a.length) + } + + function d$(a) { + var b = -1, + c = a[0].length, + d = []; + while (++b < c) d[b] = 0; + return d + } + + function d_(a) { + var b = 1, + c = 0, + d = a[0][1], + e, f = a.length; + for (; b < f; ++b)(e = a[b][1]) > d && (c = b, d = e); + return c + } + + function ea(a) { + return a.reduce(eb, 0) + } + + function eb(a, b) { + return a + b[1] + } + + function ec(a, b) { + return ed(a, Math.ceil(Math.log(b.length) / Math.LN2 + 1)) + } + + function ed(a, b) { + var c = -1, + d = +a[0], + e = (a[1] - d) / b, + f = []; + while (++c <= b) f[c] = e * c + d; + return f + } + + function ee(a) { + return [d3.min(a), d3.max(a)] + } + + function ef(a, b) { + return d3.rebind(a, b, "sort", "children", "value"), a.links = ej, a.nodes = function(b) { + return ek = !0, (a.nodes = a)(b) + }, a + } + + function eg(a) { + return a.children + } + + function eh(a) { + return a.value + } + + function ei(a, b) { + return b.value - a.value + } + + function ej(a) { + return d3.merge(a.map(function(a) { + return (a.children || []).map(function(b) { + return { + source: a, + target: b + } + }) + })) + } + + function el(a, b) { + return a.value - b.value + } + + function em(a, b) { + var c = a._pack_next; + a._pack_next = b, b._pack_prev = a, b._pack_next = c, c._pack_prev = b + } + + function en(a, b) { + a._pack_next = b, b._pack_prev = a + } + + function eo(a, b) { + var c = b.x - a.x, + d = b.y - a.y, + e = a.r + b.r; + return e * e - c * c - d * d > .001 + } + + function ep(a) { + function l(a) { + b = Math.min(a.x - a.r, b), c = Math.max(a.x + a.r, c), d = Math.min(a.y - a.r, d), e = Math.max(a.y + a.r, e) + } + var b = Infinity, + c = -Infinity, + d = Infinity, + e = -Infinity, + f = a.length, + g, h, i, j, k; + a.forEach(eq), g = a[0], g.x = -g.r, g.y = 0, l(g); + if (f > 1) { + h = a[1], h.x = h.r, h.y = 0, l(h); + if (f > 2) { + i = a[2], eu(g, h, i), l(i), em(g, i), g._pack_prev = i, em(i, h), h = g._pack_next; + for (var m = 3; m < f; m++) { + eu(g, h, i = a[m]); + var n = 0, + o = 1, + p = 1; + for (j = h._pack_next; j !== h; j = j._pack_next, o++) + if (eo(j, i)) { + n = 1; + break + } + if (n == 1) + for (k = g._pack_prev; k !== j._pack_prev; k = k._pack_prev, p++) + if (eo(k, i)) break; + n ? (o < p || o == p && h.r < g.r ? en(g, h = j) : en(g = k, h), m--) : (em(g, i), h = i, l(i)) + } + } + } + var q = (b + c) / 2, + r = (d + e) / 2, + s = 0; + for (var m = 0; m < f; m++) { + var t = a[m]; + t.x -= q, t.y -= r, s = Math.max(s, t.r + Math.sqrt(t.x * t.x + t.y * t.y)) + } + return a.forEach(er), s + } + + function eq(a) { + a._pack_next = a._pack_prev = a + } + + function er(a) { + delete a._pack_next, delete a._pack_prev + } + + function es(a) { + var b = a.children; + b && b.length ? (b.forEach(es), a.r = ep(b)) : a.r = Math.sqrt(a.value) + } + + function et(a, b, c, d) { + var e = a.children; + a.x = b += d * a.x, a.y = c += d * a.y, a.r *= d; + if (e) { + var f = -1, + g = e.length; + while (++f < g) et(e[f], b, c, d) + } + } + + function eu(a, b, c) { + var d = a.r + c.r, + e = b.x - a.x, + f = b.y - a.y; + if (d && (e || f)) { + var g = b.r + c.r, + h = Math.sqrt(e * e + f * f), + i = Math.max(-1, Math.min(1, (d * d + h * h - g * g) / (2 * d * h))), + j = Math.acos(i), + k = i * (d /= h), + l = Math.sin(j) * d; + c.x = a.x + k * e + l * f, c.y = a.y + k * f - l * e + } else c.x = a.x + d, c.y = a.y + } + + function ev(a) { + return 1 + d3.max(a, function(a) { + return a.y + }) + } + + function ew(a) { + return a.reduce(function(a, b) { + return a + b.x + }, 0) / a.length + } + + function ex(a) { + var b = a.children; + return b && b.length ? ex(b[0]) : a + } + + function ey(a) { + var b = a.children, + c; + return b && (c = b.length) ? ey(b[c - 1]) : a + } + + function ez(a, b) { + return a.parent == b.parent ? 1 : 2 + } + + function eA(a) { + var b = a.children; + return b && b.length ? b[0] : a._tree.thread + } + + function eB(a) { + var b = a.children, + c; + return b && (c = b.length) ? b[c - 1] : a._tree.thread + } + + function eC(a, b) { + var c = a.children; + if (c && (e = c.length)) { + var d, e, f = -1; + while (++f < e) b(d = eC(c[f], b), a) > 0 && (a = d) + } + return a + } + + function eD(a, b) { + return a.x - b.x + } + + function eE(a, b) { + return b.x - a.x + } + + function eF(a, b) { + return a.depth - b.depth + } + + function eG(a, b) { + function c(a, d) { + var e = a.children; + if (e && (i = e.length)) { + var f, g = null, + h = -1, + i; + while (++h < i) f = e[h], c(f, g), g = f + } + b(a, d) + } + c(a, null) + } + + function eH(a) { + var b = 0, + c = 0, + d = a.children, + e = d.length, + f; + while (--e >= 0) f = d[e]._tree, f.prelim += b, f.mod += b, b += f.shift + (c += f.change) + } + + function eI(a, b, c) { + a = a._tree, b = b._tree; + var d = c / (b.number - a.number); + a.change += d, b.change -= d, b.shift += c, b.prelim += c, b.mod += c + } + + function eJ(a, b, c) { + return a._tree.ancestor.parent == b.parent ? a._tree.ancestor : c + } + + function eK(a) { + return { + x: a.x, + y: a.y, + dx: a.dx, + dy: a.dy + } + } + + function eL(a, b) { + var c = a.x + b[3], + d = a.y + b[0], + e = a.dx - b[1] - b[3], + f = a.dy - b[0] - b[2]; + return e < 0 && (c += e / 2, e = 0), f < 0 && (d += f / 2, f = 0), { + x: c, + y: d, + dx: e, + dy: f + } + } + + function eM(a) { + return a.map(eN).join(",") + } + + function eN(a) { + return /[",\n]/.test(a) ? '"' + a.replace(/\"/g, '""') + '"' : a + } + + function eP(a, b) { + return function(c) { + return c && a.hasOwnProperty(c.type) ? a[c.type](c) : b + } + } + + function eQ(a) { + return "m0," + a + "a" + a + "," + a + " 0 1,1 0," + -2 * a + "a" + a + "," + a + " 0 1,1 0," + 2 * a + "z" + } + + function eR(a, b) { + eS.hasOwnProperty(a.type) && eS[a.type](a, b) + } + + function eT(a, b) { + eR(a.geometry, b) + } + + function eU(a, b) { + for (var c = a.features, d = 0, e = c.length; d < e; d++) eR(c[d].geometry, b) + } + + function eV(a, b) { + for (var c = a.geometries, d = 0, e = c.length; d < e; d++) eR(c[d], b) + } + + function eW(a, b) { + for (var c = a.coordinates, d = 0, e = c.length; d < e; d++) b.apply(null, c[d]) + } + + function eX(a, b) { + for (var c = a.coordinates, d = 0, e = c.length; d < e; d++) + for (var f = c[d], g = 0, h = f.length; g < h; g++) b.apply(null, f[g]) + } + + function eY(a, b) { + for (var c = a.coordinates, d = 0, e = c.length; d < e; d++) + for (var f = c[d][0], g = 0, h = f.length; g < h; g++) b.apply(null, f[g]) + } + + function eZ(a, b) { + b.apply(null, a.coordinates) + } + + function e$(a, b) { + for (var c = a.coordinates[0], d = 0, e = c.length; d < e; d++) b.apply(null, c[d]) + } + + function e_(a) { + return a.source + } + + function fa(a) { + return a.target + } + + function fb(a, b) { + function q(a) { + var b = Math.sin(o - (a *= o)) / p, + c = Math.sin(a) / p, + f = b * g * d + c * m * j, + i = b * g * e + c * m * k, + l = b * h + c * n; + return [Math.atan2(i, f) / eO, Math.atan2(l, Math.sqrt(f * f + i * i)) / eO] + } + var c = a[0] * eO, + d = Math.cos(c), + e = Math.sin(c), + f = a[1] * eO, + g = Math.cos(f), + h = Math.sin(f), + i = b[0] * eO, + j = Math.cos(i), + k = Math.sin(i), + l = b[1] * eO, + m = Math.cos(l), + n = Math.sin(l), + o = q.d = Math.acos(Math.max(-1, Math.min(1, h * n + g * m * Math.cos(i - c)))), + p = Math.sin(o); + return q + } + + function fe(a) { + var b = 0, + c = 0; + for (;;) { + if (a(b, c)) return [b, c]; + b === 0 ? (b = c + 1, c = 0) : (b -= 1, c += 1) + } + } + + function ff(a, b, c, d) { + var e, f, g, h, i, j, k; + return e = d[a], f = e[0], g = e[1], e = d[b], h = e[0], i = e[1], e = d[c], j = e[0], k = e[1], (k - g) * (h - f) - (i - g) * (j - f) > 0 + } + + function fg(a, b, c) { + return (c[0] - b[0]) * (a[1] - b[1]) < (c[1] - b[1]) * (a[0] - b[0]) + } + + function fh(a, b, c, d) { + var e = a[0], + f = b[0], + g = c[0], + h = d[0], + i = a[1], + j = b[1], + k = c[1], + l = d[1], + m = e - g, + n = f - e, + o = h - g, + p = i - k, + q = j - i, + r = l - k, + s = (o * p - r * m) / (r * n - o * q); + return [e + s * n, i + s * q] + } + + function fj(a, b) { + var c = { + list: a.map(function(a, b) { + return { + index: b, + x: a[0], + y: a[1] + } + }).sort(function(a, b) { + return a.y < b.y ? -1 : a.y > b.y ? 1 : a.x < b.x ? -1 : a.x > b.x ? 1 : 0 + }), + bottomSite: null + }, + d = { + list: [], + leftEnd: null, + rightEnd: null, + init: function() { + d.leftEnd = d.createHalfEdge(null, "l"), d.rightEnd = d.createHalfEdge(null, "l"), d.leftEnd.r = d.rightEnd, d.rightEnd.l = d.leftEnd, d.list.unshift(d.leftEnd, d.rightEnd) + }, + createHalfEdge: function(a, b) { + return { + edge: a, + side: b, + vertex: null, + l: null, + r: null + } + }, + insert: function(a, b) { + b.l = a, b.r = a.r, a.r.l = b, a.r = b + }, + leftBound: function(a) { + var b = d.leftEnd; + do b = b.r; while (b != d.rightEnd && e.rightOf(b, a)); + return b = b.l, b + }, + del: function(a) { + a.l.r = a.r, a.r.l = a.l, a.edge = null + }, + right: function(a) { + return a.r + }, + left: function(a) { + return a.l + }, + leftRegion: function(a) { + return a.edge == null ? c.bottomSite : a.edge.region[a.side] + }, + rightRegion: function(a) { + return a.edge == null ? c.bottomSite : a.edge.region[fi[a.side]] + } + }, + e = { + bisect: function(a, b) { + var c = { + region: { + l: a, + r: b + }, + ep: { + l: null, + r: null + } + }, + d = b.x - a.x, + e = b.y - a.y, + f = d > 0 ? d : -d, + g = e > 0 ? e : -e; + return c.c = a.x * d + a.y * e + (d * d + e * e) * .5, f > g ? (c.a = 1, c.b = e / d, c.c /= d) : (c.b = 1, c.a = d / e, c.c /= e), c + }, + intersect: function(a, b) { + var c = a.edge, + d = b.edge; + if (!c || !d || c.region.r == d.region.r) return null; + var e = c.a * d.b - c.b * d.a; + if (Math.abs(e) < 1e-10) return null; + var f = (c.c * d.b - d.c * c.b) / e, + g = (d.c * c.a - c.c * d.a) / e, + h = c.region.r, + i = d.region.r, + j, k; + h.y < i.y || h.y == i.y && h.x < i.x ? (j = a, k = c) : (j = b, k = d); + var l = f >= k.region.r.x; + return l && j.side === "l" || !l && j.side === "r" ? null : { + x: f, + y: g + } + }, + rightOf: function(a, b) { + var c = a.edge, + d = c.region.r, + e = b.x > d.x; + if (e && a.side === "l") return 1; + if (!e && a.side === "r") return 0; + if (c.a === 1) { + var f = b.y - d.y, + g = b.x - d.x, + h = 0, + i = 0; + !e && c.b < 0 || e && c.b >= 0 ? i = h = f >= c.b * g : (i = b.x + b.y * c.b > c.c, c.b < 0 && (i = !i), i || (h = 1)); + if (!h) { + var j = d.x - c.region.l.x; + i = c.b * (g * g - f * f) < j * f * (1 + 2 * g / j + c.b * c.b), c.b < 0 && (i = !i) + } + } else { + var k = c.c - c.a * b.x, + l = b.y - k, + m = b.x - d.x, + n = k - d.y; + i = l * l > m * m + n * n + } + return a.side === "l" ? i : !i + }, + endPoint: function(a, c, d) { + a.ep[c] = d; + if (!a.ep[fi[c]]) return; + b(a) + }, + distance: function(a, b) { + var c = a.x - b.x, + d = a.y - b.y; + return Math.sqrt(c * c + d * d) + } + }, + f = { + list: [], + insert: function(a, b, c) { + a.vertex = b, a.ystar = b.y + c; + for (var d = 0, e = f.list, g = e.length; d < g; d++) { + var h = e[d]; + if (a.ystar > h.ystar || a.ystar == h.ystar && b.x > h.vertex.x) continue; + break + } + e.splice(d, 0, a) + }, + del: function(a) { + for (var b = 0, c = f.list, d = c.length; b < d && c[b] != a; ++b); + c.splice(b, 1) + }, + empty: function() { + return f.list.length === 0 + }, + nextEvent: function(a) { + for (var b = 0, c = f.list, d = c.length; b < d; ++b) + if (c[b] == a) return c[b + 1]; + return null + }, + min: function() { + var a = f.list[0]; + return { + x: a.vertex.x, + y: a.ystar + } + }, + extractMin: function() { + return f.list.shift() + } + }; + d.init(), c.bottomSite = c.list.shift(); + var g = c.list.shift(), + h, i, j, k, l, m, n, o, p, q, r, s, t; + for (;;) { + f.empty() || (h = f.min()); + if (g && (f.empty() || g.y < h.y || g.y == h.y && g.x < h.x)) i = d.leftBound(g), j = d.right(i), n = d.rightRegion(i), s = e.bisect(n, g), m = d.createHalfEdge(s, "l"), d.insert(i, m), q = e.intersect(i, m), q && (f.del(i), f.insert(i, q, e.distance(q, g))), i = m, m = d.createHalfEdge(s, "r"), d.insert(i, m), q = e.intersect(m, j), q && f.insert(m, q, e.distance(q, g)), g = c.list.shift(); + else if (!f.empty()) i = f.extractMin(), k = d.left(i), j = d.right(i), l = d.right(j), n = d.leftRegion(i), o = d.rightRegion(j), r = i.vertex, e.endPoint(i.edge, i.side, r), e.endPoint(j.edge, j.side, r), d.del(i), f.del(j), d.del(j), t = "l", n.y > o.y && (p = n, n = o, o = p, t = "r"), s = e.bisect(n, o), m = d.createHalfEdge(s, t), d.insert(k, m), e.endPoint(s, fi[t], r), q = e.intersect(k, m), q && (f.del(k), f.insert(k, q, e.distance(q, n))), q = e.intersect(m, l), q && f.insert(m, q, e.distance(q, n)); + else break + } + for (i = d.right(d.leftEnd); i != d.rightEnd; i = d.right(i)) b(i.edge) + } + + function fk() { + return { + leaf: !0, + nodes: [], + point: null + } + } + + function fl(a, b, c, d, e, f) { + if (!a(b, c, d, e, f)) { + var g = (c + e) * .5, + h = (d + f) * .5, + i = b.nodes; + i[0] && fl(a, i[0], c, d, g, h), i[1] && fl(a, i[1], g, d, e, h), i[2] && fl(a, i[2], c, h, g, f), i[3] && fl(a, i[3], g, h, e, f) + } + } + + function fm(a) { + return { + x: a[0], + y: a[1] + } + } + + function fo() { + this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]) + } + + function fq(a, b, c, d) { + var e, f, g = 0, + h = b.length, + i = c.length; + while (g < h) { + if (d >= i) return -1; + e = b.charCodeAt(g++); + if (e == 37) { + f = fw[b.charAt(g++)]; + if (!f || (d = f(a, c, d)) < 0) return -1 + } else if (e != c.charCodeAt(d++)) return -1 + } + return d + } + + function fx(a, b, c) { + return fz.test(b.substring(c, c += 3)) ? c : -1 + } + + function fy(a, b, c) { + fA.lastIndex = 0; + var d = fA.exec(b.substring(c, c + 10)); + return d ? c += d[0].length : -1 + } + + function fC(a, b, c) { + var d = fD.get(b.substring(c, c += 3).toLowerCase()); + return d == null ? -1 : (a.m = d, c) + } + + function fE(a, b, c) { + fF.lastIndex = 0; + var d = fF.exec(b.substring(c, c + 12)); + return d ? (a.m = fG.get(d[0].toLowerCase()), c += d[0].length) : -1 + } + + function fI(a, b, c) { + return fq(a, fv.c.toString(), b, c) + } + + function fJ(a, b, c) { + return fq(a, fv.x.toString(), b, c) + } + + function fK(a, b, c) { + return fq(a, fv.X.toString(), b, c) + } + + function fL(a, b, c) { + fU.lastIndex = 0; + var d = fU.exec(b.substring(c, c + 4)); + return d ? (a.y = +d[0], c += d[0].length) : -1 + } + + function fM(a, b, c) { + fU.lastIndex = 0; + var d = fU.exec(b.substring(c, c + 2)); + return d ? (a.y = fN() + +d[0], c += d[0].length) : -1 + } + + function fN() { + return ~~((new Date).getFullYear() / 1e3) * 1e3 + } + + function fO(a, b, c) { + fU.lastIndex = 0; + var d = fU.exec(b.substring(c, c + 2)); + return d ? (a.m = d[0] - 1, c += d[0].length) : -1 + } + + function fP(a, b, c) { + fU.lastIndex = 0; + var d = fU.exec(b.substring(c, c + 2)); + return d ? (a.d = +d[0], c += d[0].length) : -1 + } + + function fQ(a, b, c) { + fU.lastIndex = 0; + var d = fU.exec(b.substring(c, c + 2)); + return d ? (a.H = +d[0], c += d[0].length) : -1 + } + + function fR(a, b, c) { + fU.lastIndex = 0; + var d = fU.exec(b.substring(c, c + 2)); + return d ? (a.M = +d[0], c += d[0].length) : -1 + } + + function fS(a, b, c) { + fU.lastIndex = 0; + var d = fU.exec(b.substring(c, c + 2)); + return d ? (a.S = +d[0], c += d[0].length) : -1 + } + + function fT(a, b, c) { + fU.lastIndex = 0; + var d = fU.exec(b.substring(c, c + 3)); + return d ? (a.L = +d[0], c += d[0].length) : -1 + } + + function fV(a, b, c) { + var d = fW.get(b.substring(c, c += 2).toLowerCase()); + return d == null ? -1 : (a.p = d, c) + } + + function fX(a) { + var b = a.getTimezoneOffset(), + c = b > 0 ? "-" : "+", + d = ~~(Math.abs(b) / 60), + e = Math.abs(b) % 60; + return c + fr(d) + fr(e) + } + + function fZ(a) { + return a.toISOString() + } + + function f$(a, b, c) { + function d(b) { + var c = a(b), + d = f(c, 1); + return b - c < d - b ? c : d + } + + function e(c) { + return b(c = a(new fn(c - 1)), 1), c + } + + function f(a, c) { + return b(a = new fn(+a), c), a + } + + function g(a, d, f) { + var g = e(a), + h = []; + if (f > 1) + while (g < d) c(g) % f || h.push(new Date(+g)), b(g, 1); + else + while (g < d) h.push(new Date(+g)), b(g, 1); + return h + } + + function h(a, b, c) { + try { + fn = fo; + var d = new fo; + return d._ = a, g(d, b, c) + } finally { + fn = Date + } + } + a.floor = a, a.round = d, a.ceil = e, a.offset = f, a.range = g; + var i = a.utc = f_(a); + return i.floor = i, i.round = f_(d), i.ceil = f_(e), i.offset = f_(f), i.range = h, a + } + + function f_(a) { + return function(b, c) { + try { + fn = fo; + var d = new fo; + return d._ = b, a(d, c)._ + } finally { + fn = Date + } + } + } + + function ga(a, b, c) { + function d(b) { + return a( + b) + } + return d.invert = function(b) { + return gc(a.invert(b)) + }, d.domain = function(b) { + return arguments.length ? (a.domain(b), d) : a.domain().map(gc) + }, d.nice = function(a) { + var b = gb(d.domain()); + return d.domain([a.floor(b[0]), a.ceil(b[1])]) + }, d.ticks = function(c, e) { + var f = gb(d.domain()); + if (typeof c != "function") { + var g = f[1] - f[0], + h = g / c, + i = d3.bisect(gg, h); + if (i == gg.length) return b.year(f, c); + if (!i) return a.ticks(c).map(gc); + Math.log(h / gg[i - 1]) < Math.log(gg[i] / h) && --i, c = b[i], e = c[1], c = c[0].range + } + return c(f[0], new Date(+f[1] + 1), e) + }, d.tickFormat = function() { + return c + }, d.copy = function() { + return ga(a.copy(), b, c) + }, d3.rebind(d, a, "range", "rangeRound", "interpolate", "clamp") + } + + function gb(a) { + var b = a[0], + c = a[a.length - 1]; + return b < c ? [b, c] : [c, b] + } + + function gc(a) { + return new Date(a) + } + + function gd(a) { + return function(b) { + var c = a.length - 1, + d = a[c]; + while (!d[1](b)) d = a[--c]; + return d[0](b) + } + } + + function ge(a) { + var b = new Date(a, 0, 1); + return b.setFullYear(a), b + } + + function gf(a) { + var b = a.getFullYear(), + c = ge(b), + d = ge(b + 1); + return b + (a - c) / (d - c) + } + + function go(a) { + var b = new Date(Date.UTC(a, 0, 1)); + return b.setUTCFullYear(a), b + } + + function gp(a) { + var b = a.getUTCFullYear(), + c = go(b), + d = go(b + 1); + return b + (a - c) / (d - c) + } + Date.now || (Date.now = function() { + return +(new Date) + }); + try { + document.createElement("div").style.setProperty("opacity", 0, "") + } catch (a) { + var b = CSSStyleDeclaration.prototype, + c = b.setProperty; + b.setProperty = function(a, b, d) { + c.call(this, a, b + "", d) + } + } + d3 = { + version: "2.9.1" + }; + var f = h; + try { + f(document.documentElement.childNodes)[0].nodeType + } catch (i) { + f = g + } + var j = [].__proto__ ? function(a, b) { + a.__proto__ = b + } : function(a, b) { + for (var c in b) a[c] = b[c] + }; + d3.map = function(a) { + var b = new k; + for (var c in a) b.set(c, a[c]); + return b + }, e(k, { + has: function(a) { + return l + a in this + }, + get: function(a) { + return this[l + a] + }, + set: function(a, b) { + return this[l + a] = b + }, + remove: function(a) { + return a = l + a, a in this && delete this[a] + }, + keys: function() { + var a = []; + return this.forEach(function(b) { + a.push(b) + }), a + }, + values: function() { + var a = []; + return this.forEach(function(b, c) { + a.push(c) + }), a + }, + entries: function() { + var a = []; + return this.forEach(function(b, c) { + a.push({ + key: b, + value: c + }) + }), a + }, + forEach: function(a) { + for (var b in this) b.charCodeAt(0) === m && a.call(this, b.substring(1), this[b]) + } + }); + var l = "\0", + m = l.charCodeAt(0); + d3.functor = q, d3.rebind = function(a, b) { + var c = 1, + d = arguments.length, + e; + while (++c < d) a[e = arguments[c]] = r(a, b, b[e]); + return a + }, d3.ascending = function(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN + }, d3.descending = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN + }, d3.mean = function(a, b) { + var c = a.length, + d, e = 0, + f = -1, + g = 0; + if (arguments.length === 1) + while (++f < c) s(d = a[f]) && (e += (d - e) / ++g); + else + while (++f < c) s(d = b.call(a, a[f], f)) && (e += (d - e) / ++g); + return g ? e : undefined + }, d3.median = function(a, b) { + return arguments.length > 1 && (a = a.map(b)), a = a.filter(s), a.length ? d3.quantile(a.sort(d3.ascending), .5) : undefined + }, d3.min = function(a, b) { + var c = -1, + d = a.length, + e, f; + if (arguments.length === 1) { + while (++c < d && ((e = a[c]) == null || e != e)) e = undefined; + while (++c < d)(f = a[c]) != null && e > f && (e = f) + } else { + while (++c < d && ((e = b.call(a, a[c], c)) == null || e != e)) e = undefined; + while (++c < d)(f = b.call(a, a[c], c)) != null && e > f && (e = f) + } + return e + }, d3.max = function(a, b) { + var c = -1, + d = a.length, + e, f; + if (arguments.length === 1) { + while (++c < d && ((e = a[c]) == null || e != e)) e = undefined; + while (++c < d)(f = a[c]) != null && f > e && (e = f) + } else { + while (++c < d && ((e = b.call(a, a[c], c)) == null || e != e)) e = undefined; + while (++c < d)(f = b.call(a, a[c], c)) != null && f > e && (e = f) + } + return e + }, d3.extent = function(a, b) { + var c = -1, + d = a.length, + e, f, g; + if (arguments.length === 1) { + while (++c < d && ((e = g = a[c]) == null || e != e)) e = g = undefined; + while (++c < d)(f = a[c]) != null && (e > f && (e = f), g < f && (g = f)) + } else { + while (++c < d && ((e = g = b.call(a, a[c], c)) == null || e != e)) e = undefined; + while (++c < d)(f = b.call(a, a[c], c)) != null && (e > f && (e = f), g < f && (g = f)) + } + return [e, g] + }, d3.random = { + normal: function(a, b) { + return arguments.length < 2 && (b = 1), arguments.length < 1 && (a = 0), + function() { + var c, d, e; + do c = Math.random() * 2 - 1, d = Math.random() * 2 - 1, e = c * c + d * d; while (!e || e > 1); + return a + b * c * Math.sqrt(-2 * Math.log(e) / e) + } + } + }, d3.sum = function(a, b) { + var c = 0, + d = a.length, + e, f = -1; + if (arguments.length === 1) + while (++f < d) isNaN(e = +a[f]) || (c += e); + else + while (++f < d) isNaN(e = +b.call(a, a[f], f)) || (c += e); + return c + }, d3.quantile = function(a, b) { + var c = (a.length - 1) * b + 1, + d = Math.floor(c), + e = a[d - 1], + f = c - d; + return f ? e + f * (a[d] - e) : e + }, d3.transpose = function(a) { + return d3.zip.apply(d3, a) + }, d3.zip = function() { + if (!(e = arguments.length)) return []; + for (var a = -1, b = d3.min(arguments, t), c = new Array(b); ++a < b;) + for (var d = -1, e, f = c[a] = new Array(e); ++d < e;) f[d] = arguments[d][a]; + return c + }, d3.bisector = function(a) { + return { + left: function(b, c, d, e) { + arguments.length < 3 && (d = 0), arguments.length < 4 && (e = b.length); + while (d < e) { + var f = d + e >> 1; + a.call(b, b[f], f) < c ? d = f + 1 : e = f + } + return d + }, + right: function(b, c, d, e) { + arguments.length < 3 && (d = 0), arguments.length < 4 && (e = b.length); + while (d < e) { + var f = d + e >> 1; + c < a.call(b, b[f], f) ? e = f : d = f + 1 + } + return d + } + } + }; + var u = d3.bisector(function(a) { + return a + }); + d3.bisectLeft = u.left, d3.bisect = d3.bisectRight = u.right, d3.first = function(a, b) { + var c = 0, + d = a.length, + e = a[0], + f; + arguments.length === 1 && (b = d3.ascending); + while (++c < d) b.call(a, e, f = a[c]) > 0 && (e = f); + return e + }, d3.last = function(a, b) { + var c = 0, + d = a.length, + e = a[0], + f; + arguments.length === 1 && (b = d3.ascending); + while (++c < d) b.call(a, e, f = a[c]) <= 0 && (e = f); + return e + }, d3.nest = function() { + function f(c, g) { + if (g >= b.length) return e ? e.call(a, c) : d ? c.sort(d) : c; + var h = -1, + i = c.length, + j = b[g++], + l, m, n = new k, + o, p = {}; + while (++h < i)(o = n.get(l = j(m = c[h]))) ? o.push(m) : n.set(l, [m]); + return n.forEach(function(a) { + p[a] = f(n.get(a), g) + }), p + } + + function g(a, d) { + if (d >= b.length) return a; + var e = [], + f = c[d++], + h; + for (h in a) e.push({ + key: h, + values: g(a[h], d) + }); + return f && e.sort(function(a, b) { + return f(a.key, b.key) + }), e + } + var a = {}, + b = [], + c = [], + d, e; + return a.map = function(a) { + return f(a, 0) + }, a.entries = function(a) { + return g(f(a, 0), 0) + }, a.key = function(c) { + return b.push(c), a + }, a.sortKeys = function(d) { + return c[b.length - 1] = d, a + }, a.sortValues = function(b) { + return d = b, a + }, a.rollup = function(b) { + return e = b, a + }, a + }, d3.keys = function(a) { + var b = []; + for (var c in a) b.push(c); + return b + }, d3.values = function(a) { + var b = []; + for (var c in a) b.push(a[c]); + return b + }, d3.entries = function(a) { + var b = []; + for (var c in a) b.push({ + key: c, + value: a[c] + }); + return b + }, d3.permute = function(a, b) { + var c = [], + d = -1, + e = b.length; + while (++d < e) c[d] = a[b[d]]; + return c + }, d3.merge = function(a) { + return Array.prototype.concat.apply([], a) + }, d3.split = function(a, b) { + var c = [], + d = [], + e, f = -1, + g = a.length; + arguments.length < 2 && (b = v); + while (++f < g) b.call(d, e = a[f], f) ? d = [] : (d.length || c.push(d), d.push(e)); + return c + }, d3.range = function(a, b, c) { + arguments.length < 3 && (c = 1, arguments.length < 2 && (b = a, a = 0)); + if ((b - a) / c === Infinity) throw new Error("infinite range"); + var d = [], + e = x(Math.abs(c)), + f = -1, + g; + a *= e, b *= e, c *= e; + if (c < 0) + while ((g = a + c * ++f) > b) d.push(g / e); + else + while ((g = a + c * ++f) < b) d.push(g / e); + return d + }, d3.requote = function(a) { + return a.replace(y, "\\$&") + }; + var y = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + d3.round = function(a, b) { + return b ? Math.round(a * (b = Math.pow(10, b))) / b : Math.round(a) + }, d3.xhr = function(a, b, c) { + var d = new XMLHttpRequest; + arguments.length < 3 ? (c = b, b = null) : b && d.overrideMimeType && d.overrideMimeType(b), d.open("GET", a, !0), b && d.setRequestHeader("Accept", b), d.onreadystatechange = function() { + if (d.readyState === 4) { + var a = d.status; + c(a >= 200 && a < 300 || a === 304 ? d : null) + } + }, d.send(null) + }, d3.text = function(a, b, c) { + function d(a) { + c(a && a.responseText) + } + arguments.length < 3 && (c = b, b = null), d3.xhr(a, b, d) + }, d3.json = function(a, b) { + d3.text(a, "application/json", function(a) { + b(a ? JSON.parse(a) : null) + }) + }, d3.html = function(a, b) { + d3.text(a, "text/html", function(a) { + if (a != null) { + var c = document.createRange(); + c.selectNode(document.body), a = c.createContextualFragment(a) + } + b(a) + }) + }, d3.xml = function(a, b, c) { + function d(a) { + c(a && a.responseXML) + } + arguments.length < 3 && (c = b, b = null), d3.xhr(a, b, d) + }; + var z = { + svg: "http://www.w3.org/2000/svg", + xhtml: "http://www.w3.org/1999/xhtml", + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + d3.ns = { + prefix: z, + qualify: function(a) { + var b = a.indexOf(":"), + c = a; + return b >= 0 && (c = a.substring(0, b), a = a.substring(b + 1)), z.hasOwnProperty(c) ? { + space: z[c], + local: a + } : a + } + }, d3.dispatch = function() { + var a = new A, + b = -1, + c = arguments.length; + while (++b < c) a[arguments[b]] = B(a); + return a + }, A.prototype.on = function(a, b) { + var c = a.indexOf("."), + d = ""; + return c > 0 && (d = a.substring(c + 1), a = a.substring(0, c)), arguments.length < 2 ? this[a].on(d) : this[a].on(d, b) + }, d3.format = function(a) { + var b = C.exec(a), + c = b[1] || " ", + d = b[3] || "", + e = b[5], + f = +b[6], + g = b[7], + h = b[8], + i = b[9], + j = 1, + k = "", + l = !1; + h && (h = +h.substring(1)), e && (c = "0", g && (f -= Math.floor((f - 1) / 4))); + switch (i) { + case "n": + g = !0, i = "g"; + break; + case "%": + j = 100, k = "%", i = "f"; + break; + case "p": + j = 100, k = "%", i = "r"; + break; + case "d": + l = !0, h = 0; + break; + case "s": + j = -1, i = "r" + } + return i == "r" && !h && (i = "g"), i = D.get(i) || F, + function(a) { + if (l && a % 1) return ""; + var b = a < 0 && (a = -a) ? "−" : d; + if (j < 0) { + var m = d3.formatPrefix(a, h); + a *= m.scale, k = m.symbol + } else a *= j; + a = i(a, h); + if (e) { + var n = a.length + b.length; + n < f && (a = (new Array(f - n + 1)).join(c) + a), g && (a = G(a)), a = b + a + } else { + g && (a = G(a)), a = b + a; + var n = a.length; + n < f && (a = (new Array(f - n + 1)).join(c) + a) + } + return a + k + } + }; + var C = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/, + D = d3.map({ + g: function(a, b) { + return a.toPrecision(b) + }, + e: function(a, b) { + return a.toExponential(b) + }, + f: function(a, b) { + return a.toFixed(b) + }, + r: function(a, b) { + return d3.round(a, b = E(a, b)).toFixed(Math.max(0, Math.min(20, b))) + } + }), + H = ["y", "z", "a", "f", "p", "n", "μ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"].map(I); + d3.formatPrefix = function(a, b) { + var c = 0; + return a && (a < 0 && (a *= -1), b && (a = d3.round(a, E(a, b))), c = 1 + Math.floor(1e-12 + Math.log(a) / Math.LN10), c = Math.max(-24, Math.min(24, Math.floor((c <= 0 ? c + 1 : c - 1) / 3) * 3))), H[8 + c / 3] + }; + var J = S(2), + K = S(3), + L = function() { + return R + }, + M = d3.map({ + linear: L, + poly: S, + quad: function() { + return J + }, + cubic: function() { + return K + }, + sin: function() { + return T + }, + exp: function() { + return U + }, + circle: function() { + return V + }, + elastic: W, + back: X, + bounce: function() { + return Y + } + }), + N = d3.map({ + "in": R, + out: P, + "in-out": Q, + "out-in": function(a) { + return Q(P(a)) + } + }); + d3.ease = function(a) { + var b = a.indexOf("-"), + c = b >= 0 ? a.substring(0, b) : a, + d = b >= 0 ? a.substring(b + 1) : "in"; + return c = M.get(c) || L, d = N.get(d) || R, O(d(c.apply(null, Array.prototype.slice.call(arguments, 1)))) + }, d3.event = null, d3.interpolate = function(a, b) { + var c = d3.interpolators.length, + d; + while (--c >= 0 && !(d = d3.interpolators[c](a, b))); + return d + }, d3.interpolateNumber = function(a, b) { + return b -= a, + function(c) { + return a + b * c + } + }, d3.interpolateRound = function(a, b) { + return b -= a, + function(c) { + return Math.round(a + b * c) + } + }, d3.interpolateString = function(a, b) { + var c, d, e, f = 0, + g = 0, + h = [], + i = [], + j, k; + ba.lastIndex = 0; + for (d = 0; c = ba.exec(b); ++d) c.index && h.push(b.substring(f, g = c.index)), i.push({ + i: h.length, + x: c[0] + }), h.push(null), f = ba.lastIndex; + f < b.length && h.push(b.substring(f)); + for (d = 0, j = i.length; + (c = ba.exec(a)) && d < j; ++d) { + k = i[d]; + if (k.x == c[0]) { + if (k.i) + if (h[k.i + 1] == null) { + h[k.i - 1] += k.x, h.splice(k.i, 1); + for (e = d + 1; e < j; ++e) i[e].i-- + } else { + h[k.i - 1] += k.x + h[k.i + 1], h.splice(k.i, 2); + for (e = d + 1; e < j; ++e) i[e].i -= 2 + } + else if (h[k.i + 1] == null) h[k.i] = k.x; + else { + h[k.i] = k.x + h[k.i + 1], h.splice(k.i + 1, 1); + for (e = d + 1; e < j; ++e) i[e].i-- + } + i.splice(d, 1), j--, d-- + } else k.x = d3.interpolateNumber(parseFloat(c[0]), parseFloat(k.x)) + } + while (d < j) k = i.pop(), h[k.i + 1] == null ? h[k.i] = k.x : (h[k.i] = k.x + h[k.i + 1], h.splice(k.i + 1, 1)), j--; + return h.length === 1 ? h[0] == null ? i[0].x : function() { + return b + } : function(a) { + for (d = 0; d < j; ++d) h[(k = i[d]).i] = k.x(a); + return h.join("") + } + }, d3.interpolateTransform = function(a, b) { + var c = [], + d = [], + e, f = d3.transform(a), + g = d3.transform(b), + h = f.translate, + i = g.translate, + j = f.rotate, + k = g.rotate, + l = f.skew, + m = g.skew, + n = f.scale, + o = g.scale; + return h[0] != i[0] || h[1] != i[1] ? (c.push("translate(", null, ",", null, ")"), d.push({ + i: 1, + x: d3.interpolateNumber(h[0], i[0]) + }, { + i: 3, + x: d3.interpolateNumber(h[1], i[1]) + })) : i[0] || i[1] ? c.push("translate(" + i + ")") : c.push(""), j != k ? d.push({ + i: c.push(c.pop() + "rotate(", null, ")") - 2, + x: d3.interpolateNumber(j, k) + }) : k && c.push(c.pop() + "rotate(" + k + ")"), l != m ? d.push({ + i: c.push(c.pop() + "skewX(", null, ")") - 2, + x: d3.interpolateNumber(l, m) + }) : m && c.push(c.pop() + "skewX(" + m + ")"), n[0] != o[0] || n[1] != o[1] ? (e = c.push(c.pop() + "scale(", null, ",", null, ")"), d.push({ + i: e - 4, + x: d3.interpolateNumber(n[0], o[0]) + }, { + i: e - 2, + x: d3.interpolateNumber(n[1], o[1]) + })) : (o[0] != 1 || o[1] != 1) && c.push(c.pop() + "scale(" + o + ")"), e = d.length, + function(a) { + var b = -1, + f; + while (++b < e) c[(f = d[b]).i] = f.x(a); + return c.join("") + } + }, d3.interpolateRgb = function(a, b) { + a = d3.rgb(a), b = d3.rgb(b); + var c = a.r, + d = a.g, + e = a.b, + f = b.r - c, + g = b.g - d, + h = b.b - e; + return function(a) { + return "#" + bg(Math.round(c + f * a)) + bg(Math.round(d + g * a)) + bg(Math.round(e + h * a)) + } + }, d3.interpolateHsl = function(a, b) { + a = d3.hsl(a), b = d3.hsl(b); + var c = a.h, + d = a.s, + e = a.l, + f = b.h - c, + g = b.s - d, + h = b.l - e; + return function(a) { + return bn(c + f * a, d + g * a, e + h * a).toString() + } + }, d3.interpolateArray = function(a, b) { + var c = [], + d = [], + e = a.length, + f = b.length, + g = Math.min(a.length, b.length), + h; + for (h = 0; h < g; ++h) c.push(d3.interpolate(a[h], b[h])); + for (; h < e; ++h) d[h] = a[h]; + for (; h < f; ++h) d[h] = b[h]; + return function(a) { + for (h = 0; h < g; ++h) d[h] = c[h](a); + return d + } + }, d3.interpolateObject = function(a, b) { + var c = {}, + d = {}, + e; + for (e in a) e in b ? c[e] = bb(e)(a[e], b[e]) : d[e] = a[e]; + for (e in b) e in a || (d[e] = b[e]); + return function(a) { + for (e in c) d[e] = c[e](a); + return d + } + }; + var ba = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; + d3.interpolators = [d3.interpolateObject, function(a, b) { + return b instanceof Array && d3.interpolateArray(a, b) + }, function(a, b) { + return (typeof a == "string" || typeof b == "string") && d3.interpolateString(a + "", b + "") + }, function(a, b) { + return (typeof b == "string" ? bk.has(b) || /^(#|rgb\(|hsl\()/.test(b) : b instanceof bf || b instanceof bm) && d3.interpolateRgb(a, b) + }, function(a, b) { + return !isNaN(a = +a) && !isNaN(b = +b) && d3.interpolateNumber(a, b) + }], d3.rgb = function(a, b, c) { + return arguments.length === 1 ? a instanceof bf ? be(a.r, a.g, a.b) : bh("" + a, be, bn) : be(~~a, ~~b, ~~c) + }, bf.prototype.brighter = function(a) { + a = Math.pow(.7, arguments.length ? a : 1); + var b = this.r, + c = this.g, + d = this.b, + e = 30; + return !b && !c && !d ? be(e, e, e) : (b && b < e && (b = e), c && c < e && (c = e), d && d < e && (d = e), be(Math.min(255, Math.floor(b / a)), Math.min(255, Math.floor(c / a)), Math.min(255, Math.floor(d / a)))) + }, bf.prototype.darker = function(a) { + return a = Math.pow(.7, arguments.length ? a : 1), be(Math.floor(a * this.r), Math.floor(a * this.g), Math.floor(a * this.b)) + }, bf.prototype.hsl = function() { + return bi(this.r, this.g, this.b) + }, bf.prototype.toString = function() { + return "#" + bg(this.r) + bg(this.g) + bg(this.b) + }; + var bk = d3.map({ + aliceblue: "#f0f8ff", + antiquewhite: "#faebd7", + aqua: "#00ffff", + aquamarine: "#7fffd4", + azure: "#f0ffff", + beige: "#f5f5dc", + bisque: "#ffe4c4", + black: "#000000", + blanchedalmond: "#ffebcd", + blue: "#0000ff", + blueviolet: "#8a2be2", + brown: "#a52a2a", + burlywood: "#deb887", + cadetblue: "#5f9ea0", + chartreuse: "#7fff00", + chocolate: "#d2691e", + coral: "#ff7f50", + cornflowerblue: "#6495ed", + cornsilk: "#fff8dc", + crimson: "#dc143c", + cyan: "#00ffff", + darkblue: "#00008b", + darkcyan: "#008b8b", + darkgoldenrod: "#b8860b", + darkgray: "#a9a9a9", + darkgreen: "#006400", + darkgrey: "#a9a9a9", + darkkhaki: "#bdb76b", + darkmagenta: "#8b008b", + darkolivegreen: "#556b2f", + darkorange: "#ff8c00", + darkorchid: "#9932cc", + darkred: "#8b0000", + darksalmon: "#e9967a", + darkseagreen: "#8fbc8f", + darkslateblue: "#483d8b", + darkslategray: "#2f4f4f", + darkslategrey: "#2f4f4f", + darkturquoise: "#00ced1", + darkviolet: "#9400d3", + deeppink: "#ff1493", + deepskyblue: "#00bfff", + dimgray: "#696969", + dimgrey: "#696969", + dodgerblue: "#1e90ff", + firebrick: "#b22222", + floralwhite: "#fffaf0", + forestgreen: "#228b22", + fuchsia: "#ff00ff", + gainsboro: "#dcdcdc", + ghostwhite: "#f8f8ff", + gold: "#ffd700", + goldenrod: "#daa520", + gray: "#808080", + green: "#008000", + greenyellow: "#adff2f", + grey: "#808080", + honeydew: "#f0fff0", + hotpink: "#ff69b4", + indianred: "#cd5c5c", + indigo: "#4b0082", + ivory: "#fffff0", + khaki: "#f0e68c", + lavender: "#e6e6fa", + lavenderblush: "#fff0f5", + lawngreen: "#7cfc00", + lemonchiffon: "#fffacd", + lightblue: "#add8e6", + lightcoral: "#f08080", + lightcyan: "#e0ffff", + lightgoldenrodyellow: "#fafad2", + lightgray: "#d3d3d3", + lightgreen: "#90ee90", + lightgrey: "#d3d3d3", + lightpink: "#ffb6c1", + lightsalmon: "#ffa07a", + lightseagreen: "#20b2aa", + lightskyblue: "#87cefa", + lightslategray: "#778899", + lightslategrey: "#778899", + lightsteelblue: "#b0c4de", + lightyellow: "#ffffe0", + lime: "#00ff00", + limegreen: "#32cd32", + linen: "#faf0e6", + magenta: "#ff00ff", + maroon: "#800000", + mediumaquamarine: "#66cdaa", + mediumblue: "#0000cd", + mediumorchid: "#ba55d3", + mediumpurple: "#9370db", + mediumseagreen: "#3cb371", + mediumslateblue: "#7b68ee", + mediumspringgreen: "#00fa9a", + mediumturquoise: "#48d1cc", + mediumvioletred: "#c71585", + midnightblue: "#191970", + mintcream: "#f5fffa", + mistyrose: "#ffe4e1", + moccasin: "#ffe4b5", + navajowhite: "#ffdead", + navy: "#000080", + oldlace: "#fdf5e6", + olive: "#808000", + olivedrab: "#6b8e23", + orange: "#ffa500", + orangered: "#ff4500", + orchid: "#da70d6", + palegoldenrod: "#eee8aa", + palegreen: "#98fb98", + paleturquoise: "#afeeee", + palevioletred: "#db7093", + papayawhip: "#ffefd5", + peachpuff: "#ffdab9", + peru: "#cd853f", + pink: "#ffc0cb", + plum: "#dda0dd", + powderblue: "#b0e0e6", + purple: "#800080", + red: "#ff0000", + rosybrown: "#bc8f8f", + royalblue: "#4169e1", + saddlebrown: "#8b4513", + salmon: "#fa8072", + sandybrown: "#f4a460", + seagreen: "#2e8b57", + seashell: "#fff5ee", + sienna: "#a0522d", + silver: "#c0c0c0", + skyblue: "#87ceeb", + slateblue: "#6a5acd", + slategray: "#708090", + slategrey: "#708090", + snow: "#fffafa", + springgreen: "#00ff7f", + steelblue: "#4682b4", + tan: "#d2b48c", + teal: "#008080", + thistle: "#d8bfd8", + tomato: "#ff6347", + turquoise: "#40e0d0", + violet: "#ee82ee", + wheat: "#f5deb3", + white: "#ffffff", + whitesmoke: "#f5f5f5", + yellow: "#ffff00", + yellowgreen: "#9acd32" + }); + bk.forEach(function(a, b) { + bk.set(a, bh(b, be, bn)) + }), d3.hsl = function(a, b, c) { + return arguments.length === 1 ? a instanceof bm ? bl(a.h, a.s, a.l) : bh("" + a, bi, bl) : bl(+a, +b, +c) + }, bm.prototype.brighter = function(a) { + return a = Math.pow(.7, arguments.length ? a : 1), bl(this.h, this.s, this.l / a) + }, bm.prototype.darker = function(a) { + return a = Math.pow(.7, arguments.length ? a : 1), bl(this.h, this.s, a * this.l) + }, bm.prototype.rgb = function() { + return bn(this.h, this.s, this.l) + }, bm.prototype.toString = function() { + return this.rgb().toString() + }; + var bp = function(a, b) { + return b.querySelector(a) + }, + bq = function(a, b) { + return b.querySelectorAll(a) + }, + br = document.documentElement, + bs = br.matchesSelector || br.webkitMatchesSelector || br.mozMatchesSelector || br.msMatchesSelector || br.oMatchesSelector, + bt = function(a, b) { + return bs.call(a, b) + }; + typeof Sizzle == "function" && (bp = function(a, b) { + return Sizzle(a, b)[0] + }, bq = function(a, b) { + return Sizzle.uniqueSort(Sizzle(a, b)) + }, bt = Sizzle.matchesSelector); + var bu = []; + d3.selection = function() { + return bC + }, d3.selection.prototype = bu, bu.select = function(a) { + var b = [], + c, d, e, f; + typeof a != "function" && (a = bv(a)); + for (var g = -1, h = this.length; ++g < h;) { + b.push(c = []), c.parentNode = (e = this[g]).parentNode; + for (var i = -1, j = e.length; ++i < j;)(f = e[i]) ? (c.push(d = a.call(f, f.__data__, i)), d && "__data__" in f && (d.__data__ = f.__data__)) : c.push(null) + } + return bo(b) + }, bu.selectAll = function(a) { + var b = [], + c, d; + typeof a != "function" && (a = bw(a)); + for (var e = -1, g = this.length; ++e < g;) + for (var h = this[e], i = -1, j = h.length; ++i < j;) + if (d = h[i]) b.push(c = f(a.call(d, d.__data__, i))), c.parentNode = d; + return bo(b) + }, bu.attr = function(a, b) { + function d() { + this.removeAttribute(a) + } + + function e() { + this.removeAttributeNS(a.space, a.local) + } + + function f() { + this.setAttribute(a, b) + } + + function g() { + this.setAttributeNS(a.space, a.local, b) + } + + function h() { + var c = b.apply(this, arguments); + c == null ? this.removeAttribute(a) : this.setAttribute(a, c) + } + + function i() { + var c = b.apply(this, arguments); + c == null ? this.removeAttributeNS(a.space, a.local) : this.setAttributeNS(a.space, a.local, c) + } + a = d3.ns.qualify(a); + if (arguments.length < 2) { + var c = this.node(); + return a.local ? c.getAttributeNS(a.space, a.local) : c.getAttribute(a) + } + return this.each(b == null ? a.local ? e : d : typeof b == "function" ? a.local ? i : h : a.local ? g : f) + }, bu.classed = function(a, b) { + var c = a.split(bx), + d = c.length, + e = -1; + if (arguments.length > 1) { + while (++e < d) by.call(this, c[e], b); + return this + } + while (++e < d) + if (!by.call(this, c[e])) return !1; + return !0 + }; + var bx = /\s+/g; + bu.style = function(a, b, c) { + function d() { + this.style.removeProperty(a) + } + + function e() { + this.style.setProperty(a, b, c) + } + + function f() { + var d = b.apply(this, arguments); + d == null ? this.style.removeProperty(a) : this.style.setProperty(a, d, c) + } + return arguments.length < 3 && (c = ""), arguments.length < 2 ? window.getComputedStyle(this.node(), null).getPropertyValue(a) : this.each(b == null ? d : typeof b == "function" ? f : e) + }, bu.property = function(a, b) { + function c() { + delete this[a] + } + + function d() { + this[a] = b + } + + function e() { + var c = b.apply(this, arguments); + c == null ? delete this[a] : this[a] = c + } + return arguments.length < 2 ? this.node()[a] : this.each(b == null ? c : typeof b == "function" ? e : d) + }, bu.text = function(a) { + return arguments.length < 1 ? this.node().textContent : this.each(typeof a == "function" ? function() { + var b = a.apply(this, arguments); + this.textContent = b == null ? "" : b + } : a == null ? function() { + this.textContent = "" + } : function() { + this.textContent = a + }) + }, bu.html = function(a) { + return arguments.length < 1 ? this.node().innerHTML : this.each(typeof a == "function" ? function() { + var b = a.apply(this, arguments); + this.innerHTML = b == null ? "" : b + } : a == null ? function() { + this.innerHTML = "" + } : function() { + this.innerHTML = a + }) + }, bu.append = function(a) { + function b() { + return this.appendChild(document.createElementNS(this.namespaceURI, a)) + } + + function c() { + return this.appendChild(document.createElementNS(a.space, a.local)) + } + return a = d3.ns.qualify(a), this.select(a.local ? c : b) + }, bu.insert = function(a, b) { + function c() { + return this.insertBefore(document.createElementNS(this.namespaceURI, a), bp(b, this)) + } + + function d() { + return this.insertBefore(document.createElementNS(a.space, a.local), bp(b, this)) + } + return a = d3.ns.qualify(a), this.select(a.local ? d : c) + }, bu.remove = function() { + return this.each(function() { + var a = this.parentNode; + a && a.removeChild(this) + }) + }, bu.data = function(a, b) { + function g(a, c) { + var d, e = a.length, + f = c.length, + g = Math.min(e, f), + l = Math.max(e, f), + m = [], + n = [], + o = [], + p, q; + if (b) { + var r = new k, + s = [], + t, u = c.length; + for (d = -1; ++d < e;) t = b.call(p = a[d], p.__data__, d), r.has(t) ? o[u++] = p : r.set(t, p), s.push(t); + for (d = -1; ++d < f;) t = b.call(c, q = c[d], d), r.has(t) ? (m[d] = p = r.get(t), p.__data__ = q, n[d] = o[d] = null) : (n[d] = bz(q), m[d] = o[d] = null), r.remove(t); + for (d = -1; ++d < e;) r.has(s[d]) && (o[d] = a[d]) + } else { + for (d = -1; ++d < g;) p = a[d], q = c[d], p ? (p.__data__ = q, m[d] = p, n[d] = o[d] = null) : (n[d] = bz(q), m[d] = o[d] = null); + for (; d < f; ++d) n[d] = bz(c[d]), m[d] = o[d] = null; + for (; d < l; ++d) o[d] = a[d], n[d] = m[d] = null + } + n.update = m, n.parentNode = m.parentNode = o.parentNode = a.parentNode, h.push(n), i.push(m), j.push(o) + } + var c = -1, + d = this.length, + e, f; + if (!arguments.length) { + a = new Array(d = (e = this[0]).length); + while (++c < d) + if (f = e[c]) a[c] = f.__data__; + return a + } + var h = bD([]), + i = bo([]), + j = bo([]); + if (typeof a == "function") + while (++c < d) g(e = this[c], a.call(e, e.parentNode.__data__, c)); + else + while (++c < d) g(e = this[c], a); + return i.enter = function() { + return h + }, i.exit = function() { + return j + }, i + }, bu.datum = bu.map = function(a) { + return arguments.length < 1 ? this.property("__data__") : this.property("__data__", a) + }, bu.filter = function(a) { + var b = [], + c, d, e; + typeof a != "function" && (a = bA(a)); + for (var f = 0, g = this.length; f < g; f++) { + b.push(c = []), c.parentNode = (d = this[f]).parentNode; + for (var h = 0, i = d.length; h < i; h++)(e = d[h]) && a.call(e, e.__data__, h) && c.push(e) + } + return bo(b) + }, bu.order = function() { + for (var a = -1, b = this.length; ++a < b;) + for (var c = this[a], d = c.length - 1, e = c[d], f; --d >= 0;) + if (f = c[d]) e && e !== f.nextSibling && e.parentNode.insertBefore(f, e), e = f; + return this + }, bu.sort = function(a) { + a = bB.apply(this, arguments); + for (var b = -1, c = this.length; ++b < c;) this[b].sort(a); + return this.order() + }, bu.on = function(a, b, c) { + arguments.length < 3 && (c = !1); + var d = "__on" + a, + e = a.indexOf("."); + return e > 0 && (a = a.substring(0, e)), arguments.length < 2 ? (e = this.node()[d]) && e._ : this.each(function(e, f) { + function i(a) { + var c = d3.event; + d3.event = a; + try { + b.call(g, g.__data__, f) + } finally { + d3.event = c + } + } + var g = this, + h = g[d]; + h && (g.removeEventListener(a, h, h.$), delete g[d]), b && (g.addEventListener(a, g[d] = i, i.$ = c), i._ = b) + }) + }, bu.each = function(a) { + for (var b = -1, c = this.length; ++b < c;) + for (var d = this[b], e = -1, f = d.length; ++e < f;) { + var g = d[e]; + g && a.call(g, g.__data__, e, b) + } + return this + }, bu.call = function(a) { + return a.apply(this, (arguments[0] = this, arguments)), this + }, bu.empty = function() { + return !this.node() + }, bu.node = function(a) { + for (var b = 0, c = this.length; b < c; b++) + for (var d = this[b], e = 0, f = d.length; e < f; e++) { + var g = d[e]; + if (g) return g + } + return null + }, bu.transition = function() { + var a = [], + b, c; + for (var d = -1, e = this.length; ++d < e;) { + a.push(b = []); + for (var f = this[d], g = -1, h = f.length; ++g < h;) b.push((c = f[g]) ? { + node: c, + delay: bP, + duration: bQ + } : null) + } + return bF(a, bL || ++bK, Date.now()) + }; + var bC = bo([ + [document] + ]); + bC[0].parentNode = br, d3.select = function(a) { + return typeof a == "string" ? bC.select(a) : bo([ + [a] + ]) + }, d3.selectAll = function(a) { + return typeof a == "string" ? bC.selectAll(a) : bo([f(a)]) + }; + var bE = []; + d3.selection.enter = bD, d3.selection.enter.prototype = bE, bE.append = bu.append, bE.insert = bu.insert, bE.empty = bu.empty, bE.node = bu.node, bE.select = function(a) { + var b = [], + c, d, e, f, g; + for (var h = -1, i = this.length; ++h < i;) { + e = (f = this[h]).update, b.push(c = []), c.parentNode = f.parentNode; + for (var j = -1, k = f.length; ++j < k;)(g = f[j]) ? (c.push(e[j] = d = a.call(f.parentNode, g.__data__, j)), d.__data__ = g.__data__) : c.push(null) + } + return bo(b) + }; + var bG = {}, + bJ = [], + bK = 0, + bL = 0, + bM = 0, + bN = 250, + bO = d3.ease("cubic-in-out"), + bP = bM, + bQ = bN, + bR = bO; + bJ.call = bu.call, d3.transition = function(a) { + return arguments.length ? bL ? a.transition() : a : bC.transition() + }, d3.transition.prototype = bJ, bJ.select = function(a) { + var b = [], + c, d, e; + typeof a != "function" && (a = bv(a)); + for (var f = -1, g = this.length; ++f < g;) { + b.push(c = []); + for (var h = this[f], i = -1, j = h.length; ++i < j;)(e = h[i]) && (d = a.call(e.node, e.node.__data__, i)) ? ("__data__" in e.node && (d.__data__ = e.node.__data__), c.push({ + node: d, + delay: e.delay, + duration: e.duration + })) : c.push(null) + } + return bF(b, this.id, this.time).ease(this.ease()) + }, bJ.selectAll = function(a) { + var b = [], + c, d, e; + typeof a != "function" && (a = bw(a)); + for (var f = -1, g = this.length; ++f < g;) + for (var h = this[f], i = -1, j = h.length; ++i < j;) + if (e = h[i]) { + d = a.call(e.node, e.node.__data__, i), b.push(c = []); + for (var k = -1, l = d.length; ++k < l;) c.push({ + node: d[k], + delay: e.delay, + duration: e.duration + }) + } + return bF(b, this.id, this.time).ease(this.ease()) + }, bJ.attr = function(a, b) { + return this.attrTween(a, bI(a, b)) + }, bJ.attrTween = function(a, b) { + function d(a, d) { + var e = b.call(this, a, d, this.getAttribute(c)); + return e === bG ? (this.removeAttribute(c), null) : e && function(a) { + this.setAttribute(c, e(a)) + } + } + + function e(a, d) { + var e = b.call(this, a, d, this.getAttributeNS(c.space, c.local)); + return e === bG ? (this.removeAttributeNS(c.space, c.local), null) : e && function(a) { + this.setAttributeNS(c.space, c.local, e(a)) + } + } + var c = d3.ns.qualify(a); + return this.tween("attr." + a, c.local ? e : d) + }, bJ.style = function(a, b, c) { + return arguments.length < 3 && (c = ""), this.styleTween(a, bI(a, b), c) + }, bJ.styleTween = function(a, b, c) { + return arguments.length < 3 && (c = ""), this.tween("style." + a, function(d, e) { + var f = b.call(this, d, e, window.getComputedStyle(this, null).getPropertyValue(a)); + return f === bG ? (this.style.removeProperty(a), null) : f && function(b) { + this.style.setProperty(a, f(b), c) + } + }) + }, bJ.text = function(a) { + return this.tween("text", function(b, c) { + this.textContent = typeof a == "function" ? a.call(this, b, c) : a + }) + }, bJ.remove = function() { + return this.each("end.transition", function() { + var a; + !this.__transition__ && (a = this.parentNode) && a.removeChild(this) + }) + }, bJ.delay = function(a) { + var b = this; + return b.each(typeof a == "function" ? function(c, d, e) { + b[e][d].delay = a.apply(this, arguments) | 0 + } : (a |= 0, function(c, d, e) { + b[e][d].delay = a + })) + }, bJ.duration = function(a) { + var b = this; + return b.each(typeof a == "function" ? function(c, d, e) { + b[e][d].duration = Math.max(1, a.apply(this, arguments) | 0) + } : (a = Math.max(1, a | 0), function(c, d, e) { + b[e][d].duration = a + })) + }, bJ.transition = function() { + return this.select(o) + }; + var bT = null, + bU, bV; + d3.timer = function(a, b, c) { + var d = !1, + e, f = bT; + if (arguments.length < 3) { + if (arguments.length < 2) b = 0; + else if (!isFinite(b)) return; + c = Date.now() + } + while (f) { + if (f.callback === a) { + f.then = c, f.delay = b, d = !0; + break + } + e = f, f = f.next + } + d || (bT = { + callback: a, + then: c, + delay: b, + next: bT + }), bU || (bV = clearTimeout(bV), bU = 1, bY(bW)) + }, d3.timer.flush = function() { + var a, b = Date.now(), + c = bT; + while (c) a = b - c.then, c.delay || (c.flush = c.callback(a)), c = c.next; + bX() + }; + var bY = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(a) { + setTimeout(a, 17) + }; + d3.transform = function(a) { + var b = document.createElementNS(d3.ns.prefix.svg, "g"), + c = { + a: 1, + b: 0, + c: 0, + d: 1, + e: 0, + f: 0 + }; + return (d3.transform = function(a) { + b.setAttribute("transform", a); + var d = b.transform.baseVal.consolidate(); + return new bZ(d ? d.matrix : c) + })(a) + }, bZ.prototype.toString = function() { + return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")" + }; + var cb = 180 / Math.PI; + d3.mouse = function(a) { + return cd(a, $()) + }; + var cc = /WebKit/.test(navigator.userAgent) ? -1 : 0; + d3.touches = function(a, b) { + return arguments.length < 2 && (b = $().touches), b ? f(b).map(function(b) { + var c = cd(a, b); + return c.identifier = b.identifier, c + }) : [] + }, d3.scale = {}, d3.scale.linear = function() { + return cj([0, 1], [0, 1], d3.interpolate, !1) + }, d3.scale.log = function() { + return cr(d3.scale.linear(), ct) + }; + var cs = d3.format(".0e"); + ct.pow = function(a) { + return Math.pow(10, a) + }, cu.pow = function(a) { + return -Math.pow(10, -a) + }, d3.scale.pow = function() { + return cv(d3.scale.linear(), 1) + }, d3.scale.sqrt = function() { + return d3.scale.pow().exponent(.5) + }, d3.scale.ordinal = function() { + return cx([], { + t: "range", + x: [] + }) + }, d3.scale.category10 = function() { + return d3.scale.ordinal().range(cy) + }, d3.scale.category20 = function() { + return d3.scale.ordinal().range(cz) + }, d3.scale.category20b = function() { + return d3.scale.ordinal().range(cA) + }, d3.scale.category20c = function() { + return d3.scale.ordinal().range(cB) + }; + var cy = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"], + cz = ["#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5"], + cA = ["#393b79", "#5254a3", "#6b6ecf", "#9c9ede", "#637939", "#8ca252", "#b5cf6b", "#cedb9c", "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#e7969c", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6"], + cB = ["#3182bd", "#6baed6", "#9ecae1", "#c6dbef", "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", "#31a354", "#74c476", "#a1d99b", "#c7e9c0", "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", "#636363", "#969696", "#bdbdbd", "#d9d9d9"]; + d3.scale.quantile = function() { + return cC([], []) + }, d3.scale.quantize = function() { + return cD(0, 1, [0, 1]) + }, d3.scale.identity = function() { + return cE([0, 1]) + }, d3.svg = {}, d3.svg.arc = function() { + function e() { + var e = a.apply(this, arguments), + f = b.apply(this, arguments), + g = c.apply(this, arguments) + cF, + h = d.apply(this, arguments) + cF, + i = (h < g && (i = g, g = h, h = i), h - g), + j = i < Math.PI ? "0" : "1", + k = Math.cos(g), + l = Math.sin(g), + m = Math.cos(h), + n = Math.sin(h); + return i >= cG ? e ? "M0," + f + "A" + f + "," + f + " 0 1,1 0," + -f + "A" + f + "," + f + " 0 1,1 0," + f + "M0," + e + "A" + e + "," + e + " 0 1,0 0," + -e + "A" + e + "," + e + " 0 1,0 0," + e + "Z" : "M0," + f + "A" + f + "," + f + " 0 1,1 0," + -f + "A" + f + "," + f + " 0 1,1 0," + f + "Z" : e ? "M" + f * k + "," + f * l + "A" + f + "," + f + " 0 " + j + ",1 " + f * m + "," + f * n + "L" + e * m + "," + e * n + "A" + e + "," + e + " 0 " + j + ",0 " + e * k + "," + e * l + "Z" : "M" + f * k + "," + f * l + "A" + f + "," + f + " 0 " + j + ",1 " + f * m + "," + f * n + "L0,0" + "Z" + } + var a = cH, + b = cI, + c = cJ, + d = cK; + return e.innerRadius = function(b) { + return arguments.length ? (a = q(b), e) : a + }, e.outerRadius = function(a) { + return arguments.length ? (b = q(a), e) : b + }, e.startAngle = function(a) { + return arguments.length ? (c = q(a), e) : c + }, e.endAngle = function(a) { + return arguments.length ? (d = q(a), e) : d + }, e.centroid = function() { + var e = (a.apply(this, arguments) + b.apply(this, arguments)) / 2, + f = (c.apply(this, arguments) + d.apply(this, arguments)) / 2 + cF; + return [Math.cos(f) * e, Math.sin(f) * e] + }, e + }; + var cF = -Math.PI / 2, + cG = 2 * Math.PI - 1e-6; + d3.svg.line = function() { + return cL(n) + }; + var cO = "linear", + cP = d3.map({ + linear: cQ, + "step-before": cR, + "step-after": cS, + basis: cY, + "basis-open": cZ, + "basis-closed": c$, + bundle: c_, + cardinal: cV, + "cardinal-open": cT, + "cardinal-closed": cU, + monotone: di + }), + db = [0, 2 / 3, 1 / 3, 0], + dc = [0, 1 / 3, 2 / 3, 0], + dd = [0, 1 / 6, 2 / 3, 1 / 6]; + d3.svg.line.radial = function() { + var a = cL(dj); + return a.radius = a.x, delete a.x, a.angle = a.y, delete a.y, a + }, cR.reverse = cS, cS.reverse = cR, d3.svg.area = function() { + return dk(Object) + }, d3.svg.area.radial = function() { + var a = dk(dj); + return a.radius = a.x, delete a.x, a.innerRadius = a.x0, delete a.x0, a.outerRadius = a.x1, delete a.x1, a.angle = a.y, delete a.y, a.startAngle = a.y0, delete a.y0, a.endAngle = a.y1, delete a.y1, a + }, d3.svg.chord = function() { + function f(c, d) { + var e = g(this, a, c, d), + f = g(this, b, c, d); + return "M" + e.p0 + i(e.r, e.p1, e.a1 - e.a0) + (h(e, f) ? j(e.r, e.p1, e.r, e.p0) : j(e.r, e.p1, f.r, f.p0) + i(f.r, f.p1, f.a1 - f.a0) + j(f.r, f.p1, e.r, e.p0)) + "Z" + } + + function g(a, b, f, g) { + var h = b.call(a, f, g), + i = c.call(a, h, g), + j = d.call(a, h, g) + cF, + k = e.call(a, h, g) + cF; + return { + r: i, + a0: j, + a1: k, + p0: [i * Math.cos(j), i * Math.sin(j)], + p1: [i * Math.cos(k), i * Math.sin(k)] + } + } + + function h(a, b) { + return a.a0 == b.a0 && a.a1 == b.a1 + } + + function i(a, b, c) { + return "A" + a + "," + a + " 0 " + +(c > Math.PI) + ",1 " + b + } + + function j(a, b, c, d) { + return "Q 0,0 " + d + } + var a = dl, + b = dm, + c = dn, + d = cJ, + e = cK; + return f.radius = function(a) { + return arguments.length ? (c = q(a), f) : c + }, f.source = function(b) { + return arguments.length ? (a = q(b), f) : a + }, f.target = function(a) { + return arguments.length ? (b = q(a), f) : b + }, f.startAngle = function(a) { + return arguments.length ? (d = q(a), f) : d + }, f.endAngle = function(a) { + return arguments.length ? (e = q(a), f) : e + }, f + }, d3.svg.diagonal = function() { + function d(d, e) { + var f = a.call(this, d, e), + g = b.call(this, d, e), + h = (f.y + g.y) / 2, + i = [f, { + x: f.x, + y: h + }, { + x: g.x, + y: h + }, g]; + return i = i.map(c), "M" + i[0] + "C" + i[1] + " " + i[2] + " " + i[3] + } + var a = dl, + b = dm, + c = dr; + return d.source = function(b) { + return arguments.length ? (a = q(b), d) : a + }, d.target = function(a) { + return arguments.length ? (b = q(a), d) : b + }, d.projection = function(a) { + return arguments.length ? (c = a, d) : c + }, d + }, d3.svg.diagonal.radial = function() { + var a = d3.svg.diagonal(), + b = dr, + c = a.projection; + return a.projection = function(a) { + return arguments.length ? c(ds(b = a)) : b + }, a + }, d3.svg.mouse = d3.mouse, d3.svg.touches = d3.touches, d3.svg.symbol = function() { + function c(c, d) { + return (dw.get(a.call(this, c, d)) || dv)(b.call(this, c, d)) + } + var a = du, + b = dt; + return c + .type = function(b) { + return arguments.length ? (a = q(b), c) : a + }, c.size = function(a) { + return arguments.length ? (b = q(a), c) : b + }, c + }; + var dw = d3.map({ + circle: dv, + cross: function(a) { + var b = Math.sqrt(a / 5) / 2; + return "M" + -3 * b + "," + -b + "H" + -b + "V" + -3 * b + "H" + b + "V" + -b + "H" + 3 * b + "V" + b + "H" + b + "V" + 3 * b + "H" + -b + "V" + b + "H" + -3 * b + "Z" + }, + diamond: function(a) { + var b = Math.sqrt(a / (2 * dy)), + c = b * dy; + return "M0," + -b + "L" + c + ",0" + " 0," + b + " " + -c + ",0" + "Z" + }, + square: function(a) { + var b = Math.sqrt(a) / 2; + return "M" + -b + "," + -b + "L" + b + "," + -b + " " + b + "," + b + " " + -b + "," + b + "Z" + }, + "triangle-down": function(a) { + var b = Math.sqrt(a / dx), + c = b * dx / 2; + return "M0," + c + "L" + b + "," + -c + " " + -b + "," + -c + "Z" + }, + "triangle-up": function(a) { + var b = Math.sqrt(a / dx), + c = b * dx / 2; + return "M0," + -c + "L" + b + "," + c + " " + -b + "," + c + "Z" + } + }); + d3.svg.symbolTypes = dw.keys(); + var dx = Math.sqrt(3), + dy = Math.tan(30 * Math.PI / 180); + d3.svg.axis = function() { + function k(k) { + k.each(function() { + var k = d3.select(this), + l = h == null ? a.ticks ? a.ticks.apply(a, g) : a.domain() : h, + m = i == null ? a.tickFormat ? a.tickFormat.apply(a, g) : String : i, + n = dB(a, l, j), + o = k.selectAll(".minor").data(n, String), + p = o.enter().insert("line", "g").attr("class", "tick minor").style("opacity", 1e-6), + q = d3.transition(o.exit()).style("opacity", 1e-6).remove(), + r = d3.transition(o).style("opacity", 1), + s = k.selectAll("g").data(l, String), + t = s.enter().insert("g", "path").style("opacity", 1e-6), + u = d3.transition(s.exit()).style("opacity", 1e-6).remove(), + v = d3.transition(s).style("opacity", 1), + w, x = cg(a), + y = k.selectAll(".domain").data([0]), + z = y.enter().append("path").attr("class", "domain"), + A = d3.transition(y), + B = a.copy(), + C = this.__chart__ || B; + this.__chart__ = B, t.append("line").attr("class", "tick"), t.append("text"), v.select("text").text(m); + switch (b) { + case "bottom": + w = dz, p.attr("y2", d), r.attr("x2", 0).attr("y2", d), t.select("line").attr("y2", c), t.select("text").attr("y", Math.max(c, 0) + f), v.select("line").attr("x2", 0).attr("y2", c), v.select("text").attr("x", 0).attr("y", Math.max(c, 0) + f).attr("dy", ".71em").attr("text-anchor", "middle"), A.attr("d", "M" + x[0] + "," + e + "V0H" + x[1] + "V" + e); + break; + case "top": + w = dz, p.attr("y2", -d), r.attr("x2", 0).attr("y2", -d), t.select("line").attr("y2", -c), t.select("text").attr("y", -(Math.max(c, 0) + f)), v.select("line").attr("x2", 0).attr("y2", -c), v.select("text").attr("x", 0).attr("y", -(Math.max(c, 0) + f)).attr("dy", "0em").attr("text-anchor", "middle"), A.attr("d", "M" + x[0] + "," + -e + "V0H" + x[1] + "V" + -e); + break; + case "left": + w = dA, p.attr("x2", -d), r.attr("x2", -d).attr("y2", 0), t.select("line").attr("x2", -c), t.select("text").attr("x", -(Math.max(c, 0) + f)), v.select("line").attr("x2", -c).attr("y2", 0), v.select("text").attr("x", -(Math.max(c, 0) + f)).attr("y", 0).attr("dy", ".32em").attr("text-anchor", "end"), A.attr("d", "M" + -e + "," + x[0] + "H0V" + x[1] + "H" + -e); + break; + case "right": + w = dA, p.attr("x2", d), r.attr("x2", d).attr("y2", 0), t.select("line").attr("x2", c), t.select("text").attr("x", Math.max(c, 0) + f), v.select("line").attr("x2", c).attr("y2", 0), v.select("text").attr("x", Math.max(c, 0) + f).attr("y", 0).attr("dy", ".32em").attr("text-anchor", "start"), A.attr("d", "M" + e + "," + x[0] + "H0V" + x[1] + "H" + e) + } + if (a.ticks) t.call(w, C), v.call(w, B), u.call(w, B), p.call(w, C), r.call(w, B), q.call(w, B); + else { + var D = B.rangeBand() / 2, + E = function(a) { + return B(a) + D + }; + t.call(w, E), v.call(w, E) + } + }) + } + var a = d3.scale.linear(), + b = "bottom", + c = 6, + d = 6, + e = 6, + f = 3, + g = [10], + h = null, + i, j = 0; + return k.scale = function(b) { + return arguments.length ? (a = b, k) : a + }, k.orient = function(a) { + return arguments.length ? (b = a, k) : b + }, k.ticks = function() { + return arguments.length ? (g = arguments, k) : g + }, k.tickValues = function(a) { + return arguments.length ? (h = a, k) : h + }, k.tickFormat = function(a) { + return arguments.length ? (i = a, k) : i + }, k.tickSize = function(a, b, f) { + if (!arguments.length) return c; + var g = arguments.length - 1; + return c = +a, d = g > 1 ? +b : c, e = g > 0 ? +arguments[g] : c, k + }, k.tickPadding = function(a) { + return arguments.length ? (f = +a, k) : f + }, k.tickSubdivide = function(a) { + return arguments.length ? (j = +a, k) : j + }, k + }, d3.svg.brush = function() { + function g(a) { + a.each(function() { + var a = d3.select(this), + e = a.selectAll(".background").data([0]), + f = a.selectAll(".extent").data([0]), + l = a.selectAll(".resize").data(d, String), + m; + a.style("pointer-events", "all").on("mousedown.brush", k).on("touchstart.brush", k), e.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"), f.enter().append("rect").attr("class", "extent").style("cursor", "move"), l.enter().append("g").attr("class", function(a) { + return "resize " + a + }).style("cursor", function(a) { + return dC[a] + }).append("rect").attr("x", function(a) { + return /[ew]$/.test(a) ? -3 : null + }).attr("y", function(a) { + return /^[ns]/.test(a) ? -3 : null + }).attr("width", 6).attr("height", 6).style("visibility", "hidden"), l.style("display", g.empty() ? "none" : null), l.exit().remove(), b && (m = cg(b), e.attr("x", m[0]).attr("width", m[1] - m[0]), i(a)), c && (m = cg(c), e.attr("y", m[0]).attr("height", m[1] - m[0]), j(a)), h(a) + }) + } + + function h(a) { + a.selectAll(".resize").attr("transform", function(a) { + return "translate(" + e[+/e$/.test(a)][0] + "," + e[+/^s/.test(a)][1] + ")" + }) + } + + function i(a) { + a.select(".extent").attr("x", e[0][0]), a.selectAll(".extent,.n>rect,.s>rect").attr("width", e[1][0] - e[0][0]) + } + + function j(a) { + a.select(".extent").attr("y", e[0][1]), a.selectAll(".extent,.e>rect,.w>rect").attr("height", e[1][1] - e[0][1]) + } + + function k() { + function x() { + var a = d3.event.changedTouches; + return a ? d3.touches(d, a)[0] : d3.mouse(d) + } + + function y() { + d3.event.keyCode == 32 && (q || (r = null, s[0] -= e[1][0], s[1] -= e[1][1], q = 2), Z()) + } + + function z() { + d3.event.keyCode == 32 && q == 2 && (s[0] += e[1][0], s[1] += e[1][1], q = 0, Z()) + } + + function A() { + var a = x(), + d = !1; + t && (a[0] += t[0], a[1] += t[1]), q || (d3.event.altKey ? (r || (r = [(e[0][0] + e[1][0]) / 2, (e[0][1] + e[1][1]) / 2]), s[0] = e[+(a[0] < r[0])][0], s[1] = e[+(a[1] < r[1])][1]) : r = null), o && B(a, b, 0) && (i(m), d = !0), p && B(a, c, 1) && (j(m), d = !0), d && (h(m), l({ + type: "brush", + mode: q ? "move" : "resize" + })) + } + + function B(a, b, c) { + var d = cg(b), + g = d[0], + h = d[1], + i = s[c], + j = e[1][c] - e[0][c], + k, l; + q && (g -= i, h -= j + i), k = Math.max(g, Math.min(h, a[c])), q ? l = (k += i) + j : (r && (i = Math.max(g, Math.min(h, 2 * r[c] - k))), i < k ? (l = k, k = i) : l = i); + if (e[0][c] !== k || e[1][c] !== l) return f = null, e[0][c] = k, e[1][c] = l, !0 + } + + function C() { + A(), m.style("pointer-events", "all").selectAll(".resize").style("display", g.empty() ? "none" : null), d3.select("body").style("cursor", null), u.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null), l({ + type: "brushend" + }), Z() + } + var d = this, + k = d3.select(d3.event.target), + l = a.of(d, arguments), + m = d3.select(d), + n = k.datum(), + o = !/^(n|s)$/.test(n) && b, + p = !/^(e|w)$/.test(n) && c, + q = k.classed("extent"), + r, s = x(), + t, u = d3.select(window).on("mousemove.brush", A).on("mouseup.brush", C).on("touchmove.brush", A).on("touchend.brush", C).on("keydown.brush", y).on("keyup.brush", z); + if (q) s[0] = e[0][0] - s[0], s[1] = e[0][1] - s[1]; + else if (n) { + var v = +/w$/.test(n), + w = +/^n/.test(n); + t = [e[1 - v][0] - s[0], e[1 - w][1] - s[1]], s[0] = e[v][0], s[1] = e[w][1] + } else d3.event.altKey && (r = s.slice()); + m.style("pointer-events", "none").selectAll(".resize").style("display", null), d3.select("body").style("cursor", k.style("cursor")), l({ + type: "brushstart" + }), A(), Z() + } + var a = _(g, "brushstart", "brush", "brushend"), + b = null, + c = null, + d = dD[0], + e = [ + [0, 0], + [0, 0] + ], + f; + return g.x = function(a) { + return arguments.length ? (b = a, d = dD[!b << 1 | !c], g) : b + }, g.y = function(a) { + return arguments.length ? (c = a, d = dD[!b << 1 | !c], g) : c + }, g.extent = function(a) { + var d, h, i, j, k; + return arguments.length ? (f = [ + [0, 0], + [0, 0] + ], b && (d = a[0], h = a[1], c && (d = d[0], h = h[0]), f[0][0] = d, f[1][0] = h, b.invert && (d = b(d), h = b(h)), h < d && (k = d, d = h, h = k), e[0][0] = d | 0, e[1][0] = h | 0), c && (i = a[0], j = a[1], b && (i = i[1], j = j[1]), f[0][1] = i, f[1][1] = j, c.invert && (i = c(i), j = c(j)), j < i && (k = i, i = j, j = k), e[0][1] = i | 0, e[1][1] = j | 0), g) : (a = f || e, b && (d = a[0][0], h = a[1][0], f || (d = e[0][0], h = e[1][0], b.invert && (d = b.invert(d), h = b.invert(h)), h < d && (k = d, d = h, h = k))), c && (i = a[0][1], j = a[1][1], f || (i = e[0][1], j = e[1][1], c.invert && (i = c.invert(i), j = c.invert(j)), j < i && (k = i, i = j, j = k))), b && c ? [ + [d, i], + [h, j] + ] : b ? [d, h] : c && [i, j]) + }, g.clear = function() { + return f = null, e[0][0] = e[0][1] = e[1][0] = e[1][1] = 0, g + }, g.empty = function() { + return b && e[0][0] === e[1][0] || c && e[0][1] === e[1][1] + }, d3.rebind(g, a, "on") + }; + var dC = { + n: "ns-resize", + e: "ew-resize", + s: "ns-resize", + w: "ew-resize", + nw: "nwse-resize", + ne: "nesw-resize", + se: "nwse-resize", + sw: "nesw-resize" + }, + dD = [ + ["n", "e", "s", "w", "nw", "ne", "se", "sw"], + ["e", "w"], + ["n", "s"], + [] + ]; + d3.behavior = {}, d3.behavior.drag = function() { + function c() { + this.on("mousedown.drag", d).on("touchstart.drag", d) + } + + function d() { + function j() { + var a = c.parentNode, + b = d3.event.changedTouches; + return b ? d3.touches(a, b)[0] : d3.mouse(a) + } + + function k() { + if (!c.parentNode) return l(); + var a = j(), + b = a[0] - g[0], + e = a[1] - g[1]; + h |= b | e, g = a, Z(), d({ + type: "drag", + x: a[0] + f[0], + y: a[1] + f[1], + dx: b, + dy: e + }) + } + + function l() { + d({ + type: "dragend" + }), h && (Z(), d3.event.target === e && i.on("click.drag", m, !0)), i.on("mousemove.drag", null).on("touchmove.drag", null).on("mouseup.drag", null).on("touchend.drag", null) + } + + function m() { + Z(), i.on("click.drag", null) + } + var c = this, + d = a.of(c, arguments), + e = d3.event.target, + f, g = j(), + h = 0, + i = d3.select(window).on("mousemove.drag", k).on("touchmove.drag", k).on("mouseup.drag", l, !0).on("touchend.drag", l, !0); + b ? (f = b.apply(c, arguments), f = [f.x - g[0], f.y - g[1]]) : f = [0, 0], Z(), d({ + type: "dragstart" + }) + } + var a = _(c, "drag", "dragstart", "dragend"), + b = null; + return c.origin = function(a) { + return arguments.length ? (b = a, c) : b + }, d3.rebind(c, a, "on") + }, d3.behavior.zoom = function() { + function l() { + this.on("mousedown.zoom", r).on("mousewheel.zoom", s).on("mousemove.zoom", t).on("DOMMouseScroll.zoom", s).on("dblclick.zoom", u).on("touchstart.zoom", v).on("touchmove.zoom", w).on("touchend.zoom", v) + } + + function m(b) { + return [(b[0] - a[0]) / c, (b[1] - a[1]) / c] + } + + function n(b) { + return [b[0] * c + a[0], b[1] * c + a[1]] + } + + function o(a) { + c = Math.max(e[0], Math.min(e[1], a)) + } + + function p(b, c) { + c = n(c), a[0] += b[0] - c[0], a[1] += b[1] - c[1] + } + + function q(b) { + h && h.domain(g.range().map(function(b) { + return (b - a[0]) / c + }).map(g.invert)), j && j.domain(i.range().map(function(b) { + return (b - a[1]) / c + }).map(i.invert)), d3.event.preventDefault(), b({ + type: "zoom", + scale: c, + translate: a + }) + } + + function r() { + function h() { + d = 1, p(d3.mouse(a), g), q(b) + } + + function i() { + d && Z(), e.on("mousemove.zoom", null).on("mouseup.zoom", null), d && d3.event.target === c && e.on("click.zoom", j, !0) + } + + function j() { + Z(), e.on("click.zoom", null) + } + var a = this, + b = f.of(a, arguments), + c = d3.event.target, + d = 0, + e = d3.select(window).on("mousemove.zoom", h).on("mouseup.zoom", i), + g = m(d3.mouse(a)); + window.focus(), Z() + } + + function s() { + b || (b = m(d3.mouse(this))), o(Math.pow(2, dG() * .002) * c), p(d3.mouse(this), b), q(f.of(this, arguments)) + } + + function t() { + b = null + } + + function u() { + var a = d3.mouse(this), + b = m(a); + o(d3.event.shiftKey ? c / 2 : c * 2), p(a, b), q(f.of(this, arguments)) + } + + function v() { + var a = d3.touches(this), + e = Date.now(); + d = c, b = {}, a.forEach(function(a) { + b[a.identifier] = m(a) + }), Z(); + if (a.length === 1 && e - k < 500) { + var g = a[0], + h = m(a[0]); + o(c * 2), p(g, h), q(f.of(this, arguments)) + } + k = e + } + + function w() { + var a = d3.touches(this), + c = a[0], + e = b[c.identifier]; + if (g = a[1]) { + var g, h = b[g.identifier]; + c = [(c[0] + g[0]) / 2, (c[1] + g[1]) / 2], e = [(e[0] + h[0]) / 2, (e[1] + h[1]) / 2], o(d3.event.scale * d) + } + p(c, e), q(f.of(this, arguments)) + } + var a = [0, 0], + b, c = 1, + d, e = dF, + f = _(l, "zoom"), + g, h, i, j, k; + return l.translate = function(b) { + return arguments.length ? (a = b.map(Number), l) : a + }, l.scale = function(a) { + return arguments.length ? (c = +a, l) : c + }, l.scaleExtent = function(a) { + return arguments.length ? (e = a == null ? dF : a.map(Number), l) : e + }, l.x = function(a) { + return arguments.length ? (h = a, g = a.copy(), l) : h + }, l.y = function(a) { + return arguments.length ? (j = a, i = a.copy(), l) : j + }, d3.rebind(l, f, "on") + }; + var dE, dF = [0, Infinity]; + d3.layout = {}, d3.layout.bundle = function() { + return function(a) { + var b = [], + c = -1, + d = a.length; + while (++c < d) b.push(dH(a[c])); + return b + } + }, d3.layout.chord = function() { + function j() { + var a = {}, + j = [], + l = d3.range(e), + m = [], + n, o, p, q, r; + b = [], c = [], n = 0, q = -1; + while (++q < e) { + o = 0, r = -1; + while (++r < e) o += d[q][r]; + j.push(o), m.push(d3.range(e)), n += o + } + g && l.sort(function(a, b) { + return g(j[a], j[b]) + }), h && m.forEach(function(a, b) { + a.sort(function(a, c) { + return h(d[b][a], d[b][c]) + }) + }), n = (2 * Math.PI - f * e) / n, o = 0, q = -1; + while (++q < e) { + p = o, r = -1; + while (++r < e) { + var s = l[q], + t = m[s][r], + u = d[s][t], + v = o, + w = o += u * n; + a[s + "-" + t] = { + index: s, + subindex: t, + startAngle: v, + endAngle: w, + value: u + } + } + c[s] = { + index: s, + startAngle: p, + endAngle: o, + value: (o - p) / n + }, o += f + } + q = -1; + while (++q < e) { + r = q - 1; + while (++r < e) { + var x = a[q + "-" + r], + y = a[r + "-" + q]; + (x.value || y.value) && b.push(x.value < y.value ? { + source: y, + target: x + } : { + source: x, + target: y + }) + } + } + i && k() + } + + function k() { + b.sort(function(a, b) { + return i((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2) + }) + } + var a = {}, + b, c, d, e, f = 0, + g, h, i; + return a.matrix = function(f) { + return arguments.length ? (e = (d = f) && d.length, b = c = null, a) : d + }, a.padding = function(d) { + return arguments.length ? (f = d, b = c = null, a) : f + }, a.sortGroups = function(d) { + return arguments.length ? (g = d, b = c = null, a) : g + }, a.sortSubgroups = function(c) { + return arguments.length ? (h = c, b = null, a) : h + }, a.sortChords = function(c) { + return arguments.length ? (i = c, b && k(), a) : i + }, a.chords = function() { + return b || j(), b + }, a.groups = function() { + return c || j(), c + }, a + }, d3.layout.force = function() { + function t(a) { + return function(b, c, d, e, f) { + if (b.point !== a) { + var g = b.cx - a.x, + h = b.cy - a.y, + i = 1 / Math.sqrt(g * g + h * h); + if ((e - c) * i < k) { + var j = b.charge * i * i; + return a.px -= g * j, a.py -= h * j, !0 + } + if (b.point && isFinite(i)) { + var j = b.pointCharge * i * i; + a.px -= g * j, a.py -= h * j + } + } + return !b.charge + } + } + + function u(b) { + dM(dL = b), dK = a + } + var a = {}, + b = d3.dispatch("start", "tick", "end"), + c = [1, 1], + d, e, f = .9, + g = dR, + h = dS, + i = -30, + j = .1, + k = .8, + l, m = [], + o = [], + p, r, s; + return a.tick = function() { + if ((e *= .99) < .005) return b.end({ + type: "end", + alpha: e = 0 + }), !0; + var a = m.length, + d = o.length, + g, h, k, l, n, q, u, v, w; + for (h = 0; h < d; ++h) { + k = o[h], l = k.source, n = k.target, v = n.x - l.x, w = n.y - l.y; + if (q = v * v + w * w) q = e * r[h] * ((q = Math.sqrt(q)) - p[h]) / q, v *= q, w *= q, n.x -= v * (u = l.weight / (n.weight + l.weight)), n.y -= w * u, l.x += v * (u = 1 - u), l.y += w * u + } + if (u = e * j) { + v = c[0] / 2, w = c[1] / 2, h = -1; + if (u) + while (++h < a) k = m[h], k.x += (v - k.x) * u, k.y += (w - k.y) * u + } + if (i) { + dQ(g = d3.geom.quadtree(m), e, s), h = -1; + while (++h < a)(k = m[h]).fixed || g.visit(t(k)) + } + h = -1; + while (++h < a) k = m[h], k.fixed ? (k.x = k.px, k.y = k.py) : (k.x -= (k.px - (k.px = k.x)) * f, k.y -= (k.py - (k.py = k.y)) * f); + b.tick({ + type: "tick", + alpha: e + }) + }, a.nodes = function(b) { + return arguments.length ? (m = b, a) : m + }, a.links = function(b) { + return arguments.length ? (o = b, a) : o + }, a.size = function(b) { + return arguments.length ? (c = b, a) : c + }, a.linkDistance = function(b) { + return arguments.length ? (g = q(b), a) : g + }, a.distance = a.linkDistance, a.linkStrength = function(b) { + return arguments.length ? (h = q(b), a) : h + }, a.friction = function(b) { + return arguments.length ? (f = b, a) : f + }, a.charge = function(b) { + return arguments.length ? (i = typeof b == "function" ? b : +b, a) : i + }, a.gravity = function(b) { + return arguments.length ? (j = b, a) : j + }, a.theta = function(b) { + return arguments.length ? (k = b, a) : k + }, a.alpha = function(c) { + return arguments.length ? (e ? c > 0 ? e = c : e = 0 : c > 0 && (b.start({ + type: "start", + alpha: e = c + }), d3.timer(a.tick)), a) : e + }, a.start = function() { + function q(a, c) { + var d = t(b), + e = -1, + f = d.length, + g; + while (++e < f) + if (!isNaN(g = d[e][a])) return g; + return Math.random() * c + } + + function t() { + if (!l) { + l = []; + for (d = 0; d < e; ++d) l[d] = []; + for (d = 0; d < f; ++d) { + var a = o[d]; + l[a.source.index].push(a.target), l[a.target.index].push(a.source) + } + } + return l[b] + } + var b, d, e = m.length, + f = o.length, + j = c[0], + k = c[1], + l, n; + for (b = 0; b < e; ++b)(n = m[b]).index = b, n.weight = 0; + p = [], r = []; + for (b = 0; b < f; ++b) n = o[b], typeof n.source == "number" && (n.source = m[n.source]), typeof n.target == "number" && (n.target = m[n.target]), p[b] = g.call(this, n, b), r[b] = h.call(this, n, b), ++n.source.weight, ++n.target.weight; + for (b = 0; b < e; ++b) n = m[b], isNaN(n.x) && (n.x = q("x", j)), isNaN(n.y) && (n.y = q("y", k)), isNaN(n.px) && (n.px = n.x), isNaN(n.py) && (n.py = n.y); + s = []; + if (typeof i == "function") + for (b = 0; b < e; ++b) s[b] = +i.call(this, m[b], b); + else + for (b = 0; b < e; ++b) s[b] = i; + return a.resume() + }, a.resume = function() { + return a.alpha(.1) + }, a.stop = function() { + return a.alpha(0) + }, a.drag = function() { + d || (d = d3.behavior.drag().origin(n).on("dragstart", u).on("drag", dP).on("dragend", dO)), this.on("mouseover.force", dM).on("mouseout.force", dN).call(d) + }, d3.rebind(a, b, "on") + }; + var dK, dL; + d3.layout.partition = function() { + function c(a, b, d, e) { + var f = a.children; + a.x = b, a.y = a.depth * e, a.dx = d, a.dy = e; + if (f && (h = f.length)) { + var g = -1, + h, i, j; + d = a.value ? d / a.value : 0; + while (++g < h) c(i = f[g], b, j = i.value * d, e), b += j + } + } + + function d(a) { + var b = a.children, + c = 0; + if (b && (f = b.length)) { + var e = -1, + f; + while (++e < f) c = Math.max(c, d(b[e])) + } + return 1 + c + } + + function e(e, f) { + var g = a.call(this, e, f); + return c(g[0], 0, b[0], b[1] / d(g[0])), g + } + var a = d3.layout.hierarchy(), + b = [1, 1]; + return e.size = function(a) { + return arguments.length ? (b = a, e) : b + }, ef(e, a) + }, d3.layout.pie = function() { + function f(g, h) { + var i = g.map(function(b, c) { + return +a.call(f, b, c) + }), + j = +(typeof c == "function" ? c.apply(this, arguments) : c), + k = ((typeof e == "function" ? e.apply(this, arguments) : e) - c) / d3.sum(i), + l = d3.range(g.length); + b != null && l.sort(b === dT ? function(a, b) { + return i[b] - i[a] + } : function(a, c) { + return b(g[a], g[c]) + }); + var m = []; + return l.forEach(function(a) { + m[a] = { + data: g[a], + value: d = i[a], + startAngle: j, + endAngle: j += d * k + } + }), m + } + var a = Number, + b = dT, + c = 0, + e = 2 * Math.PI; + return f.value = function(b) { + return arguments.length ? (a = b, f) : a + }, f.sort = function(a) { + return arguments.length ? (b = a, f) : b + }, f.startAngle = function(a) { + return arguments.length ? (c = a, f) : c + }, f.endAngle = function(a) { + return arguments.length ? (e = a, f) : e + }, f + }; + var dT = {}; + d3.layout.stack = function() { + function g(h, i) { + var j = h.map(function(b, c) { + return a.call(g, b, c) + }), + k = j.map(function(a, b) { + return a.map(function(a, b) { + return [e.call(g, a, b), f.call(g, a, b)] + }) + }), + l = b.call(g, k, i); + j = d3.permute(j, l), k = d3.permute(k, l); + var m = c.call(g, k, i), + n = j.length, + o = j[0].length, + p, q, r; + for (q = 0; q < o; ++q) { + d.call(g, j[0][q], r = m[q], k[0][q][1]); + for (p = 1; p < n; ++p) d.call(g, j[p][q], r += k[p - 1][q][1], k[p][q][1]) + } + return h + } + var a = n, + b = dZ, + c = d$, + d = dW, + e = dU, + f = dV; + return g.values = function(b) { + return arguments.length ? (a = b, g) : a + }, g.order = function(a) { + return arguments.length ? (b = typeof a == "function" ? a : dX.get(a) || dZ, g) : b + }, g.offset = function(a) { + return arguments.length ? (c = typeof a == "function" ? a : dY.get(a) || d$, g) : c + }, g.x = function(a) { + return arguments.length ? (e = a, g) : e + }, g.y = function(a) { + return arguments.length ? (f = a, g) : f + }, g.out = function(a) { + return arguments.length ? (d = a, g) : d + }, g + }; + var dX = d3.map({ + "inside-out": function(a) { + var b = a.length, + c, d, e = a.map(d_), + f = a.map(ea), + g = d3.range(b).sort(function(a, b) { + return e[a] - e[b] + }), + h = 0, + i = 0, + j = [], + k = []; + for (c = 0; c < b; ++c) d = g[c], h < i ? (h += f[d], j.push(d)) : (i += f[d], k.push(d)); + return k.reverse().concat(j) + }, + reverse: function(a) { + return d3.range(a.length).reverse() + }, + "default": dZ + }), + dY = d3.map({ + silhouette: function(a) { + var b = a.length, + c = a[0].length, + d = [], + e = 0, + f, g, h, i = []; + for (g = 0; g < c; ++g) { + for (f = 0, h = 0; f < b; f++) h += a[f][g][1]; + h > e && (e = h), d.push(h) + } + for (g = 0; g < c; ++g) i[g] = (e - d[g]) / 2; + return i + }, + wiggle: function(a) { + var b = a.length, + c = a[0], + d = c.length, + e = 0, + f, g, h, i, j, k, l, m, n, o = []; + o[0] = m = n = 0; + for (g = 1; g < d; ++g) { + for (f = 0, i = 0; f < b; ++f) i += a[f][g][1]; + for (f = 0, j = 0, l = c[g][0] - c[g - 1][0]; f < b; ++f) { + for (h = 0, k = (a[f][g][1] - a[f][g - 1][1]) / (2 * l); h < f; ++h) k += (a[h][g][1] - a[h][g - 1][1]) / l; + j += k * a[f][g][1] + } + o[g] = m -= i ? j / i * l : 0, m < n && (n = m) + } + for (g = 0; g < d; ++g) o[g] -= n; + return o + }, + expand: function(a) { + var b = a.length, + c = a[0].length, + d = 1 / b, + e, f, g, h = []; + for (f = 0; f < c; ++f) { + for (e = 0, g = 0; e < b; e++) g += a[e][f][1]; + if (g) + for (e = 0; e < b; e++) a[e][f][1] /= g; + else + for (e = 0; e < b; e++) a[e][f][1] = d + } + for (f = 0; f < c; ++f) h[f] = 0; + return h + }, + zero: d$ + }); + d3.layout.histogram = function() { + function e(e, f) { + var g = [], + h = e.map(b, this), + i = c.call(this, h, f), + j = d.call(this, i, h, f), + k, f = -1, + l = h.length, + m = j.length - 1, + n = a ? 1 : 1 / l, + o; + while (++f < m) k = g[f] = [], k.dx = j[f + 1] - (k.x = j[f]), k.y = 0; + if (m > 0) { + f = -1; + while (++f < l) o = h[f], o >= i[0] && o <= i[1] && (k = g[d3.bisect(j, o, 1, m) - 1], k.y += n, k.push(e[f])) + } + return g + } + var a = !0, + b = Number, + c = ee, + d = ec; + return e.value = function(a) { + return arguments.length ? (b = a, e) : b + }, e.range = function(a) { + return arguments.length ? (c = q(a), e) : c + }, e.bins = function(a) { + return arguments.length ? (d = typeof a == "number" ? function(b) { + return ed(b, a) + } : q(a), e) : d + }, e.frequency = function(b) { + return arguments.length ? (a = !!b, e) : a + }, e + }, d3.layout.hierarchy = function() { + function e(f, h, i) { + var j = b.call(g, f, h), + k = ek ? f : { + data: f + }; + k.depth = h, i.push(k); + if (j && (m = j.length)) { + var l = -1, + m, n = k.children = [], + o = 0, + p = h + 1; + while (++l < m) d = e(j[l], p, i), d.parent = k, n.push(d), o += d.value; + a && n.sort(a), c && (k.value = o) + } else c && (k.value = +c.call(g, f, h) || 0); + return k + } + + function f(a, b) { + var d = a.children, + e = 0; + if (d && (i = d.length)) { + var h = -1, + i, j = b + 1; + while (++h < i) e += f(d[h], j) + } else c && (e = +c.call(g, ek ? a : a.data, b) || 0); + return c && (a.value = e), e + } + + function g(a) { + var b = []; + return e(a, 0, b), b + } + var a = ei, + b = eg, + c = eh; + return g.sort = function(b) { + return arguments.length ? (a = b, g) : a + }, g.children = function(a) { + return arguments.length ? (b = a, g) : b + }, g.value = function(a) { + return arguments.length ? (c = a, g) : c + }, g.revalue = function(a) { + return f(a, 0), a + }, g + }; + var ek = !1; + d3.layout.pack = function() { + function c(c, d) { + var e = a.call(this, c, d), + f = e[0]; + f.x = 0, f.y = 0, es(f); + var g = b[0], + h = b[1], + i = 1 / Math.max(2 * f.r / g, 2 * f.r / h); + return et(f, g / 2, h / 2, i), e + } + var a = d3.layout.hierarchy().sort(el), + b = [1, 1]; + return c.size = function(a) { + return arguments.length ? (b = a, c) : b + }, ef(c, a) + }, d3.layout.cluster = function() { + function d(d, e) { + var f = a.call(this, d, e), + g = f[0], + h, i = 0, + j, k; + eG(g, function(a) { + var c = a.children; + c && c.length ? (a.x = ew(c), a.y = ev(c)) : (a.x = h ? i += b(a, h) : 0, a.y = 0, h = a) + }); + var l = ex(g), + m = ey(g), + n = l.x - b(l, m) / 2, + o = m.x + b(m, l) / 2; + return eG(g, function(a) { + a.x = (a.x - n) / (o - n) * c[0], a.y = (1 - (g.y ? a.y / g.y : 1)) * c[1] + }), f + } + var a = d3.layout.hierarchy().sort(null).value(null), + b = ez, + c = [1, 1]; + return d.separation = function(a) { + return arguments.length ? (b = a, d) : b + }, d.size = function(a) { + return arguments.length ? (c = a, d) : c + }, ef(d, a) + }, d3.layout.tree = function() { + function d(d, e) { + function h(a, c) { + var d = a.children, + e = a._tree; + if (d && (f = d.length)) { + var f, g = d[0], + i, k = g, + l, m = -1; + while (++m < f) l = d[m], h(l, i), k = j(l, i, k), i = l; + eH(a); + var n = .5 * (g._tree.prelim + l._tree.prelim); + c ? (e.prelim = c._tree.prelim + b(a, c), e.mod = e.prelim - n) : e.prelim = n + } else c && (e.prelim = c._tree.prelim + b(a, c)) + } + + function i(a, b) { + a.x = a._tree.prelim + b; + var c = a.children; + if (c && (e = c.length)) { + var d = -1, + e; + b += a._tree.mod; + while (++d < e) i(c[d], b) + } + } + + function j(a, c, d) { + if (c) { + var e = a, + f = a, + g = c, + h = a.parent.children[0], + i = e._tree.mod, + j = f._tree.mod, + k = g._tree.mod, + l = h._tree.mod, + m; + while (g = eB(g), e = eA(e), g && e) h = eA(h), f = eB(f), f._tree.ancestor = a, m = g._tree.prelim + k - e._tree.prelim - i + b(g, e), m > 0 && (eI(eJ(g, a, d), a, m), i += m, j += m), k += g._tree.mod, i += e._tree.mod, l += h._tree.mod, j += f._tree.mod; + g && !eB(f) && (f._tree.thread = g, f._tree.mod += k - j), e && !eA(h) && (h._tree.thread = e, h._tree.mod += i - l, d = a) + } + return d + } + var f = a.call(this, d, e), + g = f[0]; + eG(g, function(a, b) { + a._tree = { + ancestor: a, + prelim: 0, + mod: 0, + change: 0, + shift: 0, + number: b ? b._tree.number + 1 : 0 + } + }), h(g), i(g, -g._tree.prelim); + var k = eC(g, eE), + l = eC(g, eD), + m = eC(g, eF), + n = k.x - b(k, l) / 2, + o = l.x + b(l, k) / 2, + p = m.depth || 1; + return eG(g, function(a) { + a.x = (a.x - n) / (o - n) * c[0], a.y = a.depth / p * c[1], delete a._tree + }), f + } + var a = d3.layout.hierarchy().sort(null).value(null), + b = ez, + c = [1, 1]; + return d.separation = function(a) { + return arguments.length ? (b = a, d) : b + }, d.size = function(a) { + return arguments.length ? (c = a, d) : c + }, ef(d, a) + }, d3.layout.treemap = function() { + function i(a, b) { + var c = -1, + d = a.length, + e, f; + while (++c < d) f = (e = a[c]).value * (b < 0 ? 0 : b), e.area = isNaN(f) || f <= 0 ? 0 : f + } + + function j(a) { + var b = a.children; + if (b && b.length) { + var c = e(a), + d = [], + f = b.slice(), + g, h = Infinity, + k, n = Math.min(c.dx, c.dy), + o; + i(f, c.dx * c.dy / a.value), d.area = 0; + while ((o = f.length) > 0) d.push(g = f[o - 1]), d.area += g.area, (k = l(d, n)) <= h ? (f.pop(), h = k) : (d.area -= d.pop().area, m(d, n, c, !1), n = Math.min(c.dx, c.dy), d.length = d.area = 0, h = Infinity); + d.length && (m(d, n, c, !0), d.length = d.area = 0), b.forEach(j) + } + } + + function k(a) { + var b = a.children; + if (b && b.length) { + var c = e(a), + d = b.slice(), + f, g = []; + i(d, c.dx * c.dy / a.value), g.area = 0; + while (f = d.pop()) g.push(f), g.area += f.area, f.z != null && (m(g, f.z ? c.dx : c.dy, c, !d.length), g.length = g.area = 0); + b.forEach(k) + } + } + + function l(a, b) { + var c = a.area, + d, e = 0, + f = Infinity, + g = -1, + i = a.length; + while (++g < i) { + if (!(d = a[g].area)) continue; + d < f && (f = d), d > e && (e = d) + } + return c *= c, b *= b, c ? Math.max(b * e * h / c, c / (b * f * h)) : Infinity + } + + function m(a, c, d, e) { + var f = -1, + g = a.length, + h = d.x, + i = d.y, + j = c ? b(a.area / c) : 0, + k; + if (c == d.dx) { + if (e || j > d.dy) j = d.dy; + while (++f < g) k = a[f], k.x = h, k.y = i, k.dy = j, h += k.dx = Math.min(d.x + d.dx - h, j ? b(k.area / j) : 0); + k.z = !0, k.dx += d.x + d.dx - h, d.y += j, d.dy -= j + } else { + if (e || j > d.dx) j = d.dx; + while (++f < g) k = a[f], k.x = h, k.y = i, k.dx = j, i += k.dy = Math.min(d.y + d.dy - i, j ? b(k.area / j) : 0); + k.z = !1, k.dy += d.y + d.dy - i, d.x += j, d.dx -= j + } + } + + function n(b) { + var d = g || a(b), + e = d[0]; + return e.x = 0, e.y = 0, e.dx = c[0], e.dy = c[1], g && a.revalue(e), i([e], e.dx * e.dy / e.value), (g ? k : j)(e), f && (g = d), d + } + var a = d3.layout.hierarchy(), + b = Math.round, + c = [1, 1], + d = null, + e = eK, + f = !1, + g, h = .5 * (1 + Math.sqrt(5)); + return n.size = function(a) { + return arguments.length ? (c = a, n) : c + }, n.padding = function(a) { + function b(b) { + var c = a.call(n, b, b.depth); + return c == null ? eK(b) : eL(b, typeof c == "number" ? [c, c, c, c] : c) + } + + function c(b) { + return eL(b, a) + } + if (!arguments.length) return d; + var f; + return e = (d = a) == null ? eK : (f = typeof a) === "function" ? b : f === "number" ? (a = [a, a, a, a], c) : c, n + }, n.round = function(a) { + return arguments.length ? (b = a ? Math.round : Number, n) : b != Number + }, n.sticky = function(a) { + return arguments.length ? (f = a, g = null, n) : f + }, n.ratio = function(a) { + return arguments.length ? (h = a, n) : h + }, ef(n, a) + }, d3.csv = function(a, b) { + d3.text(a, "text/csv", function(a) { + b(a && d3.csv.parse(a)) + }) + }, d3.csv.parse = function(a) { + var b; + return d3.csv.parseRows(a, function(a, c) { + if (c) { + var d = {}, + e = -1, + f = b.length; + while (++e < f) d[b[e]] = a[e]; + return d + } + return b = a, null + }) + }, d3.csv.parseRows = function(a, b) { + function j() { + if (f.lastIndex >= a.length) return d; + if (i) return i = !1, c; + var b = f.lastIndex; + if (a.charCodeAt(b) === 34) { + var e = b; + while (e++ < a.length) + if (a.charCodeAt(e) === 34) { + if (a.charCodeAt(e + 1) !== 34) break; + e++ + } + f.lastIndex = e + 2; + var g = a.charCodeAt(e + 1); + return g === 13 ? (i = !0, a.charCodeAt(e + 2) === 10 && f.lastIndex++) : g === 10 && (i = !0), a.substring(b + 1, e).replace(/""/g, '"') + } + var h = f.exec(a); + return h ? (i = h[0].charCodeAt(0) !== 44, a.substring(b, h.index)) : (f.lastIndex = a.length, a.substring(b)) + } + var c = {}, + d = {}, + e = [], + f = /\r\n|[,\r\n]/g, + g = 0, + h, i; + f.lastIndex = 0; + while ((h = j()) !== d) { + var k = []; + while (h !== c && h !== d) k.push(h), h = j(); + if (b && !(k = b(k, g++))) continue; + e.push(k) + } + return e + }, d3.csv.format = function(a) { + return a.map(eM).join("\n") + }, d3.geo = {}; + var eO = Math.PI / 180; + d3.geo.azimuthal = function() { + function i(b) { + var f = b[0] * eO - e, + i = b[1] * eO, + j = Math.cos(f), + k = Math.sin(f), + l = Math.cos(i), + m = Math.sin(i), + n = a !== "orthographic" ? h * m + g * l * j : null, + o, p = a === "stereographic" ? 1 / (1 + n) : a === "gnomonic" ? 1 / n : a === "equidistant" ? (o = Math.acos(n), o ? o / Math.sin(o) : 0) : a === "equalarea" ? Math.sqrt(2 / (1 + n)) : 1, + q = p * l * k, + r = p * (h * l * j - g * m); + return [c * q + d[0], c * r + d[1]] + } + var a = "orthographic", + b, c = 200, + d = [480, 250], + e, f, g, h; + return i.invert = function(b) { + var f = (b[0] - d[0]) / c, + i = (b[1] - d[1]) / c, + j = Math.sqrt(f * f + i * i), + k = a === "stereographic" ? 2 * Math.atan(j) : a === "gnomonic" ? Math.atan(j) : a === "equidistant" ? j : a === "equalarea" ? 2 * Math.asin(.5 * j) : Math.asin(j), + l = Math.sin(k), + m = Math.cos(k); + return [(e + Math.atan2(f * l, j * g * m + i * h * l)) / eO, Math.asin(m * h - (j ? i * l * g / j : 0)) / eO] + }, i.mode = function(b) { + return arguments.length ? (a = b + "", i) : a + }, i.origin = function(a) { + return arguments.length ? (b = a, e = b[0] * eO, f = b[1] * eO, g = Math.cos(f), h = Math.sin(f), i) : b + }, i.scale = function(a) { + return arguments.length ? (c = +a, i) : c + }, i.translate = function(a) { + return arguments.length ? (d = [+a[0], +a[1]], i) : d + }, i.origin([0, 0]) + }, d3.geo.albers = function() { + function i(a) { + var b = f * (eO * a[0] - e), + i = Math.sqrt(g - 2 * f * Math.sin(eO * a[1])) / f; + return [c * i * Math.sin(b) + d[0], c * (i * Math.cos(b) - h) + d[1]] + } + + function j() { + var c = eO * b[0], + d = eO * b[1], + j = eO * a[1], + k = Math.sin(c), + l = Math.cos(c); + return e = eO * a[0], f = .5 * (k + Math.sin(d)), g = l * l + 2 * f * k, h = Math.sqrt(g - 2 * f * Math.sin(j)) / f, i + } + var a = [-98, 38], + b = [29.5, 45.5], + c = 1e3, + d = [480, 250], + e, f, g, h; + return i.invert = function(a) { + var b = (a[0] - d[0]) / c, + i = (a[1] - d[1]) / c, + j = h + i, + k = Math.atan2(b, j), + l = Math.sqrt(b * b + j * j); + return [(e + k / f) / eO, Math.asin((g - l * l * f * f) / (2 * f)) / eO] + }, i.origin = function(b) { + return arguments.length ? (a = [+b[0], +b[1]], j()) : a + }, i.parallels = function(a) { + return arguments.length ? (b = [+a[0], +a[1]], j()) : b + }, i.scale = function(a) { + return arguments.length ? (c = +a, i) : c + }, i.translate = function(a) { + return arguments.length ? (d = [+a[0], +a[1]], i) : d + }, j() + }, d3.geo.albersUsa = function() { + function e(e) { + var f = e[0], + g = e[1]; + return (g > 50 ? b : f < -140 ? c : g < 21 ? d : a)(e) + } + var a = d3.geo.albers(), + b = d3.geo.albers().origin([-160, 60]).parallels([55, 65]), + c = d3.geo.albers().origin([-160, 20]).parallels([8, 18]), + d = d3.geo.albers().origin([-60, 10]).parallels([8, 18]); + return e.scale = function(f) { + return arguments.length ? (a.scale(f), b.scale(f * .6), c.scale(f), d.scale(f * 1.5), e.translate(a.translate())) : a.scale() + }, e.translate = function(f) { + if (!arguments.length) return a.translate(); + var g = a.scale() / 1e3, + h = f[0], + i = f[1]; + return a.translate(f), b.translate([h - 400 * g, i + 170 * g]), c.translate([h - 190 * g, i + 200 * g]), d.translate([h + 580 * g, i + 430 * g]), e + }, e.scale(a.scale()) + }, d3.geo.bonne = function() { + function g(g) { + var h = g[0] * eO - c, + i = g[1] * eO - d; + if (e) { + var j = f + e - i, + k = h * Math.cos(i) / j; + h = j * Math.sin(k), i = j * Math.cos(k) - f + } else h *= Math.cos(i), i *= -1; + return [a * h + b[0], a * i + b[1]] + } + var a = 200, + b = [480, 250], + c, d, e, f; + return g.invert = function(d) { + var g = (d[0] - b[0]) / a, + h = (d[1] - b[1]) / a; + if (e) { + var i = f + h, + j = Math.sqrt(g * g + i * i); + h = f + e - j, g = c + j * Math.atan2(g, i) / Math.cos(h) + } else h *= -1, g /= Math.cos(h); + return [g / eO, h / eO] + }, g.parallel = function(a) { + return arguments.length ? (f = 1 / Math.tan(e = a * eO), g) : e / eO + }, g.origin = function(a) { + return arguments.length ? (c = a[0] * eO, d = a[1] * eO, g) : [c / eO, d / eO] + }, g.scale = function(b) { + return arguments.length ? (a = +b, g) : a + }, g.translate = function(a) { + return arguments.length ? (b = [+a[0], +a[1]], g) : b + }, g.origin([0, 0]).parallel(45) + }, d3.geo.equirectangular = function() { + function c(c) { + var d = c[0] / 360, + e = -c[1] / 360; + return [a * d + b[0], a * e + b[1]] + } + var a = 500, + b = [480, 250]; + return c.invert = function(c) { + var d = (c[0] - b[0]) / a, + e = (c[1] - b[1]) / a; + return [360 * d, -360 * e] + }, c.scale = function(b) { + return arguments.length ? (a = +b, c) : a + }, c.translate = function(a) { + return arguments.length ? (b = [+a[0], +a[1]], c) : b + }, c + }, d3.geo.mercator = function() { + function c(c) { + var d = c[0] / 360, + e = -(Math.log(Math.tan(Math.PI / 4 + c[1] * eO / 2)) / eO) / 360; + return [a * d + b[0], a * Math.max(-0.5, Math.min(.5, e)) + b[1]] + } + var a = 500, + b = [480, 250]; + return c.invert = function(c) { + var d = (c[0] - b[0]) / a, + e = (c[1] - b[1]) / a; + return [360 * d, 2 * Math.atan(Math.exp(-360 * e * eO)) / eO - 90] + }, c.scale = function(b) { + return arguments.length ? (a = +b, c) : a + }, c.translate = function(a) { + return arguments.length ? (b = [+a[0], +a[1]], c) : b + }, c + }, d3.geo.path = function() { + function d(c, d) { + return typeof a == "function" && (b = eQ(a.apply(this, arguments))), f(c) || null + } + + function e(a) { + return c(a).join(",") + } + + function h(a) { + var b = k(a[0]), + c = 0, + d = a.length; + while (++c < d) b -= k(a[c]); + return b + } + + function i(a) { + var b = d3.geom.polygon(a[0].map(c)), + d = b.area(), + e = b.centroid(d < 0 ? (d *= -1, 1) : -1), + f = e[0], + g = e[1], + h = d, + i = 0, + j = a.length; + while (++i < j) b = d3.geom.polygon(a[i].map(c)), d = b.area(), e = b.centroid(d < 0 ? (d *= -1, 1) : -1), f -= e[0], g -= e[1], h -= d; + return [f, g, 6 * h] + } + + function k(a) { + return Math.abs(d3.geom.polygon(a.map(c)).area()) + } + var a = 4.5, + b = eQ(a), + c = d3.geo.albersUsa(), + f = eP({ + FeatureCollection: function(a) { + var b = [], + c = a.features, + d = -1, + e = c.length; + while (++d < e) b.push(f(c[d].geometry)); + return b.join("") + }, + Feature: function(a) { + return f(a.geometry) + }, + Point: function(a) { + return "M" + e(a.coordinates) + b + }, + MultiPoint: function(a) { + var c = [], + d = a.coordinates, + f = -1, + g = d.length; + while (++f < g) c.push("M", e(d[f]), b); + return c.join("") + }, + LineString: function(a) { + var b = ["M"], + c = a.coordinates, + d = -1, + f = c.length; + while (++d < f) b.push(e(c[d]), "L"); + return b.pop(), b.join("") + }, + MultiLineString: function(a) { + var b = [], + c = a.coordinates, + d = -1, + f = c.length, + g, h, i; + while (++d < f) { + g = c[d], h = -1, i = g.length, b.push("M"); + while (++h < i) b.push(e(g[h]), "L"); + b.pop() + } + return b.join("") + }, + Polygon: function(a) { + var b = [], + c = a.coordinates, + d = -1, + f = c.length, + g, h, i; + while (++d < f) { + g = c[d], h = -1; + if ((i = g.length - 1) > 0) { + b.push("M"); + while (++h < i) b.push(e(g[h]), "L"); + b[b.length - 1] = "Z" + } + } + return b.join("") + }, + MultiPolygon: function(a) { + var b = [], + c = a.coordinates, + d = -1, + f = c.length, + g, h, i, j, k, l; + while (++d < f) { + g = c[d], h = -1, i = g.length; + while (++h < i) { + j = g[h], k = -1; + if ((l = j.length - 1) > 0) { + b.push("M"); + while (++k < l) b.push(e(j[k]), "L"); + b[b.length - 1] = "Z" + } + } + } + return b.join("") + }, + GeometryCollection: function(a) { + var b = [], + c = a.geometries, + d = -1, + e = c.length; + while (++d < e) b.push(f(c[d])); + return b.join("") + } + }), + g = d.area = eP({ + FeatureCollection: function(a) { + var b = 0, + c = a.features, + d = -1, + e = c.length; + while (++d < e) b += g(c[d]); + return b + }, + Feature: function(a) { + return g(a.geometry) + }, + Polygon: function(a) { + return h(a.coordinates) + }, + MultiPolygon: function(a) { + var b = 0, + c = a.coordinates, + d = -1, + e = c.length; + while (++d < e) b += h(c[d]); + return b + }, + GeometryCollection: function(a) { + var b = 0, + c = a.geometries, + d = -1, + e = c.length; + while (++d < e) b += g(c[d]); + return b + } + }, 0), + j = d.centroid = eP({ + Feature: function(a) { + return j(a.geometry) + }, + Polygon: function(a) { + var b = i(a.coordinates); + return [b[0] / b[2], b[1] / b[2]] + }, + MultiPolygon: function(a) { + var b = 0, + c = a.coordinates, + d, e = 0, + f = 0, + g = 0, + h = -1, + j = c.length; + while (++h < j) d = i(c[h]), e += d[0], f += d[1], g += d[2]; + return [e / g, f / g] + } + }); + return d.projection = function(a) { + return c = a, d + }, d.pointRadius = function(c) { + return typeof c == "function" ? a = c : (a = +c, b = eQ(a)), d + }, d + }, d3.geo.bounds = function(a) { + var b = Infinity, + c = Infinity, + d = -Infinity, + e = -Infinity; + return eR(a, function(a, f) { + a < b && (b = a), a > d && (d = a), f < c && (c = f), f > e && (e = f) + }), [ + [b, c], + [d, e] + ] + }; + var eS = { + Feature: eT, + FeatureCollection: eU, + GeometryCollection: eV, + LineString: eW, + MultiLineString: eX, + MultiPoint: eW, + MultiPolygon: eY, + Point: eZ, + Polygon: e$ + }; + d3.geo.circle = function() { + function e() {} + + function f(a) { + return d.distance(a) < c + } + + function h(a) { + var b = -1, + e = a.length, + f = [], + g, h, j, k, l; + while (++b < e) l = d.distance(j = a[b]), l < c ? (h && f.push(fb(h, j)((k - c) / (k - l))), f.push(j), g = h = null) : (h = j, !g && f.length && (f.push(fb(f[f.length - 1], h)((c - k) / (l - k))), g = h)), k = l; + return h && f.length && (l = d.distance(j = f[0]), f.push(fb(h, j)((k - c) / (k - l)))), i(f) + } + + function i(a) { + var b = 0, + c = a.length, + e, f, g = c ? [a[0]] : a, + h, i = d.source(); + while (++b < c) { + h = d.source(a[b - 1])(a[b]).coordinates; + for (e = 0, f = h.length; ++e < f;) g.push(h[e]) + } + return d.source(i), g + } + var a = [0, 0], + b = 89.99, + c = b * eO, + d = d3.geo.greatArc().target(n); + e.clip = function(b) { + return d.source(typeof a == "function" ? a.apply(this, arguments) : a), g(b) + }; + var g = eP({ + FeatureCollection: function(a) { + var b = a.features.map(g).filter(n); + return b && (a = Object.create(a), a.features = b, a) + }, + Feature: function( + a) { + var b = g(a.geometry); + return b && (a = Object.create(a), a.geometry = b, a) + }, + Point: function(a) { + return f(a.coordinates) && a + }, + MultiPoint: function(a) { + var b = a.coordinates.filter(f); + return b.length && { + type: a.type, + coordinates: b + } + }, + LineString: function(a) { + var b = h(a.coordinates); + return b.length && (a = Object.create(a), a.coordinates = b, a) + }, + MultiLineString: function(a) { + var b = a.coordinates.map(h).filter(function(a) { + return a.length + }); + return b.length && (a = Object.create(a), a.coordinates = b, a) + }, + Polygon: function(a) { + var b = a.coordinates.map(h); + return b[0].length && (a = Object.create(a), a.coordinates = b, a) + }, + MultiPolygon: function(a) { + var b = a.coordinates.map(function(a) { + return a.map(h) + }).filter(function(a) { + return a[0].length + }); + return b.length && (a = Object.create(a), a.coordinates = b, a) + }, + GeometryCollection: function(a) { + var b = a.geometries.map(g).filter(n); + return b.length && (a = Object.create(a), a.geometries = b, a) + } + }); + return e.origin = function(b) { + return arguments.length ? (a = b, e) : a + }, e.angle = function(a) { + return arguments.length ? (c = (b = +a) * eO, e) : b + }, e.precision = function(a) { + return arguments.length ? (d.precision(a), e) : d.precision() + }, e + }, d3.geo.greatArc = function() { + function d() { + var d = typeof a == "function" ? a.apply(this, arguments) : a, + e = typeof b == "function" ? b.apply(this, arguments) : b, + f = fb(d, e), + g = c / f.d, + h = 0, + i = [d]; + while ((h += g) < 1) i.push(f(h)); + return i.push(e), { + type: "LineString", + coordinates: i + } + } + var a = e_, + b = fa, + c = 6 * eO; + return d.distance = function() { + var c = typeof a == "function" ? a.apply(this, arguments) : a, + d = typeof b == "function" ? b.apply(this, arguments) : b; + return fb(c, d).d + }, d.source = function(b) { + return arguments.length ? (a = b, d) : a + }, d.target = function(a) { + return arguments.length ? (b = a, d) : b + }, d.precision = function(a) { + return arguments.length ? (c = a * eO, d) : c / eO + }, d + }, d3.geo.greatCircle = d3.geo.circle, d3.geom = {}, d3.geom.contour = function(a, b) { + var c = b || fe(a), + d = [], + e = c[0], + f = c[1], + g = 0, + h = 0, + i = NaN, + j = NaN, + k = 0; + do k = 0, a(e - 1, f - 1) && (k += 1), a(e, f - 1) && (k += 2), a(e - 1, f) && (k += 4), a(e, f) && (k += 8), k === 6 ? (g = j === -1 ? -1 : 1, h = 0) : k === 9 ? (g = 0, h = i === 1 ? -1 : 1) : (g = fc[k], h = fd[k]), g != i && h != j && (d.push([e, f]), i = g, j = h), e += g, f += h; while (c[0] != e || c[1] != f); + return d + }; + var fc = [1, 0, 1, 1, -1, 0, -1, 1, 0, 0, 0, 0, -1, 0, -1, NaN], + fd = [0, -1, 0, 0, 0, -1, 0, 0, 1, -1, 1, 1, 0, -1, 0, NaN]; + d3.geom.hull = function(a) { + if (a.length < 3) return []; + var b = a.length, + c = b - 1, + d = [], + e = [], + f, g, h = 0, + i, j, k, l, m, n, o, p; + for (f = 1; f < b; ++f) a[f][1] < a[h][1] ? h = f : a[f][1] == a[h][1] && (h = a[f][0] < a[h][0] ? f : h); + for (f = 0; f < b; ++f) { + if (f === h) continue; + j = a[f][1] - a[h][1], i = a[f][0] - a[h][0], d.push({ + angle: Math.atan2(j, i), + index: f + }) + } + d.sort(function(a, b) { + return a.angle - b.angle + }), o = d[0].angle, n = d[0].index, m = 0; + for (f = 1; f < c; ++f) g = d[f].index, o == d[f].angle ? (i = a[n][0] - a[h][0], j = a[n][1] - a[h][1], k = a[g][0] - a[h][0], l = a[g][1] - a[h][1], i * i + j * j >= k * k + l * l ? d[f].index = -1 : (d[m].index = -1, o = d[f].angle, m = f, n = g)) : (o = d[f].angle, m = f, n = g); + e.push(h); + for (f = 0, g = 0; f < 2; ++g) d[g].index !== -1 && (e.push(d[g].index), f++); + p = e.length; + for (; g < c; ++g) { + if (d[g].index === -1) continue; + while (!ff(e[p - 2], e[p - 1], d[g].index, a)) --p; + e[p++] = d[g].index + } + var q = []; + for (f = 0; f < p; ++f) q.push(a[e[f]]); + return q + }, d3.geom.polygon = function(a) { + return a.area = function() { + var b = 0, + c = a.length, + d = a[c - 1][0] * a[0][1], + e = a[c - 1][1] * a[0][0]; + while (++b < c) d += a[b - 1][0] * a[b][1], e += a[b - 1][1] * a[b][0]; + return (e - d) * .5 + }, a.centroid = function(b) { + var c = -1, + d = a.length, + e = 0, + f = 0, + g, h = a[d - 1], + i; + arguments.length || (b = -1 / (6 * a.area())); + while (++c < d) g = h, h = a[c], i = g[0] * h[1] - h[0] * g[1], e += (g[0] + h[0]) * i, f += (g[1] + h[1]) * i; + return [e * b, f * b] + }, a.clip = function(b) { + var c, d = -1, + e = a.length, + f, g, h = a[e - 1], + i, j, k; + while (++d < e) { + c = b.slice(), b.length = 0, i = a[d], j = c[(g = c.length) - 1], f = -1; + while (++f < g) k = c[f], fg(k, h, i) ? (fg(j, h, i) || b.push(fh(j, k, h, i)), b.push(k)) : fg(j, h, i) && b.push(fh(j, k, h, i)), j = k; + h = i + } + return b + }, a + }, d3.geom.voronoi = function(a) { + var b = a.map(function() { + return [] + }); + return fj(a, function(a) { + var c, d, e, f, g, h; + a.a === 1 && a.b >= 0 ? (c = a.ep.r, d = a.ep.l) : (c = a.ep.l, d = a.ep.r), a.a === 1 ? (g = c ? c.y : -1e6, e = a.c - a.b * g, h = d ? d.y : 1e6, f = a.c - a.b * h) : (e = c ? c.x : -1e6, g = a.c - a.a * e, f = d ? d.x : 1e6, h = a.c - a.a * f); + var i = [e, g], + j = [f, h]; + b[a.region.l.index].push(i, j), b[a.region.r.index].push(i, j) + }), b.map(function(b, c) { + var d = a[c][0], + e = a[c][1]; + return b.forEach(function(a) { + a.angle = Math.atan2(a[0] - d, a[1] - e) + }), b.sort(function(a, b) { + return a.angle - b.angle + }).filter(function(a, c) { + return !c || a.angle - b[c - 1].angle > 1e-10 + }) + }) + }; + var fi = { + l: "r", + r: "l" + }; + d3.geom.delaunay = function(a) { + var b = a.map(function() { + return [] + }), + c = []; + return fj(a, function(c) { + b[c.region.l.index].push(a[c.region.r.index]) + }), b.forEach(function(b, d) { + var e = a[d], + f = e[0], + g = e[1]; + b.forEach(function(a) { + a.angle = Math.atan2(a[0] - f, a[1] - g) + }), b.sort(function(a, b) { + return a.angle - b.angle + }); + for (var h = 0, i = b.length - 1; h < i; h++) c.push([e, b[h], b[h + 1]]) + }), c + }, d3.geom.quadtree = function(a, b, c, d, e) { + function k(a, b, c, d, e, f) { + if (isNaN(b.x) || isNaN(b.y)) return; + if (a.leaf) { + var g = a.point; + g ? Math.abs(g.x - b.x) + Math.abs(g.y - b.y) < .01 ? l(a, b, c, d, e, f) : (a.point = null, l(a, g, c, d, e, f), l(a, b, c, d, e, f)) : a.point = b + } else l(a, b, c, d, e, f) + } + + function l(a, b, c, d, e, f) { + var g = (c + e) * .5, + h = (d + f) * .5, + i = b.x >= g, + j = b.y >= h, + l = (j << 1) + i; + a.leaf = !1, a = a.nodes[l] || (a.nodes[l] = fk()), i ? c = g : e = g, j ? d = h : f = h, k(a, b, c, d, e, f) + } + var f, g = -1, + h = a.length; + h && isNaN(a[0].x) && (a = a.map(fm)); + if (arguments.length < 5) + if (arguments.length === 3) e = d = c, c = b; + else { + b = c = Infinity, d = e = -Infinity; + while (++g < h) f = a[g], f.x < b && (b = f.x), f.y < c && (c = f.y), f.x > d && (d = f.x), f.y > e && (e = f.y); + var i = d - b, + j = e - c; + i > j ? e = c + i : d = b + j + } + var m = fk(); + return m.add = function(a) { + k(m, a, b, c, d, e) + }, m.visit = function(a) { + fl(a, m, b, c, d, e) + }, a.forEach(m.add), m + }, d3.time = {}; + var fn = Date; + fo.prototype = { + getDate: function() { + return this._.getUTCDate() + }, + getDay: function() { + return this._.getUTCDay() + }, + getFullYear: function() { + return this._.getUTCFullYear() + }, + getHours: function() { + return this._.getUTCHours() + }, + getMilliseconds: function() { + return this._.getUTCMilliseconds() + }, + getMinutes: function() { + return this._.getUTCMinutes() + }, + getMonth: function() { + return this._.getUTCMonth() + }, + getSeconds: function() { + return this._.getUTCSeconds() + }, + getTime: function() { + return this._.getTime() + }, + getTimezoneOffset: function() { + return 0 + }, + valueOf: function() { + return this._.valueOf() + }, + setDate: function() { + fp.setUTCDate.apply(this._, arguments) + }, + setDay: function() { + fp.setUTCDay.apply(this._, arguments) + }, + setFullYear: function() { + fp.setUTCFullYear.apply(this._, arguments) + }, + setHours: function() { + fp.setUTCHours.apply(this._, arguments) + }, + setMilliseconds: function() { + fp.setUTCMilliseconds.apply(this._, arguments) + }, + setMinutes: function() { + fp.setUTCMinutes.apply(this._, arguments) + }, + setMonth: function() { + fp.setUTCMonth.apply(this._, arguments) + }, + setSeconds: function() { + fp.setUTCSeconds.apply(this._, arguments) + }, + setTime: function() { + fp.setTime.apply(this._, arguments) + } + }; + var fp = Date.prototype; + d3.time.format = function(a) { + function c(c) { + var d = [], + e = -1, + f = 0, + g, h; + while (++e < b) a.charCodeAt(e) == 37 && (d.push(a.substring(f, e), (h = fv[g = a.charAt(++e)]) ? h(c) : g), f = e + 1); + return d.push(a.substring(f, e)), d.join("") + } + var b = a.length; + return c.parse = function(b) { + var c = { + y: 1900, + m: 0, + d: 1, + H: 0, + M: 0, + S: 0, + L: 0 + }, + d = fq(c, a, b, 0); + if (d != b.length) return null; + "p" in c && (c.H = c.H % 12 + c.p * 12); + var e = new fn; + return e.setFullYear(c.y, c.m, c.d), e.setHours(c.H, c.M, c.S, c.L), e + }, c.toString = function() { + return a + }, c + }; + var fr = d3.format("02d"), + fs = d3.format("03d"), + ft = d3.format("04d"), + fu = d3.format("2d"), + fv = { + a: function(a) { + return fB[a.getDay()].substring(0, 3) + }, + A: function(a) { + return fB[a.getDay()] + }, + b: function(a) { + return fH[a.getMonth()].substring(0, 3) + }, + B: function(a) { + return fH[a.getMonth()] + }, + c: d3.time.format("%a %b %e %H:%M:%S %Y"), + d: function(a) { + return fr(a.getDate()) + }, + e: function(a) { + return fu(a.getDate()) + }, + H: function(a) { + return fr(a.getHours()) + }, + I: function(a) { + return fr(a.getHours() % 12 || 12) + }, + j: function(a) { + return fs(1 + d3.time.dayOfYear(a)) + }, + L: function(a) { + return fs(a.getMilliseconds()) + }, + m: function(a) { + return fr(a.getMonth() + 1) + }, + M: function(a) { + return fr(a.getMinutes()) + }, + p: function(a) { + return a.getHours() >= 12 ? "PM" : "AM" + }, + S: function(a) { + return fr(a.getSeconds()) + }, + U: function(a) { + return fr(d3.time.sundayOfYear(a)) + }, + w: function(a) { + return a.getDay() + }, + W: function(a) { + return fr(d3.time.mondayOfYear(a)) + }, + x: d3.time.format("%m/%d/%y"), + X: d3.time.format("%H:%M:%S"), + y: function(a) { + return fr(a.getFullYear() % 100) + }, + Y: function(a) { + return ft(a.getFullYear() % 1e4) + }, + Z: fX, + "%": function(a) { + return "%" + } + }, + fw = { + a: fx, + A: fy, + b: fC, + B: fE, + c: fI, + d: fP, + e: fP, + H: fQ, + I: fQ, + L: fT, + m: fO, + M: fR, + p: fV, + S: fS, + x: fJ, + X: fK, + y: fM, + Y: fL + }, + fz = /^(?:sun|mon|tue|wed|thu|fri|sat)/i, + fA = /^(?:Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)/i, + fB = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + fD = d3.map({ + jan: 0, + feb: 1, + mar: 2, + apr: 3, + may: 4, + jun: 5, + jul: 6, + aug: 7, + sep: 8, + oct: 9, + nov: 10, + dec: 11 + }), + fF = /^(?:January|February|March|April|May|June|July|August|September|October|November|December)/ig, + fG = d3.map({ + january: 0, + february: 1, + march: 2, + april: 3, + may: 4, + june: 5, + july: 6, + august: 7, + september: 8, + october: 9, + november: 10, + december: 11 + }), + fH = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + fU = /\s*\d+/, + fW = d3.map({ + am: 0, + pm: 1 + }); + d3.time.format.utc = function(a) { + function c(a) { + try { + fn = fo; + var c = new fn; + return c._ = a, b(c) + } finally { + fn = Date + } + } + var b = d3.time.format(a); + return c.parse = function(a) { + try { + fn = fo; + var c = b.parse(a); + return c && c._ + } finally { + fn = Date + } + }, c.toString = b.toString, c + }; + var fY = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ"); + d3.time.format.iso = Date.prototype.toISOString ? fZ : fY, fZ.parse = function(a) { + return new Date(a) + }, fZ.toString = fY.toString, d3.time.second = f$(function(a) { + return new fn(Math.floor(a / 1e3) * 1e3) + }, function(a, b) { + a.setTime(a.getTime() + Math.floor(b) * 1e3) + }, function(a) { + return a.getSeconds() + }), d3.time.seconds = d3.time.second.range, d3.time.seconds.utc = d3.time.second.utc.range, d3.time.minute = f$(function(a) { + return new fn(Math.floor(a / 6e4) * 6e4) + }, function(a, b) { + a.setTime(a.getTime() + Math.floor(b) * 6e4) + }, function(a) { + return a.getMinutes() + }), d3.time.minutes = d3.time.minute.range, d3.time.minutes.utc = d3.time.minute.utc.range, d3.time.hour = f$(function(a) { + var b = a.getTimezoneOffset() / 60; + return new fn((Math.floor(a / 36e5 - b) + b) * 36e5) + }, function(a, b) { + a.setTime(a.getTime() + Math.floor(b) * 36e5) + }, function(a) { + return a.getHours() + }), d3.time.hours = d3.time.hour.range, d3.time.hours.utc = d3.time.hour.utc.range, d3.time.day = f$(function(a) { + return new fn(a.getFullYear(), a.getMonth(), a.getDate()) + }, function(a, b) { + a.setDate(a.getDate() + b) + }, function(a) { + return a.getDate() - 1 + }), d3.time.days = d3.time.day.range, d3.time.days.utc = d3.time.day.utc.range, d3.time.dayOfYear = function(a) { + var b = d3.time.year(a); + return Math.floor((a - b) / 864e5 - (a.getTimezoneOffset() - b.getTimezoneOffset()) / 1440) + }, fB.forEach(function(a, b) { + a = a.toLowerCase(), b = 7 - b; + var c = d3.time[a] = f$(function(a) { + return (a = d3.time.day(a)).setDate(a.getDate() - (a.getDay() + b) % 7), a + }, function(a, b) { + a.setDate(a.getDate() + Math.floor(b) * 7) + }, function(a) { + var c = d3.time.year(a).getDay(); + return Math.floor((d3.time.dayOfYear(a) + (c + b) % 7) / 7) - (c !== b) + }); + d3.time[a + "s"] = c.range, d3.time[a + "s"].utc = c.utc.range, d3.time[a + "OfYear"] = function(a) { + var c = d3.time.year(a).getDay(); + return Math.floor((d3.time.dayOfYear(a) + (c + b) % 7) / 7) + } + }), d3.time.week = d3.time.sunday, d3.time.weeks = d3.time.sunday.range, d3.time.weeks.utc = d3.time.sunday.utc.range, d3.time.weekOfYear = d3.time.sundayOfYear, d3.time.month = f$(function(a) { + return new fn(a.getFullYear(), a.getMonth(), 1) + }, function(a, b) { + a.setMonth(a.getMonth() + b) + }, function(a) { + return a.getMonth() + }), d3.time.months = d3.time.month.range, d3.time.months.utc = d3.time.month.utc.range, d3.time.year = f$(function(a) { + return new fn(a.getFullYear(), 0, 1) + }, function(a, b) { + a.setFullYear(a.getFullYear() + b) + }, function(a) { + return a.getFullYear() + }), d3.time.years = d3.time.year.range, d3.time.years.utc = d3.time.year.utc.range; + var gg = [1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6], + gh = [ + [d3.time.second, 1], + [d3.time.second, 5], + [d3.time.second, 15], + [d3.time.second, 30], + [d3.time.minute, 1], + [d3.time.minute, 5], + [d3.time.minute, 15], + [d3.time.minute, 30], + [d3.time.hour, 1], + [d3.time.hour, 3], + [d3.time.hour, 6], + [d3.time.hour, 12], + [d3.time.day, 1], + [d3.time.day, 2], + [d3.time.week, 1], + [d3.time.month, 1], + [d3.time.month, 3], + [d3.time.year, 1] + ], + gi = [ + [d3.time.format("%Y"), function(a) { + return !0 + }], + [d3.time.format("%B"), function(a) { + return a.getMonth() + }], + [d3.time.format("%b %d"), function(a) { + return a.getDate() != 1 + }], + [d3.time.format("%a %d"), function(a) { + return a.getDay() && a.getDate() != 1 + }], + [d3.time.format("%I %p"), function(a) { + return a.getHours() + }], + [d3.time.format("%I:%M"), function(a) { + return a.getMinutes() + }], + [d3.time.format(":%S"), function(a) { + return a.getSeconds() + }], + [d3.time.format(".%L"), function(a) { + return a.getMilliseconds() + }] + ], + gj = d3.scale.linear(), + gk = gd(gi); + gh.year = function(a, b) { + return gj.domain(a.map(gf)).ticks(b).map(ge) + }, d3.time.scale = function() { + return ga(d3.scale.linear(), gh, gk) + }; + var gl = gh.map(function(a) { + return [a[0].utc, a[1]] + }), + gm = [ + [d3.time.format.utc("%Y"), function(a) { + return !0 + }], + [d3.time.format.utc("%B"), function(a) { + return a.getUTCMonth() + }], + [d3.time.format.utc("%b %d"), function(a) { + return a.getUTCDate() != 1 + }], + [d3.time.format.utc("%a %d"), function(a) { + return a.getUTCDay() && a.getUTCDate() != 1 + }], + [d3.time.format.utc("%I %p"), function(a) { + return a.getUTCHours() + }], + [d3.time.format.utc("%I:%M"), function(a) { + return a.getUTCMinutes() + }], + [d3.time.format.utc(":%S"), function(a) { + return a.getUTCSeconds() + }], + [d3.time.format.utc(".%L"), function(a) { + return a.getUTCMilliseconds() + }] + ], + gn = gd(gm); + gl.year = function(a, b) { + return gj.domain(a.map(gp)).ticks(b).map(go) + }, d3.time.scale.utc = function() { + return ga(d3.scale.linear(), gl, gn) + } +})(); \ No newline at end of file diff --git a/web-static/d3.v2.min.js b/web-static/d3.v2.min.js index 521c4206..88ce8ab8 100644 --- a/web-static/d3.v2.min.js +++ b/web-static/d3.v2.min.js @@ -1,4 +1,4 @@ -(function(){function e(a,b){try{for(var c in b)Object.defineProperty(a.prototype,c,{value:b[c],enumerable:!1})}catch(d){a.prototype=b}}function g(a){var b=-1,c=a.length,d=[];while(++b=0?a.substring(b):(b=a.length,""),d=[];while(b>0)d.push(a.substring(b-=3,b+3));return d.reverse().join(",")+c}function I(a,b){return{scale:Math.pow(10,(8-b)*3),symbol:a}}function O(a){return function(b){return b<=0?0:b>=1?1:a(b)}}function P(a){return function(b){return 1-a(1-b)}}function Q(a){return function(b){return.5*(b<.5?a(2*b):2-a(2-2*b))}}function R(a){return a}function S(a){return function(b){return Math.pow(b,a)}}function T(a){return 1-Math.cos(a*Math.PI/2)}function U(a){return Math.pow(2,10*(a-1))}function V(a){return 1-Math.sqrt(1-a*a)}function W(a,b){var c;return arguments.length<2&&(b=.45),arguments.length<1?(a=1,c=b/4):c=b/(2*Math.PI)*Math.asin(1/a),function(d){return 1+a*Math.pow(2,10*-d)*Math.sin((d-c)*2*Math.PI/b)}}function X(a){return a||(a=1.70158),function(b){return b*b*((a+1)*b-a)}}function Y(a){return a<1/2.75?7.5625*a*a:a<2/2.75?7.5625*(a-=1.5/2.75)*a+.75:a<2.5/2.75?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375}function Z(){d3.event.stopPropagation(),d3.event.preventDefault()}function $(){var a=d3.event,b;while(b=a.sourceEvent)a=b;return a}function _(a){var b=new A,c=0,d=arguments.length;while(++c360?a-=360:a<0&&(a+=360),a<60?d+(e-d)*a/60:a<180?e:a<240?d+(e-d)*(240-a)/60:d}function g(a){return Math.round(f(a)*255)}var d,e;return a%=360,a<0&&(a+=360),b=b<0?0:b>1?1:b,c=c<0?0:c>1?1:c,e=c<=.5?c*(1+b):c+b-c*b,d=2*c-e,be(g(a+120),g(a),g(a-120))}function bo(a){return j(a,bu),a}function bv(a){return function(){return bp(a,this)}}function bw(a){return function(){return bq(a,this)}}function by(a,b){function f(){if(b=this.classList)return b.add(a);var b=this.className,d=b.baseVal!=null,e=d?b.baseVal:b;c.lastIndex=0,c.test(e)||(e=w(e+" "+a),d?b.baseVal=e:this.className=e)}function g(){if(b=this.classList)return b.remove(a);var b=this.className,d=b.baseVal!=null,e=d?b.baseVal:b;e=w(e.replace(c," ")),d?b.baseVal=e:this.className=e}function h(){(b.apply(this,arguments)?f:g).call(this)}var c=new RegExp("(^|\\s+)"+d3.requote(a)+"(\\s+|$)","g");if(arguments.length<2){var d=this.node();if(e=d.classList)return e.contains(a);var e=d.className;return c.lastIndex=0,c.test(e.baseVal!=null?e.baseVal:e)}return this.each(typeof b=="function"?h:b?f:g)}function bz(a){return{__data__:a}}function bA(a){return function(){return bt(this,a)}}function bB(a){return arguments.length||(a=d3.ascending),function(b,c){return a(b&&b.__data__,c&&c.__data__)}}function bD(a){return j(a,bE),a}function bF(a,b,c){j(a,bJ);var d=new k,e=d3.dispatch("start","end"),f=bR;return a.id=b,a.time=c,a.tween=function(b,c){return arguments.length<2?d.get(b):(c==null?d.remove(b):d.set(b,c),a)},a.ease=function(b){return arguments.length?(f=typeof b=="function"?b:d3.ease.apply(d3,arguments),a):f},a.each=function(b,c){return arguments.length<2?bS.call(a,b):(e.on(b,c),a)},d3.timer(function(g){return a.each(function(h,i,j){function p(a){return o.active>b?r():(o.active=b,d.forEach(function(a,b){(b=b.call(l,h,i))&&k.push(b)}),e.start.call(l,h,i),q(a)||d3.timer(q,0,c),1)}function q(a){if(o.active!==b)return r();var c=(a-m)/n,d=f(c),g=k.length;while(g>0)k[--g].call(l,d);if(c>=1)return r(),bL=b,e.end.call(l,h,i),bL=0,1}function r(){return--o.count||delete l.__transition__,1}var k=[],l=this,m=a[j][i].delay,n=a[j][i].duration,o=l.__transition__||(l.__transition__={active:0,count:0});++o.count,m<=g?p(g):d3.timer(p,m,c)}),1},0,c),a}function bH(a,b,c){return c!=""&&bG}function bI(a,b){function d(a,d,e){var f=b.call(this,a,d);return f==null?e!=""&&bG:e!=f&&c(e,f)}function e(a,d,e){return e!=b&&c(e,b)}var c=bb(a);return typeof b=="function"?d:b==null?bH:(b+="",e)}function bS(a){var b=bL,c=bR,d=bP,e=bQ;bL=this.id,bR=this.ease();for(var f=0,g=this.length;f=c.delay&&(c.flush=c.callback(a)),c=c.next;var d=bX()-b;d>24?(isFinite(d)&&(clearTimeout(bV),bV=setTimeout(bW,d)),bU=0):(bU=1,bY(bW))}function bX(){var a=null,b=bT,c=Infinity;while(b)b.flush?b=a?a.next=b.next:bT=b.next:(c=Math.min(c,b.then+b.delay),b=(a=b).next);return c}function bZ(a){var b=[a.a,a.b],c=[a.c,a.d],d=b_(b),e=b$(b,c),f=b_(ca(c,b,-e))||0;b[0]*c[1]2?cq:cp,i=d?bd:bc;return e=g(a,b,i,c),f=g(b,a,i,d3.interpolate),h}function h(a){return e(a)}var e,f;return h.invert=function(a){return f(a)},h.domain=function(b){return arguments.length?(a=b.map(Number),g()):a},h.range=function(a){return arguments.length?(b=a,g()):b},h.rangeRound=function(a){return h.range(a).interpolate(d3.interpolateRound)},h.clamp=function(a){return arguments.length?(d=a,g()):d},h.interpolate=function(a){return arguments.length?(c=a,g()):c},h.ticks=function(b){return cn(a,b)},h.tickFormat=function(b){return co(a,b)},h.nice=function(){return ch(a,cl),g()},h.copy=function(){return cj(a,b,c,d)},g()}function ck(a,b){return d3.rebind(a,b,"range","rangeRound","interpolate","clamp")}function cl(a){return a=Math.pow(10,Math.round(Math.log(a)/Math.LN10)-1),{floor:function(b){return Math.floor(b/a)*a},ceil:function(b){return Math.ceil(b/a)*a}}}function cm(a,b){var c=cf(a),d=c[1]-c[0],e=Math.pow(10,Math.floor(Math.log(d/b)/Math.LN10)),f=b/d*e;return f<=.15?e*=10:f<=.35?e*=5:f<=.75&&(e*=2),c[0]=Math.ceil(c[0]/e)*e,c[1]=Math.floor(c[1]/e)*e+e*.5,c[2]=e,c}function cn(a,b){return d3.range.apply(d3,cm(a,b))}function co(a,b){return d3.format(",."+Math.max(0,-Math.floor(Math.log(cm(a,b)[2])/Math.LN10+.01))+"f")}function cp(a,b,c,d){var e=c(a[0],a[1]),f=d(b[0],b[1]);return function(a){return f(e(a))}}function cq(a,b,c,d){var e=[],f=[],g=0,h=Math.min(a.length,b.length)-1;a[h]0;j--)e.push(c(f)*j)}else{for(;fi;g--);e=e.slice(f,g)}return e},d.tickFormat=function(a,e){arguments.length<2&&(e=cs);if(arguments.length<1)return e;var f=a/d.ticks().length,g=b===cu?(h=-1e-12,Math.floor):(h=1e-12,Math.ceil),h;return function(a){return a/c(g(b(a)+h))0?0:-a)/Math.LN10}function cv(a,b){function e(b){return a(c(b))}var c=cw(b),d=cw(1/b);return e.invert=function(b){return d(a.invert(b))},e.domain=function(b){return arguments.length?(a.domain(b.map(c)),e):a.domain().map(d)},e.ticks=function(a){return cn(e.domain(),a)},e.tickFormat=function(a){return co(e.domain(),a)},e.nice=function(){return e.domain(ch(e.domain(),cl))},e.exponent=function(a){if(!arguments.length)return b;var f=e.domain();return c=cw(b=a),d=cw(1/b),e.domain(f)},e.copy=function(){return cv(a.copy(),b)},ck(e,a)}function cw(a){return function(b){return b<0?-Math.pow(-b,a):Math.pow(b,a)}}function cx(a,b){function f(b){return d[((c.get(b)||c.set(b,a.push(b)))-1)%d.length]}function g(b,c){return d3.range(a.length).map(function(a){return b+c*a})}var c,d,e;return f.domain=function(d){if(!arguments.length)return a;a=[],c=new k;var e=-1,g=d.length,h;while(++e1){h=b[1],f=a[i],i++,d+="C"+(e[0]+g[0])+","+(e[1]+g[1])+","+(f[0]-h[0])+","+(f[1]-h[1])+","+f[0]+","+f[1];for(var j=2;j9&&(f=c*3/Math.sqrt(f),g[h]=f*d,g[h+1]=f*e));h=-1;while(++h<=i)f=(a[Math.min(i,h+1)][0]-a[Math.max(0,h-1)][0])/(6*(1+g[h]*g[h])),b.push([f||0,g[h]*f||0]);return b}function di(a){return a.length<3?cQ(a):a[0]+cW(a,dh(a))}function dj(a){var b,c=-1,d=a.length,e,f;while(++c1){var d=cf(a.domain()),e,f=-1,g=b.length,h=(b[1]-b[0])/++c,i,j;while(++f0;)(j=+b[f]-i*h)>=d[0]&&e.push(j);for(--f,i=0;++id&&(c=b,d=e);return c}function ea(a){return a.reduce(eb,0)}function eb(a,b){return a+b[1]}function ec(a,b){return ed(a,Math.ceil(Math.log(b.length)/Math.LN2+1))}function ed(a,b){var c=-1,d=+a[0],e=(a[1]-d)/b,f=[];while(++c<=b)f[c]=e*c+d;return f}function ee(a){return[d3.min(a),d3.max(a)]}function ef(a,b){return d3.rebind(a,b,"sort","children","value"),a.links=ej,a.nodes=function(b){return ek=!0,(a.nodes=a)(b)},a}function eg(a){return a.children}function eh(a){return a.value}function ei(a,b){return b.value-a.value}function ej(a){return d3.merge(a.map(function(a){return(a.children||[]).map(function(b){return{source:a,target:b}})}))}function el(a,b){return a.value-b.value}function em(a,b){var c=a._pack_next;a._pack_next=b,b._pack_prev=a,b._pack_next=c,c._pack_prev=b}function en(a,b){a._pack_next=b,b._pack_prev=a}function eo(a,b){var c=b.x-a.x,d=b.y-a.y,e=a.r+b.r;return e*e-c*c-d*d>.001}function ep(a){function l(a){b=Math.min(a.x-a.r,b),c=Math.max(a.x+a.r,c),d=Math.min(a.y-a.r,d),e=Math.max(a.y+a.r,e)}var b=Infinity,c=-Infinity,d=Infinity,e=-Infinity,f=a.length,g,h,i,j,k;a.forEach(eq),g=a[0],g.x=-g.r,g.y=0,l(g);if(f>1){h=a[1],h.x=h.r,h.y=0,l(h);if(f>2){i=a[2],eu(g,h,i),l(i),em(g,i),g._pack_prev=i,em(i,h),h=g._pack_next;for(var m=3;m0&&(a=d)}return a}function eD(a,b){return a.x-b.x}function eE(a,b){return b.x-a.x}function eF(a,b){return a.depth-b.depth}function eG(a,b){function c(a,d){var e=a.children;if(e&&(i=e.length)){var f,g=null,h=-1,i;while(++h=0)f=d[e]._tree,f.prelim+=b,f.mod+=b,b+=f.shift+(c+=f.change)}function eI(a,b,c){a=a._tree,b=b._tree;var d=c/(b.number-a.number);a.change+=d,b.change-=d,b.shift+=c,b.prelim+=c,b.mod+=c}function eJ(a,b,c){return a._tree.ancestor.parent==b.parent?a._tree.ancestor:c}function eK(a){return{x:a.x,y:a.y,dx:a.dx,dy:a.dy}}function eL(a,b){var c=a.x+b[3],d=a.y+b[0],e=a.dx-b[1]-b[3],f=a.dy-b[0]-b[2];return e<0&&(c+=e/2,e=0),f<0&&(d+=f/2,f=0),{x:c,y:d,dx:e,dy:f}}function eM(a){return a.map(eN).join(",")}function eN(a){return/[",\n]/.test(a)?'"'+a.replace(/\"/g,'""')+'"':a}function eP(a,b){return function(c){return c&&a.hasOwnProperty(c.type)?a[c.type](c):b}}function eQ(a){return"m0,"+a+"a"+a+","+a+" 0 1,1 0,"+ -2*a+"a"+a+","+a+" 0 1,1 0,"+2*a+"z"}function eR(a,b){eS.hasOwnProperty(a.type)&&eS[a.type](a,b)}function eT(a,b){eR(a.geometry,b)}function eU(a,b){for(var c=a.features,d=0,e=c.length;d0}function fg(a,b,c){return(c[0]-b[0])*(a[1]-b[1])<(c[1]-b[1])*(a[0]-b[0])}function fh(a,b,c,d){var e=a[0],f=b[0],g=c[0],h=d[0],i=a[1],j=b[1],k=c[1],l=d[1],m=e-g,n=f-e,o=h-g,p=i-k,q=j-i,r=l-k,s=(o*p-r*m)/(r*n-o*q);return[e+s*n,i+s*q]}function fj(a,b){var c={list:a.map(function(a,b){return{index:b,x:a[0],y:a[1]}}).sort(function(a,b){return a.yb.y?1:a.xb.x?1:0}),bottomSite:null},d={list:[],leftEnd:null,rightEnd:null,init:function(){d.leftEnd=d.createHalfEdge(null,"l"),d.rightEnd=d.createHalfEdge(null,"l"),d.leftEnd.r=d.rightEnd,d.rightEnd.l=d.leftEnd,d.list.unshift(d.leftEnd,d.rightEnd)},createHalfEdge:function(a,b){return{edge:a,side:b,vertex:null,l:null,r:null}},insert:function(a,b){b.l=a,b.r=a.r,a.r.l=b,a.r=b},leftBound:function(a){var b=d.leftEnd;do b=b.r;while(b!=d.rightEnd&&e.rightOf(b,a));return b=b.l,b},del:function(a){a.l.r=a.r,a.r.l=a.l,a.edge=null},right:function(a){return a.r},left:function(a){return a.l},leftRegion:function(a){return a.edge==null?c.bottomSite:a.edge.region[a.side]},rightRegion:function(a){return a.edge==null?c.bottomSite:a.edge.region[fi[a.side]]}},e={bisect:function(a,b){var c={region:{l:a,r:b},ep:{l:null,r:null}},d=b.x-a.x,e=b.y-a.y,f=d>0?d:-d,g=e>0?e:-e;return c.c=a.x*d+a.y*e+(d*d+e*e)*.5,f>g?(c.a=1,c.b=e/d,c.c/=d):(c.b=1,c.a=d/e,c.c/=e),c},intersect:function(a,b){var c=a.edge,d=b.edge;if(!c||!d||c.region.r==d.region.r)return null;var e=c.a*d.b-c.b*d.a;if(Math.abs(e)<1e-10)return null;var f=(c.c*d.b-d.c*c.b)/e,g=(d.c*c.a-c.c*d.a)/e,h=c.region.r,i=d.region.r,j,k;h.y=k.region.r.x;return l&&j.side==="l"||!l&&j.side==="r"?null:{x:f,y:g}},rightOf:function(a,b){var c=a.edge,d=c.region.r,e=b.x>d.x;if(e&&a.side==="l")return 1;if(!e&&a.side==="r")return 0;if(c.a===1){var f=b.y-d.y,g=b.x-d.x,h=0,i=0;!e&&c.b<0||e&&c.b>=0?i=h=f>=c.b*g:(i=b.x+b.y*c.b>c.c,c.b<0&&(i=!i),i||(h=1));if(!h){var j=d.x-c.region.l.x;i=c.b*(g*g-f*f)m*m+n*n}return a.side==="l"?i:!i},endPoint:function(a,c,d){a.ep[c]=d;if(!a.ep[fi[c]])return;b(a)},distance:function(a,b){var c=a.x-b.x,d=a.y-b.y;return Math.sqrt(c*c+d*d)}},f={list:[],insert:function(a,b,c){a.vertex=b,a.ystar=b.y+c;for(var d=0,e=f.list,g=e.length;dh.ystar||a.ystar==h.ystar&&b.x>h.vertex.x)continue;break}e.splice(d,0,a)},del:function(a){for(var b=0,c=f.list,d=c.length;bo.y&&(p=n,n=o,o=p,t="r"),s=e.bisect(n,o),m=d.createHalfEdge(s,t),d.insert(k,m),e.endPoint(s,fi[t],r),q=e.intersect(k,m),q&&(f.del(k),f.insert(k,q,e.distance(q,n))),q=e.intersect(m,l),q&&f.insert(m,q,e.distance(q,n));else break}for(i=d.right(d.leftEnd);i!=d.rightEnd;i=d.right(i))b(i.edge)}function fk(){return{leaf:!0,nodes:[],point:null}}function fl(a,b,c,d,e,f){if(!a(b,c,d,e,f)){var g=(c+e)*.5,h=(d+f)*.5,i=b.nodes;i[0]&&fl(a,i[0],c,d,g,h),i[1]&&fl(a,i[1],g,d,e,h),i[2]&&fl(a,i[2],c,h,g,f),i[3]&&fl(a,i[3],g,h,e,f)}}function fm(a){return{x:a[0],y:a[1]}}function fo(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function fq(a,b,c,d){var e,f,g=0,h=b.length,i=c.length;while(g=i)return-1;e=b.charCodeAt(g++);if(e==37){f=fw[b.charAt(g++)];if(!f||(d=f(a,c,d))<0)return-1}else if(e!=c.charCodeAt(d++))return-1}return d}function fx(a,b,c){return fz.test(b.substring(c,c+=3))?c:-1}function fy(a,b,c){fA.lastIndex=0;var d=fA.exec(b.substring(c,c+10));return d?c+=d[0].length:-1}function fC(a,b,c){var d=fD.get(b.substring(c,c+=3).toLowerCase());return d==null?-1:(a.m=d,c)}function fE(a,b,c){fF.lastIndex=0;var d=fF.exec(b.substring(c,c+12));return d?(a.m=fG.get(d[0].toLowerCase()),c+=d[0].length):-1}function fI(a,b,c){return fq(a,fv.c.toString(),b,c)}function fJ(a,b,c){return fq(a,fv.x.toString(),b,c)}function fK(a,b,c){return fq(a,fv.X.toString(),b,c)}function fL(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+4));return d?(a.y=+d[0],c+=d[0].length):-1}function fM(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.y=fN()+ +d[0],c+=d[0].length):-1}function fN(){return~~((new Date).getFullYear()/1e3)*1e3}function fO(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.m=d[0]-1,c+=d[0].length):-1}function fP(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.d=+d[0],c+=d[0].length):-1}function fQ(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.H=+d[0],c+=d[0].length):-1}function fR(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.M=+d[0],c+=d[0].length):-1}function fS(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.S=+d[0],c+=d[0].length):-1}function fT(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+3));return d?(a.L=+d[0],c+=d[0].length):-1}function fV(a,b,c){var d=fW.get(b.substring(c,c+=2).toLowerCase());return d==null?-1:(a.p=d,c)}function fX(a){var b=a.getTimezoneOffset(),c=b>0?"-":"+",d=~~(Math.abs(b)/60),e=Math.abs(b)%60;return c+fr(d)+fr(e)}function fZ(a){return a.toISOString()}function f$(a,b,c){function d(b){var c=a(b),d=f(c,1);return b-c1)while(gb?1:a>=b?0:NaN},d3.descending=function(a,b){return ba?1:b>=a?0:NaN},d3.mean=function(a,b){var c=a.length,d,e=0,f=-1,g=0;if(arguments.length===1)while(++f1&&(a=a.map(b)),a=a.filter(s),a.length?d3.quantile(a.sort(d3.ascending),.5):undefined},d3.min=function(a,b){var c=-1,d=a.length,e,f;if(arguments.length===1){while(++cf&&(e=f)}else{while(++cf&&(e=f)}return e},d3.max=function(a,b){var c=-1,d=a.length,e,f;if(arguments.length===1){while(++ce&&(e=f)}else{while(++ce&&(e=f)}return e},d3.extent=function(a,b){var c=-1,d=a.length,e,f,g;if(arguments.length===1){while(++cf&&(e=f),gf&&(e=f),g1);return a+b*c*Math.sqrt(-2*Math.log(e)/e)}}},d3.sum=function(a,b){var c=0,d=a.length,e,f=-1;if(arguments.length===1)while(++f>1;a.call(b,b[f],f)>1;c0&&(e=f);return e},d3.last=function(a,b){var c=0,d=a.length,e=a[0],f;arguments.length===1&&(b=d3.ascending);while(++c=b.length)return e?e.call(a,c):d?c.sort(d):c;var h=-1,i=c.length,j=b[g++],l,m,n=new k,o,p={};while(++h=b.length)return a;var e=[],f=c[d++],h;for(h in a)e.push({key:h,values:g(a[h],d)});return f&&e.sort(function(a,b){return f(a.key,b.key)}),e}var a={},b=[],c=[],d,e;return a.map=function(a){return f(a,0)},a.entries=function(a){return g(f(a,0),0)},a.key=function(c){return b.push(c),a},a.sortKeys=function(d){return c[b.length-1]=d,a},a.sortValues=function(b){return d=b,a},a.rollup=function(b){return e=b,a},a},d3.keys=function(a){var b=[];for(var c in a)b.push(c);return b},d3.values=function(a){var b=[];for(var c in a)b.push(a[c]);return b},d3.entries=function(a){var b=[];for(var c in a)b.push({key:c,value:a[c]});return b},d3.permute=function(a,b){var c=[],d=-1,e=b.length;while(++db)d.push(g/e);else while((g=a+c*++f)=200&&a<300||a===304?d:null)}},d.send(null)},d3.text=function(a,b,c){function d(a){c(a&&a.responseText)}arguments.length<3&&(c=b,b=null),d3.xhr(a,b,d)},d3.json=function(a,b){d3.text(a,"application/json",function(a){b(a?JSON.parse(a):null)})},d3.html=function(a,b){d3.text(a,"text/html",function(a){if(a!=null){var c=document.createRange();c.selectNode(document.body),a=c.createContextualFragment(a)}b(a)})},d3.xml=function(a,b,c){function d(a){c(a&&a.responseXML)}arguments.length<3&&(c=b,b=null),d3.xhr(a,b,d)};var z={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};d3.ns={prefix:z,qualify:function(a){var b=a.indexOf(":"),c=a;return b>=0&&(c=a.substring(0,b),a=a.substring(b+1)),z.hasOwnProperty(c)?{space:z[c],local:a}:a}},d3.dispatch=function(){var a=new A,b=-1,c=arguments.length;while(++b0&&(d=a.substring(c+1),a=a.substring(0,c)),arguments.length<2?this[a].on(d):this[a].on(d,b)},d3.format=function(a){var b=C.exec(a),c=b[1]||" ",d=b[3]||"",e=b[5],f=+b[6],g=b[7],h=b[8],i=b[9],j=1,k="",l=!1;h&&(h=+h.substring(1)),e&&(c="0",g&&(f-=Math.floor((f-1)/4)));switch(i){case"n":g=!0,i="g";break;case"%":j=100,k="%",i="f";break;case"p":j=100,k="%",i="r";break;case"d":l=!0,h=0;break;case"s":j=-1,i="r"}return i=="r"&&!h&&(i="g"),i=D.get(i)||F,function(a){if(l&&a%1)return"";var b=a<0&&(a=-a)?"−":d;if(j<0){var m=d3.formatPrefix(a,h);a*=m.scale,k=m.symbol}else a*=j;a=i(a,h);if(e){var n=a.length+b.length;n=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/,D=d3.map({g:function(a,b){return a.toPrecision(b)},e:function(a,b){return a.toExponential(b)},f:function(a,b){return a.toFixed(b)},r:function(a,b){return d3.round(a,b=E(a,b)).toFixed(Math.max(0,Math.min(20,b)))}}),H=["y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y"].map(I);d3.formatPrefix=function(a,b){var c=0;return a&&(a<0&&(a*=-1),b&&(a=d3.round(a,E(a,b))),c=1+Math.floor(1e-12+Math.log(a)/Math.LN10),c=Math.max(-24,Math.min(24,Math.floor((c<=0?c+1:c-1)/3)*3))),H[8+c/3]};var J=S(2),K=S(3),L=function(){return R},M=d3.map({linear:L,poly:S,quad:function(){return J},cubic:function(){return K},sin:function(){return T},exp:function(){return U},circle:function(){return V},elastic:W,back:X,bounce:function(){return Y}}),N=d3.map({"in":R,out:P,"in-out":Q,"out-in":function(a){return Q(P(a))}});d3.ease=function(a){var b=a.indexOf("-"),c=b>=0?a.substring(0,b):a,d=b>=0?a.substring(b+1):"in";return c=M.get(c)||L,d=N.get(d)||R,O(d(c.apply(null,Array.prototype.slice.call(arguments,1))))},d3.event=null,d3.interpolate=function(a,b){var c=d3.interpolators.length,d;while(--c>=0&&!(d=d3.interpolators[c](a,b)));return d},d3.interpolateNumber=function(a,b){return b-=a,function(c){return a+b*c}},d3.interpolateRound=function(a,b){return b-=a,function(c){return Math.round(a+b*c)}},d3.interpolateString=function(a,b){var c,d,e,f=0,g=0,h=[],i=[],j,k;ba.lastIndex=0;for(d=0;c=ba.exec(b);++d)c.index&&h.push(b.substring(f,g=c.index)),i.push({i:h.length,x:c[0]}),h.push(null),f=ba.lastIndex;f1){while(++e=0;)if(f=c[d])e&&e!==f.nextSibling&&e.parentNode.insertBefore(f,e),e=f;return this},bu.sort=function(a){a=bB.apply(this,arguments);for(var b=-1,c=this.length;++b0&&(a=a.substring(0,e)),arguments.length<2?(e=this.node()[d])&&e._:this.each(function(e,f){function i(a){var c=d3.event;d3.event=a;try{b.call(g,g.__data__,f)}finally{d3.event=c}}var g=this,h=g[d];h&&(g.removeEventListener(a,h,h.$),delete g[d]),b&&(g.addEventListener(a,g[d]=i,i.$=c),i._=b)})},bu.each=function(a){for(var b=-1,c=this.length;++b=cG?e?"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"M0,"+e+"A"+e+","+e+" 0 1,0 0,"+ -e+"A"+e+","+e+" 0 1,0 0,"+e+"Z":"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"Z":e?"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L"+e*m+","+e*n+"A"+e+","+e+" 0 "+j+",0 "+e*k+","+e*l+"Z":"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L0,0"+"Z"}var a=cH,b=cI,c=cJ,d=cK;return e.innerRadius=function(b){return arguments.length?(a=q(b),e):a},e.outerRadius=function(a){return arguments.length?(b=q(a),e):b},e.startAngle=function(a){return arguments.length?(c=q(a),e):c},e.endAngle=function(a){return arguments.length?(d=q(a),e):d},e.centroid=function(){var e=(a.apply(this,arguments)+b.apply(this,arguments))/2,f=(c.apply(this,arguments)+d.apply(this,arguments))/2+cF;return[Math.cos(f)*e,Math.sin(f)*e]},e};var cF=-Math.PI/2,cG=2*Math.PI-1e-6;d3.svg.line=function(){return cL(n)};var cO="linear",cP=d3.map({linear:cQ,"step-before":cR,"step-after":cS,basis:cY,"basis-open":cZ,"basis-closed":c$,bundle:c_,cardinal:cV,"cardinal-open":cT,"cardinal-closed":cU,monotone:di}),db=[0,2/3,1/3,0],dc=[0,1/3,2/3,0],dd=[0,1/6,2/3,1/6];d3.svg.line.radial=function(){var a=cL(dj);return a.radius=a.x,delete a.x,a.angle=a.y,delete a.y,a},cR.reverse=cS,cS.reverse=cR,d3.svg.area=function(){return dk(Object)},d3.svg.area.radial=function(){var a=dk(dj);return a.radius=a.x,delete a.x,a.innerRadius=a.x0,delete a.x0,a.outerRadius=a.x1,delete a.x1,a.angle=a.y,delete a.y,a.startAngle=a.y0,delete a.y0,a.endAngle=a.y1,delete a.y1,a},d3.svg.chord=function(){function f(c,d){var e=g(this,a,c,d),f=g(this,b,c,d);return"M"+e.p0+i(e.r,e.p1,e.a1-e.a0)+(h(e,f)?j(e.r,e.p1,e.r,e.p0):j(e.r,e.p1,f.r,f.p0)+i(f.r,f.p1,f.a1-f.a0)+j(f.r,f.p1,e.r,e.p0))+"Z"}function g(a,b,f,g){var h=b.call(a,f,g),i=c.call(a,h,g),j=d.call(a,h,g)+cF,k=e.call(a,h,g)+cF;return{r:i,a0:j,a1:k,p0:[i*Math.cos(j),i*Math.sin(j)],p1:[i*Math.cos(k),i*Math.sin(k)]}}function h(a,b){return a.a0==b.a0&&a.a1==b.a1}function i(a,b,c){return"A"+a+","+a+" 0 "+ +(c>Math.PI)+",1 "+b}function j(a,b,c,d){return"Q 0,0 "+d}var a=dl,b=dm,c=dn,d=cJ,e=cK;return f.radius=function(a){return arguments.length?(c=q(a),f):c},f.source=function(b){return arguments.length?(a=q(b),f):a},f.target=function(a){return arguments.length?(b=q(a),f):b},f.startAngle=function(a){return arguments.length?(d=q(a),f):d},f.endAngle=function(a){return arguments.length?(e=q(a),f):e},f},d3.svg.diagonal=function(){function d(d,e){var f=a.call(this,d,e),g=b.call(this,d,e),h=(f.y+g.y)/2,i=[f,{x:f.x,y:h},{x:g.x,y:h},g];return i=i.map(c),"M"+i[0]+"C"+i[1]+" "+i[2]+" "+i[3]}var a=dl,b=dm,c=dr;return d.source=function(b){return arguments.length?(a=q(b),d):a},d.target=function(a){return arguments.length?(b=q(a),d):b},d.projection=function(a){return arguments.length?(c=a,d):c},d},d3.svg.diagonal.radial=function(){var a=d3.svg.diagonal(),b=dr,c=a.projection;return a.projection=function(a){return arguments.length?c(ds(b=a)):b},a},d3.svg.mouse=d3.mouse,d3.svg.touches=d3.touches,d3.svg.symbol=function(){function c(c,d){return(dw.get(a.call(this,c,d))||dv)(b.call(this,c,d))}var a=du,b=dt;return c -.type=function(b){return arguments.length?(a=q(b),c):a},c.size=function(a){return arguments.length?(b=q(a),c):b},c};var dw=d3.map({circle:dv,cross:function(a){var b=Math.sqrt(a/5)/2;return"M"+ -3*b+","+ -b+"H"+ -b+"V"+ -3*b+"H"+b+"V"+ -b+"H"+3*b+"V"+b+"H"+b+"V"+3*b+"H"+ -b+"V"+b+"H"+ -3*b+"Z"},diamond:function(a){var b=Math.sqrt(a/(2*dy)),c=b*dy;return"M0,"+ -b+"L"+c+",0"+" 0,"+b+" "+ -c+",0"+"Z"},square:function(a){var b=Math.sqrt(a)/2;return"M"+ -b+","+ -b+"L"+b+","+ -b+" "+b+","+b+" "+ -b+","+b+"Z"},"triangle-down":function(a){var b=Math.sqrt(a/dx),c=b*dx/2;return"M0,"+c+"L"+b+","+ -c+" "+ -b+","+ -c+"Z"},"triangle-up":function(a){var b=Math.sqrt(a/dx),c=b*dx/2;return"M0,"+ -c+"L"+b+","+c+" "+ -b+","+c+"Z"}});d3.svg.symbolTypes=dw.keys();var dx=Math.sqrt(3),dy=Math.tan(30*Math.PI/180);d3.svg.axis=function(){function k(k){k.each(function(){var k=d3.select(this),l=h==null?a.ticks?a.ticks.apply(a,g):a.domain():h,m=i==null?a.tickFormat?a.tickFormat.apply(a,g):String:i,n=dB(a,l,j),o=k.selectAll(".minor").data(n,String),p=o.enter().insert("line","g").attr("class","tick minor").style("opacity",1e-6),q=d3.transition(o.exit()).style("opacity",1e-6).remove(),r=d3.transition(o).style("opacity",1),s=k.selectAll("g").data(l,String),t=s.enter().insert("g","path").style("opacity",1e-6),u=d3.transition(s.exit()).style("opacity",1e-6).remove(),v=d3.transition(s).style("opacity",1),w,x=cg(a),y=k.selectAll(".domain").data([0]),z=y.enter().append("path").attr("class","domain"),A=d3.transition(y),B=a.copy(),C=this.__chart__||B;this.__chart__=B,t.append("line").attr("class","tick"),t.append("text"),v.select("text").text(m);switch(b){case"bottom":w=dz,p.attr("y2",d),r.attr("x2",0).attr("y2",d),t.select("line").attr("y2",c),t.select("text").attr("y",Math.max(c,0)+f),v.select("line").attr("x2",0).attr("y2",c),v.select("text").attr("x",0).attr("y",Math.max(c,0)+f).attr("dy",".71em").attr("text-anchor","middle"),A.attr("d","M"+x[0]+","+e+"V0H"+x[1]+"V"+e);break;case"top":w=dz,p.attr("y2",-d),r.attr("x2",0).attr("y2",-d),t.select("line").attr("y2",-c),t.select("text").attr("y",-(Math.max(c,0)+f)),v.select("line").attr("x2",0).attr("y2",-c),v.select("text").attr("x",0).attr("y",-(Math.max(c,0)+f)).attr("dy","0em").attr("text-anchor","middle"),A.attr("d","M"+x[0]+","+ -e+"V0H"+x[1]+"V"+ -e);break;case"left":w=dA,p.attr("x2",-d),r.attr("x2",-d).attr("y2",0),t.select("line").attr("x2",-c),t.select("text").attr("x",-(Math.max(c,0)+f)),v.select("line").attr("x2",-c).attr("y2",0),v.select("text").attr("x",-(Math.max(c,0)+f)).attr("y",0).attr("dy",".32em").attr("text-anchor","end"),A.attr("d","M"+ -e+","+x[0]+"H0V"+x[1]+"H"+ -e);break;case"right":w=dA,p.attr("x2",d),r.attr("x2",d).attr("y2",0),t.select("line").attr("x2",c),t.select("text").attr("x",Math.max(c,0)+f),v.select("line").attr("x2",c).attr("y2",0),v.select("text").attr("x",Math.max(c,0)+f).attr("y",0).attr("dy",".32em").attr("text-anchor","start"),A.attr("d","M"+e+","+x[0]+"H0V"+x[1]+"H"+e)}if(a.ticks)t.call(w,C),v.call(w,B),u.call(w,B),p.call(w,C),r.call(w,B),q.call(w,B);else{var D=B.rangeBand()/2,E=function(a){return B(a)+D};t.call(w,E),v.call(w,E)}})}var a=d3.scale.linear(),b="bottom",c=6,d=6,e=6,f=3,g=[10],h=null,i,j=0;return k.scale=function(b){return arguments.length?(a=b,k):a},k.orient=function(a){return arguments.length?(b=a,k):b},k.ticks=function(){return arguments.length?(g=arguments,k):g},k.tickValues=function(a){return arguments.length?(h=a,k):h},k.tickFormat=function(a){return arguments.length?(i=a,k):i},k.tickSize=function(a,b,f){if(!arguments.length)return c;var g=arguments.length-1;return c=+a,d=g>1?+b:c,e=g>0?+arguments[g]:c,k},k.tickPadding=function(a){return arguments.length?(f=+a,k):f},k.tickSubdivide=function(a){return arguments.length?(j=+a,k):j},k},d3.svg.brush=function(){function g(a){a.each(function(){var a=d3.select(this),e=a.selectAll(".background").data([0]),f=a.selectAll(".extent").data([0]),l=a.selectAll(".resize").data(d,String),m;a.style("pointer-events","all").on("mousedown.brush",k).on("touchstart.brush",k),e.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),f.enter().append("rect").attr("class","extent").style("cursor","move"),l.enter().append("g").attr("class",function(a){return"resize "+a}).style("cursor",function(a){return dC[a]}).append("rect").attr("x",function(a){return/[ew]$/.test(a)?-3:null}).attr("y",function(a){return/^[ns]/.test(a)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),l.style("display",g.empty()?"none":null),l.exit().remove(),b&&(m=cg(b),e.attr("x",m[0]).attr("width",m[1]-m[0]),i(a)),c&&(m=cg(c),e.attr("y",m[0]).attr("height",m[1]-m[0]),j(a)),h(a)})}function h(a){a.selectAll(".resize").attr("transform",function(a){return"translate("+e[+/e$/.test(a)][0]+","+e[+/^s/.test(a)][1]+")"})}function i(a){a.select(".extent").attr("x",e[0][0]),a.selectAll(".extent,.n>rect,.s>rect").attr("width",e[1][0]-e[0][0])}function j(a){a.select(".extent").attr("y",e[0][1]),a.selectAll(".extent,.e>rect,.w>rect").attr("height",e[1][1]-e[0][1])}function k(){function x(){var a=d3.event.changedTouches;return a?d3.touches(d,a)[0]:d3.mouse(d)}function y(){d3.event.keyCode==32&&(q||(r=null,s[0]-=e[1][0],s[1]-=e[1][1],q=2),Z())}function z(){d3.event.keyCode==32&&q==2&&(s[0]+=e[1][0],s[1]+=e[1][1],q=0,Z())}function A(){var a=x(),d=!1;t&&(a[0]+=t[0],a[1]+=t[1]),q||(d3.event.altKey?(r||(r=[(e[0][0]+e[1][0])/2,(e[0][1]+e[1][1])/2]),s[0]=e[+(a[0]0?e=c:e=0:c>0&&(b.start({type:"start",alpha:e=c}),d3.timer(a.tick)),a):e},a.start=function(){function q(a,c){var d=t(b),e=-1,f=d.length,g;while(++ee&&(e=h),d.push(h)}for(g=0;g0){f=-1;while(++f=i[0]&&o<=i[1]&&(k=g[d3.bisect(j,o,1,m)-1],k.y+=n,k.push(e[f]))}return g}var a=!0,b=Number,c=ee,d=ec;return e.value=function(a){return arguments.length?(b=a,e):b},e.range=function(a){return arguments.length?(c=q(a),e):c},e.bins=function(a){return arguments.length?(d=typeof a=="number"?function(b){return ed(b,a)}:q(a),e):d},e.frequency=function(b){return arguments.length?(a=!!b,e):a},e},d3.layout.hierarchy=function(){function e(f,h,i){var j=b.call(g,f,h),k=ek?f:{data:f};k.depth=h,i.push(k);if(j&&(m=j.length)){var l=-1,m,n=k.children=[],o=0,p=h+1;while(++l0&&(eI(eJ(g,a,d),a,m),i+=m,j+=m),k+=g._tree.mod,i+=e._tree.mod,l+=h._tree.mod,j+=f._tree.mod;g&&!eB(f)&&(f._tree.thread=g,f._tree.mod+=k-j),e&&!eA(h)&&(h._tree.thread=e,h._tree.mod+=i-l,d=a)}return d}var f=a.call(this,d,e),g=f[0];eG(g,function(a,b){a._tree={ancestor:a,prelim:0,mod:0,change:0,shift:0,number:b?b._tree.number+1:0}}),h(g),i(g,-g._tree.prelim);var k=eC(g,eE),l=eC(g,eD),m=eC(g,eF),n=k.x-b(k,l)/2,o=l.x+b(l,k)/2,p=m.depth||1;return eG(g,function(a){a.x=(a.x-n)/(o-n)*c[0],a.y=a.depth/p*c[1],delete a._tree}),f}var a=d3.layout.hierarchy().sort(null).value(null),b=ez,c=[1,1];return d.separation=function(a){return arguments.length?(b=a,d):b},d.size=function(a){return arguments.length?(c=a,d):c},ef(d,a)},d3.layout.treemap=function(){function i(a,b){var c=-1,d=a.length,e,f;while(++c0)d.push(g=f[o-1]),d.area+=g.area,(k=l(d,n))<=h?(f.pop(),h=k):(d.area-=d.pop().area,m(d,n,c,!1),n=Math.min(c.dx,c.dy),d.length=d.area=0,h=Infinity);d.length&&(m(d,n,c,!0),d.length=d.area=0),b.forEach(j)}}function k(a){var b=a.children;if(b&&b.length){var c=e(a),d=b.slice(),f,g=[];i(d,c.dx*c.dy/a.value),g.area=0;while(f=d.pop())g.push(f),g.area+=f.area,f.z!=null&&(m(g,f.z?c.dx:c.dy,c,!d.length),g.length=g.area=0);b.forEach(k)}}function l(a,b){var c=a.area,d,e=0,f=Infinity,g=-1,i=a.length;while(++ge&&(e=d)}return c*=c,b*=b,c?Math.max(b*e*h/c,c/(b*f*h)):Infinity}function m(a,c,d,e){var f=-1,g=a.length,h=d.x,i=d.y,j=c?b(a.area/c):0,k;if(c==d.dx){if(e||j>d.dy)j=d.dy;while(++fd.dx)j=d.dx;while(++f=a.length)return d;if(i)return i=!1,c;var b=f.lastIndex;if(a.charCodeAt(b)===34){var e=b;while(e++50?b:f<-140?c:g<21?d:a)(e)}var a=d3.geo.albers(),b=d3.geo.albers().origin([-160,60]).parallels([55,65]),c=d3.geo.albers().origin([-160,20]).parallels([8,18]),d=d3.geo.albers().origin([-60,10]).parallels([8,18]);return e.scale=function(f){return arguments.length?(a.scale(f),b.scale(f*.6),c.scale(f),d.scale(f*1.5),e.translate(a.translate())):a.scale()},e.translate=function(f){if(!arguments.length)return a.translate();var g=a.scale()/1e3,h=f[0],i=f[1];return a.translate(f),b.translate([h-400*g,i+170*g]),c.translate([h-190*g,i+200*g]),d.translate([h+580*g,i+430*g]),e},e.scale(a.scale())},d3.geo.bonne=function(){function g(g){var h=g[0]*eO-c,i=g[1]*eO-d;if(e){var j=f+e-i,k=h*Math.cos(i)/j;h=j*Math.sin(k),i=j*Math.cos(k)-f}else h*=Math.cos(i),i*=-1;return[a*h+b[0],a*i+b[1]]}var a=200,b=[480,250],c,d,e,f;return g.invert=function(d){var g=(d[0]-b[0])/a,h=(d[1]-b[1])/a;if(e){var i=f+h,j=Math.sqrt(g*g+i*i);h=f+e-j,g=c+j*Math.atan2(g,i)/Math.cos(h)}else h*=-1,g/=Math.cos(h);return[g/eO,h/eO]},g.parallel=function(a){return arguments.length?(f=1/Math.tan(e=a*eO),g):e/eO},g.origin=function(a){return arguments.length?(c=a[0]*eO,d=a[1]*eO,g):[c/eO,d/eO]},g.scale=function(b){return arguments.length?(a=+b,g):a},g.translate=function(a){return arguments.length?(b=[+a[0],+a[1]],g):b},g.origin([0,0]).parallel(45)},d3.geo.equirectangular=function(){function c(c){var d=c[0]/360,e=-c[1]/360;return[a*d+b[0],a*e+b[1]]}var a=500,b=[480,250];return c.invert=function(c){var d=(c[0]-b[0])/a,e=(c[1]-b[1])/a;return[360*d,-360*e]},c.scale=function(b){return arguments.length?(a=+b,c):a},c.translate=function(a){return arguments.length?(b=[+a[0],+a[1]],c):b},c},d3.geo.mercator=function(){function c(c){var d=c[0]/360,e=-(Math.log(Math.tan(Math.PI/4+c[1]*eO/2))/eO)/360;return[a*d+b[0],a*Math.max(-0.5,Math.min(.5,e))+b[1]]}var a=500,b=[480,250];return c.invert=function(c){var d=(c[0]-b[0])/a,e=(c[1]-b[1])/a;return[360*d,2*Math.atan(Math.exp(-360*e*eO))/eO-90]},c.scale=function(b){return arguments.length?(a=+b,c):a},c.translate=function(a){return arguments.length?(b=[+a[0],+a[1]],c):b},c},d3.geo.path=function(){function d(c,d){return typeof a=="function"&&(b=eQ(a.apply(this,arguments))),f(c)||null}function e(a){return c(a).join(",")}function h(a){var b=k(a[0]),c=0,d=a.length;while(++c0){b.push("M");while(++h0){b.push("M");while(++kd&&(d=a),fe&&(e=f)}),[[b,c],[d,e]]};var eS={Feature:eT,FeatureCollection:eU,GeometryCollection:eV,LineString:eW,MultiLineString:eX,MultiPoint:eW,MultiPolygon:eY,Point:eZ,Polygon:e$};d3.geo.circle=function(){function e(){}function f(a){return d.distance(a)=0?a.substring(b):(b=a.length,""),d=[];while(b>0)d.push(a.substring(b-=3,b+3));return d.reverse().join(",")+c}function I(a,b){return{scale:Math.pow(10,(8-b)*3),symbol:a}}function O(a){return function(b){return b<=0?0:b>=1?1:a(b)}}function P(a){return function(b){return 1-a(1-b)}}function Q(a){return function(b){return.5*(b<.5?a(2*b):2-a(2-2*b))}}function R(a){return a}function S(a){return function(b){return Math.pow(b,a)}}function T(a){return 1-Math.cos(a*Math.PI/2)}function U(a){return Math.pow(2,10*(a-1))}function V(a){return 1-Math.sqrt(1-a*a)}function W(a,b){var c;return arguments.length<2&&(b=.45),arguments.length<1?(a=1,c=b/4):c=b/(2*Math.PI)*Math.asin(1/a),function(d){return 1+a*Math.pow(2,10*-d)*Math.sin((d-c)*2*Math.PI/b)}}function X(a){return a||(a=1.70158),function(b){return b*b*((a+1)*b-a)}}function Y(a){return a<1/2.75?7.5625*a*a:a<2/2.75?7.5625*(a-=1.5/2.75)*a+.75:a<2.5/2.75?7.5625*(a-=2.25/2.75)*a+.9375:7.5625*(a-=2.625/2.75)*a+.984375}function Z(){d3.event.stopPropagation(),d3.event.preventDefault()}function $(){var a=d3.event,b;while(b=a.sourceEvent)a=b;return a}function _(a){var b=new A,c=0,d=arguments.length;while(++c360?a-=360:a<0&&(a+=360),a<60?d+(e-d)*a/60:a<180?e:a<240?d+(e-d)*(240-a)/60:d}function g(a){return Math.round(f(a)*255)}var d,e;return a%=360,a<0&&(a+=360),b=b<0?0:b>1?1:b,c=c<0?0:c>1?1:c,e=c<=.5?c*(1+b):c+b-c*b,d=2*c-e,be(g(a+120),g(a),g(a-120))}function bo(a){return j(a,bu),a}function bv(a){return function(){return bp(a,this)}}function bw(a){return function(){return bq(a,this)}}function by(a,b){function f(){if(b=this.classList)return b.add(a);var b=this.className,d=b.baseVal!=null,e=d?b.baseVal:b;c.lastIndex=0,c.test(e)||(e=w(e+" "+a),d?b.baseVal=e:this.className=e)}function g(){if(b=this.classList)return b.remove(a);var b=this.className,d=b.baseVal!=null,e=d?b.baseVal:b;e=w(e.replace(c," ")),d?b.baseVal=e:this.className=e}function h(){(b.apply(this,arguments)?f:g).call(this)}var c=new RegExp("(^|\\s+)"+d3.requote(a)+"(\\s+|$)","g");if(arguments.length<2){var d=this.node();if(e=d.classList)return e.contains(a);var e=d.className;return c.lastIndex=0,c.test(e.baseVal!=null?e.baseVal:e)}return this.each(typeof b=="function"?h:b?f:g)}function bz(a){return{__data__:a}}function bA(a){return function(){return bt(this,a)}}function bB(a){return arguments.length||(a=d3.ascending),function(b,c){return a(b&&b.__data__,c&&c.__data__)}}function bD(a){return j(a,bE),a}function bF(a,b,c){j(a,bJ);var d=new k,e=d3.dispatch("start","end"),f=bR;return a.id=b,a.time=c,a.tween=function(b,c){return arguments.length<2?d.get(b):(c==null?d.remove(b):d.set(b,c),a)},a.ease=function(b){return arguments.length?(f=typeof b=="function"?b:d3.ease.apply(d3,arguments),a):f},a.each=function(b,c){return arguments.length<2?bS.call(a,b):(e.on(b,c),a)},d3.timer(function(g){return a.each(function(h,i,j){function p(a){return o.active>b?r():(o.active=b,d.forEach(function(a,b){(b=b.call(l,h,i))&&k.push(b)}),e.start.call(l,h,i),q(a)||d3.timer(q,0,c),1)}function q(a){if(o.active!==b)return r();var c=(a-m)/n,d=f(c),g=k.length;while(g>0)k[--g].call(l,d);if(c>=1)return r(),bL=b,e.end.call(l,h,i),bL=0,1}function r(){return--o.count||delete l.__transition__,1}var k=[],l=this,m=a[j][i].delay,n=a[j][i].duration,o=l.__transition__||(l.__transition__={active:0,count:0});++o.count,m<=g?p(g):d3.timer(p,m,c)}),1},0,c),a}function bH(a,b,c){return c!=""&&bG}function bI(a,b){function d(a,d,e){var f=b.call(this,a,d);return f==null?e!=""&&bG:e!=f&&c(e,f)}function e(a,d,e){return e!=b&&c(e,b)}var c=bb(a);return typeof b=="function"?d:b==null?bH:(b+="",e)}function bS(a){var b=bL,c=bR,d=bP,e=bQ;bL=this.id,bR=this.ease();for(var f=0,g=this.length;f=c.delay&&(c.flush=c.callback(a)),c=c.next;var d=bX()-b;d>24?(isFinite(d)&&(clearTimeout(bV),bV=setTimeout(bW,d)),bU=0):(bU=1,bY(bW))}function bX(){var a=null,b=bT,c=Infinity;while(b)b.flush?b=a?a.next=b.next:bT=b.next:(c=Math.min(c,b.then+b.delay),b=(a=b).next);return c}function bZ(a){var b=[a.a,a.b],c=[a.c,a.d],d=b_(b),e=b$(b,c),f=b_(ca(c,b,-e))||0;b[0]*c[1]2?cq:cp,i=d?bd:bc;return e=g(a,b,i,c),f=g(b,a,i,d3.interpolate),h}function h(a){return e(a)}var e,f;return h.invert=function(a){return f(a)},h.domain=function(b){return arguments.length?(a=b.map(Number),g()):a},h.range=function(a){return arguments.length?(b=a,g()):b},h.rangeRound=function(a){return h.range(a).interpolate(d3.interpolateRound)},h.clamp=function(a){return arguments.length?(d=a,g()):d},h.interpolate=function(a){return arguments.length?(c=a,g()):c},h.ticks=function(b){return cn(a,b)},h.tickFormat=function(b){return co(a,b)},h.nice=function(){return ch(a,cl),g()},h.copy=function(){return cj(a,b,c,d)},g()}function ck(a,b){return d3.rebind(a,b,"range","rangeRound","interpolate","clamp")}function cl(a){return a=Math.pow(10,Math.round(Math.log(a)/Math.LN10)-1),{floor:function(b){return Math.floor(b/a)*a},ceil:function(b){return Math.ceil(b/a)*a}}}function cm(a,b){var c=cf(a),d=c[1]-c[0],e=Math.pow(10,Math.floor(Math.log(d/b)/Math.LN10)),f=b/d*e;return f<=.15?e*=10:f<=.35?e*=5:f<=.75&&(e*=2),c[0]=Math.ceil(c[0]/e)*e,c[1]=Math.floor(c[1]/e)*e+e*.5,c[2]=e,c}function cn(a,b){return d3.range.apply(d3,cm(a,b))}function co(a,b){return d3.format(",."+Math.max(0,-Math.floor(Math.log(cm(a,b)[2])/Math.LN10+.01))+"f")}function cp(a,b,c,d){var e=c(a[0],a[1]),f=d(b[0],b[1]);return function(a){return f(e(a))}}function cq(a,b,c,d){var e=[],f=[],g=0,h=Math.min(a.length,b.length)-1;a[h]0;j--)e.push(c(f)*j)}else{for(;fi;g--);e=e.slice(f,g)}return e},d.tickFormat=function(a,e){arguments.length<2&&(e=cs);if(arguments.length<1)return e;var f=a/d.ticks().length,g=b===cu?(h=-1e-12,Math.floor):(h=1e-12,Math.ceil),h;return function(a){return a/c(g(b(a)+h))0?0:-a)/Math.LN10}function cv(a,b){function e(b){return a(c(b))}var c=cw(b),d=cw(1/b);return e.invert=function(b){return d(a.invert(b))},e.domain=function(b){return arguments.length?(a.domain(b.map(c)),e):a.domain().map(d)},e.ticks=function(a){return cn(e.domain(),a)},e.tickFormat=function(a){return co(e.domain(),a)},e.nice=function(){return e.domain(ch(e.domain(),cl))},e.exponent=function(a){if(!arguments.length)return b;var f=e.domain();return c=cw(b=a),d=cw(1/b),e.domain(f)},e.copy=function(){return cv(a.copy(),b)},ck(e,a)}function cw(a){return function(b){return b<0?-Math.pow(-b,a):Math.pow(b,a)}}function cx(a,b){function f(b){return d[((c.get(b)||c.set(b,a.push(b)))-1)%d.length]}function g(b,c){return d3.range(a.length).map(function(a){return b+c*a})}var c,d,e;return f.domain=function(d){if(!arguments.length)return a;a=[],c=new k;var e=-1,g=d.length,h;while(++e1){h=b[1],f=a[i],i++,d+="C"+(e[0]+g[0])+","+(e[1]+g[1])+","+(f[0]-h[0])+","+(f[1]-h[1])+","+f[0]+","+f[1];for(var j=2;j9&&(f=c*3/Math.sqrt(f),g[h]=f*d,g[h+1]=f*e));h=-1;while(++h<=i)f=(a[Math.min(i,h+1)][0]-a[Math.max(0,h-1)][0])/(6*(1+g[h]*g[h])),b.push([f||0,g[h]*f||0]);return b}function di(a){return a.length<3?cQ(a):a[0]+cW(a,dh(a))}function dj(a){var b,c=-1,d=a.length,e,f;while(++c1){var d=cf(a.domain()),e,f=-1,g=b.length,h=(b[1]-b[0])/++c,i,j;while(++f0;)(j=+b[f]-i*h)>=d[0]&&e.push(j);for(--f,i=0;++id&&(c=b,d=e);return c}function ea(a){return a.reduce(eb,0)}function eb(a,b){return a+b[1]}function ec(a,b){return ed(a,Math.ceil(Math.log(b.length)/Math.LN2+1))}function ed(a,b){var c=-1,d=+a[0],e=(a[1]-d)/b,f=[];while(++c<=b)f[c]=e*c+d;return f}function ee(a){return[d3.min(a),d3.max(a)]}function ef(a,b){return d3.rebind(a,b,"sort","children","value"),a.links=ej,a.nodes=function(b){return ek=!0,(a.nodes=a)(b)},a}function eg(a){return a.children}function eh(a){return a.value}function ei(a,b){return b.value-a.value}function ej(a){return d3.merge(a.map(function(a){return(a.children||[]).map(function(b){return{source:a,target:b}})}))}function el(a,b){return a.value-b.value}function em(a,b){var c=a._pack_next;a._pack_next=b,b._pack_prev=a,b._pack_next=c,c._pack_prev=b}function en(a,b){a._pack_next=b,b._pack_prev=a}function eo(a,b){var c=b.x-a.x,d=b.y-a.y,e=a.r+b.r;return e*e-c*c-d*d>.001}function ep(a){function l(a){b=Math.min(a.x-a.r,b),c=Math.max(a.x+a.r,c),d=Math.min(a.y-a.r,d),e=Math.max(a.y+a.r,e)}var b=Infinity,c=-Infinity,d=Infinity,e=-Infinity,f=a.length,g,h,i,j,k;a.forEach(eq),g=a[0],g.x=-g.r,g.y=0,l(g);if(f>1){h=a[1],h.x=h.r,h.y=0,l(h);if(f>2){i=a[2],eu(g,h,i),l(i),em(g,i),g._pack_prev=i,em(i,h),h=g._pack_next;for(var m=3;m0&&(a=d)}return a}function eD(a,b){return a.x-b.x}function eE(a,b){return b.x-a.x}function eF(a,b){return a.depth-b.depth}function eG(a,b){function c(a,d){var e=a.children;if(e&&(i=e.length)){var f,g=null,h=-1,i;while(++h=0)f=d[e]._tree,f.prelim+=b,f.mod+=b,b+=f.shift+(c+=f.change)}function eI(a,b,c){a=a._tree,b=b._tree;var d=c/(b.number-a.number);a.change+=d,b.change-=d,b.shift+=c,b.prelim+=c,b.mod+=c}function eJ(a,b,c){return a._tree.ancestor.parent==b.parent?a._tree.ancestor:c}function eK(a){return{x:a.x,y:a.y,dx:a.dx,dy:a.dy}}function eL(a,b){var c=a.x+b[3],d=a.y+b[0],e=a.dx-b[1]-b[3],f=a.dy-b[0]-b[2];return e<0&&(c+=e/2,e=0),f<0&&(d+=f/2,f=0),{x:c,y:d,dx:e,dy:f}}function eM(a){return a.map(eN).join(",")}function eN(a){return/[",\n]/.test(a)?'"'+a.replace(/\"/g,'""')+'"':a}function eP(a,b){return function(c){return c&&a.hasOwnProperty(c.type)?a[c.type](c):b}}function eQ(a){return"m0,"+a+"a"+a+","+a+" 0 1,1 0,"+ -2*a+"a"+a+","+a+" 0 1,1 0,"+2*a+"z"}function eR(a,b){eS.hasOwnProperty(a.type)&&eS[a.type](a,b)}function eT(a,b){eR(a.geometry,b)}function eU(a,b){for(var c=a.features,d=0,e=c.length;d0}function fg(a,b,c){return(c[0]-b[0])*(a[1]-b[1])<(c[1]-b[1])*(a[0]-b[0])}function fh(a,b,c,d){var e=a[0],f=b[0],g=c[0],h=d[0],i=a[1],j=b[1],k=c[1],l=d[1],m=e-g,n=f-e,o=h-g,p=i-k,q=j-i,r=l-k,s=(o*p-r*m)/(r*n-o*q);return[e+s*n,i+s*q]}function fj(a,b){var c={list:a.map(function(a,b){return{index:b,x:a[0],y:a[1]}}).sort(function(a,b){return a.yb.y?1:a.xb.x?1:0}),bottomSite:null},d={list:[],leftEnd:null,rightEnd:null,init:function(){d.leftEnd=d.createHalfEdge(null,"l"),d.rightEnd=d.createHalfEdge(null,"l"),d.leftEnd.r=d.rightEnd,d.rightEnd.l=d.leftEnd,d.list.unshift(d.leftEnd,d.rightEnd)},createHalfEdge:function(a,b){return{edge:a,side:b,vertex:null,l:null,r:null}},insert:function(a,b){b.l=a,b.r=a.r,a.r.l=b,a.r=b},leftBound:function(a){var b=d.leftEnd;do b=b.r;while(b!=d.rightEnd&&e.rightOf(b,a));return b=b.l,b},del:function(a){a.l.r=a.r,a.r.l=a.l,a.edge=null},right:function(a){return a.r},left:function(a){return a.l},leftRegion:function(a){return a.edge==null?c.bottomSite:a.edge.region[a.side]},rightRegion:function(a){return a.edge==null?c.bottomSite:a.edge.region[fi[a.side]]}},e={bisect:function(a,b){var c={region:{l:a,r:b},ep:{l:null,r:null}},d=b.x-a.x,e=b.y-a.y,f=d>0?d:-d,g=e>0?e:-e;return c.c=a.x*d+a.y*e+(d*d+e*e)*.5,f>g?(c.a=1,c.b=e/d,c.c/=d):(c.b=1,c.a=d/e,c.c/=e),c},intersect:function(a,b){var c=a.edge,d=b.edge;if(!c||!d||c.region.r==d.region.r)return null;var e=c.a*d.b-c.b*d.a;if(Math.abs(e)<1e-10)return null;var f=(c.c*d.b-d.c*c.b)/e,g=(d.c*c.a-c.c*d.a)/e,h=c.region.r,i=d.region.r,j,k;h.y=k.region.r.x;return l&&j.side==="l"||!l&&j.side==="r"?null:{x:f,y:g}},rightOf:function(a,b){var c=a.edge,d=c.region.r,e=b.x>d.x;if(e&&a.side==="l")return 1;if(!e&&a.side==="r")return 0;if(c.a===1){var f=b.y-d.y,g=b.x-d.x,h=0,i=0;!e&&c.b<0||e&&c.b>=0?i=h=f>=c.b*g:(i=b.x+b.y*c.b>c.c,c.b<0&&(i=!i),i||(h=1));if(!h){var j=d.x-c.region.l.x;i=c.b*(g*g-f*f)m*m+n*n}return a.side==="l"?i:!i},endPoint:function(a,c,d){a.ep[c]=d;if(!a.ep[fi[c]])return;b(a)},distance:function(a,b){var c=a.x-b.x,d=a.y-b.y;return Math.sqrt(c*c+d*d)}},f={list:[],insert:function(a,b,c){a.vertex=b,a.ystar=b.y+c;for(var d=0,e=f.list,g=e.length;dh.ystar||a.ystar==h.ystar&&b.x>h.vertex.x)continue;break}e.splice(d,0,a)},del:function(a){for(var b=0,c=f.list,d=c.length;bo.y&&(p=n,n=o,o=p,t="r"),s=e.bisect(n,o),m=d.createHalfEdge(s,t),d.insert(k,m),e.endPoint(s,fi[t],r),q=e.intersect(k,m),q&&(f.del(k),f.insert(k,q,e.distance(q,n))),q=e.intersect(m,l),q&&f.insert(m,q,e.distance(q,n));else break}for(i=d.right(d.leftEnd);i!=d.rightEnd;i=d.right(i))b(i.edge)}function fk(){return{leaf:!0,nodes:[],point:null}}function fl(a,b,c,d,e,f){if(!a(b,c,d,e,f)){var g=(c+e)*.5,h=(d+f)*.5,i=b.nodes;i[0]&&fl(a,i[0],c,d,g,h),i[1]&&fl(a,i[1],g,d,e,h),i[2]&&fl(a,i[2],c,h,g,f),i[3]&&fl(a,i[3],g,h,e,f)}}function fm(a){return{x:a[0],y:a[1]}}function fo(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function fq(a,b,c,d){var e,f,g=0,h=b.length,i=c.length;while(g=i)return-1;e=b.charCodeAt(g++);if(e==37){f=fw[b.charAt(g++)];if(!f||(d=f(a,c,d))<0)return-1}else if(e!=c.charCodeAt(d++))return-1}return d}function fx(a,b,c){return fz.test(b.substring(c,c+=3))?c:-1}function fy(a,b,c){fA.lastIndex=0;var d=fA.exec(b.substring(c,c+10));return d?c+=d[0].length:-1}function fC(a,b,c){var d=fD.get(b.substring(c,c+=3).toLowerCase());return d==null?-1:(a.m=d,c)}function fE(a,b,c){fF.lastIndex=0;var d=fF.exec(b.substring(c,c+12));return d?(a.m=fG.get(d[0].toLowerCase()),c+=d[0].length):-1}function fI(a,b,c){return fq(a,fv.c.toString(),b,c)}function fJ(a,b,c){return fq(a,fv.x.toString(),b,c)}function fK(a,b,c){return fq(a,fv.X.toString(),b,c)}function fL(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+4));return d?(a.y=+d[0],c+=d[0].length):-1}function fM(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.y=fN()+ +d[0],c+=d[0].length):-1}function fN(){return~~((new Date).getFullYear()/1e3)*1e3}function fO(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.m=d[0]-1,c+=d[0].length):-1}function fP(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.d=+d[0],c+=d[0].length):-1}function fQ(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.H=+d[0],c+=d[0].length):-1}function fR(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.M=+d[0],c+=d[0].length):-1}function fS(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+2));return d?(a.S=+d[0],c+=d[0].length):-1}function fT(a,b,c){fU.lastIndex=0;var d=fU.exec(b.substring(c,c+3));return d?(a.L=+d[0],c+=d[0].length):-1}function fV(a,b,c){var d=fW.get(b.substring(c,c+=2).toLowerCase());return d==null?-1:(a.p=d,c)}function fX(a){var b=a.getTimezoneOffset(),c=b>0?"-":"+",d=~~(Math.abs(b)/60),e=Math.abs(b)%60;return c+fr(d)+fr(e)}function fZ(a){return a.toISOString()}function f$(a,b,c){function d(b){var c=a(b),d=f(c,1);return b-c1)while(gb?1:a>=b?0:NaN},d3.descending=function(a,b){return ba?1:b>=a?0:NaN},d3.mean=function(a,b){var c=a.length,d,e=0,f=-1,g=0;if(arguments.length===1)while(++f1&&(a=a.map(b)),a=a.filter(s),a.length?d3.quantile(a.sort(d3.ascending),.5):undefined},d3.min=function(a,b){var c=-1,d=a.length,e,f;if(arguments.length===1){while(++cf&&(e=f)}else{while(++cf&&(e=f)}return e},d3.max=function(a,b){var c=-1,d=a.length,e,f;if(arguments.length===1){while(++ce&&(e=f)}else{while(++ce&&(e=f)}return e},d3.extent=function(a,b){var c=-1,d=a.length,e,f,g;if(arguments.length===1){while(++cf&&(e=f),gf&&(e=f),g1);return a+b*c*Math.sqrt(-2*Math.log(e)/e)}}},d3.sum=function(a,b){var c=0,d=a.length,e,f=-1;if(arguments.length===1)while(++f>1;a.call(b,b[f],f)>1;c0&&(e=f);return e},d3.last=function(a,b){var c=0,d=a.length,e=a[0],f;arguments.length===1&&(b=d3.ascending);while(++c=b.length)return e?e.call(a,c):d?c.sort(d):c;var h=-1,i=c.length,j=b[g++],l,m,n=new k,o,p={};while(++h=b.length)return a;var e=[],f=c[d++],h;for(h in a)e.push({key:h,values:g(a[h],d)});return f&&e.sort(function(a,b){return f(a.key,b.key)}),e}var a={},b=[],c=[],d,e;return a.map=function(a){return f(a,0)},a.entries=function(a){return g(f(a,0),0)},a.key=function(c){return b.push(c),a},a.sortKeys=function(d){return c[b.length-1]=d,a},a.sortValues=function(b){return d=b,a},a.rollup=function(b){return e=b,a},a},d3.keys=function(a){var b=[];for(var c in a)b.push(c);return b},d3.values=function(a){var b=[];for(var c in a)b.push(a[c]);return b},d3.entries=function(a){var b=[];for(var c in a)b.push({key:c,value:a[c]});return b},d3.permute=function(a,b){var c=[],d=-1,e=b.length;while(++db)d.push(g/e);else while((g=a+c*++f)=200&&a<300||a===304?d:null)}},d.send(null)},d3.text=function(a,b,c){function d(a){c(a&&a.responseText)}arguments.length<3&&(c=b,b=null),d3.xhr(a,b,d)},d3.json=function(a,b){d3.text(a,"application/json",function(a){b(a?JSON.parse(a):null)})},d3.html=function(a,b){d3.text(a,"text/html",function(a){if(a!=null){var c=document.createRange();c.selectNode(document.body),a=c.createContextualFragment(a)}b(a)})},d3.xml=function(a,b,c){function d(a){c(a&&a.responseXML)}arguments.length<3&&(c=b,b=null),d3.xhr(a,b,d)};var z={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};d3.ns={prefix:z,qualify:function(a){var b=a.indexOf(":"),c=a;return b>=0&&(c=a.substring(0,b),a=a.substring(b+1)),z.hasOwnProperty(c)?{space:z[c],local:a}:a}},d3.dispatch=function(){var a=new A,b=-1,c=arguments.length;while(++b0&&(d=a.substring(c+1),a=a.substring(0,c)),arguments.length<2?this[a].on(d):this[a].on(d,b)},d3.format=function(a){var b=C.exec(a),c=b[1]||" ",d=b[3]||"",e=b[5],f=+b[6],g=b[7],h=b[8],i=b[9],j=1,k="",l=!1;h&&(h=+h.substring(1)),e&&(c="0",g&&(f-=Math.floor((f-1)/4)));switch(i){case"n":g=!0,i="g";break;case"%":j=100,k="%",i="f";break;case"p":j=100,k="%",i="r";break;case"d":l=!0,h=0;break;case"s":j=-1,i="r"}return i=="r"&&!h&&(i="g"),i=D.get(i)||F,function(a){if(l&&a%1)return"";var b=a<0&&(a=-a)?"−":d;if(j<0){var m=d3.formatPrefix(a,h);a*=m.scale,k=m.symbol}else a*=j;a=i(a,h);if(e){var n=a.length+b.length;n=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/,D=d3.map({g:function(a,b){return a.toPrecision(b)},e:function(a,b){return a.toExponential(b)},f:function(a,b){return a.toFixed(b)},r:function(a,b){return d3.round(a,b=E(a,b)).toFixed(Math.max(0,Math.min(20,b)))}}),H=["y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y"].map(I);d3.formatPrefix=function(a,b){var c=0;return a&&(a<0&&(a*=-1),b&&(a=d3.round(a,E(a,b))),c=1+Math.floor(1e-12+Math.log(a)/Math.LN10),c=Math.max(-24,Math.min(24,Math.floor((c<=0?c+1:c-1)/3)*3))),H[8+c/3]};var J=S(2),K=S(3),L=function(){return R},M=d3.map({linear:L,poly:S,quad:function(){return J},cubic:function(){return K},sin:function(){return T},exp:function(){return U},circle:function(){return V},elastic:W,back:X,bounce:function(){return Y}}),N=d3.map({"in":R,out:P,"in-out":Q,"out-in":function(a){return Q(P(a))}});d3.ease=function(a){var b=a.indexOf("-"),c=b>=0?a.substring(0,b):a,d=b>=0?a.substring(b+1):"in";return c=M.get(c)||L,d=N.get(d)||R,O(d(c.apply(null,Array.prototype.slice.call(arguments,1))))},d3.event=null,d3.interpolate=function(a,b){var c=d3.interpolators.length,d;while(--c>=0&&!(d=d3.interpolators[c](a,b)));return d},d3.interpolateNumber=function(a,b){return b-=a,function(c){return a+b*c}},d3.interpolateRound=function(a,b){return b-=a,function(c){return Math.round(a+b*c)}},d3.interpolateString=function(a,b){var c,d,e,f=0,g=0,h=[],i=[],j,k;ba.lastIndex=0;for(d=0;c=ba.exec(b);++d)c.index&&h.push(b.substring(f,g=c.index)),i.push({i:h.length,x:c[0]}),h.push(null),f=ba.lastIndex;f1){while(++e=0;)if(f=c[d])e&&e!==f.nextSibling&&e.parentNode.insertBefore(f,e),e=f;return this},bu.sort=function(a){a=bB.apply(this,arguments);for(var b=-1,c=this.length;++b0&&(a=a.substring(0,e)),arguments.length<2?(e=this.node()[d])&&e._:this.each(function(e,f){function i(a){var c=d3.event;d3.event=a;try{b.call(g,g.__data__,f)}finally{d3.event=c}}var g=this,h=g[d];h&&(g.removeEventListener(a,h,h.$),delete g[d]),b&&(g.addEventListener(a,g[d]=i,i.$=c),i._=b)})},bu.each=function(a){for(var b=-1,c=this.length;++b=cG?e?"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"M0,"+e+"A"+e+","+e+" 0 1,0 0,"+ -e+"A"+e+","+e+" 0 1,0 0,"+e+"Z":"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"Z":e?"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L"+e*m+","+e*n+"A"+e+","+e+" 0 "+j+",0 "+e*k+","+e*l+"Z":"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L0,0"+"Z"}var a=cH,b=cI,c=cJ,d=cK;return e.innerRadius=function(b){return arguments.length?(a=q(b),e):a},e.outerRadius=function(a){return arguments.length?(b=q(a),e):b},e.startAngle=function(a){return arguments.length?(c=q(a),e):c},e.endAngle=function(a){return arguments.length?(d=q(a),e):d},e.centroid=function(){var e=(a.apply(this,arguments)+b.apply(this,arguments))/2,f=(c.apply(this,arguments)+d.apply(this,arguments))/2+cF;return[Math.cos(f)*e,Math.sin(f)*e]},e};var cF=-Math.PI/2,cG=2*Math.PI-1e-6;d3.svg.line=function(){return cL(n)};var cO="linear",cP=d3.map({linear:cQ,"step-before":cR,"step-after":cS,basis:cY,"basis-open":cZ,"basis-closed":c$,bundle:c_,cardinal:cV,"cardinal-open":cT,"cardinal-closed":cU,monotone:di}),db=[0,2/3,1/3,0],dc=[0,1/3,2/3,0],dd=[0,1/6,2/3,1/6];d3.svg.line.radial=function(){var a=cL(dj);return a.radius=a.x,delete a.x,a.angle=a.y,delete a.y,a},cR.reverse=cS,cS.reverse=cR,d3.svg.area=function(){return dk(Object)},d3.svg.area.radial=function(){var a=dk(dj);return a.radius=a.x,delete a.x,a.innerRadius=a.x0,delete a.x0,a.outerRadius=a.x1,delete a.x1,a.angle=a.y,delete a.y,a.startAngle=a.y0,delete a.y0,a.endAngle=a.y1,delete a.y1,a},d3.svg.chord=function(){function f(c,d){var e=g(this,a,c,d),f=g(this,b,c,d);return"M"+e.p0+i(e.r,e.p1,e.a1-e.a0)+(h(e,f)?j(e.r,e.p1,e.r,e.p0):j(e.r,e.p1,f.r,f.p0)+i(f.r,f.p1,f.a1-f.a0)+j(f.r,f.p1,e.r,e.p0))+"Z"}function g(a,b,f,g){var h=b.call(a,f,g),i=c.call(a,h,g),j=d.call(a,h,g)+cF,k=e.call(a,h,g)+cF;return{r:i,a0:j,a1:k,p0:[i*Math.cos(j),i*Math.sin(j)],p1:[i*Math.cos(k),i*Math.sin(k)]}}function h(a,b){return a.a0==b.a0&&a.a1==b.a1}function i(a,b,c){return"A"+a+","+a+" 0 "+ +(c>Math.PI)+",1 "+b}function j(a,b,c,d){return"Q 0,0 "+d}var a=dl,b=dm,c=dn,d=cJ,e=cK;return f.radius=function(a){return arguments.length?(c=q(a),f):c},f.source=function(b){return arguments.length?(a=q(b),f):a},f.target=function(a){return arguments.length?(b=q(a),f):b},f.startAngle=function(a){return arguments.length?(d=q(a),f):d},f.endAngle=function(a){return arguments.length?(e=q(a),f):e},f},d3.svg.diagonal=function(){function d(d,e){var f=a.call(this,d,e),g=b.call(this,d,e),h=(f.y+g.y)/2,i=[f,{x:f.x,y:h},{x:g.x,y:h},g];return i=i.map(c),"M"+i[0]+"C"+i[1]+" "+i[2]+" "+i[3]}var a=dl,b=dm,c=dr;return d.source=function(b){return arguments.length?(a=q(b),d):a},d.target=function(a){return arguments.length?(b=q(a),d):b},d.projection=function(a){return arguments.length?(c=a,d):c},d},d3.svg.diagonal.radial=function(){var a=d3.svg.diagonal(),b=dr,c=a.projection;return a.projection=function(a){return arguments.length?c(ds(b=a)):b},a},d3.svg.mouse=d3.mouse,d3.svg.touches=d3.touches,d3.svg.symbol=function(){function c(c,d){return(dw.get(a.call(this,c,d))||dv)(b.call(this,c,d))}var a=du,b=dt;return c +.type=function(b){return arguments.length?(a=q(b),c):a},c.size=function(a){return arguments.length?(b=q(a),c):b},c};var dw=d3.map({circle:dv,cross:function(a){var b=Math.sqrt(a/5)/2;return"M"+ -3*b+","+ -b+"H"+ -b+"V"+ -3*b+"H"+b+"V"+ -b+"H"+3*b+"V"+b+"H"+b+"V"+3*b+"H"+ -b+"V"+b+"H"+ -3*b+"Z"},diamond:function(a){var b=Math.sqrt(a/(2*dy)),c=b*dy;return"M0,"+ -b+"L"+c+",0"+" 0,"+b+" "+ -c+",0"+"Z"},square:function(a){var b=Math.sqrt(a)/2;return"M"+ -b+","+ -b+"L"+b+","+ -b+" "+b+","+b+" "+ -b+","+b+"Z"},"triangle-down":function(a){var b=Math.sqrt(a/dx),c=b*dx/2;return"M0,"+c+"L"+b+","+ -c+" "+ -b+","+ -c+"Z"},"triangle-up":function(a){var b=Math.sqrt(a/dx),c=b*dx/2;return"M0,"+ -c+"L"+b+","+c+" "+ -b+","+c+"Z"}});d3.svg.symbolTypes=dw.keys();var dx=Math.sqrt(3),dy=Math.tan(30*Math.PI/180);d3.svg.axis=function(){function k(k){k.each(function(){var k=d3.select(this),l=h==null?a.ticks?a.ticks.apply(a,g):a.domain():h,m=i==null?a.tickFormat?a.tickFormat.apply(a,g):String:i,n=dB(a,l,j),o=k.selectAll(".minor").data(n,String),p=o.enter().insert("line","g").attr("class","tick minor").style("opacity",1e-6),q=d3.transition(o.exit()).style("opacity",1e-6).remove(),r=d3.transition(o).style("opacity",1),s=k.selectAll("g").data(l,String),t=s.enter().insert("g","path").style("opacity",1e-6),u=d3.transition(s.exit()).style("opacity",1e-6).remove(),v=d3.transition(s).style("opacity",1),w,x=cg(a),y=k.selectAll(".domain").data([0]),z=y.enter().append("path").attr("class","domain"),A=d3.transition(y),B=a.copy(),C=this.__chart__||B;this.__chart__=B,t.append("line").attr("class","tick"),t.append("text"),v.select("text").text(m);switch(b){case"bottom":w=dz,p.attr("y2",d),r.attr("x2",0).attr("y2",d),t.select("line").attr("y2",c),t.select("text").attr("y",Math.max(c,0)+f),v.select("line").attr("x2",0).attr("y2",c),v.select("text").attr("x",0).attr("y",Math.max(c,0)+f).attr("dy",".71em").attr("text-anchor","middle"),A.attr("d","M"+x[0]+","+e+"V0H"+x[1]+"V"+e);break;case"top":w=dz,p.attr("y2",-d),r.attr("x2",0).attr("y2",-d),t.select("line").attr("y2",-c),t.select("text").attr("y",-(Math.max(c,0)+f)),v.select("line").attr("x2",0).attr("y2",-c),v.select("text").attr("x",0).attr("y",-(Math.max(c,0)+f)).attr("dy","0em").attr("text-anchor","middle"),A.attr("d","M"+x[0]+","+ -e+"V0H"+x[1]+"V"+ -e);break;case"left":w=dA,p.attr("x2",-d),r.attr("x2",-d).attr("y2",0),t.select("line").attr("x2",-c),t.select("text").attr("x",-(Math.max(c,0)+f)),v.select("line").attr("x2",-c).attr("y2",0),v.select("text").attr("x",-(Math.max(c,0)+f)).attr("y",0).attr("dy",".32em").attr("text-anchor","end"),A.attr("d","M"+ -e+","+x[0]+"H0V"+x[1]+"H"+ -e);break;case"right":w=dA,p.attr("x2",d),r.attr("x2",d).attr("y2",0),t.select("line").attr("x2",c),t.select("text").attr("x",Math.max(c,0)+f),v.select("line").attr("x2",c).attr("y2",0),v.select("text").attr("x",Math.max(c,0)+f).attr("y",0).attr("dy",".32em").attr("text-anchor","start"),A.attr("d","M"+e+","+x[0]+"H0V"+x[1]+"H"+e)}if(a.ticks)t.call(w,C),v.call(w,B),u.call(w,B),p.call(w,C),r.call(w,B),q.call(w,B);else{var D=B.rangeBand()/2,E=function(a){return B(a)+D};t.call(w,E),v.call(w,E)}})}var a=d3.scale.linear(),b="bottom",c=6,d=6,e=6,f=3,g=[10],h=null,i,j=0;return k.scale=function(b){return arguments.length?(a=b,k):a},k.orient=function(a){return arguments.length?(b=a,k):b},k.ticks=function(){return arguments.length?(g=arguments,k):g},k.tickValues=function(a){return arguments.length?(h=a,k):h},k.tickFormat=function(a){return arguments.length?(i=a,k):i},k.tickSize=function(a,b,f){if(!arguments.length)return c;var g=arguments.length-1;return c=+a,d=g>1?+b:c,e=g>0?+arguments[g]:c,k},k.tickPadding=function(a){return arguments.length?(f=+a,k):f},k.tickSubdivide=function(a){return arguments.length?(j=+a,k):j},k},d3.svg.brush=function(){function g(a){a.each(function(){var a=d3.select(this),e=a.selectAll(".background").data([0]),f=a.selectAll(".extent").data([0]),l=a.selectAll(".resize").data(d,String),m;a.style("pointer-events","all").on("mousedown.brush",k).on("touchstart.brush",k),e.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),f.enter().append("rect").attr("class","extent").style("cursor","move"),l.enter().append("g").attr("class",function(a){return"resize "+a}).style("cursor",function(a){return dC[a]}).append("rect").attr("x",function(a){return/[ew]$/.test(a)?-3:null}).attr("y",function(a){return/^[ns]/.test(a)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),l.style("display",g.empty()?"none":null),l.exit().remove(),b&&(m=cg(b),e.attr("x",m[0]).attr("width",m[1]-m[0]),i(a)),c&&(m=cg(c),e.attr("y",m[0]).attr("height",m[1]-m[0]),j(a)),h(a)})}function h(a){a.selectAll(".resize").attr("transform",function(a){return"translate("+e[+/e$/.test(a)][0]+","+e[+/^s/.test(a)][1]+")"})}function i(a){a.select(".extent").attr("x",e[0][0]),a.selectAll(".extent,.n>rect,.s>rect").attr("width",e[1][0]-e[0][0])}function j(a){a.select(".extent").attr("y",e[0][1]),a.selectAll(".extent,.e>rect,.w>rect").attr("height",e[1][1]-e[0][1])}function k(){function x(){var a=d3.event.changedTouches;return a?d3.touches(d,a)[0]:d3.mouse(d)}function y(){d3.event.keyCode==32&&(q||(r=null,s[0]-=e[1][0],s[1]-=e[1][1],q=2),Z())}function z(){d3.event.keyCode==32&&q==2&&(s[0]+=e[1][0],s[1]+=e[1][1],q=0,Z())}function A(){var a=x(),d=!1;t&&(a[0]+=t[0],a[1]+=t[1]),q||(d3.event.altKey?(r||(r=[(e[0][0]+e[1][0])/2,(e[0][1]+e[1][1])/2]),s[0]=e[+(a[0]0?e=c:e=0:c>0&&(b.start({type:"start",alpha:e=c}),d3.timer(a.tick)),a):e},a.start=function(){function q(a,c){var d=t(b),e=-1,f=d.length,g;while(++ee&&(e=h),d.push(h)}for(g=0;g0){f=-1;while(++f=i[0]&&o<=i[1]&&(k=g[d3.bisect(j,o,1,m)-1],k.y+=n,k.push(e[f]))}return g}var a=!0,b=Number,c=ee,d=ec;return e.value=function(a){return arguments.length?(b=a,e):b},e.range=function(a){return arguments.length?(c=q(a),e):c},e.bins=function(a){return arguments.length?(d=typeof a=="number"?function(b){return ed(b,a)}:q(a),e):d},e.frequency=function(b){return arguments.length?(a=!!b,e):a},e},d3.layout.hierarchy=function(){function e(f,h,i){var j=b.call(g,f,h),k=ek?f:{data:f};k.depth=h,i.push(k);if(j&&(m=j.length)){var l=-1,m,n=k.children=[],o=0,p=h+1;while(++l0&&(eI(eJ(g,a,d),a,m),i+=m,j+=m),k+=g._tree.mod,i+=e._tree.mod,l+=h._tree.mod,j+=f._tree.mod;g&&!eB(f)&&(f._tree.thread=g,f._tree.mod+=k-j),e&&!eA(h)&&(h._tree.thread=e,h._tree.mod+=i-l,d=a)}return d}var f=a.call(this,d,e),g=f[0];eG(g,function(a,b){a._tree={ancestor:a,prelim:0,mod:0,change:0,shift:0,number:b?b._tree.number+1:0}}),h(g),i(g,-g._tree.prelim);var k=eC(g,eE),l=eC(g,eD),m=eC(g,eF),n=k.x-b(k,l)/2,o=l.x+b(l,k)/2,p=m.depth||1;return eG(g,function(a){a.x=(a.x-n)/(o-n)*c[0],a.y=a.depth/p*c[1],delete a._tree}),f}var a=d3.layout.hierarchy().sort(null).value(null),b=ez,c=[1,1];return d.separation=function(a){return arguments.length?(b=a,d):b},d.size=function(a){return arguments.length?(c=a,d):c},ef(d,a)},d3.layout.treemap=function(){function i(a,b){var c=-1,d=a.length,e,f;while(++c0)d.push(g=f[o-1]),d.area+=g.area,(k=l(d,n))<=h?(f.pop(),h=k):(d.area-=d.pop().area,m(d,n,c,!1),n=Math.min(c.dx,c.dy),d.length=d.area=0,h=Infinity);d.length&&(m(d,n,c,!0),d.length=d.area=0),b.forEach(j)}}function k(a){var b=a.children;if(b&&b.length){var c=e(a),d=b.slice(),f,g=[];i(d,c.dx*c.dy/a.value),g.area=0;while(f=d.pop())g.push(f),g.area+=f.area,f.z!=null&&(m(g,f.z?c.dx:c.dy,c,!d.length),g.length=g.area=0);b.forEach(k)}}function l(a,b){var c=a.area,d,e=0,f=Infinity,g=-1,i=a.length;while(++ge&&(e=d)}return c*=c,b*=b,c?Math.max(b*e*h/c,c/(b*f*h)):Infinity}function m(a,c,d,e){var f=-1,g=a.length,h=d.x,i=d.y,j=c?b(a.area/c):0,k;if(c==d.dx){if(e||j>d.dy)j=d.dy;while(++fd.dx)j=d.dx;while(++f=a.length)return d;if(i)return i=!1,c;var b=f.lastIndex;if(a.charCodeAt(b)===34){var e=b;while(e++50?b:f<-140?c:g<21?d:a)(e)}var a=d3.geo.albers(),b=d3.geo.albers().origin([-160,60]).parallels([55,65]),c=d3.geo.albers().origin([-160,20]).parallels([8,18]),d=d3.geo.albers().origin([-60,10]).parallels([8,18]);return e.scale=function(f){return arguments.length?(a.scale(f),b.scale(f*.6),c.scale(f),d.scale(f*1.5),e.translate(a.translate())):a.scale()},e.translate=function(f){if(!arguments.length)return a.translate();var g=a.scale()/1e3,h=f[0],i=f[1];return a.translate(f),b.translate([h-400*g,i+170*g]),c.translate([h-190*g,i+200*g]),d.translate([h+580*g,i+430*g]),e},e.scale(a.scale())},d3.geo.bonne=function(){function g(g){var h=g[0]*eO-c,i=g[1]*eO-d;if(e){var j=f+e-i,k=h*Math.cos(i)/j;h=j*Math.sin(k),i=j*Math.cos(k)-f}else h*=Math.cos(i),i*=-1;return[a*h+b[0],a*i+b[1]]}var a=200,b=[480,250],c,d,e,f;return g.invert=function(d){var g=(d[0]-b[0])/a,h=(d[1]-b[1])/a;if(e){var i=f+h,j=Math.sqrt(g*g+i*i);h=f+e-j,g=c+j*Math.atan2(g,i)/Math.cos(h)}else h*=-1,g/=Math.cos(h);return[g/eO,h/eO]},g.parallel=function(a){return arguments.length?(f=1/Math.tan(e=a*eO),g):e/eO},g.origin=function(a){return arguments.length?(c=a[0]*eO,d=a[1]*eO,g):[c/eO,d/eO]},g.scale=function(b){return arguments.length?(a=+b,g):a},g.translate=function(a){return arguments.length?(b=[+a[0],+a[1]],g):b},g.origin([0,0]).parallel(45)},d3.geo.equirectangular=function(){function c(c){var d=c[0]/360,e=-c[1]/360;return[a*d+b[0],a*e+b[1]]}var a=500,b=[480,250];return c.invert=function(c){var d=(c[0]-b[0])/a,e=(c[1]-b[1])/a;return[360*d,-360*e]},c.scale=function(b){return arguments.length?(a=+b,c):a},c.translate=function(a){return arguments.length?(b=[+a[0],+a[1]],c):b},c},d3.geo.mercator=function(){function c(c){var d=c[0]/360,e=-(Math.log(Math.tan(Math.PI/4+c[1]*eO/2))/eO)/360;return[a*d+b[0],a*Math.max(-0.5,Math.min(.5,e))+b[1]]}var a=500,b=[480,250];return c.invert=function(c){var d=(c[0]-b[0])/a,e=(c[1]-b[1])/a;return[360*d,2*Math.atan(Math.exp(-360*e*eO))/eO-90]},c.scale=function(b){return arguments.length?(a=+b,c):a},c.translate=function(a){return arguments.length?(b=[+a[0],+a[1]],c):b},c},d3.geo.path=function(){function d(c,d){return typeof a=="function"&&(b=eQ(a.apply(this,arguments))),f(c)||null}function e(a){return c(a).join(",")}function h(a){var b=k(a[0]),c=0,d=a.length;while(++c0){b.push("M");while(++h0){b.push("M");while(++kd&&(d=a),fe&&(e=f)}),[[b,c],[d,e]]};var eS={Feature:eT,FeatureCollection:eU,GeometryCollection:eV,LineString:eW,MultiLineString:eX,MultiPoint:eW,MultiPolygon:eY,Point:eZ,Polygon:e$};d3.geo.circle=function(){function e(){}function f(a){return d.distance(a)=k*k+l*l?d[f].index=-1:(d[m].index=-1,o=d[f].angle,m=f,n=g)):(o=d[f].angle,m=f,n=g);e.push(h);for(f=0,g=0;f<2;++g)d[g].index!==-1&&(e.push(d[g].index),f++);p=e.length;for(;g=0?(c=a.ep.r,d=a.ep.l):(c=a.ep.l,d=a.ep.r),a.a===1?(g=c?c.y:-1e6,e=a.c-a.b*g,h=d?d.y:1e6,f=a.c-a.b*h):(e=c?c.x:-1e6,g=a.c-a.a*e,f=d?d.x:1e6,h=a.c-a.a*f);var i=[e,g],j=[f,h];b[a.region.l.index].push(i,j),b[a.region.r.index].push(i,j)}),b.map(function(b,c){var d=a[c][0],e=a[c][1];return b.forEach(function(a){a.angle=Math.atan2(a[0]-d,a[1]-e)}),b.sort(function(a,b){return a.angle-b.angle}).filter(function(a,c){return!c||a.angle-b[c-1].angle>1e-10})})};var fi={l:"r",r:"l"};d3.geom.delaunay=function(a){var b=a.map(function(){return[]}),c=[];return fj(a,function(c){b[c.region.l.index].push(a[c.region.r.index])}),b.forEach(function(b,d){var e=a[d],f=e[0],g=e[1];b.forEach(function(a){a.angle=Math.atan2(a[0]-f,a[1]-g)}),b.sort(function(a,b){return a.angle-b.angle});for(var h=0,i=b.length-1;h=g,j=b.y>=h,l=(j<<1)+i;a.leaf=!1,a=a.nodes[l]||(a.nodes[l]=fk()),i?c=g:e=g,j?d=h:f=h,k(a,b,c,d,e,f)}var f,g=-1,h=a.length;h&&isNaN(a[0].x)&&(a=a.map(fm));if(arguments.length<5)if(arguments.length===3)e=d=c,c=b;else{b=c=Infinity,d=e=-Infinity;while(++gd&&(d=f.x),f.y>e&&(e=f.y);var i=d-b,j=e-c;i>j?e=c+i:d=b+j}var m=fk();return m.add=function(a){k(m,a,b,c,d,e)},m.visit=function(a){fl(a,m,b,c,d,e)},a.forEach(m.add),m},d3.time={};var fn=Date;fo.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){fp.setUTCDate.apply(this._,arguments)},setDay:function(){fp.setUTCDay.apply(this._,arguments)},setFullYear:function(){fp.setUTCFullYear.apply(this._,arguments)},setHours:function(){fp.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){fp.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){fp.setUTCMinutes.apply(this._,arguments)},setMonth:function(){fp.setUTCMonth.apply(this._,arguments)},setSeconds:function(){fp.setUTCSeconds.apply(this._,arguments)},setTime:function(){fp.setTime.apply(this._,arguments)}};var fp=Date.prototype;d3.time.format=function(a){function c(c){var d=[],e=-1,f=0,g,h;while(++e=12?"PM":"AM"},S:function(a){return fr(a.getSeconds())},U:function(a){return fr(d3.time.sundayOfYear(a))},w:function(a){return a.getDay()},W:function(a){return fr(d3.time.mondayOfYear(a))},x:d3.time.format("%m/%d/%y"),X:d3.time.format("%H:%M:%S"),y:function(a){return fr(a.getFullYear()%100)},Y:function(a){return ft(a.getFullYear()%1e4)},Z:fX,"%":function(a){return"%"}},fw={a:fx,A:fy,b:fC,B:fE,c:fI,d:fP,e:fP,H:fQ,I:fQ,L:fT,m:fO,M:fR,p:fV,S:fS,x:fJ,X:fK,y:fM,Y:fL},fz=/^(?:sun|mon|tue|wed|thu|fri|sat)/i,fA=/^(?:Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)/i,fB=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],fD=d3.map({jan:0,feb:1,mar:2,apr:3,may:4,jun:5,jul:6,aug:7,sep:8,oct:9,nov:10,dec:11}),fF=/^(?:January|February|March|April|May|June|July|August|September|October|November|December)/ig,fG=d3.map({january:0,february:1,march:2,april:3,may:4,june:5,july:6,august:7,september:8,october:9,november:10,december:11}),fH=["January","February","March","April","May","June","July","August","September","October","November","December"],fU=/\s*\d+/,fW=d3.map({am:0,pm:1});d3.time.format.utc=function(a){function c(a){try{fn=fo;var c=new fn;return c._=a,b(c)}finally{fn=Date}}var b=d3.time.format(a);return c.parse=function(a){try{fn=fo;var c=b.parse(a);return c&&c._}finally{fn=Date}},c.toString=b.toString,c};var fY=d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");d3.time.format.iso=Date.prototype.toISOString?fZ:fY,fZ.parse=function(a){return new Date(a)},fZ.toString=fY.toString,d3.time.second=f$(function(a){return new fn(Math.floor(a/1e3)*1e3)},function(a,b){a.setTime(a.getTime()+Math.floor(b)*1e3)},function(a){return a.getSeconds()}),d3.time.seconds=d3.time.second.range,d3.time.seconds.utc=d3.time.second.utc.range,d3.time.minute=f$(function(a){return new fn(Math.floor(a/6e4)*6e4)},function(a,b){a.setTime(a.getTime()+Math.floor(b)*6e4)},function(a){return a.getMinutes()}),d3.time.minutes=d3.time.minute.range,d3.time.minutes.utc=d3.time.minute.utc.range,d3.time.hour=f$(function(a){var b=a.getTimezoneOffset()/60;return new fn((Math.floor(a/36e5-b)+b)*36e5)},function(a,b){a.setTime(a.getTime()+Math.floor(b)*36e5)},function(a){return a.getHours()}),d3.time.hours=d3.time.hour.range,d3.time.hours.utc=d3.time.hour.utc.range,d3.time.day=f$(function(a){return new fn(a.getFullYear(),a.getMonth(),a.getDate())},function(a,b){a.setDate(a.getDate()+b)},function(a){return a.getDate()-1}),d3.time.days=d3.time.day.range,d3.time.days.utc=d3.time.day.utc.range,d3.time.dayOfYear=function(a){var b=d3.time.year(a);return Math.floor((a-b)/864e5-(a.getTimezoneOffset()-b.getTimezoneOffset())/1440)},fB.forEach(function(a,b){a=a.toLowerCase(),b=7-b;var c=d3.time[a]=f$(function(a){return(a=d3.time.day(a)).setDate(a.getDate()-(a.getDay()+b)%7),a},function(a,b){a.setDate(a.getDate()+Math.floor(b)*7)},function(a){var c=d3.time.year(a).getDay();return Math.floor((d3.time.dayOfYear(a)+(c+b)%7)/7)-(c!==b)});d3.time[a+"s"]=c.range,d3.time[a+"s"].utc=c.utc.range,d3.time[a+"OfYear"]=function(a){var c=d3.time.year(a).getDay();return Math.floor((d3.time.dayOfYear(a)+(c+b)%7)/7)}}),d3.time.week=d3.time.sunday,d3.time.weeks=d3.time.sunday.range,d3.time.weeks.utc=d3.time.sunday.utc.range,d3.time.weekOfYear=d3.time.sundayOfYear,d3.time.month=f$(function(a){return new fn(a.getFullYear(),a.getMonth(),1)},function(a,b){a.setMonth(a.getMonth()+b)},function(a){return a.getMonth()}),d3.time.months=d3.time.month.range,d3.time.months.utc=d3.time.month.utc.range,d3.time.year=f$(function(a){return new fn(a.getFullYear(),0,1)},function(a,b){a.setFullYear(a.getFullYear()+b)},function(a){return a.getFullYear()}),d3.time.years=d3.time.year.range,d3.time.years.utc=d3.time.year.utc.range;var gg=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],gh=[[d3.time.second,1],[d3.time.second,5],[d3.time.second,15],[d3.time.second,30],[d3.time.minute,1],[d3.time.minute,5],[d3.time.minute,15],[d3.time.minute,30],[d3.time.hour,1],[d3.time.hour,3],[d3.time.hour,6],[d3.time.hour,12],[d3.time.day,1],[d3.time.day,2],[d3.time.week,1],[d3.time.month,1],[d3.time.month,3],[d3.time.year,1]],gi=[[d3.time.format("%Y"),function(a){return!0}],[d3.time.format("%B"),function(a){return a.getMonth()}],[d3.time.format("%b %d"),function(a){return a.getDate()!=1}],[d3.time.format("%a %d"),function(a){return a.getDay()&&a.getDate()!=1}],[d3.time.format("%I %p"),function(a){return a.getHours()}],[d3.time.format("%I:%M"),function(a){return a.getMinutes()}],[d3.time.format(":%S"),function(a){return a.getSeconds()}],[d3.time.format(".%L"),function(a){return a.getMilliseconds()}]],gj=d3.scale.linear(),gk=gd(gi);gh.year=function(a,b){return gj.domain(a.map(gf)).ticks(b).map(ge)},d3.time.scale=function(){return ga(d3.scale.linear(),gh,gk)};var gl=gh.map(function(a){return[a[0].utc,a[1]]}),gm=[[d3.time.format.utc("%Y"),function(a){return!0}],[d3.time.format.utc("%B"),function(a){return a.getUTCMonth()}],[d3.time.format.utc("%b %d"),function(a){return a.getUTCDate()!=1}],[d3.time.format.utc("%a %d"),function(a){return a.getUTCDay()&&a.getUTCDate()!=1}],[d3.time.format.utc("%I %p"),function(a){return a.getUTCHours()}],[d3.time.format.utc("%I:%M"),function(a){return a.getUTCMinutes()}],[d3.time.format.utc(":%S"),function(a){return a.getUTCSeconds()}],[d3.time.format.utc(".%L"),function(a){return a.getUTCMilliseconds()}]],gn=gd(gm);gl.year=function(a,b){return gj.domain(a.map(gp)).ticks(b).map(go)},d3.time.scale.utc=function(){return ga(d3.scale.linear(),gl,gn)}})(); \ No newline at end of file diff --git a/web-static/graphs.html b/web-static/graphs.html index 339845d1..23bfdcd0 100644 --- a/web-static/graphs.html +++ b/web-static/graphs.html @@ -1,520 +1,557 @@ - - - - - P2Pool Graphs - - - - - - - -

P2Pool > Graphs

- -

Periods: Current:

- -
- -

Local rate

- - -

Local rate reflected in shares

- - -

Current payout to default address

- - -

Pool rate

- - -

Peers

- - -

Miners

-
- -

Desired version rates

- - -

Traffic rate

- - -

Bitcoind GetBlockTemplate Latency

- - -

Memory Usage

- - - - - + + + + + P2Pool Graphs + + + + + + + +

P2Pool > Graphs

+ +

Periods: Current:

+ +
+ +

Local rate

+ + +

Local rate reflected in shares

+ + +

Current payout to default address

+ + +

Pool rate

+ + +

Peers

+ + +

Miners

+
+ +

Desired version rates

+ + +

Traffic rate

+ + +

Bitcoind GetBlockTemplate Latency

+ + +

Memory Usage

+ + + + + \ No newline at end of file diff --git a/web-static/index.html b/web-static/index.html index 35e96951..415d170a 100644 --- a/web-static/index.html +++ b/web-static/index.html @@ -1,160 +1,150 @@ - - - - - - P2Pool - - - - - -

P2Pool

-

Graphs

-

Version:

-

Pool rate: ( DOA+orphan) Share difficulty:

-

Node uptime: Peers: out, in

-

Local rate: ( DOA) Expected time to share:

-

Shares: total ( orphaned, dead) Efficiency:

-

Payout if a block were found NOW: to . Expected after mining for 24 hours: per block.

-

Current block value: Expected time to block:

-
- -

Share explorer

-

Best share:

-

Verified heads:

-

Heads:

-

Verified tails:

-

Tails:

-

My shares:

- -

Blocks found in last day:

-

Note that blocks may have been orphaned from the P2Pool chain and so not be here.

- - -
timenumberhash/explorer linkshare
- -

Payouts if a block were found NOW:

- - -
addressamount in
- - + + + + + + P2Pool + + + + + +

P2Pool

+

Graphs

+

Version:

+

Pool rate: ( DOA+orphan) Share difficulty:

+

Node uptime: Peers: out, in

+

Local rate: ( DOA) Expected time to share:

+

Shares: total ( orphaned, dead) Efficiency:

+

Payout if a block were found NOW: to . Expected after mining for 24 hours: per block.

+

Current block value: Expected time to block:

+
+ +

Share explorer

+

Best share:

+

Verified heads:

+

Heads:

+

Verified tails:

+

Tails:

+

My shares:

+ +

Blocks found in last day:

+

Note that blocks may have been orphaned from the P2Pool chain and so not be here.

+ + +
timenumberhash/explorer linkshare
+ +

Payouts if a block were found NOW:

+ + +
addressamount in
+ + diff --git a/web-static/share.html b/web-static/share.html index 45068b95..3dd9d474 100644 --- a/web-static/share.html +++ b/web-static/share.html @@ -1,100 +1,96 @@ - - - - - P2Pool Share - - - - -

Loading...

- - - + + + + + P2Pool Share + + + + +

Loading...

+ + +