From f74e1fe20de23f9d46b12a6a139bb7a36b2a9c91 Mon Sep 17 00:00:00 2001 From: webworker01 Date: Wed, 22 May 2019 01:05:40 +0000 Subject: [PATCH 01/16] attempt to reorganize logic for validating worker names --- libs/paymentProcessor.js | 2 +- libs/poolWorker.js | 74 +- website/piratepool.io/index.html | 16 +- .../piratepool.io/pages/getting_started.html | 7 +- website/piratepool.io/pages/home.html | 13 +- .../static/favicon/android-icon-144x144.png | Bin 0 -> 3752 bytes .../static/favicon/android-icon-192x192.png | Bin 0 -> 5018 bytes .../static/favicon/android-icon-36x36.png | Bin 0 -> 1343 bytes .../static/favicon/android-icon-48x48.png | Bin 0 -> 1743 bytes .../static/favicon/android-icon-72x72.png | Bin 0 -> 2165 bytes .../static/favicon/android-icon-96x96.png | Bin 0 -> 2694 bytes .../static/favicon/apple-icon-114x114.png | Bin 0 -> 2983 bytes .../static/favicon/apple-icon-120x120.png | Bin 0 -> 3079 bytes .../static/favicon/apple-icon-144x144.png | Bin 0 -> 3752 bytes .../static/favicon/apple-icon-152x152.png | Bin 0 -> 3970 bytes .../static/favicon/apple-icon-180x180.png | Bin 0 -> 4830 bytes .../static/favicon/apple-icon-57x57.png | Bin 0 -> 1948 bytes .../static/favicon/apple-icon-60x60.png | Bin 0 -> 1973 bytes .../static/favicon/apple-icon-72x72.png | Bin 0 -> 2165 bytes .../static/favicon/apple-icon-76x76.png | Bin 0 -> 2261 bytes .../static/favicon/apple-icon-precomposed.png | Bin 0 -> 5018 bytes website/zznomp/static/favicon/apple-icon.png | Bin 0 -> 5018 bytes .../zznomp/static/favicon/browserconfig.xml | 2 + .../zznomp/static/favicon/favicon-16x16.png | Bin 0 -> 641 bytes .../zznomp/static/favicon/favicon-32x32.png | Bin 0 -> 1138 bytes .../zznomp/static/favicon/favicon-96x96.png | Bin 0 -> 2694 bytes website/zznomp/static/favicon/favicon.ico | Bin 0 -> 1150 bytes website/zznomp/static/favicon/manifest.json | 41 + .../zznomp/static/favicon/ms-icon-144x144.png | Bin 0 -> 3752 bytes .../zznomp/static/favicon/ms-icon-150x150.png | Bin 0 -> 3898 bytes .../zznomp/static/favicon/ms-icon-310x310.png | Bin 0 -> 9479 bytes .../zznomp/static/favicon/ms-icon-70x70.png | Bin 0 -> 2174 bytes website/zznomp/static/payments.js | 84 ++ website/zznomp/static/pirate128.png | Bin 0 -> 2629 bytes website/zznomp/static/saplingbonus.txt | 110 +++ website/zznomp/static/sproutfinal.txt | 820 ++++++++++++++++++ website/zznomp/static/workers.js | 79 ++ 37 files changed, 1192 insertions(+), 56 deletions(-) create mode 100644 website/zznomp/static/favicon/android-icon-144x144.png create mode 100644 website/zznomp/static/favicon/android-icon-192x192.png create mode 100644 website/zznomp/static/favicon/android-icon-36x36.png create mode 100644 website/zznomp/static/favicon/android-icon-48x48.png create mode 100644 website/zznomp/static/favicon/android-icon-72x72.png create mode 100644 website/zznomp/static/favicon/android-icon-96x96.png create mode 100644 website/zznomp/static/favicon/apple-icon-114x114.png create mode 100644 website/zznomp/static/favicon/apple-icon-120x120.png create mode 100644 website/zznomp/static/favicon/apple-icon-144x144.png create mode 100644 website/zznomp/static/favicon/apple-icon-152x152.png create mode 100644 website/zznomp/static/favicon/apple-icon-180x180.png create mode 100644 website/zznomp/static/favicon/apple-icon-57x57.png create mode 100644 website/zznomp/static/favicon/apple-icon-60x60.png create mode 100644 website/zznomp/static/favicon/apple-icon-72x72.png create mode 100644 website/zznomp/static/favicon/apple-icon-76x76.png create mode 100644 website/zznomp/static/favicon/apple-icon-precomposed.png create mode 100644 website/zznomp/static/favicon/apple-icon.png create mode 100644 website/zznomp/static/favicon/browserconfig.xml create mode 100644 website/zznomp/static/favicon/favicon-16x16.png create mode 100644 website/zznomp/static/favicon/favicon-32x32.png create mode 100644 website/zznomp/static/favicon/favicon-96x96.png create mode 100644 website/zznomp/static/favicon/favicon.ico create mode 100644 website/zznomp/static/favicon/manifest.json create mode 100644 website/zznomp/static/favicon/ms-icon-144x144.png create mode 100644 website/zznomp/static/favicon/ms-icon-150x150.png create mode 100644 website/zznomp/static/favicon/ms-icon-310x310.png create mode 100644 website/zznomp/static/favicon/ms-icon-70x70.png create mode 100644 website/zznomp/static/payments.js create mode 100644 website/zznomp/static/pirate128.png create mode 100644 website/zznomp/static/saplingbonus.txt create mode 100644 website/zznomp/static/sproutfinal.txt create mode 100644 website/zznomp/static/workers.js diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index ed77d33..7644959 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -432,7 +432,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { }); } else { logger.special(logSystem, logComponent, 'Found payment opid ' + op.id ); - redisClient.multi([ + redisClient.multi([ ['zremrangebyscore', coin + ':payments', apresult.time, apresult.time], ['zadd', coin + ':payments', apresult.time, JSON.stringify(apresult)] ]).exec(function(error, results) { diff --git a/libs/poolWorker.js b/libs/poolWorker.js index 2051688..b72daa2 100644 --- a/libs/poolWorker.js +++ b/libs/poolWorker.js @@ -13,7 +13,7 @@ module.exports = function(logger){ var portalConfig = JSON.parse(process.env.portalConfig); var forkId = process.env.forkId; - + var pools = {}; var proxySwitch = {}; @@ -22,6 +22,7 @@ module.exports = function(logger){ if (portalConfig.redis.password) { redisClient.auth(portalConfig.redis.password); } + //Handle messages from master process sent via IPC process.on('message', function(message) { switch(message.type){ @@ -71,10 +72,10 @@ module.exports = function(logger){ if (newPool) { oldPool.relinquishMiners( - function (miner, cback) { + function (miner, cback) { // relinquish miners that are attached to one of the "Auto-switch" ports and leave the others there. cback(proxyPorts.indexOf(miner.client.socket.localPort.toString()) !== -1) - }, + }, function (clients) { newPool.attachMiners(clients); } @@ -95,7 +96,6 @@ module.exports = function(logger){ } }); - Object.keys(poolConfigs).forEach(function(coin) { var poolOptions = poolConfigs[coin]; @@ -142,32 +142,10 @@ module.exports = function(logger){ var shareProcessor = new ShareProcessor(logger, poolOptions); handlers.auth = function(port, workerName, password, authCallback){ - - if (poolOptions.validateWorkerUsername !== true) + if (poolOptions.validateWorkerUsername !== true) { authCallback(true); - else { - if (privateChain) { - let poolZAddressPrefix = poolOptions.zAddress.substring(0,2); - pool.daemon.cmd('z_validateaddress', [String(workerName).split(".")[0]], function (results) { - var isValid = results.filter(function (r) { - if ( (poolOptions.coin.sapling || poolOptions.coin.sapling > 0) && poolZAddressPrefix == 'zs') { - return (r.response.isvalid && r.response.type == 'sapling'); - } else if ( poolZAddressPrefix == 'zc') { - return (r.response.isvalid && r.response.type == 'sprout'); - } else { - return r.response.isvalid; - } - }).length > 0; - authCallback(isValid); - }); - } else { - pool.daemon.cmd('validateaddress', [String(workerName).split(".")[0]], function (results) { - var isValid = results.filter(function (r) { - return r.response.isvalid - }).length > 0; - authCallback(isValid); - }); - } + } else { + authCallback(_this.validateAddress()); } }; @@ -193,9 +171,9 @@ module.exports = function(logger){ var pool = Stratum.createPool(poolOptions, authorizeFN, logger); pool.on('share', function(isValidShare, isValidBlock, data){ - + var shareData = JSON.stringify(data); - + if (data.blockHash && !isValidBlock) logger.debug(logSystem, logComponent, logSubCat, 'We thought a block was found but it was rejected by the daemon, share data: ' + shareData); @@ -212,13 +190,13 @@ module.exports = function(logger){ } else if (!isValidShare) { logger.debug(logSystem, logComponent, logSubCat, 'Share rejected: ' + shareData); } - + // handle the share handlers.share(isValidShare, isValidBlock, data); - + // send to master for pplnt time tracking process.send({type: 'shareTrack', thread:(parseInt(forkId)+1), coin:poolOptions.coin.name, isValidShare:isValidShare, isValidBlock:isValidBlock, data:data, trackShares:trackShares}); - + }).on('difficultyUpdate', function(workerName, diff){ logger.debug(logSystem, logComponent, logSubCat, 'Difficulty update to diff ' + diff + ' workerName=' + JSON.stringify(workerName)); handlers.diff(workerName, diff); @@ -275,7 +253,6 @@ module.exports = function(logger){ if (!portalConfig.switching[switchName].enabled) return; - var initalPool = proxyState.hasOwnProperty(algorithm) ? proxyState[algorithm] : _this.getFirstPoolForAlgorithm(algorithm); proxySwitch[switchName] = { algorithm: algorithm, @@ -284,7 +261,6 @@ module.exports = function(logger){ servers: [] }; - Object.keys(proxySwitch[switchName].ports).forEach(function(port){ var f = net.createServer(function(socket) { var currentPool = proxySwitch[switchName].currentPool; @@ -293,7 +269,7 @@ module.exports = function(logger){ + switchName + ' from ' + socket.remoteAddress + ' on ' + port + ' routing to ' + currentPool); - + if (pools[currentPool]) pools[currentPool].getStratumServer().handleNewClient(socket); else @@ -324,7 +300,7 @@ module.exports = function(logger){ }; // - // Called when stratum pool emits its 'started' event to copy the initial diff and vardiff + // Called when stratum pool emits its 'started' event to copy the initial diff and vardiff // configuation for any proxy switching ports configured into the stratum pool object. // this.setDifficultyForProxyPort = function(pool, coin, algo) { @@ -337,7 +313,7 @@ module.exports = function(logger){ var switchAlgo = portalConfig.switching[switchName].algorithm; if (pool.options.coin.algorithm !== switchAlgo) return; - // we know the switch configuration matches the pool's algo, so setup the diff and + // we know the switch configuration matches the pool's algo, so setup the diff and // vardiff for each of the switch's ports for (var port in portalConfig.switching[switchName].ports) { @@ -345,11 +321,29 @@ module.exports = function(logger){ pool.setVarDiff(port, portalConfig.switching[switchName].ports[port].varDiff); if (portalConfig.switching[switchName].ports[port].diff){ - if (!pool.options.ports.hasOwnProperty(port)) + if (!pool.options.ports.hasOwnProperty(port)) pool.options.ports[port] = {}; pool.options.ports[port].diff = portalConfig.switching[switchName].ports[port].diff; } } }); }; + + this.validateAddress = function(address) { + let poolZAddressPrefix = poolOptions.zAddress.substring(0,2); + let minerAddressLength = address.replace(/[^0-9a-z]/gi, '').length; + let minerAddressPrefix = address.substring(0,2); + + if (privateChain && poolZAddressPrefix == 'zs' && minerAddressLength == 78 && minerAddressPrefix == 'zs') { + //validate as sapling + return true; + } else if (privateChain && poolZAddressPrefix == 'zc' && minerAddressLength == 95 && minerAddressPrefix == 'zc') { + //validate as sprout + return true; + } else if (privateChain || address.length >= 40 || address.length <= 30) { + return false; + } else { + return true; + } + }; }; diff --git a/website/piratepool.io/index.html b/website/piratepool.io/index.html index f030ec8..4e4c8d5 100644 --- a/website/piratepool.io/index.html +++ b/website/piratepool.io/index.html @@ -5,25 +5,25 @@ - piratepool.io - mining pool for pirate (ARRR) chain - the most private and anonymous mineable cryptocurrency + piratepool.io - mining pool for PirateChain (ARRR) - the most private and anonymous mineable cryptocurrency - Pirate - - + + - - - + + + - - + + diff --git a/website/piratepool.io/pages/getting_started.html b/website/piratepool.io/pages/getting_started.html index b9f6201..411a82b 100644 --- a/website/piratepool.io/pages/getting_started.html +++ b/website/piratepool.io/pages/getting_started.html @@ -121,8 +121,11 @@

There is a limit of ~200 recipients that can be included in a single payout, so the pool payouts are monitored and the min payout adjusted accordingly to ensure a constant flow of payments.

If payments stop going out, do not worry! Funds are safu! Blocks can still be found and will be credited to your worker! Please check the #pools-and-operators channel in discord to see if it's already being worked on.

Pending blocks have not yet been scanned by the payment processor. After being scanned, blocks will need to receive both dPoW notarization and 10 confirmations before being actually paid out.

-

On your worker stats page, pending balance is the remaining estimated amount to be paid for blocks that were scanned but not yet eligible for payout either because of dPoW or min confirmations. Balance includes blocks that were scanned and already paid out but you have not yet met the min payout.

+

On your worker stats page, pending balance is the remaining estimated amount to be paid for blocks that + were scanned but not yet eligible for payout either because of + dPoW or min confirmations. + Balance includes blocks that were scanned and already paid out but you have not yet met the min payout.*

+

*Please note these 2 stats will only update when the payment processor runs which is currently every 4 hours.

Payments that show up on the payments page initially are in the process of constructing the z transaction. Once the transaction actually broadcasts to the network, the blocks paid out will become hyperlinked to the explorer and then should arrive in your wallet in the next block or two.

diff --git a/website/piratepool.io/pages/home.html b/website/piratepool.io/pages/home.html index 389f455..f1a751f 100644 --- a/website/piratepool.io/pages/home.html +++ b/website/piratepool.io/pages/home.html @@ -1,13 +1,16 @@ {{ function bigNumber(x){ return (x > 1000000000000) ? (x / 1000000000000).toFixed(1) + 'T' : (x > 1000000000) ? (x / 1000000000).toFixed(1) + 'B' : (x > 1000000) ? (x / 1000000).toFixed(1) + 'M' : (x > 1000) ? (x / 1000).toFixed(1) + 'K' : x.toFixed(1); } }}
-
Stop mining to exchange addresses…
+
+ + 300K+ ARRR donated to Onboarding/Dev and Marketing funds, made possible via KMD notary node income.
+ Thank you for all who voted me into KMD notary node for 2019 in SH! ❤ 🐸
- piratepool.io - knomp + piratepool.io - knomp

piratepool.io

-

Mining Pool For Pirate (ARRR)

+

Mining Pool For PirateChain (ARRR)

@@ -20,7 +23,7 @@ Website
Github
Bitcoin Talk
- Alternative Pools + Alternative Pools
Explorer
@@ -43,7 +46,7 @@ Download the latest Agama wallet and create a sapling address (starts with zs1) and connect to the new stratum ports labeled as arrr on Getting Started.

- You need to migrate sprout funds in your own zc wallet address by 2019-02-01. A quick guide on how to migrate can be found here. + You need to migrate sprout funds in your own zc wallet address by 2019-02-01. A quick guide on how to migrate can be found here. You could also try this service to swap your coins.

diff --git a/website/zznomp/static/favicon/android-icon-144x144.png b/website/zznomp/static/favicon/android-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..f65ef9d6b38a8bc14c95c7ffc4df72972044a376 GIT binary patch literal 3752 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 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/android-icon-36x36.png b/website/zznomp/static/favicon/android-icon-36x36.png new file mode 100644 index 0000000000000000000000000000000000000000..3dd9b57ff4cfff35140bd99ade1a82c8a263697a GIT binary patch literal 1343 zcmV-F1;F}=P)vyN){VK8H|o`lx|KQAxo6Y1W6G;l%BxlC z)r-@%W9H9<#iUHSl{x9sh}*z$*}iVNl{m$uOYYi|=+cPp+LGMEbI`J0w~;gA%YO0Q zmhs(|&$3C%YOwPD}KdCIC(%Bob-v|!}SfyJXs?b(sUqDjxOUH||8#iUE? z){W}bi^HKv-^O>{!*treZ`i$T*1KuIo)&xE>_IO58E@Z6N<&VtCNP`Hyd(6e6q`S8oDRn@s?&97Sb@#D_1WVews z`uFYd-Ie$7-SOwk=GLX^*OuYQeAKvQ&8}Gf{`>at+x70*^Xkv<CEWZso%?$DHO%(vRH7jO5OX< zh2hG6*}rt$!gJNSYuCMM{QC3t?bYt&$m`#~>fXHT+^*`|tmxUR>)fg3)1v6rnBvZt z>erRw%ZS>-e8;CxwaTLE0001IbW%=J00IU62*6Pt6AaO&he8E`9-<>TPq+uG64%gV^d#lph4x3jOV zs;HrujEQ`5Wn^AlS5{C>Nk>LOG&CNMhF`P*00KKnL_t(I%YD>mThmY!2k;~9_uhN&bw$fi(2{5^B1KUQNGIJbL-v%t;foP+)0>0@&g;Esa_}pTb6$ieYrs} zD0l@#b8Xdtum83HO2}qV+INT?gFI<)O?q`4D%-?Fbdp1U8h|Qyt=l~|I?_Vwy*hgo zL_wig@G1`dssf;vQuG%V^lCJEvZaZhhGjwL_zO|lW-M8Vnh~l8 z2>l7i!gyqM`iycY2wRKLu*XO#B}Hli9p|N(B~W;z;DqJRe3u#-w&R_>QnddbvFKTOae0Rr#a_*pK4hvV z=_j@aB8WSc@mz(;75@6s&5MZ#4;;U6>v5#;EAw4f&6GAO&eQ+^002ovPDHLkV1iVJ B{G|W@ literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/android-icon-48x48.png b/website/zznomp/static/favicon/android-icon-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..f62bd63ea7d939554d5759948b37f4eab168e564 GIT binary patch literal 1743 zcmW+#2{fDO8V*`xsWTa)mFc*xx_3J5nS1B9RIOF(6>W!Ds>hfrEgefK7p)d8L1|E1 zETwI1ZO2kOu_X~(NFoa=5s5~GNXTLaDT4d;p7Z_h|Gn?`o#%bt=lTEV2zOUKo#Q$X z2t>~f?(7BL=e|5z8XyL8wL2jY^(DkL9~Y34-g-#cd22Jd-GvvVv-v&fiwZ7UK37Dj zuouzOyYkP^5u@eYA{nQUPkJOECohtdWwQmnXbZwC2S!^!U#X3PS1g`J$v6dkQbKo; zc~`zEx!xNT<#T9S^RFUirhxJU6cya!&b;#g2OMz-QTPgb+)KNG*N*@1p2No7>npV$ zto+Y-o!2rwZJF_<^*XNvTVUE-Y&ne$9;$MsxBj*=nFWdfZ5AIjUgrs*x(m&SZ=68&@x5okeg_Wx4+m@TBHbQfJ1d+&iQFyoIt>Mk@Nu6Fy_^ZPPA9YiqENbNP@ zMCuea7;FGI*zm^^0Z*_dJA)R+lb9Vr0EasmOM2%4QcA=1nch(DP#mBknMQ%g8;WD~ zg#*z*IzRFdTX+G8Fx7RZ2W%Ix||tigZ+@)K|$j7-G1Fxvwetv6Q~&kha_ z*4TMVG$gnQKmbF~5lFE*lRG~g4_eO=V>pESY<%QQZ`ij@4f$h_KaD2z zzqDInK3k-w0I7iy;;Ag)i-?f{bQ`Vx1qeubkJwSlfLx6B06-5Iw7;*K?7U5D_NO%7 z0M?J!`vR&mAsGlLVU=ueidndrgZ=&ez1Y7@OzuePA|-`0^pu5v z_-XV38y~CMR_tu8D%W|N(y2eiRGE+@;dV>so7T8>%hRtVGicFN!5aGoe>_7#PT~*~ zC$aa~xNzVLvona&;G_IgxVA8;SnQK<-b!X`1(UV&NpPVV6rnB%*Xsx$9 zW6cV|hmMT%a`%R)n}0i^r>Kk9Iz*%3-#_!Y^z(`1NA`Ahwm*OVto%zMmq{dIk#K>_ zon=ueBqE`&yR`-Ls;soAAT=p2To6 znIw}&hlhy7er#J?Yx9T3y0XZyTi1QOufpxDEzEu}K6&)3P~@IE1fpT+=Ir1DCl$|x z{O0Xx08zNY;iV>(=@~j_PU)-bRBM^Ac|6`FSeJ=$?^$)z{O7np4X)xCG>JOei zh+X6LDZ4BzG4um0FOhahbc&6zJ{dh0S&`PY^-lVD=e-jeDmbUDV7G+F1W!+V&uYGD z?%(z}d;aXV$c@00t_^6CHgk{fevf*oKDT`zY9%hmzxX?*Hpn5NyR)5$@Y^1h{Z!}` zlA1ui;&D{vCvx}8KlAnQOPTKQGQB)*yE+LP6IRm}hnJ`O5A#ttwB`BrE)zw7=*XBw zdD4wjTDns%9!*w}utSgat7}FotuMYSy5d6A(i@ka@JvimcldXELql72bB8+kVW1_*^s%H4YCCjsKT{w(%+|;t9hj1#?9IG<)+hB2fGz8PmL@b(m*W zwz1ZDEXr1AOj3<0tJ55?us*$a)ymvR{Z9IbR(vuFIqfm{Pha2ObExcWU0o}JjSK77 zW2e-D^@8YORs8LCL&t$X42}uXx}k&Ch@OniNd5fA8YJ~ZuG;;w=mm0x*=)y+GqC$v z34Tzd?ZxMZQa#O}rKQe%X+)s`%23sOk6 zu(ydn!~StsbyUkfF}t@Ilcr{q-wB12p}0&`H4=$bsrvi5T&}gJIAV@ZsMSfE#&^`8 zKCU~3@C#8?-K@2L_)S{ID(kLJ(uaU!jPI^oo^)eZTA)W9GKR34*|c|QV@-S1x5LB_ zLFo~80d8*Ed8CNQrD)4rR#L&1=7gaHrS|e#hkt|19SzN3Jw*y6A@igeU#-f+AjL?% zMR{Og8ED72)ncnTnghE~xU!*w_t@i}b{hE>O)q$ai65Sh@V%n4J&U6UUP zx>;0&>DFv`#$n2<4Pv~&t%X49UDEwwfO;4A#zD)`s9dDN@wP14oN)QPJQA9|OaA=T Yh^?+Pc`q~({IC!=7kB3-$3W!&0CQB_X#fBK literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/android-icon-72x72.png b/website/zznomp/static/favicon/android-icon-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..77b7f67ecbbdd81bf4266350239d75cbecede0d0 GIT binary patch literal 2165 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 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/apple-icon-114x114.png b/website/zznomp/static/favicon/apple-icon-114x114.png new file mode 100644 index 0000000000000000000000000000000000000000..e8775be75dae872bf923d482071a9d255cfffddd GIT binary patch literal 2983 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 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/apple-icon-120x120.png b/website/zznomp/static/favicon/apple-icon-120x120.png new file mode 100644 index 0000000000000000000000000000000000000000..0788e583ee1dc89014cab37e2de48eb0cf0dd53e GIT binary patch literal 3079 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 KQ1wIS$o~O-ZHwms literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/apple-icon-144x144.png b/website/zznomp/static/favicon/apple-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..f65ef9d6b38a8bc14c95c7ffc4df72972044a376 GIT binary patch literal 3752 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 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/apple-icon-180x180.png b/website/zznomp/static/favicon/apple-icon-180x180.png new file mode 100644 index 0000000000000000000000000000000000000000..ad0cc3ed8bf27c5e7d3890f9f9de4d1bcab047d3 GIT binary patch literal 4830 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 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/apple-icon-72x72.png b/website/zznomp/static/favicon/apple-icon-72x72.png new file mode 100644 index 0000000000000000000000000000000000000000..77b7f67ecbbdd81bf4266350239d75cbecede0d0 GIT binary patch literal 2165 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 NEj4}BGG*Ja{{eA8*wO$1 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/apple-icon-precomposed.png b/website/zznomp/static/favicon/apple-icon-precomposed.png new file mode 100644 index 0000000000000000000000000000000000000000..bd3545452c18778cd6fba128318bec8fea8f2051 GIT binary patch literal 5018 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 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/apple-icon.png b/website/zznomp/static/favicon/apple-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bd3545452c18778cd6fba128318bec8fea8f2051 GIT binary patch literal 5018 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 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/browserconfig.xml b/website/zznomp/static/favicon/browserconfig.xml new file mode 100644 index 0000000..6d3bc21 --- /dev/null +++ b/website/zznomp/static/favicon/browserconfig.xml @@ -0,0 +1,2 @@ + +#BB9645 \ No newline at end of file diff --git a/website/zznomp/static/favicon/favicon-16x16.png b/website/zznomp/static/favicon/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..c509e1536d0d35b106d883051b57bec24f3acb0a GIT binary patch literal 641 zcmV-{0)G98P)+LE`CGq;g5 z@Z6Q~+?BtaLBE_q$9mYlb=<>q*}iSqy=(dO=jzv%&Qvd=s5B(7Y z{{8&%=;r0q(wvr*j)H-EJURaH@agI3ycf2x+u< zhKrJ;8&(@?gMk3RLf%R%8H)i3(nRbgUqQV@#6UeRF6Ow)OC5;KZy>;!h8af>^*wG= blGJ|!v~4OtS*NN~00000NkvXXu0mjf*W6*_ literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/favicon-32x32.png b/website/zznomp/static/favicon/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..94043184760d84a4a47ea47f5598f5fb20daeb91 GIT binary patch literal 1138 zcmWks2~d+)5dK4<4fhC)!(oSXV5+o;T#8C-3k_E}CPhFP4i%vmltMXLju8@RsF6Y- z5SR?dv<@l-k(&@>xFjU-laLI#I3iaF;SOgYKz)rm5aIw65aI>Q&8c$bG2p8K=h03}p$Z@w2RKxG@ySA~%1L^HjnAtEFFs*4XOgU0C75Igz;FdTHBZ;$;bYj8OogKO%`;=gKhvcTKTo3gN+3^m)jBrTA|UL93O6j zUV-`n5dl4OMO>i}l+VEhpa9K@TDd@z3u-6(vq4+L?-P&JyGI8~)wXPZYi@g)w=z*T zKUO&dlV;fYABV8hgHI%kR4@w>J!!1%0iZL|aQkp~VQp?eE_$;fDwXqzQ_MmcmmuR{ z1@x?OTAGlS$Z3u^R`2aB4{yntn+v_`ADdPr)e0d+FkVzVSHIeq_c+^ zlQqlCgg4HPrF&Sq*SR}p`Z@;XjtIJY@2l?i52yphVVYbu%218cuPyE|eQ4?wx07e1CRwv^#(P=1JH4WTR8Jt2?^pYU_k8Us9eA z{VK{g&9`4w+#|gU)kGU{qfT0KwawA_jr1psul+CZOpDadj$lL%JQZ10SUARFT|uU# z#p=t7+Oe9H{8tp?|LTrZ_KvY*E(j-6VJYIVyv8%tM!?AC{M%yFXv`dWro$X{;9CDU} zSbDUb?;nYRGE@7QxD6Alc!Z=1XE97h+{nmoC^7AeiXEvJH%!=BcpJ@W&N<+!Tx;tW zd2bT%kedZQ=bu1U_^7lDB1Wthzs7b1H->&iwk-1gQdT|sBRb5+S`_GQm>1wtqe~E? z3ZP_LM_D`efrC~EhT#JpOKlxVrc!6Z1ziI|_0|X$VM4R^gpaQ6*Ie579lm?nXmd&k zH@C*j%0^zK8^mdcQK86AAsMgy_8UD<*eZ&>?7kUur8*;Py&o(PHmla Be_H?m literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/favicon-96x96.png b/website/zznomp/static/favicon/favicon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..6e08545c16f477c8e673e294a1fea0f9cd6ab781 GIT binary patch literal 2694 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 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/favicon.ico b/website/zznomp/static/favicon/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..077d95545d21e8380514a692eabd9d81e61543b8 GIT binary patch literal 1150 zcmaKrOH30{6oxNC;=+Vf7Oq{I7+2O8YN93vHM&t(M%}6ST8I&)i3lPQMeFz0xgn(Eo&}j=rT5A~!ZD|paN9*sIDWk0kW^(3nXTCY-p7Z~VrO+XhF*>hg z*=dZeV2rJzpe0&~uhWGwdY7>*9^!MtY2VX!wp(LPJJ`^*<>+gx`ncZ4oi#cl=S{9i zUWc2@|M*pP)#A%6w(@D$tRsKOjVe9c`S3m4ala*F&*Qdh2O7FYiN^`O4QGu`oHx6m z=y0Q;+lylB2!Er`Usz@vmzCPa#D8p2H?hsN?=rUEYtii1w8i$bH~Yt; z<@UgXN=Hye!Pb<$NzJS^6m7d}j1i9$jXk(%v?JRfsEiJ|5RU^SBYukD7rHRIYI4TBVjt8kAIahs#r*~Ixt{VQKr zt=qgwW$=mpCq75t2YcYVI0Io0k=c3io(oMw#rdiKeqsK?{5&*2`RbdEOEPQU6-xR! zK>Ewp_CjGAKtcNuin}~0wR}Sb%}|)%f_|b(XGn41J(;qg-{qv=I_iIv^p7K?|6@8E z&LrsP%3u9N%elavDn~F~&@an$D*1Ok@m0rlHY@3WjQs1*>lp4K|5g-PeDdPYd}^Y9-Afs3O=YYgCFytneGtAC H7=ir_({IrI literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/manifest.json b/website/zznomp/static/favicon/manifest.json new file mode 100644 index 0000000..f9c3317 --- /dev/null +++ b/website/zznomp/static/favicon/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "App", + "icons": [ + { + "src": "\/static\/favicon\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/static\/favicon\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/static\/favicon\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/static\/favicon\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/static\/favicon\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/static\/favicon\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} \ No newline at end of file diff --git a/website/zznomp/static/favicon/ms-icon-144x144.png b/website/zznomp/static/favicon/ms-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..f65ef9d6b38a8bc14c95c7ffc4df72972044a376 GIT binary patch literal 3752 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 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/ms-icon-310x310.png b/website/zznomp/static/favicon/ms-icon-310x310.png new file mode 100644 index 0000000000000000000000000000000000000000..a4873c9f94e450332e5d7446af8fe9846f0781e3 GIT binary patch literal 9479 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 literal 0 HcmV?d00001 diff --git a/website/zznomp/static/favicon/ms-icon-70x70.png b/website/zznomp/static/favicon/ms-icon-70x70.png new file mode 100644 index 0000000000000000000000000000000000000000..093cf65be4ee49c3c14074fe953d670fe0b4d48e GIT binary patch literal 2174 zcmW+$2{_bi7avPEOI%V&TGW@NZn8vFkF6oHG?+*s4YG?X;)-nX*>`3vA>opeeHq3~ z%-GFj#+bp32HBUfjV*j{-}Ai7Ip_WV&iS3+`#%3znAv?H0Vx3p1R`W)2(Fx*BF^#%n!w|$1@sI zR2oxNfzgz%wnR&6OjW_=>9yr(0e6NN2~ce)t?#wZ8q;o0^@jGATg(un`aeIWG&wKR zlECQ#C63bQ#Oe+rl$y>B#ehPqW9bda%Cn?*6NJ~m9mDw$KAJS8s?srD7?d{12}&?K z{kuv{LD5-a)Q_$pY`z{y3xLB-&W$Om&1q^Nh|azPPHAX&P=e9v-(3cqC&z-E%^4c? z$;u!IKEM^~|89+*GEikRit(Bt1ky3y?D5Rb4@N7aX`~u^&>a}08oTNKFwoIxyEkwF z1e2pR-0T7(fXrZ(&EjyvZ|0-vfWsm+5x~349+IkUTe5Ed9E`+&G-maNOb>(u1Ei%i zz33^oAU8Onvu^iQT6Yu~(po)QGBwzYOjb|G3O%(cO>L+i!R!pczJ~%zEm@l1Yn}nS zAw`ve^E)~^0=j`b060&HTcjp1@%~h_D^LK`YR*t2)!MI)W#Ee+uzKE%fAbr|`Qi%n z=e|cz_Jz{hy=fS)o^tq)?%*F?fk2IsRu63cz3~peQLGQ>s69`Y+~|bK(E)eSiqZm< z0PU&%w`k;DpkDXC=Aa{RcR)kHu#kBWpv>XH9(W9M^!oknm4kiG zJgsQ$XZ!xn>edRKL5Lpj4By$D_Da52exh*Y3vpEPi#e zd3mB{aja~fnmb2HXAPuJ5Z;V;1X5cA=Bdz^)hg}#;Pu31|3>~I02 zJ9%m_aTNE8*5)zP;5OYA?Fim|>?;d1O9&6&G2ufO{>x(QFbNKGpzi9qy^RfWPf(zz zlcMbQ_U7u`)D&ZcOd23GR%a$BC&k7_MTGgiba%Effof~2Ts(JD`0&@>?)v%~duDo) zNhbB_u1L;kzw9$R*&H3ChF?fr4RPE)>f7l$b)@&TxD5VesD zGvoW(num8QUqc|gUyY!;@W&mWX)ce+I+DlPo$e)%Psu5c2d}nmGylJQiqPZo5 z=xe%)i(HlL$Zls;@Di%lYvg3+0{X&N7o8;!5rJ9<$7V@6^i}8H1a-;%lupR~G|qNZ zyz()}))FY8oSvg%Ss@NZoWL*8wlA*gFeC2XFePmCOMgBa?prfEB~W%>1Z89f!-&A9 z@m)ksC?P3cHFB{@45@?PcIC4Brdr24^X-IXre+MIPX!kq-t)cgzp~ei44sym0-eWW ziPP$m(+ z6@BI?>GW4_>nqAy&k{{+5pX!gBjwMF+M#n*tg#ykBgxphdWC#3R1iYC@0#b?i5=&0 z!j59rgZdVv$t6d$l=QOxb4q`iJU{+e@vwdc@545}gtvC5&Wt8S$Cf&5(jlTc2?t6} zut(x1gQ{$v{<>;isRTzH^j~?D5l_nb=Ty}OTPM+T#YSe1z3_^N{-PHd{O+iPW8|c` zU1VWaupv@4KGj`GY+v8*N*RQ&Y8 zFB=#vrJ&%(I){26DmW*rCgD<;Tco6}HH4HDNi-14_Fnji3Wdd@VJgunlhsElYjFVj#b^Nc_VF`o3^@kmCFlmW6wo;u3>jt%CuMFA71#3U)nRs ztD7-af{`r+SQGdeBRv&I;_;DN1E`Zx9p)i%M5p!0M_RMQ3*^eG6C9G3~fI^ z2~ns=Jl0r5;`QLtI6*;63yUiW$mMIPZ&}N7c|I53acv?D`enYMpZnymAGE!9zW1h- zlM6flVm<6=ZPT?^zbFQFi~46#slUQ`c&qnc1+{g|uWtU}^E z(m+^APy54O?bB`+QRhR}xxG3mz@sL(O+C5b-WR`j~k4GA1cI1-wgUi&mrP}f99>o literal 0 HcmV?d00001 diff --git a/website/zznomp/static/payments.js b/website/zznomp/static/payments.js new file mode 100644 index 0000000..0cad5b2 --- /dev/null +++ b/website/zznomp/static/payments.js @@ -0,0 +1,84 @@ +$(function() { + initStatData(); + + statsSource.addEventListener('message', function (e) { + if (document.querySelector('#pagePayments') !== null) { + var stats = JSON.parse(e.data); + + for (var f = 0; f < poolKeys.length; f++) { + var pool = poolKeys[f]; + + for (var i = 0; i < stats.pools[pool].payments.length; i++) { + var paymentstat = stats.pools[pool].payments[i]; + + var existingRow = document.querySelector('#payment' + pool + paymentstat.time); + + if (existingRow == null) { + clearInterval(nextPaymentTimer); + paymentTimerOn = false; + + //Add new + var insertPaymentTr = document.createElement('tr'); + insertPaymentTr.id = 'payment' + pool + paymentstat.time; + insertPaymentTr.setAttribute('class', 'dynamicallyInserted'); + insertPaymentTr.style.opacity = 0; + insertPaymentTr.style.transition = 'opacity 1s ease-in'; + + if (typeof paymentstat.txid !== 'undefined') { + var explorerlink = '' + paymentstat.blocks + ''; + } else { + var explorerlink = '' + paymentstat.blocks + ''; + } + + insertPaymentTr.innerHTML = ''; + insertPaymentTr.innerHTML += ''; + insertPaymentTr.innerHTML += ''; + insertPaymentTr.innerHTML += ''; + insertPaymentTr.innerHTML += ''; + + var paymentTable = document.querySelector('#paymentTable' + pool + ' tbody'); + if (paymentTable != null) { + paymentTable.insertBefore(insertPaymentTr, paymentTable.firstChild); + setTimeout(() => { + document.querySelectorAll('.dynamicallyInserted').forEach(function(newPayment) { + newPayment.style.opacity = 1; + }); + }, 25); + console.log('Added new payment!'); + } + } else { + //Update existing (txid) for private chains + if (typeof paymentstat.txid !== 'undefined' && (String(stats.pools[pool].name).startsWith("pirate") || String(stats.pools[pool].name).startsWith("arrr")) ) { + var explorer = 'https://explorer.pirate.black/tx/'; + var paymentblock = document.querySelector('#payment' + pool + paymentstat.time + ' .paymentblocks a'); + + paymentblock.setAttribute('href', explorer + paymentstat.txid); + paymentblock.setAttribute('target', '_blank'); + paymentblock.setAttribute('rel', 'noopener noreferrer'); + } + } + } + + //Global var from main.js - cleared on initStatData(), this needs to be started after the loop in case a new payment was added and old timer needs to be reset + if (!paymentTimerOn) { + nextPaymentTimer = setInterval(function() { + var timeElement = document.querySelector('#statsNextPayment' + pool); + if (timeElement !== null) { + var timeleft=(paymentInterval-parseInt((new Date().getTime() - parseInt(stats.pools[pool].payments[0].time))/1000)); + if (timeleft > 0) { + timeElement.innerHTML = timeTil(timeleft); + timeElement.setAttribute('title', timeTilNumbers(timeleft)); + } else { + timeElement.innerHTML = 'Now'; + timeElement.setAttribute('title', '00:00:00'); + } + } + }, 1000); + paymentTimerOn = true; + } + } + } + }); +}); \ No newline at end of file diff --git a/website/zznomp/static/pirate128.png b/website/zznomp/static/pirate128.png new file mode 100644 index 0000000000000000000000000000000000000000..568d0545b1939603dbd336d743e7b2fc96927ee3 GIT binary patch literal 2629 zcmV-L3cB@)P)C0008(z|$-Indyk?-1)zL`J1nm)dpKknL+x|KQc-Ing#lhLzZx|KP$kTUSxmBOAy z;m3OA&VtpqX19?v)3agMxM%9ri@KFK-oC%bn)QiZcQ0dc(#G^{gtysdKM%B4yznnqe#do%l zGSRYM?ADITsZz+NPq&dXxRErtk~QbihRCN+xs*1~uv^%>YV6jI*12cTuUof}GVa-t zwU036%Yfd+dD*;d%d1u4$b7btGP#sD=+uh2lQ-GDZ1LTg)3adf*^juBG`f{J?bwjL znLgXVa>=Pv#-&Z@(TL>Df!x7!#G*>;)r``#V#1$Bx|BG!k22lEb@JYr=FNl8uw1~N zM7NPN?%R~{-I)LX|LfL_+`@C#x@f+dKC=hCqDku1is8w8 z!l6gt$9dYnZ`i(V-osZ!(2f9=?hyqP`l z-IeXxkmt~ayO%rU&4Id=Ik}WK%d1wvy4y=>OI zX}6Ix-Nbg&*Q*pK7PfacJJwvaOB&xF#oV$rls)U5pa_3_=7{rvgk%!Bmn*5}ll?c>Gy_3Giuh1tGvy>`yAWBmH}`}yvJm(8wS`S$Mi@ZjUo zq2|$&Nvu4nt&Z^Xt>{>eB7rvFX{Y z;LVuZ#fRtDqvzC`-N%mG#ERI$gQrf>G5`Poesoe!Qvd=53lj(>8aEXUjz=sT{rUOw z@V<$6Q!pPK`SkGW=iu7S!@iq&byG(`KKb|H+}POAys)aGkB)k2P&YIE`uh0x_2}Z^ z+}YR8&c?T~sHdi+p_`bOlYoD8YhqztQAkBSC?z8f`tqiff$S#x6Dy2V1qRjpB~tS1Ykk4u@JtwVi$e2%VPf5ZwneB9qZSgEWq zxlUOQNEgPnc45t?O&d1Y18m%=P$;VQ^8}J4U+tzUttJ!&2ss@P(6V19+SS=I?ZR~` zT!1=IU7`U)bJW!xe^E~a2=w!tG?1lLzV^1DAaa1;c`qsiwr-J8zWjh=0AJsd8N|=~dQFx)4p`w;PVAyreC0tJfE6oBiW-dNo2{e- zIJBy=8+rYCt5?$ltZGd98rb3|sR9-)>dO$l{uZZb0~U265ab=ZnKnSkRP6cantihr zfGyQ91$nYBkp_S%$e4YJRDd%$0#~8FWPt77408Mz*dZlgdw10QFS0{gz^+_yK$ksI z19p{z?*4nE2jq8yZ2zNW04!_6+8+RW)!Jj|`e)*`UN@ai= z3$WAL$?58iQW9V=0+4zLMEx|q6E;MX z$!Gn2A-B!BckkZayLS&C-l!k}WOYvj%tQb#r>y@~qru;f)sauG+65%P1NIyNAm$zZ zc|a&{Fv0-EEP#w8fNNS@K**~n!oP^GN_VFi%8^S5FK)3Xr%KwWkkI-1;Dt zM+0&u41r6u0ZL1GG{76JTy;w{j*x7=>&_ zX99#RdDJCm0;&j;z^Q#{oQw4I}B0D8CZ`79s)U zEgEGM0bnG^Oc@Xy{DCJLgnftsns+9X>F816NPfh8A{TO3$isvv6fd9iB!CQH5FtRT z`C&BJkIjEpkPA^pB7jQ!DS{`-b3fEl>_Pz0seV4=$@0w)wHdM40Dbry;zo(#r7sjv z$=n;j16?K( zvF~|NdHmTI0dNxl8Igd$ytu?fsu6%}tN`H9yP?S6AF1Ar09aaett0^$zFbxBMge+T znuJmSp1%x1wP=Ktvoz^Q0EP&7Vq#(BNEg8T% z1yBrFQ_~rM+$jLAP5=~SK#H`NACN2c-5uEh`P2Lby{O!PoN2EwQS1?+0oDg#O$R){ zCrW??wm0ao08v^xfI=*=NoF*__&%NzU!WE|rD9HfAFm)*c8rK*1nGG#KWp^Md+;lpCISde+!A%?ocr^qLgzM}e;A}}2 zIF`Iq8i@y-?c@R+PoB0S0e&SQgO7~RP6QyZ2FrhVv*} ns!oq?-Fnn1)qmJ1(ZBmYxOdgPuc%3900000NkvXXu0mjfbhuBs literal 0 HcmV?d00001 diff --git a/website/zznomp/static/saplingbonus.txt b/website/zznomp/static/saplingbonus.txt new file mode 100644 index 0000000..cac6402 --- /dev/null +++ b/website/zznomp/static/saplingbonus.txt @@ -0,0 +1,110 @@ +zs17wqdk4r98ghjpx890gq5k4ymjjx4hasuq26r3xc6u45jv344hpz4726r8cumqnru35fr6tz5wxu +zs18yzxwh5slp8n3fl8rcx0aazqruuqglyaquw9ysygzh6vtx2wzjrfyv5kjm0y444wp7hwwshsuk9 +zs12fcy88l2mchyh29rqstry3jqt4yxlqp5lt7ct4ddzrlct73l7g7cec8srguup5kndr7n6qwq5km +zs19842nrx4486zutgwen2qzlet37azzdtxakumq2y7eta8qsughtcx3tv0r5fdh4jzh8n7226asx0 +zs18xa3qzr7vhzsyk2pwppnd9lsv63fyvnhrdjm69y6j9q5gdnepa770s7gph40kejrsyfy68j8htf +zs1w8veq59sqrqxmhsclaz3zgwm7uzdy0hqptqze720sjt7u6hat2dsqk2cce29xvhdwm98qs6sk2z +zs1zahnskyy9shagxlf0js8mmptac55t7duz02hczpdvf0prllef56gcxyl0x92xpr9llktu8h7z7q +zs1zeuyy70vxzxk39fwrm20cp973k483elpym339vxmhwqwuacf700wncqln97awrzxpdsrg45zlr2 +zs1ncyhf5fuhess8l3kxzxqjc3harzmxamq97dky4rkcqk7yf4m43tanrj8y43y2glg7etss3myt8w +zs1esq8rwkhwkeylsj07hfsfpqfdt68n7s08n62lpwrs0e2xfq72a60m0pn0vssfy6uqru6wlm56n4 +zs1z2t63xvsnucr4kjqm05fzt4vfq6mcz8sx9jwd9a6vqffjy6wddtarvjlya8vg05w9lfnkjvjx0z +zs1sul7ee3j952lx02cf2d4yf4u3tenz2f0n6wpsykfyd8e88mhvzawakmvjjqqpkq68vxd5ymwsj9 +zs1qgdgpf8jd435wwhfet7gn86ppflhhl2udtg07plkr0ewj374ecte5f8y6uvcp5udc0pzcftzjwm +zs1kyyygxnadu606fw5aps29fs2mgunjcczyaexqre66mhu86zcjap84x9yuejx4wkfupzr7kk0mgc +zs1r27lw44juseep0zv5l6h4syy72sypt8mczs8syek80wvmtw34w6u2r8p506kveas2qzsxw96h88 +zs1dh6j9u650e57kgl07uz9g049legqh9ns4kq938agsql4ynfpghv9rvr5qpl9v6nclyezk473fnn +zs1jpjapnkzlpm96nle6ns2xrlun5xr7r4r8pxuvdl57rt9ramwmxs8lsctxku3rsqgym3evd898mg +zs1yp6umf3w56qqzkujx8tuwuyszy3a96wz5j5ark5xh3tneyuu58wem2q5t2vcxkuy9aj6zmfzvyq +zs1qfgj94fjcflhag5vhqlnh7gwmppjk59lvsz7z8kefj42apl6873y0r8kptdfhe2tmys9xtv7e72 +zs1ffyd23d0wnfyn9322qahvg0569celx4mjut53cxefu9a6tmqn70wmmwrvqasgw9asj4gzn6mln5 +zs15x6nwqnvyh08td34swach9fcn5dmvwypwrf6v96433cvtcnyd7ny84hmqw77zqtukcgzk2pv0x5 +zs1g0lz09y2uup5r9ydk2jvktu4nrvyw2rlrl7sdpy60jv92ml5ehdm0qrf20a6zc2x98tzxe4t65m +zs1l928xv2zhemzsa9tuk9szqwy7un09eu6he2uxyngr323gme8azcrtptju02tpmadqpeavr7qyh6 +zs1jmt0nl4xu30a6tp7vpewaef5k5shcah4xp4rhkaudvtafd4qkeadf4kxyym52hck3t5tumz78a5 +zs1hnm8c0d7cvyk30pae0qmsmy8hwfkfhy6tjxn2zsenseg3qw6fr3tw94508lranzpugw4yasuezz +zs1cf4ctrjf2fquwysmcmhfgyntc007m5maxq7z0l2yzqqft99r2wcst9tknz6gjurrz994vjpc7gc +zs1u9ugqh82vskn487mvvay72jrlwge3z3upgsexmn6n7jj2u8y3t5z4nxdvgvm8ca6am0zvnld5km +zs1j7detvuzfqvpynl4lgky482vgxa2rarnkn8unady5qaejlxmj5jqqjtnjzvvdrnecauzcssyp8x +zs174d39jvd25xl5dlkk43lp3sy5jsp8r3gn635jzznh4k7g7uz465pskgrdu7f3uzldvxuw9k2esc +zs1fxw03nk0crlrawtek22ze66prr96rn0ulp36rwt9k002md8ntaf6mnpkj5cy2wwnzqssuprtapw +zs1s52kht9ylde8jzc92tkpa2km7gzjjxk08sfukp5xf39w765p32wjlzhn7pgvy6ssuxdfus40clc +zs1x9a4tmy7z0qsyk7cdfwk4p7xq0ygquh0whg6h8ewq9ewjjxavt49dsn0rgq70rrucr855y63qra +zs1fl98f9k5ltlf290ellxsjcnaflueew25agqnz8qrsr6zd9zf2rlayg58t036lkm4xx747yldc2w +zs1psyhv3acjcx02r330jnyukfgd7cfp5tzf39a6dxceprez4e0lfj5a98jsl4jjd32453fycsy52e +zs1zfexz0tm3dvugr7xxdcnpnw60pw9atmf7egr4pfjl50kvdwlf24k7nscn6k9ls6yl7ay522essr +zs10awymy4g3jqcux3r37skylp3el7w4dpthhhavvy0t5ukj5ek5fz7eyg3ctcvq0epccq9q87xyag +zs1hwhpzax5aa5xlf8f0wj3apyz43p7smwgxm8fwln7y2c5209dlt3fve9yf90d3gt0wcrkzqrcqh9 +zs1gp9egrus6zrjqmea23nae7pzpxdy9jt3w65j8netsrcctl3g9e0lrag4tgvctw3r7rhryj4f4ua +zs18c0pvr7qnh6klsl47fjlr92l2q3u93wlpw5qakgqjxa9ldfu38uu0ttme3rk3f9kleg77ldu7et +zs1g45rwagj5cpz6hu8pcagn568c9ekftgltnh4fcm8zldaa0xg9h0e7qc8rfggecm58qxfydj0dnm +zs16ktygc5v8205j5yzl6p3llqplqazcp35eg3mmpcnaz6qfwys6r3fua48gt6p2ar7egztcz8jj2y +zs1ssgtajn0ys2fh49pju63dtkge57mxatlpnp6jr2aqchj6y6g4xlnxyux2qhnj7grhcrtkqw34t9 +zs153kk8e6py3425j6haej2aad687d36agzyjwuh3sg0dplv7766v7m4g0z7tdqxkj5wz25qtmkd72 +zs1a00yx0aeky45tcq65uvemc0wem8amydelkftz0cjgql4r33ajf8fxvg374vgpvms2mqe7k9pw03 +zs149209gd7a9s7sx8v8vyt3vj8me8rdhsw4ptm02ygfktdwfp5qn3wny06t6tq4e43rxm7cfteh7j +zs1vdpfqj34lfxk9hzu3hf0mr7ztna0ncg329uys32hd2jyfkljqkryw2xxg4c8ae77d60uj7djvv6 +zs184qhg0nnv4t0xaahpfdtj96nrnm9pyqyjv5rkhzekzx4un5xs45fr327wzekcd2zkw8fqa0ntn9 +zs10qqejnqfjy90fk73aggehn9marygwx9f8hn25p2eruettrkq5hl8wy62dy3nr74jtal6wrat5pt +zs19lu05fty7h5cvt3kyq72wy44vf3khdmpdpfuvs7a5epud4573ellcq38tt6n689e6pw422evgts +zs157xlqh77us9wk6ku2zd94r94z6d30qp3m99qyr4pm0xd4ml3yh5chu70u7z0d33yjs7njylgkur +zs1w9n48xpe8x3j6aak7y4rxl2amtej09qnck67s2ypge0ul5h4tdsplrcsp0ppmy6ap0d8zxku6qt +zs18xpg7gt0zdw6pfp9ecsrfs267jz67s2st7acpcgkgq0dhyff3rcugs462wt3psr5dm2fw0lk4gn +zs1gn9kd8mpxaqjnk64u42kx5l7s6w5ldgpkj4rraf5zrrz5whpkpyfhevt4m46kvjwc20myqjawhf +zs1x5gal2u8ckl2s5nlchs3rthxs659n969tlj0v4xedpyznjy37jpnfmxkz7krz0vtm85qzqydr4y +zs1c64ck2cv8nz5c5edgg50fxzrhs6d9sm8ggtl8kt0qjtp7hf4z3wyavghsc9yrcfyfepkqeshg9v +zs1mxdg5jjrzsm755vpxhhmz8uls08v3wgacmw25xkzjplsr6qp06dc2ml8rzxvga9ej8rczmjqafd +zs12y2v99kcpnv44005e6mhdwle8rsc74z46k304zae72ptuzh80m4s5kpmydq05wytuq5cy2dpmnk +zs1g0h2t2eju3qc6sc4ay4pycmej9ytqsw2cnyc5zrn3plnhdlhp89vu9n08zgqzt87kaljvqwka79 +zs14ap9w290hm9f8zhgg32qzctnkhgcx969ssr6al8267zplzvufmdl395thuzcwljeylmf5fyyhc2 +zs1jw7nup6xf354y3y3nqlqsjfm0fphd4nsh3ezzqq2rycw5ltv4ht0zfj3v8h6mwa9gzdr633ycle +zs1c83zjak7ealmn92hejmqmjc7h3ysvglc9n95z79dhajth4fmhmrnv5zxdkufzg6l489y6hwf694 +zs1mg6tql5vpw56dqmpmy7fyukcm8zhvvsuefwx6l6fktavt45ndshrmvxaas72h95tz0rs7y90ry3 +zs12l75v3x4r9nrng46qe7mvke28m3ee6y5x8kf8836sw4nvtr6sphqq48j626g6kk2n50a5kvn04a +zs1nqwj7exawhvke96q96ykjzvh8p6yvndxhh3f3wmllzmzww0lef2cauptj53lv9nlw0sggmu2l23 +zs12gkk0lx6n290fsmgzanqr6dujkwm7mr92eaymj279952zkryp9399jpg2r8smpdl8jkdskugqpn +zs1d9eny43whhr4ukl97v7wadjfacrnmfxym4kn77gnjtw6lwa0fkerw4m3lw8dpdzywd8ewg6lf5v +zs1clfr7hxg9auqh30lnaz6nnna30sxlwtg22tysarc09mgkh2kpdl8693vgts6zyv5vszkw2lvvwm +zs1zudwjzpg9l632dnk5pf3j8t6a5qd89r6l7jma5tm564agg3fw2euq4zmecs6nz0ypmv7kjlr4wp +zs16thr6u53rg7zeaqxkcdf5xx9hlu3j5a88z0vhyt94acc99dcz5vjth04f6ptd8fsfsnnsph7fjs +zs10kpqezkszxcj3kr3auwu6lwtj9kf6e0ddrtm7ynn0d8m6eyvf92tgd0y88utkz3v9pahz5n8dkl +zs1zvwetgw3f4gkeg7w5590uuqrwtv8n7l9qy4ktpnyryf3tahqae6yqp3l6d3jcktunfcp6nk88zd +zs1ylaqrlgs2gzsq8avw469w5n8m5t68tqtvmjrrs7r2dpgu5404nea6gv7cja0tsc7cz5txkl9he2 +zs1v2f0ej6gz9l9rsy5h2sln5dfn74p7mrmc0w55k68xvvyuawzay43jel2p6lwjp0ugyhpqch0dpx +zs1772hy9g0hjlkftfafx8tmatzj7hry5ps9hzjdyqsv4r686n7cra3q2w3j7xxtw3nunsnzgnw9y2 +zs1mwnecpjnns6mfcmquscwt9aj6payrflrpqah79pjtvk6jnnhvn79jkk7cm23xs53wljxkcteksm +zs1945pnqch4v4q29vam620cu63we578ev06q4ayzu38t6d2ekslqftje762ze9aky3uem9j6uhwk5 +zs1z658lkdqf3kxay9azn0asqxfek07ww5qywvnvmk0m5s30px9ga7ap3gdsaup8uytuaec6pff4tm +zs13d9w3qc07w29xk8ca4u9h6kuxhayj5p6rv5zzwcjaskex5rjz2vs8cquaf7rw3yyn0snx4dwqw8 +zs1car6wyk4qp2577x66kwt77nd7rxfjjm67394u8ev7gqqpmx6uw7r6yexdfhjf8jj9t6e6udqmak +zs1n3ye9sgq7zpc3vzg9y3e40d05pfhtnac6ehxgx0lch5wxtdf0acv8pfvxd6qhknaxcajcqemwmn +zs15glz3qua3q04y5hkdlkvt3f0qc824usnehf64930e04gxzy07f2t9ch03tjdhau7pwf77spe2hd +zs1ws5vj06cm0zn95lqfjuf55ca6t2mschj24vslzzdt5f7w2h7404d47p90ejka7v2e87nukr2wkc +zs1r6xlrv89nn4eye8hdj02gz8398r9plc24aydd6rzzcpm3gqtg6adgpf20g7cfnaz8844q6f6t80 +zs1f23g7fete52k8wx02mxp8nl69xsfav7nu8yjlh993gwxez8apqczhzmy8xav4dcuupdycw9wz8q +zs1htd35q3hd8jxyuf59av8pg5wzuq2qt78w55wc6d4txwdwpdw9n8y7cyt63kz5ztj4nww76k427t +zs1ajezmxjdjktmkuhn5stz33nx7h7k833mvj80jkflch7qa4z5xxwxq4aq8ny4rrj9gt27wk9khp5 +zs1tp28l7q2ulpjuwslqzdwske4m49hv9ccld8mzhrcxqxttug3aakcqxlaw2rpeshajcr6k9mhu4k +zs1g6y5xy0lzrsd3t2xqen7zk5jt65q5a88grnjcgfvtmhmtausd6q6ll6a93s4wcr3226rg5xz0t7 +zs1c8068egd022j4q7hnn4h5zppntrhq6fxeyqampk2tmxumngjgddtls5z4sk5ec78kjpxwq8j6d9 +zs199886yxnqfrdkykga4u00t62e4g4c4uwnepd30vttuumd7zvn5sp09f333tnwe4trrxmkum2m97 +zs1g0p233t7hkufu2nrd2dzkvvmedr4pfl3v0juekd4k48sqej7m7lt03ddthnrehq3ugnqgqezfmw +zs18l8zl0peqr9stt9lv9thcu3grwrqyv46w3kc0nyujacmv0vc7gzuaz9dvpj3t3ujvgqzc4u0f9s +zs1sg0yz4px9ys7jsgpr365fs8w5xuh5dxqvrq77fkajylykly9aaqy2q98n8c465q0m3k35rh8daa +zs1g83322uddtrxmqt7j5qsae7t9muwmeyyzrcvm29su9dh44c2r8ztezep7uaa40mt9xprkv5k6qf +zs1jlakr2558panqn24me9umymmrj4z0fe2fp8kv5tzkf546dce6uptmrme8fv5qxys6p8ju0urn5d +zs187ua8g9yxhjrfklntdud424ggfkp5pahpnr5h382z7gsfkvee8l22tt24z57q3hkzjnryf0d2la +zs1kpcx7qeef79sunr383l57dfqqq67zhgdj9msyw8sw9zxgq3qec4hjdkfc0feurq96p0nvxmpzrp +zs1zryna6t2kys30gl507h4dmnrm747ddt64u6v8569njjy3ve433hgxduscwe32sm4zz2264mrzrj +zs1etqdw89gwr4qm4nsxnxg0tlhrux9e455evhsf9hw092rmtygl2cgxpdh67tj2wmc3yav2g2uxc2 +zs1s0y5ye6qq59lvmkv9ah2l4f2ykwggx2gldz4ffngll0tk62eq5645nt8akw4c9y93ckjuzmtksj +zs1k6v4g6fekqwfn9uspeqczs8vkrwxrtgmrdqcvruwq9qg3r00ktuxepngch2hq7573pxd26wcwy4 +zs1r6d3u6twk4esrfgajxjyp3madq0nwzr5akg7hpj9lq2wy4wdlqy000e0j59v077wjhv96l0msqg +zs15g0xcd04nl83css5u4pq48j9w57gm0ehdr9932k97lasc7779hxydu6mllw0v5kyurdmszgplwx +zs1ltsv4arjssxgdt46erlcnuj8fcsk9tzec0d6j7ewdkur9ulnuxh7kdvjl4zfqgg3ztamur7rz2e +zs1xtuuxj9d2cqxyprf7plkxjyq6yf32x3tjzj54xc9lyewn7s0mapav9gxyns3jvkv7qjhzdfyy0y +zs14gufhmuf9an0wq9sgf86v2rlcmuttpyk2wtn8nrlr92n8x42f8870lsfv0naurrkfx4pzw48dmt +zs1hysn5370ea9pdah7wlwxvjvhjchpfyzvcqlur92ff8te6wwlr55vkg99wsqth3vylkpgg7msecv +zs1tu6yvsjwc7ldcfszah5mlhvdexu308p5vyyenl7zqfqnxfkvz5uqz0207c0pv5eusnnmxpckmnk +zs1q5zatmzhxdvwg0zwyrll4ch87ajjmy2vgap7m4c7qcxfunr4hx68trd66dhe997fgerm2nxpejp +zs1ky7nd603h56y87zmhn00jrks8ucllu2gfhpu0ctkhvu8wprpucs84pwsyhjvwzax90ka5plf5pk \ No newline at end of file diff --git a/website/zznomp/static/sproutfinal.txt b/website/zznomp/static/sproutfinal.txt new file mode 100644 index 0000000..b60b203 --- /dev/null +++ b/website/zznomp/static/sproutfinal.txt @@ -0,0 +1,820 @@ +1-53 48ef9c4600406ca037a7b6c18ea7fcb23c01bb408de4f2fb8d2ef7c5107c07e8 +54-106 a07aac4f06e84ad966669b6e014a147d08b128229b843a17a88b3f180287de88 +107-156 d3ec25de2f13877208bfd2baa19d9aef2bd46f5723aab350d11ae8ec57d8c2f6 +157-206 c66047200d6d04669992987f4af7cdc11552a93f9cb8d550e60fd2c77a5a8eb9 +207-256 54e26fcd36691457a2c1026ebedc509ae41fa3538799456e3b79f03191f36979 +257-306 07db936212cfb777fc05ee6cb0be68b2c4a56b51ba91d832a483372afa3bbf6a +307-356 d87c3b0aa1d4918762311133b4d279c062b93cc2f0aac4b40cc94c3bd8eba1ad +357-406 9f06be5638ce583288ba3e9a098edaa20c09c234108f1b08fdf5adff6c6d91e7 +407-456 bd252fcb1e069ccdbadbcaf930ff643e54f316f58d0e4868e0481c7584b9d908 +457-506 5bb9d1aeffc629889764f8e6456bf9333cf64fb82154270dc14325184203874f +507-556 9e3df96d1c7059a15d95646688a875a483314d905776cc502fc438a484857311 +557-605 d34c8113bd8a2caacdacb5e9c1b3362e75855731a5516a81021bbbbef1fb2931 +606-654 541cdc371f1a943a84a75170fd140dec01f1ef869d7fe3665e93f12d395fc127 +655-703 17e391559746fe18d786f1e1b2105e32621cb995f4fb3ef1738544182768c570 +704-752 75f10bdf5f78c94e32d0c599f183abe62cb4792031ee4eaa592365b240dd7d8b +753-801 e33ee1257c53b36a0bbe8292126fad9b93d34a7cc11e7a0654c7348130866bf6 + +zcWBRP14gX57BfSqWTZr2a1oW5TX2zZpWAjCDfvZTaLfcXxeMfpaJDzHgQHx31hB9YXwUxgQxwDtz6nHRCBE1hP2eUAuGKi 255.67822211 +zcPyvbZw5siorG13kNeW7LhZQDNzokPFDo719sU4yUndgue2i1zcUM7A4coP9pDcctweWh47uvSMrtBVVyQQSKYk2EkkaSv 254.76023520 +zcB3P8YeLUkP7tQgtArQxntpnMiwvXAbqAeUfweHfv2mocrj7PvSj4oaSB4uRKaQfrDCCkg96cDqma9pGigLfouiidqiX83 251.28694844 +zc8N33Nb2gDP1GcnRbCrviZ2b2NXp5ZRMht87KFLXr6Ss5vTmkif3iTqs5Tsokzb3K2iQK3GXk6dZtjLABXuhoDTtrahJS6 250.65490285 +zcWxKE3rAcWA8iojUbe6qzzN9kz7jthMhDUhrEYWcvVd1HDE1aMvtTmkHGT7JWMnRU2pwiQA7ggMxuboSKA7irdH7DZmYJT 250.63112132 +zcMZzTTTTVjdRRHAWumHUZ1NvZFVyfti1LZWQ5MNFdnav7dLpepDj965Pks3G996eTFxGFrizz4RvULPSg9jC5WjuyscVhE 246.20989535 +zcHGJLiiLZsk3BaU9wBcnKuhCobS42N8VYup1KGRuUybUCcZ4QPYN8Hn2F423TBnmJv4qTs1wBSnB3BSheyPHRtk49oycqw 245.43206113 +zcXoxqAbfcoRrfVcVoxnyRPQYeQp9NcH7hBbyRZ4bNpVzkhLMXstiuaZL65hhQESySPDqKGESPFx6zPNjBaVFgV9L4ctaXE 243.26652371 +zcTfEmKR7EuJJ5Rhedt8rDpRvaED3CaoiR3N2nqXdx3KKP1wdKry6bNyZvoJ2Qv1SqmrWjDFf5B1qCBRKBvZU211SBzEiQf 243.13864871 +zcepxVvSbJMgY8xUHta6KZNAda3E2fX2rdKUYYUicbMXbdKGCVkRobjehuzCGaa2n4k9jx4LXYSPxRcrs3iHbfmNckfVmw2 242.65490410 +zccLxK8FNzdpJAHt8JLR5ELvGeALrenSYHsvAaz2SdW3g8m8cyUb1TBz7qCeckgZR2H1ZXuhB7JXzUn4Wg8FZEkaG823x9P 242.29883698 +zcBMvuqmL4oUPAjUdqnkeuGqqf8VieeUxnXjaZXUVz4emNqw3VS55FambHtGYauUJbnmk2C8gtBqJmQRyU5GyAhLAnjk3MD 239.70607158 +zcPbG5U9cA5YFFtT55U3g2daDsvP6sYmLn6RVSBMMHHPW7r91d2ChLe3K5UB4CEAzAUt1ZqbC8D6TRitdbwe6nqN7djVdka 238.71541641 +zcX5Awx5MFoNf1wHGJ55YXZx6f2mfQowTEJRgAMVfaEYn53JqeLeMExiNEBZ8dGWvCjuf5Z7Wd8bd4V9BoXkTRT8oUSmNui 238.29833230 +zca2B1nFPQjrZE1aZbgfk7Ju4HDQJxEYHunQTcv5gPQYhA8TQucQVMmWecHbdWYLFUeqrhSgRCbTviXN9ZNLWyCeQiE1u8r 236.48549598 +zcBDzVz4TxBcRhPsnnLCvbypDjmYinyBi9wi4Q3ZppMjoeqtc7juyjaoUbZfEffVvp1KpqUYwy9Bgs3yunRQzDo8FfGmmib 235.77658461 +zcHkmfBQpqMnTfc5ERNkS2X8Mf9oxLgE5VAPqQ1SMJMiVUYD21MUtrgvf5NaWcc1W4KN6LXYvRmS7M2UcdrXrcbpTDfUc6C 234.86543989 +zcQNvQU3r8kW3ovNe9hH865XrjyKweJUF9uK3HxCz9RY3ujKZRtvdpSrw7L8LRhkyMbdcRyRx34acDnGDwDkg38EnSUYL5X 231.40954336 +zcYGXzt78Y7A5FExKjCDXJZe1eHKHM5DnXNJXAh55PyXddcYCZpAmNo8foen1irng3QRu6DtW9FZWaLn1XUNjaQUTnVRSyJ 228.42830489 +zcUHMDDtjcgNEttABsSmC1n4UXaK8mKfyK8BUmQtdqpvFyEqB9bQkZ8Vg7Eq9JLzTLoSFnrrwRktgv25a1ro51MSEpVguBC 228.17126332 +zcVsRGorH5nydFDMj2And5eE92yq4QCUW9ysC2f1Ui89Ewjxh86L15V9yQynXiFnziyAWRDbDQjUpmN28o3UyrGT9X7ioF6 227.18895097 +zcNLZZ4ySDqxkXVpHaizKpNCXAbJPj734ECBoWZn59uUVND57ckdfP1TJYmvoSJxPxCnAJxfN3N3fUW2xhQv6TpT6ByyZSQ 226.80050751 +zcCutV88NcmvBoBrziXitUWYab1t3JJu2yBX3v1BLCt5SvsjZNDNPU8YvE5fRAHK3XPWvD26wA2Gt7SfYUZmAxPavcLj982 225.71842013 +zcGsnifdypUk8PE5rP8jkz8ryBZuDnfvLpRMWbEeyoZvgrJ4iy7AgZX4wnMJzxYhrU6Eq5CkdMSpyNHFEpLAfex6P4muMaC 224.96787615 +zcbp82cj1cyvKyGLMYb4xJc11ZBcJmtHnzCpiLntno2h3aJ3JyjscXMJHNgRQS1E2VrckQbrqTK8DmGrhavZxFJkHv2kj7U 222.49421712 +zcK1a2ktWaUE6Sg26cNbpyDsSV8zodLw8ELddJeaFSdTR5oFfF1RZiJ5sSCRdXe9tEw8wD2zcLwScsuQ72p5DdhX3jQpC16 221.19688584 +zcWyYQR4syziSQg1R4amQkQGPakD1px4phYQ4jXaDYCS5sWZ83gXQqtbLZWf29AFaPm6ff4AXLppTrPpzxRNxd5PaY17XsG 217.60911467 +zcVUHnEuZR3WvSkt5pTXEWVAdqB1tdt4D72CY8s9NND58qFnHMUFtVjbNLvwC62enBZsKFdhCtLyjZiLtKjXuDN3ry5gu6t 216.39621579 +zcV6TrYcDZH5GkUrCqWf1kVCGbhRS72GbdniGp54u3RtucFjz596mezFe1dzPSnUBoUyPcy1aiEkqFGTLAYB5upimxcHQjd 215.84322813 +zcA8aKtv4BChNdZQpdUWCWgSddMe1776FL6MCmNLK8riefbYzAkfrH6eei1pqssUntQaQZJSZuGJouLjy27inwvdoDAzyiD 213.92352545 +zcaQXAnsFSVmagd45p4euaLbLAzuLCKrbJnhARPB15qnWdK5ztTSRG24W93ou6M66dnj51uydx8sEXdd4np5hNFvHkRPt1W 213.81935819 +zcVfJrK4GBz5u5Gun3e2t8Re67iy8At6XN3kUTCkwD5SoUvTRsQMbLhaf2FEk55EbCnDLnAmiaUvLXz4i9B15yjNJAgGBHa 213.80866976 +zcgKxsY6Q8ZY85qcLaEh9ueNaAf7qiMkTbAAddLgiARt5KVt442mebSqjDmf5F17oFsriSvjUe5yqmQEYan1QW9o6tA1ez1 213.73300725 +zcdKG98EZMohXiRJXvHv2z4kJCqfAPJGr86wwtAjWayLLF9P1ke9JXhruDk8mhJsekACQSExZvxnmzG5FwgfC4j4dcy6wZp 209.85417067 +zcTNooGyid1KsS99329UXhRHsSaYGnPDA6eMS6No4oW4bDGddvU9rjshfLGL1iVBWAcFzRCDbCeFCag6iNuXUVDvk7WqMCi 209.46186941 +zcU17Q8pBowpGk3cTXAcstqHaiMYkxKQZr18Qf7iz51i14Ysp6QK3PbYfCEtPtKefeQgoWc9netNjxH7EUUvF8ThLAGb8t8 208.39089670 +zcgu2gHxnnp8VKEJ29KCH4xzsYouy4MQLaviHMRmADEjRJDdRDH8hgV1PJgQuvkX6PB1rTW29sei6ZKq3VdHuXnCL7cm32j 205.53565306 +zcXyqfqmcqb1octbxUK33T4BUbXSmcnrhoVvoGkyGvheEEvrFfPH3X61uQiB4sDkerpoH3hmRh2TE4nDXU3W3xqs9kjfqSK 205.03398341 +zcTDxF9oY1rVQnn4gPzVQNGA3PPdRsVunVDERhYDDhVdmwiqwFi3HsMXSRc5sq8vVrbLYQqXBf6HwQp4eVRQcDryrEc46Km 204.29383663 +zcbsi9UmQCmMTHNov5Lpfhj89uKDUkjUwobUdVNqWktLww2BsbTvohXDHbZnnhJbBrTzSTSUvLoZA8SHSccAJsGZedtGU43 203.16376180 +zcSTY8MS3aTUBinSgedofCEpicrWH9iMwTeYMVJKaVAyKjgCa8B4ys45p15U8VbHMjWBAkDPZG8SG6ZJCBUi7YoHX5mZXL6 202.97662596 +zcEr4BzHHa685y4MCL5UwyPVj3KHgVNFCeSH9SR38pGatGJvfvcSmuWMNLq7p48vscYvkAcaDhGoywLtisDGNQLVJF7RLDV 198.34545850 +zcFKQ7waGkjYNVw3Rt39GPGn958cJz1ZuqYWF3h2y57Prg46cKUDU8c5KpMZki2og1kx4bsUCrYBueaHNhBGwzVkM3FSv3G 196.00074374 +zcZsswKSsAp7KNvXYX4Xi2nWT1K4GbzozYQ8vyiqMKdookdATqQ6dNKSNKUi8NZjHVzRqe6RRtAso6CLxMWH6wCUYegdTXQ 194.85500151 +zcUvUh5BwBbfVfnbri4766jpyWxjSaRQ2bH8QGFSv3ifz6cjutbPSe88UZKKwasMSAwUrU97Xw9VQNVeSX3bMMv5JijMLJZ 194.79528359 +zcTNfRPjZaTLUuQdZuDCvGgRNug8G6ZnyKBGD1fCKoft4Py8gc6G3Mrf9BD3HrtQBrQDsTEZk7CsUcW3H7fPg3m6a8mD4UB 194.70884614 +zcAVies3xUmntE97dcSE1MJtqMJvA3Zf6Vwd7bXWtTcKrpcsP7gQLRy2Kwn6rmRq6hp644cab3pXgvhKnNnX22nTecv2BUy 192.86030404 +zcCFE7WNXRFkbxzzJrfRT4YfoBV9T9bjibdrA9tP7mJ5CrhtAuX6YEm39GnJgwGtEmQMTygpY76gz6tUyQN3ejraXDVtT3x 190.90531097 +zcCtnXemimGVaPQB3LG5Twbh1wAAFMm6ttsiDACDPorPbLFedLHEmYrPTRSs2HEkNohBJnAxERPmbQVGVMb9REDEFdfPyo7 190.85850952 +zcd9xKsRFgqKr7Fx19yE7MWcNUPFDnXFtuDCJtbditKSLRJ719iiHLM8JG422K7ocn3bsc52ctitpA64NSt3AgQtGdKto6g 190.69721021 +zcdeRnPerxujPKf9yHqHQMHqcNHQRBDQRAVRVg99nSP7VRiQbVYFXDWy3yxJTmQfFe7DFjjEYsMMLhFhAQuuvcEXDcJcoEU 190.39515155 +zcGL34NUkpk1bGTpXinoN1UkqxpvVGERf9KB7t6Ygaa89j4Ybe43tLfSwCPJ4mp9q7UJsff2UdoZxACDDrcsQkzP9ykLg1o 189.80532948 +zcGhkPwhHaedpFbjE2tEbHZrWPcw8DLwUkyZq4Ufep79n52ahKQhdhmX2YRHXviV1c5RBnntMSt12sJk3xzwQYmshLmDXg5 188.17880725 +zcbhjVYKnnYzCfnt2RGYYro4esguBpz6ptT7LjNjLNUNwWCPNsydvwDRAAecrQ6NnAAi2gYadm5xWpExEj4nsQR7AxQQdSU 185.55710621 +zcREqPAYsvzv1ZG61ryTEATNGg7dUHmxaW6tbYYUAVTrLXkW32iXYuSzsstWmceRNkHEGr6DMbQtrgV2mTAJPRcEeXq8ouK 184.89679559 +zceuKv1CHBxdcbKjoxRUsqjCYc51eH712tZbZLzhj6Yko8S8ubLRbvsxWU24FEVevG6U9wviuZnDQyx2FEvzzy5AERKPe4k 183.22561347 +zcDgidTnXsZgNEqcpNxhTLu1MnVuEpJAdDKMZ49R258h1ST1zYB3tHaLQN1DCSP9P78Sg2AAfDWKgDGwLiye4xNYfmvNHMM 182.93634575 +zcUwesmuEVUVa6DqihU6QNG6fXDbMA9aChD19tga7po6c8J1hLuQjxH1KyMz8WJVNoe5HgK7NToXsbRaMUnfAVBE19dGwN2 181.89850170 +zcGpAepBrZUMdJcY5T38kJZi5xcg86nyD3oiWHZiCXad6hfKJDbo7tud9eeuXw9LDDMQq3RwCUDuycqyZA3GcGFkuQBgk4Y 181.81606058 +zcR4HMdKqYyC5ajVhTML4osJZRv7nsb1ybd2Eu2DfvtgWBmkrXLn8FgjiSWELZqpHmxJqiFGTU8qJewtZaVjnjSyR5YLAxq 177.77531881 +zcHWduoWUihuPQx9U5SHvAKKsAAewpLqFRHGdCDZk4g5FS7QFJV97kzoCnZwpgTVz3Qj7BAt8zP51tJxKGFaX6UojmtegSu 177.35000811 +zcFyBkdPZe9AqkAJS3vDnyv3NBFUQmJSGtkU13wKbZQ52oyofzY3fekY3qqpePANe6aHTAtF4qyV7VmHhmbJQ582sBXngpH 176.93545013 +zcTwDX9UArXjCk5x48EqUY4uMVpWBbMSWp4WZ38DX2mDEXdKZvGngPdkHJLrAw1AS8xxwfasHbr7fW3RUfVXNDu7vpDr9ub 176.88339594 +zcfb2Yrtzbk4MsfaAiCWExsSawpq8D8wRMHka8pXABukaxZaQcXuhPPx8CWzmjMTn1sDcw5zc6bexGtNsdr2yWU9Zcmu2v8 173.99130762 +zcThA4LEv3BTtesrxHfRZUvid6gPJBeLn7m6KWP3kM6m3irMR1Uh7xMCsNMeYxsYVZCGxTRBSohu1mwWyQqCyLzRJ7bfFFn 167.29855659 +zcN6jywNM4Me8ACdSM7fKLzA42HteLGxA2M8rSx7MX834mEzczSFW3a5rVp9iGWiQ822WT2KzsrgBWWPiwUA6viwTGx9Fkk 165.35934913 +zcHqgYkCbvim8FT13bpkV3C9pGfJQ2jhUdWFLjuH3ogHpfyVpvJkRE6jP59n1ndyznot5vzytqe7upXWgJPJn9d4XfiEnNw 164.13918514 +zcdvfZMy2t7Hh3xQBYyP9tCQftjMnpdbRmYZ84pDZFUoHmFkQA1qkNjjNYzhZomUdV8G1tZCWR3AoNsR6SXPrM2gnjbAL26 163.49713187 +zcCF6hVYnivYpBqbrVzfjHQHZA3hU1vmU8gc53ZsFbjsRcrynyfWQGw6Hmnc33CQWSvNFJTqeV4T8W6C4FVBe6xjhhqvHe9 159.68355320 +zcUpaFzsV5a6eg5qp7r2zj5oR9BL2tU2vvPnFnPHJp5PvUZNQkbKnZQLsPmbkB6Qx1Yh6w3YorvV4ew1tDAdNTmWxxcfkT1 158.46811042 +zcVzAKYtkr8n6hziRzzPFiofCRRU9tvE3hHQkDSTHLrtcFjTmCd1U3ujth7wTcy4v9knVkX1JXsMyS4W4ks7A1y5E6MgGRy 157.69503093 +zcXoj6yPx6JFafmfDzvmWoRjxXuBg3pmxcHFZTvnnXN5FQzwsHqqZ3oLVhzYdgarFYt4yKgqt3EQCsgkNZmiPD2Dc4T7e4r 157.07174018 +zcPyDZhzb1E8K8q1ysKRE8tdNs2CM8H2JFNwxcQjmTDNPGxbz5oQNPDxdUdVs92AQGQP7MpYimZ9T3eU5Mud2cKmLVDd7Bk 156.94788201 +zcRZsCTyLMEN75bEaKYBFA7sD7PdjK3uSrG6ZNG7AgNd58pDZF7adkrzart5VJZ5QRuK2QiArWHAXpDDnVQRznYWKvwHE3X 156.02308989 +zcB2PGdoYLDZmHRGdZuGPuNPRz9S8tXUfPzRyHUZfhQCKqVodXoeVDN9PrRRVNmNvb5JBvRRDB3MpkXGocZQUQFkgtYxtqS 154.67576279 +zcQAoPZzptgncVKKuMyABtGGHoeEdx6hfjosjVVcYG3fTixniiKMqKX5a8WcDXRGHdvrhUDz5Wkw9kT6mXBM94Qa58bZjqz 153.49082494 +zcg2yYTjGrLh6SoQx6BJd8vX1urBfBZug5t3S4vAfLsz9qtyzgEyV1NuEKytfz51SRDVJpbnWyPZqaAbQs4ZE7Yv5dxkH2k 153.35621978 +zcV3E8BcWc4KJkY1xPdgUwKxY43NrEKCFy1K8Q9Dm2dnNsc8BFMQDr4q7i3552YEGVaXzLQnCW6Kp6jtXwR33LjBgaGdA4Z 151.54621308 +zcdbB4j9B3WxDuMCKpnYyrc4Bb2GcVXqQnb8aVuTpJSrh1XErzRYQEvpbnRRPyACegY2i8Lk8P7FjAJk4ySd5KnF8FSmhcT 151.49281674 +zcMbb66fHVoRZU5HSmBBAzpnYAEFyHsoiUXRp4HgQaSnvoHv5MwLe7Xe95JupSC3qXt5ajMQn7b5BB37oc5oNwy8k7ffsTX 151.22899794 +zcR1pdbjomXVPtffobrSddDPY7tvetyAB6dLuDvN8vqMvx6xqULTTCbwCTUfgwKWtSchHtcLWkEY5g1d1ffbtiEKFLhfJCk 151.16116460 +zcLWjVtQsSvHqdzFHxVvjipMuSjqYiZ7sSH3CFis65xmvvo26oXUBVnru6FvTp5xjx3McKsaTsC1U9DJu3b63ygZfKvUTXs 150.88608391 +zcBjU9P4dGJQAUugmBsTkun8AdPVgYbmkCRWUYTq3G2qmQYzMcpsBDbLvo8EKZFLRb2Gi7yPfFSpL5aKdMiVfgcgMt1mW64 149.51511499 +zc8t9MeWikAKXNWwCpxGv2SvrM28UDuKGBGRA8rscsrZWZZqUGNHgVaVeG3jLJw6YgtUZcJydKxPvCMJ7q5zUjHyKnHQGNW 147.69555661 +zcDhFUnijyzoL3bcZaXYF1WBBuP93E8SJUEbomp7ynXPZYf5cbtrp3nHGgD8Z4PVUHeQuk6LEcNvF8xd2Te94YdyEMjtVVo 147.13076976 +zcNyJk29R6hh9yFxMWNouXqGKQr3gJdHdELH3jeusLB4MnYXguFx7bo2br568U1eLQQzwLv9Cx45tnymopA1GHFkMdL2SpJ 146.04976660 +zcHPKrQn7E4HL1WTRpZMVzGqBHtE8LrKXzpLZ9S43rK19j8txYbsXzuSnHhbKcQXVGBVw988U7e3LWKpQM3jaZZk36txfYF 145.37901425 +zcAfZoS5wsSnfjq3xXjTsy7CqPTbUcivNNC4u2mq9wfdEDrAciZicVQnXLW7zpENwbmASNN52tumgx7ikiS9yDikRpESdVA 144.78212877 +zcBYECRj2cGVKiRn9uxRiPRKPiZgLmpQn6ssBVmgN2FGv88SjCK6iAZ211gWZokU6g2xhvpNrHJBoUvUTfBuuu1x5hd1QVz 143.66347797 +zcRRdxvg9kwpP1KRdcSPZB1hCcqxLuEr6Aip8ZPSLTwwCzSeWVBzMED3BZ1NBPexQoDcoXSUQPLYhMiMvBvamPei1vVzADd 141.68186151 +zcFoMGKHdq5Az3JfuHhvjzHkS7x1armGNqf5dVKZJUCyeNYLovAYe6V2whYFT9G9sbCCV6HxYGXuMZhuyoS4c4BPYMotn1Y 141.19180480 +zcf8Z4THNHJwCKW6Cadrqdtsgxi1U68gPwTNRhQyCUf64spNQVV6BJzCryXUvpHF9uXyW2AooQgrWKaqQvskspDoSZff1Jp 140.23180036 +zcTHe4FZo2Kxx3Gg3AKkDQDY5ByNZcSn1rhiinMGvh1K7WzmcV6hqLJr37bjdsKZNv9dmQE2rUsgWhJJhn5yQdFsDteyXXb 140.17344290 +zcY31hL2V8DQupEk8JMxeTpXd6822VGEvBuWmbZLmrt6MEbUKfp27WUNfpDkkdrnDMS4Gb18EfuW4XiiHNwLKWitvUyGq3z 139.91234583 +zcDJMsLTjtMMfMWYb8yc48KjXoFdEMSrfrW7EXfUbWYShK8NuaT7DMxLCsdNyBwWMrTMhJL7m7SRZTbxqm8VDXvvAD8kX7q 137.62946890 +zcArNz5qm656E6HrezX9XEjQyG4hMtYpY6emeA3gLyypncNRrczvoby5W97rj4kMhw4d7Wf1gmnrZV7psb2YKGnFaqG2mZw 137.55951579 +zcbu5nVMughorU96DzQ6w1wsiKryK91WKv18MU82XeE5orQFfURVeHJ481ooDVxDJxajTFZTKRqJ3ZTSSvqdbbmxjrmsLmL 136.89742295 +zcUaLSu1yaPZKoSfMQxu9n4Pi7yBN7Rwj2AJGPgb9XvsQLshY2XwiyrboUb4m5vc2stW1zuo78NYjm6iNcGTrhtYKvk1o1j 135.55543172 +zcbdXHgTUeBGm18kmNgf6gNETiBepeQA2u8juBNzXycRJsRAmu5QoGNi9tsXFvEuNTDUAW5QLuu9o95yP9EsTtNzwFGGbui 135.47165156 +zcSsEEpvD97susq4s7E4vWfuJhCdD3Ae4PmYJKF7DTuwVyfkYmpo894sCv1e3hYJhHUGQaQ7WAGUP9cH53F9bK4QbNEMQrK 134.64385663 +zcKExRWVXPRJp16p2o19BuK8nubsSyzAihiUk8UuXNWBURdGQjn9PRbP6FumPWcfEDbK1Qoq8AKmfrbASDsG2TqNNSV7QJC 134.17577470 +zccVcvi6w6LyoLBsi2fUFFjYFeHWmi5bhtBB4H2F1UjL4QFKX9xDZMhQDGc4WbeGHAdxPaovcyCZC6d2YzpaifFSLjA4rtf 133.96351463 +zcHUUm328qwP5BzAX7JrRS5jJafNZHCkkzEgy5Zgub8M7LdoJjFdUmUQnMKYcwqiRUCANHvPvDCvmPVJTQJhtL2r5V99Mak 133.65347242 +zcVC8m3eYLprz1jDSbDpBVTJcWdQSXyiJnx9jSearFWArimUZN8FThFzRxxGKRQ3mMjo9HCg7sRDHEG1xLVReGXbLr7VYVA 133.48165547 +zcUCnSusMkXdQTtHxmYPZQJkngt2DFgGWoXcYCy3SxSj4qXgXDdLymMSy1SfinwPgLWPsL8sHrxmoUCJPBPCFMDa8TAqBuc 132.00253140 +zceMhcoMh4BGL3gm8aePWn95pR3AVir9Bz76h64FWRnLSJ7UUxc74nNRZuMJUYW5XUrh8C4vtcpeCHppAEhbrq424UiMUrK 131.32313128 +zcbVzWaU3Nze7837xbqKqvZQj1dWFQCrBCDWPVRy4yk7icN1pqSFCJXMLMbrAK8MKemcVo8vqjRiCma4tq1qFHHrj4nR76n 129.29526376 +zcNgRkT7wzdGAr8UCDsdSG5nSvRWtH8oQRPUkhXoo3vZ3Nkr3fHVYEEhfgUFXTP8YEjW7uexhR3CvSsWjDkCQ4gkkHzHoqh 128.94652458 +zc8JJzg4HURtsPpSDkdnU7GCSWZEfmr1cDUnGWXT1n5i8DRaKP3KLHkYdZC9DzSEhQMEhbSyTN4T9yfkkb8BQgbZwik2dS7 128.83504478 +zcAx5SN7qn8vzS6USgpnG6q8oErkWpaJwzHDaNGyzrigJQSbrUJVbyMyN87VnD1G4QuAg4tmgeuCaa6jVS1JQHarvt2bbLV 127.71785609 +zcQYVcXoZ7V7tB4yHobpbGLpAok7cYU9yWFKCQbAdTDGxhuQhyGv8XMmWfxTyY8vvc1tWr3uRAygG9we3s71Mq5GYULeE1W 127.30411692 +zcM1KENZruPjpLVGLRC3DC8rgeZqbDRYdGvRGfwohQ9fCLEwQDSZrdp8EjMbNMH7XWxJWhYfFyA9k5hma7FDfFqTdsw7TRm 126.48717858 +zcR2F3GBREHGe5PGQHqRLNdtqGcwfWTZVbY7SxzCJrHBe6Awhk6CMaz4PbWUU6KCi94Q6NxoxWezmqxSoAMEppKrVBtJ6BH 125.10731889 +zca6XSiKpctX6P8TdX46wBm6fL8ZeBo9SboshiJZVTbThWDcueNvLCwAVrErS7EMbBPPkvaAmoEJDkhG6f5SbHfG18uTEnB 124.66728518 +zcf6cy2VQ5vrRk3whTx7xsAdb95TMT1JUsBpYA3Wt6jtRXeFCVvdgbTnfHpGAAgatQvXttZMd6TaLpjE7JFFqTQY9hx2gzd 124.39417347 +zcWgtpQv6dkGkBregCpkTgS2hvNT34tbmfXG3wBkeFSdqcyoSbmbvsg76i8cjirng6M2QNawYy36MVCL6Kkb2camW4k1ut2 123.74296632 +zcd33egpLRRYPH532UMaNwmqnLMzgKusRCRKh3Rh7uCHCyFephrB57T8ZWWZAP5LrTwknPJuBVStydqq4rcnK18yJ3YHor5 121.24922615 +zcYLU3Cd1NE5siY8h5VxKwGk3sWS1kys1HmCL3WDsMrjRNPrnrfVD3CFCpHsjoL9ib5GZoHsByFokGfyynNS47TnebgAeLL 121.09560059 +zcFVroBh6FFuECMws9FDdtc75cSePCCeDEsQJ1gJ9YXgkSi1WvaYt21hEJj16GLFNKmq8Y3Qsti3pGbL1DTRz3UEJ1565T1 120.77553086 +zcCBWDmxuUJmWERJrFKYSjbYcMmSa3Vy41R5oCuLMdtK4rYnT71Ao82dAFozXnKCkx4okpVzZv8hozT73ZQvEiRLmyuWov7 120.76255029 +zcEVVx6CLAtQM1sEYror5u3sXmLMVhX5x7SmSBmUHsP2kRSpes5XJGKUZyP3CvVVf8HjF5WJ11RMSD9rSABap9qBW9Rp3BZ 119.93842929 +zcNg29rFvRkPdhukkbeHsY2yFPvZbsrM7BqiV6KhXpS5icHGDKay6YK1Vy9kzyuPuP2Fpg9Tgwnxj54AdFS6M6D32iwsgvS 119.46697941 +zcaGZHRHpaZ9UetpmzB9mLBy1nKmB4FM1hEHa944rZLorxtPruBj8y47HDLnvqBhGdtrNqwVCeydgtwqBbFL84uX5GVzopJ 119.36692541 +zcLB8twx3sWaLFz16zhmApocZwed6Si169okcHnKmFcQ6pHyXDarmU3LMmbKefCyQhmps4yYCxnqKcD84cwPtPwDvdCGLqS 118.66973397 +zcJnQXyiXPmNw15PWFLVC21qqLyF12uBEvgHgoQZZiBG873de47jRibCfpDPJW4ELd3rcbY66hCphwsnVsJaTD4BYVYDGtC 116.40559084 +zcJJ8DdGGXFFfAWPjfLC1CxhHa8zMoifq3RrVFm9ovpQcCHWF3U1VXXV9NWUczVipm5UFbxngMHA3BpJiLmXvrWpoe7dcu8 116.15643217 +zcXA6CU6vFSwYc8UypGLQ9PEeqNF3Bh2s9ccCmhwMUP56pY1MMs1avXNn2dSZzk1D6aMz4TSsGCpyptCN9kjCuVXDptySBP 115.74507792 +zcWN1QPALXD7L9sictFi3rCFCLWUSb5JGGP4WYucPt3GVWuqywmhmfkoyDJJeKgLFB9mMtngbnYDUg5MZPNyQMnNQM3j6ed 115.58829389 +zcQ5zYFzdSfFfNZSmMhCzzH3hVjQ9xviybsetiRdd4CA6o94jDvVhTp1KmxFtq4TWxmEneCUKUY74nAh7W3bkm19sEFLLwK 115.48177711 +zcbdUqNzMLjwA77ZcULC5UK4sJxPkgqawBXQomtZ9kVLmgsio8VaNicteP8FUUXgbxfhiMryjcgZZTUzf1ZRVaUbythHbym 114.94377520 +zcd8o6y9rvpy1oG3Ls9ectsqzkFK7aWuWHR4HUeW3CqGtAeJpRLrzbmxPLKgxuixfuif1i2ALVwMcozwB8FFa64xUxMjAYq 113.77290478 +zchZsoJyDwKGCSGtP6CpkE2zN6NohmucM6TUw4nwGX2UPLa71NcKVq2PGNWWmeW1xrkJgaNUmddA4NnujwAstPVy5o8xAss 112.40886959 +zcLLVHtCs21HC4SWw3snGbXhEPppaztqAtuJ5pHq6VuJfsWSAVBsv4frYjFKoorMei7UfAn3YUWz18L65XMoKCDeZsCFeB6 111.48580971 +zcaSNziizyMPaQUcsoEwodn4zXM5zpDzvMFhB7U1eRRnbQbjkcWwFQd4wShZfdsqidWQjzJzNc3q9Phe11XCxaRFDrZd69Z 111.18800996 +zcdaXumGjEgbNGCMpTkGiUyzKxwkQZCi1QunMwG5AyaApJCNNgPtNjfEwSV1sQ8FZtUsg16dHJzxpPMd3drSrgd72DuEbtR 110.99072160 +zcXkyZmQUNt5rrhV9SfaYrESP4xxWjkZ3Tq4h9U8ZG2TLTWUzBQnm5raYvaDkfnHvyvVt4HFsGJGVYdT3ePZGRTu1derpwk 109.26464564 +zcSMSUscggmP1uDwN9UgruWVqqkTWw5p6ERy6eWupyoKRByLQ53RRqc5Tn9rGvexvNRbR7jZtp6TALyCsXZE5EkPdfjte6f 108.07933941 +zcfHNQ41kgTN2N5QpS8vzEZnKSq7NcdubcZvhJxgSwft875QYM7pg6JXBVaCZ16RxST5xJfY7s94je9BsJcqNpvQqT67BA2 107.48498480 +zcB6Bo1PPbfKTBeZHAfz94cdHv1Ev3EorRFtdW3jTXdNRzkkenyhypVo1p9tC8enM6MsdLbMBUg9XZgzqgaFLTCH8xzvbQP 107.14521442 +zcWLkecSN9Z2ZFDxqkMDPwM5GsojxoJzKpWGWUtbNKNyrtVHAGizuEDgyefRYa2JjNpUt94WNxJ2KTtLUHEwgf5AHLPWiqL 106.95099054 +zccudGQTVxgaFAVKvyEzxNtqCGTBEv8c8PXFaGPteJkEXtiw6EFjsm7FqK6kPS8uueYnBzg9znDg5fCriEezq5sQUP6Gr4R 106.40606459 +zcaxKrmgJtsTgVkzMvbv69CdYvYe6EjpqJmGLDbVMi9d1nJuyEEnX4Wd2JsS4UGyntYngfXoygQotNSi3cQ1YziHE3mqf3s 105.11331315 +zcPXDv6nhpmKSfTpS3DTxRL6dS7mSjcqrcyCeSL455PfHotL86FCPDYoFVxSXaH1NrSEPdDJXwbu2Vkw8VbHMinLBxd3fZ5 104.57523247 +zcQzVhDDUdcF9vHddgHB1kqcoGPfd2D5gkWH1Nj1E7ZP1GiZBE7n4fyGzcTNCs4xw1cYXewhYUXztpYFXXwvGxunrG6T2Lb 103.27796118 +zcFLMmnUnz3wQ6Dz9dXwASqTDSstFhGQA7Lio9UNfMxDfSh9S22wkH8Ymy2mVeoUyHWkx5ThyU87RwzpRHz2c8yfs3RZGRt 103.07588603 +zcCMi5JjFSSMhTwsEyTDvK8oS9yDt2QhWePGtxdpLP2um32vtN9nGwKTQGBCqjuNLmxhCWrwYRhV8jcx7JPxACbLFFxGrv6 102.64539404 +zcWNzsnVFUPH6aPF6hwiHjD2h4Sz2hm3qVB5tBUPWz92JquhXzzH1GVoSafo59Wcaec6bjxPoVSM6oWPTyFyfuxbKcATvWz 101.88952531 +zcQSGbMo4FomHpPfgzMX2GkpWK59WJRVH4ru5YpYmp9CAsS1oQYY1DgPLt6CXbK11fuJBe6RNYXwsNNeMcc533T5uqDVsnB 101.72249117 +zcgPH8Uqwm6XqrEiv7zUPbEzZqbKna7DyZAijqiobdD3TKA2XHqcwkvsVivBWxDc7N6jgUZyYfuZdL2JgGJwgSyfjqfx6CX 100.22225578 +zcYdjTxbbHL96emAwUtPfQVgrCBNM6Y1xmBTk5xjX5PG6NrXUkHkFKy967vSGMLGDDH3QUKVnzg7afBsbGGprHz18a9jXBC 99.98655657 +zcSWDw7XD5RomghAQhsyKjM5xbqzVrexrqxQvzpqnegu26EdToQNEJ4rshchWPZh3bsJ9vr8VCut4qDRBYix5KcdiFZpPvn 99.64281858 +zcewVWx76Wvw4pVvwApFLhWSDspC7aX1xsGgf2gpeyDAdfQdFftpMCXXvnMrMNFtm95nzNbj69GcfcYpsUtkhky3gbwuKhk 97.03981806 +zcfiDbipRPCd6vZF8UvVW2sPP4Bxa2TcKKkSAp2qccgYnRJ6z4X5TFHv83Sa1G71mpc8PE4rNMJCDRM7w4Uky3X4w8jGGU8 96.71504234 +zcGQGcvYQ5yppqodTAV4UYu34kCEXX93G2ruiGGDAeZizFG4LTDnk8d2ba9dDhioiDnsCZCrA5A2GEDwGEjpzqtcFtobg3M 96.27867963 +zcNgtkqUjrwPQ4efaxCdiEc4TizPHGYSC5ve6CWfi4ZewVmfnhGGADtk8ZBMuexehH9UJmyKcDnAscmEtgVXTFFnc7J2hEH 95.15879322 +zcXtD4Jyr9yp5dU6tQQBCEVGT5aVvfAfWNJerbWouWFhn38TNpUAnePvPhozxcPW5v79m7mPm4z5g5oJQdeuFEQnLG8phnH 95.07104222 +zcVLhAtNhEjzSkD6U89wgjfQeNFYRgaVZuGjNAtL9HmBBLgwsgvpCX3ApuhvMLD8aawtBHLPCcE6QSmnZpKy3coke5kyn5o 94.93321857 +zcJT6MVNpPBzRLdK71tT8EdEL7qGZKp2StN64pZYPTZHaMuxGGWGeGXAJ6uvjvYq4B2vYNrGizd9Wk5VtmS9YzuNEk1Bsno 93.59488922 +zcPhkfUpSKJZHXPJjdgXdMft4fxGW5NB8BTknp2XZkkKgtjD5xasjCqLyejjWTw462QRaf3asSXBSD9b8guACeTsgJrc97S 93.47791014 +zcFL8zPoNKjZCLAT359hYZHva9yryGuzr3sHngefD5dg8PaUybWFepsZjavUwWPb8Pt3SGVrHtbNfx1wDoxHEiWJNUrqQGY 92.48273651 +zcTwHL2Yza6n6VbLrbmcRug7Ybak1kZfo1AixYagYsNpKYk2BywGYdCb5ZCPXisagG4r4Y3mnVr21X9LcMC9b8VaS9Z8Ef2 91.16910368 +zcM7oW3w2hTbmK7efmturcBAfWy9jvaak9frrVxTVNCDdaRXPnwnbTmi9VNuNBH9skWFPG7y8tyFKYjLCwWhGjHae4J27xg 89.61979192 +zcTynUx4Zgi62qFBXoFRnpfit1KJGCyHCmYuNuE1k59YWSgQN5sVu6pePUfPNMdEdcP5BAx2zUHKNSDt1UxF7jZbGxeRMpP 87.84034575 +zcZuKsRf3fSK1ayjsZNyZCYeMekiEps1PcvidBxhmfZwNsXQNYXnwNiywrijvz3jpWKht1h7DPBhqvfBFhi3BQ4Ld3xzCJq 87.50857895 +zcfphmGG6WqwBVhefmcR39BPXvebJpCJSiAoQXyeWD6JtEqRiHq2AcveDNkjN37MrULNAVCNEZXE671Dohywsi954R61zre 86.22514515 +zcNmg5MiEQiRKirmwXNgKKRsx5iH65Z759gihV4mowiAua9RS2bHaeLCwDKDRyXKMBYzzTSQt8xoLwQarXNX4UNtC9iKEjr 85.93478724 +zcE2gyNZPTELnzFnPmEQWRDYyWdiUfU2wQTj57fcznYvtVAA2cy1SBF3GyrTcvBzqh3rXddpLYCmCmE14frKe1qunzBDzUX 85.88566942 +zcC85HmPBLEpXidfxkHFzPCx6a7JAerRwJY8b7R6zh1HSsspKwib9fAM8LDnX5YobYxyEVioLEXYiq3BY1gtUvG44a2wVy2 85.18818817 +zcDbFaJNbCsrRNvxf5yUkXUPBpsvUcAr4XJnXooC8UkcthDgw3YzmfZPccAT7QvAerXwK7MW4bBBZR7zLMHSmh9r6MaQbz1 84.73335611 +zcfEZea3zuyLZmU6ZV97AVsjpdeMeR8hA6D2U5oxsa4HkmPHpviv9Sm3tt2jyfJqthzRrFu9UQE8aCggK4ZGLgH5epwAiMw 84.46829133 +zchFMcM9mx6jhKn6RgVzYmYTRHUSAThtkWZjGCyPKxfsKUKpgXKBHY8Y9QyN4HCVurmeE2jytsLLGdAXxf4Kmm1YeE8n9bU 84.36521555 +zc9yQnUYHzNyooS537ZwBGRZHaequgunJsPsJoh3eKuVoqacNbMeyPYVUSwtBrWCiAXLXst6JMVGFBaD192MJfZLbcmmrXc 84.17244627 +zcFnhhxgocbSd8r5btyuHVhq148BzUVMJsGBdm1vSmyCAQNYQaL4SrdubUP5axf7swvW9e9EE6anv1S4eJMqAfA2t1dDTdJ 83.93544560 +zcXXczPc3DLfuHUxLPK24G4vfSVheR8wK9SgX27LHsuumubiWvFxUrxydRnYxtEWJKiXhLC96Ati1H3Gfhp9s117A3KLgeN 83.49646894 +zceHJPSxjFE6FxhRvNcd6CxzPdem1x8ntvCwFAhJ8UGHBS9N5ouJjSSz3EsqT1ir2rJbcFeNErfz9sSdCS6eYHas4X7sHL7 83.05107552 +zcQXeyx97YWcL78xkckcMu4sGJrRYqvNJFkXgF1mHpq2JZjr3Qmb9RUbcHqQdz1JuFGU4BxUsaHarT3v4nUe7GM3qkY9Wwz 82.69989189 +zcgoUA1jGfVjc2V1sPm9HVYPfGcfjUS5zbsBgMiaAmmP8wpw43p8gQKXJtWiPLpzRAAy4ckmV1P3X3RxnsgSkurQNTC6kcp 82.64986966 +zcffy2938UFd1iCGu4BEDzVugkSyVD62aBcmQpKhcAGgYXJnyPftb1AZ7yw8Nc2cAXhg6Qv2hTEpSCwkdZfN9qNQWzSMcDC 82.45676764 +zcUdpu52c73emRF9M89ffHfuVEF5xGZZi2EwhP2niPXxaXGrxmLJUnA9VNgBHpmrxde7w38HEJpZhzNPWeecNY6RTznsVVN 82.23108167 +zcPWPmmc1HfD9S8P84hpmBGAdJpHMjPFUGZjF238zmEU8GVrmxasBKv6TCGXkZfKufUVK4W4P3RKqKvVxsq3tdXESrbCZPL 80.75955380 +zccQ212F8YbuYVL9wxJi4NRmvTkP6arpSUQBAKKtHuq9D8ViFgMoCNj2y1bVuV9wkcrVUxPay8Xgn5FwE89WtgmcdFTu1EP 79.82204095 +zcCDyBabcDsNfUwTZgDXRAKc6E7zc9qb4fPSeR6jLxfAfaWfaU7hGDyQUCfpgkapHr6fEDUNhuPSzWfxDSphqF8jro2TQC4 78.77411673 +zc9Aj7hrrU7cQuU5FauGx9SbQbU3mDh5FTAYk5L38CE7CS6k56bGUPA9MgR4VBcqZPpkzWq7xwPgn9Ad6uDh94jyy289bqo 78.46218449 +zcAq6PcbdnHbc2GkgtJJnvCdXFRfZrTzjay2zXVxybhjM6LRihAb6q8VCrwn5k91jkAZE8Wyn4oF46ZLFKQc7V1UmiLCdyK 77.95274334 +zcDyn26k5qx23U4E4ku4UCP1LhCCaL8k7WmLtgGhRQHCq68pbypQEBNwYPnWv4a3fqF8J3rNPvcNkwuxfhFHRWsiof6Lkex 76.23897999 +zcVUE2hfasefjsM5j4LjucEpEneoMoQnGUd9eD188cgH7qCAVBZkWDcN7ZU2ysucQrTWeZ2Y7spRk9zexYzBkuVyrG61ejb 74.09409991 +zcUGRemsfbqVjC6LYSbH1YcE1hw3gTtVzwPCtXQK4u4uNv97HrwUVmjuw4F4vhubpg6nLmvo5Xn3GfGEy6WLGbJs8QBjnvd 72.66774381 +zcJvFqa64Rmp71fJKUw3RWCvr2oTEKAFCDxdDJ273QwaMCaWuFCWE2FaPCZUb8GSvNBi35ZAq9Mchr7i3tT9bJcX5KA5GZi 71.87711425 +zcNEbhETLcQTY5prcDk8Gi2anBNbW2mzmiRDLxZAFA1A7FbWyJyw3rqUcCHLxLPyuduF9L1iue4b8NQ1NihBVBsKtFLDdAU 71.68490547 +zcZ5sRFgVrwUY6rT8JKofaYqjecmpecejeNWpWgaj2RL61AsnhfHZg5aLRBA9YuP5aYPui4nsFjSgttuyc8LtxArEa5Jy2w 71.38725207 +zcEcF2oiKJryNLgxvsf1cYy5cnCbZ6WyFFLpTUxCqHKMgDe6MxTWhFNAtM9hC53W5xJ8PnMsnDaYrgcqYkzi9DAEdiDrRA6 71.04846604 +zcJDQ4T5nmT1bsH2VAHBwegfBvjTrGMKn3UdHt4DpwuGirPsJVsNm4da9zAEUuw96RmhKaJggvmqSXY8SyjS1tFWrZMbL7v 70.93728407 +zcbSNUxufH3qv8faSa37Htu4AdDShGAkEDmCohQvhhhAwFkxYWrd9fhFHEyibAXP4LFBKoKg8hLn9nrQ4sc7rfSdR5mdiGM 70.92268957 +zcCKxTL2f1SkEwjEYzucuWaxhBgTtJqnDhrp2kuRUKW1kiKX1EjhASmXU8Yq2q5nbMBGxVxgMCpSPkVZvnTyamH36QMVCu1 70.82524055 +zcSt74t3gGdqfbU4vTrVRFNtLmZeN2Zypepib5Y3SGca3mfg3iYdJ9YEoi2XrzPcV4HEZJyT1jTMeyctsq4qj8yo2qrQeB7 70.57239540 +zcRXuVh2z22TeuWtc6JabwSPmqqtXgZYfad9dYM8E9dkzRF4XExpDAuDJKuaaJAs5wpXYpZisVhkcUNLMNFpSxXm2pZdQZw 70.55573608 +zcaTiQcEonnGGJyqkXpGSUAPExi3T2ViQWJDujt8ftbYHJ2PrYcsjBjFJQfvujV3PbtEpig98zMRjXLjGZKqrcwLnjPjjDL 69.70751719 +zcX65dQmsPW8sXMGUKxoVCjKEWY5r2xk9p98nVcSupeGkKP7kdXd7Y63P65MCQMDu9WyHhnuHfrupi7CdrwHu78CqEubKK4 69.66967025 +zcA4eNHnkuwdwAJtSbKEq3XmcKFJVSzt557EbZpqy7QYJvi4Cuzw5yCQEeDf1czZZK1NgBJub6ubW1aMhmYqQz41KaMvS3R 69.48376998 +zcBvZNbyEYXF1LiKYCpYBYKqFvSa2EKyb74uHcYMah2MgJfNJDYMTaU4wfUqH1xzqdpXQNswPZtduuH1prBu1t1B7C9xrqw 68.81828470 +zcJT1e1fQz7MAhEaPE7thYTqPMiLdrzW2ieyJVbYw2m3YptYDw2gfcg61kDg7rc3jJmNzUqLqkS6hM3X1kqccPQoUvPyE5s 67.56080854 +zcaZLiPSS7V5gUsNsg8ExXoRFRe3otqHZSCM6aWeotHTQ6LwdYzuVGVojoDqWL9yNsKZAJDznkY8vTE48e7C9udC8bQXRuB 67.26911641 +zcKuLiYjZRg32MSQ9kB5iVvgF25jHRX2fSg3ZjfUGE2nZRKMzn2BDG6stVCqJ6mdbU4LKmKTZh6oHyM3DX26Py9FWkbjGL3 66.89961891 +zcHKhQvkmTHFNscAKD7gtnhkW7VCuxQmp2pvtuE1Lbhki48AhCpTQYmiF7PoRU7rJddi4MhcNgpKQ4RqsZpTvq6KGvPL6Mp 66.53680776 +zcd9TPpTV4Ptky2i9fenbz7EYK7A94f1UhwkjHqt2kaPAfLhxcY1atszZQmdaLyrtBzp5cHoWZMno2m3v9ACvdcCihDTtou 66.53139095 +zcctUCXaHxvATfhtEJLRupvpai1AmL5TmAu5FrLdaK6dZetJykbnev1bKVw9NEJhCsuHnoeSbFWvFG7WugMqryp6YQ6ZPMk 65.18661726 +zcZ1EznLz97xW5zwDBMYTLE4qJe3FvVQBVshhEURRVjmVZtHviQdwfg83aLWCyNVA8HuAXbPxEGSfU3gZ9WLFTgxFMsG6P4 65.09204572 +zcXXJHUJpXRLChvwGQxVMRN2YN7917GLaRt7xZ4c1Q8XM9AsPDCr236zwTmXHLzayGbF5oS832ZRix2LZqjDxvV8D43WUJU 64.77333717 +zcHEXMzUKPYXaib9XVQ9XQ8Nh4wisYLUXzxBZZFDqidAVMStoNCpNHKr8fD1oxK6s1HUR74uRyQ432ujgcpWz9DVbkLN33y 63.81508767 +zcDWKdsqfzv1WAeWqYvxHGHix8KcH4VGNCgxLCnjVD2oDxQv2PNLBJjU6AQrvRJDufC4HamvWFjYVpPPRpw7aS52bj2VXhb 63.80990393 +zcYTX4k2LT8WRS8H8tzVS4cL83Gsv5A8tyhBJzWub13L3oUGuig3NMfnE1sELTEMktEKSSSc7qDpQRMAtfqqKzbAKRr3qTx 62.94272372 +zcWDqwFHnq5o8rBsoxaD5uYnCYdRYzRKi22dQvVppkny4zHRCuwA67BsNYCPpyyQDYGRWCjqAuqNb6U36Gbdnd6U8nKChKQ 62.77857319 +zcQMAPQ7rBHN4gmNoTahLzvPjPmvWsi7KZGFVXQGwTF44sybaD8uciRrjwgM3USVLJYETFpufTC7YjWhBn1Syq6Cuc1oZQ3 62.31380405 +zcQC4o1L9PvUQYSXwFmJW82aKesKewW6MrTVqF2AoYf1MUBUvGbthHouCiXk2mSTE9udPgKcpVsJMw7Ar8b3jQyaaiG5as7 62.29093985 +zcMgBRWAp4MridAwWYy1ftNn5cFRYQikybmrgXmd1qssiP8iXskdp2Ny7oDWE5KgGay4KTZxCNqmuCMrGDauPo64i3xM2K8 62.01035555 +zcEGqMmjcUkoDywyqep4m9Br2AChA2D8zscfsiaSTTUM2BMZU6rHbQqix2ftkAXLmfYTNzn6tXRmFpjK68jq2RU1Ywy7bKv 61.54717386 +zcf5t8jFEYPAWYbweBQFHkddDp9c351b1mkCkgLBESRkkwSBLfuTqx3RTGre5frt7PifK3NxYsWENxEdr7HRznJikRBaHhD 61.43081785 +zch56kUWSbRVwSWzEpELsitZJ9bZTnDc7gYev7AnWLHPipzgLPMD8CunfvyERTYcjTCRRpx7GsQnntnb3TyBCVVVHbm8yjU 61.27139274 +zcQk4iaC4JjMBE5xEjh5g25FCuMbic4pbmKmdwPug1gufhu77uGd9uHuaDEaqSN3rZ79E6eSAELHWM8omuY2RVvknLp2h6v 60.81028615 +zcWWxnmtYicHrQetmg4ihYRauebJjyNQE6V8VNJN7SMGHozbwMQx46CuhiDtHcKoYbg2px3o978iuK1YHQeNT1nJFDcetnY 60.72892267 +zcS8A2up78sQ7XNRmt8gGtRDEKBxTjELNaacfDY5qCRQp5vNGfrmPva8DR2wT2C3ABr3U9mcocHd8vKu7y3XtHg5b7WZKGv 60.68202500 +zcESWzy6a9zcseyrAempfH9tu1a4U94NuP9xGH64uayqyupiECAN2FCfVNSgQYiZ35rVKHJPnE4hY8xo3nPKw7hh152dZyg 60.56156134 +zcTj6b9Bzb7TE463HKcoUnqTTyXcoCtgJLSukx6AQpinRFAb2V8fLrxP2sFTXkFErs6W8r3CAxpT1CaGCyF1uFRG2EjSufS 60.01650046 +zcH7c2JnYkDtcYgUYyFRMyy4pmW7P6uVpxNC4zXv3f1zFkM9GX6QnAAtWhik81z6SqYR5m8V69VK9HRFbzetC44KxwggpbS 59.61620416 +zcZm79brY6dhZiAHSfpC5g8Uheg85F5goXAKCUjxcsUncjktpLeEb53NpJnTkCDzPGRgnuqtz41n3sEQFjWwbrRmjZefbuj 58.90587809 +zcEWeKx2sEUHzXHQMUvgxxSy3joAwWYnj6BNjgV18pur1aQCJBZAAstS5mtWM6DGW9gsnS8xSH218cTM8kQBCeM35Ue5nkz 58.00793102 +zcRN6YfGk9rCWAyfp2sfHXPLSvXUQtaiM6bXqK7kpEtaP9CFa7zY7uoSytvVUxnsoPDMUYxAi3AHpz9uFt1xsy7mu4VE4x7 57.82529091 +zccnzKGRYfRNQnnbCfAsduaArj3RUkU3Dt51piP33NkUP8qnvs8YmJbxPBmDmtzda52BSXh2xZNh5Na4XBHEyK145beZECK 57.72627667 +zccdSnCzHp6GAG9Bo6gxqWaKEiuJLsvAgPf8WF6ge7XhnNcFAKN5vz4JUXTh8jhrcqK2RvECGgvWSZcBuYgKRr3Ty4wXaWe 57.37817157 +zcPCyfZfdTzAj2WmfxMhi3Uz8PfqfosfYCrfPvM8fchJiP1eqapR7ivMR8tYGroBs6mmcRdKswHgsbcYHtLQzysWSS2d6tm 56.46517429 +zcUdGpYMMuZ1UPioZCQSaDXmQdkPMLVuoWrWC6XST3aZXa3fNLS74uRskBmuSw5R3QRaUjFY6ifXtzfZxET6HGvKZ69YpAz 56.33801661 +zcRpcvdUA9ev6eh34zGkxsZmPx3AFioxm1GLyMmr7uawcTUc69YHQxcDQ8FnU7nu8vjAXzxyYXL5KKjDkhxawCyubxnougV 56.30003428 +zcHJxq9bfYZymyDz4rLKjJSAx3uJC6LnbQJNY877sav4djGd2sh3kHEF8GTqUr35BsxwSVFueYrJUoNL851CsxpUcuz8eB2 55.09346377 +zcS57zyFKpREvDKEhiqhZniQbeGek35ubaQUaUeiQi3p4p4ZeaAijyMX2yknGCyv7VwF1KoJZ7fmXoxyxNMNGcnnPgQ2jEh 54.58109688 +zcVKvzmoX5oWzcbAA7BC26xKMChjcdQCpD4mYR5Wwn8SLSreHd2fLe5kyaPYouFegsBp5ZviSEkpY9PDLynr7rzw4fwFHqf 54.31165060 +zcE9F6N7PJmbcdsBbpEB5x4kkYkGnsxMp9ZQuX1w6uB971C9UyLYmVP6G42MMTjsxVKN9DCywZ1QdffR5EbbBRVrRB3xkmq 54.07173868 +zcFtgc9umgugFPXCHeQxXp72rXrBbhKupqMLbdW5RWr4w6yx6tujuvhiRtkbsvhZ8pxdEPHwB47X8SzQJYJ21u3etp89MRX 54.01870369 +zcEnQFUp5bCtzVv8ZmQMdTdtek1HhzQgJDdatnRsuHta3Py7eau4WzQBNqrz2ErsHoGWBsjX7TDEJdj75eezK7RgDQvTESo 53.73491644 +zcXWYKLNgWhe2sTMKLA43Hd9ig6Rdqtut9pNuoiM7JREPLSFPtnxFEPTGwmgrFG3xNrKucCGvLdjirm2bUZkY15GpQzY1Bw 53.38069485 +zcRfBbGk9TSUBexnVbsQjQ8WVP7eukjWN7PDyHd12LaDjiv2ysqcr8AYApJ6YLhDWxKSP5PMypWdSW6BPG3ayGbkotPk2Kn 53.33062393 +zcG1uyaFqZvajMY6EsVigVz2udk2gV9oA4RxdjZWWMD4Y6WVF7EFm6Az6B2qEu72p3Atb6G2kdjSRP5KCr7JxvrTUnQB137 53.32858799 +zcCAZbHGcobeJspN7NV4Mo77agZVmPP2UHWgqhm6MkVEuQKQ2YtvKWpvCfjBgyzULf6XKKkuHxPqiHfZ49JNit9pjYvbVmw 53.31986544 +zc9tVPZY25C4j7DXmhgD9BsJYcTE3FA23Yuvunt3dw5DvqTLQi3eHaFzkeP1i72r7PaN6UKwmFx5hxnsk4anNokUB5eBJLG 52.68927437 +zcefMiv79Rj1HbZT7PCettTQ3WG72r98eTW1r1x5zG2mc9MGdf4WPM52kGBzDjtY8emJ18SyKJB3CJEbS6wjwSC8aZDYtFf 52.66666860 +zc9ohUVLWQQGkYTjrmYSbNYogPEX1Bf54TAJ5Byq7K37xa1XTkdC4HP1LJsqREYgfxiRwk1bVPZ3LibTgEZuQ17wZNzWCRJ 52.34452960 +zcMz9k71HwQb1amNWnWHzseom1JZHLiek7BD5qDXuHsDfPzWKofupKtFXmduoj6j6RRcXGnPLH1vTxQGB4S9usn34LuLnwT 52.00357977 +zcLW9uZKAFWYH81NDFjZaBuR1kjXEYFtUEWykZxHimo1UPMRiYzqFbdfEkPep2bQU7Y55emdiDapuNR4vUpj1gDXpsLPP1D 50.99697374 +zcg9RZ3CMM7yTPtXjSwjVdGXKifd2fvH8qphwm2ugnwFEi7EpgBDCB2m1zhcCBhXE8QCWs7kCfApX4LgPhCfg4KDJmqHnAN 50.77052733 +zchiMr1VARJaeK1AjEsLm9Xah4uhKvHXcC2ZiYzdQjqz22Ynhn6Q7WHkEp2b3wqrZiwmN8Bd3z5wMh7BKPXhfWUAprMw9qq 50.24343536 +zcXxXiAkLcd9g31rY3NfHPLQMUdTjuEyf3Rn1Gw3JJwwPGHDdgLMGxA4qYLgrcHUqu51e5P3c7AyP9EK9e4BL9Zcc3T689m 49.75194163 +zcbVZYbo7P8BRUPsCKTWfyE4XLovfzEX8FNdwAke9uMPaXXSzybBCf4QXn7oTS3RdrN2cyJtpn4u4ytvMLc8sotJgp26vvg 49.58100564 +zcMeBYoF3qKdnYXTpqZcMAAz7WhaEwpsYFwzqzjr4dASmyY6eU1Cv3PMdEGAq4NcFnib42WR2tSbSeVBxvXgCKp3Afkdum4 49.34896846 +zcZPUySnDxqoGjcB6pwf6BTGEZ12uXdYqwqcwEsDKjL8GxXvLxyhxJp4VYe5qy4X5zFDkgzARmh8oVy6fTtiSdtfemBrLwM 49.03184626 +zcUPKDge9zppvPAW5p8dQEHKrc6oj8PrP7hei3UXffzssswLPbc8S9yaFTLrCAVC1NWR7Cv2hFDbVQ3DCHNJidvymD1M4M5 48.39433591 +zcd1j124a1URxVWoZQUycwLEsL4S9TrX5MY7zHnbJv9dqLBQW7AcWuwsGtJrjJNdzBQDKUDQTJ1moDFUF5bGPnqrr7Tot7U 48.20196774 +zcTJekwCSd92Ctv8THbCwmxaJpqanPfEtFkaXbMSVVnzmN63vpKojeYrJo9QRrmag5zs7QU79xtsA2odj9bXcEGBbpFV7zz 47.85610243 +zcMMQopvVqk3DBk1gDMNLT3QHNvnGEcaGc29suLdhk4hMALZAAyYhjhs4wbsd84aUQuJkwEvEQE5QnMMXfENnrFwaf33SHn 47.71711728 +zcXaWqLFLPRY4aptRNTGNot3zqsHKsoFTiArbUkebwxdv9cWm9wQGLuvFZATzpqWMfQmVzjZ2ACYVxHajKscSe5geEotUWT 47.68488448 +zcWJ6cT7NPEY3XprQuM4Bh6HdLa6YWRPstSMwwP6xJeLViMEn96z9rZ9QU2CgQdiqR6BTSPwkwQsNnXwr4Gx22NLdCAiAbX 47.60782803 +zcBvfMFkh1Vc3NZ5kZ5sx6BqPNp32niRtC2MEfjyGuTFgYJwzcsa9AVGQFWGNMtx5gNSzRm72px5qqnnCWbhjrTA57t5Emr 46.92974987 +zchgXzAkCWZMtSHMdh3WKQTp6GsRjXuRapNFYU8eCUwjeT4wf6Meht7mMyszRaedngxnPLRZgeYDucuZTxN2CL3B9SL2k9E 46.77440539 +zcVFwWgH37s3yw7F9o1CAhUgb3Sa3LuxUSqoEwtGGSgG162DD1YSkMEYeq27FLaHkaj3FEaoLfKMA5GqdE2QUspjbPbB42d 45.86342181 +zccmTZLt1H6JReGuXXcf6EvmYjpp3fpDpjgr8MZ5t4oTBHXZfFopti7GB7bUAg4QbKBDYSBqxXhCb9DgXw43fqLqaxq72MR 45.32556848 +zcJ9JEFMTrqnyRPF3NJKqNDESyvqDV2BPyh1sLZxy73PkSR3aHhSHzNxf7m6kv2xqC2ekRCo2VScAJMqby9aAhGnPUyadWG 45.24958526 +zcBvetc2AgY3tvvFcXZogjpUqZ5mV3Xhn4iHuzyHN9FHgx67TdzzpV2EmL3i4QdvvS2bB7Q6mhKWRj7BVN5sd1xP9j5mbBB 44.00892100 +zcZbBcRTpNm5xDYsvfmx4C815BzrbtkwNWnAPB5vrPkHaz43Wk84p7zF8nyQqntZQxGzJp7gRHLfqtzvzND8BYwxpeT6XdV 43.90713255 +zcBscW3fLKRYULZRzCrBLvMkgb3EBgRCXkLtDptU1ZwzXfzfUeMYaYpDUBHS1APbeKczRP9tJ1v8rfKKozd7bmpyzzcc3R7 43.75357895 +zc8GqgEam5jPApvgwVmrCKRzETDcftHoguyLJ49WjZGqWtTNLkCutgTTnxig7QfVy2kvjWmp2jxetfReQCUwjGXSwMeFyzL 43.38443044 +zcEsGCpqQyHSMZRF3tWMAiptg3nJLwg5UGx7hE2jtZhbgQVvuXswxhnGTyMzccEBLKCz82SbW1CEaCKpY4h7hR2NjhLm898 43.36320212 +zcSQZKsTUS2sXMRtTc6xGLZdv1559iwPaYbZeMGSsh7xhWNC48qgCqR5YrpxnduJ7SQuW78nmcjCu2mRa2kBunY9Hgrd25H 42.23336033 +zcK8pY8xjvohAAcVeVJuN9PEccVnhr62dSzn2W84ju6M28ynCXNf1N3M8QaoPjWJzYjSDtLaznSBRZSgPJpUPLj5j9cdgWP 41.99022973 +zce4nBkBsbtjYc6Zaxz1jfS6EWb3YHwDkUF7AYSn7fvsmjNxR1UPrvnrEKZ6Yj9JHj9M3JjiB9vZfd7Dt41r83oGhgfJrAy 41.48841839 +zcXBFek35G3mqqDMgc8fRfDrZzDN5pFbBG33KC5yt8FeVkYAHkJqwLwCcdyNusWnqg7xDRs4aDxCbP6kAdPU4mp71tLXav8 41.26077367 +zcDKZuffTo83xfK9iEjoq8mMXDTiKcJkpitdBgmpKpPJRnmEWstYNd5hRFzxDCwWSc7k3DCWiMrK5wTUKPTnvqnUThTeuEa 41.10517119 +zcUztysCcJtVMzcfvJmwktQhq8fhZ4g63v6E6omopPgzaCEYyLqPFWvSePzoqs9dw17Jq8ir8eyhhSATAvzWAGLGcoPHZQq 40.84254774 +zcDjfNVZ1AW3JQHpE6kmYb1iEM1fAnCpzRGh48bQf5qLuRC1YXpJgkCMUEtJfYGZra7rhAYZWDPTavA2ZnXfJMM599vaNp2 40.28086614 +zcUawmC1fLesGEz7Xi8Ktz3h5rorMfRH89uJszYGT13tFfyQ3YzDRQt498od574tHchMFvUD17dJBiLXm34bgxbrqrcut4K 40.10110312 +zcQA8GnVp6YLuD2d4Kwm1GeBspyqMZHb1h529ZLnvTWwqnopFWuKRMvB5BQt91g9G6M85aCfrpXXHb7zFjjRwKBe1ZKLkSN 39.95044160 +zcWViMP8iN5YHXK9Tb85pxbhvXLAzd73XqQvbmSK2n7v3sp1USTPdGETHGAAn3z3isQKLeatpPGW9daN2QQnAG7fY7s94Ec 39.27976275 +zchXsW2AaQSncBDPP8KrU7uSPSZR35B27z3ZbHQHFMnWgBkVRSbmJnw9LR1NQXAYuXFvokLj3cqP81aykvqGKa9dTatePpZ 38.54989840 +zc9VUVikjyNVLcuwJnbzFCTJ1nNT6arQwMtGmv3HbccbVVdwb8V8sobqCn5G98Gu2Ftsi2fLvHmZy7jzxE7Kky1Qouy5igt 38.53056452 +zc9QH5rwLc8GNYzBuu5bPHxRx8kSzofHReEoQAnqmzH7AK5TaUcgDzAfLm6Ubbh9kN9M8LzcErX2RpLjUSBsZuokdFPWyMH 38.50569323 +zcXkZQ5dEy5V4p6Fi93QLeHvdXTzt5QcZPADLvVKvgLgvRajeqkztKYgWwAukdfAdHYdx4aySf78KnSYvie131G5gMVy84K 37.61659384 +zcWqfQYP9QSaC2xsThGJuAWdzEEqr1J7h9uvSCjZc6xWd1e4fmguXWaQ7FXytHg3Sg3qXN84CivN2Cuf4hH1nhREDKkzAKJ 37.39006746 +zcGwdbZmhiQpvfkXVCUUU9FJpyTgMud7cakcHmmqMzYXxJjqZkgoPPecPqXhFPw3RgCdtDSNc85dVgkM7iDS1nz8JXdCbSc 37.03019059 +zc8d6qXabf2tGB5hHEpjfQ1QWNU6uBDsm1qvAB1PvpwbL1A6itahq5eLq982D42HMkTM8KR6AGoVUt8mp7NYZjXZseMWwR9 36.49371105 +zcc7iD6RFyLoQFNJZE9Hm6mw46MQ7MsRQ1oU2SKKGrHFuHDxhNaxNBJ6UAWME9vhhaxsSgPt3xxUAFoxBUF14QgRa6VPjtq 36.46671220 +zc9m7cEDqxo2XXJgJwWS3qKHLkby4it6woccYjNkKm9ctcBWdy2j9rW9mC99cZpTNF2WsFuGaVjpUQe8Ws84CyW9UnA8NkT 36.23672451 +zcLbqZ4SW7G8citFFjxvNmoae1jpqCKJh1fSGnoufrmEzPv1z5UjuqNPf3KA4NBxXiAyfwbHW8iSv7nyqxz735wvNYU8MaE 35.93340497 +zcJmgB2KZBsKgxQgn1FMzpjR7GnWKKbZHLKP6Y6DPcnVStiN2YvB4iTr34UQvqXWkbbt63TvkJJtgZMoRMStobsJgELufmx 35.92259122 +zc9wnBjHqtSo29ti91ki2twrVPqvFheuufvbVwS4PEoG4K9k2jXQjHzCVuwuriAoah923viEf7xZ5dK1s3ryq7rHssB2Pnn 35.84034738 +zcXvTVFRjYDWTyob2r43PT38NEy74AG1xcszTB46zxtzzxM7eRXrWN4crUggaA39YaWyN6bdjGWTw6nCS2hXSKCHUhdLvUa 35.79303990 +zcWaUki73dv8437hDWcDVBRJwBCeMjiZKUPAJ3N22QWfhEQpocDMAx6NQ9eALaHcy6LccG2uW5gHcn8af61W7Nd1hxargXg 35.32843778 +zcciUfFVkQ2L81kFu45BdTPatro3LgZhLocwQXRp3QPKgmGEFu1V3oGXJfNMzzPpZ6BRhRc3q16cjDZ2QPmVeWT31U8jJzu 35.19272718 +zcPNPCLhcnoJoj9ZZkmggHS9KKvTbJbhH2vdcRy45X7UdGReHom7TYoChtjQGZqfCQKzQzxEeZcsH6mr6kmnw8eiqHVTisR 34.90739244 +zc8NBLMSZw9PbPnPBYscQn6KJSJfAebhRxzHecPxiZkdB9vRfKa7t9LrkfDnRYA4naMGExoCqrtWT6SHG4vXRLU8qrJp29g 34.74712693 +zc8MRoJ1pNTSkk9Ej4PXet3YY7czchgWRjW86mbneMZEY6CKdEwfoMc9FmiEfFwZMkRjqZ3gU5iUY1gs5aqveo1RbnEmkAc 34.60557084 +zcaYdxgPiXAVCj2Wrz49H9L1JUirt4KeqSiwMJvhnTg67Jss3na2zQbu47eGTKF1MtVddG53uoUUr9TF3vm12y6ihBPh778 34.28609554 +zcYquvBQNfWh973L4vvfv5JLSdNMz6sk4C1FtiHGMdmKYPtL94DVS4jENyCSNAiWwnkhR8V3RRotjhjZW64gd8yoaQP9ewb 34.21002477 +zc9kN21EBgmAJxUH3kJxKDSzgp6pmHUx7phRNPXazLQHKDkahYg374Z4d7P5AGytUTbpWBc8GL1AmejJ48qgYe82ZGti5qs 33.95584987 +zcbTwv1MXHeDxDVgqvxubGpREpDoi1mFk8YoJK2hwhy5dWvsGXEXKnfSYwoCD1jNW2pcaxPS8sx5FUcnuycpAVTMz4CPKcJ 33.92298942 +zccfsaxzRvJjm5tsXcF1uvNfoNXQdk1h1KRKQ1PqQsHsWAmWivwWgyTEPFxfecPdFXCyKkM2yrwUbppM7tFESvtnEnEjNdJ 33.88962456 +zcFXERcowBMq6o5wLWECAFv8WWWZvfaxyF2vcBNLmdjFQP47n2YaiAmduinjRx14eqxANNBHtVegmznzmP9brY6up3WnJGc 33.78472170 +zcBEc9zbTpsrvVbDdxpe658Et7zP69n5riScXz2yfL4Cp31rac7qnZftkZAog431jGs3ruKdRftjaJPzynJSEmFHkJVbUru 33.64997343 +zcLzdyBWJdzzBQMnTgwmtabm6UrEeNnpp8w7UBqxDo4ThQSdmsNfEs6TE3uCRDTF1uChgMjyTV8mToX3tTiaMDNYtUFW3DE 33.54867245 +zcFMKueUELM6JFMA2nNWeNt7ihoZ26MYc8c93odgXEQNCn5pumjXt9pLHjGErGwMB9Y3WMSXmx4ydW8zMhLcGPHsPUPrbTd 33.52173549 +zcPTck2GFkW2A17NUDgRQzFoc2SHVRvT9gyNJ1mtb5JXAXyoU5LnkdCJw2W9ynury2CNM66tUT1cTQio19JRAe1hJT7WS6L 33.17252391 +zcBWxPSksii7snNDjnSmUvnGFiv4JvbFNFMBgUvhn4fr6v8jiyj77L4MzD5VuSa4fCZpRXMMjD96FiBB6SUsyMUCFBHoTzE 33.07755450 +zcVwArad7vhd1Vix5zQ3rMGAeztqeQBrqmLc4AuuXWwkFcWtUxLTSAx5NdcZgbgQWNZiCv8VbpGERFGorYMVTN5WvDrct4D 33.00758489 +zcEv6Fcn2xKH7iYcMgnafnnAe2oKVwNFQbhbfKrTGo375gTTspCR4TZwV2iqA4zyYUNRxqpGcqJ8Ftc35jSnDvEAa7nq4V4 32.83871131 +zcQzpZRwhfjtwZTQeMnu1RxFUh5KxTUau39vrFDh5odiRDzSzYdmWwhDhg9cwySkqTBxWPSZHQuoD7io9W4j49wQyTE3w6B 32.46292744 +zcRjVD2FfHis2EG667f3FREUe8841uvQXX5btgzBDgo8LrLCJXdiZeZYTwof6gvwxdFQ4oMn4D4JBMUqWWc7NyyHuDrvLKG 32.05915645 +zcENBixUbwcB5xUmbTzJNYbNEBUs8bxNHHTLigpg7KCp24BHBbtwbx9c1A3D4BpJeRChx3pLZd4TeAfYzwA5iBn1EWBRBaJ 31.83242553 +zc8iErtpmPtUnXAchTkpbVVD1cCiVLh4YmU33zFeVyrdv5NDNQAh3WPr1q2MVTxGDJhABjwGiPzw35Terxutr9UQsbQBfcF 31.77585686 +zca5ULHi1JNzEfPNaeJs2YWQxk2XfGpW1VTMRsk8TKVcigYR5r3EMPiUbbMiDLSkmbxVGaW6iLXrzkp2FXXdpX6pcqBjTJb 31.59933037 +zcgyanE64cz8ssj42HZGPGPvJ9yUEZSxXGgdD7mcv7wTUdoWsRbTjdPjgthf8E2rSh7RgRHmbbQ7N1VUH1fEoU7a1crLv2X 31.45880288 +zcQUxara1AfX2ib9Qs4r7FLvjxKgqW4SQWVaZWvZTKs4ZF6faPZvjY7Ebv6v2G4Umreuyny8MobUC47k5pHPVpMmSq7SNxP 31.23137132 +zc8Xhm65p8M2Frp9DJfAP6ixcZ9vs2pVmnU8gHxDR534J1FrnJH51iKBZxqxq6hrhfZ4MmNXRFyaCvbTUszAgEoaHrEqXKR 31.22156194 +zcTgaTVQfFt3xx4qkKPZ8rABK3h78YhBUe5g1BpGDMsWGiw6rUhDY72xv4R8g8S2GN9RAuyvwwMrxrrEUw48f7RuR6LvcYt 31.12876593 +zcUU8CQ5A3bCcKDR2tWberi8RBJGhmnMY7ECN5eer66hSY7Y8hZSQazaHWcyx1tyARCNaQqCXkwtAsQYkYv1y5EFP6PUGrY 31.07173441 +zcCJsrw2CdLqhDYKBM48r4FM587Xw6i7xBn4WxKqSsFwBDcFguNWVaF5LwUZsmbtL5zjF6TGY4dECRKQGKFsEqWaunYS5pW 31.04605358 +zc8Hc5Ynefs6Jxen3mQZjHzgpSPkGYSenNNeqZAf9QcdqoswiGzK6TZVghJbXWwYNs7SSqvX74w2VcdmKK3AA8Mj51QEKCN 30.84159984 +zcJ2yhKaZMSnb88XBEE12XpzQSiBmwhLw2WoSoNHDKL8QDcizegfXFdgX4oJ9fvzz6sRjVPpXk1JojwCe7RznHoXGHwtPbS 30.32461192 +zcW23x53sgD9TrwJ7mKYQPRMZGX29LQzhkFgMUhsdvMmzgpKbNJFsQa7nhyiodW9EdcRZmewqFYAQsjSKPxd8YM5VWqzsKX 30.21374641 +zcNcaSkCBcSCvmJXJLZUyTWc6GCZDA7gtBrrUJL3CJchtQ4PZEfRrTRdTRt9ZUATfKEN8pVy3o8Q67Nd1UM6rNj1ifuvezP 30.01095838 +zcZkTkCE6BDN3mRHsRTNnALGFsVYSET8KJJhfpFL2AfpXwLG8E45U83V4MsJeNt7V9ziLt2dAzbpQuf7WVH7LDG2iCJndms 29.88118621 +zcLCxfMFrdbHRwHKAKyAkTCE1T7UEhtwEcCFB1LYynU6T3Si8iXG3FsL6j4SZ3JGf4SLhk5FzT8iYffZWJURTXoFF42nkiA 29.51228312 +zcMZPukV7JnWC9hhavTHig3khGwa3YA5dHzB29CfjMVx6njBiz5dj9uvAD1iNmsWL2VS32FpwZjc5fo3hQNHbESMr6YJQwY 29.29536906 +zcXhSDGrH7FrbSjHLLsd4Do2R5wh82R9aUJZB1Md2Ntpya7XTvcq4bpH3SBvGkRs7vt2jR3ckvH6vAAPi4sJDZw5mue9AGe 29.24626876 +zcgPyWjFJEgXbiD8CKDUejHYE9VtuGUWm5VCMmrjLUHUztY4DL9e5nGy91pKtsmVQ9eZKaXgb12v5wGKpfMVazfHKxUa6ej 29.09501867 +zcPnnp8HwQWg9Mx6ARCthpSpwYruJ9Uarx3yswCoMY2bMJ7iMsGE2suwzfqodRhGbtNJfnYW6xwWhpy8V4Bu2v7XERjcp7W 29.08934204 +zcBTvDRhBXky9HJ71rVDTx7nCDdYL2PPLyYKkrzPExKkCkMPioQsLemtAwGworVo1JfMS1KGBgWjaQ4S3mhz94jC1ueWBjw 28.76784824 +zcCkNB4TmZggRncCZeGWQMsjYaurrGFp9Z1MDeNJMft835B5agDe8L9rSKM9xvPaN2r2CWHesyN8daUbGs6xAzypH2eKM6B 28.67681458 +zca66kvbEds6wqCj9a1nAanjfBu5RBzXnxX7KLju2GNnWxbFWUJob29DiDNexTxhDGM2ZF71PX8rR3VkfFN5Ev11vtcxDni 28.67545241 +zcZPBkKhFV2QbaN8ZS3bvxTwfbk1BNG7ZCYh2rGQLev2LXV2QQsn1jSbrzWELu5cRtK1BnCAMeDb7MJfJ9tjDvqQTcj95zn 28.60502806 +zcRi5ZanfCp9WFPrnC6Q9obAQxX6k6PtdhZkKDTgeBfnggWSwin6Z5ZVW843hSgQnsH1NRthVZ1WXWDn1HkHCzUmkTkbcH5 28.59798844 +zcHVB1vKXCHJNQsaiE32KFbb5z3Zjr1pKsgoJ8wGZq23aZfYJU4wATfHUBsrgsRjeS9dHiRJBx6pejesgX22sC4y7Nsq5oV 28.41538062 +zcXrJAR3QwJT4r9eVSKGnBYkYse5FEZ8NRXqKfZQynERnPYTXnLNGdtTzjp47U3EfxNAbruReNxNYZKQxDJQUjLAC49i234 28.29026155 +zcVnK8gyXVYFWJPw4R3BenG6g44KWrRV2Jun95peWbmjfZvT5ssYp1mW1zfEBCcFHWtYjHp8HU1b7emAweVBEUTxzp8ht3t 27.95651240 +zcYnfKnyQ854q4fqh3DeCyAbZYruFrWwK99uDwcyzVNcoBbYPiFbpr4BYpwqKA7ogSXeviadNioGiYf5t6oiNeQoAjVtEPh 27.78490986 +zcfnCsqZCNQzv6pYjkAewJSZVSax98KPLtMBdiE5Thsx76RDVcSahP1SdJyJXHAdkzFsqxr4CskARMh8p1EqhyU7f4UNB4b 26.92253158 +zch2yNzJNusSG2QRDx6Yvm92Z8vm6ap3LthgSXcPUqidqcYsAhQ1ZbiKGFdLi6oBUvoWFf5pcwABVRrtFd2cB6DM32rBX1j 26.79019980 +zcApDSLErYAyCceGsn374vpXwfxzFTMBgVNtrQGSW49ih66vjZoho4Es8VWB7LYU9LwEQFvjqQA8oEESbj4sbQ7YVK8Wp2N 26.62116459 +zcESxyocmFVHZeHXaaq4PQMbVKdqSwdJhZdunYi6z7rYDLF2HEPuTLpwg8Xma1Rjnx1T7hZBNWAB8DVEbp1fQ1x8CSWMCX9 26.56870784 +zcgnvry4rDaP6E5i5LMkiNZfpqEumiiZfQKHVEjnPhHGNFpSaQCwnR6ef1VJba6w4nCXpNfPDd35Ge1GFumF6aynhNdA2dw 26.47651135 +zc9kNqidKGcv6Fk2PoSN4fMkSn1nZhBE4cofPDkwApNLCt4cCQgjcnENDtZ7oEdnHPvnX9wVzNoGbQWkqHqptwBra6T5BsS 26.37598171 +zcEK3pfZsuK3DpEYBfLgrENzunwWvhzVZydsDx3CJvgec7aGbo28emriHxRZH3H87UqzUMc8bTT73VzRqEkuUvwhxsMu9nC 25.95156360 +zcT74LAX6gzebpKHFejsawpr4XPgnNPwNfkfHh746oznifiJNNJVQFowdkES8vvwPYeMYggyXeetUzx89ZJPmokw1tN5z9P 25.89310270 +zcTyonmyMz21fRNk85hZvoYqy9YZAxPBYtg2T4HcpuRMiFZfW8paBHKnXQe21MRYf5wpSEVBZxWx1fdsKAzZdzPYW1YnEf4 25.86876653 +zcM1SuvrMJBJ9MLnFiMujbqhmNgB3D2onYtooPWVcCEUdDyKiCZeo2qUefDPVtStkuf4oP7YLEDWHDsHiXPpXQEs5sqeRCC 25.75518242 +zcBrY7mrVjSZP2fYnESfce9vgjfiWDUE1Vaxs5izG8ZjzNMWnmkg41euKoJpcjw7NskXZPeEZeietAU3Am6DSmrybioFT1Y 25.70216756 +zccfUbWMs2xSLNpJF5xoN5PXJtbLFLY1Erbkvyh1dA3xgnxfakip7SmWWCNJt21EkmVEm9oVewhi4VLwPmD8nhCZm7m1p2g 25.68992243 +zcXymrefowcMgKRUj95Ra6cCgqcQLNhsniJAo4TgS1VSh12keygNmZtTL1tPba8sCsFvRyNpPQzB73wjSaHGZqWLpBdx3Cp 25.55422528 +zcGUPVsMfrnfvSN1W67di4WjWsdCBirKNqZ7fxZtxhZ22tpVjSwhccg8EbyBywNURLV5X43vkZNHU3yRjNGbvzXYNn633pZ 25.42015436 +zcdvQEnUG6DNNMguXXbYcyrnX3MbJuTPNmRhP5sztVzUNCoaMjJzbJBUWmQVCMLbYt5GsPdRtSsq2pLn54m7Z8QvWW6Hh5i 25.28992683 +zcJmtQYxbqA5Sypboq7XACkpKP5atuM85oXeMkzKwZyA7JuHS8s5nQRsNcjTPXiQBrdozzx4KbgkEW2tutG1GDUNjwXyJ9k 25.17031602 +zcPBpCLLhUVmWVRPoD9isSgs7UVsyDVg1nFAfLsuokN8e53bCUfv3MBBYF5W1dp63zhMCuTssahEqAbcTLT24ewBCZXXnhu 24.98822948 +zcTNX4CySjFC9qNKgT9WuBTeUhnjafJM2JmbAVqimhDakrr1UiWpRv5ZJ5kNPAv6iAuDbeZXW8n2RpFEZjbqbL1XkGe6QpH 24.90711810 +zcPa3GMgFLtMQgk9V7fi3rCKtsB7RdAUtbQoqYXuE7Eu18D8ZhbX5tkoNQ2NyQcfXzNWExFvRBHqdtVQqQAorK8r5QFyt1W 24.85302080 +zcSkqmjkqTV8EySdhE7azWU867cAte1eZaBjTRMPbKz2bkx6kr4QxCbAn28jaHiGCi12bg3r8oDcm2H4yfyzzX1uKMycaTY 24.73705043 +zcSiGCPjzFHz5yPHTbcvpRBVQxEzWBTuPk22c7W1cJEbxsUjocQ8dUxTXpqUvKSVinpBayzpqcBWmv4mrKq3oj4zr7hE2W4 24.62403626 +zcNdT5FfkuufajEKKuEJVf75Txck6B7mZNmbRJKZNaait5FuUaJNmKT7HNM46QjcQDYhWCmDZG2fmjF3muY7AyVuG1dHF3h 24.43334374 +zcPGJnXgSFkngdFXmFk21pgtctwnGtLEh1V1dydJUEiLKH8Bue3wPrWwaGfeEDT42gd1QJ9JygCVTrJJgds2tLdHWzBrgFJ 24.31298354 +zcXqAE7RmBSM9ZbUJtkdRtBXRzc2HntEQKK1UcT4K2JkKSMfuYuJaz1dU84bnJ6dNU5fgpM83DoCkfswTeeaJik6YDHhjoo 24.30573989 +zcPvpGT1DoNu2K9wDsJVyDv6ckM7u22MoQP4HdF9wKemU3HeShkWafvBdqssftF6LPqzL4LTAg6CWa97cYeKtADKPn5j2jN 23.94630429 +zc8JmTjYgVZYyEV6ra239PrZwqhMR4Uqw1GxbUCVDSGDjgUDKLCTajwpKYBfZRCye5dR97sWYD36hqRq6Bzi9XU86dWcap3 23.90546202 +zcFrhTKjBz8pARTpdZk8jmg1mszP2d7jhFg6fFo7gWQQyzPX7oe9uvejiD1asFHdFpoydfdyp4WAoVuhHC4xtPtaD3XvB7S 23.88988849 +zcFsw2fHgFCjm3FcGPPDs5ctAgVkzKid76CzfauzGxv7AHoQuUFy4NA7tdSFuvyL3SQ5divna16bykwtBPYvfnhTP6ehipg 23.52310407 +zcV7mWD6n4KKFpVCUHPAkPvQHzEZSjTTeYbbuSVwpaUao7nCNyCDQ5vH7fksrZcq8Hsaduor7wLoD9eLAxq6B2wiqTnEZ9v 23.32450200 +zcRZarRNigTFZPu1jnJd5nfPCyXc9iroZzLXQ52cDHdASRoA2cD5N2oA9X8F37UMZ8KEvGeL2XMf1F1euhhuBTk9ZL4hQ5g 23.19389785 +zcZvoxWqfc6GdmeKsZZf2B95MnfpYQnSE9J4FGXLXcFeMQswJXpFLV4j3BKib5GXUuZuvBiTdrP38pJJtReujpETXgzTLRT 23.02435017 +zcZcu6aPvVijn84s45Gp38rBWvi6eecoNyJjQt1tVLC3ENJgSJ1US5WzViywubMX4hEzFunC4wYr2TeWZMF3Gz796FY1Xs3 23.00473923 +zcN741LBmS23ZAdHTsHqAj7KYtSM3wTr7tdxRtJJTwa8vY9ZSs7UVJa1zTy174WiTw7QTnwfTnhWPujTAdNwRukBtKFu2YJ 22.98494220 +zcPg4zkdgHMMQfEJus9dSdTTA4aHU27M6RYS8X8ABgzp2Q7vgsqLn76yQkWULmHnaYsXX1usA1tcPFa5vZHmgS3CQLhSGqd 22.48162729 +zcVJkvZriEqFRLW8HcSkfoxiWRkMxnQJiYWHKUPzYaEY138K8zDWJFLjoheutYyS2Lt7PpscPHdNUsBubeEaLcEvXgeffVZ 22.33964550 +zcVVN1ZPQKHNtvNaJAVzWpJRBztgHaesNpJsNjEM1YR3D4iP1zYNkgvw3Wk2UJ9WB6ELDEkU8Sd4ay9ciyAQrvwTWjRUp59 22.24960696 +zcUFVgWi1DQJkSUvGPs9N6aXrmTovKPykjP6CHapeEn3pktBRWL86grubtf6SucUAQgDkSGzW5ma8UXNq1sYHaeyvEyxyRt 22.07750687 +zche6gww2pnc7PuNZbkfhmg4tcU9vyu9ifh3EC9ysp4e3o8QcShrZLWrNjEDUDDkkiEa94gW37X2rPBNkVr7qjRZdrdySrk 21.84108190 +zcbbfWap5XXtdCGebgSCn8RDxUZcQVCTFaFcSr4oxdWfd4sM8Hk45J5fMCe5E2ShZNKU3oWShJbkwvRaRFEG9N6LEFQbZRG 21.83469321 +zcDQcyStVzXqaz99kJRFxfUqqzvZaBzdLue9fsnvNCfL8um1na7quNmqA9kzthk42EqmhB75KD9qb5d7nZAL495araK3VK4 21.77869665 +zcMiiD6fYHk4vRGdTZFy5haFWfHyAtfuNrzAi5ViLZATQANmryDwEgC94GtFMcR7Xm9VoTWpe92ZjeMdP3N7f7Hybog2EbR 21.68995522 +zcMAJuMdQNtRFCMV7T2qoDLWLgCk3EW7ivQiScX5ZQDBYDzXyMQPsNCoPRxNVxXimZkW2espKhzq184xTEWCqJrA28Lj8qN 21.43562927 +zc9CDfmxtqdJWgKKQs3kjvLGALcr6bLtDh39S8BP8oSFyFuBEoNQ6YpBpZmJQz1TSJLFXVZ1CKQZy4FMfExsoumrfRWmRuh 21.07468459 +zcc2LxGcMnBRZ44Yu6c9pzm5h2P9XWsKnSSooMYMf3QZ1VCF2mnLPRQYBpQeVb8fMfK4YAcchMq46rRkh5rqcbjidyFt7K1 21.02514104 +zcF8UGPwp7dHHbTTeEWD7dgaU1qEuC6ezBaizzZ81TBabaX8EX11bzHm8GvGXkYxuHkMQtY6N6QG8ccudLzBLFr89zHoyDY 20.88961829 +zcX42mQbFjvycuLjQooeNqTKh2eCdcEt6gCLAAN4gqhWM7EYq8gNGG7aoypTFLHacHmBdXmSvXKNtZKUNHoPFLMiK22QjJ1 20.57055169 +zcQiov65jjuZEuBxYR4KFFDpcFgNafhz4dBqZ9ynJtQmK9xTuHcthhopU2zCFWVjYEH2yDEuP6f561gzn78T58h6cHNAmuq 20.23191463 +zcDuiQ95jMqVuonXBPpt5AE6Ni7Rkg1pYfFpzQGaQATmEyibniVH4i9v8sfHonks7yhtabY4ejo7gWZ24m7aAuMVk3DjumZ 20.14678889 +zcD2FGHrWT4FvcEWMaZ5zxV141DHCnrEYg1q8frDQF5y7RDSgCs5v143nCXfBn7cKtYaN4jrfTUv9wZm34jfr1d8VgpTGXV 19.82685525 +zcBbEc3ECuitNZPEQ5BfuqMvg1qRtiC7HxNdVBZjkcvFrkpoYwP14BngJLQCtrJS4ezoEkwcxhKYuMRjW2WFff81fUJgekt 19.72563482 +zcWX6uiUbp7SP5oFxJ67ugoJkoKvzdzfPMCSYsoADw3zLyi3hfDSjZr2xAXtxBupQ61cfe3GcvxbHkUHAHcByBz9uwgwHfp 19.66252996 +zcNQ6taRHuYzB1QvQxH2B3NtftBZm988t9u5Jr2sQDuWLjUkNP3LonEDxtdRH16L1cRqKC8MatxUqe5QPGzJgdPrCQKPxbb 18.87356815 +zc8YToT8RusApNGAwtYm88fMGttoz629UNGjE4aPKTboegSYxwbYFnPtDKrsDxQMVxiAq8h1aqQou4wmfrgf6pcaF2GPW1D 18.75564195 +zcWnWusLbDhULcGx9fnBVfLTkZgzSKNaKpG5mtUHBdb8JCCPrKTjKhaLuhQPGfykqNFdwx3BEd64fQzDDzUWZxySYrndJhN 18.44706590 +zcgrKwxcLPtq4GFyXf4PZw4VG5D3vJKXZAeQPYZVBi2UbomRiy2oBeCp4mp1frt96Y2DT8bq9exrpcwthLdjtu9iKyioPa5 18.33701199 +zcWEkuFbyZq4oErGKMmoxgiEyiVsiE9qV7omqGngZA1AGdZAJ82HzwCEp1gteKSDq6SeqwAqRUPhGKbCp2p4bzCi9QvQ8nw 18.27825874 +zcgPXmLNMeiHzNPtcoPkTzKxctJy1e7ppvS1pi5AGEow9s9KbqkBxWh9qzbA2B71gN3zfoPVuDLgx5fwWNF1UJ8nox6vQS7 18.26277664 +zc9Kg7ezv78UEwRo7mjvBTmGrCM9pFHMiAr6xHiLpP8nxgw2T9RPuQd4K2CYf2asAUy39iAy9978CxcXKyTLJRD31p5uCfC 18.21112063 +zcce3Rn3zJHNcscSZJ51c49DnM1tuZ92sK1mt5QVBkaT5zoiXXpQFRN36Yzow6hcNX9DbWxM6HxrR32teUdLJ7Sj3ryhJVp 18.16676438 +zcdDHTkqqYjbSq1YsWDfyKem7DAbc2M2jb25UYEAEFG4pp9G98yhCxErT1K8jQFNtKJ7raoVByg4mWgYkc482f7M3wSQKoB 17.78603402 +zcFfUcjPQxhe4qHwEaSa4Dqz8FwJRrFZtgJK9MHHTWiMfT4FwtC6dSBUm6cTABBxXn8zx4tVR6fH74eHVsATB1r6Uw9WkX8 17.77314899 +zcDG4CKrNQ3iTp56qsSPQS2fBaGq3XrgLKT69Unu5LpumJQVz4ANWjQCVb81iTAYbSd1QhLYXqZBvBLq5Qc5VdfGXSePGRe 17.76597859 +zcMyKf99CwbpEzyvxvAhDQ9tHKUqDeNMv4hcyCCfQ7WhjwL1gbUpXEoSesUduDJfkHvajbp1yj7yQsbx5US22fHkPMwFYP6 17.44723402 +zcdhRpc4S1aqusxD8QgRwhF3sRFd1dqUKmkEyUC87rKVBAPysRhhxqmU1VsdRygdhfgDQu5Cz7jaT55Ho4QsKKQWDKrCkcZ 17.39183194 +zc8NN4Zedsnw5qTTsXE2Cqdjvz4ZVSbzdQaeBox9UiBHAgaH4WAfgzi1gAR9mzs3kR7W469kKhhJ4ceoisZ2chPatCFJjbT 17.13894275 +zcAyUJ3SxEKJjviQz5a13Wo6jpU6ZZ4httHmgf4N1bC2DJuUuYXDyCTxGR1rmkBy1dbacyYhxpe6KqDMLViVaQDqNHLNNFx 17.04606789 +zcMiVMrja79ezZKiFnQoPfCCasmGERcGLbofah2DjYYfiajNFpRyviPW1QwjeJ8fbbxAaAYg6HWoPDxNVfqCWaoQ1rNf3zP 16.97160167 +zchesfAxM6LxKRseFqr1tkBFMd5m8zR3u8toYGy33HQRknv7nDZaKRnpSvcD41E3p6y3ofZkV5psJAQ9J1sD14Rme2yAuMU 16.95480328 +zcFWoFeYLAncEthCakSmMLvZ16QgCRKx4AbA1qN1CmVqsSKeGgdv2C6CeSpqHKZD9S4aXfdQs2UAHwUC9euqTTWWJqHdVXx 16.84674291 +zcPhKn99huCuArHsUFThMQdPX1seFTiQA41ULW5Uyx46uMG3ZzM6UPVChCVdHgSCZ661k9g6bcmZXJuABiDVduYjS18Gzr3 16.84246164 +zcVwCto37wYQr566oCfqACiB9vsj7gt7xDJbxv8g2M4foeSgVFYDJkNu4tEp66axsgnAehqpfeiAWNGbHzwLz114y4kwqbq 16.83844645 +zcA31qH5Jsi4fh7PUbLQjR8evkuJhhBfND9veCtGwuzAD18rESC5wNahhVYxg2zshe8Vv4CGsjsMnvXpPVEtgwq8VqEh7MM 16.65385522 +zcPRnZ4Nm9vn1hs5RDQu1ixdpsT25Aiw7j7fdTyX76WLnjPX4qcaTdQXtQetFZjW58Dfx5LsaySEELkU7HWVVLdLyvTemWB 16.54664244 +zcCFVqK4htYVpXwUmTLYy6WRwFyDGXTsDrAsAkEbvF34FxB6Fi13QwXBjKYXSbVUopQ1rTQNDGpAspjjQkqTBRxukGAgPKf 16.47690769 +zcHFqucwS7eFWNBzPBMUfTYCP4GgJjpXu4NEJKhgVwrqsqHt1ewRGep1PQwpM9Pm17FjRPszbY64gHdyEkAiJznd4XkiJRq 16.20813633 +zcUJKwswAkc4WVGAqReHPCsRnQB4MmyjcUdNwV9zzAEhUmLkfDFxs2TmM71FxR7eD41Xe5HhxeQ5ECrUKD8ht3tU24ULzjS 16.20615214 +zcF4j6djSivCjvoTaVgqk8FnamvF4yjT3E4Q3UUEtZwnmw2B1WFN9wsV8gyhDNYNLhcVRBmZwCsxn8ARB99xMXf24FN46wg 16.10151071 +zcXZGWKQaZS2xzxpTpxNWhrk7oK1FqiUk7VTq7TZbBY3ZYqpdFkvQ6aYSWXgr9Moi1Zo53e3XCjnWUptSehAdwjxvYU44BE 15.97715148 +zccxqrP6uHKfgtraUDXqGfkBiSjT64xHXpMwPqY8e3KqmTBwQ962PRkpVncvxbrv9SFunVAVQMTuHgQVzMZATFbkNiYS51K 15.92218694 +zcGR7wgoEewi2QZYacM1YKh92hSa3eQhHZonSzYDkAjj2jse4PxBsWshdZgBYVmkBjGQCQMuaDiFCRjFnCYgJV4cm3pTcG7 15.77869920 +zcDPR5L8soANkAtYJhj1fjDmqprja3X8gQ6iXWGWcmCUqmKBnm675bcu7V7C2wyJqGsguV8bpKnFxuuGSYwqzZDuQAwfzo6 15.75508716 +zcQdfwswqWJp2bwgeoC7bkWsMWPFKRCFxMFBuyVoLh6CwPTm4KQ65GKorsZExiuXXm2VcKfszNZqvukurPHQeZP9Ew5A9Xp 15.71953835 +zcL69uAv5vnf2kNDpgvgrVVkGCKsPhkRVq4HZ31PCU4sE3zqFEUvRj59MRfiqdgaNP2VCHCyBZkYJjkgGEtW34ERf4N2mRD 15.64005503 +zcLiPufNx2NTuyEnPzcoDW7PJmjne9m3odGXTCy3NitTfKyn5Zyv1sYY8LE7Ff4GuEHdzj7QHiUMW2UcALaDLUXQ7g1gUiv 15.17708388 +zcDtkFBMpeQmbu1QHB3Z975oiqdbN5j3Lk3MNckR1bbSjMZonHx9y1nzPuMtYqmdyYx4RkukQCKJ76YYTTg13oBzqSZcWgd 14.82093238 +zcSmWLEK7AqziCjCs4cVdu8yTydxaCVWhBmY61yE9UyCQv6tR8UnXL8m12PBhR21LxkietD5QCMyid7pX2zeDefdzuFupP3 14.76472032 +zc9vNqmvb393HRcVPKFgUuPb9mQERPddNG7BiD7zigZFVgmwiHMVxRrNuQ1yTCz73Gij1BJmbBk34sMuy14GahG3c1SRu7U 14.62968526 +zcPMMATmJnqVKMVhM9hczXSrejB31yUcuhVdsqWL3GanfXXHFavkniHogWZfTBTHNY5jLtDBmtJRv127zYz7aqnTKDa8mgc 14.62190020 +zcY4BF3ZaD9FfJuD3w7p3FnxiqDVjtsNYSqZk4rX2bBRbFeu7wwWwNLtMNoN9j9rpVuL7hXdHrDBhuMJWtErbfmpHgsN5f2 14.27590032 +zcWhKnA2nA2nNMZza78QWfkmYXHjKDqdMgQ2pi5r6LGYpaSfs2W8BpQNfSU38jJCnx9rtu5qgYjSrcBuprg4cyeKU6nRsCE 14.07996253 +zcVDSJMEQxS93DJt11ozWrsWegV5brhm9QFjZK6RKkWSqmJaTr3BRiwMwm8Gsp5sVoc7EoWZrziHtAyW7jQY32r3qte9utu 14.06486451 +zcDbNiNqLjw1C3stMjjDm8o6g9JkrDm3wedJnB4U5jRPb9qDR36rAwsMDWaDQAWgVPrhXE9YPSFV8dadttd9vm2nbJPUZu5 13.80687197 +zcL3mX1AXvho4L5Yu4KrKr2W7sPF9zoqe3kBQt6aviXFbxjoXmzjdJD7jVCCEpxJRWk7Q8dFYZt45b5xkVgd1Am3U55XB9G 13.78532672 +zcDEbSq8NPyms5ueaAgX8gtkA7HJKTmS9NRnJUzkpsEsKbfhAQUEa3vXHE4qWAcCxcQqxt3j2xUsqQvJzuGfHwVvVVL8Ggt 13.74740267 +zcBVeZ65xSo3KCyvTiyQFRdqZTyvWfzGWawmYPzABhBubhY7f7kdLnSoWq6px445KWHDXYf7YHLx7sBNvR8Rpjd69FqhT1x 13.54790512 +zcTVfhCavLU9yqq4X1Sm7cTRaqwJVQyRM8Y2LA9RAvzgC2F6hj5jJdwgzdMiCLhU8BeMhGhraThXnxqyzotU8EBfLKbXhyY 13.53374466 +zcSeHQm59AzufCWGWRSGCb7gsxt8NrXGXC6hTjon2NM8V7dAGVTb3AGKFNRtarfqiTyNAL5VrUsbnUBnvBc6QFPDiaRoMGn 13.42975846 +zcYwocPi7H2YkmWa7ujo78Wn6GCRbG3wMSRTaUhwVCe8wkC6JssS2MZuCe22r3dJAhXXcnRacVQmyRqVXmpMTrTn5pgAkXb 13.23998964 +zcVHMFLw5i4tMYywX7mPZx92WhfUddXv7xzFKvdu1RUNTHFSioSefa7A8jfe1jXqDwXYJshDv27gKJEmSDRVXLBHBkaZzir 12.98798224 +zcXcaQAbKP83FJBwBSkDWdekxMcAZ5AFsNJRpXWafMjhKaYER6cfMbumHcHGkvzCNEHcP7hiXTsupsP4s9zunA33ebC4ui7 12.85761953 +zcWjoQffPqTY1wziHUSbMnZzpRPewyRKXmhyKfW5PNGnkZXe4Djd6QjKYrHmcCUvP5sRh2Rw32dt5VJxYT68FX2fGDEdvfn 12.41537695 +zcXoDYDkVuNpMKHBmjLYgxg6RaMVL21taTb7yJ3eYnqV74bWKuhKYfjJTgwSN36XMrUXVH11xKpJ51MhMovsqoUghXe1Vht 12.40037090 +zca5sRgWifS5EecUjXebsvCd5Lvbzp5pxtTp12jAs3iXK31jq9cGas1CwjVwZBvf28969EvQKetUDu5zw5AoSNFArQdLjVY 12.26768130 +zcHrfMetAGL7Rq2UfQ8yaGPcvKcSXJWKf3Cb2WLe8TyvkeTwx9pii5DGscda87CQCwHfWMNkCWRer5DPBatbKGsfYFwj1Rv 12.18733538 +zcBhTmHFwNPeNGhibzSR6AUcekMSnJPxm8RdbawmhdKmMq7JamdisCMag7MecsainwdQAeMWasvPpaVxnJe9zrC1RYbmHr3 12.16273018 +zc8dxN5eM9zdxCk3kpeFLbJepa9b24fYz338EHZYdJr42zx6YoVB9Q4gNBCLzmpDnAvaBLw5PwhiPCsqNgpUrqUNYyAr9Dq 12.00928070 +zcWjBrc3aEhod1dt6MWJ88k8mGZTC5h61ooysnCCvCh3w8tQgWYnXcDoRZaRXYEi3qQ8Bp5P1qxKT4pmQwpToBKkf24tva1 11.78200384 +zcLYvfVypFLqf4Aw6FK8bKPB2X8Z6Qjg9o6D3nFkaxquddpdfBpL8ptfeqCM4ypF4bXD3uzLN35ij9myYXXAxxPmA35ivFU 11.76184209 +zcaCzx6E61KNB4CuDh1abSN6wNNeD1Mqj7Cn4LwkioryKpwURECopgCN4RYvr9JVDMuS4GLqiwdoD4krUiPQCACqM8voWYH 11.71317741 +zcKmqJAEPYo6YJVTd7kJP4sjQvW97XMwCZMAMFi9VtNe98y2o8tb1QoVyAsQNRb7PmpAUuiRu8xqWSbqC5JpKKdrVdaDFs2 11.63395171 +zcJLEi7JYJ7Mu68ktkfQkw1M8XyY9sSYWZtksVR699NSQzgFnGUYHXLxd51sZYYEpKNFvFKRcScpbGxpL8FJHKxb2dogu4F 11.46705848 +zc9sTXaqicpJGosW8tYmiL8bSkFygrzTHnwK3gy9kBzuouJjekiwr3S7p5kyf1ZYZDRMmjHaNAHreQknLLEj3UM77moq6e3 11.18597846 +zcBCHFojachKPMcZ6j1TgpoTgUrPPUG8ukti4JJtriaJomQdiH29pg62Hv1ugZ4WaMLZ92KC34m3EQqQpDmMvT5nyM1MZCs 10.99741969 +zcEGjccVDS1VdW2BuDhhVvZiz65pRgVPUQLrWRQqxYS2ddecfUCktnmWywrwvArrJDKcNfGxstYwWh5RvhZ3i9QVYGWfnsb 10.87189778 +zcU2F77UaZ3XRpPPXj9jRTDrmXR3uKC5RgzPBcDtzynZBH8ko7sMGZE2J9NdxAqX85UjSTjbxS6R374wPsxnD5RUSka1nWe 10.82722449 +zcgUvA6vRXKFK6RSY5Cv7X4Cq7cQyehyVeJQSYukEqNmv5bVD8CBGStSghcdSnT6ZXPBdtx31bEp5Dti2fzQ9yTcamDV7Vx 10.71633974 +zcNxRNhLq5CUD1e2yzEzuHWDiRLGMUu58VNw4Mr6ZA2NxnP5ubPvGAdtM3k8ZRu9gsXiWsa95qxgVBR3bSabhGrNXe4awuh 10.62771043 +zcNUVwT8agq3Jrtwv8Ny7KHwW69XNoA9xCTkquhfA9dG1ZPn6z6hioSdAsd4i85eiTJQSookUyWUhPfCCSminN19CX7o8zZ 10.45277669 +zcZaHuecVcK8tydd9XfCB4mrK1u4QnAV66i826ufMffF2xsJdXkU7m3saZJ1QW4v5m9JGBQqr1tVmZskz8WRqwpmt4fhYxL 10.38852761 +zcbCKqsFNTuf3L1sy1BjJsFRVjRLWBcCttEC7oEdjp9acx8wcGKaiGeT7qkFs5YacBrZVFYDY67hURpaWvirLrjtnZnWmNu 10.26536784 +zcSYMJWq6pEJkrxU6fgaDfRyPYnYWvHymxksRP1swEJ693o4Ymv81qmEmiafxTsJGToCw5oQkaJwmunHRF32NiKE5vYnCmU 10.23922495 +zcRnvDSjYboB5UxTTgJ8ULATRm4zWyToKoE4sgZmGNBYUz6Jzz4pt4MWCc6fNysPJcF4EgJZYHAGqMAaumiws8cccc9ZfbF 10.04815724 +zcdY9kRYBTiyXU3b7sRHh6Mt5aimKv8EnHyCGtgTaaUYG5kYwcG8Hg35JSJVYKxTHA5Et6FKp92AET9HiVE3fXQJ5j1rEFP 9.85691643 +zcLFPiXZvCsDAeBXTdRohtZftKd4AG2svLzazpqVvJWUcyhL9QykNNKMU3KcePmv1aLZ9jzAjiiw6tJ5KvVAin5dXYLua2S 9.40613688 +zcAqgt53GV8yFqnbyxeizAQusa7Rs6cLe9Ff4K3KH56s8QCHstysh3BmNYCg6fT445STPcgU547oZBv2cn8kRsaViEBk5cL 9.32641614 +zcCD2T95rLdaNYNaPxmjUtptg3MUeg6B5ZnN4qR3WP37ZCfMkWv54UgDoLJZpqBUZQsytgMeMpYMAjzvKrr8YtZM3Nbxya3 9.25422476 +zcZyriJMTBJ2mA7saeUTHYcaWnv9zt7DoaGiYeEAsJkDqp48mZr1oFqTT6VUHTr1Bx8jQbxv1qXf3zUnDWVBdvHaNXQD1VC 9.21124025 +zcaanUmp86yT9BCNrKGeVK7A8Gaoqb5XZ5FbxYUugipD3Vj2LeJMMkJsixaqMZpdMszRitRPqQMsotUK4jG2NwCzp1VKsYd 9.17428857 +zcNs7EaPxuTo8p6iwQB4LBk2CSPUfEGC8ZGzQx4QiTMKHwrzcScJcjtCjqC7isvxQVgGbkJQHS3CyjjR4jFWZJiZxAmELQ6 9.09828134 +zc8MvcZkesqmAFGK43tgRoMN3aSBGeXRtSiivekQJQinorqYMFD4hs3kSPPkg5VvgjvjdzwGLjHq9nwPFreZrFwAXsTykFd 8.93727156 +zcJGJSCbwUnA6W3edGEeX52ijEd594abGZcJyh7YfB4Y4Nk6AoSDxTtWAbcZFDLHAeFtASNhNAVkyeAtTqKZFju2ddezSUn 8.86059113 +zcPUBZLfLwSxjgAQ2jJNNPYMujAxfxxwvFBbH2EvmKKU9qBHyqATbVviP2pxbXzFu2E7U4gkJtwNDjZRGTwJkT9WW8Ak6bT 8.77236849 +zcCq1CEPWW4Vv3cGWss6ouyLCNmQ4sKSmeQLtVA2jkQTNesArMe8L1atZDW5fiEcaPtompGAdFeYbz6dZZgHGJT3SwmRgKB 8.63935920 +zcRtd7QA8uBvhEpigXFJTaMFfp75VM7Kd7ZyRreLR3c7zmuePBzWpynwhrpoTaaeVgwfVE33o2VFLgXsZs1beevVp75NXsE 8.57665912 +zcTwRurcmhdx3EM2vCy1BkdKXsq61VJj3qSXR9eRTNMKWv55zo8TgjkTmrfZiB1JGKiBwAofS6DquhVNAfr7Tdq3mvZeALp 8.49000524 +zcBbcGrQZPfNFFHAC8475F5dpZQu2UKMpjCmYqniBzmVNzTmY3EpsrvDK4af5uRH9NAs9MojTQSst7Vn6ad26ympnX43fRM 8.46860739 +zcf9CeunLsftdFA7QogwCU5YSBJUMGMUqv1GHNf792JMFqyUpNComm7dBNNQ2faced9VeXjGHerGiZBhHHxVDFnBAhGviVt 8.39185023 +zcP2UkAs6fuKdqgaDQFowzmzXgZ5FqV2vbiiExampo7SCkBb991iu4Q8bRhywkzjhYbzYcZ79gAaYxAdrZfWQ165ESSSxDW 8.29917986 +zcRcY4F15B8mn26JjoBo8tJzyr2jfpWSzt1FHr4DuP6HgERhsgXv7FM6j3rzuG4PVyeoYy7CgDkZaP8sreGuB5NHzSXuwDJ 8.29283624 +zcMYSv8g3k2yrFjrbt7WmPSPxjd8YFLYD63UahfCjJxL6TurFgzyPYkEYk5cYwpjPRQddq7NvSYv6fgSjGEpUwvEP8ttQkp 8.12433757 +zcQbfpp3ji7Sp48d9znEq3CxtYshENrP6fD1GLAcsxc61NHZxCAzGEfv8Enin3B231rFA4jiqzSPs7PCePUc59tgESVFjoU 8.06972013 +zcD54pdMkrt6YcFDWWswrYX3X77YGLzz4aDVdWvQiPEgXwUY1srGt5fWWb8ppaMfKcnySAUufaXmwmDSfKQcbSBCpZj9gCy 8.03893356 +zcWwFEGr31qT41ndDR9JJtxy6yE6vbyoGHM3L93xAfrpRiVz5W8gcnnPwkrBeSdMdb92bqJkh522vB9EmnxEsSBkCAKbXKa 7.92741467 +zcf4Jw2ZvfxX7sTWnTBLa856HQfKGMmRaUpPVwEFPn3v3QJGr9GY9muusYPHiy52yCXsPY4EdfpBkTXot7C96iB2PirhFv7 7.76377816 +zcXUA2QEJGSBL7K3bLobzTBhN4FBxpgTSzFmYt2bsgF3FkY4LF7LmmBTUgKHoBzRJJ3hMsY8ixoL5G2EsKB185LQWkabuf9 7.74828910 +zcT1MYtsKQvqqBUq9FFUfXcAGVAhebGurHJYxvkusU5w6ACdaXci72AEjLiRXJaNvioJWrHBMbeNNEBCVwnKM5tFixcAm3T 7.74454515 +zcFxyXGCgcFisibpfeRLfVVVwCcaTeLi1qfr6sFTDzZPPUZLpw2g3ApSaYSs9zKAkzyqt7AYGQLBvZdcVDkQKy8ipZnDMd6 7.71533055 +zcEwaF99sy1GzkCdHY37SjJmWXVEaVuAQLvPgJ7uWsZDhSDBm3uZ1LAyBkYHEXWHAZYL88iS4ZU1ZQjEPCmjd3Qv9cdFB8t 7.66433980 +zcBrPC7QR9h7a73JnvCzbacW67VL5ZTcPdBWoEYj9TEVL4vcANx4G6NVtRe7tP1iM7YUiaUxYqULPmMC46BBkEBgqFdb4po 7.62130390 +zcNzAi8Knsznpn5zEsfXBSm6iUTncKjbr9Fp74YDUhcnFxPNPuNimf8yZXDcLQsy7vK5T8GSTkyxrrFxWd1Wznq8TMiYFWj 7.60870480 +zcME1hi9Sr6zkjVKabMefSFSvLeX59mCkGQVkpsGMTkaBqQuD2w7oheQUY41zg8BZnYtEUwGxrm3KQA1RCJHg6SLaZWgxkT 7.10396527 +zc91RBNtkJRoFuXPsWy13b95VQUnirHCmUQu6fs9JhbCK2bnrtNzEUzq176Ldqq9oW2Fp718HXgcAam1SM8VuCE3mfEaDyk 6.98450491 +zcRPpPBdgbQURqjLGYM41KUTemXrZbocBKSEq6RoRWVRkH4Jqqn2bbTXd7tdpV2jPtYw2nA8QYN37WG75QaJMXtwV4bo92k 6.97753725 +zcGZrZhaJFmx6q3MHz4mVfmk6wjfrujq5FKhbbjCPxczo1rvsLE1Z24XSdd6tJ5N5mo4XAjEnBXDHw22xQkb5Go1vu7WEdV 6.83974980 +zcc8vaEHvDhA5VQQsxLdTyjYKpDyttn7wh5f4Ae7Gb4Wr9NEfvasoQow4pfmB4zSuEJiFxuvY5wcKZTkBc6udKBadoVJG7c 6.77618041 +zcWRYVeVNNnL51pHcY15zu95XSD8wm1Po6u56c7dCNJiiU4hP8QbGmeTGpCQ9VCf6jmJH2RWJyPQYZauZVHCnyRXGxBrPXE 6.70483512 +zcPjDuMtRenDQyH4rDDr9GLRUGHbvpeoEFiJN2j8u42jvRfgkNUhq6eSxW75p9j9fhDPgH5x4bMnkfgthbbRkzf21FFrG2Z 6.69473927 +zcEM8PhHMaEABVJ8V61jL279C5W7XPdiD1QS7HcuKBeL2GiGnRRfojsNws1yR9aDcZ45xs2BQquEV2E3vVwkiPHjAC8rxCs 6.67425853 +zcbqcmdiiAimGQdgjdYTdCUNKvw7gw35J2TVxoi4scAL1KQUYbWSTJjfqNic331QDryRa23gNvKv4PKgai2mam1wC8wng5L 6.64297988 +zcLyoPXNDZP3xtPNbkBMp2UASZpABW1VfBVJzKqDGDLSAHrjghYHdU824WkKKc9MR6fXW8ZgQF4s7nHyTRS2Cpk6DBUcjPc 6.62065965 +zcS3aFFUA6MP2szo6qn3qd78yyeVkFXvfC2YvAYtoUfDnN74V8JRZJPCHVqKJrW17DzGxTyfpJuvLVeyLYo5n9Mm45D3LfJ 6.54542940 +zc8cRkqsanf8RLGe1WWRDMKKpxsuzF1CUmCWjpWzuh2EoXTJahKCmsRyB9ZWBUkd81NK3B5zo5Hip8XuJG3sjZzKZHffhGi 6.51536997 +zcB7ZgSEzm98J1UZQt3GnQ3uN3V6KEPQmVWsc4VTT5G2BC4CZjHbGnUP1PgR2cg3NKRuA6PVtmyyhqTMwEephqkHYqRpJFw 6.43918117 +zcSU5hYMz8HsKKiX9JyF26Y5GsNki7F6srsKjHsSf8QV48Cx2FqaWZfqwFVZ6eNkXc4fTELqLEBWu8Ke6tTBdno74oMHhTe 6.35338352 +zcWKPjthaSc3cdW96sZRPArXTA3JRvMfQJFwnTNJ8KZdnRHfskDxi4FQddiJ6tTrBrrJugnMPVoyHLManGyQ6GvpiFYRBbJ 6.31075474 +zcXyubuAiLm5aHtxpFc1igvjjGMxRS1YY5TPE1PsPuRW7Z9mfJTvJNy2KLWqkyNg6xDEKG7RDtA4cCEfVYMFMXkLyHfyxqR 6.23039031 +zcX7icZaTQy7mggWn3M6MRvovoTc5exGZedNoqds9HvMZEDNWuW9zbMfT8EjxMY4mf3zerMvr2mTCToUHFoVTq5hx7conJL 6.17998676 +zcXNk9GJGz28Rta7r7iVSGkdbjiGE9WRtcBGvqvEWAwfjciSSDC3iyM37HU8fnRwcrYfvS2EHz9TrujFfw9TyHjyj8rxS9u 6.15083129 +zcU3Bd9BUEc1i3G6kc7JuGs4FwVsTCYqSAHN8C2VUAnNW8uzAjNtC9xfLhDu45rj81WmzaJ2Mh253NsayKGfnRCL4ebUiwN 6.13697978 +zcNqczYddMfd6dGjpPwYFXaQjgRWY35CPZALSb2fsk1V2zXpSF2yF4vEtnMiVyoyfrUYvQCr63Uzmr2jD81GdQ8JNfxDcsU 6.10953112 +zc8LwdBhPXoYp6Vof6TLTFTipGPjsiwUJqzwNcyJrHRGmjApY8J9L4aUEjXGKaYXhesPb72N2h41ieM8q5pcQ97xK5Rttw6 6.09900801 +zcMEQQvWcqy2tUUFsa1R6Q9sFJGLdux4pXzGpKGDck6Sqzywn713Bape9GdNQm9PZUniJTderdS569u3uzQU8czCV6fSy9Q 6.04024167 +zcASrHKhuLi8H9B8hDebDyXkj9fNUMKqpfXeQ3hpg9dPxNWacQP5LqWY93RwNjnwT6afKp8j7sSpfsYaEPtoS57AzKzQXdh 5.96066956 +zcV49wNsRt2Jn1PPDubuZSxQBcPwJ8C5DGAxHBa9CMa4dU7CYTCT413cz5rwyQMHw4SzoGF2hHhmJvSyxva2oPxxn1ZLzT7 5.92471494 +zcQ1XZePkYPTm2DCgabb4J4ierLL6CBLuMUktBS6Q83UKAN3DCZEcPRRrNzadyG8j9DshZr4imXBB5foYjzKaxbizepGHyy 5.91680783 +zcLcfAw3pViN6er8ZiX1movRVAWwUaq1v81rZUmFKjnmZ2uZrWpJBszPRkW7BGxQ4Zot2cUHCsUzgDp6sQBKVRcTHudLzMp 5.81088732 +zceqDgpyRKYuc75h7dmNPHVdY2bXjuec3GeMT7nFphV2BQUYSgAq83E18CZ1gPqCuszFipBq6DGPZFpGYQL6gQoDNm1DwQb 5.79533679 +zcGvvoiCPhDnXyjmosZe6EyyAMeqmfCqU8ZXTmpknNJ15cZ9M6bA9i2SC6cVWg9JSeNa4CMJVg5TC3BPpg6epgfKs8gd9UM 5.70757683 +zcW73cZUmjv8jy93LKvo2p899RJahXxxi9VzD3PdAgWJN1VjRwAoL8fkM9iScrnfMFSFbKnGpc5XQxBA4pVbwj5Uqr4BZj9 5.53433200 +zcDmynMGkmGk9zP2gWJcFv8hygdfyMEWiUfcU1dUihzrvWmfsk4NZ1Qisw56FipmN3o8Pv2rcxqmCCkdtanQssxnr3KUdft 5.48904802 +zcG8jHgXaGcSk3Yingb6kMQVA6ag35xysB2fzi4qnLcn6nNiTuZjWyhP16VXqex9wcFVQD8RnFejdtwP26zXeTxX5uvBWu3 5.38652942 +zcJeYzmeqvT6rKEGMVQjtmnmmHWaQDYrDZE3bxf7S7xAhQXjnioYFYPY3A6ZVdPSdgXjtTHvR1fWKMy99RjoFfNMiQeLHos 5.37672377 +zcfmWJELckgWocZPVdN8VWinq7pKC9ZDuy53sUw9LrCVo6FXvHzDcD6y6nFSWnq8vzLHvPnMFhkqwmpVRzJFirVxvCZN5Ug 5.28693304 +zc9Je6aApwa3xLgCiYBQRuWUrBSvFcqw6SxzY4KrYjqZsGabkCNNBSLZWQD9iJe6pkmCCbZPSAgRinjFL6CV6oBRPkwJrCX 5.17444299 +zcLMAuES47XZaDdMPUEgZkkhwP5X2YgZd3HtZ51pYvn2ok8SJJYArCCDxQdqNeiVJ7KuFwHWCZ5WesuDQd6SZiwiQ76hms7 5.14626591 +zcVuqK8SxmugqYH5339z9ft4CwRqb1FAfPcgNS2ZkbE4Hc2CzyuBXDK9D8T4cKScMs3J2L4CrCr96bFGVNM9Lc7EZHww3FT 5.11714394 +zca4mPzUxL76uxWJeB5ihmQJkwWMj3GU61NsMWZPizy9ndgVVF3z1fJXyVDoLERXccwN5szPSvJXdVc8QGpct5cXurhCfVP 5.04229045 +zcaufdBTX5hNTbe4LQxgy6AVzTqJ5ET6DkvKPEbxb3P7iAMTB1g37LR2gfpSV31BdCuUE7YnGzMw9N6nAH3e7K8ajFqYpSE 5.02753040 +zcgvZfRhN7EqUGhcRWe4CCy6a9XbYatAdJ8pVui5FdE9NZiLrqSt1tiYsVRnVnd2cgRKmMtVxsG29HzioTHn3dbx69G7mei 4.99371056 +zcN8152bvCn6UUC2e4u7DnX2RoPMcJNsZyXhTJt7naLWdQWwHWfJ37wtjrMK8J25WeGE6u9K6SZW9zCmsycYjUmNFyhpPsm 4.97482482 +zcW8gRc37xJu5mGtP4Z4af59czZvW7ey4yP7u1Avf9ULZrdy6YaD6qayA4RCki6cTAg3sy5hiY9Ly59Yo2AZhYwJyEpLurx 4.96625631 +zcKYKid2Srr3UskLGc5mtTTmyM1SQcUeDaEeHweNGaedwKYJUq47b5f98enqLKjojWGWnd7fqVytjh3t7GqPiaKrBogwC6B 4.96295694 +zcf7qH2k5J4qVXBXQwee7WFMsCXAXyJb4beGe3P9eU62cvaePjhSyt8J6LyWEkivgEfAUibohYxP3MtWYZ4djF88Sr18BUa 4.80842073 +zcbM9ou5pycL2xSKbQsA61wG2dJ7uvhKZMdqcgwuxphh1rnYXYfnkBmSpszaqd7CuMYmRYEizjEMTbPdmr1iZDq3hxDABmr 4.75410827 +zcMXFQwvjEX3yg3j5nc5jMT9WKzjNNb9mbQW63vnbmg23upaQ1Nr8Csz3tAeKHm88Tkq5AdTeR8npXbkSCEVrorPtanZeVY 4.75026342 +zcQQkxpycC9vfw18Uc5B5cGvzovmQZx41fv9f1v9EWrzd912LhMahERJyayNGcohxb395KVZsmpF72ZsrYuCccXrrsYosQa 4.73024716 +zcUW5VB5JuuU39FHeQ4oznTCSEqcTn4bQ9o2KxR7Rb6nAH6BuJu6qrW4JFKn5eo7VHTqPkefnwhcXhqiYCsDg3WweMCDREp 4.63443810 +zcBT4VCUUF1WWCPivFu86LC34wQbiDeMC1B2U6LQgKfQquAWWdjTKVubNw2FY1XtqBk4mstrepWoHtTUxXSFMB9JMXF4JoR 4.55779194 +zcJaUPazgyv1h9D6yY916n5kXSdsyfZtDC3qFcbRyqR9gW5XiDaj5nnWJ1gUjZa1C8n6a8wxgL48WRWbgkJxCCAdtdwMhLd 4.49385493 +zcBPQRvYjn7Tn4yFnPANJ6Z3yahaZSxzDpTPDpVHSnadu4cPkgGoGAAR4vqgKCHJoXchRsc3RFd59Yd2HoXtwK9mr1mqy24 4.46296185 +zcHiUNwiDukocg6pS9AHg3JrDdGjE5spzBCXy3sMxJZBs652BEnm8Kz2rChgddPSusybudynQnrSrQaLGC4XurxW78SgxjT 4.41589213 +zcQNnNxjrBMzwbMhNjXfgM2dAMj1mfjoZp8bSWMboHr9eJFBYiDPjxT497Gor3HYyyiBji13rDoCogGYMHyBS5Me9TxPkjB 4.39496475 +zcZVpjUbCo4B6w96N8cQuGpgbrUDpT1p4Mo1RLxdba4GdHhd7HoGj31nMmAm3pLWg9fDzRhwbfacxDLpj8yBnwnLVsSDgFZ 4.36492267 +zcAcZwiNE6VkomM1KP4qJzNBgYftqQa8SaVsLcfAvNjjFhKZ7T8hKgtMtd9wuqnrNJRLGbFNQkgQzMxH86GFQgigGGZgnyE 4.34515833 +zcg3skt9YpvwJYaJGdsdoGTfW8SX4LS41uB8oixvZY8S9UXqZjuz48DMnALCedqeHxdPFaFgVHc5ASdbeUBkhWMkssnQkUQ 4.30581173 +zcEVsJvn2PyUDzpxufoCFUeNQA58pEdGrxbSUiAZ9YqxAq8zDvHUkfDuHACK3x6jkSKyWZEZmjAQrBju63kR88A24SQgtzq 4.28166794 +zcNYzdZQmn4JfpmvJ3hQZozXgDkkXLe1NgVmz32aM4HuHw7q1tCrvZ3naYXUVdqXyMubRWbMqi4LFMvpnrKvS9mrDKSw7Jq 4.28134230 +zcHuRh8nWs5k4vJV44v2p7gzoXQyZxYYsozhrivNMrF5MsNuJkCJfrSfqzm1Q2XBJRDLN3HzuMGKBFjSS7RHKDa7TUzmZRH 4.18079012 +zc9etdsuHtYtv1KqBj8uQ8aU26tKoJTsCujvUguxdhQxQcEfzYv84CpCbTBF6oWuXZtEpqEhECvzEPevKnhZAncryjwsYVC 4.16323301 +zcW5hUCFuuFyWmTDLAJmMBziGUEQHRjQ1NKxqcHwHSWcUF7B3d3JBV7sDXanfXsC6ENEovQzFMNb7PXwsmmVjXR4BGxQmJJ 4.15227482 +zcTm2FEiXLn6RNp2PZHZVKPKYxzyhjWXM8BmHQbH3RmqpPD2pmnrrdXNfvCPxVxHasT2KRSJ9w7A7qsKxbnRov6zGQwp2tp 4.14396258 +zcGHiFKF3oABNn71maHfya4DAYEvk3eoAzzHTW86u6cas116nCEwbeYYptUhEbbrJdeFNFRyyrX3RMPgankQhnq6CyRDH6f 4.09486624 +zcPdR7cxcUELEAnnyq3vzmjG86jHChSTHZFdsU69KGvjcfYJzqD9zuBGLm3922HqQVUzaS1Z5QHc9rHzBbBZjHDESvZGcE2 3.85334327 +zcNYvwgtDhRgr2BgfLid7KkWbXuSdcJQMJ1i9V8tvrkSCu9MXeAeunwAxo79bg3vMgT9i5o1gF5hZojxcux8bvnvWHUR43P 3.83910217 +zcf6pyDRWnsq9Lctcbawcmt3rDomtvSVwHNGfLVC79ZzcgSMLDP5yKqtXCDUziMNr3GFTZ41GKpKtQssrsHGth8zNbrQGQH 3.83163550 +zcdNoddKRJnbXhRyegGtRFTWmR6GNA2iXcKWDLN9qtHpMWw9DoGP9HGywNAzVRi6V71cgV984mifHCKMrzvs5zUPrmzwRhZ 3.79856897 +zcZYvvzdfWGYiCvvcDcooh6mi7WwCUBQ2fjmCdTTh5oyRE723Ex7GcuQc1L8Z5FNCN8zpz6ehMk19afXgY2D2A2egAd3wRy 3.77183874 +zcBZWMv8dNhnFFaRLwn35FxiETcbzJ7PGiC9WRVzPAwG5ehAtNuVNKEULh4QP5nTg5FauEmaNHyHma58ZxDHX7XXkWWoV4B 3.76907099 +zcbRT8cuy8P4b35iosuUp85hCQNfMkUYopwyXRMTDS3qVWS8jr1L2G94dbBY8soYXSYGCQnBNeNentwR8UVWhRmsWWnrA6n 3.76691852 +zcL1pZjZnQry8y6nhTydgbbjJHFVhe2skFGzzxPgWAmL6CPv8yEVgtGrxa3B3KHrc8zoJguYRJYAr6qFJJfnc2zZHYPSrc8 3.76500979 +zcaKVaoeeg5eMuEvj7s9rEEukR2rBDjJkFy3D9Q15F4FqHYQtKtTfmHpYZr75mLa2UXyUXDR5tDgQrdFc7qTZ4QY5xhAFDL 3.73343896 +zcg6Q6avvTPWk6ZgGdDdMBNRF15pojaQbmxasJMNFFN46g3cz5jPmpcow6UrFnzUCHM82i14Dnq6jpx3zoWFaRWa1Ug3KXe 3.72007094 +zcVS2DrHP8nJchJ7MHnLC6UBnKR8ge4J9zP8c9JHKqMQjdNjUBS6ERfwXtQn5BV5mNQW5ArQfoHC45jrtGvHArH6TgAgWo3 3.68289149 +zcg1aUAu8YS9oYU2b9vhLZtXesdefR2x1SLfmnaQ3CaW5SoyRfhRHnnWmdpPAyTTYhEvPigRUQyY6fjr66Lvx8oqPjdkhK8 3.61930376 +zcXq5N9d8BJ2CBUz5t6h5to3UEV4h2rvgKmchxKK35vXDFEYynMW2ECV8h7JRUmA9LXQsrVuAP8THFQYArv62nrSVejzBFK 3.59247061 +zcXrvDWo4pcYotpNV5NvJrnRmBKxscAoTAQtjiUWSuBwTyfW2uv6UpdgMv4j8A4gwEQvZGbWXh8YLaYinrPaZ86zzYEk68d 3.57582014 +zcEErNaZkBfFYudawZMvmfCKoWTgC7MxJgrYf1HQJq6skqU9wwfDrHnfL1ZHV8ASDaXqU6GzwobeGgDvAj2Dy1U6G6JTaE2 3.54755100 +zcNzF7PM4ooCdmW7DgdffPZEBpk7Sx6gzZqPScLS8dswfvHu3XviZKruA5zo3g5dMkNSL1687AHwcWX3jncnHxDxM1zdknS 3.50835924 +zcYSEb7eoiqm3jSTXhe4uM4VZ5sbqXneQKHw7yP9ssLNwJL9rYCQ3Xy15cacX8KiVMrPbhynKMk1aQAs6kYUC78DYwU49uc 3.50408937 +zcGWvfjXUjwigM1nwzzbEk4G8JTCTSmgy3Rec6L5mq1HofZGm877wHAjmybyeXRByUYbq88vsqRPqJNFJWRF3o3nVEXZtUR 3.43060960 +zcEBMxDffhEBxLtgzNCdKoqmn3PYmGXowpawt9CfuqnH342WCCuYNHf5ztnqYNvpJBoa1kPhvFG7Xv3cXjXF6RBc3SUAbsX 3.39268450 +zcMbpwREfY7ybKUwMCi5M1nJuDXBxxDQr8CnLnjuwAfQdRHNNqHfSAAUv6MuJP4YBYjLzy8SdBcXs89vGz1oBVdYJb4bN7S 3.31288420 +zcRGPtKuDtUEx8tn3k3EijxxNzFVwD1VV2SeUqhsmYMfWJ11PNoZBouL6aqoTzaZV3GeiT8bT5Nvgtcouy3EK1bLs8apbe2 3.22095234 +zcYVumgc2i5HFUZGRea1FojhmR4E2yZ5zX4xhFkxHevhGt4P6uQKSaJ1dgeizwzFdMyhQ56HnQxcNKwG3iubURxjvzseP9C 3.10385939 +zcF9iMTsaFXjhaVjzrg4cQTubRJV1M8ZJuf96u36cofDSdRaNRwFprqTHgcKBzzkNRn4GJbsEKrmviod4RBawyDvVTS1LVS 3.06477450 +zcBsP1TBoZRbWsa6NUsUWZBbHcBGWRmLvCTToLtcwpVvFSafXaUzuHe46kLfvgRuWcJEAxjGZvJqCEwgg8QNgpUXbm5MxcF 3.04494901 +zcRJwwDjfQzHjfwpdBFURrj4FBZ1dju5ZPfLynoTWHruKnoQs6vUxUSFFPHeW9yKDi7JCKZMY9DfpAVhHB5P8ri4EaYKhVi 3.03407039 +zcYxfSd3MJbpxzkzV5GmJwjcNCEqie9kkKMsdtm7JejLHR8TEwdGJbwbgyZqUJ8UbLgLsE8ZP3DNd8HDfAGp3MsL26RR5C5 3.01623120 +zcKNX4HKv5BWZRpSgCGDRbPonQHXNL8fHYmYkDi69qcomkkSjhFKydmvuGYq5VSuBqENcEQsft2JR4sDZodVjHwyHFjRgdf 3.01462661 +zcQZ5Q7PS54teN7fywMhevj6xAzRiEeRXV3VYymzGHRfLjQ3727iWcBWWeYgqY1BJ3EnjaJUoJQ5ZQjRGgSiCBXN7B4EnK6 3.00491132 +zcayjPFuDFHWY4osVnfKekKxAoDoSjmuVPjWN2jRp87j4sEj1kofjp2NzRsZpxMAGMF31RUzH4qfwG4a6D4GbcS2jVZcjJe 2.99579483 +zcE6RczaoX98JRZ4uVrCkvLxxQSxQeDVT8oP4vb7ZCPVVe5VN3H8ig6jr3figNg9VSv1eLNyAvLhtKAMUYKtM2QhS4cgQVv 2.98320630 +zcLveCJfHjppUcnKjs4PuoCi6Ncz45t4tjE1FkXLXGEZqkzKodcEVcQDTThebGUNTZviMk1bSHsJhBGmsUA6Crvsx15vbnt 2.95475126 +zccVzFCv3EnjEBMVacxPecfHhMZqC7psq75LfefHWAcdaSMppzbWsFQmdjqdMno71Hw95XqLsSathKJhWwDskkb5kfdgBP3 2.92608326 +zcLpS3tuozNhT6pp38NNELtJazV76Kc83UppznvAMkYtoVMgVYmzmzyLmiR9cAcWSigYiB92xzkguAhsTCZLTikTB5jCUQM 2.92483272 +zceXxWQHvxuGQKuwAPV2WfuvnB9AgsyjfpV6muNopff5ttTbv28wLpZmnce4duVaTJRcBMF1cbkDDGGCeBWqWqgLABixzhc 2.80356358 +zcH6ywduMtrT5JRvmy5uis4mJhrB3dtLd4h83cBJNZsQPfyDwLdAsAP7K953gTZvEBzpQhtPMW28HTNsLyMnvyrb19LGTXp 2.78886954 +zcG4VbH548rgqgY3Y2QoSSx1VRvML9nRHedWGwapNQfQuPYS5VnjBJjtgmD9DDtgF4XyvyY6RCWrGWYmjbWTKXAcEVtGG1J 2.71732544 +zccq78RCcuHEUy6SaCJoaFSMpAYqytJUd942xosx1D1pd7LzcJtiNz4HWo8KwBNvKg6WtbPMG4RrNg5myVHEdsRZtBxgLv3 2.69998381 +zcAUuMgejnWfjyHtkg9XQ4fvDBZe2qBUsJ31wK2HWfcsuM3k3Qymef8bSUefJHapzzDZN2H3qkMksZqCwk5ZUhg4ZoDNpw9 2.66715432 +zcfZBdFPovSZrVMXa91diFgqmums2vS8zYGJGxKGYCKiRRKV2eafmWi4WPGTmyZDohYjm1KTDzPJuQyYNtx88zWhiSxECWa 2.64422999 +zcfVozUUQELKbi3zKo1mbbmuBRTMYvB9CzQRsNy9SNz4oDL4aVhJf7iDUdtW8Aib1qKKraGXbf6X1sokix1njZKGCx8cUVs 2.62664221 +zcHvq2k4Xuophx222QN8bsjyNZhWqhgRno1CUdfy4QTssjE7b3hou7BAVQenUm4Joy8izvQHhW24WimPfNa5Rioyq7xSkwW 2.58305788 +zcLt6NbiYRwAFRX5qM8V2X2quhoYoEzo1Fqmjd7zcRTb7DoawD1SRRDJ9dV6s3VYw3VX9od1NQh9q8Qt1ms4KQhUr2ai3Ky 2.57327004 +zcHKHBkfAXYGJiXu8CKrQALJgjxHdsAguUjfjKhUs1NtsgyuU1Kpk4xiiX6vxDjeePs79KzLjM6cPJtDxSMFesLCJvgrrob 2.54795563 +zcXGvSkoaQ3Fzh2Y8vF5bLC13ViQBpSjMQNmMn4gyU9CuHNvFynRcJm83qSv83DiPGjQUUU1S4W1n7oodY2EuD35XPPHSjb 2.53237163 +zcSRFNpjrkDFpJibBPcRKpnVmy1VRJ9FZ4cF6bAUtJqqXPZ9xDfKB5HgYkBsvv1DaMFdCtYVzn95kdK3tD1c8rVJvyGnVuP 2.42974746 +zc9AfSAmeDKmpMipmQtFbGqoHYBhkGeWc1oSTQbJkKPJpcGbNTDfEVxC1xjQzD4PLhHBTZcpkbrSAaNFDrYMtAMb2Hv7Ho9 2.41489180 +zcBsNuWbMrc8kJt8dCcFe6TV6HN5XzNRZp1rz2noNutcsP1NcyWD9RgUtEMCKkhvh42zsxUajfXvaHGVjJcnvpPGHvRWEUU 2.40005944 +zcF1fWCzCzpq2c9N2EVXTx12bek6nL9S1ZAi6Au7BR5XWxDKDZdrnvjNEpY7ESsyGgLH7RtYBGXF2QpbjfC3gkxcwKTy4WY 2.37048587 +zcJrgUZjSJ7Skf8WYJGprhuUmsBsKSrzxUiaDu8nNPyQ6AJ95tbcmnfs9w9Prrxr6WyzwkBX7AyGT1kq9oR4CeY8Wt7TVVY 2.35239953 +zcbYv3dZDCg3eTi2VyJTfzVnsqGQb5A1LRa2mPsnaxpVb33jJk9SdcLvhSkAiSSLRVrMgAMQg6bPNjVQBPj2Meg5XTpBY6Z 2.22688079 +zcP9PtNnjnCqMEFM3hGQdt7bge63n1KZYQuob6rkqt18M9XvQuXcFa5SZp5XtBVCVGraeTvNp4M2X479iwzq3ays9MfcE6b 2.19624088 +zcJmdsq9UZue3at1rpxRQLXKkgPVEYyMvsPiVsFiWcQmhr9kEtSadyqViUDF52a4arQVEb6maCGdhLxwM1ziStMDVsgd8kr 2.11924015 +zcSmHMzMcCApkKYZhwUSzAPizFdKFfpCEVt8DpdiBbGRRfTBoUzQ1hLWJBKc95PisNteyKozuVo4B5vMGfEXqGYYfHUtfsw 2.10574833 +zceo5DiBppg1QSTy5afGVBp9EANQxK3SZ3isi4S9McEbv1hqU4FLTAhNtQRcqwKFrztGaNSTb2VDz1pwMBaUhh3BrF1BN6W 2.10462684 +zcHXK4RCvKhkSAE5r3rQ1xSBQ1TqwHe5uBAsMwNj5heJLesW1DNoWuf4wAS4TK3WChyTvBVD2yPjMQJkquQQFZ1rRUttDg5 2.09753296 +zcWCntAv1ejvcVvDa3m2bbC7rU7MBBKNEHtYKT9fGhCnGEA3HzULrCvy981njZcuhaTyPHTx8pyPosyWhrR3vuARaYA9A2E 2.06257077 +zcDf2czcYyiBW4Z2vhsnarLhbbLJxBtADbbCj4suHceC1w5tGPxMsdFRSGpZP132D1CViSpgTpGJvmrcmyRkpKvSYKUDpqC 2.05539523 +zcGzVBXG7K5miJW6PW2KgjdX2vsMWhfTBzxuK3pPQK3vJjU65edsCPaiEPUYFZ6m8RZdyQ6WGivD1YLQvtMju366Yg7PCSq 2.04711869 +zcVi1PGpdbRz8wyyfvzEfpspxKWZsJgt7dLXLxApaZp7RXk924J5b7Lm5sHZvbREL7B8pxeJdDbearUa46wZnQSDPnaviDU 1.99749863 +zcKUKodanajAZQqV9LK2djpSMqLtWtHDdGUBPKpi5FnAd3DhtkQDcWxxWKy3NTyzjNoD6quMjoBnAy5sZ9Pa4HFq2WxpwgR 1.98939799 +zcPKhgFuLeKPKSB7HjQvTcU9jwvqNg2AsQpPRJS7aoLwDKH5qbVpXsUDAr85k2Xyfk7KYMqLvzLRLcbwUgFfXPQyd2p6aHM 1.95908456 +zcCqg1pV6WbETjiVaGC7Q8KwDtBUdAiRVrjvfBYX79DykjrK6TcQ1Fxt1CtmhSiZ4j4bysrhDnf6NAkB7Sq6VSigwsViNCq 1.92840423 +zcWjohP7mo7hWCYGmRhRMGA1wwPKExM1bj7SJF14cXzgVHYfVVTBGTad5eHmoTSwp6psH58WNp7iTYQxAo9jBedkAb1Porm 1.92039230 +zcR8tSn9s2CRh6kjoQNi4uq5WmstRjhL8bZT76yMF789jK1Nv2BuaHM2ouoE4M7nJtPYxSi3WWoXi9qAogyqVCCFEF6Su3Q 1.90612967 +zc8ebVMHEzoXrzyMxqca1gJrAUbDTgpP5SrCEYrXCVyRG1gGEocWZJ4XWLwduP2zJdU5tyX6Y3VDcTwodcKo8BohVwyYvbq 1.83119102 +zc97Wuy1GMjC3oUQyrBAXFWa2gnyfSkwUzJ7gcZAZhPVEMveKJH2ZV3BPhC1e6e8aWwSwAn1ja3qhsSMxcuf5igLaunvyp6 1.75398841 +zcJ4s6shFiGgCsASYbRDVZ5kKqMADK6A7wt8z6ArZRoESwrdVqoJPar2BuQjZuKtJpSyh3f7ZoaG5ydY8RnHd4A3eUszYrq 1.72336003 +zcZkhCwNUTH2oxqieTA3imc3iFALDjo9Dvy69tG5wSmQ7HrDD9G5DmFbXBsnAbheB4SZcN1eeVnK2Xe1pXfi5BzxfAuYxfo 1.67463142 +zcTYtY7rHXf7eKt8FDmVnkKVJcCHc35NEei4jNkm8wNaQeGnScHr6uvR9y8L2YdpRK142NSbWVvY1STdesjhme7ZE49bFjf 1.55589247 +zcJLdoLxxDdhNZhwyEevWUdmuYqhpbqBgvudaRpp9fEr5V5sBsQBk81k79f4CaSYeZi5ESyS9NJLVdkQXucoxFTjV32v7ro 1.55543805 +zcJfsVJrquSKwhqRSy7ZUjgAobgBtKZW5QPvkJSSvRz23tPSjuWu1y5JgYmYeWUEsUnCVQTe9yLLrQtS7z2gjSY1DiuShKx 1.54518137 +zc9VT8B6boGh8PPofmK622rgNihsGo3hG9cyu7qq4ovcjpUE96FhyMHx2a7JNdkHo4ZfJ5NF8eSK3nh9AYUFokKX7rPxQVQ 1.53009227 +zcLU5GNvRhsM4XS75ASmAsX28MWytsEjUz9X2BnirHwtUM74TRhge7xFkq6YQgWXx9hpqjGGfXdTHSfAk6Xn3MdzVqjc9tL 1.52621439 +zcNetLERU3pqnv6VzvHBzbSpV6hr9QGaUciky8upob1ADq7NE3kj15nYog26PQFFhCqfGsV3cSfsztCg73DwEtw8XJ44eKV 1.51113687 +zccahWrKzbiHU2puFQi72imh2AsRqvV3QAsuaLFj6ZMmkaC5FZyoywp96ugThMDtenrhmUjjspcrjEsRqVT2fcCUFjH4Qwm 1.48669521 +zcRfxMDNRfqtzMW7iW5rptBMAcvyuccrPYJWa1qwEuybCoBymo7K24hbiVBMjnxfimm5MBTsVSxVmNZZWcC4Lh3hjeqW1kE 1.43643098 +zcUHofRkFoTQikBTc7qnr8YnQmWqnbx22fZgMxerUf9zj12x9BidU48J7ra5pwXPVyHLypexqNLcji2YmXREkfHMJMKstje 1.42951689 +zcgdK5BNYr9LFnY3YE8pjBM8aXyjCXox1bMn7CuSuLf3rNBAcj3pfz3vKHmwetC2oBJw6dmkCB7Jn32s36JBMqPDUXV4i1M 1.40009323 +zcQLf5ibetocyaSotbPvpPfRCj9GGtCcbpshCTmSLW1F98vo9mcep1BUEB4zudHj1fCWMMmWGU3J8Y8sTvm3pYq1rgkxTzX 1.37641549 +zcUTyv7qDLWTQQPSNGSW1oxRMFw27oMEviDtXoDS55DWYyB5kTL7ExYjA5PnF1fxD2coaK5dsHffktbEMeMA6HP59zVRTiK 1.32291124 +zcDvzJy97YLfG7Bqv7JTHD7F7ManupcU3qxmc5jQLyGPbx594PwR9RTVKAs6yuHr8WMR1uPP56ajbCz9gqm6hUVK1WZXePw 1.24520144 +zcTwr4xwf4WT9rEBEVQXt2NBFmSkLycSV9uZVotbRRcM8FKVyh4JbZVnD5vKn7mQHdJpsNJEayLekFsrTW6VVyykDkuQsQo 1.16567418 +zcQQHm6wiWg2pZVBUxxFdHG7AxY6oxzz3EExnvAk6Dx6BTVpMdwVBMG3pRVFYBncSTqxVCGAWRpJuoFqB8aZghcZCZgLAp5 1.15932717 +zcEwwmgHaj2xju1vQMxuWQri7nAGFALZDhRQMePsXh1G5GaczfVVC7jHrGhb1M4aug6q9a1HBwepW58HieEfvVFmeRHygii 1.12713095 +zcccEtUbyWyoSBHHiTRF8wtpn8uiF918ZeRg7T4zk2tdQVegwuVgAy7mDUyRkdL71gtRrvVzZbGcepcuW7B5BQqL29kQaCn 1.11945929 +zcXWvf6Z8WDEfucm924XMQvF9WkgJDkaFTM9BCj1yn4P8QGDi8dBa8qTLYQe8HfspLnobci4JJSmXnc51YD2jRGwDKB62mW 1.09121848 +zcYTEoqJM7ZBr665ksjcFi92uCRT43VK91LAFfxBUA4eWm51MS6J7mKAGich84qjSGWPpvRCL7CjMTeMoVs4LzvsqMJEt9X 1.06069175 +zcdF8bEeqzERG7SgUsN29h4KFE9St7776bk5yTZRJ2QyK8mL2fBT3Br8DgyxFiLfQAH8YeWaWco98Vo7T6fbvS3jmhfsgVd 1.03674971 +zcKjVBKkspXX8FzHCQSjEQm7EmxJun89rPTWvwW2W7SKK4WYSDtcDzPbWnUBmwtipSyHYZFhjVD4CtwbYD5dcE9V1R23C7u 0.96629889 +zcMAF4sUYdqrUgvJjno622Dn3ngXxn2hQdhw2jHx7vhyDS6qnSTs9PGVZAUgpNYwVNYuze8bavDAhpPuAT4oGh3dcqx338M 0.95442117 +zcPWaR1YrUqbGi7wfQR3pnEGHGSWvdz9s26gYRUBLaKrQgxhDgrH7J6y6QcaypbB3u13UuuWYCpPzm8rqLfi4m6pgu4NRmS 0.95304876 +zcHp68S8zHurnQSFQbdMYdhm4rcyRdR74j2AmsnKYcb9T4A6mdsqPDoJXTzwwHkMkdMVKys6Bhsswx2qpgWY1buwt4XY3gY 0.91849044 +zc8SvD48fHzjEaT76wbZds7o3YAzKrZixJJzSyEvqVx8X2SrxBwExX7AfD1vPKdnr9MrsYiBYm6x5Je6sMTjWnAvuZxKLQM 0.89815232 +zcC1bv1YH1DdEfR8H2HAcz1KoUWfs8ZP4beuJ7P3NGL6958ma9M8yuwdCxpXtoo7rD2VT2Qs472HiZxeoi63xvQsXKf3yxu 0.89679879 +zcK2kFAghvfayioFvEqBZAisaYdPNA616jwyQAkR4eW9CXZKX2FrmghHqvQMWogjAjNPgSfE1usLa65uxjXiNxtXrbYpZMj 0.87591561 +zcYqdMbjxxqQDha48y7eXG3Y3o2mdDVQ2de16cQHVSRXxvQxYBEVCqtkyVGxMsEpWGVDBsmdT2kdQsDaMfqEsuaByFVu5Vj 0.84518557 +zcBLf7APU6D6RUYHCw4iLxQJD9j1DaAKHERBZRXwuLRtPz5hZxRyErRLXzgqDF1BeRaody6WpaBZ1fGHVn2xtWM2u4u9Uti 0.82198535 +zc96A3YbJn2rWJUVXD1uQYRVtENAzBKK13cSXUdGxPubnNtrvB7LuTFtKtoyG6d3oGdVPbAMjJiFiXCJC1QaF8ocajJzUcE 0.81338899 +zcJHoozoCVD8mLixnKRT5fA8unzpCEJnRMhfGAX345PYck6gm6rT8rqk1uMwSxanAPpDjXQ24pbMz7RY5RRbz61Bpv4b1yC 0.81118924 +zcGaje6AA5ukwn2f1hh8A5RtHTkM9omKou5Q5uSFEJ7vakK6QwE2NrR1aPsKVkRHLxgsRVUEKof3StEb1P1GTQyN6zQ6Kga 0.80288267 +zcd1VNK55eDtRHVNfUVGtHBehhtN9H3vQcrketY9tegGmxgczViPPfn8uNHZFdM2fXq4Hnf8REeEBFvNtdbu9h1UA6fRqm3 0.75406890 +zcUXCHv7t1r5iKfEykBjDzkz1FDeqqD4Y8PYoHxLs3pGRqE3WTRh5AfjzjXGhH54ztM9TbY91GQFwJtTWgbME3eo6kaf1DT 0.74973698 +zcHXhjyY2FAGbwxjjF2s3TWKvE76Bqs33R3hkugpcQ5CLkvkbEeR6smuEsrvBqcei8fV9Rxgn7YnXJ1hTvs2VetuXE6NHJj 0.74208243 +zcJH1qu6DedMp4QgBRJqT3r1phtFSbiGjdLKJvxczPchTVGtmyynh45yLmvoLfCmoJA5qmJ45LF6JjJJ6gFiUaRNwbJ5BR7 0.72408644 +zcGwvfR28PxRhfH3JdAkhCRE6RKyMxLzfVN3rjgKpid5eCjPFR3VDHkGBkgedcpinKeeARq36D3UTemTgsVahPkFshhTmD9 0.68136904 +zcJZE2DnvjpEKQwWcTzmjE16uAH8uguy8B3rbGXh9NHZPzTSimXVgHni1WeKfCw68uEw18aDWMbpyJ7DtewwZJxq76nLM2d 0.67191585 +zcXrQEMRyETYnvzMQYjhCinxaS1qoBv7DKrbsnTgDbEshaeueZ2ANVRYApS7WyRKCC1zYosv7nPaNU4iER5i1hyhfsCqsVb 0.65541553 +zcMkJNSeWkdySMGpcWqN8Gki3JrELwQ7TafArPDegGJYYCwPbAaqTS5KVowfQ48WDVB1FUfBRTKB4TVQVBa3gRcAHpLjarq 0.65401806 +zccNRPDyHtYxSWzNPXgmeWQWmaU1V2mXjKQFDE7ZEgCiXdhCHSCh9wXSo39NviY2yafEh1uruErXLF78kvhHDXTdyXDJ5qr 0.61124103 +zch2mcLNBQJJouVEWGHNk1K2HyncYqNWF3eBmBveDJcV2En1yZwLDAtGKNP6p2NbrDAayZbZxTAPrvQSnatbKoiojWtASqT 0.60140950 +zcewYPmYoK7KW2np8h3VmVkhmc3vxEpjmR7oPb5bJnYktuBgNdPbuYgJWAWXvhWZ1Wz32mbff1Yx3cfQRJP1UUB7dfTXjPu 0.58787999 +zcPx2h9iDX7TGRURrannCukWVCRM8y7yvfpXx9UK4yMvkR5sizoLL1wyKEYpB1QVaJGMQsBHkgZKoCnuPir7MRF6gpHQz9B 0.58180391 +zc9qqtVywxfVUMtXoDyiqHJnae92QExbDmvkU4f2ENzdrZCM1v3UT49SfrhW6h1sR2phKMiH3RdpxQZw8Q2r3MvKKfKwQ3s 0.55943661 +zcdfsLHzVvKKoNx1eKfDryAUtMuACBF8ndHPiYSYTz2cWepfw1aS8iU22P4H4DCSqFvvNCziSgAyZ5SvrQbGBxLSNj1b5he 0.54923166 +zcday9x7h77mXYeont51VbB9XRA6fVc6T67tqU6zgc9Z69SwWWTHUQfcLmz6xrcGax6fdsyi453NZfTdC4oDhuJfUXMcF7A 0.54500955 +zcStXHXMW5E8vhXkG3RZxCj9U9N9TcCoXLWbDDZ6Q8smzwVo3pKdu4QerHp5oPgBeQ3sm46ggxnDrPN6G4GTuaPy61NWKcx 0.53443131 +zcGMwejiWKrs8q71KunhwAtPUcDWvLiWtkscrQcieZLnkFvGVLE9NfPUFQPUzzmsY46gfG1UoiidvGtv5y7qhyGKpVRP5pw 0.53287905 +zcJbdYukkcSck9y7ZwqbUtmb7gm6QSds7WV7f1gR6VFtQsuHdAJkKLEeeXke39Xi2qmEa7J9JcM1Q9n9UT4S7b4ZYKABePD 0.52544252 +zcYbYNCerhoZAb4j3A9g1UsaMa18GvRGeMzivR5Bw5wcFSnYSEEfHuyiDyFZfKS5frxzqn2apH5m54Y5EUJFPdZeZ4hXAAH 0.51389386 +zcEetZczrX2DDJxVxGPNJpVkibBxJzvYTPKXPiC8Vxb6db4Ma2kNLUg4dH18CW1HGdPxm4SVTRJYQLvoDqy2AeT4CNifTWn 0.49894782 +zcTDAhTDwMQ6wWUE2XtfbL2ydGDZF8bN8GMSDUAqWkVGGuDNwDhYBXXiRaE1PBaj5Q2VVUieD4p2GpWCWtNiZjVMRsLfSqz 0.48176943 +zcZ8NSyuBewoQqdx4UqRgH1LnGbyB3oFyUakrKGw969AcnX49bJ3FxQ1XRrfofe74xrnChf8KsMLbmYMGfAy5x4WH4N8omR 0.48097343 +zcPpmeEdJ5AWjShSpt1yZKTjro6bay9SuCUMaxBFAV5Avn41UofYik5yPLKQ1aTubumKrCAJSC1KdqeCMv5QU2sYkCbqFxy 0.47933329 +zcBoPtWqXZ2QGcj7uJucebaUKYnGT7g9AULSt8pi9dhHztisawE1wva6vKJWQZCjVPrwvb2CAwQ64SkRgCfbTuow8xf6kjp 0.46483260 +zcVjTGm97Pha4razBbAoAHP3K7kaAvMH6r6Rn1NHYxxAKoWoQKQSnVK3oJhreGz6SuW5vhiU4MCxt1eSowAShQsAggKQR9U 0.45247462 +zcGUUXjVaLFuyF39VEHbSt8vpGQnSAhtk4XtaLf3GSFw2NJEwrNY398Dxrf2Kv8W9kQ7iAcuHZofaJECv8Z223Qrvauhz7X 0.44629669 +zc8PPAM9sjbizrjwwwVXC4gQWJTzFwmSwzWQRZMHMYrVnxvNREeTroCwEhNgBHUPy1Z55oM7NMATyuUxJphMhns18XzWHMU 0.44493658 +zc9ULZLNbF8NAX313X7Kag11ZDtVaTBs3qMjZHzedfu9hCfdqPgjmfpx5U8a6S4TMnGmCU2PR2wCpG7PQctj5pwL8jDGpYv 0.44100427 +zcawPCNkamyeet3G6tfpihyNy7osPs3chYEYXiJtdrXz97MW7MUFCoJGHZcnr9Bs6WRnquz5HHKmh6cpuXGbA4BEUUGykdd 0.43394904 +zcUVhcGxQjC1f3Pyiho7csruneFxZt4xTatcSvvWQT5jnnUi1dwh7LaepXLdj32t6PXEKkrAC2TWQCaQyxmhFe4bimZvRwE 0.42337008 +zcDj4EZY8dAfTfsCFWGeUVPtfiy3qkQcPxDqTSXxqHzsLbh2DLqs3rVk1myEd7pkUmcBTVAqE6Q8NfyfY4gooPpT4BPLV3p 0.42166579 +zchcgx3265hHde72mXxKJ7xvecPqyk2kms1HnJvgemxwXWyUdLM4zqrEXBFPQbyRhqfrPtRFcf1kFAxTG71R8uL5iYRmqkL 0.40946013 +zcWWeDDdsQTJamQ8EoCYRkRxDKjmJCzMoffGgtALfGVsagH8czpeC59bYcAFFd5RrAYERLZe5vVuF5UaqsNetufvrVXAe5L 0.40264022 +zcQ5pc4dx69ZVazrzZfJCH3DeQBxNDJbNG3A7jFpx8PoVuCXVxW1mu49mAqEBozRSdAv9HDk63ZnsAjxAJaP5DvyqavQKQS 0.38585126 +zcLSeubnjQA3GCPb35ZRicaCo3eJ5BuF1d3iH3m31YQHeqepw8JBDCK1TzapD4eDw544sKVYVCjEhptfFxKBzDo9cto5Gyz 0.38541081 +zcFvEfiyav52tAHi39AJXikLp1sxGBq98zy12EYK9F8B9n2oW8aYPfFDMT3ARCrkUNZDxHgQMqE6G7t8MqDvoEjr8Wi4bLT 0.38095029 +zcCkxaZ91H5LeuWUAPVKkDMt5SzPhaxGfTNVusdCMwxGrW7BvdZXgcDNouekRgAWv3HZn19UUT2yednVufmFaPPcBGnH5Fe 0.37951503 +zcGQZZ4j5kuqcLJ2SqDtJgV5xtvQqKzndckgF4ndnJH6bbKneVk3vPf6ztEHaawNqSfuEYEX6FbEeFa6dyWQVN1u9D5bxkT 0.37830015 +zcY8uBpdBsTCHwE546PZm3mexvTku9RrmUUQLuWXjGdiVLBnGrZY144WRQssRVfbcmyNLmxmPRQhetmPHDWmCRWnmybjsyK 0.36709177 +zcKZoTVMkf3NpQqF8R4vyb9LN6mw8ZsE8WWirZLNN4hPdjBCibUAfahmM2jgbke3CCjAMWVUoPSiVD14cKrxqKTFXBMem9J 0.35699480 +zcEGhCEVG5oehipZkWwdXQ4FLeHdhE2SRD8FmMhPhrZiEKEnvx4CnGBa6CEh2kPhdzyTCm51X85uobRG4GX2cHbY6HyVR37 0.35656349 +zcZMCug4bcToufcRKxk2qrkdnBioaco212HRtk6qoQWXanwJzXvmbAu7aet5D7RHkFM6L4pWh9E2JTf3akY7pVb7x27VvMe 0.35215211 +zcVSmq13qb1wMSRJUtUDiX7yJRNoxETeeFDzikoSWgjSCF9hXmJDx4p3AyWfwjpqgbCkp1Auyv2Vj4UQvkuk8Ve7vGLp14K 0.34691471 +zcKXk1BwZRhBshAw2n4tdhS657K11izxArDsAcxDkW28FtwfD7P7HhgCfm5kMchKyd3vpuAhCYvetd75MZAyZznbUQPzHQ4 0.34103895 +zcY13TG6D15WCABXZ6Lg9N8WeGeUfUgQhCZbkWkvmhyWJkLmYL6zG6GxA7krNY8c5zut8wZQTBxHu5tDCkfWkxQ5LbGnXsT 0.33887093 +zcaenwiLxJRFniiNNX6SsdDBiqD8Cf9aWcUXJc3LWBgyoeVmKBvPKawCAWXYe54J3J1oxFFyDESJTWNPy299VEt7inj9Qca 0.33032197 +zcbVHNxbPHEVHixm3pm4FSzADeV5SdngmWfLghGH99TdCvcY7MxH4gxQoVfSMo9QRtwpQL7mPjKiMuusV8qzjz6n5yTL8ww 0.32513040 +zcLHUfzQx8V1V4cvFhSnRZU3wq7ue15owCF2foWnezqrV5z7wfHvbf2vQJfyygtiwbkxevNt8faxTndb9Jf9MYvJbj1QgZf 0.32442221 +zcEpp5yq3BLmBvnd98pfBuPgu4RPPHQN7rKK8U22CZ5ggp1AiHzdzgX69o2czNCHpBTNgXjxLpauMvAbScftzcgB3QRL7qm 0.31697240 +zcLZExtZMfV947KbSWRSEQTC2jBjahrqz91TLK1thLXXgYm2uassVCMNfWjXWnFTL1DcsvX1FDeDSxDmLS8BiLjePMiXHaN 0.31466647 +zcRahi8pVEo2FeB9EmhPC4FUTU7oJPe3qEN7N5tD87kMYywUzcQ8R6Ss6EFYYAuqSCY4cDhjvJAAYfpNtpgk53CL5PtXTN2 0.30020259 +zccmHPRXKaBP4gZSqnFhxccR8s8PSyQKk7zjsXUmEVoDzTFK6gfRZPwJw4Jk2Z9AW87kddRbtsncuMuoQfFEMcwojvpUCAP 0.29490782 +zcCsJn8ZSLWfVMVu2iYTq8YbZwRnTtmiB5bn6UpD7BB2UXjGWAPumMp1wRbBraY5S31fbULtXJba5VhWkRd9ArKsqDCTXbW 0.28961367 +zcc9sbD4piR2VsrxjxbVTes9fxXgaxqXggRZT8oNYpAT49LTdb5ZvNzD6JioF6U28977ACS66xTubkHgBBEVijPZN35sUzn 0.28430453 +zchDgsUbz3BG5BsZefPn553vTsX5yirrw3pXwfa74EdEGM2NBh4vg34jAh28ci3xn5F3VSpTU2uwu1oNoP9ZbEqYBCppCQe 0.28043455 +zcbpSQEVgcG95Hf3bhrD9KczVRHWhotpRgKE85SMfA3fgXie88nkqnjvWhUKeQdaTi27WALd6w2Ay8mTA6tsNJhoqTgUCL5 0.26438185 +zcgv4oUULnFjjr86V3SsqZrqSfG3pg59c31uDJvoqSDdQRMQwAsd1YXuvaGKiTxUadygc7bHgV3XLqYcSsahWzwdUUXC1jE 0.26167676 +zcYYTPr95HPSd2k3zHbLCpCs97BTSBsBPGcFSvGyJhDbkQ6DyHDiRHqSaMxU7rJSmiatxnyViMBU6Va77kDNcgi4v5bBD3P 0.26137495 +zc97HHri7CB76q4dcMoJTyP2pHnQ2mhrpsg6aX9Fh8TVFBqj8xBZ7wMFQH1dmwqhmy8yMbeCDLJUZM7qG3s7iAHXtp19oBe 0.23545696 +zcWrbLDHro1zYYSujvnZNmKKjdeLvkF2dk14yCqVijtpVasKJviBwTWiPnm5U7bYX8qijDZdpZogUs39SnF39eJeybtYMRU 0.23204621 +zcgRg7EiiemARsViwvw1z3SaeQNNudGY5DekEfgahtft74S7v2QsbsgwvrzonK9ALu2A4WdigL3CoxWjkxjvsD9RieMjnBQ 0.23185241 +zcNkxhKAx5dwkWiggycVPiFHb1o9cg4TGBVUosRjF1yebYFtyFybxe3UW2Z24M1fUtP7zmPEevE9UVQ45SDgJyUGzSvsjAv 0.22935472 +zcJcdNkKg49gayLQi9aPVvatA8ngGnCcSwFoENKbk1tCZPhn7S4ZR4YBHvTvatfYJR1aWK4obymbdapXo11VKzy4fMf9gDm 0.21418334 +zcD6tf6ZuXcmjEkqAG1MT7n3uv6Gs3aexBv4s2chR8szcFPQZEx9H6rV34qGBz2KGJifB2GBcMmGMHL2v7asEZhVwpeoRRE 0.21301490 +zcetu8BY2WLwWg9pGNWnKDShVv1zvy6PjCYW9uWykQa74rjyFF16JY1rLamvUwDEjdrAvF5v62T8v7D4RG6gjhPWpPigiCQ 0.20435158 +zc9EQecgPqarRJA1f1z3UvK6YXpNbhEDrXzsZtkXJQrCU74icdaACpRnq4DHfMeid3KyhFinWuLbs2LnuTTDUXK2kpGHQGy 0.20422690 +zcRBMrSHSKsgVXHWmVSsj2aCU6uFeanpRrDWEJt6ym3u3VhHWQeUqHXr7JtPmaEZ68rrCSyM6fJRLgoG2TYZiLshbx7XWNN 0.19896784 +zcHQQN3LtMsMFr3P2ZMSX6d1TJndQN6V7F1A6qbN4bCcNyynEYvtdXJxcPw4CrHL9GZapxo52dMdUtd6JEFM8eMCiCvWRDW 0.19629718 +zcNmXr3UAqr7ZrYHEeZJ8WksAjBUeWUq6sQSyeLFCoy99sQNUe1x5ZVd2njVSeMUxMF9V1Z2KGUceQGT6rNSGhDyEJMSF3U 0.19223682 +zcfvN562fWduPSDw1Ry1Pm458VZdwo1TKHHmJPkUQMzJJcZzn5h2HsFLcf4Ep1q4ZqnAf2FU2ZA23uQehXnZhobbxXR63d5 0.16633081 +zca8hvKaQWuD3BxgB7Dhi1mxovc9dVHnZUo14jf7poNiaQN63jiTz5hLSNjLbv7nF9funjLfdzV8GXQdkH14pQMWVcJH31Y 0.15730366 +zcW2yZUKShYGiCP4j6UarajDYLJZceWjzpureaa1iyhNQmqQcQv8gXyUa9mED1YenfdhPPNrJX8Wf9XivMhXHctrxRvfS2v 0.15518445 +zcfKKh61VpE16dV7hTJQnbWNN1mfYpHTqj56XdRWeLKG6L81fzqA1yLskAhkK29giowZpQX7NuMpaCJca8r1PAw8KWLAM3m 0.13943725 +zcYZXyLFBFNq8KEXSuW8G7XakUdeBbQoubRXiePGk3gRTAiCnTs7vwvcRqMK7sNYFvQi5xPEBtbUSRzbQQd4jzZa2eXyzPT 0.13676772 +zcFpGKuQSZ2G8ZWpgSGYAkQDD7TDBdYG4U21g3Mdmu9FCSNtMo8VxnVAFUPb8ZKyMKbJfiHbo2hQLFf8WAF4tkgnLxcisZG 0.13136988 +zcGoXeYrgSF9VNpFYK6zhPTPX2vd7C4LnhCU8Egesyu1VXgBayhEkpmgKRLGx78cPn7KchPrXb45KrvAH4TEwitcM8m4k3a 0.13067182 +zcEaj7VpTrvhu3HVaoNUimNQB9atQqKTo3bEcjkF7UGX2GyNg8tLxVYuZsi1XPqaWeNNtusa8BX7Juoq5hnyB4rHqGD99SL 0.12694722 +zcTWyj3NdkpabgMT5CYxDPp7upQ5qGND1WFcKFeFZRjsEw4Hp9843bq6nMjCFz1R92CnP69sAnZ9Q6iLb3HsnUjf1zdRZnw 0.12325854 +zcW4Xvmv2Bxj3wm4Ay9cp2o4YeHEU8Z6pozw8FHCS9niJ1qk5pyNZ3dFZLteUZfr8vBW7vYxUd4EZQwdqUT5r9hKADpDuB8 0.11932710 +zcC9Dn7rh1CcgDjdYeAhjbUMWb7xzc3XxLSpzL9j1o1Yv34GwL1VMUB32QDgXzkfz2YiJU2PdCKLVAwFLJBe9TniuNbUjb7 0.11871871 +zcALXqYKsNMMt1uEZZNA1qsyDkZ8zy98gcQVD1qM6TqfrH2UrQCgXdMDHKz9KZKEpjYynBGdivSUmZXfyiU3qUJhXCRrZrn 0.11717727 +zcP2xRWf1hSSMd5tQ8QBArV2JxwaRBAosshAVm5iyCwZue7WLy2ZtbDmH6PLfNkvRPykW5JF4CjrE4RBYv9ZUKJT4M8LBcb 0.11596974 +zcfBJTy8NbPhTGK1FJYpNqEtZxD34iGAXCgRqSsBfBmGys6sFDbcJHu5gzDRgkNmE75UtKBYNoiZ3p13vWFvQhr5Z1UiU1u 0.11193153 +zcbxqN1cg5J4JXFp9fbQH9iAqjin4Avq2DbEcEWcji74r9eUzqMdRjxKBXbVhRa7X6VB4Lk8RoV4E6cWECa6Uv5HgyhnM8y 0.10260291 +zcdARJeMUJmPMLvJHJWqdecMGosCcbXsLoK9J749pX3nYDkkqv57CxEBJsHDHw9BPxXf9L2TBk51fLN2nFRBw2qYozqCV9G 0.10001667 +zceQMJc8cYedcbDFXEuaLofojFWLp6vun6SLaJ26wwmJd3AFVbttysbnpsrqfa1ReUjwvPxAgXVbigt2kifL8CrncR7rhGe 0.09392734 +zceUD8QTJ9JKEmj4N6cGioLzAbb6EwJv7GcNG8EGBBirzW7J7WCHDohphm9YgYKU1d6xbKKc4GhCcuCBWmj5Xfya7AWnP6g 0.09104754 +zcZ4APYkB1xUMTFE58CkdMipZoioprVPTBeRZBRA1xTEZt3Nt4SZEt6snh2LprBDkEjbviVqDN5R5KrtXkA5DpnJj2ra5PB 0.09084450 +zcbVPSTHzmkJ7xACWd9ViCT47q21HYKirhqrE29JnUDvzGExLigVtjMbxPjuAzfXpUoybr7i3ZGVAhe31qJiZr2yUzvyowV 0.08797293 +zcLM9mf1SWg5Kn6L4F5rMSTPbXVLqsLEgcAipCsey67TcQKyrRruPFGYyknrJSXXrTZV6uQt1vye6xzUm87ifMQhwFmEFbj 0.08159772 +zcEVVYbWvT2XZ7Vwv1EoqFnSL6RcyE4s11PZbuXeY3gBWmsgCtmidQRMh6zjt82ykiyjrZeJQ4DCPoM1Lh7ZazsesevDN3z 0.08134030 +zcbxWeXT3ujiUEcDNfXUZkfkNFeWFKLM7EboZugjTSkwYk6Bo4SRM4SRZqJzeeTexib6f8mDmySNetro22V2DHsKycNLrJc 0.07929887 +zccqzaq1MUUue3aticfxwyQS3TNwEiUvQ38VqbsdihqsNsZvfNpBFBgYnmZiNJrYFAEK3mi9xQmLsJ2z5ods4bAjLg1r9S2 0.07626856 +zcNaTQ22PRE1MdKzrf7Bx5cLScYwx1UjCbspBxr3tLpWn91uDWwrVCmFLYgoiHCtsRGDnvMTMKFsWtm6dZsV9BAA89C5opu 0.07596657 +zcZiwou4j3gSfbHppMs9NGapDgKhnXGFMXqGPSzEGNo96AEsbHtLMqV9n4n4wjMCrKykEGz77MVzLSXiZiX3hrNcaQxodJK 0.06811364 +zcWz3Q2Jv48dBzBRgSeu5Z92dSPpbjVXFU3BYTJUxLNyvEjk2oS1vRs6qa5SypMzj3YYUCtBqZ3Rm1Tde9bRvoXkmjE2x2r 0.06717970 +zcMokMR1qYwLB68Xv6psuv8sJYw3YQqXf8p9ZjRKzwH3yqwo5u7T25pR7CVGFx1k8MxV5QXnD1DRYV5oXc7TGxhZEBvNZV5 0.06657492 +zcYk5gS3bFx661bVM6rZUw2RMJ3noHQdwQEzQQ7qjbmUZTeGzLPFvpiGgz9yBBEXxCtL4ikTASn1q5YK1YmKUBhGkgjqNAg 0.06645133 +zc9fTFL73ccq2R143q8W71NVP4jtXJsB2WhZ93fXV6FGTmCta1iHffB5mt9QWYcf19zEMptVFG3DdhgxXTUtGVnd8wVAH8K 0.06640802 +zcYkRApZZfEgkogzrZBPizi5c5YRJRPu86UtKCXku3VBjT31uCM9B3a2jr26qUurDYTbBvDvWPfsF9L8QhdUfPUusAvJi57 0.06520634 +zcNnJW7b2oKLExLxmUzvFHwUhWHNubDTKTpYdjC1Rk8UzR2Hzwib3CcwH9Yyi6SrTwKMYmyx2JWUcCsHGJZBRxDWQYaNN5e 0.06466773 +zcYyH8d5n3p8pPkMWgD2RwGQRNcYdbe27gWgVmZHMmGd8Xu72Tr7rYcFDYNeWn44axdgQtqpHPfUUqEM9r6p8Y1ZMP4TRaU 0.06228533 +zcQxmL8se6WQTTAUW4GfMLFBmhUbuCaahgPTD9bmjJiVaeXP9B7S35ZvLHnv7yPMZsayYwfwNnzq4KYhB1iF1jkGLkLfBjk 0.06224273 +zcfUJv8E28WVS71C8rnznL6UBDpz12WDRMNKbn5scaWSoKp1KGY5ez41rwMX4cLuyBfojCyrVp6qo64HbWbBmHynkXzJsej 0.06067893 +zcS6VzYBcsaEsM9qvcLrwn8SjUjrCKm64kdqTXUt9Rj2f4dffATnTFGUwG9p4UTL2X6j4qxhkq1qr5fdUT1ukuPFNu6iAeg 0.05920480 +zcFH3puBCJnxt5EiUA8ASvSXn7r2pYJwHYUscifBG1NhcCgrmm7BWJTddGtx999Kkv3qGmqJDxx3wARqguHRYYh2PgjtN68 0.05797143 +zcZ5dwFFnc6GjfAyyXxSXasyUmGR6CpiAPUFDoH7hLiAhRBwQwHbTJ2eMyxiqGKie7nT3gHmeR6tH3G8UgyidfNGrx2p9Zx 0.05598771 +zcdos6S33StCScGnCyBTXcvhSuT6SLKvvb5RnMam2m1H9bjWUcGxZ1FR5CXy8PZctvSQxYEfziMknYaT8WbZ559xTHs77An 0.05301738 +zcadXPJeWBzjmTfWLJhxJrDFTEWwgDzW2rwFUJMAdXwzCN4Vqbz361trGVae6Ma76NFTvKnWmZdomKqC1hKECbvPA3LnzQT 0.05084446 +zcDbz5VYXGYg14MoiBnZ7GL914gcYKK3Laqm8HW63oBqagRzAP5TEQwi2bwRJJADKsAmuKYac4RJ5EAJnL2fMdxWKE4Mptj 0.04917092 +zcFYAY8SR6nv15NDpywAFQNe3iKpzFGdY3VsboGNx9TKgXonESW9btLtN4vcm1YWx1GnAv7bBmEbyqR77tjFKvo31u3bckq 0.04838771 +zch6mE1d12iBwFjpVZHZfHMqM6wgfuM77VWvJzRFsFF8ahKkiybmPdJsCfxenqvG9h1X6EDL9oH5ceMNVCbYACm15G4wxXx 0.04448867 +zcMnYMPrpLm9W7LWGsM9V1Pf8aZyPNUxH9hUpKFGATkqNcVX27yay6kYkRQTiqTSiCxxbzvm8SFArcuGnsLkdCFA3Mf2CaC 0.04133326 +zcNEAo5VejsTzvqJ9wfdbYv39RQegjWMVF7Qb6jLPCq6yFpaS1SvTTDjWT1QEqJ3dpRyB3zR849oP4UeVXgrNwmeCqwenLe 0.03947846 +zcVHHtp5vTFDASaMoWXGYnPYq7n6xqwtYDFmN4F9UX4T88MscMJY9wQgyAMWpM4ttNXDyQHcFDGgegs3CBDQ9KNWvUXaaUA 0.03267893 +zcW56vAJBYz6YTsbqt9qNwCBgRmLahax7sPdZc15RPovvLyLzuA4Zuf4M2hK5heZvqY6xBhQMoicGCNwUjJHfkAsZQbEa6s 0.03054712 +zcCFBW3knWzE9Mdeq91xyBj4sPbDkHCatrRoLtmXGFvhrw9KGsddZyB6zjTehEfQtem7UpUNSPK2jN1UuEaGymAuts5Psoq 0.02519975 +zcdK3hJ9q8SaDSCnMw34eV2yRPJudtSHH8VrBjsG1JdQ4ZKxMrMXW1CSukf9tzc2hR1nDXkGXA3CnnpcyGvBprYK8hHo6j2 0.02384176 +zccFLTr7KpTmTF5uVQYjiB64JX7HkMuVfp1xrTQ3Us1WNGKey3LV99Hkoe5ckswebcc6fnQFhuB84MqhPWLVvUv9JYXqhyr 0.02285850 +zcMapykyDJeZCHT1UTaCHVQW2mhx9XwuBPFCMo4HWWd3bn8CTdS32ftTFamL2uC7ZFy6XJRAs3Nr6F3FWxSXtg7ascWdGVq 0.02215891 +zcQyyT4SZHqraAy329UR2NoNvgheDNfUcJkxNp19qJ3zPtV34aRRY7UQH6x2bcpHgvhe8F17udtmozyZH9YQqVYagT7W3pu 0.02166958 +zcg7dVwGFFGBSjSAswcaoFvs6QV4T2dNEz6LEasRXzAHUq5ugEmn2zw7k3kRqcPjA6TksDMeHf9W2XwgWPiq8hkpjJS9KF4 0.02138292 +zcesKmbs5LdLUB6ToCP3zNzCvk2s8ppWB9iondvVGQQjeWhAtfSiFjDnKgGniYCiydxpTc3hxLPZf7Twa9fN8ZHyJh6t3DA 0.02061743 +zcNxGp2ZxzPjpaNC3TJHrGHt6cqWaWHezx5oeRtbobdfXeKWiGNSgVxQAPtL8zrPTsHkayX3HsBjpN1v9pYNsCDwUidju6E 0.01781090 +zccjmBgwEAweE9WUiyTCmqUHLfnPxoV3phLFrZ9Qoa39aUYf3WkAjWPVgzz9oVjwyuJLSdF6mkUvGDa7LH9HnTPBKeuo9ci 0.01754414 +zcgqGEJhK1YecezXU75UUZY2L7Q3xbQ1R7381C9MMgLoVJLMQhPXCKh8gZ15hKz9W6A9srbtin5d5wVPRmWjipxx1fMdHfk 0.01643947 +zcLXzNo9p7ZNCDVtQNmRyTVcLMovtRQTuWEUMu19h5nYqdvfjKaQbzXkTmTTGwDNEp8ewMTs4q54BEfZsU2ZM7bLek2iD8y 0.01635094 +zceUhkwY6cpRyzfDKqFYutmyp4yV5ojqraFn94kfYuTRJ2jGo6ezE4ztr7qQYqhDLMxwPsUUs2EhMb9MWBWd9U2AWgFd2rw 0.01604043 +zcao1fctbra5zbHuzVKfn56EPBHvsdQHUj4vbXsx7qB5UrPBpRx5QNGEkduxJMm7K5A4YfunVzzPixn2CQDTSMwXXzJekJF 0.01429152 +zcJzYZLrSEdKUUgbrSuyHhmpMDCtuQUwCxLGJhRuSUGuKpYXYeFBchkcpYvse9sEpZD4VnzjTjGjKaW5x2RiHiwchnUsXz8 0.01131670 +zc9Tn2fNKuYTA9duwpRVmXFZyH3N6thguoiAXxr5Gvq8159LR1db6mnEoypQdCz2w92w4wPE5dLgoRvJ7sZEHdnpc6nrfbr 0.01078443 +zcgfNnd91e1SStDC1qi4tse5jJyzKWKKqrUKiYK7jAyGvGvgdvPx1noHYPT7TFuK8KvkjzMuinCUNN7Mek9f38XpNvKXUBh 0.01023136 +zcLMSrGT4Fi9Nrrf5MgvXMLn6ohe6tZs9HtRXh1pRkmtvXnJhAZdPR5uBtm8TrwUK4dJVCqBwZ78CCfBjkjkxtJkSkbEK2D 0.01017816 +zcCc1tmRJ6kZLfvQCW55bZDWU2Cf92sYis1Z1Ax91h33oZf4afuLWRKoB7stiedDrq6R3793cjv2p1wReiL5ievg1bmsfYu 0.00988874 +zcHX2Th8W3k2JX25zKGe23Tv1Avp9yMZirYgh8F9NmiVyFo4CqxpSZxUURZoEkgnpAjJaCJ8cKa2FEKLyZyA11ystyGGTaR 0.00595513 +zcG93ferV85GjphQEzaAgQh666VQPMTLioJZTpjPZBZCwNMwmJJujAGK4r8e6SW9mCUDE4DLFSzPei8JJUQvFEJxnET827D 0.00589895 +zcgJ37hJCs1EMumzpx7gMxFL6dnUQrFrC4WCBqjjXQwk2FHE2SkLoDWCE5dfCKDNpa4oywkRYvMMCY2TesQXGt1ga6wbkqz 0.00517659 +zcYfApyXiD9vYW86ruykToDRF5GVzFQ7SnYqNgdXEF5AQUTDGvkTR1p5sFA79QLzuiVVFusgazeatC3ujeH6Z62F7TJ3VzY 0.00509498 +zcSoGfGho3muy5jVAyqaXnfSnMv8vWfjWVotF5WK8qHtcuf3TysoV4iizrC68U8PrYGRipvZFdS4XaVqn2CEqb8GHyHNn3b 0.00235127 +zcgUWcZfzVFk4VKKUqVwWr2sb2pfYF9YLQ6iKDYtUEseLnN6LknbeGvYNnj7TyXJpyUwXnd2vPpU8jYF6FkGhgrw7vctK88 0.00168853 +zcKPfFNpncT2s9GHJJ1MBKQERHRHkKaBFQUMj3v3eou835wWa7dFEZMxPEpVWkPDvST8yNvPbDirjP3CktU8ohBC1EFi2pY 0.00122527 +zcUa9kGH1PJWXbvL1qWTHpRfDtam3J8SCGzdYG57TeA1E1hLTNjexJpCUass91Hm3i8CCNaqsLqyacirwqsKY7NhuEbSAtF 0.00098275 +zcSAhm6Du3Zpx7iU8v3z7SSXtYk6LGdXho21H92H1qU16VMH1EUaAbJSW3hN4EgjTwAm4rwmibTF6p4nVfFar5ua6xKepen 0.00071656 +zcJS7BmeuFhyFpxNyhkr4Ho3HuoHcZV6USEEMPPDAS9JfmZ5htWdTedeAGCYt8LDF3L7rRiiHvxg428KyjJvK52B2C3WiFT 0.00070148 +zcE4JfSy2ppywrQmomwEzbDBRjh9vkhZAL6F1og4QPE6Bna61iiZ4DtjTU73AX1785yTeSJ6FB15oznrztPXz6fU4N5oEMa 0.00037565 +zcdFs9jwXtnDRD36MWiHUv6sZGqQ3WmgHFBdiNv45wryPFWz83Jk928j9LNrTpz55Tjhppg5CjBEwGD8afgzcXLsR8B6YR1 0.00027618 +zcDRrSy759bWAFoof5YQFVEEtZf3DN5gxwNmF7smab5HpmB1ZJ5ZrrNhm6jGcY9vt1D5exDTFwY8z8dfJ3VBvfWqKT55Rmn 0.00009672 +zcTxDwTtsZmsL8J8g8Bc79uQoMW3TAumqmUK4vyHSo99ts17oS5ezLjfGwrDV1sH5VoXFjm1jPbVagYtidwd6HKS8LL89cn 0.00008582 +zcfdmBMvfTMnh9GD6QPq31MCL9uJm87QQoFkWTUCWvnEyBfSwMpZ9PDWjVj1Ru7nKiqRuTpoeBQQLvJjdvL5F77uaWuVGjb 0.00001583 + + diff --git a/website/zznomp/static/workers.js b/website/zznomp/static/workers.js new file mode 100644 index 0000000..4ec41aa --- /dev/null +++ b/website/zznomp/static/workers.js @@ -0,0 +1,79 @@ +$(function() { + initStatData(); + + $('.btn-lg').click(function(){ + window.location = "workers/" + $('.input-lg').val(); + }); + + statsSource.addEventListener('message', function (e) { + if (document.querySelector('#pageWorkers') !== null) { + var stats = JSON.parse(e.data); + + for (var f = 0; f < poolKeys.length; f++) { + var pool = poolKeys[f]; + var sharesTotal = 0; + + for (var addr in stats.pools[pool].miners) { + var workerstat = stats.pools[pool].miners[addr]; + sharesTotal += parseFloat(workerstat.shares); + var existingRow = document.querySelector('#workers' + pool + ' #worker' + addr); + var minerEfficiency = ( workerstat.shares > 0 ) ? Math.floor(10000 * workerstat.shares / (workerstat.shares + workerstat.invalidshares)) / 100 : 0; + + if (existingRow == null) { + //Add new + var insertMinerTr = document.createElement('tr'); + insertMinerTr.id = 'worker' + addr; + insertMinerTr.setAttribute('data-hashrate', workerstat.hashrate); + insertMinerTr.innerHTML = ''; + insertMinerTr.innerHTML += ''; + insertMinerTr.innerHTML += ''; + insertMinerTr.innerHTML += ''; + + document.querySelector('#workers' + pool + ' .poolMinerTable tbody').appendChild(insertMinerTr); + + console.log('Added new miner! [' + addr + ']'); + } else { + //Update existing + document.querySelector('#workers' + pool + ' #worker' + addr + ' td:nth-child(2) span:nth-child(2)').innerHTML = bigNumber(workerstat.shares); + document.querySelector('#workers' + pool + ' #worker' + addr + ' td:nth-child(3) span:nth-child(2)').innerHTML = minerEfficiency + '%'; + document.querySelector('#workers' + pool + ' #worker' + addr + ' td:nth-child(4) span:nth-child(2)').innerHTML = workerstat.hashrateString; + document.querySelector('#workers' + pool + ' #worker' + addr).setAttribute('data-hashrate', workerstat.hashrate); + } + } + + document.querySelector('#statsShares' + pool).innerHTML = bigNumber(sharesTotal); + + //Remove inactive + var workerList = document.querySelectorAll('#workers' + pool + ' .poolMinerTable tbody tr'); + for ( var i = workerList.length-1; i >= 0; i--) { + var workerTrID = workerList[i].id.substring(6); + + if( typeof stats.pools[pool].miners[workerTrID] == 'undefined') { + console.log('Removing miner :( [' + workerTrID + ']'); + workerList[i].parentNode.removeChild(workerList[i]); + } + } + + //Resort table + var table = document.querySelector('#workers' + pool + ' table.poolMinerTable tbody'); + var rows = document.querySelectorAll('#workers' + pool + ' table.poolMinerTable tbody tr'); + var rowsArr = [].slice.call(rows).sort(function (a, b) { + return (parseFloat(a.dataset.hashrate) == parseFloat(b.dataset.hashrate)) ? 0 : ((parseFloat(a.dataset.hashrate) < parseFloat(b.dataset.hashrate)) ? 1 : -1); + }); + for (var i = 0; i < rowsArr.length; i++){ table.append(rowsArr[i]); } + } + } + }); +}); + +function searchKeyPress(e) +{ + // look for window.event in case event isn't passed in + e = e || window.event; + if (e.keyCode == 13) + { + document.getElementById('btnSearch').click(); + return false; + } + return true; +} \ No newline at end of file From e37f11c1ddc758be5599c357c91d57f58b93441a Mon Sep 17 00:00:00 2001 From: webworker01 Date: Wed, 22 May 2019 01:15:01 +0000 Subject: [PATCH 02/16] use rpc address validation on payment --- libs/paymentProcessor.js | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index 7644959..de8a0d5 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -1127,6 +1127,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { minerTotals[address] = toSendSatoshis; } } + // now process each workers balance, and pay the miner for (var w in workers) { var worker = workers[w]; @@ -1158,6 +1159,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { } } } + // track share work if (worker.totalShares > 0) { if (shareAmounts[address] != null && shareAmounts[address] > 0) { @@ -1191,7 +1193,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { } } - //console.log(addressAmounts); + //console.log(addressAmounts); // POINT OF NO RETURN! GOOD LUCK! // WE ARE SENDING PAYMENT CMD TO DAEMON @@ -1515,20 +1517,33 @@ function SetupForPool(logger, poolOptions, setupFinished) { var getProperAddress = function(address){ let poolZAddressPrefix = poolOptions.zAddress.substring(0,2); - let minerAddressLength = address.replace(/[^0-9a-z]/gi, '').length; - let minerAddressPrefix = address.substring(0,2); - if (privateChain && poolZAddressPrefix == 'zs' && minerAddressLength == 78 && minerAddressPrefix == 'zs') { - //validate as sapling - return address; - } else if (privateChain && poolZAddressPrefix == 'zc' && minerAddressLength == 95 && minerAddressPrefix == 'zc') { - //validate as sprout - return address; - } else if (privateChain || address.length >= 40 || address.length <= 30) { - logger.warning(logSystem, logComponent, 'Invalid address ' + address + ', convert to address ' + (poolOptions.invalidAddress || poolOptions.address)); - return (poolOptions.invalidAddress || poolOptions.address); + if (privateChain) { + pool.daemon.cmd('z_validateaddress', [String(workerName).split(".")[0]], function (results) { + var isValid = results.filter(function (r) { + if ( (poolOptions.coin.sapling || poolOptions.coin.sapling > 0) && poolZAddressPrefix == 'zs') { + return (r.response.isvalid && r.response.type == 'sapling'); + } else if ( poolZAddressPrefix == 'zc') { + return (r.response.isvalid && r.response.type == 'sprout'); + } else { + return r.response.isvalid; + } + }).length > 0; + authCallback(isValid); + }); } else { + pool.daemon.cmd('validateaddress', [String(workerName).split(".")[0]], function (results) { + var isValid = results.filter(function (r) { + return r.response.isvalid + }).length > 0; + authCallback(isValid); + }); + } + + if (isValid) { return address; + } else { + return (poolOptions.invalidAddress || poolOptions.address); } }; From 80cd090a7a9aff033590a542201071f2b2ec6f27 Mon Sep 17 00:00:00 2001 From: webworker01 Date: Wed, 22 May 2019 01:16:09 +0000 Subject: [PATCH 03/16] fix variables --- libs/paymentProcessor.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index de8a0d5..cda262f 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -1517,10 +1517,11 @@ function SetupForPool(logger, poolOptions, setupFinished) { var getProperAddress = function(address){ let poolZAddressPrefix = poolOptions.zAddress.substring(0,2); + var isValid = false; if (privateChain) { - pool.daemon.cmd('z_validateaddress', [String(workerName).split(".")[0]], function (results) { - var isValid = results.filter(function (r) { + daemon.cmd('z_validateaddress', [address], function (results) { + isValid = results.filter(function (r) { if ( (poolOptions.coin.sapling || poolOptions.coin.sapling > 0) && poolZAddressPrefix == 'zs') { return (r.response.isvalid && r.response.type == 'sapling'); } else if ( poolZAddressPrefix == 'zc') { @@ -1529,14 +1530,14 @@ function SetupForPool(logger, poolOptions, setupFinished) { return r.response.isvalid; } }).length > 0; - authCallback(isValid); + //authCallback(isValid); }); } else { - pool.daemon.cmd('validateaddress', [String(workerName).split(".")[0]], function (results) { - var isValid = results.filter(function (r) { + daemon.cmd('validateaddress', [address], function (results) { + isValid = results.filter(function (r) { return r.response.isvalid }).length > 0; - authCallback(isValid); + //authCallback(isValid); }); } From 5c9e37d258127eaf7660b0ce967fc27494d006a3 Mon Sep 17 00:00:00 2001 From: webworker01 Date: Wed, 22 May 2019 01:55:54 +0000 Subject: [PATCH 04/16] remove unused theme files --- website/zznomp/static/saplingbonus.txt | 110 ---- website/zznomp/static/sproutfinal.txt | 820 ------------------------- 2 files changed, 930 deletions(-) delete mode 100644 website/zznomp/static/saplingbonus.txt delete mode 100644 website/zznomp/static/sproutfinal.txt diff --git a/website/zznomp/static/saplingbonus.txt b/website/zznomp/static/saplingbonus.txt deleted file mode 100644 index cac6402..0000000 --- a/website/zznomp/static/saplingbonus.txt +++ /dev/null @@ -1,110 +0,0 @@ -zs17wqdk4r98ghjpx890gq5k4ymjjx4hasuq26r3xc6u45jv344hpz4726r8cumqnru35fr6tz5wxu -zs18yzxwh5slp8n3fl8rcx0aazqruuqglyaquw9ysygzh6vtx2wzjrfyv5kjm0y444wp7hwwshsuk9 -zs12fcy88l2mchyh29rqstry3jqt4yxlqp5lt7ct4ddzrlct73l7g7cec8srguup5kndr7n6qwq5km -zs19842nrx4486zutgwen2qzlet37azzdtxakumq2y7eta8qsughtcx3tv0r5fdh4jzh8n7226asx0 -zs18xa3qzr7vhzsyk2pwppnd9lsv63fyvnhrdjm69y6j9q5gdnepa770s7gph40kejrsyfy68j8htf -zs1w8veq59sqrqxmhsclaz3zgwm7uzdy0hqptqze720sjt7u6hat2dsqk2cce29xvhdwm98qs6sk2z -zs1zahnskyy9shagxlf0js8mmptac55t7duz02hczpdvf0prllef56gcxyl0x92xpr9llktu8h7z7q -zs1zeuyy70vxzxk39fwrm20cp973k483elpym339vxmhwqwuacf700wncqln97awrzxpdsrg45zlr2 -zs1ncyhf5fuhess8l3kxzxqjc3harzmxamq97dky4rkcqk7yf4m43tanrj8y43y2glg7etss3myt8w -zs1esq8rwkhwkeylsj07hfsfpqfdt68n7s08n62lpwrs0e2xfq72a60m0pn0vssfy6uqru6wlm56n4 -zs1z2t63xvsnucr4kjqm05fzt4vfq6mcz8sx9jwd9a6vqffjy6wddtarvjlya8vg05w9lfnkjvjx0z -zs1sul7ee3j952lx02cf2d4yf4u3tenz2f0n6wpsykfyd8e88mhvzawakmvjjqqpkq68vxd5ymwsj9 -zs1qgdgpf8jd435wwhfet7gn86ppflhhl2udtg07plkr0ewj374ecte5f8y6uvcp5udc0pzcftzjwm -zs1kyyygxnadu606fw5aps29fs2mgunjcczyaexqre66mhu86zcjap84x9yuejx4wkfupzr7kk0mgc -zs1r27lw44juseep0zv5l6h4syy72sypt8mczs8syek80wvmtw34w6u2r8p506kveas2qzsxw96h88 -zs1dh6j9u650e57kgl07uz9g049legqh9ns4kq938agsql4ynfpghv9rvr5qpl9v6nclyezk473fnn -zs1jpjapnkzlpm96nle6ns2xrlun5xr7r4r8pxuvdl57rt9ramwmxs8lsctxku3rsqgym3evd898mg -zs1yp6umf3w56qqzkujx8tuwuyszy3a96wz5j5ark5xh3tneyuu58wem2q5t2vcxkuy9aj6zmfzvyq -zs1qfgj94fjcflhag5vhqlnh7gwmppjk59lvsz7z8kefj42apl6873y0r8kptdfhe2tmys9xtv7e72 -zs1ffyd23d0wnfyn9322qahvg0569celx4mjut53cxefu9a6tmqn70wmmwrvqasgw9asj4gzn6mln5 -zs15x6nwqnvyh08td34swach9fcn5dmvwypwrf6v96433cvtcnyd7ny84hmqw77zqtukcgzk2pv0x5 -zs1g0lz09y2uup5r9ydk2jvktu4nrvyw2rlrl7sdpy60jv92ml5ehdm0qrf20a6zc2x98tzxe4t65m -zs1l928xv2zhemzsa9tuk9szqwy7un09eu6he2uxyngr323gme8azcrtptju02tpmadqpeavr7qyh6 -zs1jmt0nl4xu30a6tp7vpewaef5k5shcah4xp4rhkaudvtafd4qkeadf4kxyym52hck3t5tumz78a5 -zs1hnm8c0d7cvyk30pae0qmsmy8hwfkfhy6tjxn2zsenseg3qw6fr3tw94508lranzpugw4yasuezz -zs1cf4ctrjf2fquwysmcmhfgyntc007m5maxq7z0l2yzqqft99r2wcst9tknz6gjurrz994vjpc7gc -zs1u9ugqh82vskn487mvvay72jrlwge3z3upgsexmn6n7jj2u8y3t5z4nxdvgvm8ca6am0zvnld5km -zs1j7detvuzfqvpynl4lgky482vgxa2rarnkn8unady5qaejlxmj5jqqjtnjzvvdrnecauzcssyp8x -zs174d39jvd25xl5dlkk43lp3sy5jsp8r3gn635jzznh4k7g7uz465pskgrdu7f3uzldvxuw9k2esc -zs1fxw03nk0crlrawtek22ze66prr96rn0ulp36rwt9k002md8ntaf6mnpkj5cy2wwnzqssuprtapw -zs1s52kht9ylde8jzc92tkpa2km7gzjjxk08sfukp5xf39w765p32wjlzhn7pgvy6ssuxdfus40clc -zs1x9a4tmy7z0qsyk7cdfwk4p7xq0ygquh0whg6h8ewq9ewjjxavt49dsn0rgq70rrucr855y63qra -zs1fl98f9k5ltlf290ellxsjcnaflueew25agqnz8qrsr6zd9zf2rlayg58t036lkm4xx747yldc2w -zs1psyhv3acjcx02r330jnyukfgd7cfp5tzf39a6dxceprez4e0lfj5a98jsl4jjd32453fycsy52e -zs1zfexz0tm3dvugr7xxdcnpnw60pw9atmf7egr4pfjl50kvdwlf24k7nscn6k9ls6yl7ay522essr -zs10awymy4g3jqcux3r37skylp3el7w4dpthhhavvy0t5ukj5ek5fz7eyg3ctcvq0epccq9q87xyag -zs1hwhpzax5aa5xlf8f0wj3apyz43p7smwgxm8fwln7y2c5209dlt3fve9yf90d3gt0wcrkzqrcqh9 -zs1gp9egrus6zrjqmea23nae7pzpxdy9jt3w65j8netsrcctl3g9e0lrag4tgvctw3r7rhryj4f4ua -zs18c0pvr7qnh6klsl47fjlr92l2q3u93wlpw5qakgqjxa9ldfu38uu0ttme3rk3f9kleg77ldu7et -zs1g45rwagj5cpz6hu8pcagn568c9ekftgltnh4fcm8zldaa0xg9h0e7qc8rfggecm58qxfydj0dnm -zs16ktygc5v8205j5yzl6p3llqplqazcp35eg3mmpcnaz6qfwys6r3fua48gt6p2ar7egztcz8jj2y -zs1ssgtajn0ys2fh49pju63dtkge57mxatlpnp6jr2aqchj6y6g4xlnxyux2qhnj7grhcrtkqw34t9 -zs153kk8e6py3425j6haej2aad687d36agzyjwuh3sg0dplv7766v7m4g0z7tdqxkj5wz25qtmkd72 -zs1a00yx0aeky45tcq65uvemc0wem8amydelkftz0cjgql4r33ajf8fxvg374vgpvms2mqe7k9pw03 -zs149209gd7a9s7sx8v8vyt3vj8me8rdhsw4ptm02ygfktdwfp5qn3wny06t6tq4e43rxm7cfteh7j -zs1vdpfqj34lfxk9hzu3hf0mr7ztna0ncg329uys32hd2jyfkljqkryw2xxg4c8ae77d60uj7djvv6 -zs184qhg0nnv4t0xaahpfdtj96nrnm9pyqyjv5rkhzekzx4un5xs45fr327wzekcd2zkw8fqa0ntn9 -zs10qqejnqfjy90fk73aggehn9marygwx9f8hn25p2eruettrkq5hl8wy62dy3nr74jtal6wrat5pt -zs19lu05fty7h5cvt3kyq72wy44vf3khdmpdpfuvs7a5epud4573ellcq38tt6n689e6pw422evgts -zs157xlqh77us9wk6ku2zd94r94z6d30qp3m99qyr4pm0xd4ml3yh5chu70u7z0d33yjs7njylgkur -zs1w9n48xpe8x3j6aak7y4rxl2amtej09qnck67s2ypge0ul5h4tdsplrcsp0ppmy6ap0d8zxku6qt -zs18xpg7gt0zdw6pfp9ecsrfs267jz67s2st7acpcgkgq0dhyff3rcugs462wt3psr5dm2fw0lk4gn -zs1gn9kd8mpxaqjnk64u42kx5l7s6w5ldgpkj4rraf5zrrz5whpkpyfhevt4m46kvjwc20myqjawhf -zs1x5gal2u8ckl2s5nlchs3rthxs659n969tlj0v4xedpyznjy37jpnfmxkz7krz0vtm85qzqydr4y -zs1c64ck2cv8nz5c5edgg50fxzrhs6d9sm8ggtl8kt0qjtp7hf4z3wyavghsc9yrcfyfepkqeshg9v -zs1mxdg5jjrzsm755vpxhhmz8uls08v3wgacmw25xkzjplsr6qp06dc2ml8rzxvga9ej8rczmjqafd -zs12y2v99kcpnv44005e6mhdwle8rsc74z46k304zae72ptuzh80m4s5kpmydq05wytuq5cy2dpmnk -zs1g0h2t2eju3qc6sc4ay4pycmej9ytqsw2cnyc5zrn3plnhdlhp89vu9n08zgqzt87kaljvqwka79 -zs14ap9w290hm9f8zhgg32qzctnkhgcx969ssr6al8267zplzvufmdl395thuzcwljeylmf5fyyhc2 -zs1jw7nup6xf354y3y3nqlqsjfm0fphd4nsh3ezzqq2rycw5ltv4ht0zfj3v8h6mwa9gzdr633ycle -zs1c83zjak7ealmn92hejmqmjc7h3ysvglc9n95z79dhajth4fmhmrnv5zxdkufzg6l489y6hwf694 -zs1mg6tql5vpw56dqmpmy7fyukcm8zhvvsuefwx6l6fktavt45ndshrmvxaas72h95tz0rs7y90ry3 -zs12l75v3x4r9nrng46qe7mvke28m3ee6y5x8kf8836sw4nvtr6sphqq48j626g6kk2n50a5kvn04a -zs1nqwj7exawhvke96q96ykjzvh8p6yvndxhh3f3wmllzmzww0lef2cauptj53lv9nlw0sggmu2l23 -zs12gkk0lx6n290fsmgzanqr6dujkwm7mr92eaymj279952zkryp9399jpg2r8smpdl8jkdskugqpn -zs1d9eny43whhr4ukl97v7wadjfacrnmfxym4kn77gnjtw6lwa0fkerw4m3lw8dpdzywd8ewg6lf5v -zs1clfr7hxg9auqh30lnaz6nnna30sxlwtg22tysarc09mgkh2kpdl8693vgts6zyv5vszkw2lvvwm -zs1zudwjzpg9l632dnk5pf3j8t6a5qd89r6l7jma5tm564agg3fw2euq4zmecs6nz0ypmv7kjlr4wp -zs16thr6u53rg7zeaqxkcdf5xx9hlu3j5a88z0vhyt94acc99dcz5vjth04f6ptd8fsfsnnsph7fjs -zs10kpqezkszxcj3kr3auwu6lwtj9kf6e0ddrtm7ynn0d8m6eyvf92tgd0y88utkz3v9pahz5n8dkl -zs1zvwetgw3f4gkeg7w5590uuqrwtv8n7l9qy4ktpnyryf3tahqae6yqp3l6d3jcktunfcp6nk88zd -zs1ylaqrlgs2gzsq8avw469w5n8m5t68tqtvmjrrs7r2dpgu5404nea6gv7cja0tsc7cz5txkl9he2 -zs1v2f0ej6gz9l9rsy5h2sln5dfn74p7mrmc0w55k68xvvyuawzay43jel2p6lwjp0ugyhpqch0dpx -zs1772hy9g0hjlkftfafx8tmatzj7hry5ps9hzjdyqsv4r686n7cra3q2w3j7xxtw3nunsnzgnw9y2 -zs1mwnecpjnns6mfcmquscwt9aj6payrflrpqah79pjtvk6jnnhvn79jkk7cm23xs53wljxkcteksm -zs1945pnqch4v4q29vam620cu63we578ev06q4ayzu38t6d2ekslqftje762ze9aky3uem9j6uhwk5 -zs1z658lkdqf3kxay9azn0asqxfek07ww5qywvnvmk0m5s30px9ga7ap3gdsaup8uytuaec6pff4tm -zs13d9w3qc07w29xk8ca4u9h6kuxhayj5p6rv5zzwcjaskex5rjz2vs8cquaf7rw3yyn0snx4dwqw8 -zs1car6wyk4qp2577x66kwt77nd7rxfjjm67394u8ev7gqqpmx6uw7r6yexdfhjf8jj9t6e6udqmak -zs1n3ye9sgq7zpc3vzg9y3e40d05pfhtnac6ehxgx0lch5wxtdf0acv8pfvxd6qhknaxcajcqemwmn -zs15glz3qua3q04y5hkdlkvt3f0qc824usnehf64930e04gxzy07f2t9ch03tjdhau7pwf77spe2hd -zs1ws5vj06cm0zn95lqfjuf55ca6t2mschj24vslzzdt5f7w2h7404d47p90ejka7v2e87nukr2wkc -zs1r6xlrv89nn4eye8hdj02gz8398r9plc24aydd6rzzcpm3gqtg6adgpf20g7cfnaz8844q6f6t80 -zs1f23g7fete52k8wx02mxp8nl69xsfav7nu8yjlh993gwxez8apqczhzmy8xav4dcuupdycw9wz8q -zs1htd35q3hd8jxyuf59av8pg5wzuq2qt78w55wc6d4txwdwpdw9n8y7cyt63kz5ztj4nww76k427t -zs1ajezmxjdjktmkuhn5stz33nx7h7k833mvj80jkflch7qa4z5xxwxq4aq8ny4rrj9gt27wk9khp5 -zs1tp28l7q2ulpjuwslqzdwske4m49hv9ccld8mzhrcxqxttug3aakcqxlaw2rpeshajcr6k9mhu4k -zs1g6y5xy0lzrsd3t2xqen7zk5jt65q5a88grnjcgfvtmhmtausd6q6ll6a93s4wcr3226rg5xz0t7 -zs1c8068egd022j4q7hnn4h5zppntrhq6fxeyqampk2tmxumngjgddtls5z4sk5ec78kjpxwq8j6d9 -zs199886yxnqfrdkykga4u00t62e4g4c4uwnepd30vttuumd7zvn5sp09f333tnwe4trrxmkum2m97 -zs1g0p233t7hkufu2nrd2dzkvvmedr4pfl3v0juekd4k48sqej7m7lt03ddthnrehq3ugnqgqezfmw -zs18l8zl0peqr9stt9lv9thcu3grwrqyv46w3kc0nyujacmv0vc7gzuaz9dvpj3t3ujvgqzc4u0f9s -zs1sg0yz4px9ys7jsgpr365fs8w5xuh5dxqvrq77fkajylykly9aaqy2q98n8c465q0m3k35rh8daa -zs1g83322uddtrxmqt7j5qsae7t9muwmeyyzrcvm29su9dh44c2r8ztezep7uaa40mt9xprkv5k6qf -zs1jlakr2558panqn24me9umymmrj4z0fe2fp8kv5tzkf546dce6uptmrme8fv5qxys6p8ju0urn5d -zs187ua8g9yxhjrfklntdud424ggfkp5pahpnr5h382z7gsfkvee8l22tt24z57q3hkzjnryf0d2la -zs1kpcx7qeef79sunr383l57dfqqq67zhgdj9msyw8sw9zxgq3qec4hjdkfc0feurq96p0nvxmpzrp -zs1zryna6t2kys30gl507h4dmnrm747ddt64u6v8569njjy3ve433hgxduscwe32sm4zz2264mrzrj -zs1etqdw89gwr4qm4nsxnxg0tlhrux9e455evhsf9hw092rmtygl2cgxpdh67tj2wmc3yav2g2uxc2 -zs1s0y5ye6qq59lvmkv9ah2l4f2ykwggx2gldz4ffngll0tk62eq5645nt8akw4c9y93ckjuzmtksj -zs1k6v4g6fekqwfn9uspeqczs8vkrwxrtgmrdqcvruwq9qg3r00ktuxepngch2hq7573pxd26wcwy4 -zs1r6d3u6twk4esrfgajxjyp3madq0nwzr5akg7hpj9lq2wy4wdlqy000e0j59v077wjhv96l0msqg -zs15g0xcd04nl83css5u4pq48j9w57gm0ehdr9932k97lasc7779hxydu6mllw0v5kyurdmszgplwx -zs1ltsv4arjssxgdt46erlcnuj8fcsk9tzec0d6j7ewdkur9ulnuxh7kdvjl4zfqgg3ztamur7rz2e -zs1xtuuxj9d2cqxyprf7plkxjyq6yf32x3tjzj54xc9lyewn7s0mapav9gxyns3jvkv7qjhzdfyy0y -zs14gufhmuf9an0wq9sgf86v2rlcmuttpyk2wtn8nrlr92n8x42f8870lsfv0naurrkfx4pzw48dmt -zs1hysn5370ea9pdah7wlwxvjvhjchpfyzvcqlur92ff8te6wwlr55vkg99wsqth3vylkpgg7msecv -zs1tu6yvsjwc7ldcfszah5mlhvdexu308p5vyyenl7zqfqnxfkvz5uqz0207c0pv5eusnnmxpckmnk -zs1q5zatmzhxdvwg0zwyrll4ch87ajjmy2vgap7m4c7qcxfunr4hx68trd66dhe997fgerm2nxpejp -zs1ky7nd603h56y87zmhn00jrks8ucllu2gfhpu0ctkhvu8wprpucs84pwsyhjvwzax90ka5plf5pk \ No newline at end of file diff --git a/website/zznomp/static/sproutfinal.txt b/website/zznomp/static/sproutfinal.txt deleted file mode 100644 index b60b203..0000000 --- a/website/zznomp/static/sproutfinal.txt +++ /dev/null @@ -1,820 +0,0 @@ -1-53 48ef9c4600406ca037a7b6c18ea7fcb23c01bb408de4f2fb8d2ef7c5107c07e8 -54-106 a07aac4f06e84ad966669b6e014a147d08b128229b843a17a88b3f180287de88 -107-156 d3ec25de2f13877208bfd2baa19d9aef2bd46f5723aab350d11ae8ec57d8c2f6 -157-206 c66047200d6d04669992987f4af7cdc11552a93f9cb8d550e60fd2c77a5a8eb9 -207-256 54e26fcd36691457a2c1026ebedc509ae41fa3538799456e3b79f03191f36979 -257-306 07db936212cfb777fc05ee6cb0be68b2c4a56b51ba91d832a483372afa3bbf6a -307-356 d87c3b0aa1d4918762311133b4d279c062b93cc2f0aac4b40cc94c3bd8eba1ad -357-406 9f06be5638ce583288ba3e9a098edaa20c09c234108f1b08fdf5adff6c6d91e7 -407-456 bd252fcb1e069ccdbadbcaf930ff643e54f316f58d0e4868e0481c7584b9d908 -457-506 5bb9d1aeffc629889764f8e6456bf9333cf64fb82154270dc14325184203874f -507-556 9e3df96d1c7059a15d95646688a875a483314d905776cc502fc438a484857311 -557-605 d34c8113bd8a2caacdacb5e9c1b3362e75855731a5516a81021bbbbef1fb2931 -606-654 541cdc371f1a943a84a75170fd140dec01f1ef869d7fe3665e93f12d395fc127 -655-703 17e391559746fe18d786f1e1b2105e32621cb995f4fb3ef1738544182768c570 -704-752 75f10bdf5f78c94e32d0c599f183abe62cb4792031ee4eaa592365b240dd7d8b -753-801 e33ee1257c53b36a0bbe8292126fad9b93d34a7cc11e7a0654c7348130866bf6 - -zcWBRP14gX57BfSqWTZr2a1oW5TX2zZpWAjCDfvZTaLfcXxeMfpaJDzHgQHx31hB9YXwUxgQxwDtz6nHRCBE1hP2eUAuGKi 255.67822211 -zcPyvbZw5siorG13kNeW7LhZQDNzokPFDo719sU4yUndgue2i1zcUM7A4coP9pDcctweWh47uvSMrtBVVyQQSKYk2EkkaSv 254.76023520 -zcB3P8YeLUkP7tQgtArQxntpnMiwvXAbqAeUfweHfv2mocrj7PvSj4oaSB4uRKaQfrDCCkg96cDqma9pGigLfouiidqiX83 251.28694844 -zc8N33Nb2gDP1GcnRbCrviZ2b2NXp5ZRMht87KFLXr6Ss5vTmkif3iTqs5Tsokzb3K2iQK3GXk6dZtjLABXuhoDTtrahJS6 250.65490285 -zcWxKE3rAcWA8iojUbe6qzzN9kz7jthMhDUhrEYWcvVd1HDE1aMvtTmkHGT7JWMnRU2pwiQA7ggMxuboSKA7irdH7DZmYJT 250.63112132 -zcMZzTTTTVjdRRHAWumHUZ1NvZFVyfti1LZWQ5MNFdnav7dLpepDj965Pks3G996eTFxGFrizz4RvULPSg9jC5WjuyscVhE 246.20989535 -zcHGJLiiLZsk3BaU9wBcnKuhCobS42N8VYup1KGRuUybUCcZ4QPYN8Hn2F423TBnmJv4qTs1wBSnB3BSheyPHRtk49oycqw 245.43206113 -zcXoxqAbfcoRrfVcVoxnyRPQYeQp9NcH7hBbyRZ4bNpVzkhLMXstiuaZL65hhQESySPDqKGESPFx6zPNjBaVFgV9L4ctaXE 243.26652371 -zcTfEmKR7EuJJ5Rhedt8rDpRvaED3CaoiR3N2nqXdx3KKP1wdKry6bNyZvoJ2Qv1SqmrWjDFf5B1qCBRKBvZU211SBzEiQf 243.13864871 -zcepxVvSbJMgY8xUHta6KZNAda3E2fX2rdKUYYUicbMXbdKGCVkRobjehuzCGaa2n4k9jx4LXYSPxRcrs3iHbfmNckfVmw2 242.65490410 -zccLxK8FNzdpJAHt8JLR5ELvGeALrenSYHsvAaz2SdW3g8m8cyUb1TBz7qCeckgZR2H1ZXuhB7JXzUn4Wg8FZEkaG823x9P 242.29883698 -zcBMvuqmL4oUPAjUdqnkeuGqqf8VieeUxnXjaZXUVz4emNqw3VS55FambHtGYauUJbnmk2C8gtBqJmQRyU5GyAhLAnjk3MD 239.70607158 -zcPbG5U9cA5YFFtT55U3g2daDsvP6sYmLn6RVSBMMHHPW7r91d2ChLe3K5UB4CEAzAUt1ZqbC8D6TRitdbwe6nqN7djVdka 238.71541641 -zcX5Awx5MFoNf1wHGJ55YXZx6f2mfQowTEJRgAMVfaEYn53JqeLeMExiNEBZ8dGWvCjuf5Z7Wd8bd4V9BoXkTRT8oUSmNui 238.29833230 -zca2B1nFPQjrZE1aZbgfk7Ju4HDQJxEYHunQTcv5gPQYhA8TQucQVMmWecHbdWYLFUeqrhSgRCbTviXN9ZNLWyCeQiE1u8r 236.48549598 -zcBDzVz4TxBcRhPsnnLCvbypDjmYinyBi9wi4Q3ZppMjoeqtc7juyjaoUbZfEffVvp1KpqUYwy9Bgs3yunRQzDo8FfGmmib 235.77658461 -zcHkmfBQpqMnTfc5ERNkS2X8Mf9oxLgE5VAPqQ1SMJMiVUYD21MUtrgvf5NaWcc1W4KN6LXYvRmS7M2UcdrXrcbpTDfUc6C 234.86543989 -zcQNvQU3r8kW3ovNe9hH865XrjyKweJUF9uK3HxCz9RY3ujKZRtvdpSrw7L8LRhkyMbdcRyRx34acDnGDwDkg38EnSUYL5X 231.40954336 -zcYGXzt78Y7A5FExKjCDXJZe1eHKHM5DnXNJXAh55PyXddcYCZpAmNo8foen1irng3QRu6DtW9FZWaLn1XUNjaQUTnVRSyJ 228.42830489 -zcUHMDDtjcgNEttABsSmC1n4UXaK8mKfyK8BUmQtdqpvFyEqB9bQkZ8Vg7Eq9JLzTLoSFnrrwRktgv25a1ro51MSEpVguBC 228.17126332 -zcVsRGorH5nydFDMj2And5eE92yq4QCUW9ysC2f1Ui89Ewjxh86L15V9yQynXiFnziyAWRDbDQjUpmN28o3UyrGT9X7ioF6 227.18895097 -zcNLZZ4ySDqxkXVpHaizKpNCXAbJPj734ECBoWZn59uUVND57ckdfP1TJYmvoSJxPxCnAJxfN3N3fUW2xhQv6TpT6ByyZSQ 226.80050751 -zcCutV88NcmvBoBrziXitUWYab1t3JJu2yBX3v1BLCt5SvsjZNDNPU8YvE5fRAHK3XPWvD26wA2Gt7SfYUZmAxPavcLj982 225.71842013 -zcGsnifdypUk8PE5rP8jkz8ryBZuDnfvLpRMWbEeyoZvgrJ4iy7AgZX4wnMJzxYhrU6Eq5CkdMSpyNHFEpLAfex6P4muMaC 224.96787615 -zcbp82cj1cyvKyGLMYb4xJc11ZBcJmtHnzCpiLntno2h3aJ3JyjscXMJHNgRQS1E2VrckQbrqTK8DmGrhavZxFJkHv2kj7U 222.49421712 -zcK1a2ktWaUE6Sg26cNbpyDsSV8zodLw8ELddJeaFSdTR5oFfF1RZiJ5sSCRdXe9tEw8wD2zcLwScsuQ72p5DdhX3jQpC16 221.19688584 -zcWyYQR4syziSQg1R4amQkQGPakD1px4phYQ4jXaDYCS5sWZ83gXQqtbLZWf29AFaPm6ff4AXLppTrPpzxRNxd5PaY17XsG 217.60911467 -zcVUHnEuZR3WvSkt5pTXEWVAdqB1tdt4D72CY8s9NND58qFnHMUFtVjbNLvwC62enBZsKFdhCtLyjZiLtKjXuDN3ry5gu6t 216.39621579 -zcV6TrYcDZH5GkUrCqWf1kVCGbhRS72GbdniGp54u3RtucFjz596mezFe1dzPSnUBoUyPcy1aiEkqFGTLAYB5upimxcHQjd 215.84322813 -zcA8aKtv4BChNdZQpdUWCWgSddMe1776FL6MCmNLK8riefbYzAkfrH6eei1pqssUntQaQZJSZuGJouLjy27inwvdoDAzyiD 213.92352545 -zcaQXAnsFSVmagd45p4euaLbLAzuLCKrbJnhARPB15qnWdK5ztTSRG24W93ou6M66dnj51uydx8sEXdd4np5hNFvHkRPt1W 213.81935819 -zcVfJrK4GBz5u5Gun3e2t8Re67iy8At6XN3kUTCkwD5SoUvTRsQMbLhaf2FEk55EbCnDLnAmiaUvLXz4i9B15yjNJAgGBHa 213.80866976 -zcgKxsY6Q8ZY85qcLaEh9ueNaAf7qiMkTbAAddLgiARt5KVt442mebSqjDmf5F17oFsriSvjUe5yqmQEYan1QW9o6tA1ez1 213.73300725 -zcdKG98EZMohXiRJXvHv2z4kJCqfAPJGr86wwtAjWayLLF9P1ke9JXhruDk8mhJsekACQSExZvxnmzG5FwgfC4j4dcy6wZp 209.85417067 -zcTNooGyid1KsS99329UXhRHsSaYGnPDA6eMS6No4oW4bDGddvU9rjshfLGL1iVBWAcFzRCDbCeFCag6iNuXUVDvk7WqMCi 209.46186941 -zcU17Q8pBowpGk3cTXAcstqHaiMYkxKQZr18Qf7iz51i14Ysp6QK3PbYfCEtPtKefeQgoWc9netNjxH7EUUvF8ThLAGb8t8 208.39089670 -zcgu2gHxnnp8VKEJ29KCH4xzsYouy4MQLaviHMRmADEjRJDdRDH8hgV1PJgQuvkX6PB1rTW29sei6ZKq3VdHuXnCL7cm32j 205.53565306 -zcXyqfqmcqb1octbxUK33T4BUbXSmcnrhoVvoGkyGvheEEvrFfPH3X61uQiB4sDkerpoH3hmRh2TE4nDXU3W3xqs9kjfqSK 205.03398341 -zcTDxF9oY1rVQnn4gPzVQNGA3PPdRsVunVDERhYDDhVdmwiqwFi3HsMXSRc5sq8vVrbLYQqXBf6HwQp4eVRQcDryrEc46Km 204.29383663 -zcbsi9UmQCmMTHNov5Lpfhj89uKDUkjUwobUdVNqWktLww2BsbTvohXDHbZnnhJbBrTzSTSUvLoZA8SHSccAJsGZedtGU43 203.16376180 -zcSTY8MS3aTUBinSgedofCEpicrWH9iMwTeYMVJKaVAyKjgCa8B4ys45p15U8VbHMjWBAkDPZG8SG6ZJCBUi7YoHX5mZXL6 202.97662596 -zcEr4BzHHa685y4MCL5UwyPVj3KHgVNFCeSH9SR38pGatGJvfvcSmuWMNLq7p48vscYvkAcaDhGoywLtisDGNQLVJF7RLDV 198.34545850 -zcFKQ7waGkjYNVw3Rt39GPGn958cJz1ZuqYWF3h2y57Prg46cKUDU8c5KpMZki2og1kx4bsUCrYBueaHNhBGwzVkM3FSv3G 196.00074374 -zcZsswKSsAp7KNvXYX4Xi2nWT1K4GbzozYQ8vyiqMKdookdATqQ6dNKSNKUi8NZjHVzRqe6RRtAso6CLxMWH6wCUYegdTXQ 194.85500151 -zcUvUh5BwBbfVfnbri4766jpyWxjSaRQ2bH8QGFSv3ifz6cjutbPSe88UZKKwasMSAwUrU97Xw9VQNVeSX3bMMv5JijMLJZ 194.79528359 -zcTNfRPjZaTLUuQdZuDCvGgRNug8G6ZnyKBGD1fCKoft4Py8gc6G3Mrf9BD3HrtQBrQDsTEZk7CsUcW3H7fPg3m6a8mD4UB 194.70884614 -zcAVies3xUmntE97dcSE1MJtqMJvA3Zf6Vwd7bXWtTcKrpcsP7gQLRy2Kwn6rmRq6hp644cab3pXgvhKnNnX22nTecv2BUy 192.86030404 -zcCFE7WNXRFkbxzzJrfRT4YfoBV9T9bjibdrA9tP7mJ5CrhtAuX6YEm39GnJgwGtEmQMTygpY76gz6tUyQN3ejraXDVtT3x 190.90531097 -zcCtnXemimGVaPQB3LG5Twbh1wAAFMm6ttsiDACDPorPbLFedLHEmYrPTRSs2HEkNohBJnAxERPmbQVGVMb9REDEFdfPyo7 190.85850952 -zcd9xKsRFgqKr7Fx19yE7MWcNUPFDnXFtuDCJtbditKSLRJ719iiHLM8JG422K7ocn3bsc52ctitpA64NSt3AgQtGdKto6g 190.69721021 -zcdeRnPerxujPKf9yHqHQMHqcNHQRBDQRAVRVg99nSP7VRiQbVYFXDWy3yxJTmQfFe7DFjjEYsMMLhFhAQuuvcEXDcJcoEU 190.39515155 -zcGL34NUkpk1bGTpXinoN1UkqxpvVGERf9KB7t6Ygaa89j4Ybe43tLfSwCPJ4mp9q7UJsff2UdoZxACDDrcsQkzP9ykLg1o 189.80532948 -zcGhkPwhHaedpFbjE2tEbHZrWPcw8DLwUkyZq4Ufep79n52ahKQhdhmX2YRHXviV1c5RBnntMSt12sJk3xzwQYmshLmDXg5 188.17880725 -zcbhjVYKnnYzCfnt2RGYYro4esguBpz6ptT7LjNjLNUNwWCPNsydvwDRAAecrQ6NnAAi2gYadm5xWpExEj4nsQR7AxQQdSU 185.55710621 -zcREqPAYsvzv1ZG61ryTEATNGg7dUHmxaW6tbYYUAVTrLXkW32iXYuSzsstWmceRNkHEGr6DMbQtrgV2mTAJPRcEeXq8ouK 184.89679559 -zceuKv1CHBxdcbKjoxRUsqjCYc51eH712tZbZLzhj6Yko8S8ubLRbvsxWU24FEVevG6U9wviuZnDQyx2FEvzzy5AERKPe4k 183.22561347 -zcDgidTnXsZgNEqcpNxhTLu1MnVuEpJAdDKMZ49R258h1ST1zYB3tHaLQN1DCSP9P78Sg2AAfDWKgDGwLiye4xNYfmvNHMM 182.93634575 -zcUwesmuEVUVa6DqihU6QNG6fXDbMA9aChD19tga7po6c8J1hLuQjxH1KyMz8WJVNoe5HgK7NToXsbRaMUnfAVBE19dGwN2 181.89850170 -zcGpAepBrZUMdJcY5T38kJZi5xcg86nyD3oiWHZiCXad6hfKJDbo7tud9eeuXw9LDDMQq3RwCUDuycqyZA3GcGFkuQBgk4Y 181.81606058 -zcR4HMdKqYyC5ajVhTML4osJZRv7nsb1ybd2Eu2DfvtgWBmkrXLn8FgjiSWELZqpHmxJqiFGTU8qJewtZaVjnjSyR5YLAxq 177.77531881 -zcHWduoWUihuPQx9U5SHvAKKsAAewpLqFRHGdCDZk4g5FS7QFJV97kzoCnZwpgTVz3Qj7BAt8zP51tJxKGFaX6UojmtegSu 177.35000811 -zcFyBkdPZe9AqkAJS3vDnyv3NBFUQmJSGtkU13wKbZQ52oyofzY3fekY3qqpePANe6aHTAtF4qyV7VmHhmbJQ582sBXngpH 176.93545013 -zcTwDX9UArXjCk5x48EqUY4uMVpWBbMSWp4WZ38DX2mDEXdKZvGngPdkHJLrAw1AS8xxwfasHbr7fW3RUfVXNDu7vpDr9ub 176.88339594 -zcfb2Yrtzbk4MsfaAiCWExsSawpq8D8wRMHka8pXABukaxZaQcXuhPPx8CWzmjMTn1sDcw5zc6bexGtNsdr2yWU9Zcmu2v8 173.99130762 -zcThA4LEv3BTtesrxHfRZUvid6gPJBeLn7m6KWP3kM6m3irMR1Uh7xMCsNMeYxsYVZCGxTRBSohu1mwWyQqCyLzRJ7bfFFn 167.29855659 -zcN6jywNM4Me8ACdSM7fKLzA42HteLGxA2M8rSx7MX834mEzczSFW3a5rVp9iGWiQ822WT2KzsrgBWWPiwUA6viwTGx9Fkk 165.35934913 -zcHqgYkCbvim8FT13bpkV3C9pGfJQ2jhUdWFLjuH3ogHpfyVpvJkRE6jP59n1ndyznot5vzytqe7upXWgJPJn9d4XfiEnNw 164.13918514 -zcdvfZMy2t7Hh3xQBYyP9tCQftjMnpdbRmYZ84pDZFUoHmFkQA1qkNjjNYzhZomUdV8G1tZCWR3AoNsR6SXPrM2gnjbAL26 163.49713187 -zcCF6hVYnivYpBqbrVzfjHQHZA3hU1vmU8gc53ZsFbjsRcrynyfWQGw6Hmnc33CQWSvNFJTqeV4T8W6C4FVBe6xjhhqvHe9 159.68355320 -zcUpaFzsV5a6eg5qp7r2zj5oR9BL2tU2vvPnFnPHJp5PvUZNQkbKnZQLsPmbkB6Qx1Yh6w3YorvV4ew1tDAdNTmWxxcfkT1 158.46811042 -zcVzAKYtkr8n6hziRzzPFiofCRRU9tvE3hHQkDSTHLrtcFjTmCd1U3ujth7wTcy4v9knVkX1JXsMyS4W4ks7A1y5E6MgGRy 157.69503093 -zcXoj6yPx6JFafmfDzvmWoRjxXuBg3pmxcHFZTvnnXN5FQzwsHqqZ3oLVhzYdgarFYt4yKgqt3EQCsgkNZmiPD2Dc4T7e4r 157.07174018 -zcPyDZhzb1E8K8q1ysKRE8tdNs2CM8H2JFNwxcQjmTDNPGxbz5oQNPDxdUdVs92AQGQP7MpYimZ9T3eU5Mud2cKmLVDd7Bk 156.94788201 -zcRZsCTyLMEN75bEaKYBFA7sD7PdjK3uSrG6ZNG7AgNd58pDZF7adkrzart5VJZ5QRuK2QiArWHAXpDDnVQRznYWKvwHE3X 156.02308989 -zcB2PGdoYLDZmHRGdZuGPuNPRz9S8tXUfPzRyHUZfhQCKqVodXoeVDN9PrRRVNmNvb5JBvRRDB3MpkXGocZQUQFkgtYxtqS 154.67576279 -zcQAoPZzptgncVKKuMyABtGGHoeEdx6hfjosjVVcYG3fTixniiKMqKX5a8WcDXRGHdvrhUDz5Wkw9kT6mXBM94Qa58bZjqz 153.49082494 -zcg2yYTjGrLh6SoQx6BJd8vX1urBfBZug5t3S4vAfLsz9qtyzgEyV1NuEKytfz51SRDVJpbnWyPZqaAbQs4ZE7Yv5dxkH2k 153.35621978 -zcV3E8BcWc4KJkY1xPdgUwKxY43NrEKCFy1K8Q9Dm2dnNsc8BFMQDr4q7i3552YEGVaXzLQnCW6Kp6jtXwR33LjBgaGdA4Z 151.54621308 -zcdbB4j9B3WxDuMCKpnYyrc4Bb2GcVXqQnb8aVuTpJSrh1XErzRYQEvpbnRRPyACegY2i8Lk8P7FjAJk4ySd5KnF8FSmhcT 151.49281674 -zcMbb66fHVoRZU5HSmBBAzpnYAEFyHsoiUXRp4HgQaSnvoHv5MwLe7Xe95JupSC3qXt5ajMQn7b5BB37oc5oNwy8k7ffsTX 151.22899794 -zcR1pdbjomXVPtffobrSddDPY7tvetyAB6dLuDvN8vqMvx6xqULTTCbwCTUfgwKWtSchHtcLWkEY5g1d1ffbtiEKFLhfJCk 151.16116460 -zcLWjVtQsSvHqdzFHxVvjipMuSjqYiZ7sSH3CFis65xmvvo26oXUBVnru6FvTp5xjx3McKsaTsC1U9DJu3b63ygZfKvUTXs 150.88608391 -zcBjU9P4dGJQAUugmBsTkun8AdPVgYbmkCRWUYTq3G2qmQYzMcpsBDbLvo8EKZFLRb2Gi7yPfFSpL5aKdMiVfgcgMt1mW64 149.51511499 -zc8t9MeWikAKXNWwCpxGv2SvrM28UDuKGBGRA8rscsrZWZZqUGNHgVaVeG3jLJw6YgtUZcJydKxPvCMJ7q5zUjHyKnHQGNW 147.69555661 -zcDhFUnijyzoL3bcZaXYF1WBBuP93E8SJUEbomp7ynXPZYf5cbtrp3nHGgD8Z4PVUHeQuk6LEcNvF8xd2Te94YdyEMjtVVo 147.13076976 -zcNyJk29R6hh9yFxMWNouXqGKQr3gJdHdELH3jeusLB4MnYXguFx7bo2br568U1eLQQzwLv9Cx45tnymopA1GHFkMdL2SpJ 146.04976660 -zcHPKrQn7E4HL1WTRpZMVzGqBHtE8LrKXzpLZ9S43rK19j8txYbsXzuSnHhbKcQXVGBVw988U7e3LWKpQM3jaZZk36txfYF 145.37901425 -zcAfZoS5wsSnfjq3xXjTsy7CqPTbUcivNNC4u2mq9wfdEDrAciZicVQnXLW7zpENwbmASNN52tumgx7ikiS9yDikRpESdVA 144.78212877 -zcBYECRj2cGVKiRn9uxRiPRKPiZgLmpQn6ssBVmgN2FGv88SjCK6iAZ211gWZokU6g2xhvpNrHJBoUvUTfBuuu1x5hd1QVz 143.66347797 -zcRRdxvg9kwpP1KRdcSPZB1hCcqxLuEr6Aip8ZPSLTwwCzSeWVBzMED3BZ1NBPexQoDcoXSUQPLYhMiMvBvamPei1vVzADd 141.68186151 -zcFoMGKHdq5Az3JfuHhvjzHkS7x1armGNqf5dVKZJUCyeNYLovAYe6V2whYFT9G9sbCCV6HxYGXuMZhuyoS4c4BPYMotn1Y 141.19180480 -zcf8Z4THNHJwCKW6Cadrqdtsgxi1U68gPwTNRhQyCUf64spNQVV6BJzCryXUvpHF9uXyW2AooQgrWKaqQvskspDoSZff1Jp 140.23180036 -zcTHe4FZo2Kxx3Gg3AKkDQDY5ByNZcSn1rhiinMGvh1K7WzmcV6hqLJr37bjdsKZNv9dmQE2rUsgWhJJhn5yQdFsDteyXXb 140.17344290 -zcY31hL2V8DQupEk8JMxeTpXd6822VGEvBuWmbZLmrt6MEbUKfp27WUNfpDkkdrnDMS4Gb18EfuW4XiiHNwLKWitvUyGq3z 139.91234583 -zcDJMsLTjtMMfMWYb8yc48KjXoFdEMSrfrW7EXfUbWYShK8NuaT7DMxLCsdNyBwWMrTMhJL7m7SRZTbxqm8VDXvvAD8kX7q 137.62946890 -zcArNz5qm656E6HrezX9XEjQyG4hMtYpY6emeA3gLyypncNRrczvoby5W97rj4kMhw4d7Wf1gmnrZV7psb2YKGnFaqG2mZw 137.55951579 -zcbu5nVMughorU96DzQ6w1wsiKryK91WKv18MU82XeE5orQFfURVeHJ481ooDVxDJxajTFZTKRqJ3ZTSSvqdbbmxjrmsLmL 136.89742295 -zcUaLSu1yaPZKoSfMQxu9n4Pi7yBN7Rwj2AJGPgb9XvsQLshY2XwiyrboUb4m5vc2stW1zuo78NYjm6iNcGTrhtYKvk1o1j 135.55543172 -zcbdXHgTUeBGm18kmNgf6gNETiBepeQA2u8juBNzXycRJsRAmu5QoGNi9tsXFvEuNTDUAW5QLuu9o95yP9EsTtNzwFGGbui 135.47165156 -zcSsEEpvD97susq4s7E4vWfuJhCdD3Ae4PmYJKF7DTuwVyfkYmpo894sCv1e3hYJhHUGQaQ7WAGUP9cH53F9bK4QbNEMQrK 134.64385663 -zcKExRWVXPRJp16p2o19BuK8nubsSyzAihiUk8UuXNWBURdGQjn9PRbP6FumPWcfEDbK1Qoq8AKmfrbASDsG2TqNNSV7QJC 134.17577470 -zccVcvi6w6LyoLBsi2fUFFjYFeHWmi5bhtBB4H2F1UjL4QFKX9xDZMhQDGc4WbeGHAdxPaovcyCZC6d2YzpaifFSLjA4rtf 133.96351463 -zcHUUm328qwP5BzAX7JrRS5jJafNZHCkkzEgy5Zgub8M7LdoJjFdUmUQnMKYcwqiRUCANHvPvDCvmPVJTQJhtL2r5V99Mak 133.65347242 -zcVC8m3eYLprz1jDSbDpBVTJcWdQSXyiJnx9jSearFWArimUZN8FThFzRxxGKRQ3mMjo9HCg7sRDHEG1xLVReGXbLr7VYVA 133.48165547 -zcUCnSusMkXdQTtHxmYPZQJkngt2DFgGWoXcYCy3SxSj4qXgXDdLymMSy1SfinwPgLWPsL8sHrxmoUCJPBPCFMDa8TAqBuc 132.00253140 -zceMhcoMh4BGL3gm8aePWn95pR3AVir9Bz76h64FWRnLSJ7UUxc74nNRZuMJUYW5XUrh8C4vtcpeCHppAEhbrq424UiMUrK 131.32313128 -zcbVzWaU3Nze7837xbqKqvZQj1dWFQCrBCDWPVRy4yk7icN1pqSFCJXMLMbrAK8MKemcVo8vqjRiCma4tq1qFHHrj4nR76n 129.29526376 -zcNgRkT7wzdGAr8UCDsdSG5nSvRWtH8oQRPUkhXoo3vZ3Nkr3fHVYEEhfgUFXTP8YEjW7uexhR3CvSsWjDkCQ4gkkHzHoqh 128.94652458 -zc8JJzg4HURtsPpSDkdnU7GCSWZEfmr1cDUnGWXT1n5i8DRaKP3KLHkYdZC9DzSEhQMEhbSyTN4T9yfkkb8BQgbZwik2dS7 128.83504478 -zcAx5SN7qn8vzS6USgpnG6q8oErkWpaJwzHDaNGyzrigJQSbrUJVbyMyN87VnD1G4QuAg4tmgeuCaa6jVS1JQHarvt2bbLV 127.71785609 -zcQYVcXoZ7V7tB4yHobpbGLpAok7cYU9yWFKCQbAdTDGxhuQhyGv8XMmWfxTyY8vvc1tWr3uRAygG9we3s71Mq5GYULeE1W 127.30411692 -zcM1KENZruPjpLVGLRC3DC8rgeZqbDRYdGvRGfwohQ9fCLEwQDSZrdp8EjMbNMH7XWxJWhYfFyA9k5hma7FDfFqTdsw7TRm 126.48717858 -zcR2F3GBREHGe5PGQHqRLNdtqGcwfWTZVbY7SxzCJrHBe6Awhk6CMaz4PbWUU6KCi94Q6NxoxWezmqxSoAMEppKrVBtJ6BH 125.10731889 -zca6XSiKpctX6P8TdX46wBm6fL8ZeBo9SboshiJZVTbThWDcueNvLCwAVrErS7EMbBPPkvaAmoEJDkhG6f5SbHfG18uTEnB 124.66728518 -zcf6cy2VQ5vrRk3whTx7xsAdb95TMT1JUsBpYA3Wt6jtRXeFCVvdgbTnfHpGAAgatQvXttZMd6TaLpjE7JFFqTQY9hx2gzd 124.39417347 -zcWgtpQv6dkGkBregCpkTgS2hvNT34tbmfXG3wBkeFSdqcyoSbmbvsg76i8cjirng6M2QNawYy36MVCL6Kkb2camW4k1ut2 123.74296632 -zcd33egpLRRYPH532UMaNwmqnLMzgKusRCRKh3Rh7uCHCyFephrB57T8ZWWZAP5LrTwknPJuBVStydqq4rcnK18yJ3YHor5 121.24922615 -zcYLU3Cd1NE5siY8h5VxKwGk3sWS1kys1HmCL3WDsMrjRNPrnrfVD3CFCpHsjoL9ib5GZoHsByFokGfyynNS47TnebgAeLL 121.09560059 -zcFVroBh6FFuECMws9FDdtc75cSePCCeDEsQJ1gJ9YXgkSi1WvaYt21hEJj16GLFNKmq8Y3Qsti3pGbL1DTRz3UEJ1565T1 120.77553086 -zcCBWDmxuUJmWERJrFKYSjbYcMmSa3Vy41R5oCuLMdtK4rYnT71Ao82dAFozXnKCkx4okpVzZv8hozT73ZQvEiRLmyuWov7 120.76255029 -zcEVVx6CLAtQM1sEYror5u3sXmLMVhX5x7SmSBmUHsP2kRSpes5XJGKUZyP3CvVVf8HjF5WJ11RMSD9rSABap9qBW9Rp3BZ 119.93842929 -zcNg29rFvRkPdhukkbeHsY2yFPvZbsrM7BqiV6KhXpS5icHGDKay6YK1Vy9kzyuPuP2Fpg9Tgwnxj54AdFS6M6D32iwsgvS 119.46697941 -zcaGZHRHpaZ9UetpmzB9mLBy1nKmB4FM1hEHa944rZLorxtPruBj8y47HDLnvqBhGdtrNqwVCeydgtwqBbFL84uX5GVzopJ 119.36692541 -zcLB8twx3sWaLFz16zhmApocZwed6Si169okcHnKmFcQ6pHyXDarmU3LMmbKefCyQhmps4yYCxnqKcD84cwPtPwDvdCGLqS 118.66973397 -zcJnQXyiXPmNw15PWFLVC21qqLyF12uBEvgHgoQZZiBG873de47jRibCfpDPJW4ELd3rcbY66hCphwsnVsJaTD4BYVYDGtC 116.40559084 -zcJJ8DdGGXFFfAWPjfLC1CxhHa8zMoifq3RrVFm9ovpQcCHWF3U1VXXV9NWUczVipm5UFbxngMHA3BpJiLmXvrWpoe7dcu8 116.15643217 -zcXA6CU6vFSwYc8UypGLQ9PEeqNF3Bh2s9ccCmhwMUP56pY1MMs1avXNn2dSZzk1D6aMz4TSsGCpyptCN9kjCuVXDptySBP 115.74507792 -zcWN1QPALXD7L9sictFi3rCFCLWUSb5JGGP4WYucPt3GVWuqywmhmfkoyDJJeKgLFB9mMtngbnYDUg5MZPNyQMnNQM3j6ed 115.58829389 -zcQ5zYFzdSfFfNZSmMhCzzH3hVjQ9xviybsetiRdd4CA6o94jDvVhTp1KmxFtq4TWxmEneCUKUY74nAh7W3bkm19sEFLLwK 115.48177711 -zcbdUqNzMLjwA77ZcULC5UK4sJxPkgqawBXQomtZ9kVLmgsio8VaNicteP8FUUXgbxfhiMryjcgZZTUzf1ZRVaUbythHbym 114.94377520 -zcd8o6y9rvpy1oG3Ls9ectsqzkFK7aWuWHR4HUeW3CqGtAeJpRLrzbmxPLKgxuixfuif1i2ALVwMcozwB8FFa64xUxMjAYq 113.77290478 -zchZsoJyDwKGCSGtP6CpkE2zN6NohmucM6TUw4nwGX2UPLa71NcKVq2PGNWWmeW1xrkJgaNUmddA4NnujwAstPVy5o8xAss 112.40886959 -zcLLVHtCs21HC4SWw3snGbXhEPppaztqAtuJ5pHq6VuJfsWSAVBsv4frYjFKoorMei7UfAn3YUWz18L65XMoKCDeZsCFeB6 111.48580971 -zcaSNziizyMPaQUcsoEwodn4zXM5zpDzvMFhB7U1eRRnbQbjkcWwFQd4wShZfdsqidWQjzJzNc3q9Phe11XCxaRFDrZd69Z 111.18800996 -zcdaXumGjEgbNGCMpTkGiUyzKxwkQZCi1QunMwG5AyaApJCNNgPtNjfEwSV1sQ8FZtUsg16dHJzxpPMd3drSrgd72DuEbtR 110.99072160 -zcXkyZmQUNt5rrhV9SfaYrESP4xxWjkZ3Tq4h9U8ZG2TLTWUzBQnm5raYvaDkfnHvyvVt4HFsGJGVYdT3ePZGRTu1derpwk 109.26464564 -zcSMSUscggmP1uDwN9UgruWVqqkTWw5p6ERy6eWupyoKRByLQ53RRqc5Tn9rGvexvNRbR7jZtp6TALyCsXZE5EkPdfjte6f 108.07933941 -zcfHNQ41kgTN2N5QpS8vzEZnKSq7NcdubcZvhJxgSwft875QYM7pg6JXBVaCZ16RxST5xJfY7s94je9BsJcqNpvQqT67BA2 107.48498480 -zcB6Bo1PPbfKTBeZHAfz94cdHv1Ev3EorRFtdW3jTXdNRzkkenyhypVo1p9tC8enM6MsdLbMBUg9XZgzqgaFLTCH8xzvbQP 107.14521442 -zcWLkecSN9Z2ZFDxqkMDPwM5GsojxoJzKpWGWUtbNKNyrtVHAGizuEDgyefRYa2JjNpUt94WNxJ2KTtLUHEwgf5AHLPWiqL 106.95099054 -zccudGQTVxgaFAVKvyEzxNtqCGTBEv8c8PXFaGPteJkEXtiw6EFjsm7FqK6kPS8uueYnBzg9znDg5fCriEezq5sQUP6Gr4R 106.40606459 -zcaxKrmgJtsTgVkzMvbv69CdYvYe6EjpqJmGLDbVMi9d1nJuyEEnX4Wd2JsS4UGyntYngfXoygQotNSi3cQ1YziHE3mqf3s 105.11331315 -zcPXDv6nhpmKSfTpS3DTxRL6dS7mSjcqrcyCeSL455PfHotL86FCPDYoFVxSXaH1NrSEPdDJXwbu2Vkw8VbHMinLBxd3fZ5 104.57523247 -zcQzVhDDUdcF9vHddgHB1kqcoGPfd2D5gkWH1Nj1E7ZP1GiZBE7n4fyGzcTNCs4xw1cYXewhYUXztpYFXXwvGxunrG6T2Lb 103.27796118 -zcFLMmnUnz3wQ6Dz9dXwASqTDSstFhGQA7Lio9UNfMxDfSh9S22wkH8Ymy2mVeoUyHWkx5ThyU87RwzpRHz2c8yfs3RZGRt 103.07588603 -zcCMi5JjFSSMhTwsEyTDvK8oS9yDt2QhWePGtxdpLP2um32vtN9nGwKTQGBCqjuNLmxhCWrwYRhV8jcx7JPxACbLFFxGrv6 102.64539404 -zcWNzsnVFUPH6aPF6hwiHjD2h4Sz2hm3qVB5tBUPWz92JquhXzzH1GVoSafo59Wcaec6bjxPoVSM6oWPTyFyfuxbKcATvWz 101.88952531 -zcQSGbMo4FomHpPfgzMX2GkpWK59WJRVH4ru5YpYmp9CAsS1oQYY1DgPLt6CXbK11fuJBe6RNYXwsNNeMcc533T5uqDVsnB 101.72249117 -zcgPH8Uqwm6XqrEiv7zUPbEzZqbKna7DyZAijqiobdD3TKA2XHqcwkvsVivBWxDc7N6jgUZyYfuZdL2JgGJwgSyfjqfx6CX 100.22225578 -zcYdjTxbbHL96emAwUtPfQVgrCBNM6Y1xmBTk5xjX5PG6NrXUkHkFKy967vSGMLGDDH3QUKVnzg7afBsbGGprHz18a9jXBC 99.98655657 -zcSWDw7XD5RomghAQhsyKjM5xbqzVrexrqxQvzpqnegu26EdToQNEJ4rshchWPZh3bsJ9vr8VCut4qDRBYix5KcdiFZpPvn 99.64281858 -zcewVWx76Wvw4pVvwApFLhWSDspC7aX1xsGgf2gpeyDAdfQdFftpMCXXvnMrMNFtm95nzNbj69GcfcYpsUtkhky3gbwuKhk 97.03981806 -zcfiDbipRPCd6vZF8UvVW2sPP4Bxa2TcKKkSAp2qccgYnRJ6z4X5TFHv83Sa1G71mpc8PE4rNMJCDRM7w4Uky3X4w8jGGU8 96.71504234 -zcGQGcvYQ5yppqodTAV4UYu34kCEXX93G2ruiGGDAeZizFG4LTDnk8d2ba9dDhioiDnsCZCrA5A2GEDwGEjpzqtcFtobg3M 96.27867963 -zcNgtkqUjrwPQ4efaxCdiEc4TizPHGYSC5ve6CWfi4ZewVmfnhGGADtk8ZBMuexehH9UJmyKcDnAscmEtgVXTFFnc7J2hEH 95.15879322 -zcXtD4Jyr9yp5dU6tQQBCEVGT5aVvfAfWNJerbWouWFhn38TNpUAnePvPhozxcPW5v79m7mPm4z5g5oJQdeuFEQnLG8phnH 95.07104222 -zcVLhAtNhEjzSkD6U89wgjfQeNFYRgaVZuGjNAtL9HmBBLgwsgvpCX3ApuhvMLD8aawtBHLPCcE6QSmnZpKy3coke5kyn5o 94.93321857 -zcJT6MVNpPBzRLdK71tT8EdEL7qGZKp2StN64pZYPTZHaMuxGGWGeGXAJ6uvjvYq4B2vYNrGizd9Wk5VtmS9YzuNEk1Bsno 93.59488922 -zcPhkfUpSKJZHXPJjdgXdMft4fxGW5NB8BTknp2XZkkKgtjD5xasjCqLyejjWTw462QRaf3asSXBSD9b8guACeTsgJrc97S 93.47791014 -zcFL8zPoNKjZCLAT359hYZHva9yryGuzr3sHngefD5dg8PaUybWFepsZjavUwWPb8Pt3SGVrHtbNfx1wDoxHEiWJNUrqQGY 92.48273651 -zcTwHL2Yza6n6VbLrbmcRug7Ybak1kZfo1AixYagYsNpKYk2BywGYdCb5ZCPXisagG4r4Y3mnVr21X9LcMC9b8VaS9Z8Ef2 91.16910368 -zcM7oW3w2hTbmK7efmturcBAfWy9jvaak9frrVxTVNCDdaRXPnwnbTmi9VNuNBH9skWFPG7y8tyFKYjLCwWhGjHae4J27xg 89.61979192 -zcTynUx4Zgi62qFBXoFRnpfit1KJGCyHCmYuNuE1k59YWSgQN5sVu6pePUfPNMdEdcP5BAx2zUHKNSDt1UxF7jZbGxeRMpP 87.84034575 -zcZuKsRf3fSK1ayjsZNyZCYeMekiEps1PcvidBxhmfZwNsXQNYXnwNiywrijvz3jpWKht1h7DPBhqvfBFhi3BQ4Ld3xzCJq 87.50857895 -zcfphmGG6WqwBVhefmcR39BPXvebJpCJSiAoQXyeWD6JtEqRiHq2AcveDNkjN37MrULNAVCNEZXE671Dohywsi954R61zre 86.22514515 -zcNmg5MiEQiRKirmwXNgKKRsx5iH65Z759gihV4mowiAua9RS2bHaeLCwDKDRyXKMBYzzTSQt8xoLwQarXNX4UNtC9iKEjr 85.93478724 -zcE2gyNZPTELnzFnPmEQWRDYyWdiUfU2wQTj57fcznYvtVAA2cy1SBF3GyrTcvBzqh3rXddpLYCmCmE14frKe1qunzBDzUX 85.88566942 -zcC85HmPBLEpXidfxkHFzPCx6a7JAerRwJY8b7R6zh1HSsspKwib9fAM8LDnX5YobYxyEVioLEXYiq3BY1gtUvG44a2wVy2 85.18818817 -zcDbFaJNbCsrRNvxf5yUkXUPBpsvUcAr4XJnXooC8UkcthDgw3YzmfZPccAT7QvAerXwK7MW4bBBZR7zLMHSmh9r6MaQbz1 84.73335611 -zcfEZea3zuyLZmU6ZV97AVsjpdeMeR8hA6D2U5oxsa4HkmPHpviv9Sm3tt2jyfJqthzRrFu9UQE8aCggK4ZGLgH5epwAiMw 84.46829133 -zchFMcM9mx6jhKn6RgVzYmYTRHUSAThtkWZjGCyPKxfsKUKpgXKBHY8Y9QyN4HCVurmeE2jytsLLGdAXxf4Kmm1YeE8n9bU 84.36521555 -zc9yQnUYHzNyooS537ZwBGRZHaequgunJsPsJoh3eKuVoqacNbMeyPYVUSwtBrWCiAXLXst6JMVGFBaD192MJfZLbcmmrXc 84.17244627 -zcFnhhxgocbSd8r5btyuHVhq148BzUVMJsGBdm1vSmyCAQNYQaL4SrdubUP5axf7swvW9e9EE6anv1S4eJMqAfA2t1dDTdJ 83.93544560 -zcXXczPc3DLfuHUxLPK24G4vfSVheR8wK9SgX27LHsuumubiWvFxUrxydRnYxtEWJKiXhLC96Ati1H3Gfhp9s117A3KLgeN 83.49646894 -zceHJPSxjFE6FxhRvNcd6CxzPdem1x8ntvCwFAhJ8UGHBS9N5ouJjSSz3EsqT1ir2rJbcFeNErfz9sSdCS6eYHas4X7sHL7 83.05107552 -zcQXeyx97YWcL78xkckcMu4sGJrRYqvNJFkXgF1mHpq2JZjr3Qmb9RUbcHqQdz1JuFGU4BxUsaHarT3v4nUe7GM3qkY9Wwz 82.69989189 -zcgoUA1jGfVjc2V1sPm9HVYPfGcfjUS5zbsBgMiaAmmP8wpw43p8gQKXJtWiPLpzRAAy4ckmV1P3X3RxnsgSkurQNTC6kcp 82.64986966 -zcffy2938UFd1iCGu4BEDzVugkSyVD62aBcmQpKhcAGgYXJnyPftb1AZ7yw8Nc2cAXhg6Qv2hTEpSCwkdZfN9qNQWzSMcDC 82.45676764 -zcUdpu52c73emRF9M89ffHfuVEF5xGZZi2EwhP2niPXxaXGrxmLJUnA9VNgBHpmrxde7w38HEJpZhzNPWeecNY6RTznsVVN 82.23108167 -zcPWPmmc1HfD9S8P84hpmBGAdJpHMjPFUGZjF238zmEU8GVrmxasBKv6TCGXkZfKufUVK4W4P3RKqKvVxsq3tdXESrbCZPL 80.75955380 -zccQ212F8YbuYVL9wxJi4NRmvTkP6arpSUQBAKKtHuq9D8ViFgMoCNj2y1bVuV9wkcrVUxPay8Xgn5FwE89WtgmcdFTu1EP 79.82204095 -zcCDyBabcDsNfUwTZgDXRAKc6E7zc9qb4fPSeR6jLxfAfaWfaU7hGDyQUCfpgkapHr6fEDUNhuPSzWfxDSphqF8jro2TQC4 78.77411673 -zc9Aj7hrrU7cQuU5FauGx9SbQbU3mDh5FTAYk5L38CE7CS6k56bGUPA9MgR4VBcqZPpkzWq7xwPgn9Ad6uDh94jyy289bqo 78.46218449 -zcAq6PcbdnHbc2GkgtJJnvCdXFRfZrTzjay2zXVxybhjM6LRihAb6q8VCrwn5k91jkAZE8Wyn4oF46ZLFKQc7V1UmiLCdyK 77.95274334 -zcDyn26k5qx23U4E4ku4UCP1LhCCaL8k7WmLtgGhRQHCq68pbypQEBNwYPnWv4a3fqF8J3rNPvcNkwuxfhFHRWsiof6Lkex 76.23897999 -zcVUE2hfasefjsM5j4LjucEpEneoMoQnGUd9eD188cgH7qCAVBZkWDcN7ZU2ysucQrTWeZ2Y7spRk9zexYzBkuVyrG61ejb 74.09409991 -zcUGRemsfbqVjC6LYSbH1YcE1hw3gTtVzwPCtXQK4u4uNv97HrwUVmjuw4F4vhubpg6nLmvo5Xn3GfGEy6WLGbJs8QBjnvd 72.66774381 -zcJvFqa64Rmp71fJKUw3RWCvr2oTEKAFCDxdDJ273QwaMCaWuFCWE2FaPCZUb8GSvNBi35ZAq9Mchr7i3tT9bJcX5KA5GZi 71.87711425 -zcNEbhETLcQTY5prcDk8Gi2anBNbW2mzmiRDLxZAFA1A7FbWyJyw3rqUcCHLxLPyuduF9L1iue4b8NQ1NihBVBsKtFLDdAU 71.68490547 -zcZ5sRFgVrwUY6rT8JKofaYqjecmpecejeNWpWgaj2RL61AsnhfHZg5aLRBA9YuP5aYPui4nsFjSgttuyc8LtxArEa5Jy2w 71.38725207 -zcEcF2oiKJryNLgxvsf1cYy5cnCbZ6WyFFLpTUxCqHKMgDe6MxTWhFNAtM9hC53W5xJ8PnMsnDaYrgcqYkzi9DAEdiDrRA6 71.04846604 -zcJDQ4T5nmT1bsH2VAHBwegfBvjTrGMKn3UdHt4DpwuGirPsJVsNm4da9zAEUuw96RmhKaJggvmqSXY8SyjS1tFWrZMbL7v 70.93728407 -zcbSNUxufH3qv8faSa37Htu4AdDShGAkEDmCohQvhhhAwFkxYWrd9fhFHEyibAXP4LFBKoKg8hLn9nrQ4sc7rfSdR5mdiGM 70.92268957 -zcCKxTL2f1SkEwjEYzucuWaxhBgTtJqnDhrp2kuRUKW1kiKX1EjhASmXU8Yq2q5nbMBGxVxgMCpSPkVZvnTyamH36QMVCu1 70.82524055 -zcSt74t3gGdqfbU4vTrVRFNtLmZeN2Zypepib5Y3SGca3mfg3iYdJ9YEoi2XrzPcV4HEZJyT1jTMeyctsq4qj8yo2qrQeB7 70.57239540 -zcRXuVh2z22TeuWtc6JabwSPmqqtXgZYfad9dYM8E9dkzRF4XExpDAuDJKuaaJAs5wpXYpZisVhkcUNLMNFpSxXm2pZdQZw 70.55573608 -zcaTiQcEonnGGJyqkXpGSUAPExi3T2ViQWJDujt8ftbYHJ2PrYcsjBjFJQfvujV3PbtEpig98zMRjXLjGZKqrcwLnjPjjDL 69.70751719 -zcX65dQmsPW8sXMGUKxoVCjKEWY5r2xk9p98nVcSupeGkKP7kdXd7Y63P65MCQMDu9WyHhnuHfrupi7CdrwHu78CqEubKK4 69.66967025 -zcA4eNHnkuwdwAJtSbKEq3XmcKFJVSzt557EbZpqy7QYJvi4Cuzw5yCQEeDf1czZZK1NgBJub6ubW1aMhmYqQz41KaMvS3R 69.48376998 -zcBvZNbyEYXF1LiKYCpYBYKqFvSa2EKyb74uHcYMah2MgJfNJDYMTaU4wfUqH1xzqdpXQNswPZtduuH1prBu1t1B7C9xrqw 68.81828470 -zcJT1e1fQz7MAhEaPE7thYTqPMiLdrzW2ieyJVbYw2m3YptYDw2gfcg61kDg7rc3jJmNzUqLqkS6hM3X1kqccPQoUvPyE5s 67.56080854 -zcaZLiPSS7V5gUsNsg8ExXoRFRe3otqHZSCM6aWeotHTQ6LwdYzuVGVojoDqWL9yNsKZAJDznkY8vTE48e7C9udC8bQXRuB 67.26911641 -zcKuLiYjZRg32MSQ9kB5iVvgF25jHRX2fSg3ZjfUGE2nZRKMzn2BDG6stVCqJ6mdbU4LKmKTZh6oHyM3DX26Py9FWkbjGL3 66.89961891 -zcHKhQvkmTHFNscAKD7gtnhkW7VCuxQmp2pvtuE1Lbhki48AhCpTQYmiF7PoRU7rJddi4MhcNgpKQ4RqsZpTvq6KGvPL6Mp 66.53680776 -zcd9TPpTV4Ptky2i9fenbz7EYK7A94f1UhwkjHqt2kaPAfLhxcY1atszZQmdaLyrtBzp5cHoWZMno2m3v9ACvdcCihDTtou 66.53139095 -zcctUCXaHxvATfhtEJLRupvpai1AmL5TmAu5FrLdaK6dZetJykbnev1bKVw9NEJhCsuHnoeSbFWvFG7WugMqryp6YQ6ZPMk 65.18661726 -zcZ1EznLz97xW5zwDBMYTLE4qJe3FvVQBVshhEURRVjmVZtHviQdwfg83aLWCyNVA8HuAXbPxEGSfU3gZ9WLFTgxFMsG6P4 65.09204572 -zcXXJHUJpXRLChvwGQxVMRN2YN7917GLaRt7xZ4c1Q8XM9AsPDCr236zwTmXHLzayGbF5oS832ZRix2LZqjDxvV8D43WUJU 64.77333717 -zcHEXMzUKPYXaib9XVQ9XQ8Nh4wisYLUXzxBZZFDqidAVMStoNCpNHKr8fD1oxK6s1HUR74uRyQ432ujgcpWz9DVbkLN33y 63.81508767 -zcDWKdsqfzv1WAeWqYvxHGHix8KcH4VGNCgxLCnjVD2oDxQv2PNLBJjU6AQrvRJDufC4HamvWFjYVpPPRpw7aS52bj2VXhb 63.80990393 -zcYTX4k2LT8WRS8H8tzVS4cL83Gsv5A8tyhBJzWub13L3oUGuig3NMfnE1sELTEMktEKSSSc7qDpQRMAtfqqKzbAKRr3qTx 62.94272372 -zcWDqwFHnq5o8rBsoxaD5uYnCYdRYzRKi22dQvVppkny4zHRCuwA67BsNYCPpyyQDYGRWCjqAuqNb6U36Gbdnd6U8nKChKQ 62.77857319 -zcQMAPQ7rBHN4gmNoTahLzvPjPmvWsi7KZGFVXQGwTF44sybaD8uciRrjwgM3USVLJYETFpufTC7YjWhBn1Syq6Cuc1oZQ3 62.31380405 -zcQC4o1L9PvUQYSXwFmJW82aKesKewW6MrTVqF2AoYf1MUBUvGbthHouCiXk2mSTE9udPgKcpVsJMw7Ar8b3jQyaaiG5as7 62.29093985 -zcMgBRWAp4MridAwWYy1ftNn5cFRYQikybmrgXmd1qssiP8iXskdp2Ny7oDWE5KgGay4KTZxCNqmuCMrGDauPo64i3xM2K8 62.01035555 -zcEGqMmjcUkoDywyqep4m9Br2AChA2D8zscfsiaSTTUM2BMZU6rHbQqix2ftkAXLmfYTNzn6tXRmFpjK68jq2RU1Ywy7bKv 61.54717386 -zcf5t8jFEYPAWYbweBQFHkddDp9c351b1mkCkgLBESRkkwSBLfuTqx3RTGre5frt7PifK3NxYsWENxEdr7HRznJikRBaHhD 61.43081785 -zch56kUWSbRVwSWzEpELsitZJ9bZTnDc7gYev7AnWLHPipzgLPMD8CunfvyERTYcjTCRRpx7GsQnntnb3TyBCVVVHbm8yjU 61.27139274 -zcQk4iaC4JjMBE5xEjh5g25FCuMbic4pbmKmdwPug1gufhu77uGd9uHuaDEaqSN3rZ79E6eSAELHWM8omuY2RVvknLp2h6v 60.81028615 -zcWWxnmtYicHrQetmg4ihYRauebJjyNQE6V8VNJN7SMGHozbwMQx46CuhiDtHcKoYbg2px3o978iuK1YHQeNT1nJFDcetnY 60.72892267 -zcS8A2up78sQ7XNRmt8gGtRDEKBxTjELNaacfDY5qCRQp5vNGfrmPva8DR2wT2C3ABr3U9mcocHd8vKu7y3XtHg5b7WZKGv 60.68202500 -zcESWzy6a9zcseyrAempfH9tu1a4U94NuP9xGH64uayqyupiECAN2FCfVNSgQYiZ35rVKHJPnE4hY8xo3nPKw7hh152dZyg 60.56156134 -zcTj6b9Bzb7TE463HKcoUnqTTyXcoCtgJLSukx6AQpinRFAb2V8fLrxP2sFTXkFErs6W8r3CAxpT1CaGCyF1uFRG2EjSufS 60.01650046 -zcH7c2JnYkDtcYgUYyFRMyy4pmW7P6uVpxNC4zXv3f1zFkM9GX6QnAAtWhik81z6SqYR5m8V69VK9HRFbzetC44KxwggpbS 59.61620416 -zcZm79brY6dhZiAHSfpC5g8Uheg85F5goXAKCUjxcsUncjktpLeEb53NpJnTkCDzPGRgnuqtz41n3sEQFjWwbrRmjZefbuj 58.90587809 -zcEWeKx2sEUHzXHQMUvgxxSy3joAwWYnj6BNjgV18pur1aQCJBZAAstS5mtWM6DGW9gsnS8xSH218cTM8kQBCeM35Ue5nkz 58.00793102 -zcRN6YfGk9rCWAyfp2sfHXPLSvXUQtaiM6bXqK7kpEtaP9CFa7zY7uoSytvVUxnsoPDMUYxAi3AHpz9uFt1xsy7mu4VE4x7 57.82529091 -zccnzKGRYfRNQnnbCfAsduaArj3RUkU3Dt51piP33NkUP8qnvs8YmJbxPBmDmtzda52BSXh2xZNh5Na4XBHEyK145beZECK 57.72627667 -zccdSnCzHp6GAG9Bo6gxqWaKEiuJLsvAgPf8WF6ge7XhnNcFAKN5vz4JUXTh8jhrcqK2RvECGgvWSZcBuYgKRr3Ty4wXaWe 57.37817157 -zcPCyfZfdTzAj2WmfxMhi3Uz8PfqfosfYCrfPvM8fchJiP1eqapR7ivMR8tYGroBs6mmcRdKswHgsbcYHtLQzysWSS2d6tm 56.46517429 -zcUdGpYMMuZ1UPioZCQSaDXmQdkPMLVuoWrWC6XST3aZXa3fNLS74uRskBmuSw5R3QRaUjFY6ifXtzfZxET6HGvKZ69YpAz 56.33801661 -zcRpcvdUA9ev6eh34zGkxsZmPx3AFioxm1GLyMmr7uawcTUc69YHQxcDQ8FnU7nu8vjAXzxyYXL5KKjDkhxawCyubxnougV 56.30003428 -zcHJxq9bfYZymyDz4rLKjJSAx3uJC6LnbQJNY877sav4djGd2sh3kHEF8GTqUr35BsxwSVFueYrJUoNL851CsxpUcuz8eB2 55.09346377 -zcS57zyFKpREvDKEhiqhZniQbeGek35ubaQUaUeiQi3p4p4ZeaAijyMX2yknGCyv7VwF1KoJZ7fmXoxyxNMNGcnnPgQ2jEh 54.58109688 -zcVKvzmoX5oWzcbAA7BC26xKMChjcdQCpD4mYR5Wwn8SLSreHd2fLe5kyaPYouFegsBp5ZviSEkpY9PDLynr7rzw4fwFHqf 54.31165060 -zcE9F6N7PJmbcdsBbpEB5x4kkYkGnsxMp9ZQuX1w6uB971C9UyLYmVP6G42MMTjsxVKN9DCywZ1QdffR5EbbBRVrRB3xkmq 54.07173868 -zcFtgc9umgugFPXCHeQxXp72rXrBbhKupqMLbdW5RWr4w6yx6tujuvhiRtkbsvhZ8pxdEPHwB47X8SzQJYJ21u3etp89MRX 54.01870369 -zcEnQFUp5bCtzVv8ZmQMdTdtek1HhzQgJDdatnRsuHta3Py7eau4WzQBNqrz2ErsHoGWBsjX7TDEJdj75eezK7RgDQvTESo 53.73491644 -zcXWYKLNgWhe2sTMKLA43Hd9ig6Rdqtut9pNuoiM7JREPLSFPtnxFEPTGwmgrFG3xNrKucCGvLdjirm2bUZkY15GpQzY1Bw 53.38069485 -zcRfBbGk9TSUBexnVbsQjQ8WVP7eukjWN7PDyHd12LaDjiv2ysqcr8AYApJ6YLhDWxKSP5PMypWdSW6BPG3ayGbkotPk2Kn 53.33062393 -zcG1uyaFqZvajMY6EsVigVz2udk2gV9oA4RxdjZWWMD4Y6WVF7EFm6Az6B2qEu72p3Atb6G2kdjSRP5KCr7JxvrTUnQB137 53.32858799 -zcCAZbHGcobeJspN7NV4Mo77agZVmPP2UHWgqhm6MkVEuQKQ2YtvKWpvCfjBgyzULf6XKKkuHxPqiHfZ49JNit9pjYvbVmw 53.31986544 -zc9tVPZY25C4j7DXmhgD9BsJYcTE3FA23Yuvunt3dw5DvqTLQi3eHaFzkeP1i72r7PaN6UKwmFx5hxnsk4anNokUB5eBJLG 52.68927437 -zcefMiv79Rj1HbZT7PCettTQ3WG72r98eTW1r1x5zG2mc9MGdf4WPM52kGBzDjtY8emJ18SyKJB3CJEbS6wjwSC8aZDYtFf 52.66666860 -zc9ohUVLWQQGkYTjrmYSbNYogPEX1Bf54TAJ5Byq7K37xa1XTkdC4HP1LJsqREYgfxiRwk1bVPZ3LibTgEZuQ17wZNzWCRJ 52.34452960 -zcMz9k71HwQb1amNWnWHzseom1JZHLiek7BD5qDXuHsDfPzWKofupKtFXmduoj6j6RRcXGnPLH1vTxQGB4S9usn34LuLnwT 52.00357977 -zcLW9uZKAFWYH81NDFjZaBuR1kjXEYFtUEWykZxHimo1UPMRiYzqFbdfEkPep2bQU7Y55emdiDapuNR4vUpj1gDXpsLPP1D 50.99697374 -zcg9RZ3CMM7yTPtXjSwjVdGXKifd2fvH8qphwm2ugnwFEi7EpgBDCB2m1zhcCBhXE8QCWs7kCfApX4LgPhCfg4KDJmqHnAN 50.77052733 -zchiMr1VARJaeK1AjEsLm9Xah4uhKvHXcC2ZiYzdQjqz22Ynhn6Q7WHkEp2b3wqrZiwmN8Bd3z5wMh7BKPXhfWUAprMw9qq 50.24343536 -zcXxXiAkLcd9g31rY3NfHPLQMUdTjuEyf3Rn1Gw3JJwwPGHDdgLMGxA4qYLgrcHUqu51e5P3c7AyP9EK9e4BL9Zcc3T689m 49.75194163 -zcbVZYbo7P8BRUPsCKTWfyE4XLovfzEX8FNdwAke9uMPaXXSzybBCf4QXn7oTS3RdrN2cyJtpn4u4ytvMLc8sotJgp26vvg 49.58100564 -zcMeBYoF3qKdnYXTpqZcMAAz7WhaEwpsYFwzqzjr4dASmyY6eU1Cv3PMdEGAq4NcFnib42WR2tSbSeVBxvXgCKp3Afkdum4 49.34896846 -zcZPUySnDxqoGjcB6pwf6BTGEZ12uXdYqwqcwEsDKjL8GxXvLxyhxJp4VYe5qy4X5zFDkgzARmh8oVy6fTtiSdtfemBrLwM 49.03184626 -zcUPKDge9zppvPAW5p8dQEHKrc6oj8PrP7hei3UXffzssswLPbc8S9yaFTLrCAVC1NWR7Cv2hFDbVQ3DCHNJidvymD1M4M5 48.39433591 -zcd1j124a1URxVWoZQUycwLEsL4S9TrX5MY7zHnbJv9dqLBQW7AcWuwsGtJrjJNdzBQDKUDQTJ1moDFUF5bGPnqrr7Tot7U 48.20196774 -zcTJekwCSd92Ctv8THbCwmxaJpqanPfEtFkaXbMSVVnzmN63vpKojeYrJo9QRrmag5zs7QU79xtsA2odj9bXcEGBbpFV7zz 47.85610243 -zcMMQopvVqk3DBk1gDMNLT3QHNvnGEcaGc29suLdhk4hMALZAAyYhjhs4wbsd84aUQuJkwEvEQE5QnMMXfENnrFwaf33SHn 47.71711728 -zcXaWqLFLPRY4aptRNTGNot3zqsHKsoFTiArbUkebwxdv9cWm9wQGLuvFZATzpqWMfQmVzjZ2ACYVxHajKscSe5geEotUWT 47.68488448 -zcWJ6cT7NPEY3XprQuM4Bh6HdLa6YWRPstSMwwP6xJeLViMEn96z9rZ9QU2CgQdiqR6BTSPwkwQsNnXwr4Gx22NLdCAiAbX 47.60782803 -zcBvfMFkh1Vc3NZ5kZ5sx6BqPNp32niRtC2MEfjyGuTFgYJwzcsa9AVGQFWGNMtx5gNSzRm72px5qqnnCWbhjrTA57t5Emr 46.92974987 -zchgXzAkCWZMtSHMdh3WKQTp6GsRjXuRapNFYU8eCUwjeT4wf6Meht7mMyszRaedngxnPLRZgeYDucuZTxN2CL3B9SL2k9E 46.77440539 -zcVFwWgH37s3yw7F9o1CAhUgb3Sa3LuxUSqoEwtGGSgG162DD1YSkMEYeq27FLaHkaj3FEaoLfKMA5GqdE2QUspjbPbB42d 45.86342181 -zccmTZLt1H6JReGuXXcf6EvmYjpp3fpDpjgr8MZ5t4oTBHXZfFopti7GB7bUAg4QbKBDYSBqxXhCb9DgXw43fqLqaxq72MR 45.32556848 -zcJ9JEFMTrqnyRPF3NJKqNDESyvqDV2BPyh1sLZxy73PkSR3aHhSHzNxf7m6kv2xqC2ekRCo2VScAJMqby9aAhGnPUyadWG 45.24958526 -zcBvetc2AgY3tvvFcXZogjpUqZ5mV3Xhn4iHuzyHN9FHgx67TdzzpV2EmL3i4QdvvS2bB7Q6mhKWRj7BVN5sd1xP9j5mbBB 44.00892100 -zcZbBcRTpNm5xDYsvfmx4C815BzrbtkwNWnAPB5vrPkHaz43Wk84p7zF8nyQqntZQxGzJp7gRHLfqtzvzND8BYwxpeT6XdV 43.90713255 -zcBscW3fLKRYULZRzCrBLvMkgb3EBgRCXkLtDptU1ZwzXfzfUeMYaYpDUBHS1APbeKczRP9tJ1v8rfKKozd7bmpyzzcc3R7 43.75357895 -zc8GqgEam5jPApvgwVmrCKRzETDcftHoguyLJ49WjZGqWtTNLkCutgTTnxig7QfVy2kvjWmp2jxetfReQCUwjGXSwMeFyzL 43.38443044 -zcEsGCpqQyHSMZRF3tWMAiptg3nJLwg5UGx7hE2jtZhbgQVvuXswxhnGTyMzccEBLKCz82SbW1CEaCKpY4h7hR2NjhLm898 43.36320212 -zcSQZKsTUS2sXMRtTc6xGLZdv1559iwPaYbZeMGSsh7xhWNC48qgCqR5YrpxnduJ7SQuW78nmcjCu2mRa2kBunY9Hgrd25H 42.23336033 -zcK8pY8xjvohAAcVeVJuN9PEccVnhr62dSzn2W84ju6M28ynCXNf1N3M8QaoPjWJzYjSDtLaznSBRZSgPJpUPLj5j9cdgWP 41.99022973 -zce4nBkBsbtjYc6Zaxz1jfS6EWb3YHwDkUF7AYSn7fvsmjNxR1UPrvnrEKZ6Yj9JHj9M3JjiB9vZfd7Dt41r83oGhgfJrAy 41.48841839 -zcXBFek35G3mqqDMgc8fRfDrZzDN5pFbBG33KC5yt8FeVkYAHkJqwLwCcdyNusWnqg7xDRs4aDxCbP6kAdPU4mp71tLXav8 41.26077367 -zcDKZuffTo83xfK9iEjoq8mMXDTiKcJkpitdBgmpKpPJRnmEWstYNd5hRFzxDCwWSc7k3DCWiMrK5wTUKPTnvqnUThTeuEa 41.10517119 -zcUztysCcJtVMzcfvJmwktQhq8fhZ4g63v6E6omopPgzaCEYyLqPFWvSePzoqs9dw17Jq8ir8eyhhSATAvzWAGLGcoPHZQq 40.84254774 -zcDjfNVZ1AW3JQHpE6kmYb1iEM1fAnCpzRGh48bQf5qLuRC1YXpJgkCMUEtJfYGZra7rhAYZWDPTavA2ZnXfJMM599vaNp2 40.28086614 -zcUawmC1fLesGEz7Xi8Ktz3h5rorMfRH89uJszYGT13tFfyQ3YzDRQt498od574tHchMFvUD17dJBiLXm34bgxbrqrcut4K 40.10110312 -zcQA8GnVp6YLuD2d4Kwm1GeBspyqMZHb1h529ZLnvTWwqnopFWuKRMvB5BQt91g9G6M85aCfrpXXHb7zFjjRwKBe1ZKLkSN 39.95044160 -zcWViMP8iN5YHXK9Tb85pxbhvXLAzd73XqQvbmSK2n7v3sp1USTPdGETHGAAn3z3isQKLeatpPGW9daN2QQnAG7fY7s94Ec 39.27976275 -zchXsW2AaQSncBDPP8KrU7uSPSZR35B27z3ZbHQHFMnWgBkVRSbmJnw9LR1NQXAYuXFvokLj3cqP81aykvqGKa9dTatePpZ 38.54989840 -zc9VUVikjyNVLcuwJnbzFCTJ1nNT6arQwMtGmv3HbccbVVdwb8V8sobqCn5G98Gu2Ftsi2fLvHmZy7jzxE7Kky1Qouy5igt 38.53056452 -zc9QH5rwLc8GNYzBuu5bPHxRx8kSzofHReEoQAnqmzH7AK5TaUcgDzAfLm6Ubbh9kN9M8LzcErX2RpLjUSBsZuokdFPWyMH 38.50569323 -zcXkZQ5dEy5V4p6Fi93QLeHvdXTzt5QcZPADLvVKvgLgvRajeqkztKYgWwAukdfAdHYdx4aySf78KnSYvie131G5gMVy84K 37.61659384 -zcWqfQYP9QSaC2xsThGJuAWdzEEqr1J7h9uvSCjZc6xWd1e4fmguXWaQ7FXytHg3Sg3qXN84CivN2Cuf4hH1nhREDKkzAKJ 37.39006746 -zcGwdbZmhiQpvfkXVCUUU9FJpyTgMud7cakcHmmqMzYXxJjqZkgoPPecPqXhFPw3RgCdtDSNc85dVgkM7iDS1nz8JXdCbSc 37.03019059 -zc8d6qXabf2tGB5hHEpjfQ1QWNU6uBDsm1qvAB1PvpwbL1A6itahq5eLq982D42HMkTM8KR6AGoVUt8mp7NYZjXZseMWwR9 36.49371105 -zcc7iD6RFyLoQFNJZE9Hm6mw46MQ7MsRQ1oU2SKKGrHFuHDxhNaxNBJ6UAWME9vhhaxsSgPt3xxUAFoxBUF14QgRa6VPjtq 36.46671220 -zc9m7cEDqxo2XXJgJwWS3qKHLkby4it6woccYjNkKm9ctcBWdy2j9rW9mC99cZpTNF2WsFuGaVjpUQe8Ws84CyW9UnA8NkT 36.23672451 -zcLbqZ4SW7G8citFFjxvNmoae1jpqCKJh1fSGnoufrmEzPv1z5UjuqNPf3KA4NBxXiAyfwbHW8iSv7nyqxz735wvNYU8MaE 35.93340497 -zcJmgB2KZBsKgxQgn1FMzpjR7GnWKKbZHLKP6Y6DPcnVStiN2YvB4iTr34UQvqXWkbbt63TvkJJtgZMoRMStobsJgELufmx 35.92259122 -zc9wnBjHqtSo29ti91ki2twrVPqvFheuufvbVwS4PEoG4K9k2jXQjHzCVuwuriAoah923viEf7xZ5dK1s3ryq7rHssB2Pnn 35.84034738 -zcXvTVFRjYDWTyob2r43PT38NEy74AG1xcszTB46zxtzzxM7eRXrWN4crUggaA39YaWyN6bdjGWTw6nCS2hXSKCHUhdLvUa 35.79303990 -zcWaUki73dv8437hDWcDVBRJwBCeMjiZKUPAJ3N22QWfhEQpocDMAx6NQ9eALaHcy6LccG2uW5gHcn8af61W7Nd1hxargXg 35.32843778 -zcciUfFVkQ2L81kFu45BdTPatro3LgZhLocwQXRp3QPKgmGEFu1V3oGXJfNMzzPpZ6BRhRc3q16cjDZ2QPmVeWT31U8jJzu 35.19272718 -zcPNPCLhcnoJoj9ZZkmggHS9KKvTbJbhH2vdcRy45X7UdGReHom7TYoChtjQGZqfCQKzQzxEeZcsH6mr6kmnw8eiqHVTisR 34.90739244 -zc8NBLMSZw9PbPnPBYscQn6KJSJfAebhRxzHecPxiZkdB9vRfKa7t9LrkfDnRYA4naMGExoCqrtWT6SHG4vXRLU8qrJp29g 34.74712693 -zc8MRoJ1pNTSkk9Ej4PXet3YY7czchgWRjW86mbneMZEY6CKdEwfoMc9FmiEfFwZMkRjqZ3gU5iUY1gs5aqveo1RbnEmkAc 34.60557084 -zcaYdxgPiXAVCj2Wrz49H9L1JUirt4KeqSiwMJvhnTg67Jss3na2zQbu47eGTKF1MtVddG53uoUUr9TF3vm12y6ihBPh778 34.28609554 -zcYquvBQNfWh973L4vvfv5JLSdNMz6sk4C1FtiHGMdmKYPtL94DVS4jENyCSNAiWwnkhR8V3RRotjhjZW64gd8yoaQP9ewb 34.21002477 -zc9kN21EBgmAJxUH3kJxKDSzgp6pmHUx7phRNPXazLQHKDkahYg374Z4d7P5AGytUTbpWBc8GL1AmejJ48qgYe82ZGti5qs 33.95584987 -zcbTwv1MXHeDxDVgqvxubGpREpDoi1mFk8YoJK2hwhy5dWvsGXEXKnfSYwoCD1jNW2pcaxPS8sx5FUcnuycpAVTMz4CPKcJ 33.92298942 -zccfsaxzRvJjm5tsXcF1uvNfoNXQdk1h1KRKQ1PqQsHsWAmWivwWgyTEPFxfecPdFXCyKkM2yrwUbppM7tFESvtnEnEjNdJ 33.88962456 -zcFXERcowBMq6o5wLWECAFv8WWWZvfaxyF2vcBNLmdjFQP47n2YaiAmduinjRx14eqxANNBHtVegmznzmP9brY6up3WnJGc 33.78472170 -zcBEc9zbTpsrvVbDdxpe658Et7zP69n5riScXz2yfL4Cp31rac7qnZftkZAog431jGs3ruKdRftjaJPzynJSEmFHkJVbUru 33.64997343 -zcLzdyBWJdzzBQMnTgwmtabm6UrEeNnpp8w7UBqxDo4ThQSdmsNfEs6TE3uCRDTF1uChgMjyTV8mToX3tTiaMDNYtUFW3DE 33.54867245 -zcFMKueUELM6JFMA2nNWeNt7ihoZ26MYc8c93odgXEQNCn5pumjXt9pLHjGErGwMB9Y3WMSXmx4ydW8zMhLcGPHsPUPrbTd 33.52173549 -zcPTck2GFkW2A17NUDgRQzFoc2SHVRvT9gyNJ1mtb5JXAXyoU5LnkdCJw2W9ynury2CNM66tUT1cTQio19JRAe1hJT7WS6L 33.17252391 -zcBWxPSksii7snNDjnSmUvnGFiv4JvbFNFMBgUvhn4fr6v8jiyj77L4MzD5VuSa4fCZpRXMMjD96FiBB6SUsyMUCFBHoTzE 33.07755450 -zcVwArad7vhd1Vix5zQ3rMGAeztqeQBrqmLc4AuuXWwkFcWtUxLTSAx5NdcZgbgQWNZiCv8VbpGERFGorYMVTN5WvDrct4D 33.00758489 -zcEv6Fcn2xKH7iYcMgnafnnAe2oKVwNFQbhbfKrTGo375gTTspCR4TZwV2iqA4zyYUNRxqpGcqJ8Ftc35jSnDvEAa7nq4V4 32.83871131 -zcQzpZRwhfjtwZTQeMnu1RxFUh5KxTUau39vrFDh5odiRDzSzYdmWwhDhg9cwySkqTBxWPSZHQuoD7io9W4j49wQyTE3w6B 32.46292744 -zcRjVD2FfHis2EG667f3FREUe8841uvQXX5btgzBDgo8LrLCJXdiZeZYTwof6gvwxdFQ4oMn4D4JBMUqWWc7NyyHuDrvLKG 32.05915645 -zcENBixUbwcB5xUmbTzJNYbNEBUs8bxNHHTLigpg7KCp24BHBbtwbx9c1A3D4BpJeRChx3pLZd4TeAfYzwA5iBn1EWBRBaJ 31.83242553 -zc8iErtpmPtUnXAchTkpbVVD1cCiVLh4YmU33zFeVyrdv5NDNQAh3WPr1q2MVTxGDJhABjwGiPzw35Terxutr9UQsbQBfcF 31.77585686 -zca5ULHi1JNzEfPNaeJs2YWQxk2XfGpW1VTMRsk8TKVcigYR5r3EMPiUbbMiDLSkmbxVGaW6iLXrzkp2FXXdpX6pcqBjTJb 31.59933037 -zcgyanE64cz8ssj42HZGPGPvJ9yUEZSxXGgdD7mcv7wTUdoWsRbTjdPjgthf8E2rSh7RgRHmbbQ7N1VUH1fEoU7a1crLv2X 31.45880288 -zcQUxara1AfX2ib9Qs4r7FLvjxKgqW4SQWVaZWvZTKs4ZF6faPZvjY7Ebv6v2G4Umreuyny8MobUC47k5pHPVpMmSq7SNxP 31.23137132 -zc8Xhm65p8M2Frp9DJfAP6ixcZ9vs2pVmnU8gHxDR534J1FrnJH51iKBZxqxq6hrhfZ4MmNXRFyaCvbTUszAgEoaHrEqXKR 31.22156194 -zcTgaTVQfFt3xx4qkKPZ8rABK3h78YhBUe5g1BpGDMsWGiw6rUhDY72xv4R8g8S2GN9RAuyvwwMrxrrEUw48f7RuR6LvcYt 31.12876593 -zcUU8CQ5A3bCcKDR2tWberi8RBJGhmnMY7ECN5eer66hSY7Y8hZSQazaHWcyx1tyARCNaQqCXkwtAsQYkYv1y5EFP6PUGrY 31.07173441 -zcCJsrw2CdLqhDYKBM48r4FM587Xw6i7xBn4WxKqSsFwBDcFguNWVaF5LwUZsmbtL5zjF6TGY4dECRKQGKFsEqWaunYS5pW 31.04605358 -zc8Hc5Ynefs6Jxen3mQZjHzgpSPkGYSenNNeqZAf9QcdqoswiGzK6TZVghJbXWwYNs7SSqvX74w2VcdmKK3AA8Mj51QEKCN 30.84159984 -zcJ2yhKaZMSnb88XBEE12XpzQSiBmwhLw2WoSoNHDKL8QDcizegfXFdgX4oJ9fvzz6sRjVPpXk1JojwCe7RznHoXGHwtPbS 30.32461192 -zcW23x53sgD9TrwJ7mKYQPRMZGX29LQzhkFgMUhsdvMmzgpKbNJFsQa7nhyiodW9EdcRZmewqFYAQsjSKPxd8YM5VWqzsKX 30.21374641 -zcNcaSkCBcSCvmJXJLZUyTWc6GCZDA7gtBrrUJL3CJchtQ4PZEfRrTRdTRt9ZUATfKEN8pVy3o8Q67Nd1UM6rNj1ifuvezP 30.01095838 -zcZkTkCE6BDN3mRHsRTNnALGFsVYSET8KJJhfpFL2AfpXwLG8E45U83V4MsJeNt7V9ziLt2dAzbpQuf7WVH7LDG2iCJndms 29.88118621 -zcLCxfMFrdbHRwHKAKyAkTCE1T7UEhtwEcCFB1LYynU6T3Si8iXG3FsL6j4SZ3JGf4SLhk5FzT8iYffZWJURTXoFF42nkiA 29.51228312 -zcMZPukV7JnWC9hhavTHig3khGwa3YA5dHzB29CfjMVx6njBiz5dj9uvAD1iNmsWL2VS32FpwZjc5fo3hQNHbESMr6YJQwY 29.29536906 -zcXhSDGrH7FrbSjHLLsd4Do2R5wh82R9aUJZB1Md2Ntpya7XTvcq4bpH3SBvGkRs7vt2jR3ckvH6vAAPi4sJDZw5mue9AGe 29.24626876 -zcgPyWjFJEgXbiD8CKDUejHYE9VtuGUWm5VCMmrjLUHUztY4DL9e5nGy91pKtsmVQ9eZKaXgb12v5wGKpfMVazfHKxUa6ej 29.09501867 -zcPnnp8HwQWg9Mx6ARCthpSpwYruJ9Uarx3yswCoMY2bMJ7iMsGE2suwzfqodRhGbtNJfnYW6xwWhpy8V4Bu2v7XERjcp7W 29.08934204 -zcBTvDRhBXky9HJ71rVDTx7nCDdYL2PPLyYKkrzPExKkCkMPioQsLemtAwGworVo1JfMS1KGBgWjaQ4S3mhz94jC1ueWBjw 28.76784824 -zcCkNB4TmZggRncCZeGWQMsjYaurrGFp9Z1MDeNJMft835B5agDe8L9rSKM9xvPaN2r2CWHesyN8daUbGs6xAzypH2eKM6B 28.67681458 -zca66kvbEds6wqCj9a1nAanjfBu5RBzXnxX7KLju2GNnWxbFWUJob29DiDNexTxhDGM2ZF71PX8rR3VkfFN5Ev11vtcxDni 28.67545241 -zcZPBkKhFV2QbaN8ZS3bvxTwfbk1BNG7ZCYh2rGQLev2LXV2QQsn1jSbrzWELu5cRtK1BnCAMeDb7MJfJ9tjDvqQTcj95zn 28.60502806 -zcRi5ZanfCp9WFPrnC6Q9obAQxX6k6PtdhZkKDTgeBfnggWSwin6Z5ZVW843hSgQnsH1NRthVZ1WXWDn1HkHCzUmkTkbcH5 28.59798844 -zcHVB1vKXCHJNQsaiE32KFbb5z3Zjr1pKsgoJ8wGZq23aZfYJU4wATfHUBsrgsRjeS9dHiRJBx6pejesgX22sC4y7Nsq5oV 28.41538062 -zcXrJAR3QwJT4r9eVSKGnBYkYse5FEZ8NRXqKfZQynERnPYTXnLNGdtTzjp47U3EfxNAbruReNxNYZKQxDJQUjLAC49i234 28.29026155 -zcVnK8gyXVYFWJPw4R3BenG6g44KWrRV2Jun95peWbmjfZvT5ssYp1mW1zfEBCcFHWtYjHp8HU1b7emAweVBEUTxzp8ht3t 27.95651240 -zcYnfKnyQ854q4fqh3DeCyAbZYruFrWwK99uDwcyzVNcoBbYPiFbpr4BYpwqKA7ogSXeviadNioGiYf5t6oiNeQoAjVtEPh 27.78490986 -zcfnCsqZCNQzv6pYjkAewJSZVSax98KPLtMBdiE5Thsx76RDVcSahP1SdJyJXHAdkzFsqxr4CskARMh8p1EqhyU7f4UNB4b 26.92253158 -zch2yNzJNusSG2QRDx6Yvm92Z8vm6ap3LthgSXcPUqidqcYsAhQ1ZbiKGFdLi6oBUvoWFf5pcwABVRrtFd2cB6DM32rBX1j 26.79019980 -zcApDSLErYAyCceGsn374vpXwfxzFTMBgVNtrQGSW49ih66vjZoho4Es8VWB7LYU9LwEQFvjqQA8oEESbj4sbQ7YVK8Wp2N 26.62116459 -zcESxyocmFVHZeHXaaq4PQMbVKdqSwdJhZdunYi6z7rYDLF2HEPuTLpwg8Xma1Rjnx1T7hZBNWAB8DVEbp1fQ1x8CSWMCX9 26.56870784 -zcgnvry4rDaP6E5i5LMkiNZfpqEumiiZfQKHVEjnPhHGNFpSaQCwnR6ef1VJba6w4nCXpNfPDd35Ge1GFumF6aynhNdA2dw 26.47651135 -zc9kNqidKGcv6Fk2PoSN4fMkSn1nZhBE4cofPDkwApNLCt4cCQgjcnENDtZ7oEdnHPvnX9wVzNoGbQWkqHqptwBra6T5BsS 26.37598171 -zcEK3pfZsuK3DpEYBfLgrENzunwWvhzVZydsDx3CJvgec7aGbo28emriHxRZH3H87UqzUMc8bTT73VzRqEkuUvwhxsMu9nC 25.95156360 -zcT74LAX6gzebpKHFejsawpr4XPgnNPwNfkfHh746oznifiJNNJVQFowdkES8vvwPYeMYggyXeetUzx89ZJPmokw1tN5z9P 25.89310270 -zcTyonmyMz21fRNk85hZvoYqy9YZAxPBYtg2T4HcpuRMiFZfW8paBHKnXQe21MRYf5wpSEVBZxWx1fdsKAzZdzPYW1YnEf4 25.86876653 -zcM1SuvrMJBJ9MLnFiMujbqhmNgB3D2onYtooPWVcCEUdDyKiCZeo2qUefDPVtStkuf4oP7YLEDWHDsHiXPpXQEs5sqeRCC 25.75518242 -zcBrY7mrVjSZP2fYnESfce9vgjfiWDUE1Vaxs5izG8ZjzNMWnmkg41euKoJpcjw7NskXZPeEZeietAU3Am6DSmrybioFT1Y 25.70216756 -zccfUbWMs2xSLNpJF5xoN5PXJtbLFLY1Erbkvyh1dA3xgnxfakip7SmWWCNJt21EkmVEm9oVewhi4VLwPmD8nhCZm7m1p2g 25.68992243 -zcXymrefowcMgKRUj95Ra6cCgqcQLNhsniJAo4TgS1VSh12keygNmZtTL1tPba8sCsFvRyNpPQzB73wjSaHGZqWLpBdx3Cp 25.55422528 -zcGUPVsMfrnfvSN1W67di4WjWsdCBirKNqZ7fxZtxhZ22tpVjSwhccg8EbyBywNURLV5X43vkZNHU3yRjNGbvzXYNn633pZ 25.42015436 -zcdvQEnUG6DNNMguXXbYcyrnX3MbJuTPNmRhP5sztVzUNCoaMjJzbJBUWmQVCMLbYt5GsPdRtSsq2pLn54m7Z8QvWW6Hh5i 25.28992683 -zcJmtQYxbqA5Sypboq7XACkpKP5atuM85oXeMkzKwZyA7JuHS8s5nQRsNcjTPXiQBrdozzx4KbgkEW2tutG1GDUNjwXyJ9k 25.17031602 -zcPBpCLLhUVmWVRPoD9isSgs7UVsyDVg1nFAfLsuokN8e53bCUfv3MBBYF5W1dp63zhMCuTssahEqAbcTLT24ewBCZXXnhu 24.98822948 -zcTNX4CySjFC9qNKgT9WuBTeUhnjafJM2JmbAVqimhDakrr1UiWpRv5ZJ5kNPAv6iAuDbeZXW8n2RpFEZjbqbL1XkGe6QpH 24.90711810 -zcPa3GMgFLtMQgk9V7fi3rCKtsB7RdAUtbQoqYXuE7Eu18D8ZhbX5tkoNQ2NyQcfXzNWExFvRBHqdtVQqQAorK8r5QFyt1W 24.85302080 -zcSkqmjkqTV8EySdhE7azWU867cAte1eZaBjTRMPbKz2bkx6kr4QxCbAn28jaHiGCi12bg3r8oDcm2H4yfyzzX1uKMycaTY 24.73705043 -zcSiGCPjzFHz5yPHTbcvpRBVQxEzWBTuPk22c7W1cJEbxsUjocQ8dUxTXpqUvKSVinpBayzpqcBWmv4mrKq3oj4zr7hE2W4 24.62403626 -zcNdT5FfkuufajEKKuEJVf75Txck6B7mZNmbRJKZNaait5FuUaJNmKT7HNM46QjcQDYhWCmDZG2fmjF3muY7AyVuG1dHF3h 24.43334374 -zcPGJnXgSFkngdFXmFk21pgtctwnGtLEh1V1dydJUEiLKH8Bue3wPrWwaGfeEDT42gd1QJ9JygCVTrJJgds2tLdHWzBrgFJ 24.31298354 -zcXqAE7RmBSM9ZbUJtkdRtBXRzc2HntEQKK1UcT4K2JkKSMfuYuJaz1dU84bnJ6dNU5fgpM83DoCkfswTeeaJik6YDHhjoo 24.30573989 -zcPvpGT1DoNu2K9wDsJVyDv6ckM7u22MoQP4HdF9wKemU3HeShkWafvBdqssftF6LPqzL4LTAg6CWa97cYeKtADKPn5j2jN 23.94630429 -zc8JmTjYgVZYyEV6ra239PrZwqhMR4Uqw1GxbUCVDSGDjgUDKLCTajwpKYBfZRCye5dR97sWYD36hqRq6Bzi9XU86dWcap3 23.90546202 -zcFrhTKjBz8pARTpdZk8jmg1mszP2d7jhFg6fFo7gWQQyzPX7oe9uvejiD1asFHdFpoydfdyp4WAoVuhHC4xtPtaD3XvB7S 23.88988849 -zcFsw2fHgFCjm3FcGPPDs5ctAgVkzKid76CzfauzGxv7AHoQuUFy4NA7tdSFuvyL3SQ5divna16bykwtBPYvfnhTP6ehipg 23.52310407 -zcV7mWD6n4KKFpVCUHPAkPvQHzEZSjTTeYbbuSVwpaUao7nCNyCDQ5vH7fksrZcq8Hsaduor7wLoD9eLAxq6B2wiqTnEZ9v 23.32450200 -zcRZarRNigTFZPu1jnJd5nfPCyXc9iroZzLXQ52cDHdASRoA2cD5N2oA9X8F37UMZ8KEvGeL2XMf1F1euhhuBTk9ZL4hQ5g 23.19389785 -zcZvoxWqfc6GdmeKsZZf2B95MnfpYQnSE9J4FGXLXcFeMQswJXpFLV4j3BKib5GXUuZuvBiTdrP38pJJtReujpETXgzTLRT 23.02435017 -zcZcu6aPvVijn84s45Gp38rBWvi6eecoNyJjQt1tVLC3ENJgSJ1US5WzViywubMX4hEzFunC4wYr2TeWZMF3Gz796FY1Xs3 23.00473923 -zcN741LBmS23ZAdHTsHqAj7KYtSM3wTr7tdxRtJJTwa8vY9ZSs7UVJa1zTy174WiTw7QTnwfTnhWPujTAdNwRukBtKFu2YJ 22.98494220 -zcPg4zkdgHMMQfEJus9dSdTTA4aHU27M6RYS8X8ABgzp2Q7vgsqLn76yQkWULmHnaYsXX1usA1tcPFa5vZHmgS3CQLhSGqd 22.48162729 -zcVJkvZriEqFRLW8HcSkfoxiWRkMxnQJiYWHKUPzYaEY138K8zDWJFLjoheutYyS2Lt7PpscPHdNUsBubeEaLcEvXgeffVZ 22.33964550 -zcVVN1ZPQKHNtvNaJAVzWpJRBztgHaesNpJsNjEM1YR3D4iP1zYNkgvw3Wk2UJ9WB6ELDEkU8Sd4ay9ciyAQrvwTWjRUp59 22.24960696 -zcUFVgWi1DQJkSUvGPs9N6aXrmTovKPykjP6CHapeEn3pktBRWL86grubtf6SucUAQgDkSGzW5ma8UXNq1sYHaeyvEyxyRt 22.07750687 -zche6gww2pnc7PuNZbkfhmg4tcU9vyu9ifh3EC9ysp4e3o8QcShrZLWrNjEDUDDkkiEa94gW37X2rPBNkVr7qjRZdrdySrk 21.84108190 -zcbbfWap5XXtdCGebgSCn8RDxUZcQVCTFaFcSr4oxdWfd4sM8Hk45J5fMCe5E2ShZNKU3oWShJbkwvRaRFEG9N6LEFQbZRG 21.83469321 -zcDQcyStVzXqaz99kJRFxfUqqzvZaBzdLue9fsnvNCfL8um1na7quNmqA9kzthk42EqmhB75KD9qb5d7nZAL495araK3VK4 21.77869665 -zcMiiD6fYHk4vRGdTZFy5haFWfHyAtfuNrzAi5ViLZATQANmryDwEgC94GtFMcR7Xm9VoTWpe92ZjeMdP3N7f7Hybog2EbR 21.68995522 -zcMAJuMdQNtRFCMV7T2qoDLWLgCk3EW7ivQiScX5ZQDBYDzXyMQPsNCoPRxNVxXimZkW2espKhzq184xTEWCqJrA28Lj8qN 21.43562927 -zc9CDfmxtqdJWgKKQs3kjvLGALcr6bLtDh39S8BP8oSFyFuBEoNQ6YpBpZmJQz1TSJLFXVZ1CKQZy4FMfExsoumrfRWmRuh 21.07468459 -zcc2LxGcMnBRZ44Yu6c9pzm5h2P9XWsKnSSooMYMf3QZ1VCF2mnLPRQYBpQeVb8fMfK4YAcchMq46rRkh5rqcbjidyFt7K1 21.02514104 -zcF8UGPwp7dHHbTTeEWD7dgaU1qEuC6ezBaizzZ81TBabaX8EX11bzHm8GvGXkYxuHkMQtY6N6QG8ccudLzBLFr89zHoyDY 20.88961829 -zcX42mQbFjvycuLjQooeNqTKh2eCdcEt6gCLAAN4gqhWM7EYq8gNGG7aoypTFLHacHmBdXmSvXKNtZKUNHoPFLMiK22QjJ1 20.57055169 -zcQiov65jjuZEuBxYR4KFFDpcFgNafhz4dBqZ9ynJtQmK9xTuHcthhopU2zCFWVjYEH2yDEuP6f561gzn78T58h6cHNAmuq 20.23191463 -zcDuiQ95jMqVuonXBPpt5AE6Ni7Rkg1pYfFpzQGaQATmEyibniVH4i9v8sfHonks7yhtabY4ejo7gWZ24m7aAuMVk3DjumZ 20.14678889 -zcD2FGHrWT4FvcEWMaZ5zxV141DHCnrEYg1q8frDQF5y7RDSgCs5v143nCXfBn7cKtYaN4jrfTUv9wZm34jfr1d8VgpTGXV 19.82685525 -zcBbEc3ECuitNZPEQ5BfuqMvg1qRtiC7HxNdVBZjkcvFrkpoYwP14BngJLQCtrJS4ezoEkwcxhKYuMRjW2WFff81fUJgekt 19.72563482 -zcWX6uiUbp7SP5oFxJ67ugoJkoKvzdzfPMCSYsoADw3zLyi3hfDSjZr2xAXtxBupQ61cfe3GcvxbHkUHAHcByBz9uwgwHfp 19.66252996 -zcNQ6taRHuYzB1QvQxH2B3NtftBZm988t9u5Jr2sQDuWLjUkNP3LonEDxtdRH16L1cRqKC8MatxUqe5QPGzJgdPrCQKPxbb 18.87356815 -zc8YToT8RusApNGAwtYm88fMGttoz629UNGjE4aPKTboegSYxwbYFnPtDKrsDxQMVxiAq8h1aqQou4wmfrgf6pcaF2GPW1D 18.75564195 -zcWnWusLbDhULcGx9fnBVfLTkZgzSKNaKpG5mtUHBdb8JCCPrKTjKhaLuhQPGfykqNFdwx3BEd64fQzDDzUWZxySYrndJhN 18.44706590 -zcgrKwxcLPtq4GFyXf4PZw4VG5D3vJKXZAeQPYZVBi2UbomRiy2oBeCp4mp1frt96Y2DT8bq9exrpcwthLdjtu9iKyioPa5 18.33701199 -zcWEkuFbyZq4oErGKMmoxgiEyiVsiE9qV7omqGngZA1AGdZAJ82HzwCEp1gteKSDq6SeqwAqRUPhGKbCp2p4bzCi9QvQ8nw 18.27825874 -zcgPXmLNMeiHzNPtcoPkTzKxctJy1e7ppvS1pi5AGEow9s9KbqkBxWh9qzbA2B71gN3zfoPVuDLgx5fwWNF1UJ8nox6vQS7 18.26277664 -zc9Kg7ezv78UEwRo7mjvBTmGrCM9pFHMiAr6xHiLpP8nxgw2T9RPuQd4K2CYf2asAUy39iAy9978CxcXKyTLJRD31p5uCfC 18.21112063 -zcce3Rn3zJHNcscSZJ51c49DnM1tuZ92sK1mt5QVBkaT5zoiXXpQFRN36Yzow6hcNX9DbWxM6HxrR32teUdLJ7Sj3ryhJVp 18.16676438 -zcdDHTkqqYjbSq1YsWDfyKem7DAbc2M2jb25UYEAEFG4pp9G98yhCxErT1K8jQFNtKJ7raoVByg4mWgYkc482f7M3wSQKoB 17.78603402 -zcFfUcjPQxhe4qHwEaSa4Dqz8FwJRrFZtgJK9MHHTWiMfT4FwtC6dSBUm6cTABBxXn8zx4tVR6fH74eHVsATB1r6Uw9WkX8 17.77314899 -zcDG4CKrNQ3iTp56qsSPQS2fBaGq3XrgLKT69Unu5LpumJQVz4ANWjQCVb81iTAYbSd1QhLYXqZBvBLq5Qc5VdfGXSePGRe 17.76597859 -zcMyKf99CwbpEzyvxvAhDQ9tHKUqDeNMv4hcyCCfQ7WhjwL1gbUpXEoSesUduDJfkHvajbp1yj7yQsbx5US22fHkPMwFYP6 17.44723402 -zcdhRpc4S1aqusxD8QgRwhF3sRFd1dqUKmkEyUC87rKVBAPysRhhxqmU1VsdRygdhfgDQu5Cz7jaT55Ho4QsKKQWDKrCkcZ 17.39183194 -zc8NN4Zedsnw5qTTsXE2Cqdjvz4ZVSbzdQaeBox9UiBHAgaH4WAfgzi1gAR9mzs3kR7W469kKhhJ4ceoisZ2chPatCFJjbT 17.13894275 -zcAyUJ3SxEKJjviQz5a13Wo6jpU6ZZ4httHmgf4N1bC2DJuUuYXDyCTxGR1rmkBy1dbacyYhxpe6KqDMLViVaQDqNHLNNFx 17.04606789 -zcMiVMrja79ezZKiFnQoPfCCasmGERcGLbofah2DjYYfiajNFpRyviPW1QwjeJ8fbbxAaAYg6HWoPDxNVfqCWaoQ1rNf3zP 16.97160167 -zchesfAxM6LxKRseFqr1tkBFMd5m8zR3u8toYGy33HQRknv7nDZaKRnpSvcD41E3p6y3ofZkV5psJAQ9J1sD14Rme2yAuMU 16.95480328 -zcFWoFeYLAncEthCakSmMLvZ16QgCRKx4AbA1qN1CmVqsSKeGgdv2C6CeSpqHKZD9S4aXfdQs2UAHwUC9euqTTWWJqHdVXx 16.84674291 -zcPhKn99huCuArHsUFThMQdPX1seFTiQA41ULW5Uyx46uMG3ZzM6UPVChCVdHgSCZ661k9g6bcmZXJuABiDVduYjS18Gzr3 16.84246164 -zcVwCto37wYQr566oCfqACiB9vsj7gt7xDJbxv8g2M4foeSgVFYDJkNu4tEp66axsgnAehqpfeiAWNGbHzwLz114y4kwqbq 16.83844645 -zcA31qH5Jsi4fh7PUbLQjR8evkuJhhBfND9veCtGwuzAD18rESC5wNahhVYxg2zshe8Vv4CGsjsMnvXpPVEtgwq8VqEh7MM 16.65385522 -zcPRnZ4Nm9vn1hs5RDQu1ixdpsT25Aiw7j7fdTyX76WLnjPX4qcaTdQXtQetFZjW58Dfx5LsaySEELkU7HWVVLdLyvTemWB 16.54664244 -zcCFVqK4htYVpXwUmTLYy6WRwFyDGXTsDrAsAkEbvF34FxB6Fi13QwXBjKYXSbVUopQ1rTQNDGpAspjjQkqTBRxukGAgPKf 16.47690769 -zcHFqucwS7eFWNBzPBMUfTYCP4GgJjpXu4NEJKhgVwrqsqHt1ewRGep1PQwpM9Pm17FjRPszbY64gHdyEkAiJznd4XkiJRq 16.20813633 -zcUJKwswAkc4WVGAqReHPCsRnQB4MmyjcUdNwV9zzAEhUmLkfDFxs2TmM71FxR7eD41Xe5HhxeQ5ECrUKD8ht3tU24ULzjS 16.20615214 -zcF4j6djSivCjvoTaVgqk8FnamvF4yjT3E4Q3UUEtZwnmw2B1WFN9wsV8gyhDNYNLhcVRBmZwCsxn8ARB99xMXf24FN46wg 16.10151071 -zcXZGWKQaZS2xzxpTpxNWhrk7oK1FqiUk7VTq7TZbBY3ZYqpdFkvQ6aYSWXgr9Moi1Zo53e3XCjnWUptSehAdwjxvYU44BE 15.97715148 -zccxqrP6uHKfgtraUDXqGfkBiSjT64xHXpMwPqY8e3KqmTBwQ962PRkpVncvxbrv9SFunVAVQMTuHgQVzMZATFbkNiYS51K 15.92218694 -zcGR7wgoEewi2QZYacM1YKh92hSa3eQhHZonSzYDkAjj2jse4PxBsWshdZgBYVmkBjGQCQMuaDiFCRjFnCYgJV4cm3pTcG7 15.77869920 -zcDPR5L8soANkAtYJhj1fjDmqprja3X8gQ6iXWGWcmCUqmKBnm675bcu7V7C2wyJqGsguV8bpKnFxuuGSYwqzZDuQAwfzo6 15.75508716 -zcQdfwswqWJp2bwgeoC7bkWsMWPFKRCFxMFBuyVoLh6CwPTm4KQ65GKorsZExiuXXm2VcKfszNZqvukurPHQeZP9Ew5A9Xp 15.71953835 -zcL69uAv5vnf2kNDpgvgrVVkGCKsPhkRVq4HZ31PCU4sE3zqFEUvRj59MRfiqdgaNP2VCHCyBZkYJjkgGEtW34ERf4N2mRD 15.64005503 -zcLiPufNx2NTuyEnPzcoDW7PJmjne9m3odGXTCy3NitTfKyn5Zyv1sYY8LE7Ff4GuEHdzj7QHiUMW2UcALaDLUXQ7g1gUiv 15.17708388 -zcDtkFBMpeQmbu1QHB3Z975oiqdbN5j3Lk3MNckR1bbSjMZonHx9y1nzPuMtYqmdyYx4RkukQCKJ76YYTTg13oBzqSZcWgd 14.82093238 -zcSmWLEK7AqziCjCs4cVdu8yTydxaCVWhBmY61yE9UyCQv6tR8UnXL8m12PBhR21LxkietD5QCMyid7pX2zeDefdzuFupP3 14.76472032 -zc9vNqmvb393HRcVPKFgUuPb9mQERPddNG7BiD7zigZFVgmwiHMVxRrNuQ1yTCz73Gij1BJmbBk34sMuy14GahG3c1SRu7U 14.62968526 -zcPMMATmJnqVKMVhM9hczXSrejB31yUcuhVdsqWL3GanfXXHFavkniHogWZfTBTHNY5jLtDBmtJRv127zYz7aqnTKDa8mgc 14.62190020 -zcY4BF3ZaD9FfJuD3w7p3FnxiqDVjtsNYSqZk4rX2bBRbFeu7wwWwNLtMNoN9j9rpVuL7hXdHrDBhuMJWtErbfmpHgsN5f2 14.27590032 -zcWhKnA2nA2nNMZza78QWfkmYXHjKDqdMgQ2pi5r6LGYpaSfs2W8BpQNfSU38jJCnx9rtu5qgYjSrcBuprg4cyeKU6nRsCE 14.07996253 -zcVDSJMEQxS93DJt11ozWrsWegV5brhm9QFjZK6RKkWSqmJaTr3BRiwMwm8Gsp5sVoc7EoWZrziHtAyW7jQY32r3qte9utu 14.06486451 -zcDbNiNqLjw1C3stMjjDm8o6g9JkrDm3wedJnB4U5jRPb9qDR36rAwsMDWaDQAWgVPrhXE9YPSFV8dadttd9vm2nbJPUZu5 13.80687197 -zcL3mX1AXvho4L5Yu4KrKr2W7sPF9zoqe3kBQt6aviXFbxjoXmzjdJD7jVCCEpxJRWk7Q8dFYZt45b5xkVgd1Am3U55XB9G 13.78532672 -zcDEbSq8NPyms5ueaAgX8gtkA7HJKTmS9NRnJUzkpsEsKbfhAQUEa3vXHE4qWAcCxcQqxt3j2xUsqQvJzuGfHwVvVVL8Ggt 13.74740267 -zcBVeZ65xSo3KCyvTiyQFRdqZTyvWfzGWawmYPzABhBubhY7f7kdLnSoWq6px445KWHDXYf7YHLx7sBNvR8Rpjd69FqhT1x 13.54790512 -zcTVfhCavLU9yqq4X1Sm7cTRaqwJVQyRM8Y2LA9RAvzgC2F6hj5jJdwgzdMiCLhU8BeMhGhraThXnxqyzotU8EBfLKbXhyY 13.53374466 -zcSeHQm59AzufCWGWRSGCb7gsxt8NrXGXC6hTjon2NM8V7dAGVTb3AGKFNRtarfqiTyNAL5VrUsbnUBnvBc6QFPDiaRoMGn 13.42975846 -zcYwocPi7H2YkmWa7ujo78Wn6GCRbG3wMSRTaUhwVCe8wkC6JssS2MZuCe22r3dJAhXXcnRacVQmyRqVXmpMTrTn5pgAkXb 13.23998964 -zcVHMFLw5i4tMYywX7mPZx92WhfUddXv7xzFKvdu1RUNTHFSioSefa7A8jfe1jXqDwXYJshDv27gKJEmSDRVXLBHBkaZzir 12.98798224 -zcXcaQAbKP83FJBwBSkDWdekxMcAZ5AFsNJRpXWafMjhKaYER6cfMbumHcHGkvzCNEHcP7hiXTsupsP4s9zunA33ebC4ui7 12.85761953 -zcWjoQffPqTY1wziHUSbMnZzpRPewyRKXmhyKfW5PNGnkZXe4Djd6QjKYrHmcCUvP5sRh2Rw32dt5VJxYT68FX2fGDEdvfn 12.41537695 -zcXoDYDkVuNpMKHBmjLYgxg6RaMVL21taTb7yJ3eYnqV74bWKuhKYfjJTgwSN36XMrUXVH11xKpJ51MhMovsqoUghXe1Vht 12.40037090 -zca5sRgWifS5EecUjXebsvCd5Lvbzp5pxtTp12jAs3iXK31jq9cGas1CwjVwZBvf28969EvQKetUDu5zw5AoSNFArQdLjVY 12.26768130 -zcHrfMetAGL7Rq2UfQ8yaGPcvKcSXJWKf3Cb2WLe8TyvkeTwx9pii5DGscda87CQCwHfWMNkCWRer5DPBatbKGsfYFwj1Rv 12.18733538 -zcBhTmHFwNPeNGhibzSR6AUcekMSnJPxm8RdbawmhdKmMq7JamdisCMag7MecsainwdQAeMWasvPpaVxnJe9zrC1RYbmHr3 12.16273018 -zc8dxN5eM9zdxCk3kpeFLbJepa9b24fYz338EHZYdJr42zx6YoVB9Q4gNBCLzmpDnAvaBLw5PwhiPCsqNgpUrqUNYyAr9Dq 12.00928070 -zcWjBrc3aEhod1dt6MWJ88k8mGZTC5h61ooysnCCvCh3w8tQgWYnXcDoRZaRXYEi3qQ8Bp5P1qxKT4pmQwpToBKkf24tva1 11.78200384 -zcLYvfVypFLqf4Aw6FK8bKPB2X8Z6Qjg9o6D3nFkaxquddpdfBpL8ptfeqCM4ypF4bXD3uzLN35ij9myYXXAxxPmA35ivFU 11.76184209 -zcaCzx6E61KNB4CuDh1abSN6wNNeD1Mqj7Cn4LwkioryKpwURECopgCN4RYvr9JVDMuS4GLqiwdoD4krUiPQCACqM8voWYH 11.71317741 -zcKmqJAEPYo6YJVTd7kJP4sjQvW97XMwCZMAMFi9VtNe98y2o8tb1QoVyAsQNRb7PmpAUuiRu8xqWSbqC5JpKKdrVdaDFs2 11.63395171 -zcJLEi7JYJ7Mu68ktkfQkw1M8XyY9sSYWZtksVR699NSQzgFnGUYHXLxd51sZYYEpKNFvFKRcScpbGxpL8FJHKxb2dogu4F 11.46705848 -zc9sTXaqicpJGosW8tYmiL8bSkFygrzTHnwK3gy9kBzuouJjekiwr3S7p5kyf1ZYZDRMmjHaNAHreQknLLEj3UM77moq6e3 11.18597846 -zcBCHFojachKPMcZ6j1TgpoTgUrPPUG8ukti4JJtriaJomQdiH29pg62Hv1ugZ4WaMLZ92KC34m3EQqQpDmMvT5nyM1MZCs 10.99741969 -zcEGjccVDS1VdW2BuDhhVvZiz65pRgVPUQLrWRQqxYS2ddecfUCktnmWywrwvArrJDKcNfGxstYwWh5RvhZ3i9QVYGWfnsb 10.87189778 -zcU2F77UaZ3XRpPPXj9jRTDrmXR3uKC5RgzPBcDtzynZBH8ko7sMGZE2J9NdxAqX85UjSTjbxS6R374wPsxnD5RUSka1nWe 10.82722449 -zcgUvA6vRXKFK6RSY5Cv7X4Cq7cQyehyVeJQSYukEqNmv5bVD8CBGStSghcdSnT6ZXPBdtx31bEp5Dti2fzQ9yTcamDV7Vx 10.71633974 -zcNxRNhLq5CUD1e2yzEzuHWDiRLGMUu58VNw4Mr6ZA2NxnP5ubPvGAdtM3k8ZRu9gsXiWsa95qxgVBR3bSabhGrNXe4awuh 10.62771043 -zcNUVwT8agq3Jrtwv8Ny7KHwW69XNoA9xCTkquhfA9dG1ZPn6z6hioSdAsd4i85eiTJQSookUyWUhPfCCSminN19CX7o8zZ 10.45277669 -zcZaHuecVcK8tydd9XfCB4mrK1u4QnAV66i826ufMffF2xsJdXkU7m3saZJ1QW4v5m9JGBQqr1tVmZskz8WRqwpmt4fhYxL 10.38852761 -zcbCKqsFNTuf3L1sy1BjJsFRVjRLWBcCttEC7oEdjp9acx8wcGKaiGeT7qkFs5YacBrZVFYDY67hURpaWvirLrjtnZnWmNu 10.26536784 -zcSYMJWq6pEJkrxU6fgaDfRyPYnYWvHymxksRP1swEJ693o4Ymv81qmEmiafxTsJGToCw5oQkaJwmunHRF32NiKE5vYnCmU 10.23922495 -zcRnvDSjYboB5UxTTgJ8ULATRm4zWyToKoE4sgZmGNBYUz6Jzz4pt4MWCc6fNysPJcF4EgJZYHAGqMAaumiws8cccc9ZfbF 10.04815724 -zcdY9kRYBTiyXU3b7sRHh6Mt5aimKv8EnHyCGtgTaaUYG5kYwcG8Hg35JSJVYKxTHA5Et6FKp92AET9HiVE3fXQJ5j1rEFP 9.85691643 -zcLFPiXZvCsDAeBXTdRohtZftKd4AG2svLzazpqVvJWUcyhL9QykNNKMU3KcePmv1aLZ9jzAjiiw6tJ5KvVAin5dXYLua2S 9.40613688 -zcAqgt53GV8yFqnbyxeizAQusa7Rs6cLe9Ff4K3KH56s8QCHstysh3BmNYCg6fT445STPcgU547oZBv2cn8kRsaViEBk5cL 9.32641614 -zcCD2T95rLdaNYNaPxmjUtptg3MUeg6B5ZnN4qR3WP37ZCfMkWv54UgDoLJZpqBUZQsytgMeMpYMAjzvKrr8YtZM3Nbxya3 9.25422476 -zcZyriJMTBJ2mA7saeUTHYcaWnv9zt7DoaGiYeEAsJkDqp48mZr1oFqTT6VUHTr1Bx8jQbxv1qXf3zUnDWVBdvHaNXQD1VC 9.21124025 -zcaanUmp86yT9BCNrKGeVK7A8Gaoqb5XZ5FbxYUugipD3Vj2LeJMMkJsixaqMZpdMszRitRPqQMsotUK4jG2NwCzp1VKsYd 9.17428857 -zcNs7EaPxuTo8p6iwQB4LBk2CSPUfEGC8ZGzQx4QiTMKHwrzcScJcjtCjqC7isvxQVgGbkJQHS3CyjjR4jFWZJiZxAmELQ6 9.09828134 -zc8MvcZkesqmAFGK43tgRoMN3aSBGeXRtSiivekQJQinorqYMFD4hs3kSPPkg5VvgjvjdzwGLjHq9nwPFreZrFwAXsTykFd 8.93727156 -zcJGJSCbwUnA6W3edGEeX52ijEd594abGZcJyh7YfB4Y4Nk6AoSDxTtWAbcZFDLHAeFtASNhNAVkyeAtTqKZFju2ddezSUn 8.86059113 -zcPUBZLfLwSxjgAQ2jJNNPYMujAxfxxwvFBbH2EvmKKU9qBHyqATbVviP2pxbXzFu2E7U4gkJtwNDjZRGTwJkT9WW8Ak6bT 8.77236849 -zcCq1CEPWW4Vv3cGWss6ouyLCNmQ4sKSmeQLtVA2jkQTNesArMe8L1atZDW5fiEcaPtompGAdFeYbz6dZZgHGJT3SwmRgKB 8.63935920 -zcRtd7QA8uBvhEpigXFJTaMFfp75VM7Kd7ZyRreLR3c7zmuePBzWpynwhrpoTaaeVgwfVE33o2VFLgXsZs1beevVp75NXsE 8.57665912 -zcTwRurcmhdx3EM2vCy1BkdKXsq61VJj3qSXR9eRTNMKWv55zo8TgjkTmrfZiB1JGKiBwAofS6DquhVNAfr7Tdq3mvZeALp 8.49000524 -zcBbcGrQZPfNFFHAC8475F5dpZQu2UKMpjCmYqniBzmVNzTmY3EpsrvDK4af5uRH9NAs9MojTQSst7Vn6ad26ympnX43fRM 8.46860739 -zcf9CeunLsftdFA7QogwCU5YSBJUMGMUqv1GHNf792JMFqyUpNComm7dBNNQ2faced9VeXjGHerGiZBhHHxVDFnBAhGviVt 8.39185023 -zcP2UkAs6fuKdqgaDQFowzmzXgZ5FqV2vbiiExampo7SCkBb991iu4Q8bRhywkzjhYbzYcZ79gAaYxAdrZfWQ165ESSSxDW 8.29917986 -zcRcY4F15B8mn26JjoBo8tJzyr2jfpWSzt1FHr4DuP6HgERhsgXv7FM6j3rzuG4PVyeoYy7CgDkZaP8sreGuB5NHzSXuwDJ 8.29283624 -zcMYSv8g3k2yrFjrbt7WmPSPxjd8YFLYD63UahfCjJxL6TurFgzyPYkEYk5cYwpjPRQddq7NvSYv6fgSjGEpUwvEP8ttQkp 8.12433757 -zcQbfpp3ji7Sp48d9znEq3CxtYshENrP6fD1GLAcsxc61NHZxCAzGEfv8Enin3B231rFA4jiqzSPs7PCePUc59tgESVFjoU 8.06972013 -zcD54pdMkrt6YcFDWWswrYX3X77YGLzz4aDVdWvQiPEgXwUY1srGt5fWWb8ppaMfKcnySAUufaXmwmDSfKQcbSBCpZj9gCy 8.03893356 -zcWwFEGr31qT41ndDR9JJtxy6yE6vbyoGHM3L93xAfrpRiVz5W8gcnnPwkrBeSdMdb92bqJkh522vB9EmnxEsSBkCAKbXKa 7.92741467 -zcf4Jw2ZvfxX7sTWnTBLa856HQfKGMmRaUpPVwEFPn3v3QJGr9GY9muusYPHiy52yCXsPY4EdfpBkTXot7C96iB2PirhFv7 7.76377816 -zcXUA2QEJGSBL7K3bLobzTBhN4FBxpgTSzFmYt2bsgF3FkY4LF7LmmBTUgKHoBzRJJ3hMsY8ixoL5G2EsKB185LQWkabuf9 7.74828910 -zcT1MYtsKQvqqBUq9FFUfXcAGVAhebGurHJYxvkusU5w6ACdaXci72AEjLiRXJaNvioJWrHBMbeNNEBCVwnKM5tFixcAm3T 7.74454515 -zcFxyXGCgcFisibpfeRLfVVVwCcaTeLi1qfr6sFTDzZPPUZLpw2g3ApSaYSs9zKAkzyqt7AYGQLBvZdcVDkQKy8ipZnDMd6 7.71533055 -zcEwaF99sy1GzkCdHY37SjJmWXVEaVuAQLvPgJ7uWsZDhSDBm3uZ1LAyBkYHEXWHAZYL88iS4ZU1ZQjEPCmjd3Qv9cdFB8t 7.66433980 -zcBrPC7QR9h7a73JnvCzbacW67VL5ZTcPdBWoEYj9TEVL4vcANx4G6NVtRe7tP1iM7YUiaUxYqULPmMC46BBkEBgqFdb4po 7.62130390 -zcNzAi8Knsznpn5zEsfXBSm6iUTncKjbr9Fp74YDUhcnFxPNPuNimf8yZXDcLQsy7vK5T8GSTkyxrrFxWd1Wznq8TMiYFWj 7.60870480 -zcME1hi9Sr6zkjVKabMefSFSvLeX59mCkGQVkpsGMTkaBqQuD2w7oheQUY41zg8BZnYtEUwGxrm3KQA1RCJHg6SLaZWgxkT 7.10396527 -zc91RBNtkJRoFuXPsWy13b95VQUnirHCmUQu6fs9JhbCK2bnrtNzEUzq176Ldqq9oW2Fp718HXgcAam1SM8VuCE3mfEaDyk 6.98450491 -zcRPpPBdgbQURqjLGYM41KUTemXrZbocBKSEq6RoRWVRkH4Jqqn2bbTXd7tdpV2jPtYw2nA8QYN37WG75QaJMXtwV4bo92k 6.97753725 -zcGZrZhaJFmx6q3MHz4mVfmk6wjfrujq5FKhbbjCPxczo1rvsLE1Z24XSdd6tJ5N5mo4XAjEnBXDHw22xQkb5Go1vu7WEdV 6.83974980 -zcc8vaEHvDhA5VQQsxLdTyjYKpDyttn7wh5f4Ae7Gb4Wr9NEfvasoQow4pfmB4zSuEJiFxuvY5wcKZTkBc6udKBadoVJG7c 6.77618041 -zcWRYVeVNNnL51pHcY15zu95XSD8wm1Po6u56c7dCNJiiU4hP8QbGmeTGpCQ9VCf6jmJH2RWJyPQYZauZVHCnyRXGxBrPXE 6.70483512 -zcPjDuMtRenDQyH4rDDr9GLRUGHbvpeoEFiJN2j8u42jvRfgkNUhq6eSxW75p9j9fhDPgH5x4bMnkfgthbbRkzf21FFrG2Z 6.69473927 -zcEM8PhHMaEABVJ8V61jL279C5W7XPdiD1QS7HcuKBeL2GiGnRRfojsNws1yR9aDcZ45xs2BQquEV2E3vVwkiPHjAC8rxCs 6.67425853 -zcbqcmdiiAimGQdgjdYTdCUNKvw7gw35J2TVxoi4scAL1KQUYbWSTJjfqNic331QDryRa23gNvKv4PKgai2mam1wC8wng5L 6.64297988 -zcLyoPXNDZP3xtPNbkBMp2UASZpABW1VfBVJzKqDGDLSAHrjghYHdU824WkKKc9MR6fXW8ZgQF4s7nHyTRS2Cpk6DBUcjPc 6.62065965 -zcS3aFFUA6MP2szo6qn3qd78yyeVkFXvfC2YvAYtoUfDnN74V8JRZJPCHVqKJrW17DzGxTyfpJuvLVeyLYo5n9Mm45D3LfJ 6.54542940 -zc8cRkqsanf8RLGe1WWRDMKKpxsuzF1CUmCWjpWzuh2EoXTJahKCmsRyB9ZWBUkd81NK3B5zo5Hip8XuJG3sjZzKZHffhGi 6.51536997 -zcB7ZgSEzm98J1UZQt3GnQ3uN3V6KEPQmVWsc4VTT5G2BC4CZjHbGnUP1PgR2cg3NKRuA6PVtmyyhqTMwEephqkHYqRpJFw 6.43918117 -zcSU5hYMz8HsKKiX9JyF26Y5GsNki7F6srsKjHsSf8QV48Cx2FqaWZfqwFVZ6eNkXc4fTELqLEBWu8Ke6tTBdno74oMHhTe 6.35338352 -zcWKPjthaSc3cdW96sZRPArXTA3JRvMfQJFwnTNJ8KZdnRHfskDxi4FQddiJ6tTrBrrJugnMPVoyHLManGyQ6GvpiFYRBbJ 6.31075474 -zcXyubuAiLm5aHtxpFc1igvjjGMxRS1YY5TPE1PsPuRW7Z9mfJTvJNy2KLWqkyNg6xDEKG7RDtA4cCEfVYMFMXkLyHfyxqR 6.23039031 -zcX7icZaTQy7mggWn3M6MRvovoTc5exGZedNoqds9HvMZEDNWuW9zbMfT8EjxMY4mf3zerMvr2mTCToUHFoVTq5hx7conJL 6.17998676 -zcXNk9GJGz28Rta7r7iVSGkdbjiGE9WRtcBGvqvEWAwfjciSSDC3iyM37HU8fnRwcrYfvS2EHz9TrujFfw9TyHjyj8rxS9u 6.15083129 -zcU3Bd9BUEc1i3G6kc7JuGs4FwVsTCYqSAHN8C2VUAnNW8uzAjNtC9xfLhDu45rj81WmzaJ2Mh253NsayKGfnRCL4ebUiwN 6.13697978 -zcNqczYddMfd6dGjpPwYFXaQjgRWY35CPZALSb2fsk1V2zXpSF2yF4vEtnMiVyoyfrUYvQCr63Uzmr2jD81GdQ8JNfxDcsU 6.10953112 -zc8LwdBhPXoYp6Vof6TLTFTipGPjsiwUJqzwNcyJrHRGmjApY8J9L4aUEjXGKaYXhesPb72N2h41ieM8q5pcQ97xK5Rttw6 6.09900801 -zcMEQQvWcqy2tUUFsa1R6Q9sFJGLdux4pXzGpKGDck6Sqzywn713Bape9GdNQm9PZUniJTderdS569u3uzQU8czCV6fSy9Q 6.04024167 -zcASrHKhuLi8H9B8hDebDyXkj9fNUMKqpfXeQ3hpg9dPxNWacQP5LqWY93RwNjnwT6afKp8j7sSpfsYaEPtoS57AzKzQXdh 5.96066956 -zcV49wNsRt2Jn1PPDubuZSxQBcPwJ8C5DGAxHBa9CMa4dU7CYTCT413cz5rwyQMHw4SzoGF2hHhmJvSyxva2oPxxn1ZLzT7 5.92471494 -zcQ1XZePkYPTm2DCgabb4J4ierLL6CBLuMUktBS6Q83UKAN3DCZEcPRRrNzadyG8j9DshZr4imXBB5foYjzKaxbizepGHyy 5.91680783 -zcLcfAw3pViN6er8ZiX1movRVAWwUaq1v81rZUmFKjnmZ2uZrWpJBszPRkW7BGxQ4Zot2cUHCsUzgDp6sQBKVRcTHudLzMp 5.81088732 -zceqDgpyRKYuc75h7dmNPHVdY2bXjuec3GeMT7nFphV2BQUYSgAq83E18CZ1gPqCuszFipBq6DGPZFpGYQL6gQoDNm1DwQb 5.79533679 -zcGvvoiCPhDnXyjmosZe6EyyAMeqmfCqU8ZXTmpknNJ15cZ9M6bA9i2SC6cVWg9JSeNa4CMJVg5TC3BPpg6epgfKs8gd9UM 5.70757683 -zcW73cZUmjv8jy93LKvo2p899RJahXxxi9VzD3PdAgWJN1VjRwAoL8fkM9iScrnfMFSFbKnGpc5XQxBA4pVbwj5Uqr4BZj9 5.53433200 -zcDmynMGkmGk9zP2gWJcFv8hygdfyMEWiUfcU1dUihzrvWmfsk4NZ1Qisw56FipmN3o8Pv2rcxqmCCkdtanQssxnr3KUdft 5.48904802 -zcG8jHgXaGcSk3Yingb6kMQVA6ag35xysB2fzi4qnLcn6nNiTuZjWyhP16VXqex9wcFVQD8RnFejdtwP26zXeTxX5uvBWu3 5.38652942 -zcJeYzmeqvT6rKEGMVQjtmnmmHWaQDYrDZE3bxf7S7xAhQXjnioYFYPY3A6ZVdPSdgXjtTHvR1fWKMy99RjoFfNMiQeLHos 5.37672377 -zcfmWJELckgWocZPVdN8VWinq7pKC9ZDuy53sUw9LrCVo6FXvHzDcD6y6nFSWnq8vzLHvPnMFhkqwmpVRzJFirVxvCZN5Ug 5.28693304 -zc9Je6aApwa3xLgCiYBQRuWUrBSvFcqw6SxzY4KrYjqZsGabkCNNBSLZWQD9iJe6pkmCCbZPSAgRinjFL6CV6oBRPkwJrCX 5.17444299 -zcLMAuES47XZaDdMPUEgZkkhwP5X2YgZd3HtZ51pYvn2ok8SJJYArCCDxQdqNeiVJ7KuFwHWCZ5WesuDQd6SZiwiQ76hms7 5.14626591 -zcVuqK8SxmugqYH5339z9ft4CwRqb1FAfPcgNS2ZkbE4Hc2CzyuBXDK9D8T4cKScMs3J2L4CrCr96bFGVNM9Lc7EZHww3FT 5.11714394 -zca4mPzUxL76uxWJeB5ihmQJkwWMj3GU61NsMWZPizy9ndgVVF3z1fJXyVDoLERXccwN5szPSvJXdVc8QGpct5cXurhCfVP 5.04229045 -zcaufdBTX5hNTbe4LQxgy6AVzTqJ5ET6DkvKPEbxb3P7iAMTB1g37LR2gfpSV31BdCuUE7YnGzMw9N6nAH3e7K8ajFqYpSE 5.02753040 -zcgvZfRhN7EqUGhcRWe4CCy6a9XbYatAdJ8pVui5FdE9NZiLrqSt1tiYsVRnVnd2cgRKmMtVxsG29HzioTHn3dbx69G7mei 4.99371056 -zcN8152bvCn6UUC2e4u7DnX2RoPMcJNsZyXhTJt7naLWdQWwHWfJ37wtjrMK8J25WeGE6u9K6SZW9zCmsycYjUmNFyhpPsm 4.97482482 -zcW8gRc37xJu5mGtP4Z4af59czZvW7ey4yP7u1Avf9ULZrdy6YaD6qayA4RCki6cTAg3sy5hiY9Ly59Yo2AZhYwJyEpLurx 4.96625631 -zcKYKid2Srr3UskLGc5mtTTmyM1SQcUeDaEeHweNGaedwKYJUq47b5f98enqLKjojWGWnd7fqVytjh3t7GqPiaKrBogwC6B 4.96295694 -zcf7qH2k5J4qVXBXQwee7WFMsCXAXyJb4beGe3P9eU62cvaePjhSyt8J6LyWEkivgEfAUibohYxP3MtWYZ4djF88Sr18BUa 4.80842073 -zcbM9ou5pycL2xSKbQsA61wG2dJ7uvhKZMdqcgwuxphh1rnYXYfnkBmSpszaqd7CuMYmRYEizjEMTbPdmr1iZDq3hxDABmr 4.75410827 -zcMXFQwvjEX3yg3j5nc5jMT9WKzjNNb9mbQW63vnbmg23upaQ1Nr8Csz3tAeKHm88Tkq5AdTeR8npXbkSCEVrorPtanZeVY 4.75026342 -zcQQkxpycC9vfw18Uc5B5cGvzovmQZx41fv9f1v9EWrzd912LhMahERJyayNGcohxb395KVZsmpF72ZsrYuCccXrrsYosQa 4.73024716 -zcUW5VB5JuuU39FHeQ4oznTCSEqcTn4bQ9o2KxR7Rb6nAH6BuJu6qrW4JFKn5eo7VHTqPkefnwhcXhqiYCsDg3WweMCDREp 4.63443810 -zcBT4VCUUF1WWCPivFu86LC34wQbiDeMC1B2U6LQgKfQquAWWdjTKVubNw2FY1XtqBk4mstrepWoHtTUxXSFMB9JMXF4JoR 4.55779194 -zcJaUPazgyv1h9D6yY916n5kXSdsyfZtDC3qFcbRyqR9gW5XiDaj5nnWJ1gUjZa1C8n6a8wxgL48WRWbgkJxCCAdtdwMhLd 4.49385493 -zcBPQRvYjn7Tn4yFnPANJ6Z3yahaZSxzDpTPDpVHSnadu4cPkgGoGAAR4vqgKCHJoXchRsc3RFd59Yd2HoXtwK9mr1mqy24 4.46296185 -zcHiUNwiDukocg6pS9AHg3JrDdGjE5spzBCXy3sMxJZBs652BEnm8Kz2rChgddPSusybudynQnrSrQaLGC4XurxW78SgxjT 4.41589213 -zcQNnNxjrBMzwbMhNjXfgM2dAMj1mfjoZp8bSWMboHr9eJFBYiDPjxT497Gor3HYyyiBji13rDoCogGYMHyBS5Me9TxPkjB 4.39496475 -zcZVpjUbCo4B6w96N8cQuGpgbrUDpT1p4Mo1RLxdba4GdHhd7HoGj31nMmAm3pLWg9fDzRhwbfacxDLpj8yBnwnLVsSDgFZ 4.36492267 -zcAcZwiNE6VkomM1KP4qJzNBgYftqQa8SaVsLcfAvNjjFhKZ7T8hKgtMtd9wuqnrNJRLGbFNQkgQzMxH86GFQgigGGZgnyE 4.34515833 -zcg3skt9YpvwJYaJGdsdoGTfW8SX4LS41uB8oixvZY8S9UXqZjuz48DMnALCedqeHxdPFaFgVHc5ASdbeUBkhWMkssnQkUQ 4.30581173 -zcEVsJvn2PyUDzpxufoCFUeNQA58pEdGrxbSUiAZ9YqxAq8zDvHUkfDuHACK3x6jkSKyWZEZmjAQrBju63kR88A24SQgtzq 4.28166794 -zcNYzdZQmn4JfpmvJ3hQZozXgDkkXLe1NgVmz32aM4HuHw7q1tCrvZ3naYXUVdqXyMubRWbMqi4LFMvpnrKvS9mrDKSw7Jq 4.28134230 -zcHuRh8nWs5k4vJV44v2p7gzoXQyZxYYsozhrivNMrF5MsNuJkCJfrSfqzm1Q2XBJRDLN3HzuMGKBFjSS7RHKDa7TUzmZRH 4.18079012 -zc9etdsuHtYtv1KqBj8uQ8aU26tKoJTsCujvUguxdhQxQcEfzYv84CpCbTBF6oWuXZtEpqEhECvzEPevKnhZAncryjwsYVC 4.16323301 -zcW5hUCFuuFyWmTDLAJmMBziGUEQHRjQ1NKxqcHwHSWcUF7B3d3JBV7sDXanfXsC6ENEovQzFMNb7PXwsmmVjXR4BGxQmJJ 4.15227482 -zcTm2FEiXLn6RNp2PZHZVKPKYxzyhjWXM8BmHQbH3RmqpPD2pmnrrdXNfvCPxVxHasT2KRSJ9w7A7qsKxbnRov6zGQwp2tp 4.14396258 -zcGHiFKF3oABNn71maHfya4DAYEvk3eoAzzHTW86u6cas116nCEwbeYYptUhEbbrJdeFNFRyyrX3RMPgankQhnq6CyRDH6f 4.09486624 -zcPdR7cxcUELEAnnyq3vzmjG86jHChSTHZFdsU69KGvjcfYJzqD9zuBGLm3922HqQVUzaS1Z5QHc9rHzBbBZjHDESvZGcE2 3.85334327 -zcNYvwgtDhRgr2BgfLid7KkWbXuSdcJQMJ1i9V8tvrkSCu9MXeAeunwAxo79bg3vMgT9i5o1gF5hZojxcux8bvnvWHUR43P 3.83910217 -zcf6pyDRWnsq9Lctcbawcmt3rDomtvSVwHNGfLVC79ZzcgSMLDP5yKqtXCDUziMNr3GFTZ41GKpKtQssrsHGth8zNbrQGQH 3.83163550 -zcdNoddKRJnbXhRyegGtRFTWmR6GNA2iXcKWDLN9qtHpMWw9DoGP9HGywNAzVRi6V71cgV984mifHCKMrzvs5zUPrmzwRhZ 3.79856897 -zcZYvvzdfWGYiCvvcDcooh6mi7WwCUBQ2fjmCdTTh5oyRE723Ex7GcuQc1L8Z5FNCN8zpz6ehMk19afXgY2D2A2egAd3wRy 3.77183874 -zcBZWMv8dNhnFFaRLwn35FxiETcbzJ7PGiC9WRVzPAwG5ehAtNuVNKEULh4QP5nTg5FauEmaNHyHma58ZxDHX7XXkWWoV4B 3.76907099 -zcbRT8cuy8P4b35iosuUp85hCQNfMkUYopwyXRMTDS3qVWS8jr1L2G94dbBY8soYXSYGCQnBNeNentwR8UVWhRmsWWnrA6n 3.76691852 -zcL1pZjZnQry8y6nhTydgbbjJHFVhe2skFGzzxPgWAmL6CPv8yEVgtGrxa3B3KHrc8zoJguYRJYAr6qFJJfnc2zZHYPSrc8 3.76500979 -zcaKVaoeeg5eMuEvj7s9rEEukR2rBDjJkFy3D9Q15F4FqHYQtKtTfmHpYZr75mLa2UXyUXDR5tDgQrdFc7qTZ4QY5xhAFDL 3.73343896 -zcg6Q6avvTPWk6ZgGdDdMBNRF15pojaQbmxasJMNFFN46g3cz5jPmpcow6UrFnzUCHM82i14Dnq6jpx3zoWFaRWa1Ug3KXe 3.72007094 -zcVS2DrHP8nJchJ7MHnLC6UBnKR8ge4J9zP8c9JHKqMQjdNjUBS6ERfwXtQn5BV5mNQW5ArQfoHC45jrtGvHArH6TgAgWo3 3.68289149 -zcg1aUAu8YS9oYU2b9vhLZtXesdefR2x1SLfmnaQ3CaW5SoyRfhRHnnWmdpPAyTTYhEvPigRUQyY6fjr66Lvx8oqPjdkhK8 3.61930376 -zcXq5N9d8BJ2CBUz5t6h5to3UEV4h2rvgKmchxKK35vXDFEYynMW2ECV8h7JRUmA9LXQsrVuAP8THFQYArv62nrSVejzBFK 3.59247061 -zcXrvDWo4pcYotpNV5NvJrnRmBKxscAoTAQtjiUWSuBwTyfW2uv6UpdgMv4j8A4gwEQvZGbWXh8YLaYinrPaZ86zzYEk68d 3.57582014 -zcEErNaZkBfFYudawZMvmfCKoWTgC7MxJgrYf1HQJq6skqU9wwfDrHnfL1ZHV8ASDaXqU6GzwobeGgDvAj2Dy1U6G6JTaE2 3.54755100 -zcNzF7PM4ooCdmW7DgdffPZEBpk7Sx6gzZqPScLS8dswfvHu3XviZKruA5zo3g5dMkNSL1687AHwcWX3jncnHxDxM1zdknS 3.50835924 -zcYSEb7eoiqm3jSTXhe4uM4VZ5sbqXneQKHw7yP9ssLNwJL9rYCQ3Xy15cacX8KiVMrPbhynKMk1aQAs6kYUC78DYwU49uc 3.50408937 -zcGWvfjXUjwigM1nwzzbEk4G8JTCTSmgy3Rec6L5mq1HofZGm877wHAjmybyeXRByUYbq88vsqRPqJNFJWRF3o3nVEXZtUR 3.43060960 -zcEBMxDffhEBxLtgzNCdKoqmn3PYmGXowpawt9CfuqnH342WCCuYNHf5ztnqYNvpJBoa1kPhvFG7Xv3cXjXF6RBc3SUAbsX 3.39268450 -zcMbpwREfY7ybKUwMCi5M1nJuDXBxxDQr8CnLnjuwAfQdRHNNqHfSAAUv6MuJP4YBYjLzy8SdBcXs89vGz1oBVdYJb4bN7S 3.31288420 -zcRGPtKuDtUEx8tn3k3EijxxNzFVwD1VV2SeUqhsmYMfWJ11PNoZBouL6aqoTzaZV3GeiT8bT5Nvgtcouy3EK1bLs8apbe2 3.22095234 -zcYVumgc2i5HFUZGRea1FojhmR4E2yZ5zX4xhFkxHevhGt4P6uQKSaJ1dgeizwzFdMyhQ56HnQxcNKwG3iubURxjvzseP9C 3.10385939 -zcF9iMTsaFXjhaVjzrg4cQTubRJV1M8ZJuf96u36cofDSdRaNRwFprqTHgcKBzzkNRn4GJbsEKrmviod4RBawyDvVTS1LVS 3.06477450 -zcBsP1TBoZRbWsa6NUsUWZBbHcBGWRmLvCTToLtcwpVvFSafXaUzuHe46kLfvgRuWcJEAxjGZvJqCEwgg8QNgpUXbm5MxcF 3.04494901 -zcRJwwDjfQzHjfwpdBFURrj4FBZ1dju5ZPfLynoTWHruKnoQs6vUxUSFFPHeW9yKDi7JCKZMY9DfpAVhHB5P8ri4EaYKhVi 3.03407039 -zcYxfSd3MJbpxzkzV5GmJwjcNCEqie9kkKMsdtm7JejLHR8TEwdGJbwbgyZqUJ8UbLgLsE8ZP3DNd8HDfAGp3MsL26RR5C5 3.01623120 -zcKNX4HKv5BWZRpSgCGDRbPonQHXNL8fHYmYkDi69qcomkkSjhFKydmvuGYq5VSuBqENcEQsft2JR4sDZodVjHwyHFjRgdf 3.01462661 -zcQZ5Q7PS54teN7fywMhevj6xAzRiEeRXV3VYymzGHRfLjQ3727iWcBWWeYgqY1BJ3EnjaJUoJQ5ZQjRGgSiCBXN7B4EnK6 3.00491132 -zcayjPFuDFHWY4osVnfKekKxAoDoSjmuVPjWN2jRp87j4sEj1kofjp2NzRsZpxMAGMF31RUzH4qfwG4a6D4GbcS2jVZcjJe 2.99579483 -zcE6RczaoX98JRZ4uVrCkvLxxQSxQeDVT8oP4vb7ZCPVVe5VN3H8ig6jr3figNg9VSv1eLNyAvLhtKAMUYKtM2QhS4cgQVv 2.98320630 -zcLveCJfHjppUcnKjs4PuoCi6Ncz45t4tjE1FkXLXGEZqkzKodcEVcQDTThebGUNTZviMk1bSHsJhBGmsUA6Crvsx15vbnt 2.95475126 -zccVzFCv3EnjEBMVacxPecfHhMZqC7psq75LfefHWAcdaSMppzbWsFQmdjqdMno71Hw95XqLsSathKJhWwDskkb5kfdgBP3 2.92608326 -zcLpS3tuozNhT6pp38NNELtJazV76Kc83UppznvAMkYtoVMgVYmzmzyLmiR9cAcWSigYiB92xzkguAhsTCZLTikTB5jCUQM 2.92483272 -zceXxWQHvxuGQKuwAPV2WfuvnB9AgsyjfpV6muNopff5ttTbv28wLpZmnce4duVaTJRcBMF1cbkDDGGCeBWqWqgLABixzhc 2.80356358 -zcH6ywduMtrT5JRvmy5uis4mJhrB3dtLd4h83cBJNZsQPfyDwLdAsAP7K953gTZvEBzpQhtPMW28HTNsLyMnvyrb19LGTXp 2.78886954 -zcG4VbH548rgqgY3Y2QoSSx1VRvML9nRHedWGwapNQfQuPYS5VnjBJjtgmD9DDtgF4XyvyY6RCWrGWYmjbWTKXAcEVtGG1J 2.71732544 -zccq78RCcuHEUy6SaCJoaFSMpAYqytJUd942xosx1D1pd7LzcJtiNz4HWo8KwBNvKg6WtbPMG4RrNg5myVHEdsRZtBxgLv3 2.69998381 -zcAUuMgejnWfjyHtkg9XQ4fvDBZe2qBUsJ31wK2HWfcsuM3k3Qymef8bSUefJHapzzDZN2H3qkMksZqCwk5ZUhg4ZoDNpw9 2.66715432 -zcfZBdFPovSZrVMXa91diFgqmums2vS8zYGJGxKGYCKiRRKV2eafmWi4WPGTmyZDohYjm1KTDzPJuQyYNtx88zWhiSxECWa 2.64422999 -zcfVozUUQELKbi3zKo1mbbmuBRTMYvB9CzQRsNy9SNz4oDL4aVhJf7iDUdtW8Aib1qKKraGXbf6X1sokix1njZKGCx8cUVs 2.62664221 -zcHvq2k4Xuophx222QN8bsjyNZhWqhgRno1CUdfy4QTssjE7b3hou7BAVQenUm4Joy8izvQHhW24WimPfNa5Rioyq7xSkwW 2.58305788 -zcLt6NbiYRwAFRX5qM8V2X2quhoYoEzo1Fqmjd7zcRTb7DoawD1SRRDJ9dV6s3VYw3VX9od1NQh9q8Qt1ms4KQhUr2ai3Ky 2.57327004 -zcHKHBkfAXYGJiXu8CKrQALJgjxHdsAguUjfjKhUs1NtsgyuU1Kpk4xiiX6vxDjeePs79KzLjM6cPJtDxSMFesLCJvgrrob 2.54795563 -zcXGvSkoaQ3Fzh2Y8vF5bLC13ViQBpSjMQNmMn4gyU9CuHNvFynRcJm83qSv83DiPGjQUUU1S4W1n7oodY2EuD35XPPHSjb 2.53237163 -zcSRFNpjrkDFpJibBPcRKpnVmy1VRJ9FZ4cF6bAUtJqqXPZ9xDfKB5HgYkBsvv1DaMFdCtYVzn95kdK3tD1c8rVJvyGnVuP 2.42974746 -zc9AfSAmeDKmpMipmQtFbGqoHYBhkGeWc1oSTQbJkKPJpcGbNTDfEVxC1xjQzD4PLhHBTZcpkbrSAaNFDrYMtAMb2Hv7Ho9 2.41489180 -zcBsNuWbMrc8kJt8dCcFe6TV6HN5XzNRZp1rz2noNutcsP1NcyWD9RgUtEMCKkhvh42zsxUajfXvaHGVjJcnvpPGHvRWEUU 2.40005944 -zcF1fWCzCzpq2c9N2EVXTx12bek6nL9S1ZAi6Au7BR5XWxDKDZdrnvjNEpY7ESsyGgLH7RtYBGXF2QpbjfC3gkxcwKTy4WY 2.37048587 -zcJrgUZjSJ7Skf8WYJGprhuUmsBsKSrzxUiaDu8nNPyQ6AJ95tbcmnfs9w9Prrxr6WyzwkBX7AyGT1kq9oR4CeY8Wt7TVVY 2.35239953 -zcbYv3dZDCg3eTi2VyJTfzVnsqGQb5A1LRa2mPsnaxpVb33jJk9SdcLvhSkAiSSLRVrMgAMQg6bPNjVQBPj2Meg5XTpBY6Z 2.22688079 -zcP9PtNnjnCqMEFM3hGQdt7bge63n1KZYQuob6rkqt18M9XvQuXcFa5SZp5XtBVCVGraeTvNp4M2X479iwzq3ays9MfcE6b 2.19624088 -zcJmdsq9UZue3at1rpxRQLXKkgPVEYyMvsPiVsFiWcQmhr9kEtSadyqViUDF52a4arQVEb6maCGdhLxwM1ziStMDVsgd8kr 2.11924015 -zcSmHMzMcCApkKYZhwUSzAPizFdKFfpCEVt8DpdiBbGRRfTBoUzQ1hLWJBKc95PisNteyKozuVo4B5vMGfEXqGYYfHUtfsw 2.10574833 -zceo5DiBppg1QSTy5afGVBp9EANQxK3SZ3isi4S9McEbv1hqU4FLTAhNtQRcqwKFrztGaNSTb2VDz1pwMBaUhh3BrF1BN6W 2.10462684 -zcHXK4RCvKhkSAE5r3rQ1xSBQ1TqwHe5uBAsMwNj5heJLesW1DNoWuf4wAS4TK3WChyTvBVD2yPjMQJkquQQFZ1rRUttDg5 2.09753296 -zcWCntAv1ejvcVvDa3m2bbC7rU7MBBKNEHtYKT9fGhCnGEA3HzULrCvy981njZcuhaTyPHTx8pyPosyWhrR3vuARaYA9A2E 2.06257077 -zcDf2czcYyiBW4Z2vhsnarLhbbLJxBtADbbCj4suHceC1w5tGPxMsdFRSGpZP132D1CViSpgTpGJvmrcmyRkpKvSYKUDpqC 2.05539523 -zcGzVBXG7K5miJW6PW2KgjdX2vsMWhfTBzxuK3pPQK3vJjU65edsCPaiEPUYFZ6m8RZdyQ6WGivD1YLQvtMju366Yg7PCSq 2.04711869 -zcVi1PGpdbRz8wyyfvzEfpspxKWZsJgt7dLXLxApaZp7RXk924J5b7Lm5sHZvbREL7B8pxeJdDbearUa46wZnQSDPnaviDU 1.99749863 -zcKUKodanajAZQqV9LK2djpSMqLtWtHDdGUBPKpi5FnAd3DhtkQDcWxxWKy3NTyzjNoD6quMjoBnAy5sZ9Pa4HFq2WxpwgR 1.98939799 -zcPKhgFuLeKPKSB7HjQvTcU9jwvqNg2AsQpPRJS7aoLwDKH5qbVpXsUDAr85k2Xyfk7KYMqLvzLRLcbwUgFfXPQyd2p6aHM 1.95908456 -zcCqg1pV6WbETjiVaGC7Q8KwDtBUdAiRVrjvfBYX79DykjrK6TcQ1Fxt1CtmhSiZ4j4bysrhDnf6NAkB7Sq6VSigwsViNCq 1.92840423 -zcWjohP7mo7hWCYGmRhRMGA1wwPKExM1bj7SJF14cXzgVHYfVVTBGTad5eHmoTSwp6psH58WNp7iTYQxAo9jBedkAb1Porm 1.92039230 -zcR8tSn9s2CRh6kjoQNi4uq5WmstRjhL8bZT76yMF789jK1Nv2BuaHM2ouoE4M7nJtPYxSi3WWoXi9qAogyqVCCFEF6Su3Q 1.90612967 -zc8ebVMHEzoXrzyMxqca1gJrAUbDTgpP5SrCEYrXCVyRG1gGEocWZJ4XWLwduP2zJdU5tyX6Y3VDcTwodcKo8BohVwyYvbq 1.83119102 -zc97Wuy1GMjC3oUQyrBAXFWa2gnyfSkwUzJ7gcZAZhPVEMveKJH2ZV3BPhC1e6e8aWwSwAn1ja3qhsSMxcuf5igLaunvyp6 1.75398841 -zcJ4s6shFiGgCsASYbRDVZ5kKqMADK6A7wt8z6ArZRoESwrdVqoJPar2BuQjZuKtJpSyh3f7ZoaG5ydY8RnHd4A3eUszYrq 1.72336003 -zcZkhCwNUTH2oxqieTA3imc3iFALDjo9Dvy69tG5wSmQ7HrDD9G5DmFbXBsnAbheB4SZcN1eeVnK2Xe1pXfi5BzxfAuYxfo 1.67463142 -zcTYtY7rHXf7eKt8FDmVnkKVJcCHc35NEei4jNkm8wNaQeGnScHr6uvR9y8L2YdpRK142NSbWVvY1STdesjhme7ZE49bFjf 1.55589247 -zcJLdoLxxDdhNZhwyEevWUdmuYqhpbqBgvudaRpp9fEr5V5sBsQBk81k79f4CaSYeZi5ESyS9NJLVdkQXucoxFTjV32v7ro 1.55543805 -zcJfsVJrquSKwhqRSy7ZUjgAobgBtKZW5QPvkJSSvRz23tPSjuWu1y5JgYmYeWUEsUnCVQTe9yLLrQtS7z2gjSY1DiuShKx 1.54518137 -zc9VT8B6boGh8PPofmK622rgNihsGo3hG9cyu7qq4ovcjpUE96FhyMHx2a7JNdkHo4ZfJ5NF8eSK3nh9AYUFokKX7rPxQVQ 1.53009227 -zcLU5GNvRhsM4XS75ASmAsX28MWytsEjUz9X2BnirHwtUM74TRhge7xFkq6YQgWXx9hpqjGGfXdTHSfAk6Xn3MdzVqjc9tL 1.52621439 -zcNetLERU3pqnv6VzvHBzbSpV6hr9QGaUciky8upob1ADq7NE3kj15nYog26PQFFhCqfGsV3cSfsztCg73DwEtw8XJ44eKV 1.51113687 -zccahWrKzbiHU2puFQi72imh2AsRqvV3QAsuaLFj6ZMmkaC5FZyoywp96ugThMDtenrhmUjjspcrjEsRqVT2fcCUFjH4Qwm 1.48669521 -zcRfxMDNRfqtzMW7iW5rptBMAcvyuccrPYJWa1qwEuybCoBymo7K24hbiVBMjnxfimm5MBTsVSxVmNZZWcC4Lh3hjeqW1kE 1.43643098 -zcUHofRkFoTQikBTc7qnr8YnQmWqnbx22fZgMxerUf9zj12x9BidU48J7ra5pwXPVyHLypexqNLcji2YmXREkfHMJMKstje 1.42951689 -zcgdK5BNYr9LFnY3YE8pjBM8aXyjCXox1bMn7CuSuLf3rNBAcj3pfz3vKHmwetC2oBJw6dmkCB7Jn32s36JBMqPDUXV4i1M 1.40009323 -zcQLf5ibetocyaSotbPvpPfRCj9GGtCcbpshCTmSLW1F98vo9mcep1BUEB4zudHj1fCWMMmWGU3J8Y8sTvm3pYq1rgkxTzX 1.37641549 -zcUTyv7qDLWTQQPSNGSW1oxRMFw27oMEviDtXoDS55DWYyB5kTL7ExYjA5PnF1fxD2coaK5dsHffktbEMeMA6HP59zVRTiK 1.32291124 -zcDvzJy97YLfG7Bqv7JTHD7F7ManupcU3qxmc5jQLyGPbx594PwR9RTVKAs6yuHr8WMR1uPP56ajbCz9gqm6hUVK1WZXePw 1.24520144 -zcTwr4xwf4WT9rEBEVQXt2NBFmSkLycSV9uZVotbRRcM8FKVyh4JbZVnD5vKn7mQHdJpsNJEayLekFsrTW6VVyykDkuQsQo 1.16567418 -zcQQHm6wiWg2pZVBUxxFdHG7AxY6oxzz3EExnvAk6Dx6BTVpMdwVBMG3pRVFYBncSTqxVCGAWRpJuoFqB8aZghcZCZgLAp5 1.15932717 -zcEwwmgHaj2xju1vQMxuWQri7nAGFALZDhRQMePsXh1G5GaczfVVC7jHrGhb1M4aug6q9a1HBwepW58HieEfvVFmeRHygii 1.12713095 -zcccEtUbyWyoSBHHiTRF8wtpn8uiF918ZeRg7T4zk2tdQVegwuVgAy7mDUyRkdL71gtRrvVzZbGcepcuW7B5BQqL29kQaCn 1.11945929 -zcXWvf6Z8WDEfucm924XMQvF9WkgJDkaFTM9BCj1yn4P8QGDi8dBa8qTLYQe8HfspLnobci4JJSmXnc51YD2jRGwDKB62mW 1.09121848 -zcYTEoqJM7ZBr665ksjcFi92uCRT43VK91LAFfxBUA4eWm51MS6J7mKAGich84qjSGWPpvRCL7CjMTeMoVs4LzvsqMJEt9X 1.06069175 -zcdF8bEeqzERG7SgUsN29h4KFE9St7776bk5yTZRJ2QyK8mL2fBT3Br8DgyxFiLfQAH8YeWaWco98Vo7T6fbvS3jmhfsgVd 1.03674971 -zcKjVBKkspXX8FzHCQSjEQm7EmxJun89rPTWvwW2W7SKK4WYSDtcDzPbWnUBmwtipSyHYZFhjVD4CtwbYD5dcE9V1R23C7u 0.96629889 -zcMAF4sUYdqrUgvJjno622Dn3ngXxn2hQdhw2jHx7vhyDS6qnSTs9PGVZAUgpNYwVNYuze8bavDAhpPuAT4oGh3dcqx338M 0.95442117 -zcPWaR1YrUqbGi7wfQR3pnEGHGSWvdz9s26gYRUBLaKrQgxhDgrH7J6y6QcaypbB3u13UuuWYCpPzm8rqLfi4m6pgu4NRmS 0.95304876 -zcHp68S8zHurnQSFQbdMYdhm4rcyRdR74j2AmsnKYcb9T4A6mdsqPDoJXTzwwHkMkdMVKys6Bhsswx2qpgWY1buwt4XY3gY 0.91849044 -zc8SvD48fHzjEaT76wbZds7o3YAzKrZixJJzSyEvqVx8X2SrxBwExX7AfD1vPKdnr9MrsYiBYm6x5Je6sMTjWnAvuZxKLQM 0.89815232 -zcC1bv1YH1DdEfR8H2HAcz1KoUWfs8ZP4beuJ7P3NGL6958ma9M8yuwdCxpXtoo7rD2VT2Qs472HiZxeoi63xvQsXKf3yxu 0.89679879 -zcK2kFAghvfayioFvEqBZAisaYdPNA616jwyQAkR4eW9CXZKX2FrmghHqvQMWogjAjNPgSfE1usLa65uxjXiNxtXrbYpZMj 0.87591561 -zcYqdMbjxxqQDha48y7eXG3Y3o2mdDVQ2de16cQHVSRXxvQxYBEVCqtkyVGxMsEpWGVDBsmdT2kdQsDaMfqEsuaByFVu5Vj 0.84518557 -zcBLf7APU6D6RUYHCw4iLxQJD9j1DaAKHERBZRXwuLRtPz5hZxRyErRLXzgqDF1BeRaody6WpaBZ1fGHVn2xtWM2u4u9Uti 0.82198535 -zc96A3YbJn2rWJUVXD1uQYRVtENAzBKK13cSXUdGxPubnNtrvB7LuTFtKtoyG6d3oGdVPbAMjJiFiXCJC1QaF8ocajJzUcE 0.81338899 -zcJHoozoCVD8mLixnKRT5fA8unzpCEJnRMhfGAX345PYck6gm6rT8rqk1uMwSxanAPpDjXQ24pbMz7RY5RRbz61Bpv4b1yC 0.81118924 -zcGaje6AA5ukwn2f1hh8A5RtHTkM9omKou5Q5uSFEJ7vakK6QwE2NrR1aPsKVkRHLxgsRVUEKof3StEb1P1GTQyN6zQ6Kga 0.80288267 -zcd1VNK55eDtRHVNfUVGtHBehhtN9H3vQcrketY9tegGmxgczViPPfn8uNHZFdM2fXq4Hnf8REeEBFvNtdbu9h1UA6fRqm3 0.75406890 -zcUXCHv7t1r5iKfEykBjDzkz1FDeqqD4Y8PYoHxLs3pGRqE3WTRh5AfjzjXGhH54ztM9TbY91GQFwJtTWgbME3eo6kaf1DT 0.74973698 -zcHXhjyY2FAGbwxjjF2s3TWKvE76Bqs33R3hkugpcQ5CLkvkbEeR6smuEsrvBqcei8fV9Rxgn7YnXJ1hTvs2VetuXE6NHJj 0.74208243 -zcJH1qu6DedMp4QgBRJqT3r1phtFSbiGjdLKJvxczPchTVGtmyynh45yLmvoLfCmoJA5qmJ45LF6JjJJ6gFiUaRNwbJ5BR7 0.72408644 -zcGwvfR28PxRhfH3JdAkhCRE6RKyMxLzfVN3rjgKpid5eCjPFR3VDHkGBkgedcpinKeeARq36D3UTemTgsVahPkFshhTmD9 0.68136904 -zcJZE2DnvjpEKQwWcTzmjE16uAH8uguy8B3rbGXh9NHZPzTSimXVgHni1WeKfCw68uEw18aDWMbpyJ7DtewwZJxq76nLM2d 0.67191585 -zcXrQEMRyETYnvzMQYjhCinxaS1qoBv7DKrbsnTgDbEshaeueZ2ANVRYApS7WyRKCC1zYosv7nPaNU4iER5i1hyhfsCqsVb 0.65541553 -zcMkJNSeWkdySMGpcWqN8Gki3JrELwQ7TafArPDegGJYYCwPbAaqTS5KVowfQ48WDVB1FUfBRTKB4TVQVBa3gRcAHpLjarq 0.65401806 -zccNRPDyHtYxSWzNPXgmeWQWmaU1V2mXjKQFDE7ZEgCiXdhCHSCh9wXSo39NviY2yafEh1uruErXLF78kvhHDXTdyXDJ5qr 0.61124103 -zch2mcLNBQJJouVEWGHNk1K2HyncYqNWF3eBmBveDJcV2En1yZwLDAtGKNP6p2NbrDAayZbZxTAPrvQSnatbKoiojWtASqT 0.60140950 -zcewYPmYoK7KW2np8h3VmVkhmc3vxEpjmR7oPb5bJnYktuBgNdPbuYgJWAWXvhWZ1Wz32mbff1Yx3cfQRJP1UUB7dfTXjPu 0.58787999 -zcPx2h9iDX7TGRURrannCukWVCRM8y7yvfpXx9UK4yMvkR5sizoLL1wyKEYpB1QVaJGMQsBHkgZKoCnuPir7MRF6gpHQz9B 0.58180391 -zc9qqtVywxfVUMtXoDyiqHJnae92QExbDmvkU4f2ENzdrZCM1v3UT49SfrhW6h1sR2phKMiH3RdpxQZw8Q2r3MvKKfKwQ3s 0.55943661 -zcdfsLHzVvKKoNx1eKfDryAUtMuACBF8ndHPiYSYTz2cWepfw1aS8iU22P4H4DCSqFvvNCziSgAyZ5SvrQbGBxLSNj1b5he 0.54923166 -zcday9x7h77mXYeont51VbB9XRA6fVc6T67tqU6zgc9Z69SwWWTHUQfcLmz6xrcGax6fdsyi453NZfTdC4oDhuJfUXMcF7A 0.54500955 -zcStXHXMW5E8vhXkG3RZxCj9U9N9TcCoXLWbDDZ6Q8smzwVo3pKdu4QerHp5oPgBeQ3sm46ggxnDrPN6G4GTuaPy61NWKcx 0.53443131 -zcGMwejiWKrs8q71KunhwAtPUcDWvLiWtkscrQcieZLnkFvGVLE9NfPUFQPUzzmsY46gfG1UoiidvGtv5y7qhyGKpVRP5pw 0.53287905 -zcJbdYukkcSck9y7ZwqbUtmb7gm6QSds7WV7f1gR6VFtQsuHdAJkKLEeeXke39Xi2qmEa7J9JcM1Q9n9UT4S7b4ZYKABePD 0.52544252 -zcYbYNCerhoZAb4j3A9g1UsaMa18GvRGeMzivR5Bw5wcFSnYSEEfHuyiDyFZfKS5frxzqn2apH5m54Y5EUJFPdZeZ4hXAAH 0.51389386 -zcEetZczrX2DDJxVxGPNJpVkibBxJzvYTPKXPiC8Vxb6db4Ma2kNLUg4dH18CW1HGdPxm4SVTRJYQLvoDqy2AeT4CNifTWn 0.49894782 -zcTDAhTDwMQ6wWUE2XtfbL2ydGDZF8bN8GMSDUAqWkVGGuDNwDhYBXXiRaE1PBaj5Q2VVUieD4p2GpWCWtNiZjVMRsLfSqz 0.48176943 -zcZ8NSyuBewoQqdx4UqRgH1LnGbyB3oFyUakrKGw969AcnX49bJ3FxQ1XRrfofe74xrnChf8KsMLbmYMGfAy5x4WH4N8omR 0.48097343 -zcPpmeEdJ5AWjShSpt1yZKTjro6bay9SuCUMaxBFAV5Avn41UofYik5yPLKQ1aTubumKrCAJSC1KdqeCMv5QU2sYkCbqFxy 0.47933329 -zcBoPtWqXZ2QGcj7uJucebaUKYnGT7g9AULSt8pi9dhHztisawE1wva6vKJWQZCjVPrwvb2CAwQ64SkRgCfbTuow8xf6kjp 0.46483260 -zcVjTGm97Pha4razBbAoAHP3K7kaAvMH6r6Rn1NHYxxAKoWoQKQSnVK3oJhreGz6SuW5vhiU4MCxt1eSowAShQsAggKQR9U 0.45247462 -zcGUUXjVaLFuyF39VEHbSt8vpGQnSAhtk4XtaLf3GSFw2NJEwrNY398Dxrf2Kv8W9kQ7iAcuHZofaJECv8Z223Qrvauhz7X 0.44629669 -zc8PPAM9sjbizrjwwwVXC4gQWJTzFwmSwzWQRZMHMYrVnxvNREeTroCwEhNgBHUPy1Z55oM7NMATyuUxJphMhns18XzWHMU 0.44493658 -zc9ULZLNbF8NAX313X7Kag11ZDtVaTBs3qMjZHzedfu9hCfdqPgjmfpx5U8a6S4TMnGmCU2PR2wCpG7PQctj5pwL8jDGpYv 0.44100427 -zcawPCNkamyeet3G6tfpihyNy7osPs3chYEYXiJtdrXz97MW7MUFCoJGHZcnr9Bs6WRnquz5HHKmh6cpuXGbA4BEUUGykdd 0.43394904 -zcUVhcGxQjC1f3Pyiho7csruneFxZt4xTatcSvvWQT5jnnUi1dwh7LaepXLdj32t6PXEKkrAC2TWQCaQyxmhFe4bimZvRwE 0.42337008 -zcDj4EZY8dAfTfsCFWGeUVPtfiy3qkQcPxDqTSXxqHzsLbh2DLqs3rVk1myEd7pkUmcBTVAqE6Q8NfyfY4gooPpT4BPLV3p 0.42166579 -zchcgx3265hHde72mXxKJ7xvecPqyk2kms1HnJvgemxwXWyUdLM4zqrEXBFPQbyRhqfrPtRFcf1kFAxTG71R8uL5iYRmqkL 0.40946013 -zcWWeDDdsQTJamQ8EoCYRkRxDKjmJCzMoffGgtALfGVsagH8czpeC59bYcAFFd5RrAYERLZe5vVuF5UaqsNetufvrVXAe5L 0.40264022 -zcQ5pc4dx69ZVazrzZfJCH3DeQBxNDJbNG3A7jFpx8PoVuCXVxW1mu49mAqEBozRSdAv9HDk63ZnsAjxAJaP5DvyqavQKQS 0.38585126 -zcLSeubnjQA3GCPb35ZRicaCo3eJ5BuF1d3iH3m31YQHeqepw8JBDCK1TzapD4eDw544sKVYVCjEhptfFxKBzDo9cto5Gyz 0.38541081 -zcFvEfiyav52tAHi39AJXikLp1sxGBq98zy12EYK9F8B9n2oW8aYPfFDMT3ARCrkUNZDxHgQMqE6G7t8MqDvoEjr8Wi4bLT 0.38095029 -zcCkxaZ91H5LeuWUAPVKkDMt5SzPhaxGfTNVusdCMwxGrW7BvdZXgcDNouekRgAWv3HZn19UUT2yednVufmFaPPcBGnH5Fe 0.37951503 -zcGQZZ4j5kuqcLJ2SqDtJgV5xtvQqKzndckgF4ndnJH6bbKneVk3vPf6ztEHaawNqSfuEYEX6FbEeFa6dyWQVN1u9D5bxkT 0.37830015 -zcY8uBpdBsTCHwE546PZm3mexvTku9RrmUUQLuWXjGdiVLBnGrZY144WRQssRVfbcmyNLmxmPRQhetmPHDWmCRWnmybjsyK 0.36709177 -zcKZoTVMkf3NpQqF8R4vyb9LN6mw8ZsE8WWirZLNN4hPdjBCibUAfahmM2jgbke3CCjAMWVUoPSiVD14cKrxqKTFXBMem9J 0.35699480 -zcEGhCEVG5oehipZkWwdXQ4FLeHdhE2SRD8FmMhPhrZiEKEnvx4CnGBa6CEh2kPhdzyTCm51X85uobRG4GX2cHbY6HyVR37 0.35656349 -zcZMCug4bcToufcRKxk2qrkdnBioaco212HRtk6qoQWXanwJzXvmbAu7aet5D7RHkFM6L4pWh9E2JTf3akY7pVb7x27VvMe 0.35215211 -zcVSmq13qb1wMSRJUtUDiX7yJRNoxETeeFDzikoSWgjSCF9hXmJDx4p3AyWfwjpqgbCkp1Auyv2Vj4UQvkuk8Ve7vGLp14K 0.34691471 -zcKXk1BwZRhBshAw2n4tdhS657K11izxArDsAcxDkW28FtwfD7P7HhgCfm5kMchKyd3vpuAhCYvetd75MZAyZznbUQPzHQ4 0.34103895 -zcY13TG6D15WCABXZ6Lg9N8WeGeUfUgQhCZbkWkvmhyWJkLmYL6zG6GxA7krNY8c5zut8wZQTBxHu5tDCkfWkxQ5LbGnXsT 0.33887093 -zcaenwiLxJRFniiNNX6SsdDBiqD8Cf9aWcUXJc3LWBgyoeVmKBvPKawCAWXYe54J3J1oxFFyDESJTWNPy299VEt7inj9Qca 0.33032197 -zcbVHNxbPHEVHixm3pm4FSzADeV5SdngmWfLghGH99TdCvcY7MxH4gxQoVfSMo9QRtwpQL7mPjKiMuusV8qzjz6n5yTL8ww 0.32513040 -zcLHUfzQx8V1V4cvFhSnRZU3wq7ue15owCF2foWnezqrV5z7wfHvbf2vQJfyygtiwbkxevNt8faxTndb9Jf9MYvJbj1QgZf 0.32442221 -zcEpp5yq3BLmBvnd98pfBuPgu4RPPHQN7rKK8U22CZ5ggp1AiHzdzgX69o2czNCHpBTNgXjxLpauMvAbScftzcgB3QRL7qm 0.31697240 -zcLZExtZMfV947KbSWRSEQTC2jBjahrqz91TLK1thLXXgYm2uassVCMNfWjXWnFTL1DcsvX1FDeDSxDmLS8BiLjePMiXHaN 0.31466647 -zcRahi8pVEo2FeB9EmhPC4FUTU7oJPe3qEN7N5tD87kMYywUzcQ8R6Ss6EFYYAuqSCY4cDhjvJAAYfpNtpgk53CL5PtXTN2 0.30020259 -zccmHPRXKaBP4gZSqnFhxccR8s8PSyQKk7zjsXUmEVoDzTFK6gfRZPwJw4Jk2Z9AW87kddRbtsncuMuoQfFEMcwojvpUCAP 0.29490782 -zcCsJn8ZSLWfVMVu2iYTq8YbZwRnTtmiB5bn6UpD7BB2UXjGWAPumMp1wRbBraY5S31fbULtXJba5VhWkRd9ArKsqDCTXbW 0.28961367 -zcc9sbD4piR2VsrxjxbVTes9fxXgaxqXggRZT8oNYpAT49LTdb5ZvNzD6JioF6U28977ACS66xTubkHgBBEVijPZN35sUzn 0.28430453 -zchDgsUbz3BG5BsZefPn553vTsX5yirrw3pXwfa74EdEGM2NBh4vg34jAh28ci3xn5F3VSpTU2uwu1oNoP9ZbEqYBCppCQe 0.28043455 -zcbpSQEVgcG95Hf3bhrD9KczVRHWhotpRgKE85SMfA3fgXie88nkqnjvWhUKeQdaTi27WALd6w2Ay8mTA6tsNJhoqTgUCL5 0.26438185 -zcgv4oUULnFjjr86V3SsqZrqSfG3pg59c31uDJvoqSDdQRMQwAsd1YXuvaGKiTxUadygc7bHgV3XLqYcSsahWzwdUUXC1jE 0.26167676 -zcYYTPr95HPSd2k3zHbLCpCs97BTSBsBPGcFSvGyJhDbkQ6DyHDiRHqSaMxU7rJSmiatxnyViMBU6Va77kDNcgi4v5bBD3P 0.26137495 -zc97HHri7CB76q4dcMoJTyP2pHnQ2mhrpsg6aX9Fh8TVFBqj8xBZ7wMFQH1dmwqhmy8yMbeCDLJUZM7qG3s7iAHXtp19oBe 0.23545696 -zcWrbLDHro1zYYSujvnZNmKKjdeLvkF2dk14yCqVijtpVasKJviBwTWiPnm5U7bYX8qijDZdpZogUs39SnF39eJeybtYMRU 0.23204621 -zcgRg7EiiemARsViwvw1z3SaeQNNudGY5DekEfgahtft74S7v2QsbsgwvrzonK9ALu2A4WdigL3CoxWjkxjvsD9RieMjnBQ 0.23185241 -zcNkxhKAx5dwkWiggycVPiFHb1o9cg4TGBVUosRjF1yebYFtyFybxe3UW2Z24M1fUtP7zmPEevE9UVQ45SDgJyUGzSvsjAv 0.22935472 -zcJcdNkKg49gayLQi9aPVvatA8ngGnCcSwFoENKbk1tCZPhn7S4ZR4YBHvTvatfYJR1aWK4obymbdapXo11VKzy4fMf9gDm 0.21418334 -zcD6tf6ZuXcmjEkqAG1MT7n3uv6Gs3aexBv4s2chR8szcFPQZEx9H6rV34qGBz2KGJifB2GBcMmGMHL2v7asEZhVwpeoRRE 0.21301490 -zcetu8BY2WLwWg9pGNWnKDShVv1zvy6PjCYW9uWykQa74rjyFF16JY1rLamvUwDEjdrAvF5v62T8v7D4RG6gjhPWpPigiCQ 0.20435158 -zc9EQecgPqarRJA1f1z3UvK6YXpNbhEDrXzsZtkXJQrCU74icdaACpRnq4DHfMeid3KyhFinWuLbs2LnuTTDUXK2kpGHQGy 0.20422690 -zcRBMrSHSKsgVXHWmVSsj2aCU6uFeanpRrDWEJt6ym3u3VhHWQeUqHXr7JtPmaEZ68rrCSyM6fJRLgoG2TYZiLshbx7XWNN 0.19896784 -zcHQQN3LtMsMFr3P2ZMSX6d1TJndQN6V7F1A6qbN4bCcNyynEYvtdXJxcPw4CrHL9GZapxo52dMdUtd6JEFM8eMCiCvWRDW 0.19629718 -zcNmXr3UAqr7ZrYHEeZJ8WksAjBUeWUq6sQSyeLFCoy99sQNUe1x5ZVd2njVSeMUxMF9V1Z2KGUceQGT6rNSGhDyEJMSF3U 0.19223682 -zcfvN562fWduPSDw1Ry1Pm458VZdwo1TKHHmJPkUQMzJJcZzn5h2HsFLcf4Ep1q4ZqnAf2FU2ZA23uQehXnZhobbxXR63d5 0.16633081 -zca8hvKaQWuD3BxgB7Dhi1mxovc9dVHnZUo14jf7poNiaQN63jiTz5hLSNjLbv7nF9funjLfdzV8GXQdkH14pQMWVcJH31Y 0.15730366 -zcW2yZUKShYGiCP4j6UarajDYLJZceWjzpureaa1iyhNQmqQcQv8gXyUa9mED1YenfdhPPNrJX8Wf9XivMhXHctrxRvfS2v 0.15518445 -zcfKKh61VpE16dV7hTJQnbWNN1mfYpHTqj56XdRWeLKG6L81fzqA1yLskAhkK29giowZpQX7NuMpaCJca8r1PAw8KWLAM3m 0.13943725 -zcYZXyLFBFNq8KEXSuW8G7XakUdeBbQoubRXiePGk3gRTAiCnTs7vwvcRqMK7sNYFvQi5xPEBtbUSRzbQQd4jzZa2eXyzPT 0.13676772 -zcFpGKuQSZ2G8ZWpgSGYAkQDD7TDBdYG4U21g3Mdmu9FCSNtMo8VxnVAFUPb8ZKyMKbJfiHbo2hQLFf8WAF4tkgnLxcisZG 0.13136988 -zcGoXeYrgSF9VNpFYK6zhPTPX2vd7C4LnhCU8Egesyu1VXgBayhEkpmgKRLGx78cPn7KchPrXb45KrvAH4TEwitcM8m4k3a 0.13067182 -zcEaj7VpTrvhu3HVaoNUimNQB9atQqKTo3bEcjkF7UGX2GyNg8tLxVYuZsi1XPqaWeNNtusa8BX7Juoq5hnyB4rHqGD99SL 0.12694722 -zcTWyj3NdkpabgMT5CYxDPp7upQ5qGND1WFcKFeFZRjsEw4Hp9843bq6nMjCFz1R92CnP69sAnZ9Q6iLb3HsnUjf1zdRZnw 0.12325854 -zcW4Xvmv2Bxj3wm4Ay9cp2o4YeHEU8Z6pozw8FHCS9niJ1qk5pyNZ3dFZLteUZfr8vBW7vYxUd4EZQwdqUT5r9hKADpDuB8 0.11932710 -zcC9Dn7rh1CcgDjdYeAhjbUMWb7xzc3XxLSpzL9j1o1Yv34GwL1VMUB32QDgXzkfz2YiJU2PdCKLVAwFLJBe9TniuNbUjb7 0.11871871 -zcALXqYKsNMMt1uEZZNA1qsyDkZ8zy98gcQVD1qM6TqfrH2UrQCgXdMDHKz9KZKEpjYynBGdivSUmZXfyiU3qUJhXCRrZrn 0.11717727 -zcP2xRWf1hSSMd5tQ8QBArV2JxwaRBAosshAVm5iyCwZue7WLy2ZtbDmH6PLfNkvRPykW5JF4CjrE4RBYv9ZUKJT4M8LBcb 0.11596974 -zcfBJTy8NbPhTGK1FJYpNqEtZxD34iGAXCgRqSsBfBmGys6sFDbcJHu5gzDRgkNmE75UtKBYNoiZ3p13vWFvQhr5Z1UiU1u 0.11193153 -zcbxqN1cg5J4JXFp9fbQH9iAqjin4Avq2DbEcEWcji74r9eUzqMdRjxKBXbVhRa7X6VB4Lk8RoV4E6cWECa6Uv5HgyhnM8y 0.10260291 -zcdARJeMUJmPMLvJHJWqdecMGosCcbXsLoK9J749pX3nYDkkqv57CxEBJsHDHw9BPxXf9L2TBk51fLN2nFRBw2qYozqCV9G 0.10001667 -zceQMJc8cYedcbDFXEuaLofojFWLp6vun6SLaJ26wwmJd3AFVbttysbnpsrqfa1ReUjwvPxAgXVbigt2kifL8CrncR7rhGe 0.09392734 -zceUD8QTJ9JKEmj4N6cGioLzAbb6EwJv7GcNG8EGBBirzW7J7WCHDohphm9YgYKU1d6xbKKc4GhCcuCBWmj5Xfya7AWnP6g 0.09104754 -zcZ4APYkB1xUMTFE58CkdMipZoioprVPTBeRZBRA1xTEZt3Nt4SZEt6snh2LprBDkEjbviVqDN5R5KrtXkA5DpnJj2ra5PB 0.09084450 -zcbVPSTHzmkJ7xACWd9ViCT47q21HYKirhqrE29JnUDvzGExLigVtjMbxPjuAzfXpUoybr7i3ZGVAhe31qJiZr2yUzvyowV 0.08797293 -zcLM9mf1SWg5Kn6L4F5rMSTPbXVLqsLEgcAipCsey67TcQKyrRruPFGYyknrJSXXrTZV6uQt1vye6xzUm87ifMQhwFmEFbj 0.08159772 -zcEVVYbWvT2XZ7Vwv1EoqFnSL6RcyE4s11PZbuXeY3gBWmsgCtmidQRMh6zjt82ykiyjrZeJQ4DCPoM1Lh7ZazsesevDN3z 0.08134030 -zcbxWeXT3ujiUEcDNfXUZkfkNFeWFKLM7EboZugjTSkwYk6Bo4SRM4SRZqJzeeTexib6f8mDmySNetro22V2DHsKycNLrJc 0.07929887 -zccqzaq1MUUue3aticfxwyQS3TNwEiUvQ38VqbsdihqsNsZvfNpBFBgYnmZiNJrYFAEK3mi9xQmLsJ2z5ods4bAjLg1r9S2 0.07626856 -zcNaTQ22PRE1MdKzrf7Bx5cLScYwx1UjCbspBxr3tLpWn91uDWwrVCmFLYgoiHCtsRGDnvMTMKFsWtm6dZsV9BAA89C5opu 0.07596657 -zcZiwou4j3gSfbHppMs9NGapDgKhnXGFMXqGPSzEGNo96AEsbHtLMqV9n4n4wjMCrKykEGz77MVzLSXiZiX3hrNcaQxodJK 0.06811364 -zcWz3Q2Jv48dBzBRgSeu5Z92dSPpbjVXFU3BYTJUxLNyvEjk2oS1vRs6qa5SypMzj3YYUCtBqZ3Rm1Tde9bRvoXkmjE2x2r 0.06717970 -zcMokMR1qYwLB68Xv6psuv8sJYw3YQqXf8p9ZjRKzwH3yqwo5u7T25pR7CVGFx1k8MxV5QXnD1DRYV5oXc7TGxhZEBvNZV5 0.06657492 -zcYk5gS3bFx661bVM6rZUw2RMJ3noHQdwQEzQQ7qjbmUZTeGzLPFvpiGgz9yBBEXxCtL4ikTASn1q5YK1YmKUBhGkgjqNAg 0.06645133 -zc9fTFL73ccq2R143q8W71NVP4jtXJsB2WhZ93fXV6FGTmCta1iHffB5mt9QWYcf19zEMptVFG3DdhgxXTUtGVnd8wVAH8K 0.06640802 -zcYkRApZZfEgkogzrZBPizi5c5YRJRPu86UtKCXku3VBjT31uCM9B3a2jr26qUurDYTbBvDvWPfsF9L8QhdUfPUusAvJi57 0.06520634 -zcNnJW7b2oKLExLxmUzvFHwUhWHNubDTKTpYdjC1Rk8UzR2Hzwib3CcwH9Yyi6SrTwKMYmyx2JWUcCsHGJZBRxDWQYaNN5e 0.06466773 -zcYyH8d5n3p8pPkMWgD2RwGQRNcYdbe27gWgVmZHMmGd8Xu72Tr7rYcFDYNeWn44axdgQtqpHPfUUqEM9r6p8Y1ZMP4TRaU 0.06228533 -zcQxmL8se6WQTTAUW4GfMLFBmhUbuCaahgPTD9bmjJiVaeXP9B7S35ZvLHnv7yPMZsayYwfwNnzq4KYhB1iF1jkGLkLfBjk 0.06224273 -zcfUJv8E28WVS71C8rnznL6UBDpz12WDRMNKbn5scaWSoKp1KGY5ez41rwMX4cLuyBfojCyrVp6qo64HbWbBmHynkXzJsej 0.06067893 -zcS6VzYBcsaEsM9qvcLrwn8SjUjrCKm64kdqTXUt9Rj2f4dffATnTFGUwG9p4UTL2X6j4qxhkq1qr5fdUT1ukuPFNu6iAeg 0.05920480 -zcFH3puBCJnxt5EiUA8ASvSXn7r2pYJwHYUscifBG1NhcCgrmm7BWJTddGtx999Kkv3qGmqJDxx3wARqguHRYYh2PgjtN68 0.05797143 -zcZ5dwFFnc6GjfAyyXxSXasyUmGR6CpiAPUFDoH7hLiAhRBwQwHbTJ2eMyxiqGKie7nT3gHmeR6tH3G8UgyidfNGrx2p9Zx 0.05598771 -zcdos6S33StCScGnCyBTXcvhSuT6SLKvvb5RnMam2m1H9bjWUcGxZ1FR5CXy8PZctvSQxYEfziMknYaT8WbZ559xTHs77An 0.05301738 -zcadXPJeWBzjmTfWLJhxJrDFTEWwgDzW2rwFUJMAdXwzCN4Vqbz361trGVae6Ma76NFTvKnWmZdomKqC1hKECbvPA3LnzQT 0.05084446 -zcDbz5VYXGYg14MoiBnZ7GL914gcYKK3Laqm8HW63oBqagRzAP5TEQwi2bwRJJADKsAmuKYac4RJ5EAJnL2fMdxWKE4Mptj 0.04917092 -zcFYAY8SR6nv15NDpywAFQNe3iKpzFGdY3VsboGNx9TKgXonESW9btLtN4vcm1YWx1GnAv7bBmEbyqR77tjFKvo31u3bckq 0.04838771 -zch6mE1d12iBwFjpVZHZfHMqM6wgfuM77VWvJzRFsFF8ahKkiybmPdJsCfxenqvG9h1X6EDL9oH5ceMNVCbYACm15G4wxXx 0.04448867 -zcMnYMPrpLm9W7LWGsM9V1Pf8aZyPNUxH9hUpKFGATkqNcVX27yay6kYkRQTiqTSiCxxbzvm8SFArcuGnsLkdCFA3Mf2CaC 0.04133326 -zcNEAo5VejsTzvqJ9wfdbYv39RQegjWMVF7Qb6jLPCq6yFpaS1SvTTDjWT1QEqJ3dpRyB3zR849oP4UeVXgrNwmeCqwenLe 0.03947846 -zcVHHtp5vTFDASaMoWXGYnPYq7n6xqwtYDFmN4F9UX4T88MscMJY9wQgyAMWpM4ttNXDyQHcFDGgegs3CBDQ9KNWvUXaaUA 0.03267893 -zcW56vAJBYz6YTsbqt9qNwCBgRmLahax7sPdZc15RPovvLyLzuA4Zuf4M2hK5heZvqY6xBhQMoicGCNwUjJHfkAsZQbEa6s 0.03054712 -zcCFBW3knWzE9Mdeq91xyBj4sPbDkHCatrRoLtmXGFvhrw9KGsddZyB6zjTehEfQtem7UpUNSPK2jN1UuEaGymAuts5Psoq 0.02519975 -zcdK3hJ9q8SaDSCnMw34eV2yRPJudtSHH8VrBjsG1JdQ4ZKxMrMXW1CSukf9tzc2hR1nDXkGXA3CnnpcyGvBprYK8hHo6j2 0.02384176 -zccFLTr7KpTmTF5uVQYjiB64JX7HkMuVfp1xrTQ3Us1WNGKey3LV99Hkoe5ckswebcc6fnQFhuB84MqhPWLVvUv9JYXqhyr 0.02285850 -zcMapykyDJeZCHT1UTaCHVQW2mhx9XwuBPFCMo4HWWd3bn8CTdS32ftTFamL2uC7ZFy6XJRAs3Nr6F3FWxSXtg7ascWdGVq 0.02215891 -zcQyyT4SZHqraAy329UR2NoNvgheDNfUcJkxNp19qJ3zPtV34aRRY7UQH6x2bcpHgvhe8F17udtmozyZH9YQqVYagT7W3pu 0.02166958 -zcg7dVwGFFGBSjSAswcaoFvs6QV4T2dNEz6LEasRXzAHUq5ugEmn2zw7k3kRqcPjA6TksDMeHf9W2XwgWPiq8hkpjJS9KF4 0.02138292 -zcesKmbs5LdLUB6ToCP3zNzCvk2s8ppWB9iondvVGQQjeWhAtfSiFjDnKgGniYCiydxpTc3hxLPZf7Twa9fN8ZHyJh6t3DA 0.02061743 -zcNxGp2ZxzPjpaNC3TJHrGHt6cqWaWHezx5oeRtbobdfXeKWiGNSgVxQAPtL8zrPTsHkayX3HsBjpN1v9pYNsCDwUidju6E 0.01781090 -zccjmBgwEAweE9WUiyTCmqUHLfnPxoV3phLFrZ9Qoa39aUYf3WkAjWPVgzz9oVjwyuJLSdF6mkUvGDa7LH9HnTPBKeuo9ci 0.01754414 -zcgqGEJhK1YecezXU75UUZY2L7Q3xbQ1R7381C9MMgLoVJLMQhPXCKh8gZ15hKz9W6A9srbtin5d5wVPRmWjipxx1fMdHfk 0.01643947 -zcLXzNo9p7ZNCDVtQNmRyTVcLMovtRQTuWEUMu19h5nYqdvfjKaQbzXkTmTTGwDNEp8ewMTs4q54BEfZsU2ZM7bLek2iD8y 0.01635094 -zceUhkwY6cpRyzfDKqFYutmyp4yV5ojqraFn94kfYuTRJ2jGo6ezE4ztr7qQYqhDLMxwPsUUs2EhMb9MWBWd9U2AWgFd2rw 0.01604043 -zcao1fctbra5zbHuzVKfn56EPBHvsdQHUj4vbXsx7qB5UrPBpRx5QNGEkduxJMm7K5A4YfunVzzPixn2CQDTSMwXXzJekJF 0.01429152 -zcJzYZLrSEdKUUgbrSuyHhmpMDCtuQUwCxLGJhRuSUGuKpYXYeFBchkcpYvse9sEpZD4VnzjTjGjKaW5x2RiHiwchnUsXz8 0.01131670 -zc9Tn2fNKuYTA9duwpRVmXFZyH3N6thguoiAXxr5Gvq8159LR1db6mnEoypQdCz2w92w4wPE5dLgoRvJ7sZEHdnpc6nrfbr 0.01078443 -zcgfNnd91e1SStDC1qi4tse5jJyzKWKKqrUKiYK7jAyGvGvgdvPx1noHYPT7TFuK8KvkjzMuinCUNN7Mek9f38XpNvKXUBh 0.01023136 -zcLMSrGT4Fi9Nrrf5MgvXMLn6ohe6tZs9HtRXh1pRkmtvXnJhAZdPR5uBtm8TrwUK4dJVCqBwZ78CCfBjkjkxtJkSkbEK2D 0.01017816 -zcCc1tmRJ6kZLfvQCW55bZDWU2Cf92sYis1Z1Ax91h33oZf4afuLWRKoB7stiedDrq6R3793cjv2p1wReiL5ievg1bmsfYu 0.00988874 -zcHX2Th8W3k2JX25zKGe23Tv1Avp9yMZirYgh8F9NmiVyFo4CqxpSZxUURZoEkgnpAjJaCJ8cKa2FEKLyZyA11ystyGGTaR 0.00595513 -zcG93ferV85GjphQEzaAgQh666VQPMTLioJZTpjPZBZCwNMwmJJujAGK4r8e6SW9mCUDE4DLFSzPei8JJUQvFEJxnET827D 0.00589895 -zcgJ37hJCs1EMumzpx7gMxFL6dnUQrFrC4WCBqjjXQwk2FHE2SkLoDWCE5dfCKDNpa4oywkRYvMMCY2TesQXGt1ga6wbkqz 0.00517659 -zcYfApyXiD9vYW86ruykToDRF5GVzFQ7SnYqNgdXEF5AQUTDGvkTR1p5sFA79QLzuiVVFusgazeatC3ujeH6Z62F7TJ3VzY 0.00509498 -zcSoGfGho3muy5jVAyqaXnfSnMv8vWfjWVotF5WK8qHtcuf3TysoV4iizrC68U8PrYGRipvZFdS4XaVqn2CEqb8GHyHNn3b 0.00235127 -zcgUWcZfzVFk4VKKUqVwWr2sb2pfYF9YLQ6iKDYtUEseLnN6LknbeGvYNnj7TyXJpyUwXnd2vPpU8jYF6FkGhgrw7vctK88 0.00168853 -zcKPfFNpncT2s9GHJJ1MBKQERHRHkKaBFQUMj3v3eou835wWa7dFEZMxPEpVWkPDvST8yNvPbDirjP3CktU8ohBC1EFi2pY 0.00122527 -zcUa9kGH1PJWXbvL1qWTHpRfDtam3J8SCGzdYG57TeA1E1hLTNjexJpCUass91Hm3i8CCNaqsLqyacirwqsKY7NhuEbSAtF 0.00098275 -zcSAhm6Du3Zpx7iU8v3z7SSXtYk6LGdXho21H92H1qU16VMH1EUaAbJSW3hN4EgjTwAm4rwmibTF6p4nVfFar5ua6xKepen 0.00071656 -zcJS7BmeuFhyFpxNyhkr4Ho3HuoHcZV6USEEMPPDAS9JfmZ5htWdTedeAGCYt8LDF3L7rRiiHvxg428KyjJvK52B2C3WiFT 0.00070148 -zcE4JfSy2ppywrQmomwEzbDBRjh9vkhZAL6F1og4QPE6Bna61iiZ4DtjTU73AX1785yTeSJ6FB15oznrztPXz6fU4N5oEMa 0.00037565 -zcdFs9jwXtnDRD36MWiHUv6sZGqQ3WmgHFBdiNv45wryPFWz83Jk928j9LNrTpz55Tjhppg5CjBEwGD8afgzcXLsR8B6YR1 0.00027618 -zcDRrSy759bWAFoof5YQFVEEtZf3DN5gxwNmF7smab5HpmB1ZJ5ZrrNhm6jGcY9vt1D5exDTFwY8z8dfJ3VBvfWqKT55Rmn 0.00009672 -zcTxDwTtsZmsL8J8g8Bc79uQoMW3TAumqmUK4vyHSo99ts17oS5ezLjfGwrDV1sH5VoXFjm1jPbVagYtidwd6HKS8LL89cn 0.00008582 -zcfdmBMvfTMnh9GD6QPq31MCL9uJm87QQoFkWTUCWvnEyBfSwMpZ9PDWjVj1Ru7nKiqRuTpoeBQQLvJjdvL5F77uaWuVGjb 0.00001583 - - From 579914d705de435d0544b95aebf4de4765d56380 Mon Sep 17 00:00:00 2001 From: webworker01 Date: Fri, 24 May 2019 04:02:50 +0000 Subject: [PATCH 05/16] Refactoring --- libs/paymentProcessor.js | 1748 +++++++++++++++++++------------------- 1 file changed, 893 insertions(+), 855 deletions(-) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index cda262f..741aa71 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -7,7 +7,7 @@ var async = require('async'); var Stratum = require('stratum-pool'); var util = require('stratum-pool/lib/util.js'); -module.exports = function(logger){ +module.exports = function(logger) { var poolConfigs = JSON.parse(process.env.pools); @@ -50,8 +50,12 @@ function SetupForPool(logger, poolOptions, setupFinished) { var displayBalances = false; var sendingTXFeeSats = 10000; + var coinPrecision; var opidCount = 0; var opids = []; + var magnitude; + var minPaymentSatoshis; + var paymentInterval; // zcash team recommends 10 confirmations for safety from orphaned blocks var minConfShield = Math.max((processingConfig.minConf || 10), 1); // Don't allow 0 conf transactions. @@ -91,19 +95,14 @@ function SetupForPool(logger, poolOptions, setupFinished) { var daemon = new Stratum.daemon.interface([processingConfig.daemon], function(severity, message){ logger[severity](logSystem, logComponent, message); }); + var redisClient = redis.createClient(poolOptions.redis.port, poolOptions.redis.host); // redis auth if enabled if (poolOptions.redis.password) { redisClient.auth(poolOptions.redis.password); } - var magnitude; - var minPaymentSatoshis; - var coinPrecision; - - var paymentInterval; - - function validateAddress (callback){ + function validateAddress(callback) { daemon.cmd('validateaddress', [poolOptions.address], function(result) { if (result.error){ logger.error(logSystem, logComponent, 'Error with payment processing daemon ' + JSON.stringify(result.error)); @@ -121,7 +120,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { }, true); } - function validateTAddress (callback) { + function validateTAddress(callback) { daemon.cmd('validateaddress', [poolOptions.tAddress], function(result) { if (result.error){ logger.error(logSystem, logComponent, 'Error with payment processing daemon ' + JSON.stringify(result.error)); @@ -139,36 +138,34 @@ function SetupForPool(logger, poolOptions, setupFinished) { }, true); } - function validateZAddress (callback) { + function validateZAddress(callback) { daemon.cmd('z_validateaddress', [poolOptions.zAddress], function(result) { if (result.error){ logger.error(logSystem, logComponent, 'Error with payment processing daemon ' + JSON.stringify(result.error)); callback(true); - } - else if (!result.response || !result.response.ismine) { + } else if (!result.response || !result.response.ismine) { logger.error(logSystem, logComponent, 'Daemon does not own pool address - payment processing can not be done with this daemon, ' + JSON.stringify(result.response)); callback(true); - } - else{ + } else { callback() } }, true); } - function getBalance(callback){ - daemon.cmd('getbalance', [], function(result){ - if (result.error){ + function getBalance(callback) { + daemon.cmd('getbalance', [], function(result) { + if (result.error) { return callback(true); } + try { var d = result.data.split('result":')[1].split(',')[0].split('.')[1]; magnitude = parseInt('10' + new Array(d.length).join('0')); minPaymentSatoshis = parseInt(processingConfig.minimumPayment * magnitude); coinPrecision = magnitude.toString().length - 1; - } - catch(e){ + } catch(e) { logger.error(logSystem, logComponent, 'Error detecting number of satoshis in a coin, cannot do payment processing. Tried parsing: ' + result.data); return callback(true); } @@ -176,11 +173,12 @@ function SetupForPool(logger, poolOptions, setupFinished) { }, true, true); } - function asyncComplete(err){ - if (err){ + function asyncComplete(err) { + if (err) { setupFinished(false); return; } + if (paymentInterval) { clearInterval(paymentInterval); } @@ -219,20 +217,20 @@ function SetupForPool(logger, poolOptions, setupFinished) { } //get t_address coinbalance - function listUnspent (addr, notAddr, minConf, displayBool, callback) { + function listUnspent(addr, notAddr, minConf, displayBool, callback) { if (addr !== null) { var args = [minConf, 99999999, [addr]]; } else { addr = 'Payout wallet'; var args = [minConf, 99999999]; } + daemon.cmd('listunspent', args, function (result) { if (!result || result.error || result[0].error) { logger.error(logSystem, logComponent, 'Error with RPC call listunspent '+addr+' '+JSON.stringify(result[0].error)); callback = function (){}; callback(true); - } - else { + } else { var tBalance = parseFloat(0); if (result[0].response != null && result[0].response.length > 0) { for (var i = 0, len = result[0].response.length; i < len; i++) { @@ -251,14 +249,13 @@ function SetupForPool(logger, poolOptions, setupFinished) { } // get z_address coinbalance - function listUnspentZ (addr, minConf, displayBool, callback) { + function listUnspentZ(addr, minConf, displayBool, callback) { daemon.cmd('z_getbalance', [addr, minConf], function (result) { if (!result || result.error || result[0].error) { logger.error(logSystem, logComponent, 'Error with RPC call z_getbalance '+addr+' '+JSON.stringify(result[0].error)); callback = function (){}; callback(true); - } - else { + } else { var zBalance = parseFloat(0); if (result[0].response != null) { zBalance = coinsRound(result[0].response); @@ -272,15 +269,19 @@ function SetupForPool(logger, poolOptions, setupFinished) { } //send t_address balance to z_address - function sendTToZ (callback, tBalance) { - if (callback === true) + function sendTToZ(callback, tBalance) { + if (callback === true) { return; + } + if (tBalance === NaN) { logger.error(logSystem, logComponent, 'tBalance === NaN for sendTToZ'); return; } - if ((tBalance - sendingTXFeeSats) <= 0) + + if ((tBalance - sendingTXFeeSats) <= 0) { return; + } // do not allow more than a single z_sendmany operation at a time if (opidCount > 0) { @@ -311,18 +312,23 @@ function SetupForPool(logger, poolOptions, setupFinished) { } // send z_address balance to t_address - function sendZToT (callback, zBalance) { + function sendZToT(callback, zBalance) { if (privateChain) { return; } - if (callback === true) + + if (callback === true) { return; + } + if (zBalance === NaN) { logger.error(logSystem, logComponent, 'zBalance === NaN for sendZToT'); return; } - if ((zBalance - sendingTXFeeSats) <= 0) + + if ((zBalance - sendingTXFeeSats) <= 0) { return; + } // do not allow more than a single z_sendmany operation at a time if (opidCount > 0) { @@ -332,8 +338,9 @@ function SetupForPool(logger, poolOptions, setupFinished) { var amount = satoshisToCoins(zBalance - sendingTXFeeSats); // unshield no more than 100 ZEC at a time - if (amount > 100.0) + if (amount > 100.0) { amount = 100.0; + } var params = [poolOptions.zAddress, [{'address': poolOptions.tAddress, 'amount': amount}]]; daemon.cmd('z_sendmany', params, @@ -343,8 +350,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { logger.error(logSystem, logComponent, 'Error trying to send z_address coin balance to payout t_address.'+JSON.stringify(result[0].error)); callback = function (){}; callback(true); - } - else { + } else { var opid = (result.response || result[0].response); opidCount++; opids.push(opid); @@ -395,6 +401,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { logger.warning(logSystem, logComponent, 'Clearing operation ids due to empty result set.'); } } + // loop through op-ids checking their status ops.forEach(function(op, i){ // check operation id status @@ -482,6 +489,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { opidTimeout = setTimeout(checkOpids, opid_interval); return; } + // clear results for completed operations daemon.batchCmd(batchRPC, function(error, results){ if (error || !results) { @@ -499,6 +507,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { opidTimeout = setTimeout(checkOpids, opid_interval); }); }; + // check for completed operation ids daemon.cmd('z_getoperationstatus', null, function (result) { var err = false; @@ -555,10 +564,61 @@ function SetupForPool(logger, poolOptions, setupFinished) { return count > 1; } + var validateAddress = async function(address, callback) { + let poolZAddressPrefix = poolOptions.zAddress.substring(0,2); + var isValid = false; + + if (privateChain) { + daemon.cmd('z_validateaddress', [address], function (results) { + isValid = results.filter(function (r) { + if ( (poolOptions.coin.sapling || poolOptions.coin.sapling > 0) && poolZAddressPrefix == 'zs') { + return (r.response.isvalid && r.response.type == 'sapling'); + } else if ( poolZAddressPrefix == 'zc') { + return (r.response.isvalid && r.response.type == 'sprout'); + } else { + return r.response.isvalid; + } + }).length > 0; + //authCallback(isValid); + }); + } else { + daemon.cmd('validateaddress', [address], function (results) { + isValid = results.filter(function (r) { + return r.response.isvalid + }).length > 0; + //authCallback(isValid); + }); + } + + if (isValid) { + return address; + } else { + return (poolOptions.invalidAddress || poolOptions.address); + } + }; + + var getProperAddress = function(address) { + let poolZAddressPrefix = poolOptions.zAddress.substring(0,2); + let minerAddressLength = address.replace(/[^0-9a-z]/gi, '').length; + let minerAddressPrefix = address.substring(0,2); + + if (privateChain && poolZAddressPrefix == 'zs' && minerAddressLength == 78 && minerAddressPrefix == 'zs') { + //validate as sapling + return address; + } else if (privateChain && poolZAddressPrefix == 'zc' && minerAddressLength == 95 && minerAddressPrefix == 'zc') { + //validate as sprout + return address; + } else if (privateChain || address.length >= 40 || address.length <= 30) { + return (poolOptions.invalidAddress || poolOptions.address); + } else { + return address; + } + }; + /* Deal with numbers in smallest possible units (satoshis) as much as possible. This greatly helps with accuracy when rounding and whatnot. When we are storing numbers for only humans to see, store in whole coin units. */ - var processPayments = function(){ + var processPayments = function() { var startPaymentProcess = Date.now(); @@ -576,765 +636,675 @@ function SetupForPool(logger, poolOptions, setupFinished) { var startRPCTimer = function(){ startTimeRPC = Date.now(); }; var endRPCTimer = function(){ timeSpentRPC += Date.now() - startTimeRedis }; - async.waterfall([ - /* - Step 1 - build workers and rounds objects from redis - * removes duplicate block submissions from redis - */ - function(callback){ - startRedisTimer(); - redisClient.multi([ - ['hgetall', coin + ':balances'], - ['smembers', coin + ':blocksPending'] - ]).exec(function(error, results){ - endRedisTimer(); - if (error){ - logger.error(logSystem, logComponent, 'Could not get blocks from redis ' + JSON.stringify(error)); - callback(true); - return; - } - // build workers object from :balances - var workers = {}; - for (var w in results[0]){ - workers[w] = {balance: coinsToSatoshies(parseFloat(results[0][w]))}; + /* + Step 1 - build workers and rounds objects from redis + * removes duplicate block submissions from redis + */ + var buildWorkers = function(callback) { + startRedisTimer(); + redisClient.multi([ + ['hgetall', coin + ':balances'], + ['smembers', coin + ':blocksPending'] + ]).exec(function(error, results) { + endRedisTimer(); + if (error){ + logger.error(logSystem, logComponent, 'Could not get blocks from redis ' + JSON.stringify(error)); + callback(true); + return; + } + + // build workers object from :balances + var workers = {}; + for (var w in results[0]){ + workers[w] = {balance: coinsToSatoshies(parseFloat(results[0][w]))}; + } + + // build rounds object from :blocksPending + var rounds = results[1].map(function(r) { + var details = r.split(':'); + return { + blockHash: details[0], + txHash: details[1], + height: details[2], + minedby: details[3], + time: details[4], + duplicate: false, + serialized: r + }; + }); + + /* sort rounds by block hieght to pay in order */ + rounds.sort(function(a, b) { + return a.height - b.height; + }); + + // find duplicate blocks by height + // this can happen when two or more solutions are submitted at the same block height + var duplicateFound = false; + for (var i = 0; i < rounds.length; i++) { + if (checkForDuplicateBlockHeight(rounds, rounds[i].height) === true) { + rounds[i].duplicate = true; + duplicateFound = true; } - // build rounds object from :blocksPending - var rounds = results[1].map(function(r){ - var details = r.split(':'); - return { - blockHash: details[0], - txHash: details[1], - height: details[2], - minedby: details[3], - time: details[4], - duplicate: false, - serialized: r - }; - }); - /* sort rounds by block hieght to pay in order */ - rounds.sort(function(a, b) { - return a.height - b.height; + } + + // handle duplicates if needed + if (duplicateFound) { + var dups = rounds.filter(function(round){ return round.duplicate; }); + logger.warning(logSystem, logComponent, 'Duplicate pending blocks found: ' + JSON.stringify(dups)); + // attempt to find the invalid duplicates + var rpcDupCheck = dups.map(function(r){ + return ['getblock', [r.blockHash]]; }); - // find duplicate blocks by height - // this can happen when two or more solutions are submitted at the same block height - var duplicateFound = false; - for (var i = 0; i < rounds.length; i++) { - if (checkForDuplicateBlockHeight(rounds, rounds[i].height) === true) { - rounds[i].duplicate = true; - duplicateFound = true; + + startRPCTimer(); + + daemon.batchCmd(rpcDupCheck, function(error, blocks){ + endRPCTimer(); + if (error || !blocks) { + logger.error(logSystem, logComponent, 'Error with duplicate block check rpc call getblock ' + JSON.stringify(error)); + return; } - } - // handle duplicates if needed - if (duplicateFound) { - var dups = rounds.filter(function(round){ return round.duplicate; }); - logger.warning(logSystem, logComponent, 'Duplicate pending blocks found: ' + JSON.stringify(dups)); - // attempt to find the invalid duplicates - var rpcDupCheck = dups.map(function(r){ - return ['getblock', [r.blockHash]]; - }); - startRPCTimer(); - daemon.batchCmd(rpcDupCheck, function(error, blocks){ - endRPCTimer(); - if (error || !blocks) { - logger.error(logSystem, logComponent, 'Error with duplicate block check rpc call getblock ' + JSON.stringify(error)); - return; - } - // look for the invalid duplicate block - var validBlocks = {}; // hashtable for unique look up - var invalidBlocks = []; // array for redis work - blocks.forEach(function(block, i) { - if (block && block.result) { - // invalid duplicate submit blocks have negative confirmations - if (block.result.confirmations < 0) { - logger.warning(logSystem, logComponent, 'Remove invalid duplicate block ' + block.result.height + ' > ' + block.result.hash); + + // look for the invalid duplicate block + var validBlocks = {}; // hashtable for unique look up + var invalidBlocks = []; // array for redis work + blocks.forEach(function(block, i) { + if (block && block.result) { + // invalid duplicate submit blocks have negative confirmations + if (block.result.confirmations < 0) { + logger.warning(logSystem, logComponent, 'Remove invalid duplicate block ' + block.result.height + ' > ' + block.result.hash); + // move from blocksPending to blocksDuplicate... + invalidBlocks.push(['smove', coin + ':blocksPending', coin + ':blocksDuplicate', dups[i].serialized]); + } else { + // block must be valid, make sure it is unique + if (validBlocks.hasOwnProperty(dups[i].blockHash)) { + // not unique duplicate block + logger.warning(logSystem, logComponent, 'Remove non-unique duplicate block ' + block.result.height + ' > ' + block.result.hash); // move from blocksPending to blocksDuplicate... invalidBlocks.push(['smove', coin + ':blocksPending', coin + ':blocksDuplicate', dups[i].serialized]); } else { - // block must be valid, make sure it is unique - if (validBlocks.hasOwnProperty(dups[i].blockHash)) { - // not unique duplicate block - logger.warning(logSystem, logComponent, 'Remove non-unique duplicate block ' + block.result.height + ' > ' + block.result.hash); - // move from blocksPending to blocksDuplicate... - invalidBlocks.push(['smove', coin + ':blocksPending', coin + ':blocksDuplicate', dups[i].serialized]); - } else { - // keep unique valid block - validBlocks[dups[i].blockHash] = dups[i].serialized; - logger.debug(logSystem, logComponent, 'Keep valid duplicate block ' + block.result.height + ' > ' + block.result.hash); - } + // keep unique valid block + validBlocks[dups[i].blockHash] = dups[i].serialized; + logger.debug(logSystem, logComponent, 'Keep valid duplicate block ' + block.result.height + ' > ' + block.result.hash); } } - }); - // filter out all duplicates to prevent double payments - rounds = rounds.filter(function(round){ return !round.duplicate; }); - // if we detected the invalid duplicates, move them - if (invalidBlocks.length > 0) { - // move invalid duplicate blocks in redis - startRedisTimer(); - redisClient.multi(invalidBlocks).exec(function(error, kicked){ - endRedisTimer(); - if (error) { - logger.error(logSystem, logComponent, 'Error could not move invalid duplicate blocks in redis ' + JSON.stringify(error)); - } - // continue payments normally - callback(null, workers, rounds); - }); - } else { - // notify pool owner that we are unable to find the invalid duplicate blocks, manual intervention required... - logger.error(logSystem, logComponent, 'Unable to detect invalid duplicate blocks, duplicate block payments on hold.'); - // continue payments normally - callback(null, workers, rounds); } }); - } else { - // no duplicates, continue payments normally - callback(null, workers, rounds); + + // filter out all duplicates to prevent double payments + rounds = rounds.filter(function(round){ return !round.duplicate; }); + // if we detected the invalid duplicates, move them + if (invalidBlocks.length > 0) { + // move invalid duplicate blocks in redis + startRedisTimer(); + redisClient.multi(invalidBlocks).exec(function(error, kicked){ + endRedisTimer(); + if (error) { + logger.error(logSystem, logComponent, 'Error could not move invalid duplicate blocks in redis ' + JSON.stringify(error)); + } + // continue payments normally + callback(null, workers, rounds); + }); + } else { + // notify pool owner that we are unable to find the invalid duplicate blocks, manual intervention required... + logger.error(logSystem, logComponent, 'Unable to detect invalid duplicate blocks, duplicate block payments on hold.'); + // continue payments normally + callback(null, workers, rounds); + } + }); + } else { + // no duplicates, continue payments normally + callback(null, workers, rounds); + } + }); + } + + /* + Step 2 - check if mined block coinbase tx are ready for payment + * adds block reward to rounds object + * adds block confirmations count to rounds object + */ + var checkMined = function(workers, rounds, callback) { + // get pending block tx details + var batchRPCcommand = rounds.map(function(r){ + return ['gettransaction', [r.txHash]]; + }); + // get account address (not implemented at this time) + // is this needed? + batchRPCcommand.push(['getaccount', [poolOptions.address]]); + + startRPCTimer(); + daemon.batchCmd(batchRPCcommand, function(error, txDetails){ + endRPCTimer(); + if (error || !txDetails){ + logger.error(logSystem, logComponent, 'Check finished - daemon rpc error with batch gettransactions ' + JSON.stringify(error)); + callback(true); + return; + } + + var addressAccount = ""; + + // check for transaction errors and generated coins + txDetails.forEach(function(tx, i){ + if (i === txDetails.length - 1){ + if (tx.result && tx.result.toString().length > 0) { + addressAccount = tx.result.toString(); + } + return; } - }); - }, - - - /* - Step 2 - check if mined block coinbase tx are ready for payment - * adds block reward to rounds object - * adds block confirmations count to rounds object - */ - function(workers, rounds, callback){ - // get pending block tx details - var batchRPCcommand = rounds.map(function(r){ - return ['gettransaction', [r.txHash]]; - }); - // get account address (not implemented at this time) - // is this needed? - batchRPCcommand.push(['getaccount', [poolOptions.address]]); - - startRPCTimer(); - daemon.batchCmd(batchRPCcommand, function(error, txDetails){ - endRPCTimer(); - if (error || !txDetails){ - logger.error(logSystem, logComponent, 'Check finished - daemon rpc error with batch gettransactions ' + JSON.stringify(error)); - callback(true); + + var round = rounds[i]; + + // update confirmations for round + if (tx && tx.result) { + round.confirmations = parseInt((tx.result.confirmations || 0)); + } + + // look for transaction errors + if (tx.error && tx.error.code === -5){ + logger.warning(logSystem, logComponent, 'Daemon reports invalid transaction: ' + round.txHash); + round.category = 'kicked'; + return; + } else if (!tx.result.details || (tx.result.details && tx.result.details.length === 0)) { + logger.warning(logSystem, logComponent, 'Daemon reports no details for transaction: ' + round.txHash); + round.category = 'kicked'; + return; + } else if (tx.error || !tx.result) { + logger.error(logSystem, logComponent, 'Odd error with gettransaction ' + round.txHash + ' ' + JSON.stringify(tx)); return; } - var addressAccount = ""; + // get the coin base generation tx + var generationTx = tx.result.details.filter(function(tx){ + return tx.address === poolOptions.address; + })[0]; - // check for transaction errors and generated coins - txDetails.forEach(function(tx, i){ - if (i === txDetails.length - 1){ - if (tx.result && tx.result.toString().length > 0) { - addressAccount = tx.result.toString(); - } - return; - } - var round = rounds[i]; - // update confirmations for round - if (tx && tx.result) { - round.confirmations = parseInt((tx.result.confirmations || 0)); - } + if (!generationTx && tx.result.details.length === 1){ + generationTx = tx.result.details[0]; + } - // look for transaction errors - if (tx.error && tx.error.code === -5){ - logger.warning(logSystem, logComponent, 'Daemon reports invalid transaction: ' + round.txHash); - round.category = 'kicked'; - return; - } - else if (!tx.result.details || (tx.result.details && tx.result.details.length === 0)){ - logger.warning(logSystem, logComponent, 'Daemon reports no details for transaction: ' + round.txHash); - round.category = 'kicked'; - return; - } - else if (tx.error || !tx.result){ - logger.error(logSystem, logComponent, 'Odd error with gettransaction ' + round.txHash + ' ' + JSON.stringify(tx)); - return; - } - // get the coin base generation tx - var generationTx = tx.result.details.filter(function(tx){ - return tx.address === poolOptions.address; - })[0]; - if (!generationTx && tx.result.details.length === 1){ - generationTx = tx.result.details[0]; - } - if (!generationTx){ - logger.error(logSystem, logComponent, 'Missing output details to pool address for transaction ' + round.txHash); - return; - } + if (!generationTx){ + logger.error(logSystem, logComponent, 'Missing output details to pool address for transaction ' + round.txHash); + return; + } - // get transaction category for round - round.category = generationTx.category; + // get transaction category for round + round.category = generationTx.category; - // get reward for newly generated blocks - if (round.category === 'generate' || round.category === 'immature') { - var minerperc = 1; - if (poolOptions.coin.disablecb && poolOptions.rewardRecipients.length !== 0) { - for (var r in poolOptions.rewardRecipients) { - minerperc = minerperc - (poolOptions.rewardRecipients[r]/100); - } + // get reward for newly generated blocks + if (round.category === 'generate' || round.category === 'immature') { + var minerperc = 1; + if (poolOptions.coin.disablecb && poolOptions.rewardRecipients.length !== 0) { + for (var r in poolOptions.rewardRecipients) { + minerperc = minerperc - (poolOptions.rewardRecipients[r]/100); } - poolperc = roundTo(1 - minerperc,4); - round.reward = coinsRound(parseFloat(generationTx.amount*minerperc || generationTx.value*minerperc)); } - //console.log(round.reward); - }); + poolperc = roundTo(1 - minerperc,4); + round.reward = coinsRound(parseFloat(generationTx.amount*minerperc || generationTx.value*minerperc)); + } + //console.log(round.reward); + }); - var canDeleteShares = function(r){ - for (var i = 0; i < rounds.length; i++){ - var compareR = rounds[i]; - if ((compareR.height === r.height) - && (compareR.category !== 'kicked') - && (compareR.category !== 'orphan') - && (compareR.serialized !== r.serialized)){ - return false; - } + var canDeleteShares = function(r) { + for (var i = 0; i < rounds.length; i++){ + var compareR = rounds[i]; + if ((compareR.height === r.height) + && (compareR.category !== 'kicked') + && (compareR.category !== 'orphan') + && (compareR.serialized !== r.serialized)){ + return false; } + } + return true; + }; + + // only pay max blocks at a time + var payingBlocks = 0; + rounds = rounds.filter(function(r) { + // Don't count for payout before minConfirmations from config + if ( r.confirmations > -1 && r.confirmations < (minConfPayout*2) ) { + r.category = 'immature'; return true; - }; + } - // only pay max blocks at a time - var payingBlocks = 0; - rounds = rounds.filter(function(r){ - // Don't count for payout before minConfirmations from config - if ( r.confirmations > -1 && r.confirmations < (minConfPayout*2) ) { - r.category = 'immature'; + switch (r.category) { + case 'orphan': + case 'kicked': + r.canDeleteShares = canDeleteShares(r); + case 'immature': return true; - } + case 'generate': + payingBlocks++; + // if over maxBlocksPerPayment... + // change category to immature to prevent payment + // and to keep track of confirmations/immature balances + if (payingBlocks > maxBlocksPerPayment) + r.category = 'immature'; + return true; + default: + return false; + }; + }); - switch (r.category) { - case 'orphan': - case 'kicked': - r.canDeleteShares = canDeleteShares(r); - case 'immature': - return true; - case 'generate': - payingBlocks++; - // if over maxBlocksPerPayment... - // change category to immature to prevent payment - // and to keep track of confirmations/immature balances - if (payingBlocks > maxBlocksPerPayment) - r.category = 'immature'; - return true; - default: - return false; - }; - }); + // continue to next step in waterfall + callback(null, workers, rounds, addressAccount); + }); + } - // continue to next step in waterfall - callback(null, workers, rounds, addressAccount); - }); - }, - - - /* - Step 3 - lookup shares and calculate rewards - * pull pplnt times from redis - * pull shares from redis - * calculate rewards - * pplnt share reductions if needed - */ - function(workers, rounds, addressAccount, callback){ - // pplnt times lookup - var timeLookups = rounds.map(function(r){ - return ['hgetall', coin + ':shares:times' + r.height] + /* + Step 3 - lookup shares and calculate rewards + * pull pplnt times from redis + * pull shares from redis + * calculate rewards + * pplnt share reductions if needed + */ + var calculateRewards = function(workers, rounds, addressAccount, callback) { + // pplnt times lookup + var timeLookups = rounds.map(function(r){ + return ['hgetall', coin + ':shares:times' + r.height] + }); + startRedisTimer(); + redisClient.multi(timeLookups).exec(function(error, allWorkerTimes){ + endRedisTimer(); + if (error){ + callback('Check finished - redis error with multi get rounds time'); + return; + } + // shares lookup + var shareLookups = rounds.map(function(r){ + return ['hgetall', coin + ':shares:round' + r.height]; }); startRedisTimer(); - redisClient.multi(timeLookups).exec(function(error, allWorkerTimes){ + redisClient.multi(shareLookups).exec(function(error, allWorkerShares){ endRedisTimer(); if (error){ - callback('Check finished - redis error with multi get rounds time'); + callback('Check finished - redis error with multi get rounds share'); return; } - // shares lookup - var shareLookups = rounds.map(function(r){ - return ['hgetall', coin + ':shares:round' + r.height]; - }); - startRedisTimer(); - redisClient.multi(shareLookups).exec(function(error, allWorkerShares){ - endRedisTimer(); - if (error){ - callback('Check finished - redis error with multi get rounds share'); - return; - } - // error detection - var err = null; - var performPayment = false; + // error detection + var err = null; + var performPayment = false; - var notAddr = null; - if (requireShielding === true) { - notAddr = poolOptions.address; - } + var notAddr = null; + if (requireShielding === true) { + notAddr = poolOptions.address; + } - // calculate what the pool owes its miners - var feeSatoshi = coinsToSatoshies(fee); - var totalOwed = parseInt(0); - for (var i = 0; i < rounds.length; i++) { - // only pay generated blocks, not orphaned, kicked, immature - if (rounds[i].category == 'generate') { - totalOwed = totalOwed + coinsToSatoshies(rounds[i].reward) - feeSatoshi; - } - } - // also include balances owed - for (var w in workers) { - var worker = workers[w]; - totalOwed = totalOwed + (worker.balance||0); + // calculate what the pool owes its miners + var feeSatoshi = coinsToSatoshies(fee); + var totalOwed = parseInt(0); + for (var i = 0; i < rounds.length; i++) { + // only pay generated blocks, not orphaned, kicked, immature + if (rounds[i].category == 'generate') { + totalOwed = totalOwed + coinsToSatoshies(rounds[i].reward) - feeSatoshi; } + } + // also include balances owed + for (var w in workers) { + var worker = workers[w]; + totalOwed = totalOwed + (worker.balance||0); + } - //Check if private transaction already in progress - if (privateChain && opidCount > 0) { - logger.warning(logSystem, logComponent, 'Z Transaction already in progress, cannot send shares'); + //Check if private transaction already in progress + if (privateChain && opidCount > 0) { + logger.warning(logSystem, logComponent, 'Z Transaction already in progress, cannot send shares'); + return callback(true); + } + + // check if we have enough tAddress funds to begin payment processing + listunspenttype = privateChain ? 'Z' : 'T'; + listUnspentType(listunspenttype, poolOptions.zAddress, notAddr, minConfPayout, displayBalances, function (error, tBalance) { + if (error) { + logger.error(logSystem, logComponent, 'Error checking pool balance before processing payments.'); return callback(true); + } else if (tBalance < totalOwed) { + logger.error(logSystem, logComponent, 'Insufficient [' + listunspenttype + '] funds ('+satoshisToCoins(tBalance) + ') to process payments (' + satoshisToCoins(totalOwed)+'); possibly waiting for txs.'); + performPayment = false; + } else if (tBalance > totalOwed) { + performPayment = true; + } + // just in case... + if (totalOwed <= 0) { + performPayment = false; + } + // if we can not perform payment + if (performPayment === false) { + // convert category generate to immature + rounds = rounds.filter(function(r){ + switch (r.category) { + case 'orphan': + case 'kicked': + case 'immature': + return true; + case 'generate': + r.category = 'immature'; + return true; + default: + return false; + }; + }); } - // check if we have enough tAddress funds to begin payment processing - listunspenttype = privateChain ? 'Z' : 'T'; - listUnspentType(listunspenttype, poolOptions.zAddress, notAddr, minConfPayout, displayBalances, function (error, tBalance) { - if (error) { - logger.error(logSystem, logComponent, 'Error checking pool balance before processing payments.'); - return callback(true); - } else if (tBalance < totalOwed) { - logger.error(logSystem, logComponent, 'Insufficient [' + listunspenttype + '] funds ('+satoshisToCoins(tBalance) + ') to process payments (' + satoshisToCoins(totalOwed)+'); possibly waiting for txs.'); - performPayment = false; - } else if (tBalance > totalOwed) { - performPayment = true; - } - // just in case... - if (totalOwed <= 0) { - performPayment = false; - } - // if we can not perform payment - if (performPayment === false) { - // convert category generate to immature - rounds = rounds.filter(function(r){ - switch (r.category) { - case 'orphan': - case 'kicked': - case 'immature': - return true; - case 'generate': - r.category = 'immature'; - return true; - default: - return false; - }; - }); + // handle rounds + rounds.forEach(function(round, i){ + var workerShares = allWorkerShares[i]; + if (!workerShares){ + err = true; + logger.error(logSystem, logComponent, 'No worker shares for round: ' + round.height + ' blockHash: ' + round.blockHash); + return; } - - // handle rounds - rounds.forEach(function(round, i){ - var workerShares = allWorkerShares[i]; - if (!workerShares){ - err = true; - logger.error(logSystem, logComponent, 'No worker shares for round: ' + round.height + ' blockHash: ' + round.blockHash); - return; - } - var workerTimesWithPoolIds = allWorkerTimes[i]; - var workerTimes = {}; - var maxTime = 0; - if (pplntEnabled === true) { - for (var workerAddressWithPoolId in workerTimesWithPoolIds){ - var workerWithoutPoolId = workerAddressWithPoolId.split('.')[0]; - var workerTimeFloat = parseFloat(workerTimesWithPoolIds[workerAddressWithPoolId]); - if (maxTime < workerTimeFloat) { - maxTime = workerTimeFloat; - } - if (!(workerWithoutPoolId in workerTimes)) { - workerTimes[workerWithoutPoolId] = workerTimeFloat; + var workerTimesWithPoolIds = allWorkerTimes[i]; + var workerTimes = {}; + var maxTime = 0; + if (pplntEnabled === true) { + for (var workerAddressWithPoolId in workerTimesWithPoolIds){ + var workerWithoutPoolId = workerAddressWithPoolId.split('.')[0]; + var workerTimeFloat = parseFloat(workerTimesWithPoolIds[workerAddressWithPoolId]); + if (maxTime < workerTimeFloat) { + maxTime = workerTimeFloat; + } + if (!(workerWithoutPoolId in workerTimes)) { + workerTimes[workerWithoutPoolId] = workerTimeFloat; + } else { + // add time from other instances with penalty + if (workerTimes[workerWithoutPoolId] < workerTimeFloat) { + workerTimes[workerWithoutPoolId] = workerTimes[workerWithoutPoolId] * 0.5 + workerTimeFloat; } else { - // add time from other instances with penalty - if (workerTimes[workerWithoutPoolId] < workerTimeFloat) { - workerTimes[workerWithoutPoolId] = workerTimes[workerWithoutPoolId] * 0.5 + workerTimeFloat; - } else { - workerTimes[workerWithoutPoolId] = workerTimes[workerWithoutPoolId] + workerTimeFloat * 0.5; - } - if (workerTimes[workerWithoutPoolId] > maxTime) { - workerTimes[workerWithoutPoolId] = maxTime; - } + workerTimes[workerWithoutPoolId] = workerTimes[workerWithoutPoolId] + workerTimeFloat * 0.5; + } + if (workerTimes[workerWithoutPoolId] > maxTime) { + workerTimes[workerWithoutPoolId] = maxTime; } } } - switch (round.category){ - case 'kicked': - case 'orphan': - round.workerShares = workerShares; - break; - - /* calculate immature balances */ - case 'immature': - var feeSatoshi = coinsToSatoshies(fee); - var immature = coinsToSatoshies(round.reward); - var totalShares = parseFloat(0); - var sharesLost = parseFloat(0); - - // adjust block immature .. tx fees - immature = Math.round(immature - feeSatoshi); - - // total up shares for round - for (var workerAddress in workerShares){ - var worker = workers[workerAddress] = (workers[workerAddress] || {}); - var shares = parseFloat((workerShares[workerAddress] || 0)); - // if pplnt mode - if (pplntEnabled === true && maxTime > 0) { - var tshares = shares; - var lost = parseFloat(0); - var address = workerAddress.split('.')[0]; - if (workerTimes[address] != null && parseFloat(workerTimes[address]) > 0) { - var timePeriod = roundTo(parseFloat(workerTimes[address] || 1) / maxTime , 2); - if (timePeriod > 0 && timePeriod < pplntTimeQualify) { - var lost = shares - (shares * timePeriod); - sharesLost += lost; - shares = Math.max(shares - lost, 0); - } + } + switch (round.category){ + case 'kicked': + case 'orphan': + round.workerShares = workerShares; + break; + + /* calculate immature balances */ + case 'immature': + var feeSatoshi = coinsToSatoshies(fee); + var immature = coinsToSatoshies(round.reward); + var totalShares = parseFloat(0); + var sharesLost = parseFloat(0); + + // adjust block immature .. tx fees + immature = Math.round(immature - feeSatoshi); + + // total up shares for round + for (var workerAddress in workerShares){ + var worker = workers[workerAddress] = (workers[workerAddress] || {}); + var shares = parseFloat((workerShares[workerAddress] || 0)); + // if pplnt mode + if (pplntEnabled === true && maxTime > 0) { + var tshares = shares; + var lost = parseFloat(0); + var address = workerAddress.split('.')[0]; + if (workerTimes[address] != null && parseFloat(workerTimes[address]) > 0) { + var timePeriod = roundTo(parseFloat(workerTimes[address] || 1) / maxTime , 2); + if (timePeriod > 0 && timePeriod < pplntTimeQualify) { + var lost = shares - (shares * timePeriod); + sharesLost += lost; + shares = Math.max(shares - lost, 0); } } - worker.roundShares = shares; - totalShares += shares; - } - - //console.log('--IMMATURE DEBUG--------------'); - //console.log('performPayment: '+performPayment); - //console.log('blockHeight: '+round.height); - //console.log('blockReward: '+Math.round(immature)); - //console.log('blockConfirmations: '+round.confirmations); - - // calculate rewards for round - var totalAmount = 0; - for (var workerAddress in workerShares){ - var worker = workers[workerAddress] = (workers[workerAddress] || {}); - var percent = parseFloat(worker.roundShares) / totalShares; - // calculate workers immature for this round - var workerImmatureTotal = Math.round(immature * percent); - worker.immature = (worker.immature || 0) + workerImmatureTotal; - totalAmount += workerImmatureTotal; } + worker.roundShares = shares; + totalShares += shares; + } - //console.log('----------------------------'); - break; + //console.log('--IMMATURE DEBUG--------------'); + //console.log('performPayment: '+performPayment); + //console.log('blockHeight: '+round.height); + //console.log('blockReward: '+Math.round(immature)); + //console.log('blockConfirmations: '+round.confirmations); + + // calculate rewards for round + var totalAmount = 0; + for (var workerAddress in workerShares){ + var worker = workers[workerAddress] = (workers[workerAddress] || {}); + var percent = parseFloat(worker.roundShares) / totalShares; + // calculate workers immature for this round + var workerImmatureTotal = Math.round(immature * percent); + worker.immature = (worker.immature || 0) + workerImmatureTotal; + totalAmount += workerImmatureTotal; + } - /* calculate reward balances */ - case 'generate': - var feeSatoshi = coinsToSatoshies(fee); - var reward = coinsToSatoshies(round.reward); - var totalShares = parseFloat(0); - var sharesLost = parseFloat(0); - - // adjust block reward .. tx fees - reward = Math.round(reward - feeSatoshi); - - // total up shares for round - for (var workerAddress in workerShares){ - var worker = workers[workerAddress] = (workers[workerAddress] || {}); - var shares = parseFloat((workerShares[workerAddress] || 0)); - // if pplnt mode - if (pplntEnabled === true && maxTime > 0) { - var tshares = shares; - var lost = parseFloat(0); - var address = workerAddress.split('.')[0]; - if (workerTimes[address] != null && parseFloat(workerTimes[address]) > 0) { - var timePeriod = roundTo(parseFloat(workerTimes[address] || 1) / maxTime , 2); - if (timePeriod > 0 && timePeriod < pplntTimeQualify) { - var lost = shares - (shares * timePeriod); - sharesLost += lost; - shares = Math.max(shares - lost, 0); - logger.warning(logSystem, logComponent, 'PPLNT: Reduced shares for '+workerAddress+' round:' + round.height + ' maxTime:'+maxTime+'sec timePeriod:'+roundTo(timePeriod,6)+' shares:'+tshares+' lost:'+lost+' new:'+shares); - } - if (timePeriod > 1.0) { - err = true; - logger.error(logSystem, logComponent, 'Time share period is greater than 1.0 for '+workerAddress+' round:' + round.height + ' blockHash:' + round.blockHash); - return; - } - worker.timePeriod = timePeriod; + //console.log('----------------------------'); + break; + + /* calculate reward balances */ + case 'generate': + var feeSatoshi = coinsToSatoshies(fee); + var reward = coinsToSatoshies(round.reward); + var totalShares = parseFloat(0); + var sharesLost = parseFloat(0); + + // adjust block reward .. tx fees + reward = Math.round(reward - feeSatoshi); + + // total up shares for round + for (var workerAddress in workerShares){ + var worker = workers[workerAddress] = (workers[workerAddress] || {}); + var shares = parseFloat((workerShares[workerAddress] || 0)); + // if pplnt mode + if (pplntEnabled === true && maxTime > 0) { + var tshares = shares; + var lost = parseFloat(0); + var address = workerAddress.split('.')[0]; + if (workerTimes[address] != null && parseFloat(workerTimes[address]) > 0) { + var timePeriod = roundTo(parseFloat(workerTimes[address] || 1) / maxTime , 2); + if (timePeriod > 0 && timePeriod < pplntTimeQualify) { + var lost = shares - (shares * timePeriod); + sharesLost += lost; + shares = Math.max(shares - lost, 0); + logger.warning(logSystem, logComponent, 'PPLNT: Reduced shares for '+workerAddress+' round:' + round.height + ' maxTime:'+maxTime+'sec timePeriod:'+roundTo(timePeriod,6)+' shares:'+tshares+' lost:'+lost+' new:'+shares); } + if (timePeriod > 1.0) { + err = true; + logger.error(logSystem, logComponent, 'Time share period is greater than 1.0 for '+workerAddress+' round:' + round.height + ' blockHash:' + round.blockHash); + return; + } + worker.timePeriod = timePeriod; } - worker.roundShares = shares; - worker.totalShares = parseFloat(worker.totalShares || 0) + shares; - totalShares += shares; } + worker.roundShares = shares; + worker.totalShares = parseFloat(worker.totalShares || 0) + shares; + totalShares += shares; + } - //console.log('--REWARD DEBUG--------------'); - //console.log('performPayment: '+performPayment); - //console.log('blockHeight: '+round.height); - //console.log('blockReward: ' + Math.round(reward)); - //console.log('blockConfirmations: '+round.confirmations); - - // calculate rewards for round - var totalAmount = 0; - for (var workerAddress in workerShares){ - var worker = workers[workerAddress] = (workers[workerAddress] || {}); - var percent = parseFloat(worker.roundShares) / totalShares; - if (percent > 1.0) { - err = true; - logger.error(logSystem, logComponent, 'Share percent is greater than 1.0 for '+workerAddress+' round:' + round.height + ' blockHash:' + round.blockHash); - return; - } - // calculate workers reward for this round - var workerRewardTotal = Math.round(reward * percent); - worker.reward = (worker.reward || 0) + workerRewardTotal; - totalAmount += workerRewardTotal; + //console.log('--REWARD DEBUG--------------'); + //console.log('performPayment: '+performPayment); + //console.log('blockHeight: '+round.height); + //console.log('blockReward: ' + Math.round(reward)); + //console.log('blockConfirmations: '+round.confirmations); + + // calculate rewards for round + var totalAmount = 0; + for (var workerAddress in workerShares){ + var worker = workers[workerAddress] = (workers[workerAddress] || {}); + var percent = parseFloat(worker.roundShares) / totalShares; + if (percent > 1.0) { + err = true; + logger.error(logSystem, logComponent, 'Share percent is greater than 1.0 for '+workerAddress+' round:' + round.height + ' blockHash:' + round.blockHash); + return; } + // calculate workers reward for this round + var workerRewardTotal = Math.round(reward * percent); + worker.reward = (worker.reward || 0) + workerRewardTotal; + totalAmount += workerRewardTotal; + } - //console.log('----------------------------'); - break; - } - }); - - // if there was no errors - if (err === null) { - callback(null, workers, rounds, addressAccount); - } else { - // some error, stop waterfall - callback(true); + //console.log('----------------------------'); + break; } + }); - }); // end funds check - });// end share lookup - }); // end time lookup - - }, + // if there was no errors + if (err === null) { + callback(null, workers, rounds, addressAccount); + } else { + // some error, stop waterfall + callback(true); + } + }); // end funds check + });// end share lookup + }); // end time lookup + } - /* - Step 4 - Generate RPC commands to send payments - When deciding the sent balance, it the difference should be -1*amount they had in db, - If not sending the balance, the differnce should be +(the amount they earned this round) - */ - function(workers, rounds, addressAccount, callback) { + /* + Step 4 - Generate RPC commands to send payments + When deciding the sent balance, it the difference should be -1*amount they had in db, + If not sending the balance, the differnce should be +(the amount they earned this round) + */ + var sendPayments = function(workers, rounds, addressAccount, callback) { - var tries = 0; - var trySend = function (withholdPercent) { + var tries = 0; + var trySend = function (withholdPercent) { - var addressAmounts = {}; - var balanceAmounts = {}; - var shareAmounts = {}; - var timePeriods = {}; - var minerTotals = {}; - var totalSent = 0; - var totalShares = 0; + var addressAmounts = {}; + var balanceAmounts = {}; + var shareAmounts = {}; + var timePeriods = {}; + var minerTotals = {}; + var totalSent = 0; + var totalShares = 0; - // track attempts made, calls to trySend... - tries++; + // track attempts made, calls to trySend... + tries++; - // total up miner's balances - for (var w in workers) { - var worker = workers[w]; - totalShares += (worker.totalShares || 0) - worker.balance = worker.balance || 0; - worker.reward = worker.reward || 0; - // get miner payout totals - var toSendSatoshis = Math.round((worker.balance + worker.reward) * (1 - withholdPercent)); - var address = worker.address = (worker.address || getProperAddress(w.split('.')[0])).trim(); - if (minerTotals[address] != null && minerTotals[address] > 0) { - minerTotals[address] += toSendSatoshis; - } else { - minerTotals[address] = toSendSatoshis; - } + // total up miner's balances + for (var w in workers) { + var worker = workers[w]; + totalShares += (worker.totalShares || 0) + worker.balance = worker.balance || 0; + worker.reward = worker.reward || 0; + // get miner payout totals + var toSendSatoshis = Math.round((worker.balance + worker.reward) * (1 - withholdPercent)); + var address = worker.address = (worker.address || getProperAddress(w.split('.')[0])).trim(); + if (minerTotals[address] != null && minerTotals[address] > 0) { + minerTotals[address] += toSendSatoshis; + } else { + minerTotals[address] = toSendSatoshis; } + } - // now process each workers balance, and pay the miner - for (var w in workers) { - var worker = workers[w]; - worker.balance = worker.balance || 0; - worker.reward = worker.reward || 0; - var toSendSatoshis = Math.round((worker.balance + worker.reward) * (1 - withholdPercent)); - var address = worker.address = (worker.address || getProperAddress(w.split('.')[0])).trim(); - // if miners total is enough, go ahead and add this worker balance - if (minerTotals[address] >= minPaymentSatoshis) { - totalSent += toSendSatoshis; - // send funds - worker.sent = satoshisToCoins(toSendSatoshis); - worker.balanceChange = Math.min(worker.balance, toSendSatoshis) * -1; - if (addressAmounts[address] != null && addressAmounts[address] > 0) { - addressAmounts[address] = coinsRound(addressAmounts[address] + worker.sent); - } else { - addressAmounts[address] = worker.sent; - } + // now process each workers balance, and pay the miner + for (var w in workers) { + var worker = workers[w]; + worker.balance = worker.balance || 0; + worker.reward = worker.reward || 0; + var toSendSatoshis = Math.round((worker.balance + worker.reward) * (1 - withholdPercent)); + var address = worker.address = (worker.address || getProperAddress(w.split('.')[0])).trim(); + // if miners total is enough, go ahead and add this worker balance + if (minerTotals[address] >= minPaymentSatoshis) { + totalSent += toSendSatoshis; + // send funds + worker.sent = satoshisToCoins(toSendSatoshis); + worker.balanceChange = Math.min(worker.balance, toSendSatoshis) * -1; + if (addressAmounts[address] != null && addressAmounts[address] > 0) { + addressAmounts[address] = coinsRound(addressAmounts[address] + worker.sent); } else { - // add to balance, not enough minerals - worker.sent = 0; - worker.balanceChange = Math.max(toSendSatoshis - worker.balance, 0); - // track balance changes - if (worker.balanceChange > 0) { - if (balanceAmounts[address] != null && balanceAmounts[address] > 0) { - balanceAmounts[address] = coinsRound(balanceAmounts[address] + satoshisToCoins(worker.balanceChange)); - } else { - balanceAmounts[address] = satoshisToCoins(worker.balanceChange); - } - } + addressAmounts[address] = worker.sent; } - - // track share work - if (worker.totalShares > 0) { - if (shareAmounts[address] != null && shareAmounts[address] > 0) { - shareAmounts[address] += worker.totalShares; + } else { + // add to balance, not enough minerals + worker.sent = 0; + worker.balanceChange = Math.max(toSendSatoshis - worker.balance, 0); + // track balance changes + if (worker.balanceChange > 0) { + if (balanceAmounts[address] != null && balanceAmounts[address] > 0) { + balanceAmounts[address] = coinsRound(balanceAmounts[address] + satoshisToCoins(worker.balanceChange)); } else { - shareAmounts[address] = worker.totalShares; + balanceAmounts[address] = satoshisToCoins(worker.balanceChange); } } } - // if no payouts...continue to next set of callbacks - if (Object.keys(addressAmounts).length === 0){ - callback(null, workers, rounds, []); - return; - } - - // do final rounding of payments per address - // this forces amounts to be valid (0.12345678) - var totalcoinstosend = 0; - for (var a in addressAmounts) { - addressAmounts[a] = coinsRound(addressAmounts[a]); - totalcoinstosend = totalcoinstosend + addressAmounts[a]; - } - - if (poolOptions.coin.disablecb && poolOptions.rewardRecipients.length !== 0) { - var totalbr = coinsRound(totalcoinstosend*(poolperc+1)); - //console.log(totalbr); - for (var r in poolOptions.rewardRecipients) { - var feetopay = coinsRound(totalbr*(poolOptions.rewardRecipients[r]/100)); - addressAmounts[r] = feetopay; + // track share work + if (worker.totalShares > 0) { + if (shareAmounts[address] != null && shareAmounts[address] > 0) { + shareAmounts[address] += worker.totalShares; + } else { + shareAmounts[address] = worker.totalShares; } } + } - //console.log(addressAmounts); - - // POINT OF NO RETURN! GOOD LUCK! - // WE ARE SENDING PAYMENT CMD TO DAEMON - - if (privateChain) { - // perform z_sendmany - - //Get total z balance - listUnspentZ (poolOptions.zAddress, minConfPayout, displayBalances, function (error, getBalance) { - zBalance = getBalance; - - //for now we'll reshape the addressAmounts variable here instead of hacking up where it's constructed in the rest of the code - zaddressAmounts = []; - sharetotal = 0; - for (var a in addressAmounts) { - sharetotal += addressAmounts[a]; - thisaddressamount = {address: a, amount: addressAmounts[a]}; - zaddressAmounts.push(thisaddressamount); - } - - keepInWallet = satoshisToCoins(zBalance - sendingTXFeeSats - (sharetotal * 100000000)); + // if no payouts...continue to next set of callbacks + if (Object.keys(addressAmounts).length === 0){ + callback(null, workers, rounds, []); + return; + } - zaddressAmounts.push({address: poolOptions.zAddress, amount: keepInWallet}); + // do final rounding of payments per address + // this forces amounts to be valid (0.12345678) + var totalcoinstosend = 0; + for (var a in addressAmounts) { + addressAmounts[a] = coinsRound(addressAmounts[a]); + totalcoinstosend = totalcoinstosend + addressAmounts[a]; + } - var rpccallTracking = 'z_sendmany ' + poolOptions.zAddress + ' ' + JSON.stringify(zaddressAmounts) + ' 1'; - logger.warning(logSystem, logComponent, rpccallTracking); + if (poolOptions.coin.disablecb && poolOptions.rewardRecipients.length !== 0) { + var totalbr = coinsRound(totalcoinstosend*(poolperc+1)); + //console.log(totalbr); + for (var r in poolOptions.rewardRecipients) { + var feetopay = coinsRound(totalbr*(poolOptions.rewardRecipients[r]/100)); + addressAmounts[r] = feetopay; + } + } - daemon.cmd('z_sendmany', [poolOptions.zAddress, zaddressAmounts], function(result) { - if (result.error) { - logger.error(logSystem, logComponent, 'Error sending Z payments ' + JSON.stringify(result.error)); - // payment failed, prevent updates to redis - callback(true); - return; - } else { - // make sure z_sendmany gives us back a opid - var opid = null; - if (result.response) { - opid = result.response; - } - if (opid != null) { - opidCount++; - // it worked, congrats on your pools payout ;) - logger.special(logSystem, logComponent, 'Sent ' + satoshisToCoins(totalSent) - + ' to ' + Object.keys(addressAmounts).length + ' miners; opid: '+opid); - - if (withholdPercent > 0) { - logger.warning(logSystem, logComponent, 'Had to withhold ' + (withholdPercent * 100) - + '% of reward from miners to cover transaction fees. ' - + 'Fund pool wallet with coins to prevent this from happening'); - } + //console.log(addressAmounts); - // save payments data to redis - var paymentBlocks = rounds.filter(function(r){ return r.category == 'generate'; }).map(function(r){ - return parseInt(r.height); - }); + // POINT OF NO RETURN! GOOD LUCK! + // WE ARE SENDING PAYMENT CMD TO DAEMON - var paymentsUpdate = []; - let paymentTime = Date.now(); - var paymentsData = {time:paymentTime, opid:opid, shares:totalShares, paid:satoshisToCoins(totalSent), miners:Object.keys(addressAmounts).length, blocks: paymentBlocks, amounts: addressAmounts, balances: balanceAmounts, work:shareAmounts}; - paymentsUpdate.push(['zadd', logComponent + ':payments', paymentTime, JSON.stringify(paymentsData)]); + if (privateChain) { + // perform z_sendmany + + //Get total z balance + listUnspentZ (poolOptions.zAddress, minConfPayout, displayBalances, function (error, getBalance) { + zBalance = getBalance; + + //for now we'll reshape the addressAmounts variable here instead of hacking up where it's constructed in the rest of the code + zaddressAmounts = []; + sharetotal = 0; + for (var a in addressAmounts) { + sharetotal += addressAmounts[a]; + thisaddressamount = {address: a, amount: addressAmounts[a]}; + zaddressAmounts.push(thisaddressamount); + } - callback(null, workers, rounds, paymentsUpdate); - } else { + keepInWallet = satoshisToCoins(zBalance - sendingTXFeeSats - (sharetotal * 100000000)); - clearInterval(paymentInterval); + zaddressAmounts.push({address: poolOptions.zAddress, amount: keepInWallet}); - logger.error(logSystem, logComponent, 'Error RPC sendmany did not return opid ' - + JSON.stringify(result) + 'Disabling payment processing to prevent possible double-payouts.'); + var rpccallTracking = 'z_sendmany ' + poolOptions.zAddress + ' ' + JSON.stringify(zaddressAmounts) + ' 1'; + logger.warning(logSystem, logComponent, rpccallTracking); - callback(true); - return; - } - } - }, true, true); - }); - } else { - // perform the sendmany operation .. addressAccount - var rpccallTracking = 'sendmany "" '+JSON.stringify(addressAmounts); - //console.log(rpccallTracking); - - daemon.cmd('sendmany', ["", addressAmounts], function (result) { - // check for failed payments, there are many reasons - if (result.error && result.error.code === -6) { - // check if it is because we don't have enough funds - if (result.error.message && result.error.message.includes("insufficient funds")) { - // only try up to XX times (Max, 0.5%) - if (tries < 5) { - // we thought we had enough funds to send payments, but apparently not... - // try decreasing payments by a small percent to cover unexpected tx fees? - var higherPercent = withholdPercent + 0.001; // 0.1% - logger.warning(logSystem, logComponent, 'Insufficient funds (??) for payments ('+satoshisToCoins(totalSent)+'), decreasing rewards by ' + (higherPercent * 100).toFixed(1) + '% and retrying'); - trySend(higherPercent); - } else { - logger.warning(logSystem, logComponent, rpccallTracking); - logger.error(logSystem, logComponent, "Error sending payments, decreased rewards by too much!!!"); - callback(true); - } - } else { - // there was some fatal payment error? - logger.warning(logSystem, logComponent, rpccallTracking); - logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error)); - // payment failed, prevent updates to redis - callback(true); - } - return; - } - else if (result.error && result.error.code === -5) { - // invalid address specified in addressAmounts array - logger.warning(logSystem, logComponent, rpccallTracking); - logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error)); - // payment failed, prevent updates to redis - callback(true); - return; - } - else if (result.error && result.error.message != null) { - // invalid amount, others? - logger.warning(logSystem, logComponent, rpccallTracking); - logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error)); + daemon.cmd('z_sendmany', [poolOptions.zAddress, zaddressAmounts], function(result) { + if (result.error) { + logger.error(logSystem, logComponent, 'Error sending Z payments ' + JSON.stringify(result.error)); // payment failed, prevent updates to redis callback(true); return; - } - else if (result.error) { - // unknown error - logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error)); - // payment failed, prevent updates to redis - callback(true); - return; - } - else { - - // make sure sendmany gives us back a txid - var txid = null; + } else { + // make sure z_sendmany gives us back a opid + var opid = null; if (result.response) { - txid = result.response; + opid = result.response; } - if (txid != null) { - + if (opid != null) { + opidCount++; // it worked, congrats on your pools payout ;) logger.special(logSystem, logComponent, 'Sent ' + satoshisToCoins(totalSent) - + ' to ' + Object.keys(addressAmounts).length + ' miners; txid: '+txid); + + ' to ' + Object.keys(addressAmounts).length + ' miners; opid: '+opid); if (withholdPercent > 0) { logger.warning(logSystem, logComponent, 'Had to withhold ' + (withholdPercent * 100) @@ -1348,16 +1318,16 @@ function SetupForPool(logger, poolOptions, setupFinished) { }); var paymentsUpdate = []; - var paymentsData = {time:Date.now(), txid:txid, shares:totalShares, paid:satoshisToCoins(totalSent), miners:Object.keys(addressAmounts).length, blocks: paymentBlocks, amounts: addressAmounts, balances: balanceAmounts, work:shareAmounts}; - paymentsUpdate.push(['zadd', logComponent + ':payments', Date.now(), JSON.stringify(paymentsData)]); + let paymentTime = Date.now(); + var paymentsData = {time:paymentTime, opid:opid, shares:totalShares, paid:satoshisToCoins(totalSent), miners:Object.keys(addressAmounts).length, blocks: paymentBlocks, amounts: addressAmounts, balances: balanceAmounts, work:shareAmounts}; + paymentsUpdate.push(['zadd', logComponent + ':payments', paymentTime, JSON.stringify(paymentsData)]); callback(null, workers, rounds, paymentsUpdate); - } else { clearInterval(paymentInterval); - logger.error(logSystem, logComponent, 'Error RPC sendmany did not return txid ' + logger.error(logSystem, logComponent, 'Error RPC sendmany did not return opid ' + JSON.stringify(result) + 'Disabling payment processing to prevent possible double-payouts.'); callback(true); @@ -1365,187 +1335,255 @@ function SetupForPool(logger, poolOptions, setupFinished) { } } }, true, true); - } - }; + }); + } else { + // perform the sendmany operation .. addressAccount + var rpccallTracking = 'sendmany "" '+JSON.stringify(addressAmounts); + //console.log(rpccallTracking); + + daemon.cmd('sendmany', ["", addressAmounts], function (result) { + // check for failed payments, there are many reasons + if (result.error && result.error.code === -6) { + // check if it is because we don't have enough funds + if (result.error.message && result.error.message.includes("insufficient funds")) { + // only try up to XX times (Max, 0.5%) + if (tries < 5) { + // we thought we had enough funds to send payments, but apparently not... + // try decreasing payments by a small percent to cover unexpected tx fees? + var higherPercent = withholdPercent + 0.001; // 0.1% + logger.warning(logSystem, logComponent, 'Insufficient funds (??) for payments ('+satoshisToCoins(totalSent)+'), decreasing rewards by ' + (higherPercent * 100).toFixed(1) + '% and retrying'); + trySend(higherPercent); + } else { + logger.warning(logSystem, logComponent, rpccallTracking); + logger.error(logSystem, logComponent, "Error sending payments, decreased rewards by too much!!!"); + callback(true); + } + } else { + // there was some fatal payment error? + logger.warning(logSystem, logComponent, rpccallTracking); + logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error)); + // payment failed, prevent updates to redis + callback(true); + } + return; + } + else if (result.error && result.error.code === -5) { + // invalid address specified in addressAmounts array + logger.warning(logSystem, logComponent, rpccallTracking); + logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error)); + // payment failed, prevent updates to redis + callback(true); + return; + } + else if (result.error && result.error.message != null) { + // invalid amount, others? + logger.warning(logSystem, logComponent, rpccallTracking); + logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error)); + // payment failed, prevent updates to redis + callback(true); + return; + } + else if (result.error) { + // unknown error + logger.error(logSystem, logComponent, 'Error sending payments ' + JSON.stringify(result.error)); + // payment failed, prevent updates to redis + callback(true); + return; + } + else { - // attempt to send any owed payments - trySend(0); - }, + // make sure sendmany gives us back a txid + var txid = null; + if (result.response) { + txid = result.response; + } + if (txid != null) { - /* - Step 5 - Final redis commands - */ - function(workers, rounds, paymentsUpdate, callback){ + // it worked, congrats on your pools payout ;) + logger.special(logSystem, logComponent, 'Sent ' + satoshisToCoins(totalSent) + + ' to ' + Object.keys(addressAmounts).length + ' miners; txid: '+txid); - var totalPaid = parseFloat(0); + if (withholdPercent > 0) { + logger.warning(logSystem, logComponent, 'Had to withhold ' + (withholdPercent * 100) + + '% of reward from miners to cover transaction fees. ' + + 'Fund pool wallet with coins to prevent this from happening'); + } - var immatureUpdateCommands = []; - var balanceUpdateCommands = []; - var workerPayoutsCommand = []; + // save payments data to redis + var paymentBlocks = rounds.filter(function(r){ return r.category == 'generate'; }).map(function(r){ + return parseInt(r.height); + }); - // update worker paid/balance stats - for (var w in workers) { - var worker = workers[w]; - // update balances - if ((worker.balanceChange || 0) !== 0){ - balanceUpdateCommands.push([ - 'hincrbyfloat', - coin + ':balances', - w, - satoshisToCoins(worker.balanceChange) - ]); - } - // update payouts - if ((worker.sent || 0) > 0){ - workerPayoutsCommand.push(['hincrbyfloat', coin + ':payouts', w, coinsRound(worker.sent)]); - totalPaid = coinsRound(totalPaid + worker.sent); - } - // update immature balances - if ((worker.immature || 0) > 0) { - immatureUpdateCommands.push(['hset', coin + ':immature', w, worker.immature]); - } else { - immatureUpdateCommands.push(['hset', coin + ':immature', w, 0]); - } - } + var paymentsUpdate = []; + var paymentsData = {time:Date.now(), txid:txid, shares:totalShares, paid:satoshisToCoins(totalSent), miners:Object.keys(addressAmounts).length, blocks: paymentBlocks, amounts: addressAmounts, balances: balanceAmounts, work:shareAmounts}; + paymentsUpdate.push(['zadd', logComponent + ':payments', Date.now(), JSON.stringify(paymentsData)]); - var movePendingCommands = []; - var roundsToDelete = []; - var orphanMergeCommands = []; + callback(null, workers, rounds, paymentsUpdate); - var confirmsUpdate = []; - var confirmsToDelete = []; + } else { - var moveSharesToCurrent = function(r){ - var workerShares = r.workerShares; - if (workerShares != null) { - logger.warning(logSystem, logComponent, 'Moving shares from orphaned block '+r.height+' to current round.'); - Object.keys(workerShares).forEach(function(worker){ - orphanMergeCommands.push(['hincrby', coin + ':shares:roundCurrent', worker, workerShares[worker]]); - }); - } - }; + clearInterval(paymentInterval); - rounds.forEach(function(r){ - switch(r.category){ - case 'kicked': - case 'orphan': - confirmsToDelete.push(['hdel', coin + ':blocksPendingConfirms', r.blockHash]); - movePendingCommands.push(['smove', coin + ':blocksPending', coin + ':blocksKicked', r.serialized]); - if (r.canDeleteShares){ - moveSharesToCurrent(r); - roundsToDelete.push(coin + ':shares:round' + r.height); - roundsToDelete.push(coin + ':shares:times' + r.height); + logger.error(logSystem, logComponent, 'Error RPC sendmany did not return txid ' + + JSON.stringify(result) + 'Disabling payment processing to prevent possible double-payouts.'); + + callback(true); + return; } - return; - case 'immature': - confirmsUpdate.push(['hset', coin + ':blocksPendingConfirms', r.blockHash, (r.confirmations || 0)]); - return; - case 'generate': - confirmsToDelete.push(['hdel', coin + ':blocksPendingConfirms', r.blockHash]); - movePendingCommands.push(['smove', coin + ':blocksPending', coin + ':blocksConfirmed', r.serialized]); + } + }, true, true); + } + }; + + // attempt to send any owed payments + trySend(0); + } + + /* + Step 5 - Final redis commands + */ + var writeToRedis = function(workers, rounds, paymentsUpdate, callback) { + + var totalPaid = parseFloat(0); + + var immatureUpdateCommands = []; + var balanceUpdateCommands = []; + var workerPayoutsCommand = []; + + // update worker paid/balance stats + for (var w in workers) { + var worker = workers[w]; + // update balances + if ((worker.balanceChange || 0) !== 0){ + balanceUpdateCommands.push([ + 'hincrbyfloat', + coin + ':balances', + w, + satoshisToCoins(worker.balanceChange) + ]); + } + // update payouts + if ((worker.sent || 0) > 0){ + workerPayoutsCommand.push(['hincrbyfloat', coin + ':payouts', w, coinsRound(worker.sent)]); + totalPaid = coinsRound(totalPaid + worker.sent); + } + // update immature balances + if ((worker.immature || 0) > 0) { + immatureUpdateCommands.push(['hset', coin + ':immature', w, worker.immature]); + } else { + immatureUpdateCommands.push(['hset', coin + ':immature', w, 0]); + } + } + + var movePendingCommands = []; + var roundsToDelete = []; + var orphanMergeCommands = []; + + var confirmsUpdate = []; + var confirmsToDelete = []; + + var moveSharesToCurrent = function(r){ + var workerShares = r.workerShares; + if (workerShares != null) { + logger.warning(logSystem, logComponent, 'Moving shares from orphaned block '+r.height+' to current round.'); + Object.keys(workerShares).forEach(function(worker){ + orphanMergeCommands.push(['hincrby', coin + ':shares:roundCurrent', worker, workerShares[worker]]); + }); + } + }; + + rounds.forEach(function(r){ + switch(r.category){ + case 'kicked': + case 'orphan': + confirmsToDelete.push(['hdel', coin + ':blocksPendingConfirms', r.blockHash]); + movePendingCommands.push(['smove', coin + ':blocksPending', coin + ':blocksKicked', r.serialized]); + if (r.canDeleteShares){ + moveSharesToCurrent(r); roundsToDelete.push(coin + ':shares:round' + r.height); roundsToDelete.push(coin + ':shares:times' + r.height); - return; - } - }); + } + return; + case 'immature': + confirmsUpdate.push(['hset', coin + ':blocksPendingConfirms', r.blockHash, (r.confirmations || 0)]); + return; + case 'generate': + confirmsToDelete.push(['hdel', coin + ':blocksPendingConfirms', r.blockHash]); + movePendingCommands.push(['smove', coin + ':blocksPending', coin + ':blocksConfirmed', r.serialized]); + roundsToDelete.push(coin + ':shares:round' + r.height); + roundsToDelete.push(coin + ':shares:times' + r.height); + return; + } + }); - var finalRedisCommands = []; + var finalRedisCommands = []; - if (movePendingCommands.length > 0) - finalRedisCommands = finalRedisCommands.concat(movePendingCommands); + if (movePendingCommands.length > 0) + finalRedisCommands = finalRedisCommands.concat(movePendingCommands); - if (orphanMergeCommands.length > 0) - finalRedisCommands = finalRedisCommands.concat(orphanMergeCommands); + if (orphanMergeCommands.length > 0) + finalRedisCommands = finalRedisCommands.concat(orphanMergeCommands); - if (immatureUpdateCommands.length > 0) - finalRedisCommands = finalRedisCommands.concat(immatureUpdateCommands); + if (immatureUpdateCommands.length > 0) + finalRedisCommands = finalRedisCommands.concat(immatureUpdateCommands); - if (balanceUpdateCommands.length > 0) - finalRedisCommands = finalRedisCommands.concat(balanceUpdateCommands); + if (balanceUpdateCommands.length > 0) + finalRedisCommands = finalRedisCommands.concat(balanceUpdateCommands); - if (workerPayoutsCommand.length > 0) - finalRedisCommands = finalRedisCommands.concat(workerPayoutsCommand); + if (workerPayoutsCommand.length > 0) + finalRedisCommands = finalRedisCommands.concat(workerPayoutsCommand); - if (roundsToDelete.length > 0) - finalRedisCommands.push(['del'].concat(roundsToDelete)); + if (roundsToDelete.length > 0) + finalRedisCommands.push(['del'].concat(roundsToDelete)); - if (confirmsUpdate.length > 0) - finalRedisCommands = finalRedisCommands.concat(confirmsUpdate); + if (confirmsUpdate.length > 0) + finalRedisCommands = finalRedisCommands.concat(confirmsUpdate); - if (confirmsToDelete.length > 0) - finalRedisCommands = finalRedisCommands.concat(confirmsToDelete); + if (confirmsToDelete.length > 0) + finalRedisCommands = finalRedisCommands.concat(confirmsToDelete); - if (paymentsUpdate.length > 0) - finalRedisCommands = finalRedisCommands.concat(paymentsUpdate); + if (paymentsUpdate.length > 0) + finalRedisCommands = finalRedisCommands.concat(paymentsUpdate); - if (totalPaid !== 0) - finalRedisCommands.push(['hincrbyfloat', coin + ':stats', 'totalPaid', totalPaid]); + if (totalPaid !== 0) + finalRedisCommands.push(['hincrbyfloat', coin + ':stats', 'totalPaid', totalPaid]); - if (finalRedisCommands.length === 0){ - callback(); - return; - } + if (finalRedisCommands.length === 0){ + callback(); + return; + } - startRedisTimer(); - redisClient.multi(finalRedisCommands).exec(function(error, results){ - endRedisTimer(); - if (error) { - clearInterval(paymentInterval); + startRedisTimer(); + redisClient.multi(finalRedisCommands).exec(function(error, results){ + endRedisTimer(); + if (error) { + clearInterval(paymentInterval); - logger.error(logSystem, logComponent, - 'Payments sent but could not update redis. ' + JSON.stringify(error) - + ' Disabling payment processing to prevent possible double-payouts. The redis commands in ' - + coin + '_finalRedisCommands.txt must be ran manually'); + logger.error(logSystem, logComponent, + 'Payments sent but could not update redis. ' + JSON.stringify(error) + + ' Disabling payment processing to prevent possible double-payouts. The redis commands in ' + + coin + '_finalRedisCommands.txt must be ran manually'); - fs.writeFile(coin + '_finalRedisCommands.txt', JSON.stringify(finalRedisCommands), function(err){ - logger.error('Could not write finalRedisCommands.txt, you are fucked.'); - }); - } - callback(); - }); - } + fs.writeFile(coin + '_finalRedisCommands.txt', JSON.stringify(finalRedisCommands), function(err){ + logger.error('Could not write finalRedisCommands.txt, you are fucked.'); + }); + } + callback(); + }); + } + async.waterfall([ + buildWorkers, + checkMined, + calculateRewards, + sendPayments, + writeToRedis ], function(){ - + //On complete var paymentProcessTime = Date.now() - startPaymentProcess; logger.debug(logSystem, logComponent, 'Finished interval - time spent: ' + paymentProcessTime + 'ms total, ' + timeSpentRedis + 'ms redis, ' + timeSpentRPC + 'ms daemon RPC'); - }); }; - - var getProperAddress = function(address){ - let poolZAddressPrefix = poolOptions.zAddress.substring(0,2); - var isValid = false; - - if (privateChain) { - daemon.cmd('z_validateaddress', [address], function (results) { - isValid = results.filter(function (r) { - if ( (poolOptions.coin.sapling || poolOptions.coin.sapling > 0) && poolZAddressPrefix == 'zs') { - return (r.response.isvalid && r.response.type == 'sapling'); - } else if ( poolZAddressPrefix == 'zc') { - return (r.response.isvalid && r.response.type == 'sprout'); - } else { - return r.response.isvalid; - } - }).length > 0; - //authCallback(isValid); - }); - } else { - daemon.cmd('validateaddress', [address], function (results) { - isValid = results.filter(function (r) { - return r.response.isvalid - }).length > 0; - //authCallback(isValid); - }); - } - - if (isValid) { - return address; - } else { - return (poolOptions.invalidAddress || poolOptions.address); - } - }; - } From 906392608e722ff10623742e047e4f4fc93a259b Mon Sep 17 00:00:00 2001 From: webworker01 Date: Tue, 28 May 2019 01:54:39 +0000 Subject: [PATCH 06/16] Add `info` error logging level --- init.js | 30 ++++++++++++++-------------- libs/logUtil.js | 41 ++++++++++++++++---------------------- libs/networkStats.js | 6 +++--- libs/paymentProcessor.js | 16 +++++++-------- libs/poolWorker.js | 26 +++++++++++------------- libs/profitSwitch.js | 43 ++++++++++++++++++++-------------------- libs/shareProcessor.js | 4 ++-- libs/website.js | 10 +++++----- 8 files changed, 83 insertions(+), 93 deletions(-) diff --git a/init.js b/init.js index 0a6560f..43a4590 100644 --- a/init.js +++ b/init.js @@ -37,7 +37,7 @@ var logger = new PoolLogger({ try { require('newrelic'); if (cluster.isMaster) - logger.debug('NewRelic', 'Monitor', 'New Relic initiated'); + logger.info('NewRelic', 'Monitor', 'New Relic initiated'); } catch(e) {} @@ -57,13 +57,13 @@ try{ // Set our server's uid to that user if (uid) { process.setuid(uid); - logger.debug('POSIX', 'Connection Limit', 'Raised to 100K concurrent connections, now running as non-root user: ' + process.getuid()); + logger.info('POSIX', 'Connection Limit', 'Raised to 100K concurrent connections, now running as non-root user: ' + process.getuid()); } } } catch(e){ if (cluster.isMaster) - logger.debug('POSIX', 'Connection Limit', '(Safe to ignore) POSIX module not installed and resource (connection) limit was not raised'); + logger.info('POSIX', 'Connection Limit', '(Safe to ignore) POSIX module not installed and resource (connection) limit was not raised'); } if (cluster.isWorker){ @@ -87,7 +87,7 @@ if (cluster.isWorker){ } return; -} +} //Read all pool configs from pool_configs and join them with their coin profile @@ -194,7 +194,7 @@ var spawnPoolWorkers = function(){ var redisConfig; var connection; - + Object.keys(poolConfigs).forEach(function(coin){ var pcfg = poolConfigs[coin]; if (!Array.isArray(pcfg.daemons) || pcfg.daemons.length < 1){ @@ -204,7 +204,7 @@ var spawnPoolWorkers = function(){ redisConfig = pcfg.redis; connection = redis.createClient(redisConfig.port, redisConfig.host); connection.on('ready', function(){ - logger.debug('PPLNT', coin, 'TimeShare processing setup with redis (' + redisConfig.host + + logger.info('PPLNT', coin, 'TimeShare processing setup with redis (' + redisConfig.host + ':' + redisConfig.port + ')'); }); } @@ -260,7 +260,7 @@ var spawnPoolWorkers = function(){ var lastShareTime = now; var lastStartTime = now; var workerAddress = msg.data.worker.split('.')[0]; - + // if needed, initialize PPLNT objects for coin if (!_lastShareTimes[msg.coin]) { _lastShareTimes[msg.coin] = {}; @@ -268,7 +268,7 @@ var spawnPoolWorkers = function(){ if (!_lastStartTimes[msg.coin]) { _lastStartTimes[msg.coin] = {}; } - + // did they just join in this round? if (!_lastShareTimes[msg.coin][workerAddress] || !_lastStartTimes[msg.coin][workerAddress]) { _lastShareTimes[msg.coin][workerAddress] = now; @@ -280,16 +280,16 @@ var spawnPoolWorkers = function(){ lastShareTime = _lastShareTimes[msg.coin][workerAddress]; lastStartTime = _lastStartTimes[msg.coin][workerAddress]; } - + var redisCommands = []; - + // if its been less than 15 minutes since last share was submitted var timeChangeSec = roundTo(Math.max(now - lastShareTime, 0) / 1000, 4); //var timeChangeTotal = roundTo(Math.max(now - lastStartTime, 0) / 1000, 4); if (timeChangeSec < 900 && msg.trackShares) { // loyal miner keeps mining :) - redisCommands.push(['hincrbyfloat', msg.coin + ':shares:timesCurrent', workerAddress + "." + poolConfigs[msg.coin].poolId, timeChangeSec]); - //logger.debug('PPLNT', msg.coin, 'Thread '+msg.thread, workerAddress+':{totalTimeSec:'+timeChangeTotal+', timeChangeSec:'+timeChangeSec+'}'); + redisCommands.push(['hincrbyfloat', msg.coin + ':shares:timesCurrent', workerAddress + "." + poolConfigs[msg.coin].poolId, timeChangeSec]); + //logger.info('PPLNT', msg.coin, 'Thread '+msg.thread, workerAddress+':{totalTimeSec:'+timeChangeTotal+', timeChangeSec:'+timeChangeSec+'}'); connection.multi(redisCommands).exec(function(err, replies){ if (err) logger.error('PPLNT', msg.coin, 'Thread '+msg.thread, 'Error with time share processor call to redis ' + JSON.stringify(err)); @@ -299,7 +299,7 @@ var spawnPoolWorkers = function(){ _lastStartTimes[workerAddress] = now; logger.debug('PPLNT', msg.coin, 'Thread '+msg.thread, workerAddress+' re-joined.'); } - + // track last time share _lastShareTimes[msg.coin][workerAddress] = now; } @@ -319,7 +319,7 @@ var spawnPoolWorkers = function(){ i++; if (i === numForks){ clearInterval(spawnInterval); - logger.debug('Master', 'PoolSpawner', 'Spawned ' + Object.keys(poolConfigs).length + ' pool(s) on ' + numForks + ' thread(s)'); + logger.info('Master', 'PoolSpawner', 'Spawned ' + Object.keys(poolConfigs).length + ' pool(s) on ' + numForks + ' thread(s)'); } }, 250); @@ -331,7 +331,7 @@ var startCliListener = function(){ var listener = new CliListener(cliPort); listener.on('log', function(text){ - logger.debug('Master', 'CLI', text); + logger.info('Master', 'CLI', text); }).on('command', function(command, params, options, reply){ switch(command){ diff --git a/libs/logUtil.js b/libs/logUtil.js index 7b56b98..70eeca4 100644 --- a/libs/logUtil.js +++ b/libs/logUtil.js @@ -8,6 +8,8 @@ var severityToColor = function(severity, text) { return text.cyan.underline; case 'debug': return text.green; + case 'info': + return text.green; case 'warning': return text.yellow; case 'error': @@ -20,25 +22,24 @@ var severityToColor = function(severity, text) { var severityValues = { 'debug': 1, - 'warning': 2, - 'error': 3, - 'special': 4 + 'info' : 2, + 'warning': 3, + 'error': 4, + 'special': 5 }; - -var PoolLogger = function (configuration) { - +var PoolLogger = function(configuration) { var logLevelInt = severityValues[configuration.logLevel]; var logColors = configuration.logColors; - - var log = function(severity, system, component, text, subcat) { - if (severityValues[severity] < logLevelInt) return; + if (severityValues[severity] < logLevelInt) { + return; + } - if (subcat){ + if (subcat) { var realText = subcat; var realSubCat = text; text = realText; @@ -49,19 +50,14 @@ var PoolLogger = function (configuration) { if (logColors) { entryDesc = severityToColor(severity, entryDesc); - var logString = - entryDesc + - ('[' + component + '] ').italic; + var logString = entryDesc + ('[' + component + '] ').italic; if (subcat) logString += ('(' + subcat + ') ').bold.grey; logString += text.grey; - } - else { - var logString = - entryDesc + - '[' + component + '] '; + } else { + var logString = entryDesc + '[' + component + '] '; if (subcat) logString += '(' + subcat + ') '; @@ -70,15 +66,12 @@ var PoolLogger = function (configuration) { } console.log(logString); - - }; // public - var _this = this; - Object.keys(severityValues).forEach(function(logType){ - _this[logType] = function(){ + Object.keys(severityValues).forEach(function(logType) { + _this[logType] = function() { var args = Array.prototype.slice.call(arguments, 0); args.unshift(logType); log.apply(this, args); @@ -86,4 +79,4 @@ var PoolLogger = function (configuration) { }); }; -module.exports = PoolLogger; \ No newline at end of file +module.exports = PoolLogger; diff --git a/libs/networkStats.js b/libs/networkStats.js index 205d5c2..9a5c7d2 100644 --- a/libs/networkStats.js +++ b/libs/networkStats.js @@ -29,9 +29,9 @@ module.exports = function(logger){ var logSystem = 'Payments'; var logComponent = coin; - logger.debug(logSystem, logComponent, 'Network stats setup with daemon (' + logger.info(logSystem, logComponent, 'Network stats setup with daemon (' + daemonConfig.user + '@' + daemonConfig.host + ':' + daemonConfig.port - + ') and redis (' + poolOptions.redis.host + ':' + poolOptions.redis.port + ')'); + + ') and redis (' + poolOptions.redis.host + ':' + poolOptions.redis.port + ')'); }); }); }; @@ -118,7 +118,7 @@ function SetupForStats(logger, poolOptions, setupFinished) { var coin = logComponent.replace('_testnet', '').toLowerCase(); if (coin == 'zen') coin = 'zencash'; - + request('https://api.coinmarketcap.com/v1/ticker/'+coin+'/', function (error, response, body) { if (error) { logger.error(logSystem, logComponent, 'Error with http request to https://api.coinmarketcap.com/ ' + JSON.stringify(error)); diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index 741aa71..cebf39c 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -32,7 +32,7 @@ module.exports = function(logger) { var logSystem = 'Payments'; var logComponent = coin; - logger.debug(logSystem, logComponent, 'Payment processing setup with daemon (' + logger.info(logSystem, logComponent, 'Payment processing setup with daemon (' + processingConfig.daemon.user + '@' + processingConfig.daemon.host + ':' + processingConfig.daemon.port + ') and redis (' + poolOptions.redis.host + ':' + poolOptions.redis.port + ')'); }); @@ -86,11 +86,11 @@ function SetupForPool(logger, poolOptions, setupFinished) { var fee = parseFloat(poolOptions.coin.txfee) || parseFloat(0.0004); - logger.debug(logSystem, logComponent, logComponent + ' requireShielding: ' + requireShielding); - logger.debug(logSystem, logComponent, logComponent + ' minConf: ' + minConfShield); - logger.debug(logSystem, logComponent, logComponent + ' payments txfee reserve: ' + fee); - logger.debug(logSystem, logComponent, logComponent + ' maxBlocksPerPayment: ' + maxBlocksPerPayment); - logger.debug(logSystem, logComponent, logComponent + ' PPLNT: ' + pplntEnabled + ', time period: '+pplntTimeQualify); + logger.info(logSystem, logComponent, logComponent + ' requireShielding: ' + requireShielding); + logger.info(logSystem, logComponent, logComponent + ' minConf: ' + minConfShield); + logger.info(logSystem, logComponent, logComponent + ' payments txfee reserve: ' + fee); + logger.info(logSystem, logComponent, logComponent + ' maxBlocksPerPayment: ' + maxBlocksPerPayment); + logger.info(logSystem, logComponent, logComponent + ' PPLNT: ' + pplntEnabled + ', time period: '+pplntTimeQualify); var daemon = new Stratum.daemon.interface([processingConfig.daemon], function(severity, message){ logger[severity](logSystem, logComponent, message); @@ -726,7 +726,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { } else { // keep unique valid block validBlocks[dups[i].blockHash] = dups[i].serialized; - logger.debug(logSystem, logComponent, 'Keep valid duplicate block ' + block.result.height + ' > ' + block.result.hash); + logger.info(logSystem, logComponent, 'Keep valid duplicate block ' + block.result.height + ' > ' + block.result.hash); } } } @@ -1581,7 +1581,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { ], function(){ //On complete var paymentProcessTime = Date.now() - startPaymentProcess; - logger.debug(logSystem, logComponent, 'Finished interval - time spent: ' + logger.info(logSystem, logComponent, 'Finished interval - time spent: ' + paymentProcessTime + 'ms total, ' + timeSpentRedis + 'ms redis, ' + timeSpentRPC + 'ms daemon RPC'); }); diff --git a/libs/poolWorker.js b/libs/poolWorker.js index b72daa2..9d1c5e1 100644 --- a/libs/poolWorker.js +++ b/libs/poolWorker.js @@ -64,11 +64,11 @@ module.exports = function(logger){ var proxyPorts = Object.keys(proxySwitch[switchName].ports); if (newCoin == oldCoin) { - logger.debug(logSystem, logComponent, logSubCat, 'Switch message would have no effect - ignoring ' + newCoin); + logger.info(logSystem, logComponent, logSubCat, 'Switch message would have no effect - ignoring ' + newCoin); break; } - logger.debug(logSystem, logComponent, logSubCat, 'Proxy message for ' + algo + ' from ' + oldCoin + ' to ' + newCoin); + logger.info(logSystem, logComponent, logSubCat, 'Proxy message for ' + algo + ' from ' + oldCoin + ' to ' + newCoin); if (newPool) { oldPool.relinquishMiners( @@ -87,7 +87,7 @@ module.exports = function(logger){ logger.error(logSystem, logComponent, logSubCat, 'Redis error writing proxy config: ' + JSON.stringify(err)) } else { - logger.debug(logSystem, logComponent, logSubCat, 'Last proxy state saved to redis for ' + algo); + logger.info(logSystem, logComponent, logSubCat, 'Last proxy state saved to redis for ' + algo); } }); @@ -159,7 +159,7 @@ module.exports = function(logger){ var authString = authorized ? 'Authorized' : 'Unauthorized '; - logger.debug(logSystem, logComponent, logSubCat, authString + ' ' + workerName + ':' + password + ' [' + ip + ']'); + logger.info(logSystem, logComponent, logSubCat, authString + ' ' + workerName + ':' + password + ' [' + ip + ']'); callback({ error: null, authorized: authorized, @@ -175,10 +175,10 @@ module.exports = function(logger){ var shareData = JSON.stringify(data); if (data.blockHash && !isValidBlock) - logger.debug(logSystem, logComponent, logSubCat, 'We thought a block was found but it was rejected by the daemon, share data: ' + shareData); + logger.info(logSystem, logComponent, logSubCat, 'We thought a block was found but it was rejected by the daemon, share data: ' + shareData); else if (isValidBlock) - logger.debug(logSystem, logComponent, logSubCat, 'Block found: ' + data.blockHash + ' by ' + data.worker); + logger.info(logSystem, logComponent, logSubCat, 'Block found: ' + data.blockHash + ' by ' + data.worker); if (isValidShare) { if(data.shareDiff > 1000000000) { @@ -188,7 +188,7 @@ module.exports = function(logger){ } //logger.debug(logSystem, logComponent, logSubCat, 'Share accepted at diff ' + data.difficulty + '/' + data.shareDiff + ' by ' + data.worker + ' [' + data.ip + ']' ); } else if (!isValidShare) { - logger.debug(logSystem, logComponent, logSubCat, 'Share rejected: ' + shareData); + logger.info(logSystem, logComponent, logSubCat, 'Share rejected: ' + shareData); } // handle the share @@ -225,9 +225,7 @@ module.exports = function(logger){ // Load proxy state for each algorithm from redis which allows NOMP to resume operation // on the last pool it was using when reloaded or restarted // - logger.debug(logSystem, logComponent, logSubCat, 'Loading last proxy state from redis'); - - + logger.info(logSystem, logComponent, logSubCat, 'Loading last proxy state from redis'); /*redisClient.on('error', function(err){ logger.debug(logSystem, logComponent, logSubCat, 'Pool configuration failed: ' + err); @@ -236,7 +234,7 @@ module.exports = function(logger){ redisClient.hgetall("proxyState", function(error, obj) { if (!error && obj) { proxyState = obj; - logger.debug(logSystem, logComponent, logSubCat, 'Last proxy state loaded from redis'); + logger.info(logSystem, logComponent, logSubCat, 'Last proxy state loaded from redis'); } // @@ -265,7 +263,7 @@ module.exports = function(logger){ var f = net.createServer(function(socket) { var currentPool = proxySwitch[switchName].currentPool; - logger.debug(logSystem, 'Connect', logSubCat, 'Connection to ' + logger.info(logSystem, 'Connect', logSubCat, 'Connection to ' + switchName + ' from ' + socket.remoteAddress + ' on ' + port + ' routing to ' + currentPool); @@ -276,7 +274,7 @@ module.exports = function(logger){ pools[initalPool].getStratumServer().handleNewClient(socket); }).listen(parseInt(port), function() { - logger.debug(logSystem, logComponent, logSubCat, 'Switching "' + switchName + logger.info(logSystem, logComponent, logSubCat, 'Switching "' + switchName + '" listening for ' + algorithm + ' on port ' + port + ' into ' + proxySwitch[switchName].currentPool); @@ -305,7 +303,7 @@ module.exports = function(logger){ // this.setDifficultyForProxyPort = function(pool, coin, algo) { - logger.debug(logSystem, logComponent, algo, 'Setting proxy difficulties after pool start'); + logger.info(logSystem, logComponent, algo, 'Setting proxy difficulties after pool start'); Object.keys(portalConfig.switching).forEach(function(switchName) { if (!portalConfig.switching[switchName].enabled) return; diff --git a/libs/profitSwitch.js b/libs/profitSwitch.js index 990314e..334f93f 100644 --- a/libs/profitSwitch.js +++ b/libs/profitSwitch.js @@ -19,7 +19,7 @@ module.exports = function(logger){ var logSystem = 'Profit'; - // + // // build status tracker for collecting coin market information // var profitStatus = {}; @@ -44,7 +44,7 @@ module.exports = function(logger){ }); - // + // // ensure we have something to switch // Object.keys(profitStatus).forEach(function(algo){ @@ -57,12 +57,12 @@ module.exports = function(logger){ } }); if (Object.keys(profitStatus).length == 0){ - logger.debug(logSystem, 'Config', 'No alternative coins to switch to in current config, switching disabled.'); + logger.info(logSystem, 'Config', 'No alternative coins to switch to in current config, switching disabled.'); return; } - // + // // setup APIs // var poloApi = new Poloniex( @@ -83,7 +83,7 @@ module.exports = function(logger){ // 'API_SECRET' ); - // + // // market data collection from Poloniex // this.getProfitDataPoloniex = function(callback){ @@ -139,12 +139,12 @@ module.exports = function(logger){ var marketData = profitStatus[symbolToAlgorithmMap[symbol]][symbol].exchangeInfo['Poloniex']; if (marketData.hasOwnProperty('BTC') && marketData['BTC'].bid > 0){ depthTasks.push(function(callback){ - _this.getMarketDepthFromPoloniex('BTC', symbol, marketData['BTC'].bid, callback) + _this.getMarketDepthFromPoloniex('BTC', symbol, marketData['BTC'].bid, callback) }); } if (marketData.hasOwnProperty('LTC') && marketData['LTC'].bid > 0){ depthTasks.push(function(callback){ - _this.getMarketDepthFromPoloniex('LTC', symbol, marketData['LTC'].bid, callback) + _this.getMarketDepthFromPoloniex('LTC', symbol, marketData['LTC'].bid, callback) }); } }); @@ -168,7 +168,7 @@ module.exports = function(logger){ } callback(null); }); - + }; this.getMarketDepthFromPoloniex = function(symbolA, symbolB, coinPrice, callback){ poloApi.getOrderBook(symbolA, symbolB, function(err, data){ @@ -199,7 +199,7 @@ module.exports = function(logger){ }); }; - + this.getProfitDataCryptsy = function(callback){ async.series([ function(taskCallback){ @@ -285,7 +285,7 @@ module.exports = function(logger){ } callback(null); }); - + }; @@ -339,12 +339,12 @@ module.exports = function(logger){ var marketData = profitStatus[symbolToAlgorithmMap[symbol]][symbol].exchangeInfo['Mintpal']; if (marketData.hasOwnProperty('BTC') && marketData['BTC'].bid > 0){ depthTasks.push(function(callback){ - _this.getMarketDepthFromMintpal('BTC', symbol, marketData['BTC'].bid, callback) + _this.getMarketDepthFromMintpal('BTC', symbol, marketData['BTC'].bid, callback) }); } if (marketData.hasOwnProperty('LTC') && marketData['LTC'].bid > 0){ depthTasks.push(function(callback){ - _this.getMarketDepthFromMintpal('LTC', symbol, marketData['LTC'].bid, callback) + _this.getMarketDepthFromMintpal('LTC', symbol, marketData['LTC'].bid, callback) }); } }); @@ -451,12 +451,12 @@ module.exports = function(logger){ var marketData = profitStatus[symbolToAlgorithmMap[symbol]][symbol].exchangeInfo['Bittrex']; if (marketData.hasOwnProperty('BTC') && marketData['BTC'].bid > 0){ depthTasks.push(function(callback){ - _this.getMarketDepthFromBittrex('BTC', symbol, marketData['BTC'].bid, callback) + _this.getMarketDepthFromBittrex('BTC', symbol, marketData['BTC'].bid, callback) }); } if (marketData.hasOwnProperty('LTC') && marketData['LTC'].bid > 0){ depthTasks.push(function(callback){ - _this.getMarketDepthFromBittrex('LTC', symbol, marketData['LTC'].bid, callback) + _this.getMarketDepthFromBittrex('LTC', symbol, marketData['LTC'].bid, callback) }); } }); @@ -554,7 +554,7 @@ module.exports = function(logger){ // some shitcoins dont provide target, only bits, so we need to deal with both var target = response.target ? bignum(response.target, 16) : util.bignumFromBitsHex(response.bits); coinStatus.difficulty = parseFloat((diff1 / target.toNumber()).toFixed(9)); - logger.debug(logSystem, symbol, 'difficulty is ' + coinStatus.difficulty); + logger.info(logSystem, symbol, 'difficulty is ' + coinStatus.difficulty); coinStatus.reward = response.coinbasevalue / 100000000; callback(null); @@ -596,7 +596,7 @@ module.exports = function(logger){ bestCoin = profitStatus[algo][symbol].name; } coinStatus.btcPerMhPerHour = btcPerMhPerHour; - logger.debug(logSystem, 'CALC', 'BTC/' + symbol + ' on ' + exchange + ' with ' + coinStatus.btcPerMhPerHour.toFixed(8) + ' BTC/day per Mh/s'); + logger.info(logSystem, 'CALC', 'BTC/' + symbol + ' on ' + exchange + ' with ' + coinStatus.btcPerMhPerHour.toFixed(8) + ' BTC/day per Mh/s'); } if (exchangeData.hasOwnProperty('LTC') && exchangeData['LTC'].hasOwnProperty('weightedBid')){ var btcPerMhPerHour = (exchangeData['LTC'].weightedBid * coinStatus.coinsPerMhPerHour) * exchangeData['LTC'].ltcToBtc; @@ -606,12 +606,11 @@ module.exports = function(logger){ bestCoin = profitStatus[algo][symbol].name; } coinStatus.btcPerMhPerHour = btcPerMhPerHour; - logger.debug(logSystem, 'CALC', 'LTC/' + symbol + ' on ' + exchange + ' with ' + coinStatus.btcPerMhPerHour.toFixed(8) + ' BTC/day per Mh/s'); + logger.info(logSystem, 'CALC', 'LTC/' + symbol + ' on ' + exchange + ' with ' + coinStatus.btcPerMhPerHour.toFixed(8) + ' BTC/day per Mh/s'); } }); }); - logger.debug(logSystem, 'RESULT', 'Best coin for ' + algo + ' is ' + bestCoin + ' on ' + bestExchange + ' with ' + bestBtcPerMhPerHour.toFixed(8) + ' BTC/day per Mh/s'); - + logger.info(logSystem, 'RESULT', 'Best coin for ' + algo + ' is ' + bestCoin + ' on ' + bestExchange + ' with ' + bestBtcPerMhPerHour.toFixed(8) + ' BTC/day per Mh/s'); var client = net.connect(portalConfig.cliPort, function () { client.write(JSON.stringify({ @@ -631,7 +630,7 @@ module.exports = function(logger){ var checkProfitability = function(){ - logger.debug(logSystem, 'Check', 'Collecting profitability data.'); + logger.info(logSystem, 'Check', 'Collecting profitability data.'); profitabilityTasks = []; if (portalConfig.profitSwitch.usePoloniex) @@ -649,7 +648,7 @@ module.exports = function(logger){ profitabilityTasks.push(_this.getCoindDaemonInfo); profitabilityTasks.push(_this.getMiningRate); - // has to be series + // has to be series async.series(profitabilityTasks, function(err){ if (err){ logger.error(logSystem, 'Check', 'Error while checking profitability: ' + err); @@ -657,7 +656,7 @@ module.exports = function(logger){ } // // TODO offer support for a userConfigurable function for deciding on coin to override the default - // + // _this.switchToMostProfitableCoins(); }); }; diff --git a/libs/shareProcessor.js b/libs/shareProcessor.js index 79cf3e1..70c2ac5 100644 --- a/libs/shareProcessor.js +++ b/libs/shareProcessor.js @@ -21,13 +21,13 @@ module.exports = function(logger, poolConfig){ var logSystem = 'Pool'; var logComponent = coin; var logSubCat = 'Thread ' + (parseInt(forkId) + 1); - + var connection = redis.createClient(redisConfig.port, redisConfig.host); if (redisConfig.password) { connection.auth(redisConfig.password); } connection.on('ready', function(){ - logger.debug(logSystem, logComponent, logSubCat, 'Share processing setup with redis (' + redisConfig.host + + logger.info(logSystem, logComponent, logSubCat, 'Share processing setup with redis (' + redisConfig.host + ':' + redisConfig.port + ')'); }); connection.on('error', function(err){ diff --git a/libs/website.js b/libs/website.js index ab08afb..6afbddd 100644 --- a/libs/website.js +++ b/libs/website.js @@ -100,7 +100,7 @@ module.exports = function(logger){ basename = path.basename(evt); else basename = path.basename(filename); - + if (basename in pageFiles){ readPageFiles([basename]); logger.special(logSystem, 'Server', 'Reloaded file ' + basename); @@ -243,7 +243,7 @@ module.exports = function(logger){ res.send(500, 'Something broke!'); }); - try { + try { if (portalConfig.website.tlsOptions && portalConfig.website.tlsOptions.enabled === true) { var TLSoptions = { key: fs.readFileSync(portalConfig.website.tlsOptions.key), @@ -251,11 +251,11 @@ module.exports = function(logger){ }; https.createServer(TLSoptions, app).listen(portalConfig.website.port, portalConfig.website.host, function() { - logger.debug(logSystem, 'Server', 'TLS Website started on ' + portalConfig.website.host + ':' + portalConfig.website.port); - }); + logger.info(logSystem, 'Server', 'TLS Website started on ' + portalConfig.website.host + ':' + portalConfig.website.port); + }); } else { app.listen(portalConfig.website.port, portalConfig.website.host, function () { - logger.debug(logSystem, 'Server', 'Website started on ' + portalConfig.website.host + ':' + portalConfig.website.port); + logger.info(logSystem, 'Server', 'Website started on ' + portalConfig.website.host + ':' + portalConfig.website.port); }); } } From 1fcd2e28242154e817bd30b1fcc2aa0505a9660e Mon Sep 17 00:00:00 2001 From: webworker01 Date: Tue, 28 May 2019 02:23:20 +0000 Subject: [PATCH 07/16] Fix for undefined variables in poolWorker.js:validateAddress() --- libs/poolWorker.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/libs/poolWorker.js b/libs/poolWorker.js index 9d1c5e1..33ce6cb 100644 --- a/libs/poolWorker.js +++ b/libs/poolWorker.js @@ -105,14 +105,6 @@ module.exports = function(logger){ var logSubCat = 'Thread ' + (parseInt(forkId) + 1); var trackShares = (typeof poolOptions.trackShares !== 'undefined' && typeof poolOptions.trackShares.disable !== 'undefined') ? !poolOptions.trackShares.disable : true; - if (typeof poolOptions.coin.privateChain !== 'undefined' && poolOptions.coin.privateChain === true) { - var privateChain = poolOptions.coin.privateChain === true; - // var requireShielding = true; - } else { - var privateChain = false; - // var requireShielding = poolOptions.coin.requireShielding === true; - } - var handlers = { auth: function(){}, share: function(){}, @@ -145,7 +137,7 @@ module.exports = function(logger){ if (poolOptions.validateWorkerUsername !== true) { authCallback(true); } else { - authCallback(_this.validateAddress()); + authCallback(_this.validateAddress(String(workerName).split(".")[0], poolOptions)); } }; @@ -188,7 +180,7 @@ module.exports = function(logger){ } //logger.debug(logSystem, logComponent, logSubCat, 'Share accepted at diff ' + data.difficulty + '/' + data.shareDiff + ' by ' + data.worker + ' [' + data.ip + ']' ); } else if (!isValidShare) { - logger.info(logSystem, logComponent, logSubCat, 'Share rejected: ' + shareData); + logger.debug(logSystem, logComponent, logSubCat, 'Share rejected: ' + shareData); } // handle the share @@ -327,11 +319,17 @@ module.exports = function(logger){ }); }; - this.validateAddress = function(address) { - let poolZAddressPrefix = poolOptions.zAddress.substring(0,2); + this.validateAddress = function(address, poolOptions) { + let poolZAddressPrefix = (typeof poolOptions.zAddress !== 'undefined' ? poolOptions.zAddress : '').substring(0,2); let minerAddressLength = address.replace(/[^0-9a-z]/gi, '').length; let minerAddressPrefix = address.substring(0,2); + if (typeof poolOptions.coin.privateChain !== 'undefined' && poolOptions.coin.privateChain === true) { + var privateChain = poolOptions.coin.privateChain === true; + } else { + var privateChain = false; + } + if (privateChain && poolZAddressPrefix == 'zs' && minerAddressLength == 78 && minerAddressPrefix == 'zs') { //validate as sapling return true; From eb87663217dca2b9d028b59b8b9e353efa46d4c4 Mon Sep 17 00:00:00 2001 From: webworker01 Date: Fri, 31 May 2019 16:43:08 +0000 Subject: [PATCH 08/16] add option for minerprefix in pool_config --- libs/paymentProcessor.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index cebf39c..9847c4a 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -601,6 +601,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { let poolZAddressPrefix = poolOptions.zAddress.substring(0,2); let minerAddressLength = address.replace(/[^0-9a-z]/gi, '').length; let minerAddressPrefix = address.substring(0,2); + let checkPrefix = (poolOptions.minerPrefix || false); if (privateChain && poolZAddressPrefix == 'zs' && minerAddressLength == 78 && minerAddressPrefix == 'zs') { //validate as sapling @@ -609,6 +610,10 @@ function SetupForPool(logger, poolOptions, setupFinished) { //validate as sprout return address; } else if (privateChain || address.length >= 40 || address.length <= 30) { + logger.warning(logSystem, logComponent, 'Invalid address ' + address + ', convert to address ' + (poolOptions.invalidAddress || poolOptions.address)); + return (poolOptions.invalidAddress || poolOptions.address); + } else if (checkPrefix && address.substring(0, checkPrefix.length) != checkPrefix) { + logger.warning(logSystem, logComponent, 'Invalid address ' + address + ', convert to address ' + (poolOptions.invalidAddress || poolOptions.address)); return (poolOptions.invalidAddress || poolOptions.address); } else { return address; From 174abb6cdd72f2a9666e89b843c2996073f8dc7e Mon Sep 17 00:00:00 2001 From: webworker01 Date: Fri, 31 May 2019 16:48:27 +0000 Subject: [PATCH 09/16] comment for minerprefix --- libs/paymentProcessor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index 9847c4a..9cca0e2 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -612,6 +612,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { } else if (privateChain || address.length >= 40 || address.length <= 30) { logger.warning(logSystem, logComponent, 'Invalid address ' + address + ', convert to address ' + (poolOptions.invalidAddress || poolOptions.address)); return (poolOptions.invalidAddress || poolOptions.address); + // as a final stopgap you can add "minerPrefix":"R" to pool_config } else if (checkPrefix && address.substring(0, checkPrefix.length) != checkPrefix) { logger.warning(logSystem, logComponent, 'Invalid address ' + address + ', convert to address ' + (poolOptions.invalidAddress || poolOptions.address)); return (poolOptions.invalidAddress || poolOptions.address); From 3e61e44dc6ae5a15317c027efc096e3e4c5bad85 Mon Sep 17 00:00:00 2001 From: webworker01 Date: Fri, 31 May 2019 16:52:44 +0000 Subject: [PATCH 10/16] remove test --- libs/paymentProcessor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index 9cca0e2..97e9691 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -480,7 +480,7 @@ function SetupForPool(logger, poolOptions, setupFinished) { /* Not sure if this is needed but call this to clear out operations (some seemed to get stuck) */ if (privateChain) { - logger.special(logSystem, logComponent, "Running z_operationresult for privateChain - TEST"); + logger.special(logSystem, logComponent, "Running z_operationresult for privateChain"); batchRPC.push(['z_getoperationresult']); } From ef638200cd70a96fea64b949d2deb40138988cde Mon Sep 17 00:00:00 2001 From: webworker01 Date: Tue, 4 Jun 2019 02:56:17 +0000 Subject: [PATCH 11/16] Add heapdump for debugging --- init.js | 10 ++++++++++ package.json | 1 + 2 files changed, 11 insertions(+) diff --git a/init.js b/init.js index 43a4590..c808a08 100644 --- a/init.js +++ b/init.js @@ -16,6 +16,8 @@ var Website = require('./libs/website.js'); var ProfitSwitch = require('./libs/profitSwitch.js'); var NetworkStats = require('./libs/networkStats.js'); +var heapdump = require('heapdump'); + var algos = require('stratum-pool/lib/algoProperties.js'); JSON.minify = JSON.minify || require("node-json-minify"); @@ -505,6 +507,13 @@ var startNetworkStats = function(){ }); }; +var startHeapDumper = function() { + heapdump.writeSnapshot(Date.now() + '.heapsnapshot'); + setTimeout(function() { + heapdump.writeSnapshot(Date.now() + '.heapsnapshot'); + }, 900000); +}; + (function init(){ poolConfigs = buildPoolConfigs(); @@ -521,4 +530,5 @@ var startNetworkStats = function(){ startCliListener(); + startHeapDumper(); })(); diff --git a/package.json b/package.json index 007917e..93c14c1 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "dot": "1.1.2", "express": "^4.16.3", "extend": "3.0.2", + "heapdump": "^0.3.14", "mysql": "^2.16.0", "node-json-minify": "1.0.0", "node-watch": "0.5.8", From a7f1470e09ac6af82ff495be45f3bd45f259fbd2 Mon Sep 17 00:00:00 2001 From: webworker01 Date: Tue, 4 Jun 2019 03:27:19 +0000 Subject: [PATCH 12/16] Configurable heapdump --- init.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/init.js b/init.js index c808a08..0c924e8 100644 --- a/init.js +++ b/init.js @@ -508,10 +508,17 @@ var startNetworkStats = function(){ }; var startHeapDumper = function() { - heapdump.writeSnapshot(Date.now() + '.heapsnapshot'); - setTimeout(function() { + if (typeof portalConfig.heapdumpSeconds !== 'undefined' && parseInt(portalConfig.heapdumpSeconds) > 0) { heapdump.writeSnapshot(Date.now() + '.heapsnapshot'); - }, 900000); + logger.info('Pool', 'heapdump', 'Heap snapshotting will occur every ' + portalConfig.heapdumpSeconds + ' seconds' ); + logger.info('Pool', 'heapdump', 'Wrote heap snapshot to file ' + (Date.now() + '.heapsnapshot') ); + setTimeout(function() { + heapdump.writeSnapshot(Date.now() + '.heapsnapshot'); + logger.info('Pool', 'heapdump', 'Wrote heap snapshot to file ' + (Date.now() + '.heapsnapshot') ); + }, portalConfig.heapdumpSeconds * 1000); + } else { + logger.info('Pool', 'heapdump', 'Heap snapshotting disabled, configure heapdumpSeconds in config.json to enable'); + } }; (function init(){ From 0dcd17dddee3dcb3f087abd747c7b6b7a9621c3f Mon Sep 17 00:00:00 2001 From: webworker01 Date: Tue, 4 Jun 2019 18:35:26 +0000 Subject: [PATCH 13/16] Make timeout into interval for heapdump --- init.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.js b/init.js index 0c924e8..0d6a762 100644 --- a/init.js +++ b/init.js @@ -512,7 +512,7 @@ var startHeapDumper = function() { heapdump.writeSnapshot(Date.now() + '.heapsnapshot'); logger.info('Pool', 'heapdump', 'Heap snapshotting will occur every ' + portalConfig.heapdumpSeconds + ' seconds' ); logger.info('Pool', 'heapdump', 'Wrote heap snapshot to file ' + (Date.now() + '.heapsnapshot') ); - setTimeout(function() { + setInterval(function() { heapdump.writeSnapshot(Date.now() + '.heapsnapshot'); logger.info('Pool', 'heapdump', 'Wrote heap snapshot to file ' + (Date.now() + '.heapsnapshot') ); }, portalConfig.heapdumpSeconds * 1000); From c8ab25a524dcd8b0f8a3ff2d7eb159a0b957bb5f Mon Sep 17 00:00:00 2001 From: webworker01 Date: Tue, 4 Jun 2019 19:47:48 +0000 Subject: [PATCH 14/16] Add heapdump config to example --- config_example.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config_example.json b/config_example.json index c386745..b00be4e 100644 --- a/config_example.json +++ b/config_example.json @@ -3,6 +3,8 @@ "_logLevelOptions": "debug/warning/error", "logColors": true, + "heapdumpSeconds": false, + "cliPort": 17117, "clustering": { From 1ce258e7a9903b97c78387a3bb30fefc8123dc67 Mon Sep 17 00:00:00 2001 From: webworker01 Date: Fri, 27 Sep 2019 04:37:57 +0000 Subject: [PATCH 15/16] Piratepool html updates --- website/piratepool.io/index.html | 12 ++++----- .../piratepool.io/pages/getting_started.html | 16 ++++++------ website/piratepool.io/pages/home.html | 26 ++++++++++++------- website/piratepool.io/pages/miner_stats.html | 8 +++++- website/piratepool.io/pages/payments.html | 24 ++++++++++------- website/piratepool.io/pages/stats.html | 8 +++--- website/piratepool.io/pages/workers.html | 14 +++++----- 7 files changed, 64 insertions(+), 44 deletions(-) diff --git a/website/piratepool.io/index.html b/website/piratepool.io/index.html index 4e4c8d5..fe9410e 100644 --- a/website/piratepool.io/index.html +++ b/website/piratepool.io/index.html @@ -7,7 +7,7 @@ piratepool.io - mining pool for PirateChain (ARRR) - the most private and anonymous mineable cryptocurrency - Pirate - + @@ -15,20 +15,20 @@ - + - + - + @@ -93,9 +93,9 @@ {{=it.page}}
- No warranties matey! If ye be 'aving any troubles, invoke yarrr right t' parlay at #pirate + No warranties matey! If ye be 'aving any troubles, invoke yarrr right t' parlay at #piratepool
- <3 🐸 · Built with knomp + <3 🕷️ · Built with knomp
diff --git a/website/piratepool.io/pages/getting_started.html b/website/piratepool.io/pages/getting_started.html index 411a82b..5885ff3 100644 --- a/website/piratepool.io/pages/getting_started.html +++ b/website/piratepool.io/pages/getting_started.html @@ -110,20 +110,20 @@

Optiminer

- optiminer-zcash -s {{=it.portalConfig.website.stratumHost}}:{{= Object.keys(it.poolsConfigs[Object.keys(it.poolsConfigs)[0]].ports)[0] }} -u zs1nrn7h684wq4429pz8a20r49dmmhd3ey07u38f8m2n9du33ashd0xcnls3lfz0spdvn26z3r4jrv.myrigname -p x + optiminer-zcash -s {{=it.portalConfig.website.stratumHost}}:{{= Object.keys(it.poolsConfigs[Object.keys(it.poolsConfigs)[0]].ports)[0] }} -u zs1nrn7h684wq4429pz8a20r49dmmhd3ey07u38f8m2n9du33ashd0xcnls3lfz0spdvn26z3r4jrv.myrigname -p x
{{ } }}

Payments

-

Payouts are currently scheduled once every 4 hours with a minimum payout of 42 ARRR.

+

Payouts are currently scheduled once every 4 hours with a minimum payout of 21 ARRR.

There is a limit of ~200 recipients that can be included in a single payout, so the pool payouts are monitored and the min payout adjusted accordingly to ensure a constant flow of payments.

-

If payments stop going out, do not worry! Funds are safu! Blocks can still be found and will be credited to your worker! Please check the #pools-and-operators channel in discord to see if it's already being worked on.

+

If payments stop going out, do not worry! Funds are safu! Blocks can still be found and will be credited to your worker! Please check #piratepool in discord to see if it's already being worked on.

Pending blocks have not yet been scanned by the payment processor. After being scanned, blocks will need to receive both dPoW notarization and 10 confirmations before being actually paid out.

-

On your worker stats page, pending balance is the remaining estimated amount to be paid for blocks that - were scanned but not yet eligible for payout either because of - dPoW or min confirmations. +

On your worker stats page, pending balance is the remaining estimated amount to be paid for blocks that + were scanned but not yet eligible for payout either because of + dPoW or min confirmations. Balance includes blocks that were scanned and already paid out but you have not yet met the min payout.*

*Please note these 2 stats will only update when the payment processor runs which is currently every 4 hours.

Payments that show up on the payments page initially are in the process of constructing the z transaction. Once the transaction actually broadcasts to the network, the blocks paid out will become hyperlinked to the explorer and then should arrive in your wallet in the next block or two.

@@ -131,7 +131,7 @@

Generate Wallet and Address

-

The Agama GUI Wallet for PIRATE is available. For Agama support please visit #newpirates on Discord

+

The PirateOceanQT for PIRATE is available. For wallet support please visit #newpirates on Discord

CLI Wallet:

    @@ -172,7 +172,7 @@
  1. Bminer Lite
  2. Claymore's ZCash/BTG AMD GPU Miner
  3. Optiminer AMD
  4. - +
diff --git a/website/piratepool.io/pages/home.html b/website/piratepool.io/pages/home.html index f1a751f..60e3ce5 100644 --- a/website/piratepool.io/pages/home.html +++ b/website/piratepool.io/pages/home.html @@ -2,8 +2,11 @@
- 300K+ ARRR donated to Onboarding/Dev and Marketing funds, made possible via KMD notary node income.
- Thank you for all who voted me into KMD notary node for 2019 in SH! ❤ 🐸
+ + + Payout strategy changed to PPLNT with 1 hour payout frequency! Join #piratepool for support and discussion! 🐸 +
piratepool.io - knomp @@ -11,8 +14,15 @@

piratepool.io

Mining Pool For PirateChain (ARRR)

+

+ Donating 66% of the pool fee to the PirateChain project!
+ 33% to PIRATE dev and onboarding fund +
+ 33% to PIRATE Marketing!
+

Algorithm: Equihash
Payout Frequency: {{=it.poolsConfigs['arrr'].paymentProcessing.paymentInterval/60/60}} Hours
' + + ' Blocks: [' + paymentstat.blocks.length + '] ' + + explorerlink + '
Time: ' + readableDate(paymentstat.time) + ' Miners: ' + paymentstat.miners + ' Shares: ' + bigNumber(paymentstat.shares) + ' Amount: ' + paymentstat.paid + ' ' + stats.pools[pool].symbol + ' Address: '+ middleEllipsis(addr, 20) + ' Shares: ' + bigNumber(workerstat.shares) + ' Efficiency: ' + minerEfficiency + '% Hashrate: ' + workerstat.hashrateString + '
+ @@ -36,19 +46,15 @@

- 1/3rd of the pool fee is donated to the PIRATE onboarding fund and
- 1/3rd is donated to PIRATE Marketing!
-

-

- Sprout stratum has been retired! Final Sprout Payouts Report + Download the latest PirateOcean wallet and create a sapling address (starts with zs1) and connect to the new stratum ports labeled as arrr on Getting Started.

- Download the latest Agama wallet and create a sapling address (starts with zs1) and connect to the new stratum ports labeled as arrr on Getting Started. + {{ /* Sprout stratum has been retired! Final Sprout Payouts Report */ }}

-

+

diff --git a/website/piratepool.io/pages/miner_stats.html b/website/piratepool.io/pages/miner_stats.html index 535439d..8ff9fe8 100644 --- a/website/piratepool.io/pages/miner_stats.html +++ b/website/piratepool.io/pages/miner_stats.html @@ -1,5 +1,11 @@ {{ function middleEllipsis(x) { return x.length > 40 ? x.substring(0, 20) + '...' + x.substring(x.length-20, x.length): x; } }} +{{ function checkCompromised(m) { var compromised = ['zs10jprfefpt2ra88u2ml96nzh3dmlqqqfeha5l7g0x0s0d2awme0eqfyt4w7r7pee0na8tcz6ezzj', 'zs12urwtysy5rkqzy3xgaxeu9g3ezf4fr0wfq44xrnf48uq6ug8qfxp059lms06khekppquvzadxyf', 'zs16sk9n6lyc8ulzkrf5xc72cr07hkyjvvj2emeqjel7xmn90qaf9mj2m8vt34yw45l7syqxlmfe5v', 'zs16xlsu48grwgsr29c9ztcn8jl0s47rtyucv3dw0n2e6y00w0wtt3d4ukqk4sq4sycrdhtxxg7g3k', 'zs19whs7s29a2kn5d4s8mpdad0m4setz86sq64kpv0t2v263mrqvuducp6nlmlwvynltam9zm9mr0p', 'zs1au66ft2gyu8ylgkw70vy4we2ktzum52esl94875w44mu8cmw2dcwfc29kahgmvfwcagwy39ctee', 'zs1c83zjak7ealmn92hejmqmjc7h3ysvglc9n95z79dhajth4fmhmrnv5zxdkufzg6l489y6hwf694', 'zs1d9myt9rpvu6grsl3ntg9wv0dfuj4vhp4rr0m3f940tt6fpxy8adpx4uzs7hgtclqtqe4wq2sjr8', 'zs1df3t2wpdmsjmzd7pwet67grfgr900fg6hjy97hl9vv0tkf7w5eye2zur6xhhzhfxdceu740g04g', 'zs1g342mavfn70xf5pycn8xwu2zsc4vq3fe8zzg99dfkdsdr39rqszvnuzxdp238d3uaqg96mmrclq', 'zs1gp9egrus6zrjqmea23nae7pzpxdy9jt3w65j8netsrcctl3g9e0lrag4tgvctw3r7rhryj4f4ua', 'zs1jttxxfwurarqw3cmkf94ygfs8skh7xxjf83wuh4awq6zjcee9p804p6aurmxv5q02f2uxc3qm93', 'zs1kqaakh9tw8uj039e9hzkh0444rw533uh8r5http8mfjuakmglqyqrjvd2ertnk8j9jlvvnzne9r', 'zs1lpp9qdtj9tkqjfj64wkcprvp2kflpu8cxz8fgclx80uuu4ajsmslkxkx0fh49cpw2yyhxwk0yzg', 'zs1pd047rvjf6es3ypx6vnl7vgnngmt3mkegn4vjtymfy26rxzp97mpjw5y2gkmyljmk99qs2wa4c0', 'zs1qsr5r8fp9scdz4wt08h4uxnlmefl0dmukuzxzs3f8wx6tk6ged399c9taphhx0asagryjkqgya7', 'zs1r4kfr08dm5yx60yg535dzhnpg8m8s4dl8ap42exkwm6699prpw9zu8sgj6xjd5efmrnj6p4u0an', 'zs1sfj20kyt95sfvll20lraw5q22q2aagw2r3pcdgtlaw4epc9sdwymxzdsge8c84f707ytqpjlnx4', 'zs1stzrmj7rfwr8g0hcsgs7aln0vxwcss6h7qfvzkyf9f6vuupeq6eqhrx7kwa0kmm5dawf7f9j8hr', 'zs1u7sy6prj270ucxwcwh9sh7vr33lnlgs6a95nt4hzgwxwvtcesu240px90822mffc0epf2kjlrjq', 'zs1ued52v4gv83yrguw4gpp4j85mtz9euedmwlszqmldl99cgefz8tz4y60ttjgm4avpqegyhnesns', 'zs1uhnyckurr2x4e8ak6ffqes4ggth8n2vxlzyksd8ufv9zltdhggdnxcx4q2jfn8tuea3f7w4yevs', 'zs1v569xvf7klgw8ylgf0dvtd92dtmu669xcqv05qvxud78nt4zwwcjdz046ghq7lvs4r0d227sgrv', 'zs1xl7l6sn0r5nsa6cex87yp3z7j2mj9jgf32dng6qqp7ym66s8wkx9lykmd896uq62e5xlq2mkaqq', 'zs1yxspuhm7fd5ffrjlmxtsyuryaj983paurt794rg87ln98ekdsugexl7kfvjw97ejhv66ytd3454', 'zs1yyeyhf856aag8vxlq4mkhjs8qjrlxfzz67s4jgjazpedrqfj62tr4zkp3tsj6cgc3hggq4t5raf', 'zs1z4aqxzy2krpvu45mfqes74a20yjmeuxlj0s4x89zr932panatzsfh8wf90qulh5683cgg9q0u2v']; return compromised.indexOf(m) > -1; } }}
+ {{ if (checkCompromised(it.stats.address)) { }} +
+ Your wallet address was possibly comporomised! Please visit discord for more details! +
+ {{ } }}
@@ -25,4 +31,4 @@ var _workerCount = 0; document.querySelector('main').appendChild(document.createElement('script')).src = '/static/miner_stats.js'; -
\ No newline at end of file +
diff --git a/website/piratepool.io/pages/payments.html b/website/piratepool.io/pages/payments.html index ea1c5af..02986ae 100644 --- a/website/piratepool.io/pages/payments.html +++ b/website/piratepool.io/pages/payments.html @@ -1,11 +1,11 @@ -{{ -function readableDate(a){ - return new Date(parseInt(a)).toISOString().substring(0, 16).replace('T', ' ') + ' UTC'; +{{ +function readableDate(a){ + return new Date(parseInt(a)).toISOString().substring(0, 16).replace('T', ' ') + ' UTC'; } -function bigNumber(x){ - return (x > 1000000000000) ? (x / 1000000000000).toFixed(1) + 'T' : (x > 1000000000) ? (x / 1000000000).toFixed(1) + 'B' : (x > 1000000) ? (x / 1000000).toFixed(1) + 'M' : (x > 1000) ? (x / 1000).toFixed(1) + 'K' : x.toFixed(1); +function bigNumber(x){ + return (x > 1000000000000) ? (x / 1000000000000).toFixed(1) + 'T' : (x > 1000000000) ? (x / 1000000000).toFixed(1) + 'B' : (x > 1000000) ? (x / 1000000).toFixed(1) + 'M' : (x > 1000) ? (x / 1000).toFixed(1) + 'K' : x.toFixed(1); } -function timeTil(x){ +function timeTil(x){ return (x < 0) ? 'Now' : (x > 86400) ? (x/86400).toFixed(1) + ' Days' : (x > 3600) ? (x/3600).toFixed(1) + ' Hours' : (x > 60) ? (x / 60).toFixed(1) + ' Minutes' : x + ' Seconds'; } function timeTilNumbers(timestamp) { @@ -13,7 +13,11 @@ function timeTilNumbers(timestamp) { } }}
-
Payout frequency has been changed to 4 hours because miners have been mining to exchange addresses…
+
+ + + Payout strategy changed to PPLNT with 1 hour payout frequency! Join #piratepool for support and discussion! 🐸 +
{{ for(var pool in it.stats.pools) { }}
{{=it.stats.pools[pool].name}} Payments   
@@ -37,7 +41,7 @@ function timeTilNumbers(timestamp) {
{{ for(var p in it.stats.pools[pool].payments) { }} -
Algorithm: Equihash
Payout Strategy: PPLNT
Payout Frequency: {{=it.poolsConfigs['arrr'].paymentProcessing.paymentInterval/60/60}} Hours
Min Payout: {{=it.poolsConfigs['arrr'].paymentProcessing.minimumPayment}} ARRR
Pool Fee: 1%
+ Blocks: [{{=it.stats.pools[pool].payments[p].blocks.length}}] {{if (String(it.stats.pools[pool].name) == "KMD") { }} {{=it.stats.pools[pool].payments[p].blocks}} @@ -57,8 +61,8 @@ function timeTilNumbers(timestamp) {
{{ } }} - + -
\ No newline at end of file +
diff --git a/website/piratepool.io/pages/stats.html b/website/piratepool.io/pages/stats.html index 4828ae4..9a389ad 100644 --- a/website/piratepool.io/pages/stats.html +++ b/website/piratepool.io/pages/stats.html @@ -3,6 +3,10 @@ {{ function bigNumber(x){ return (x > 1000000000000) ? (x / 1000000000000).toFixed(1) + 'T' : (x > 1000000000) ? (x / 1000000000).toFixed(1) + 'B' : (x > 1000000) ? (x / 1000000).toFixed(1) + 'M' : (x > 1000) ? (x / 1000).toFixed(1) + 'K' : x.toFixed(1); } }} {{ function middleEllipsis(x) { return x.length > 40 ? x.substring(0, 15) + '...' + x.substring(x.length-15, x.length): x; } }}
+
+ + Payout strategy changed to PPLNT with 1 hour payout frequency! Join #piratepool for support and discussion! 🐸 +

Pool Hashrate

@@ -35,7 +39,7 @@
  • Block Height: {{=it.stats.pools[pool].poolStats.networkBlocks}}
  • Network Hash/s: {{=it.stats.pools[pool].poolStats.networkSolsString}}
  • Difficulty: {{=bigNumber(it.stats.pools[pool].poolStats.networkDiff)}}
  • -
  • Total Supply: {{=(it.stats.pools[pool].poolStats.networkBlocks*256).toLocaleString('en')}}
  • +
  • Total Supply: {{=(99554304+(it.stats.pools[pool].poolStats.networkBlocks-388884)*128).toLocaleString('en')}}
  • Node Connections: {{=it.stats.pools[pool].poolStats.networkConnections}}
  • @@ -79,7 +83,6 @@ Pending {{ } }}
    -
    Mined By: {{=middleEllipsis(block[3])}}
    {{ } }} @@ -95,7 +98,6 @@ {{ } }} Paid
    -
    Mined By: {{=middleEllipsis(block[3])}}
    {{ } }} diff --git a/website/piratepool.io/pages/workers.html b/website/piratepool.io/pages/workers.html index 8bdd7f4..966149d 100644 --- a/website/piratepool.io/pages/workers.html +++ b/website/piratepool.io/pages/workers.html @@ -6,7 +6,7 @@
    - Miner Lookup: + Miner Lookup: @@ -24,22 +24,24 @@ - + + {{ var minerindex = 0; }} {{ for(var worker in it.stats.pools[pool].miners) { }} + {{ minerindex++; }} {{var workerstat = it.stats.pools[pool].miners[worker];}} - - + + - {{ } }} + {{ } }}
    AddressMiner Shares Efficiency Hashrate
    Address: {{=middleEllipsis(worker)}}
    Miner #{{=minerindex}} Shares: {{=bigNumber(workerstat.currRoundShares)}} Efficiency: {{? workerstat.shares > 0}} {{=Math.floor(10000 * workerstat.shares / (workerstat.shares + workerstat.invalidshares)) / 100}}% {{??}} 0% {{?}} Hashrate: {{=workerstat.hashrateString}}
    @@ -48,4 +50,4 @@ -
    \ No newline at end of file + From a7e42712bff37b39b85a6e1de279dd52004292b0 Mon Sep 17 00:00:00 2001 From: webworker01 Date: Fri, 27 Sep 2019 04:42:56 +0000 Subject: [PATCH 16/16] Miner Privacy Update --- libs/paymentProcessor.js | 5 +- libs/stats.js | 661 +++++++++++++---------- website/default/static/miner_stats.js | 322 +++++------ website/piratepool.io/static/payments.js | 7 +- website/piratepool.io/static/stats.js | 6 +- website/piratepool.io/static/style.css | 67 +-- website/piratepool.io/static/workers.js | 22 +- 7 files changed, 592 insertions(+), 498 deletions(-) diff --git a/libs/paymentProcessor.js b/libs/paymentProcessor.js index 97e9691..5a8a9f9 100644 --- a/libs/paymentProcessor.js +++ b/libs/paymentProcessor.js @@ -603,7 +603,10 @@ function SetupForPool(logger, poolOptions, setupFinished) { let minerAddressPrefix = address.substring(0,2); let checkPrefix = (poolOptions.minerPrefix || false); - if (privateChain && poolZAddressPrefix == 'zs' && minerAddressLength == 78 && minerAddressPrefix == 'zs') { + if (typeof poolOptions.rewardsDisabled !== 'undefined' && poolOptions.rewardsDisabled.includes(address)) { + logger.warning(logSystem, logComponent, 'Rewards disabled for this adddress: ' + address + ', convert to address ' + (poolOptions.invalidAddress || poolOptions.address)); + return (poolOptions.invalidAddress || poolOptions.address); + } else if (privateChain && poolZAddressPrefix == 'zs' && minerAddressLength == 78 && minerAddressPrefix == 'zs') { //validate as sapling return address; } else if (privateChain && poolZAddressPrefix == 'zc' && minerAddressLength == 95 && minerAddressPrefix == 'zc') { diff --git a/libs/stats.js b/libs/stats.js index b0049cd..d647db2 100644 --- a/libs/stats.js +++ b/libs/stats.js @@ -25,31 +25,31 @@ function rediscreateClient(port, host, pass) { * @returns {Array} array of items in [[key,value],[key,value],...] format. */ function sortProperties(obj, sortedBy, isNumericSort, reverse) { - sortedBy = sortedBy || 1; // by default first key - isNumericSort = isNumericSort || false; // by default text sort - reverse = reverse || false; // by default no reverse - - var reversed = (reverse) ? -1 : 1; - - var sortable = []; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - sortable.push([key, obj[key]]); - } - } - if (isNumericSort) - sortable.sort(function (a, b) { - return reversed * (a[1][sortedBy] - b[1][sortedBy]); - }); - else - sortable.sort(function (a, b) { - var x = a[1][sortedBy].toLowerCase(), - y = b[1][sortedBy].toLowerCase(); - return x < y ? reversed * -1 : x > y ? reversed : 0; - }); - return sortable; // array in format [ [ key1, val1 ], [ key2, val2 ], ... ] + sortedBy = sortedBy || 1; // by default first key + isNumericSort = isNumericSort || false; // by default text sort + reverse = reverse || false; // by default no reverse + + var reversed = (reverse) ? -1 : 1; + + var sortable = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + sortable.push([key, obj[key]]); + } + } + if (isNumericSort) + sortable.sort(function (a, b) { + return reversed * (a[1][sortedBy] - b[1][sortedBy]); + }); + else + sortable.sort(function (a, b) { + var x = a[1][sortedBy].toLowerCase(), + y = b[1][sortedBy].toLowerCase(); + return x < y ? reversed * -1 : x > y ? reversed : 0; + }); + return sortable; // array in format [ [ key1, val1 ], [ key2, val2 ], ... ] } - + module.exports = function(logger, portalConfig, poolConfigs){ var _this = this; @@ -101,19 +101,29 @@ module.exports = function(logger, portalConfig, poolConfigs){ async.each(_this.stats.pools, function(pool, pcb) { if (_this.stats.pools[pool.name].pending && _this.stats.pools[pool.name].pending.blocks) - for (var i=0; i<_this.stats.pools[pool.name].pending.blocks.length; i++) - allBlocks[pool.name+"-"+_this.stats.pools[pool.name].pending.blocks[i].split(':')[2]] = _this.stats.pools[pool.name].pending.blocks[i]; - + for (var i=0; i<_this.stats.pools[pool.name].pending.blocks.length; i++) { + let blockoutput = _this.stats.pools[pool.name].pending.blocks[i].split(':'); + blockoutput[3] = pool.name + '-miner'; + blockoutput = blockoutput.join(':'); + + allBlocks[pool.name+"-"+_this.stats.pools[pool.name].pending.blocks[i].split(':')[2]] = blockoutput; + } + if (_this.stats.pools[pool.name].confirmed && _this.stats.pools[pool.name].confirmed.blocks) - for (var i=0; i<_this.stats.pools[pool.name].confirmed.blocks.length; i++) - allBlocks[pool.name+"-"+_this.stats.pools[pool.name].confirmed.blocks[i].split(':')[2]] = _this.stats.pools[pool.name].confirmed.blocks[i]; - + for (var i=0; i<_this.stats.pools[pool.name].confirmed.blocks.length; i++) { + let blockoutput = _this.stats.pools[pool.name].confirmed.blocks[i].split(':'); + blockoutput[3] = pool.name + '-miner'; + blockoutput = blockoutput.join(':'); + + allBlocks[pool.name+"-"+_this.stats.pools[pool.name].confirmed.blocks[i].split(':')[2]] = blockoutput; + } + pcb(); }, function(err) { - cback(allBlocks); + cback(allBlocks); }); }; - + function gatherStatHistory(){ var retentionTime = (((Date.now() / 1000) - portalConfig.website.stats.historicalRetention) | 0).toString(); redisStats.zrangebyscore(['statHistory', retentionTime, '+inf'], function(err, replies){ @@ -133,34 +143,34 @@ module.exports = function(logger, portalConfig, poolConfigs){ }); } - function getWorkerStats(address) { - address = address.split(".")[0]; - if (address.length > 0 && address.startsWith('t')) { - for (var h in statHistory) { - for(var pool in statHistory[h].pools) { - - statHistory[h].pools[pool].workers.sort(sortWorkersByHashrate); - - for(var w in statHistory[h].pools[pool].workers){ - if (w.startsWith(address)) { - if (history[w] == null) { - history[w] = []; - } - if (workers[w] == null && stats.pools[pool].workers[w] != null) { - workers[w] = stats.pools[pool].workers[w]; - } - if (statHistory[h].pools[pool].workers[w].hashrate) { - history[w].push({time: statHistory[h].time, hashrate:statHistory[h].pools[pool].workers[w].hashrate}); - } - } - } - } - } - return JSON.stringify({"workers": workers, "history": history}); - } - return null; - } - + function getWorkerStats(address) { + address = address.split(".")[0]; + if (address.length > 0 && address.startsWith('t')) { + for (var h in statHistory) { + for(var pool in statHistory[h].pools) { + + statHistory[h].pools[pool].workers.sort(sortWorkersByHashrate); + + for(var w in statHistory[h].pools[pool].workers){ + if (w.startsWith(address)) { + if (history[w] == null) { + history[w] = []; + } + if (workers[w] == null && stats.pools[pool].workers[w] != null) { + workers[w] = stats.pools[pool].workers[w]; + } + if (statHistory[h].pools[pool].workers[w].hashrate) { + history[w].push({time: statHistory[h].time, hashrate:statHistory[h].pools[pool].workers[w].hashrate}); + } + } + } + } + } + return JSON.stringify({"workers": workers, "history": history}); + } + return null; + } + function addStatPoolHistory(stats){ var data = { time: stats.time, @@ -175,10 +185,10 @@ module.exports = function(logger, portalConfig, poolConfigs){ } _this.statPoolHistory.push(data); } - + var magnitude = 100000000; var coinPrecision = magnitude.toString().length - 1; - + function roundTo(n, digits) { if (digits === undefined) { digits = 0; @@ -192,7 +202,7 @@ module.exports = function(logger, portalConfig, poolConfigs){ var satoshisToCoins = function(satoshis){ return roundTo((satoshis / magnitude), coinPrecision); }; - + var coinsToSatoshies = function(coins){ return Math.round(coins * magnitude); }; @@ -200,7 +210,7 @@ module.exports = function(logger, portalConfig, poolConfigs){ function coinsRound(number) { return roundTo(number, coinPrecision); } - + function readableSeconds(t) { var seconds = Math.round(t); var minutes = Math.floor(seconds/60); @@ -219,7 +229,7 @@ module.exports = function(logger, portalConfig, poolConfigs){ _this.stats.coins = redisClients[0].coins; cback(); }; - + this.getPayout = function(address, cback){ async.waterfall([ function(callback){ @@ -231,38 +241,38 @@ module.exports = function(logger, portalConfig, poolConfigs){ cback(coinsRound(total).toFixed(8)); }); }; - - this.getTotalSharesByAddress = function(address, cback) { - var a = address.split(".")[0]; + + this.getTotalSharesByAddress = function(address, cback) { + var a = address.split(".")[0]; var client = redisClients[0].client, coins = redisClients[0].coins, shares = []; var pindex = parseInt(0); - var totalShares = parseFloat(0); - async.each(_this.stats.pools, function(pool, pcb) { + var totalShares = parseFloat(0); + async.each(_this.stats.pools, function(pool, pcb) { pindex++; - var coin = String(_this.stats.pools[pool.name].name); - client.hscan(coin + ':shares:roundCurrent', 0, "match", a+"*", "count", 1000, function(error, result) { + var coin = String(_this.stats.pools[pool.name].name); + client.hscan(coin + ':shares:roundCurrent', 0, "match", a+"*", "count", 1000, function(error, result) { if (error) { pcb(error); return; } - var workerName=""; - var shares = 0; - for (var i in result[1]) { - if (Math.abs(i % 2) != 1) { - workerName = String(result[1][i]); - } else { - shares += parseFloat(result[1][i]); - } - } + var workerName=""; + var shares = 0; + for (var i in result[1]) { + if (Math.abs(i % 2) != 1) { + workerName = String(result[1][i]); + } else { + shares += parseFloat(result[1][i]); + } + } if (shares>0) { totalShares = shares; } pcb(); - }); - }, function(err) { + }); + }, function(err) { if (err) { cback(0); return; @@ -271,37 +281,37 @@ module.exports = function(logger, portalConfig, poolConfigs){ cback(totalShares); return; } - }); - }; + }); + }; this.getBalanceByAddress = function(address, cback){ - var a = address.split(".")[0]; - + var a = address.split(".")[0]; + var client = redisClients[0].client, coins = redisClients[0].coins, balances = []; - - var totalHeld = parseFloat(0); - var totalPaid = parseFloat(0); + + var totalHeld = parseFloat(0); + var totalPaid = parseFloat(0); var totalImmature = parseFloat(0); - - async.each(_this.stats.pools, function(pool, pcb) { - var coin = String(_this.stats.pools[pool.name].name); - // get all immature balances from address - client.hscan(coin + ':immature', 0, "match", a+"*", "count", 10000, function(error, pends) { + + async.each(_this.stats.pools, function(pool, pcb) { + var coin = String(_this.stats.pools[pool.name].name); + // get all immature balances from address + client.hscan(coin + ':immature', 0, "match", a+"*", "count", 10000, function(error, pends) { // get all balances from address client.hscan(coin + ':balances', 0, "match", a+"*", "count", 10000, function(error, bals) { // get all payouts from address client.hscan(coin + ':payouts', 0, "match", a+"*", "count", 10000, function(error, pays) { - + var workerName = ""; var balAmount = 0; var paidAmount = 0; var pendingAmount = 0; - + var workers = {}; - + for (var i in pays[1]) { if (Math.abs(i % 2) != 1) { workerName = String(pays[1][i]); @@ -335,7 +345,7 @@ module.exports = function(logger, portalConfig, poolConfigs){ totalImmature += pendingAmount; } } - + for (var w in workers) { balances.push({ worker:String(w), @@ -344,23 +354,23 @@ module.exports = function(logger, portalConfig, poolConfigs){ immature:workers[w].immature }); } - + pcb(); }); }); }); - }, function(err) { - if (err) { - callback("There was an error getting balances"); - return; - } - - _this.stats.balances = balances; - _this.stats.address = address; - - cback({totalHeld:coinsRound(totalHeld), totalPaid:coinsRound(totalPaid), totalImmature:satoshisToCoins(totalImmature), balances}); - }); - }; + }, function(err) { + if (err) { + callback("There was an error getting balances"); + return; + } + + _this.stats.balances = balances; + _this.stats.address = address; + + cback({totalHeld:coinsRound(totalHeld), totalPaid:coinsRound(totalPaid), totalImmature:satoshisToCoins(totalImmature), balances}); + }); + }; this.getGlobalStats = function(callback){ @@ -379,9 +389,9 @@ module.exports = function(logger, portalConfig, poolConfigs){ ['scard', ':blocksPending'], ['scard', ':blocksConfirmed'], ['scard', ':blocksKicked'], - ['smembers', ':blocksPending'], - ['smembers', ':blocksConfirmed'], - ['hgetall', ':shares:roundCurrent'], + ['smembers', ':blocksPending'], + ['smembers', ':blocksConfirmed'], + ['hgetall', ':shares:roundCurrent'], ['hgetall', ':blocksPendingConfirms'], ['zrange', ':payments', -100, -1], ['hgetall', ':shares:timesCurrent'] @@ -411,6 +421,39 @@ module.exports = function(logger, portalConfig, poolConfigs){ marketStats = replies[i + 2] ? (JSON.parse(replies[i + 2].coinmarketcap)[0] || 0) : 0; } } + + //anonymize currentRoundShares + let currentRoundSharesIndex = 0; + for (var worker in replies[i + 8]) { + Object.defineProperty(replies[i+8], 'worker' + currentRoundSharesIndex, Object.getOwnPropertyDescriptor(replies[i+8], worker)); + delete replies[i+8][worker]; + currentRoundSharesIndex++; + } + + //anonymize currentRoundTimes + let currentRoundTimesIndex = 0; + for (var worker in replies[i + 11]) { + Object.defineProperty(replies[i+11], 'worker' + currentRoundTimesIndex, Object.getOwnPropertyDescriptor(replies[i+11], worker)); + delete replies[i+11][worker]; + currentRoundTimesIndex++; + } + + //anonymize confirmed blocks + for (var b=0; b < replies[i + 7].length; b++) { + let blockoutput = replies[i + 7][b].split(':'); + blockoutput[3] = coinName + '-miner'; + blockoutput = blockoutput.join(':'); + replies[i + 7][b] = blockoutput; + } + + //anonymize pending blocks + for (var b=0; b < replies[i + 6].length; b++) { + let blockoutput = replies[i + 6][b].split(':'); + blockoutput[3] = coinName + '-miner'; + blockoutput = blockoutput.join(':'); + replies[i + 6][b] = blockoutput; + } + var coinStats = { name: coinName, symbol: poolConfigs[coinName].coin.symbol.toUpperCase(), @@ -421,11 +464,11 @@ module.exports = function(logger, portalConfig, poolConfigs){ validBlocks: replies[i + 2] ? (replies[i + 2].validBlocks || 0) : 0, invalidShares: replies[i + 2] ? (replies[i + 2].invalidShares || 0) : 0, totalPaid: replies[i + 2] ? (replies[i + 2].totalPaid || 0) : 0, - networkBlocks: replies[i + 2] ? (replies[i + 2].networkBlocks || 0) : 0, - networkSols: replies[i + 2] ? (replies[i + 2].networkSols || 0) : 0, - networkSolsString: getReadableNetworkHashRateString(replies[i + 2] ? (replies[i + 2].networkSols || 0) : 0), - networkDiff: replies[i + 2] ? (replies[i + 2].networkDiff || 0) : 0, - networkConnections: replies[i + 2] ? (replies[i + 2].networkConnections || 0) : 0, + networkBlocks: replies[i + 2] ? (replies[i + 2].networkBlocks || 0) : 0, + networkSols: replies[i + 2] ? (replies[i + 2].networkSols || 0) : 0, + networkSolsString: getReadableNetworkHashRateString(replies[i + 2] ? (replies[i + 2].networkSols || 0) : 0), + networkDiff: replies[i + 2] ? (replies[i + 2].networkDiff || 0) : 0, + networkConnections: replies[i + 2] ? (replies[i + 2].networkConnections || 0) : 0, networkVersion: replies[i + 2] ? (replies[i + 2].networkSubVersion || 0) : 0, networkProtocolVersion: replies[i + 2] ? (replies[i + 2].networkProtocolVersion || 0) : 0 }, @@ -437,16 +480,16 @@ module.exports = function(logger, portalConfig, poolConfigs){ orphaned: replies[i + 5] }, /* show all pending blocks */ - pending: { - blocks: replies[i + 6].sort(sortBlocks), + pending: { + blocks: replies[i + 6].sort(sortBlocks), confirms: (replies[i + 9] || {}) - }, + }, /* show last 50 found blocks */ - confirmed: { - blocks: replies[i + 7].sort(sortBlocks).slice(0,50) - }, + confirmed: { + blocks: replies[i + 7].sort(sortBlocks).slice(0,50) + }, payments: [], - currentRoundShares: (replies[i + 8] || {}), + currentRoundShares: (replies[i + 8] || {}), currentRoundTimes: (replies[i + 11] || {}), maxRoundTime: 0, shareCount: 0, @@ -459,7 +502,31 @@ module.exports = function(logger, portalConfig, poolConfigs){ } catch(e) { jsonObj = null; } - if (jsonObj !== null) { + if (jsonObj !== null) { + //Anonymize paid amounts + let paymentIndex = 0; + for (var payment in jsonObj.amounts) { + Object.defineProperty(jsonObj.amounts, 'miner' + paymentIndex, Object.getOwnPropertyDescriptor(jsonObj.amounts, payment)); + delete jsonObj.amounts[payment]; + paymentIndex++; + } + + //Anonymize balances + let balanceIndex = 0; + for (var balance in jsonObj.balances) { + Object.defineProperty(jsonObj.balances, 'miner' + balanceIndex, Object.getOwnPropertyDescriptor(jsonObj.balances, balance)); + delete jsonObj.balances[balance]; + balanceIndex++; + } + + //Anonymize work + let workIndex = 0; + for (var work in jsonObj.work) { + Object.defineProperty(jsonObj.work, 'miner' + workIndex, Object.getOwnPropertyDescriptor(jsonObj.work, work)); + delete jsonObj.work[work]; + workIndex++; + } + coinStats.payments.push(jsonObj); } } @@ -491,103 +558,120 @@ module.exports = function(logger, portalConfig, poolConfigs){ Object.keys(allCoinStats).forEach(function(coin){ var coinStats = allCoinStats[coin]; coinStats.workers = {}; - coinStats.miners = {}; + coinStats.miners = {}; coinStats.shares = 0; coinStats.hashrates.forEach(function(ins){ var parts = ins.split(':'); var workerShares = parseFloat(parts[0]); - var miner = parts[1].split('.')[0]; + var miner = parts[1].split('.')[0]; var worker = parts[1]; - var diff = Math.round(parts[0] * 8192); + var diff = Math.round(parts[0] * 8192); if (workerShares > 0) { coinStats.shares += workerShares; - // build worker stats + // build worker stats if (worker in coinStats.workers) { coinStats.workers[worker].shares += workerShares; - coinStats.workers[worker].diff = diff; + coinStats.workers[worker].diff = diff; } else { coinStats.workers[worker] = { - name: worker, - diff: diff, + name: worker, + diff: diff, shares: workerShares, invalidshares: 0, - currRoundShares: 0, + currRoundShares: 0, currRoundTime: 0, - hashrate: null, + hashrate: null, hashrateString: null, - luckDays: null, - luckHours: null, - paid: 0, - balance: 0 + luckDays: null, + luckHours: null, + paid: 0, + balance: 0 }; - } - // build miner stats - if (miner in coinStats.miners) { - coinStats.miners[miner].shares += workerShares; - } else { - coinStats.miners[miner] = { - name: miner, - shares: workerShares, - invalidshares: 0, - currRoundShares: 0, + } + // build miner stats + if (miner in coinStats.miners) { + coinStats.miners[miner].shares += workerShares; + } else { + coinStats.miners[miner] = { + name: miner, + shares: workerShares, + invalidshares: 0, + currRoundShares: 0, currRoundTime: 0, - hashrate: null, - hashrateString: null, - luckDays: null, - luckHours: null - }; - } - } - else { - // build worker stats + hashrate: null, + hashrateString: null, + luckDays: null, + luckHours: null + }; + } + } else { + // build worker stats if (worker in coinStats.workers) { coinStats.workers[worker].invalidshares -= workerShares; // workerShares is negative number! - coinStats.workers[worker].diff = diff; + coinStats.workers[worker].diff = diff; } else { coinStats.workers[worker] = { - name: worker, - diff: diff, + name: worker, + diff: diff, shares: 0, - invalidshares: -workerShares, - currRoundShares: 0, + invalidshares: -workerShares, + currRoundShares: 0, currRoundTime: 0, - hashrate: null, + hashrate: null, hashrateString: null, - luckDays: null, - luckHours: null, - paid: 0, - balance: 0 + luckDays: null, + luckHours: null, + paid: 0, + balance: 0 }; - } - // build miner stats - if (miner in coinStats.miners) { - coinStats.miners[miner].invalidshares -= workerShares; // workerShares is negative number! - } else { - coinStats.miners[miner] = { - name: miner, - shares: 0, - invalidshares: -workerShares, - currRoundShares: 0, + } + // build miner stats + if (miner in coinStats.miners) { + coinStats.miners[miner].invalidshares -= workerShares; // workerShares is negative number! + } else { + coinStats.miners[miner] = { + name: miner, + shares: 0, + invalidshares: -workerShares, + currRoundShares: 0, currRoundTime: 0, - hashrate: null, - hashrateString: null, - luckDays: null, - luckHours: null - }; - } + hashrate: null, + hashrateString: null, + luckDays: null, + luckHours: null + }; + } } }); - + + //anonymize miners + let minerindex = 0; + for (var miner in coinStats.miners) { + Object.defineProperty(coinStats.miners, 'miner' + minerindex, Object.getOwnPropertyDescriptor(coinStats.miners, miner)); + coinStats.miners['miner' + minerindex].name = 'miner' + minerindex; + delete coinStats.miners[miner]; + minerindex++; + } + + //anonymize workers + let workerindex = 0; + for (var worker in coinStats.workers) { + Object.defineProperty(coinStats.workers, 'worker' + workerindex, Object.getOwnPropertyDescriptor(coinStats.workers, worker)); + coinStats.workers['worker' + workerindex].name = 'worker' + workerindex; + delete coinStats.workers[worker]; + workerindex++; + } + var shareMultiplier = Math.pow(2, 32) / algos[coinStats.algorithm].multiplier; coinStats.hashrate = shareMultiplier * coinStats.shares / portalConfig.website.stats.hashrateWindow; coinStats.hashrateString = _this.getReadableHashRateString(coinStats.hashrate); - + var _blocktime = 160; - var _networkHashRate = parseFloat(coinStats.poolStats.networkSols) * 1.2; - var _myHashRate = (coinStats.hashrate / 1000000) * 2; - coinStats.luckDays = ((_networkHashRate / _myHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3); - coinStats.luckHours = ((_networkHashRate / _myHashRate * _blocktime) / (60 * 60)).toFixed(3); - coinStats.minerCount = Object.keys(coinStats.miners).length; + var _networkHashRate = parseFloat(coinStats.poolStats.networkSols) * 1.2; + var _myHashRate = (coinStats.hashrate / 1000000) * 2; + coinStats.luckDays = ((_networkHashRate / _myHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3); + coinStats.luckHours = ((_networkHashRate / _myHashRate * _blocktime) / (60 * 60)).toFixed(3); + coinStats.minerCount = Object.keys(coinStats.miners).length; coinStats.workerCount = Object.keys(coinStats.workers).length; portalStats.global.workers += coinStats.workerCount; @@ -627,29 +711,29 @@ module.exports = function(logger, portalConfig, poolConfigs){ coinStats.shareCount = _shareTotal; coinStats.maxRoundTime = _maxTimeShare; coinStats.maxRoundTimeString = readableSeconds(_maxTimeShare); - + for (var worker in coinStats.workers) { - var _workerRate = shareMultiplier * coinStats.workers[worker].shares / portalConfig.website.stats.hashrateWindow; - var _wHashRate = (_workerRate / 1000000) * 2; - coinStats.workers[worker].luckDays = ((_networkHashRate / _wHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3); - coinStats.workers[worker].luckHours = ((_networkHashRate / _wHashRate * _blocktime) / (60 * 60)).toFixed(3); - coinStats.workers[worker].hashrate = _workerRate; - coinStats.workers[worker].hashrateString = _this.getReadableHashRateString(_workerRate); - var miner = worker.split('.')[0]; - if (miner in coinStats.miners) { - coinStats.workers[worker].currRoundTime = coinStats.miners[miner].currRoundTime; - } + var _workerRate = shareMultiplier * coinStats.workers[worker].shares / portalConfig.website.stats.hashrateWindow; + var _wHashRate = (_workerRate / 1000000) * 2; + coinStats.workers[worker].luckDays = ((_networkHashRate / _wHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3); + coinStats.workers[worker].luckHours = ((_networkHashRate / _wHashRate * _blocktime) / (60 * 60)).toFixed(3); + coinStats.workers[worker].hashrate = _workerRate; + coinStats.workers[worker].hashrateString = _this.getReadableHashRateString(_workerRate); + var miner = worker.split('.')[0]; + if (miner in coinStats.miners) { + coinStats.workers[worker].currRoundTime = coinStats.miners[miner].currRoundTime; + } } - for (var miner in coinStats.miners) { - var _workerRate = shareMultiplier * coinStats.miners[miner].shares / portalConfig.website.stats.hashrateWindow; - var _wHashRate = (_workerRate / 1000000) * 2; - coinStats.miners[miner].luckDays = ((_networkHashRate / _wHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3); - coinStats.miners[miner].luckHours = ((_networkHashRate / _wHashRate * _blocktime) / (60 * 60)).toFixed(3); - coinStats.miners[miner].hashrate = _workerRate; - coinStats.miners[miner].hashrateString = _this.getReadableHashRateString(_workerRate); + for (var miner in coinStats.miners) { + var _workerRate = shareMultiplier * coinStats.miners[miner].shares / portalConfig.website.stats.hashrateWindow; + var _wHashRate = (_workerRate / 1000000) * 2; + coinStats.miners[miner].luckDays = ((_networkHashRate / _wHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3); + coinStats.miners[miner].luckHours = ((_networkHashRate / _wHashRate * _blocktime) / (60 * 60)).toFixed(3); + coinStats.miners[miner].hashrate = _workerRate; + coinStats.miners[miner].hashrateString = _this.getReadableHashRateString(_workerRate); } - - // sort workers by name + + // sort workers by name coinStats.workers = sortWorkersByName(coinStats.workers); coinStats.miners = sortMinersByHashrate(coinStats.miners); @@ -666,7 +750,7 @@ module.exports = function(logger, portalConfig, poolConfigs){ portalStats.pools = sortPoolsByHashrate(portalStats.pools); _this.stats = portalStats; - + // save historical hashrate, not entire stats! var saveStats = JSON.parse(JSON.stringify(portalStats)); Object.keys(saveStats.pools).forEach(function(pool){ @@ -679,9 +763,9 @@ module.exports = function(logger, portalConfig, poolConfigs){ }); _this.statsString = JSON.stringify(saveStats); _this.statHistory.push(saveStats); - - addStatPoolHistory(portalStats); - + + addStatPoolHistory(portalStats); + var retentionTime = (((Date.now() / 1000) - portalConfig.website.stats.historicalRetention) | 0); for (var i = 0; i < _this.statHistory.length; i++){ @@ -701,42 +785,43 @@ module.exports = function(logger, portalConfig, poolConfigs){ if (err) logger.error(logSystem, 'Historics', 'Error adding stats to historics ' + JSON.stringify(err)); }); + callback(); }); }; function sortPoolsByName(objects) { - var newObject = {}; - var sortedArray = sortProperties(objects, 'name', false, false); - for (var i = 0; i < sortedArray.length; i++) { - var key = sortedArray[i][0]; - var value = sortedArray[i][1]; - newObject[key] = value; - } - return newObject; + var newObject = {}; + var sortedArray = sortProperties(objects, 'name', false, false); + for (var i = 0; i < sortedArray.length; i++) { + var key = sortedArray[i][0]; + var value = sortedArray[i][1]; + newObject[key] = value; + } + return newObject; } - + function sortPoolsByHashrate(objects) { - var newObject = {}; - var sortedArray = sortProperties(objects, 'hashrate', true, true); - for (var i = 0; i < sortedArray.length; i++) { - var key = sortedArray[i][0]; - var value = sortedArray[i][1]; - newObject[key] = value; - } - return newObject; + var newObject = {}; + var sortedArray = sortProperties(objects, 'hashrate', true, true); + for (var i = 0; i < sortedArray.length; i++) { + var key = sortedArray[i][0]; + var value = sortedArray[i][1]; + newObject[key] = value; + } + return newObject; } function sortPoolsByShares(objects) { - var newObject = {}; - var sortedArray = sortProperties(objects, 'shareSort', true, true); - for (var i = 0; i < sortedArray.length; i++) { - var key = sortedArray[i][0]; - var value = sortedArray[i][1]; - newObject[key] = value; - } - return newObject; + var newObject = {}; + var sortedArray = sortProperties(objects, 'shareSort', true, true); + for (var i = 0; i < sortedArray.length; i++) { + var key = sortedArray[i][0]; + var value = sortedArray[i][1]; + newObject[key] = value; + } + return newObject; } function sortBlocks(a, b) { @@ -746,56 +831,56 @@ module.exports = function(logger, portalConfig, poolConfigs){ if (as < bs) return 1; return 0; } - - function sortWorkersByName(objects) { - var newObject = {}; - var sortedArray = sortProperties(objects, 'name', false, false); - for (var i = 0; i < sortedArray.length; i++) { - var key = sortedArray[i][0]; - var value = sortedArray[i][1]; - newObject[key] = value; - } - return newObject; - } - - function sortMinersByHashrate(objects) { - var newObject = {}; - var sortedArray = sortProperties(objects, 'hashrate', true, true); - for (var i = 0; i < sortedArray.length; i++) { - var key = sortedArray[i][0]; - var value = sortedArray[i][1]; - newObject[key] = value; - } - return newObject; - } - - function sortWorkersByHashrate(a, b) { - if (a.hashrate === b.hashrate) { - return 0; - } - else { - return (a.hashrate < b.hashrate) ? -1 : 1; - } - } - + + function sortWorkersByName(objects) { + var newObject = {}; + var sortedArray = sortProperties(objects, 'name', false, false); + for (var i = 0; i < sortedArray.length; i++) { + var key = sortedArray[i][0]; + var value = sortedArray[i][1]; + newObject[key] = value; + } + return newObject; + } + + function sortMinersByHashrate(objects) { + var newObject = {}; + var sortedArray = sortProperties(objects, 'hashrate', true, true); + for (var i = 0; i < sortedArray.length; i++) { + var key = sortedArray[i][0]; + var value = sortedArray[i][1]; + newObject[key] = value; + } + return newObject; + } + + function sortWorkersByHashrate(a, b) { + if (a.hashrate === b.hashrate) { + return 0; + } + else { + return (a.hashrate < b.hashrate) ? -1 : 1; + } + } + this.getReadableHashRateString = function(hashrate){ - hashrate = (hashrate * 2); - if (hashrate < 1000000) { - return (Math.round(hashrate / 1000) / 1000 ).toFixed(2)+' Sol/s'; - } + hashrate = (hashrate * 2); + if (hashrate < 1000000) { + return (Math.round(hashrate / 1000) / 1000 ).toFixed(2)+' Sol/s'; + } var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ]; var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1); hashrate = (hashrate/1000) / Math.pow(1000, i + 1); return hashrate.toFixed(2) + byteUnits[i]; }; - - function getReadableNetworkHashRateString(hashrate) { - hashrate = (hashrate * 1000000); - if (hashrate < 1000000) - return '0 Sol'; - var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ]; - var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1); - hashrate = (hashrate/1000) / Math.pow(1000, i + 1); - return hashrate.toFixed(2) + byteUnits[i]; - } + + function getReadableNetworkHashRateString(hashrate) { + hashrate = (hashrate * 1000000); + if (hashrate < 1000000) + return '0 Sol'; + var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ]; + var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1); + hashrate = (hashrate/1000) / Math.pow(1000, i + 1); + return hashrate.toFixed(2) + byteUnits[i]; + } }; diff --git a/website/default/static/miner_stats.js b/website/default/static/miner_stats.js index 36b53c3..3f23ffd 100644 --- a/website/default/static/miner_stats.js +++ b/website/default/static/miner_stats.js @@ -10,14 +10,14 @@ var totalPaid; var totalShares; function getReadableHashRateString(hashrate){ - hashrate = (hashrate * 2); - if (hashrate < 1000000) { - return (Math.round(hashrate / 1000) / 1000 ).toFixed(2)+' Sol/s'; - } - var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ]; - var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1); - hashrate = (hashrate/1000) / Math.pow(1000, i + 1); - return hashrate.toFixed(2) + byteUnits[i]; + hashrate = (hashrate * 2); + if (hashrate < 1000000) { + return (Math.round(hashrate / 1000) / 1000 ).toFixed(2)+' Sol/s'; + } + var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ]; + var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1); + hashrate = (hashrate/1000) / Math.pow(1000, i + 1); + return hashrate.toFixed(2) + byteUnits[i]; } function timeOfDayFormat(timestamp){ @@ -27,95 +27,95 @@ function timeOfDayFormat(timestamp){ } function getWorkerNameFromAddress(w) { - var worker = w; - if (w.split(".").length > 1) { - worker = w.split(".")[1]; - if (worker == null || worker.length < 1) { - worker = "noname"; - } - } else { - worker = "noname"; - } - return worker; + var worker = w; + if (w.split(".").length > 1) { + worker = w.split(".")[1]; + if (worker == null || worker.length < 1) { + worker = "noname"; + } + } else { + worker = "noname"; + } + return worker; } function buildChartData(){ var workers = {}; - for (var w in statData.history) { - var worker = getWorkerNameFromAddress(w); - var a = workers[worker] = (workers[worker] || { - hashrate: [] - }); - for (var wh in statData.history[w]) { - a.hashrate.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]); - } - if (a.hashrate.length > workerHistoryMax) { - workerHistoryMax = a.hashrate.length; - } - } - - var i=0; + for (var w in statData.history) { + var worker = getWorkerNameFromAddress(w); + var a = workers[worker] = (workers[worker] || { + hashrate: [] + }); + for (var wh in statData.history[w]) { + a.hashrate.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]); + } + if (a.hashrate.length > workerHistoryMax) { + workerHistoryMax = a.hashrate.length; + } + } + + var i=0; workerHashrateData = []; for (var worker in workers){ workerHashrateData.push({ key: worker, - disabled: (i > Math.min((_workerCount-1), 3)), + disabled: (i > Math.min((_workerCount-1), 3)), values: workers[worker].hashrate }); - i++; + i++; } } function updateChartData(){ var workers = {}; - for (var w in statData.history) { - var worker = getWorkerNameFromAddress(w); - // get a reference to lastest workerhistory - for (var wh in statData.history[w]) { } - //var wh = statData.history[w][statData.history[w].length - 1]; - var foundWorker = false; - for (var i = 0; i < workerHashrateData.length; i++) { - if (workerHashrateData[i].key === worker) { - foundWorker = true; - if (workerHashrateData[i].values.length >= workerHistoryMax) { - workerHashrateData[i].values.shift(); - } - workerHashrateData[i].values.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]); - break; - } - } - if (!foundWorker) { - var hashrate = []; - hashrate.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]); - workerHashrateData.push({ - key: worker, - values: hashrate - }); - rebuildWorkerDisplay(); - return true; - } - } - triggerChartUpdates(); - return false; + for (var w in statData.history) { + var worker = getWorkerNameFromAddress(w); + // get a reference to lastest workerhistory + for (var wh in statData.history[w]) { } + //var wh = statData.history[w][statData.history[w].length - 1]; + var foundWorker = false; + for (var i = 0; i < workerHashrateData.length; i++) { + if (workerHashrateData[i].key === worker) { + foundWorker = true; + if (workerHashrateData[i].values.length >= workerHistoryMax) { + workerHashrateData[i].values.shift(); + } + workerHashrateData[i].values.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]); + break; + } + } + if (!foundWorker) { + var hashrate = []; + hashrate.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]); + workerHashrateData.push({ + key: worker, + values: hashrate + }); + rebuildWorkerDisplay(); + return true; + } + } + triggerChartUpdates(); + return false; } function calculateAverageHashrate(worker) { - var count = 0; - var total = 1; - var avg = 0; - for (var i = 0; i < workerHashrateData.length; i++) { - count = 0; - for (var ii = 0; ii < workerHashrateData[i].values.length; ii++) { - if (worker == null || workerHashrateData[i].key === worker) { - count++; - avg += parseFloat(workerHashrateData[i].values[ii][1]); - } - } - if (count > total) - total = count; - } - avg = avg / total; - return avg; + var count = 0; + var total = 1; + var avg = 0; + for (var i = 0; i < workerHashrateData.length; i++) { + count = 0; + for (var ii = 0; ii < workerHashrateData[i].values.length; ii++) { + if (worker == null || workerHashrateData[i].key === worker) { + count++; + avg += parseFloat(workerHashrateData[i].values[ii][1]); + } + } + if (count > total) + total = count; + } + avg = avg / total; + return avg; } function triggerChartUpdates(){ @@ -141,67 +141,67 @@ function displayCharts() { } function updateStats() { - totalHash = statData.totalHash; - totalPaid = statData.paid; - totalBal = statData.balance; - totalImmature = statData.immature; - totalShares = statData.totalShares; - // do some calculations - var _blocktime = 250; - var _networkHashRate = parseFloat(statData.networkSols) * 1.2; - var _myHashRate = (totalHash / 1000000) * 2; - var luckDays = ((_networkHashRate / _myHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3); - // update miner stats - $("#statsHashrate").text(getReadableHashRateString(totalHash)); - $("#statsHashrateAvg").text(getReadableHashRateString(calculateAverageHashrate(null))); - $("#statsLuckDays").text(luckDays); - $("#statsTotalImmature").text(totalImmature); - $("#statsTotalBal").text(totalBal); - $("#statsTotalPaid").text(totalPaid); - $("#statsTotalShares").text(totalShares.toFixed(2)); + totalHash = statData.totalHash; + totalPaid = statData.paid; + totalBal = statData.balance; + totalImmature = statData.immature; + totalShares = statData.totalShares; + // do some calculations + var _blocktime = 250; + var _networkHashRate = parseFloat(statData.networkSols) * 1.2; + var _myHashRate = (totalHash / 1000000) * 2; + var luckDays = ((_networkHashRate / _myHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3); + // update miner stats + $("#statsHashrate").text(getReadableHashRateString(totalHash)); + $("#statsHashrateAvg").text(getReadableHashRateString(calculateAverageHashrate(null))); + $("#statsLuckDays").text(luckDays); + $("#statsTotalImmature").text(totalImmature); + $("#statsTotalBal").text(totalBal); + $("#statsTotalPaid").text(totalPaid); + $("#statsTotalShares").text(totalShares.toFixed(2)); } function updateWorkerStats() { - // update worker stats - var i=0; - for (var w in statData.workers) { i++; - var htmlSafeWorkerName = w.split('.').join('_').replace(/[^\w\s]/gi, ''); - var saneWorkerName = getWorkerNameFromAddress(w); - $("#statsHashrate"+htmlSafeWorkerName).text(getReadableHashRateString(statData.workers[w].hashrate)); - $("#statsHashrateAvg"+htmlSafeWorkerName).text(getReadableHashRateString(calculateAverageHashrate(saneWorkerName))); - $("#statsLuckDays"+htmlSafeWorkerName).text(statData.workers[w].luckDays); - $("#statsPaid"+htmlSafeWorkerName).text(statData.workers[w].paid); - $("#statsBalance"+htmlSafeWorkerName).text(statData.workers[w].balance); - $("#statsShares"+htmlSafeWorkerName).text(Math.round(statData.workers[w].currRoundShares * 100) / 100); - $("#statsDiff"+htmlSafeWorkerName).text(statData.workers[w].diff); - } + // update worker stats + var i=0; + for (var w in statData.workers) { i++; + var htmlSafeWorkerName = w.split('.').join('_').replace(/[^\w\s]/gi, ''); + var saneWorkerName = getWorkerNameFromAddress(w); + $("#statsHashrate"+htmlSafeWorkerName).text(getReadableHashRateString(statData.workers[w].hashrate)); + $("#statsHashrateAvg"+htmlSafeWorkerName).text(getReadableHashRateString(calculateAverageHashrate(saneWorkerName))); + $("#statsLuckDays"+htmlSafeWorkerName).text(statData.workers[w].luckDays); + $("#statsPaid"+htmlSafeWorkerName).text(statData.workers[w].paid); + $("#statsBalance"+htmlSafeWorkerName).text(statData.workers[w].balance); + $("#statsShares"+htmlSafeWorkerName).text(Math.round(statData.workers[w].currRoundShares * 100) / 100); + $("#statsDiff"+htmlSafeWorkerName).text(statData.workers[w].diff); + } } function addWorkerToDisplay(name, htmlSafeName, workerObj) { - var htmlToAdd = ""; - htmlToAdd = '
    '; - if (htmlSafeName.indexOf("_") >= 0) { - htmlToAdd+= '
    '+htmlSafeName.substr(htmlSafeName.indexOf("_")+1,htmlSafeName.length)+'
    '; - } else { - htmlToAdd+= '
    noname
    '; - } - htmlToAdd+='
    '+getReadableHashRateString(workerObj.hashrate)+' (Now)
    '; - htmlToAdd+='
    '+getReadableHashRateString(calculateAverageHashrate(name))+' (Avg)
    '; - htmlToAdd+='
    Diff: '+workerObj.diff+'
    '; - htmlToAdd+='
    Shares: '+(Math.round(workerObj.currRoundShares * 100) / 100)+'
    '; - htmlToAdd+='
    Luck '+workerObj.luckDays+' Days
    '; - htmlToAdd+='
    Bal: '+workerObj.balance+'
    '; - htmlToAdd+='
    Paid: '+workerObj.paid+'
    '; - htmlToAdd+='
    '; - $("#boxesWorkers").html($("#boxesWorkers").html()+htmlToAdd); + var htmlToAdd = ""; + htmlToAdd = '
    '; + if (htmlSafeName.indexOf("_") >= 0) { + htmlToAdd+= '
    '+htmlSafeName.substr(htmlSafeName.indexOf("_")+1,htmlSafeName.length)+'
    '; + } else { + htmlToAdd+= '
    noname
    '; + } + htmlToAdd+='
    '+getReadableHashRateString(workerObj.hashrate)+' (Now)
    '; + htmlToAdd+='
    '+getReadableHashRateString(calculateAverageHashrate(name))+' (Avg)
    '; + htmlToAdd+='
    Diff: '+workerObj.diff+'
    '; + htmlToAdd+='
    Shares: '+(Math.round(workerObj.currRoundShares * 100) / 100)+'
    '; + htmlToAdd+='
    Luck '+workerObj.luckDays+' Days
    '; + htmlToAdd+='
    Bal: '+workerObj.balance+'
    '; + htmlToAdd+='
    Paid: '+workerObj.paid+'
    '; + htmlToAdd+='
    '; + $("#boxesWorkers").html($("#boxesWorkers").html()+htmlToAdd); } function rebuildWorkerDisplay() { - $("#boxesWorkers").html(""); - var i=0; - for (var w in statData.workers) { i++; - var htmlSafeWorkerName = w.split('.').join('_').replace(/[^\w\s]/gi, ''); - var saneWorkerName = getWorkerNameFromAddress(w); - addWorkerToDisplay(saneWorkerName, htmlSafeWorkerName, statData.workers[w]); - } + $("#boxesWorkers").html(""); + var i=0; + for (var w in statData.workers) { i++; + var htmlSafeWorkerName = w.split('.').join('_').replace(/[^\w\s]/gi, ''); + var saneWorkerName = getWorkerNameFromAddress(w); + addWorkerToDisplay(saneWorkerName, htmlSafeWorkerName, statData.workers[w]); + } } // resize chart on window resize @@ -210,37 +210,37 @@ nv.utils.windowResize(triggerChartUpdates); // grab initial stats $.getJSON('/api/worker_stats?'+_miner, function(data){ statData = data; - for (var w in statData.workers) { _workerCount++; } - buildChartData(); - displayCharts(); - rebuildWorkerDisplay(); + for (var w in statData.workers) { _workerCount++; } + buildChartData(); + displayCharts(); + rebuildWorkerDisplay(); updateStats(); }); // live stat updates statsSource.addEventListener('message', function(e){ - // TODO, create miner_live_stats... - // miner_live_stats will return the same josn except without the worker history - // FOR NOW, use this to grab updated stats - $.getJSON('/api/worker_stats?'+_miner, function(data){ - statData = data; - // check for missing workers - var wc = 0; - var rebuilt = false; - // update worker stats - for (var w in statData.workers) { wc++; } - // TODO, this isn't 100% fool proof! - if (_workerCount != wc) { - if (_workerCount > wc) { - rebuildWorkerDisplay(); - rebuilt = true; - } - _workerCount = wc; - } - rebuilt = (rebuilt || updateChartData()); - updateStats(); - if (!rebuilt) { - updateWorkerStats(); - } - }); + // TODO, create miner_live_stats... + // miner_live_stats will return the same josn except without the worker history + // FOR NOW, use this to grab updated stats + $.getJSON('/api/worker_stats?'+_miner, function(data){ + statData = data; + // check for missing workers + var wc = 0; + var rebuilt = false; + // update worker stats + for (var w in statData.workers) { wc++; } + // TODO, this isn't 100% fool proof! + if (_workerCount != wc) { + if (_workerCount > wc) { + rebuildWorkerDisplay(); + rebuilt = true; + } + _workerCount = wc; + } + rebuilt = (rebuilt || updateChartData()); + updateStats(); + if (!rebuilt) { + updateWorkerStats(); + } + }); }); diff --git a/website/piratepool.io/static/payments.js b/website/piratepool.io/static/payments.js index 0cad5b2..f9f275a 100644 --- a/website/piratepool.io/static/payments.js +++ b/website/piratepool.io/static/payments.js @@ -49,12 +49,11 @@ $(function() { console.log('Added new payment!'); } } else { - //Update existing (txid) for private chains + //Update existing (txid) for private chains if (typeof paymentstat.txid !== 'undefined' && (String(stats.pools[pool].name).startsWith("pirate") || String(stats.pools[pool].name).startsWith("arrr")) ) { - var explorer = 'https://explorer.pirate.black/tx/'; var paymentblock = document.querySelector('#payment' + pool + paymentstat.time + ' .paymentblocks a'); - paymentblock.setAttribute('href', explorer + paymentstat.txid); + paymentblock.setAttribute('href', explorerURL + 'tx/' + paymentstat.txid); paymentblock.setAttribute('target', '_blank'); paymentblock.setAttribute('rel', 'noopener noreferrer'); } @@ -81,4 +80,4 @@ $(function() { } } }); -}); \ No newline at end of file +}); diff --git a/website/piratepool.io/static/stats.js b/website/piratepool.io/static/stats.js index e64c284..95f6d21 100644 --- a/website/piratepool.io/static/stats.js +++ b/website/piratepool.io/static/stats.js @@ -58,7 +58,7 @@ $(function() { insertPendingBlock.setAttribute('title', 'Waiting for payment processor to review'); insertPendingBlock.style.opacity = 0; insertPendingBlock.style.transition = 'opacity 1s ease-in'; - insertPendingBlock.innerHTML = '
    Block: ' + checkblock[2] + '' + readableDate(checkblock[4]) + 'Pending
    '; + insertPendingBlock.innerHTML = '
    Block: ' + checkblock[2] + '' + readableDate(checkblock[4]) + 'Pending
    '; if (parseInt(checkblock[2]) > prevHeight) { poolFoundList.insertBefore(insertPendingBlock, poolFoundList.firstChild); @@ -85,7 +85,7 @@ $(function() { insertPendingBlock.id = 'blocksFoundPaid' + checkblock[0]; insertPendingBlock.setAttribute('class', 'blocksFoundPaid'); insertPendingBlock.setAttribute('title', 'Payment sent, please check payments page'); - insertPendingBlock.innerHTML = '
    Block: ' + checkblock[2] + '' + readableDate(checkblock[4]) + 'Pending
    '; + insertPendingBlock.innerHTML = '
    Block: ' + checkblock[2] + '' + readableDate(checkblock[4]) + 'Pending
    '; poolFoundList.insertBefore(insertPendingBlock, document.querySelectorAll('.blocksFoundList .blocksFoundPaid')[0]); } @@ -146,4 +146,4 @@ function displayCharts(){ function triggerChartUpdates(){ poolHashrateChart.update(); -} \ No newline at end of file +} diff --git a/website/piratepool.io/static/style.css b/website/piratepool.io/static/style.css index a208032..ccb268a 100644 --- a/website/piratepool.io/static/style.css +++ b/website/piratepool.io/static/style.css @@ -13,7 +13,7 @@ } html, body, button, input, select, textarea, -.pure-g [class *= "pure-u"] { +.pure-g [class *= "pure-u"] { font-family: 'Roboto', sans-serif; line-height: 1.4em; } @@ -99,8 +99,8 @@ footer a { } .highlight { - color:var(--gold); - font-weight:900; + color:var(--gold); + font-weight:900; } .muted { @@ -117,11 +117,11 @@ br.responsiveonly { } .alertbar { - color:var(--gold); + color:var(--gold); font-weight:900; text-shadow: -3px -3px 0px #000; text-align:center; - padding:10px 0; + padding:10px 0; background-color:var(--dark-blue); } @@ -134,7 +134,7 @@ header .pure-menu { } header .home-menu, -header .home-menu .pure-menu-list, +header .home-menu .pure-menu-list, header .home-menu .pure-menu-list li { display: flex; align-items: center; @@ -151,7 +151,7 @@ header .home-menu a { transition:background-color 0.33s ease-out, color 0.33s ease-out; } -header .home-menu a:hover, +header .home-menu a:hover, header .home-menu .pure-menu-selected a { color: #FFF!important; background-color: var(--gold); @@ -162,7 +162,7 @@ header .home-menu li a i { margin-right:5px; } -.pure-menu.pure-menu-open, +.pure-menu.pure-menu-open, .pure-menu.pure-menu-horizontal li .pure-menu-children { border:none; } @@ -208,7 +208,7 @@ header .home-menu li a i { background-color: var(--dark-blue); color: white; max-width:640px; - margin:15px auto 10px auto; + margin:15px auto 10px auto; padding:5px 10px 10px; box-shadow: -1px -1px 0 #000; } @@ -265,7 +265,7 @@ header .home-menu li a i { } .blocksFoundList .countLabel { - float:right; + float:right; font-size:0.8em; line-height:1em; } @@ -298,7 +298,7 @@ header .home-menu li a i { } .blocksFoundHeader > div:nth-child(2) { - font-size:0.8em; + font-size:0.8em; text-align:right; } @@ -349,6 +349,11 @@ header .home-menu li a i { } .paymentblocks .fade { + display:none; +} + +.paymentblocksexpand .fade { + display:block; z-index: 10; background-image: linear-gradient(to bottom, rgba(20, 20, 20, 0), rgba(20, 20, 20, 1) 90%); width: 95%; @@ -370,11 +375,11 @@ header .home-menu li a i { transition: max-height 0.2s ease-out 0.33s; } -.paymentblocks a:hover { +.paymentblocksexpand a:hover { max-height: 1000px; } -.paymentblocks a:hover + .fade { +.paymentblocksexpand a:hover + .fade { opacity:0; } @@ -444,9 +449,9 @@ header .home-menu li a i { .nv-group.nv-series-0, .nv-series:first-of-type .nv-legend-symbol { - stroke-opacity: 1; - fill-opacity: 0.5; - fill: var(--gold)!important; + stroke-opacity: 1; + fill-opacity: 0.5; + fill: var(--gold)!important; stroke: var(--gold)!important; } @@ -468,32 +473,32 @@ header .home-menu li a i { font-size: 1em; line-height: 1em; } - + .home-menu li a i { margin-right:0; } - .pure-table { + .pure-table { border-top: 1px solid var(--grey); } - table, thead, tbody, th, td, tr { - display: block; + table, thead, tbody, th, td, tr { + display: block; } - thead tr { + thead tr { display:none; visiblity:hidden; } - tr { + tr { border-bottom: 1px solid var(--grey); } - td { + td { border: none; position: relative; - + } .pure-table td { @@ -508,11 +513,11 @@ header .home-menu li a i { br.responsiveonly { display:initial; } - + .responsivehide { display:none; } - + .boxWelcome h1, .boxWelcome h2 { text-align:center!important; @@ -525,7 +530,7 @@ header .home-menu li a i { .blocksFoundHeader > div { text-align:center!important; } - + .blocksFoundList > div { flex: 1; } @@ -534,17 +539,17 @@ header .home-menu li a i { display:inline-block; visibility:visible; } - + .pure-responsive-disable, .flex-responsive-disable { width: 100%; } - + .paymentblocks a { display:inline; } - + .paymentblocks .fade { display:none; } -} \ No newline at end of file +} diff --git a/website/piratepool.io/static/workers.js b/website/piratepool.io/static/workers.js index 4ec41aa..7cecee4 100644 --- a/website/piratepool.io/static/workers.js +++ b/website/piratepool.io/static/workers.js @@ -12,32 +12,34 @@ $(function() { for (var f = 0; f < poolKeys.length; f++) { var pool = poolKeys[f]; var sharesTotal = 0; + var minerIndex = 0; for (var addr in stats.pools[pool].miners) { + minerIndex++; var workerstat = stats.pools[pool].miners[addr]; sharesTotal += parseFloat(workerstat.shares); - var existingRow = document.querySelector('#workers' + pool + ' #worker' + addr); + var existingRow = document.querySelector('#workers' + pool + ' #worker' + minerIndex); var minerEfficiency = ( workerstat.shares > 0 ) ? Math.floor(10000 * workerstat.shares / (workerstat.shares + workerstat.invalidshares)) / 100 : 0; - + if (existingRow == null) { //Add new var insertMinerTr = document.createElement('tr'); - insertMinerTr.id = 'worker' + addr; + insertMinerTr.id = 'worker' + minerIndex; insertMinerTr.setAttribute('data-hashrate', workerstat.hashrate); - insertMinerTr.innerHTML = ' Address: '+ middleEllipsis(addr, 20) + ''; + insertMinerTr.innerHTML = 'Miner #'+ minerIndex +''; insertMinerTr.innerHTML += ' Shares: ' + bigNumber(workerstat.shares) + ''; insertMinerTr.innerHTML += ' Efficiency: ' + minerEfficiency + '%'; insertMinerTr.innerHTML += ' Hashrate: ' + workerstat.hashrateString + ''; document.querySelector('#workers' + pool + ' .poolMinerTable tbody').appendChild(insertMinerTr); - console.log('Added new miner! [' + addr + ']'); + console.log('Added new miner! [' + minerIndex + ']'); } else { //Update existing - document.querySelector('#workers' + pool + ' #worker' + addr + ' td:nth-child(2) span:nth-child(2)').innerHTML = bigNumber(workerstat.shares); - document.querySelector('#workers' + pool + ' #worker' + addr + ' td:nth-child(3) span:nth-child(2)').innerHTML = minerEfficiency + '%'; - document.querySelector('#workers' + pool + ' #worker' + addr + ' td:nth-child(4) span:nth-child(2)').innerHTML = workerstat.hashrateString; - document.querySelector('#workers' + pool + ' #worker' + addr).setAttribute('data-hashrate', workerstat.hashrate); + document.querySelector('#workers' + pool + ' #worker' + minerIndex + ' td:nth-child(2) span:nth-child(2)').innerHTML = bigNumber(workerstat.shares); + document.querySelector('#workers' + pool + ' #worker' + minerIndex + ' td:nth-child(3) span:nth-child(2)').innerHTML = minerEfficiency + '%'; + document.querySelector('#workers' + pool + ' #worker' + minerIndex + ' td:nth-child(4) span:nth-child(2)').innerHTML = workerstat.hashrateString; + document.querySelector('#workers' + pool + ' #worker' + minerIndex).setAttribute('data-hashrate', workerstat.hashrate); } } @@ -76,4 +78,4 @@ function searchKeyPress(e) return false; } return true; -} \ No newline at end of file +}