From f38c04f13a76756071c74c2f96de9e062945b4e8 Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 16 Apr 2013 21:11:34 -0700 Subject: [PATCH 01/23] Portals-list code cleanup, change four to two space line indent --- plugins/portals-list.user.js | 645 ++++++++++++++++++----------------- 1 file changed, 323 insertions(+), 322 deletions(-) diff --git a/plugins/portals-list.user.js b/plugins/portals-list.user.js index 37997cc2..6224df3e 100644 --- a/plugins/portals-list.user.js +++ b/plugins/portals-list.user.js @@ -45,328 +45,329 @@ window.plugin.portalslist.resP = 0; window.plugin.portalslist.filter=0; //fill the listPortals array with portals avalaible on the map (level filtered portals will not appear in the table) -window.plugin.portalslist.getPortals = function(){ - //filter : 0 = All, 1 = Res, 2 = Enl - //console.log('** getPortals'); - var retval=false; - - window.plugin.portalslist.listPortals = []; - //get portals informations from IITC - $.each(window.portals, function(i, portal) { - - retval=true; - var d = portal.options.details; - var name = d.portalV2.descriptiveText.TITLE; - var address = d.portalV2.descriptiveText.ADDRESS; - var img = d.imageByUrl && d.imageByUrl.imageUrl ? d.imageByUrl.imageUrl : DEFAULT_PORTAL_IMG; - var team = portal.options.team; - switch (team){ - case 1 : - window.plugin.portalslist.resP++; - break; - case 2 : - window.plugin.portalslist.enlP++; - break; - } - var level = getPortalLevel(d).toFixed(2); - var guid = portal.options.guid; - - - //get resonators informations - var resonators = []; // my local resonator array : reso level, reso deployed by, distance to portal, energy total, max - var energy = 0; - var maxenergy=0; - $.each(portal.options.details.resonatorArray.resonators, function(ind, reso) { - if(reso) { - resonators[ind] = [reso.level, window.getPlayerName(reso.ownerGuid), reso.distanceToPortal, reso.energyTotal, RESO_NRG[reso.level]]; - energy += reso.energyTotal; - maxenergy += RESO_NRG[reso.level]; - } else { resonators[ind] = [0,'',0,0,0]; } - }); - // Sort resonators array by resonator level - resonators.sort(function (a, b) {return b[0] - a[0]}); - - //get shield informations - var shields = []; - $.each(d.portalV2.linkedModArray, function(ind, mod) { - if (mod) - //shields[ind] = mod.rarity.capitalize().replace('_', ' '); - shields[ind] = [mod.rarity.substr(0,1).capitalize(), getPlayerName(mod.installingUser)] ; - else - shields[ind] = ['', '']; - }); - - var APgain= getAttackApGain(d).enemyAp; - var thisPortal = {'portal':d,'name':name,'team':team,'level':level,'guid':guid, 'resonators':resonators,'energyratio' : Math.floor(energy/maxenergy*100), 'shields':shields, 'APgain':APgain, 'EAP' : (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy':maxenergy, 'lat':portal._latlng.lat, 'lng':portal._latlng.lng, 'address': address, 'img' : img}; - window.plugin.portalslist.listPortals.push(thisPortal); +window.plugin.portalslist.getPortals = function() { + //filter : 0 = All, 1 = Res, 2 = Enl + //console.log('** getPortals'); + var retval=false; + + window.plugin.portalslist.listPortals = []; + //get portals informations from IITC + $.each(window.portals, function(i, portal) { + + retval=true; + var d = portal.options.details; + var name = d.portalV2.descriptiveText.TITLE; + var address = d.portalV2.descriptiveText.ADDRESS; + var img = d.imageByUrl && d.imageByUrl.imageUrl ? d.imageByUrl.imageUrl : DEFAULT_PORTAL_IMG; + var team = portal.options.team; + switch (team){ + case 1 : + window.plugin.portalslist.resP++; + break; + case 2 : + window.plugin.portalslist.enlP++; + break; + } + var level = getPortalLevel(d).toFixed(2); + var guid = portal.options.guid; + + + //get resonators informations + var resonators = []; // my local resonator array : reso level, reso deployed by, distance to portal, energy total, max + var energy = 0; + var maxenergy=0; + $.each(portal.options.details.resonatorArray.resonators, function(ind, reso) { + if(reso) { + resonators[ind] = [reso.level, window.getPlayerName(reso.ownerGuid), reso.distanceToPortal, reso.energyTotal, RESO_NRG[reso.level]]; + energy += reso.energyTotal; + maxenergy += RESO_NRG[reso.level]; + } else { resonators[ind] = [0,'',0,0,0]; } }); - - return retval; + // Sort resonators array by resonator level + resonators.sort(function (a, b) {return b[0] - a[0]}); + + //get shield informations + var shields = []; + $.each(d.portalV2.linkedModArray, function(ind, mod) { + if (mod) { + //shields[ind] = mod.rarity.capitalize().replace('_', ' '); + shields[ind] = [mod.rarity.substr(0,1).capitalize(), getPlayerName(mod.installingUser)] ; + } else { + shields[ind] = ['', '']; + } + }); + + var APgain= getAttackApGain(d).enemyAp; + var thisPortal = {'portal':d,'name':name,'team':team,'level':level,'guid':guid, 'resonators':resonators,'energyratio' : Math.floor(energy/maxenergy*100), 'shields':shields, 'APgain':APgain, 'EAP' : (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy':maxenergy, 'lat':portal._latlng.lat, 'lng':portal._latlng.lng, 'address': address, 'img' : img}; + window.plugin.portalslist.listPortals.push(thisPortal); + }); + + return retval; } -window.plugin.portalslist.displayPL = function() { - // debug tools - //var start = new Date().getTime(); - //console.log('***** Start ' + start); - - var html = ''; - window.plugin.portalslist.sortOrder=-1; - window.plugin.portalslist.enlP = 0; - window.plugin.portalslist.resP = 0; +window.plugin.portalslist.displayPL = function() { + // debug tools + //var start = new Date().getTime(); + //console.log('***** Start ' + start); - if (window.plugin.portalslist.getPortals()) { - html += window.plugin.portalslist.portalTable('level', window.plugin.portalslist.sortOrder,window.plugin.portalslist.filter); - } else { - html = '
Nothing to Show !
'; - }; - alert('
' + html + '
', true, function() {$(".ui-dialog").removeClass('ui-dialog-portalslist');}); - $(".ui-dialog").addClass('ui-dialog-portalslist'); + var html = ''; + window.plugin.portalslist.sortOrder=-1; + window.plugin.portalslist.enlP = 0; + window.plugin.portalslist.resP = 0; + + if (window.plugin.portalslist.getPortals()) { + html += window.plugin.portalslist.portalTable('level', window.plugin.portalslist.sortOrder,window.plugin.portalslist.filter); + } else { + html = '
Nothing to Show !
'; + }; + alert('
' + html + '
', true, function() {$(".ui-dialog").removeClass('ui-dialog-portalslist');}); + $(".ui-dialog").addClass('ui-dialog-portalslist'); + + // Setup sorting + $(document).on('click', '#portalslist table th', function() { + $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,window.plugin.portalslist.filter)); + }); + $(document).on('click', '#portalslist .filterAll', function() { + $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,0)); + }); + $(document).on('click', '#portalslist .filterRes', function() { + $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,1)); + }); + $(document).on('click', '#portalslist .filterEnl', function() { + $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,2)); + }); - // Setup sorting - $(document).on('click', '#portalslist table th', function() { - $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,window.plugin.portalslist.filter)); - }); - $(document).on('click', '#portalslist .filterAll', function() { - $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,0)); - }); - $(document).on('click', '#portalslist .filterRes', function() { - $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,1)); - }); - $(document).on('click', '#portalslist .filterEnl', function() { - $('#portalslist').html(window.plugin.portalslist.portalTable($(this).data('sort'),window.plugin.portalslist.sortOrder,2)); - }); - - //debug tools - //end = new Date().getTime(); - //console.log('***** end : ' + end + ' and Elapse : ' + (end - start)); + //debug tools + //end = new Date().getTime(); + //console.log('***** end : ' + end + ' and Elapse : ' + (end - start)); } window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { - // sortOrder <0 ==> desc, >0 ==> asc, i use sortOrder * -1 to change the state - window.plugin.portalslist.filter=filter; - var portals=window.plugin.portalslist.listPortals; - - //Array sort - window.plugin.portalslist.listPortals.sort(function(a, b) { - var retVal = 0; - switch (sortBy) { - case 'names': - retVal = a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; - break; - case 'r1': - retVal = b.resonators[0][0] - a.resonators[0][0]; - break; - case 'r2': - retVal = b.resonators[1][0] - a.resonators[1][0]; - break; - case 'r3': - retVal = b.resonators[2][0] - a.resonators[2][0]; - break; - case 'r4': - retVal = b.resonators[3][0] - a.resonators[3][0]; - break; - case 'r5': - retVal = b.resonators[4][0] - a.resonators[4][0]; - break; - case 'r6': - retVal = b.resonators[5][0] - a.resonators[5][0]; - break; - case 'r7': - retVal = b.resonators[6][0] - a.resonators[6][0]; - break; - case 'r8': - retVal = b.resonators[7][0] - a.resonators[7][0]; - break; - case 's1': - retVal = a.shields[0].toLowerCase() > b.shields[0].toLowerCase() ? -1 : 1; - break; - case 's2': - retVal = a.shields[1].toLowerCase() > b.shields[1].toLowerCase() ? -1 : 1; - break; - case 's3': - retVal = a.shields[2].toLowerCase() > b.shields[2].toLowerCase() ? -1 : 1; - break; - case 's4': - retVal = a.shields[3].toLowerCase() > b.shields[3].toLowerCase() ? -1 : 1; - break; - default: - retVal = b[sortBy] - a[sortBy]; - break; - } - if (sortOrder > 0) { retVal = -retVal} //thx @jonatkins - return retVal; - }); - - var sort = window.plugin.portalslist.portalTableSort; - var html = window.plugin.portalslist.stats(); - html += '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + '' - + ''; - - - $.each(portals, function(ind, portal) { - - if (filter === 0 || filter === portal.team){ - html += '' - + '' - + '' - + ''; - - $.each([0, 1, 2, 3 ,4 ,5 ,6 ,7], function(ind, slot) { - - var title = 'title="owner: ' + portal.resonators[slot][1] + '
' - + 'energy: ' + portal.resonators[slot][3] + ' / ' + portal.resonators[slot][4] + ' (' + Math.floor(portal.resonators[slot][3]/portal.resonators[slot][4]*100) + '%)
' - + 'distance: ' + portal.resonators[slot][2] + 'm'; - - html += ''; - - }); - - html += '' - + '' - + '' - + '' - + '' - + '' - + ''; - - html+= ''; - } - }); - html += '
PortalLevelTR1R2R3R4R5R6R7R8EnergyS1S2S3S4AP GainE/AP
' + window.plugin.portalslist.getPortalLink(portal.portal, portal.guid) + '' + portal.level + '' + portal.team + '' + portal.resonators[slot][0] + '' + portal.energyratio + '%' + portal.shields[0][0] + '' + portal.shields[1][0] + '' + portal.shields[2][0] + '' + portal.shields[3][0] + '' + portal.APgain + '' + portal.EAP + '
'; - - //html += window.plugin.portalslist.exportLinks(); - - html += '
Click on portals table headers to sort by that column. ' - + 'Click on All Portals, Resistant Portals, Enlightened Portals to filter
' - + 'Thanks to @vita10gy & @xelio for their IITC plugins who inspired me. A @teo96 production. Vive la Résistance !
'; + // sortOrder <0 ==> desc, >0 ==> asc, i use sortOrder * -1 to change the state + window.plugin.portalslist.filter=filter; + var portals=window.plugin.portalslist.listPortals; - window.plugin.portalslist.sortOrder = window.plugin.portalslist.sortOrder*-1; - return html; + //Array sort + window.plugin.portalslist.listPortals.sort(function(a, b) { + var retVal = 0; + switch (sortBy) { + case 'names': + retVal = a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; + break; + case 'r1': + retVal = b.resonators[0][0] - a.resonators[0][0]; + break; + case 'r2': + retVal = b.resonators[1][0] - a.resonators[1][0]; + break; + case 'r3': + retVal = b.resonators[2][0] - a.resonators[2][0]; + break; + case 'r4': + retVal = b.resonators[3][0] - a.resonators[3][0]; + break; + case 'r5': + retVal = b.resonators[4][0] - a.resonators[4][0]; + break; + case 'r6': + retVal = b.resonators[5][0] - a.resonators[5][0]; + break; + case 'r7': + retVal = b.resonators[6][0] - a.resonators[6][0]; + break; + case 'r8': + retVal = b.resonators[7][0] - a.resonators[7][0]; + break; + case 's1': + retVal = a.shields[0].toLowerCase() > b.shields[0].toLowerCase() ? -1 : 1; + break; + case 's2': + retVal = a.shields[1].toLowerCase() > b.shields[1].toLowerCase() ? -1 : 1; + break; + case 's3': + retVal = a.shields[2].toLowerCase() > b.shields[2].toLowerCase() ? -1 : 1; + break; + case 's4': + retVal = a.shields[3].toLowerCase() > b.shields[3].toLowerCase() ? -1 : 1; + break; + default: + retVal = b[sortBy] - a[sortBy]; + break; + } + if (sortOrder > 0) retVal = -retVal; //thx @jonatkins + return retVal; + }); + + var sort = window.plugin.portalslist.portalTableSort; + var html = window.plugin.portalslist.stats(); + html += '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + ''; + + + $.each(portals, function(ind, portal) { + + if (filter === 0 || filter === portal.team){ + html += '' + + '' + + '' + + ''; + + $.each([0, 1, 2, 3 ,4 ,5 ,6 ,7], function(ind, slot) { + + var title = 'title="owner: ' + portal.resonators[slot][1] + '
' + + 'energy: ' + portal.resonators[slot][3] + ' / ' + portal.resonators[slot][4] + ' (' + Math.floor(portal.resonators[slot][3]/portal.resonators[slot][4]*100) + '%)
' + + 'distance: ' + portal.resonators[slot][2] + 'm'; + + html += ''; + + }); + + html += '' + + '' + + '' + + '' + + '' + + '' + + ''; + + html+= ''; + } + }); + html += '
PortalLevelTR1R2R3R4R5R6R7R8EnergyS1S2S3S4AP GainE/AP
' + window.plugin.portalslist.getPortalLink(portal.portal, portal.guid) + '' + portal.level + '' + portal.team + '' + portal.resonators[slot][0] + '' + portal.energyratio + '%' + portal.shields[0][0] + '' + portal.shields[1][0] + '' + portal.shields[2][0] + '' + portal.shields[3][0] + '' + portal.APgain + '' + portal.EAP + '
'; + + //html += window.plugin.portalslist.exportLinks(); + + html += '
Click on portals table headers to sort by that column. ' + + 'Click on All Portals, Resistant Portals, Enlightened Portals to filter
' + + 'Thanks to @vita10gy & @xelio for their IITC plugins who inspired me. A @teo96 production. Vive la Résistance !
'; + + window.plugin.portalslist.sortOrder = window.plugin.portalslist.sortOrder*-1; + return html; } window.plugin.portalslist.stats = function(sortBy) { - //console.log('** stats'); - var html = '' - + '' - + '' - + '' - + '' - + '
All Portals : (click to filter)' + window.plugin.portalslist.listPortals.length + 'Resistant Portals : ' + window.plugin.portalslist.resP +' (' + Math.floor(window.plugin.portalslist.resP/window.plugin.portalslist.listPortals.length*100) + '%)Enlightened Portals : '+ window.plugin.portalslist.enlP +' (' + Math.floor(window.plugin.portalslist.enlP/window.plugin.portalslist.listPortals.length*100) + '%)
'; - return html; + //console.log('** stats'); + var html = '' + + '' + + '' + + '' + + '' + + '
All Portals : (click to filter)' + window.plugin.portalslist.listPortals.length + 'Resistant Portals : ' + window.plugin.portalslist.resP +' (' + Math.floor(window.plugin.portalslist.resP/window.plugin.portalslist.listPortals.length*100) + '%)Enlightened Portals : '+ window.plugin.portalslist.enlP +' (' + Math.floor(window.plugin.portalslist.enlP/window.plugin.portalslist.listPortals.length*100) + '%)
'; + return html; } //return Html generated to export links -window.plugin.portalslist.exportLinks = function(){ - var html=''; - var stamp = new Date().getTime(); - - html+='
' - + '' - + '
'; - return html; +window.plugin.portalslist.exportLinks = function() { + var html=''; + var stamp = new Date().getTime(); + + html+='
' + + '' + + '
'; + return html; } -window.plugin.portalslist.export = function(fileformat){ - //alert('format :' + fileformat); - var file = ''; - var uri = ''; - - switch (fileformat) { - case 'csv': - file = window.plugin.portalslist.exportCSV(); - break; - case 'kml': - file = window.plugin.portalslist.exportKML(); - break; - } - - if (file !== '') { - //http://stackoverflow.com/questions/4639372/export-to-csv-in-jquery - var uri = 'data:application/' + fileformat + 'csv;charset=UTF-8,' + encodeURIComponent(file); - //window.open(uri); - } - return uri; +window.plugin.portalslist.export = function(fileformat) { + //alert('format :' + fileformat); + var file = ''; + var uri = ''; + + switch (fileformat) { + case 'csv': + file = window.plugin.portalslist.exportCSV(); + break; + case 'kml': + file = window.plugin.portalslist.exportKML(); + break; + } + + if (file !== '') { + //http://stackoverflow.com/questions/4639372/export-to-csv-in-jquery + var uri = 'data:application/' + fileformat + 'csv;charset=UTF-8,' + encodeURIComponent(file); + //window.open(uri); + } + return uri; } -window.plugin.portalslist.exportCSV = function(){ - var csv = ''; - var filter = window.plugin.portalslist.filter; - var portals = window.plugin.portalslist.listPortals; - - //headers - csv += 'Portal\tLevel\tTeam\tR1\tR2\tR3\tR4\tR5\tR6\tR7\tR8\tEnergy\tS1\tS2\tS3\tS4\tAP Gain\tE/AP\tlat\tlong\n'; - - $.each(portals, function(ind, portal) { - - if (filter === 0 || filter === portal.team){ - csv += portal.name + '\t' - + portal.level + '\t' - + portal.team + '\t'; - - $.each([0, 1, 2, 3 ,4 ,5 ,6 ,7], function(ind, slot) { - csv += portal.resonators[slot][0] + '\t'; - }); - - csv += portal.energyratio + '\t' + portal.shields[0][0] + '\t' + portal.shields[1][0] + '\t' + portal.shields[2][0] + '\t' + portal.shields[3][0] + '\t' + portal.APgain + '\t' + portal.EAP + '\t'; - csv += portal.lat + '\t' + portal.lng; - csv += '\n'; - } - }); - - return csv; +window.plugin.portalslist.exportCSV = function() { + var csv = ''; + var filter = window.plugin.portalslist.filter; + var portals = window.plugin.portalslist.listPortals; + + //headers + csv += 'Portal\tLevel\tTeam\tR1\tR2\tR3\tR4\tR5\tR6\tR7\tR8\tEnergy\tS1\tS2\tS3\tS4\tAP Gain\tE/AP\tlat\tlong\n'; + + $.each(portals, function(ind, portal) { + + if (filter === 0 || filter === portal.team) { + csv += portal.name + '\t' + + portal.level + '\t' + + portal.team + '\t'; + + $.each([0, 1, 2, 3 ,4 ,5 ,6 ,7], function(ind, slot) { + csv += portal.resonators[slot][0] + '\t'; + }); + + csv += portal.energyratio + '\t' + portal.shields[0][0] + '\t' + portal.shields[1][0] + '\t' + portal.shields[2][0] + '\t' + portal.shields[3][0] + '\t' + portal.APgain + '\t' + portal.EAP + '\t'; + csv += portal.lat + '\t' + portal.lng; + csv += '\n'; + } + }); + + return csv; } -window.plugin.portalslist.exportKML = function(){ - var kml = ''; - var filter = window.plugin.portalslist.filter; - // all portals informations are avalaible in the listPortals array - var portals = window.plugin.portalslist.listPortals; - - //headers - kml = '\n' - + 'Ingress Export'; - - // define colored markers as style0 (neutral), style1 (Resistance), style2 (Enlight) - kml += '' - + '' - + '\n'; - - $.each(portals, function(ind, portal) { - // add the portal in the kml file only if part of the filter choice - if (filter === 0 || filter === portal.team){ - // description contain picture of the portal, address and link to the Intel map - var description = '
' + portal.address - + '
Link to Intel Map
' - + ']]>'; - - kml += 'L' + Math.floor(portal.level) + ' - ' + portal.name + '' - + '' + description + '' - + '#style' + portal.team + ''; - - //coordinates - kml += '' + portal.lng + ',' + portal.lat + ',0'; - kml += '\n'; - } - }); - kml += '
'; - return kml; +window.plugin.portalslist.exportKML = function() { + var kml = ''; + var filter = window.plugin.portalslist.filter; + // all portals informations are avalaible in the listPortals array + var portals = window.plugin.portalslist.listPortals; + + //headers + kml = '\n' + + 'Ingress Export'; + + // define colored markers as style0 (neutral), style1 (Resistance), style2 (Enlight) + kml += '' + + '' + + '\n'; + + $.each(portals, function(ind, portal) { + // add the portal in the kml file only if part of the filter choice + if (filter === 0 || filter === portal.team){ + // description contain picture of the portal, address and link to the Intel map + var description = '
' + portal.address + + '
Link to Intel Map
' + + ']]>'; + + kml += 'L' + Math.floor(portal.level) + ' - ' + portal.name + '' + + '' + description + '' + + '#style' + portal.team + ''; + + //coordinates + kml += '' + portal.lng + ',' + portal.lat + ',0'; + kml += '\n'; + } + }); + kml += '
'; + return kml; } // A little helper functon so the above isn't so messy @@ -383,29 +384,29 @@ window.plugin.portalslist.portalTableSort = function(name, by) { // hover: show address // code from getPortalLink function by xelio from iitc: AP List - https://raw.github.com/breunigs/ingress-intel-total-conversion/gh-pages/plugins/ap-list.user.js window.plugin.portalslist.getPortalLink = function(portal,guid) { - - var latlng = [portal.locationE6.latE6/1E6, portal.locationE6.lngE6/1E6].join(); - var jsSingleClick = 'window.renderPortalDetails(\''+guid+'\');return false'; - var jsDoubleClick = 'window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false'; - var perma = '/intel?latE6='+portal.locationE6.latE6+'&lngE6='+portal.locationE6.lngE6+'&z=17&pguid='+guid; - - //Use Jquery to create the link, which escape characters in TITLE and ADDRESS of portal - var a = $('',{ - "class": 'help', - text: portal.portalV2.descriptiveText.TITLE, - title: portal.portalV2.descriptiveText.ADDRESS, - href: perma, - onClick: jsSingleClick, - onDblClick: jsDoubleClick - })[0].outerHTML; - var div = '
'+a+'
'; - return div; + + var latlng = [portal.locationE6.latE6/1E6, portal.locationE6.lngE6/1E6].join(); + var jsSingleClick = 'window.renderPortalDetails(\''+guid+'\');return false'; + var jsDoubleClick = 'window.zoomToAndShowPortal(\''+guid+'\', ['+latlng+']);return false'; + var perma = '/intel?latE6='+portal.locationE6.latE6+'&lngE6='+portal.locationE6.lngE6+'&z=17&pguid='+guid; + + //Use Jquery to create the link, which escape characters in TITLE and ADDRESS of portal + var a = $('
',{ + "class": 'help', + text: portal.portalV2.descriptiveText.TITLE, + title: portal.portalV2.descriptiveText.ADDRESS, + href: perma, + onClick: jsSingleClick, + onDblClick: jsDoubleClick + })[0].outerHTML; + var div = '
'+a+'
'; + return div; } var setup = function() { $('#toolbox').append('
Portals list'); - $('head').append('' - + '' - + '\n'; - - $.each(portals, function(ind, portal) { - // add the portal in the kml file only if part of the filter choice - if (filter === 0 || filter === portal.team){ - // description contain picture of the portal, address and link to the Intel map - var description = '
' + portal.address - + '
Link to Intel Map
' - + ']]>'; - - kml += 'L' + Math.floor(portal.level) + ' - ' + portal.name + '' - + '' + description + '' - + '#style' + portal.team + ''; - - //coordinates - kml += '' + portal.lng + ',' + portal.lat + ',0'; - kml += '\n'; - } - }); - kml += ''; - return kml; -} - // A little helper functon so the above isn't so messy window.plugin.portalslist.portalTableSort = function(name, by) { var retVal = 'data-sort="' + name + '"'; From 4adf3d6e798f775d3b8035fd9f897b83adb29272 Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 16 Apr 2013 23:28:00 -0700 Subject: [PATCH 06/23] Opps on a nit, reverted. --- plugins/portals-list.user.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/portals-list.user.js b/plugins/portals-list.user.js index 1d2b9855..899a1247 100644 --- a/plugins/portals-list.user.js +++ b/plugins/portals-list.user.js @@ -160,28 +160,28 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { retVal = a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1; break; case 'r1': - retVal = b.resonators[0][3] - a.resonators[0][3]; + retVal = b.resonators[0][0] - a.resonators[0][0]; break; case 'r2': - retVal = b.resonators[1][3] - a.resonators[1][3]; + retVal = b.resonators[1][0] - a.resonators[1][0]; break; case 'r3': - retVal = b.resonators[2][3] - a.resonators[2][3]; + retVal = b.resonators[2][0] - a.resonators[2][0]; break; case 'r4': - retVal = b.resonators[3][3] - a.resonators[3][3]; + retVal = b.resonators[3][0] - a.resonators[3][0]; break; case 'r5': - retVal = b.resonators[4][3] - a.resonators[4][3]; + retVal = b.resonators[4][0] - a.resonators[4][0]; break; case 'r6': - retVal = b.resonators[5][3] - a.resonators[5][3]; + retVal = b.resonators[5][0] - a.resonators[5][0]; break; case 'r7': - retVal = b.resonators[6][3] - a.resonators[6][3]; + retVal = b.resonators[6][0] - a.resonators[6][0]; break; case 'r8': - retVal = b.resonators[7][3] - a.resonators[7][3]; + retVal = b.resonators[7][0] - a.resonators[7][0]; break; case 's1': retVal = a.shields[0].toLowerCase() > b.shields[0].toLowerCase() ? -1 : 1; From 4a16668c6ac49154a5c5a109cee374272f913e6d Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Wed, 24 Apr 2013 02:40:53 +0100 Subject: [PATCH 07/23] change player tracker display for unknown plyaer levels, to match that used in the guess player levels plugin --- plugins/player-tracker.user.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/player-tracker.user.js b/plugins/player-tracker.user.js index 864a006a..7f20df6c 100644 --- a/plugins/player-tracker.user.js +++ b/plugins/player-tracker.user.js @@ -266,12 +266,13 @@ window.plugin.playerTracker.drawData = function() { if(window.plugin.guessPlayerLevels !== undefined && window.plugin.guessPlayerLevels.fetchLevelByPlayer !== undefined) { var playerLevel = window.plugin.guessPlayerLevels.fetchLevelByPlayer(pguid); - if (playerLevel === undefined) playerLevel = 1; //if player level unknown, assume level 1 if(playerLevel !== undefined) { title += 'Level ' + playerLevel + (playerLevel < (window.MAX_XM_PER_LEVEL.length - 1) ? ' (guessed)' : '') + ''; + } else { + title += 'Level unknown' } } From 0010626c916077b475a347f80a84692485c9ceaa Mon Sep 17 00:00:00 2001 From: goodsoft Date: Wed, 24 Apr 2013 06:17:36 +0300 Subject: [PATCH 08/23] Recreate links omitted from Niantic data See #192 --- code/map_data.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/code/map_data.js b/code/map_data.js index 91c6b4f0..76d72e89 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -78,7 +78,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { // portals can be brought to front, this costs extra time. They need // to be in the foreground, or they cannot be clicked. See // https://github.com/Leaflet/Leaflet/issues/185 - var ppp = []; + var ppp = {}; var p2f = {}; $.each(m, function(qk, val) { $.each(val.deletedGameEntityGuids || [], function(ind, guid) { @@ -115,7 +115,7 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { ent[2].imageByUrl = {'imageUrl': DEFAULT_PORTAL_IMG}; } - ppp.push(ent); // delay portal render + ppp[ent[0]] = ent; // delay portal render } else if(ent[2].edge !== undefined) { renderLink(ent); } else if(ent[2].capturedRegion !== undefined) { @@ -132,6 +132,25 @@ window.handleDataResponse = function(data, textStatus, jqXHR) { }); $.each(ppp, function(ind, portal) { + if ('portalV2' in portal[2] && 'linkedEdges' in portal[2].portalV2) { + $.each(portal[2].portalV2.linkedEdges, function (ind, edge) { + if (!ppp[edge.otherPortalGuid]) + return; + renderLink([ + edge.edgeGuid, + portal[1], + { + "controllingTeam": portal[2].controllingTeam, + "edge": { + "destinationPortalGuid": edge.isOrigin ? ppp[edge.otherPortalGuid][0] : portal[0], + "destinationPortalLocation": edge.isOrigin ? ppp[edge.otherPortalGuid][2].locationE6 : portal[2].locationE6, + "originPortalGuid": !edge.isOrigin ? ppp[edge.otherPortalGuid][0] : portal[0], + "originPortalLocation": !edge.isOrigin ? ppp[edge.otherPortalGuid][2].locationE6 : portal[2].locationE6 + } + } + ]); + }); + } if(portal[2].portalV2['linkedFields'] === undefined) { portal[2].portalV2['linkedFields'] = []; } From f7f8e1ca94efad9e008e4a861ec404f512906117 Mon Sep 17 00:00:00 2001 From: Paul Tsupikoff Date: Wed, 24 Apr 2013 12:58:31 +0300 Subject: [PATCH 09/23] Rewritten tile request calculation --- code/map_data.js | 40 ++++++++++------------ code/map_data_calc_tools.js | 68 +++++++++++++------------------------ 2 files changed, 42 insertions(+), 66 deletions(-) diff --git a/code/map_data.js b/code/map_data.js index 76d72e89..89e8eeb2 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -12,34 +12,30 @@ window.requestData = function() { requests.abort(); cleanUp(); - var magic = convertCenterLat(map.getCenter().lat); - var R = calculateR(magic); - var bounds = map.getBounds(); - // convert to point values - topRight = convertLatLngToPoint(bounds.getNorthEast(), magic, R); - bottomLeft = convertLatLngToPoint(bounds.getSouthWest() , magic, R); - // how many quadrants intersect the current view? - quadsX = Math.abs(bottomLeft.x - topRight.x); - quadsY = Math.abs(bottomLeft.y - topRight.y); + + var x1 = lngToTile(bounds.getNorthWest().lng, map.getZoom()); + var x2 = lngToTile(bounds.getNorthEast().lng, map.getZoom()); + var y1 = latToTile(bounds.getNorthWest().lat, map.getZoom()); + var y2 = latToTile(bounds.getSouthWest().lat, map.getZoom()); // will group requests by second-last quad-key quadrant tiles = {}; // walk in x-direction, starts right goes left - for(var i = 0; i <= quadsX; i++) { - var x = Math.abs(topRight.x - i); - var qk = pointToQuadKey(x, topRight.y); - var bnds = convertPointToLatLng(x, topRight.y, magic, R); - if(!tiles[qk.slice(0, -1)]) tiles[qk.slice(0, -1)] = []; - tiles[qk.slice(0, -1)].push(generateBoundsParams(qk, bnds)); - - // walk in y-direction, starts top, goes down - for(var j = 1; j <= quadsY; j++) { - var qk = pointToQuadKey(x, topRight.y + j); - var bnds = convertPointToLatLng(x, topRight.y + j, magic, R); - if(!tiles[qk.slice(0, -1)]) tiles[qk.slice(0, -1)] = []; - tiles[qk.slice(0, -1)].push(generateBoundsParams(qk, bnds)); + for (var x = x1; x <= x2; x++) { + for (var y = y1; y <= y2; y++) { + var tile_id = pointToTileId(map.getZoom(), x, y); + var bucket = Math.floor(x / 2) + "" + Math.floor(y / 2); + if (!tiles[bucket]) + tiles[bucket] = []; + tiles[bucket].push(generateBoundsParams( + tile_id, + tileToLat(y + 1, map.getZoom()), + tileToLng(x, map.getZoom()), + tileToLat(y, map.getZoom()), + tileToLng(x + 1, map.getZoom()) + )); } } diff --git a/code/map_data_calc_tools.js b/code/map_data_calc_tools.js index eca1b7e9..98535759 100644 --- a/code/map_data_calc_tools.js +++ b/code/map_data_calc_tools.js @@ -1,65 +1,45 @@ - // MAP DATA REQUEST CALCULATORS ////////////////////////////////////// // Ingress Intel splits up requests for map data (portals, links, // fields) into tiles. To get data for the current viewport (i.e. what // is currently visible) it first calculates which tiles intersect. // For all those tiles, it then calculates the lat/lng bounds of that // tile and a quadkey. Both the bounds and the quadkey are “somewhat” -// required to get complete data. No idea how the projection between -// lat/lng and tiles works. -// What follows now are functions that allow conversion between tiles -// and lat/lng as well as calculating the quad key. The variable names -// may be misleading. -// The minified source for this code was in gen_dashboard.js after the -// “// input 89” line (alternatively: the class was called “Xe”). +// required to get complete data. +// +// Convertion functions courtesy of +// http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames -window.convertCenterLat = function(centerLat) { - return Math.round(256 * 0.9999 * Math.abs(1 / Math.cos(centerLat * DEG2RAD))); +window.lngToTile = function(lng, zoom) { + return Math.floor((lng + 180) / 360 * Math.pow(2, zoom)); } -window.calculateR = function(convCenterLat) { - return 1 << window.map.getZoom() - (convCenterLat / 256 - 1); +window.latToTile = function(lat, zoom) { + return Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) + + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom)); } -window.convertLatLngToPoint = function(latlng, magic, R) { - var x = (magic + latlng.lng * magic / 180)*R; - var l = Math.sin(latlng.lat * DEG2RAD); - var y = (magic + Math.log((1+l)/(1-l)) * -(magic / (2*Math.PI)))*R; - return {x: Math.floor(x/magic), y: Math.floor(y/magic)}; +window.tileToLng = function(x, zoom) { + return x / Math.pow(2, zoom) * 360 - 180; } -window.convertPointToLatLng = function(x, y, magic, R) { - var e = {}; - e.sw = { - // orig function put together from all over the place - // lat: (2 * Math.atan(Math.exp((((y + 1) * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180), - // shortened version by your favorite algebra program. - lat: (360*Math.atan(Math.exp(Math.PI - Math.PI*(y+1)/R)))/Math.PI - 90, - lng: 180*x/R-180 - }; - e.ne = { - //lat: (2 * Math.atan(Math.exp(((y * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180), - lat: (360*Math.atan(Math.exp(Math.PI - Math.PI*y/R)))/Math.PI - 90, - lng: 180*(x+1)/R-180 - }; - return e; +window.tileToLat = function(y, zoom) { + var n = Math.PI - 2 * Math.PI * y / Math.pow(2, zoom); + return 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); } -// calculates the quad key for a given point. The point is not(!) in -// lat/lng format. -window.pointToQuadKey = function(x, y) { - return window.map.getZoom() + "_" + x + "_" + y; +window.pointToTileId = function(zoom, x, y) { + return zoom + "_" + x + "_" + y; } -// given quadkey and bounds, returns the format as required by the +// given tile id and bounds, returns the format as required by the // Ingress API to request map data. -window.generateBoundsParams = function(quadkey, bounds) { +window.generateBoundsParams = function(tile_id, minLat, minLng, maxLat, maxLng) { return { - id: quadkey, - qk: quadkey, - minLatE6: Math.round(bounds.sw.lat * 1E6), - minLngE6: Math.round(bounds.sw.lng * 1E6), - maxLatE6: Math.round(bounds.ne.lat * 1E6), - maxLngE6: Math.round(bounds.ne.lng * 1E6) + id: tile_id, + qk: tile_id, + minLatE6: Math.round(minLat * 1E6), + minLngE6: Math.round(minLng * 1E6), + maxLatE6: Math.round(maxLat * 1E6), + maxLngE6: Math.round(maxLng * 1E6) }; } From 395c27a9d28a6f0ec46090179e88d94f78031d9a Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Wed, 24 Apr 2013 13:32:15 +0100 Subject: [PATCH 10/23] bump version number for fixed coordinate calculations --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index f87807ad..c14497e5 100644 --- a/main.js +++ b/main.js @@ -1,7 +1,7 @@ // ==UserScript== // @id ingress-intel-total-conversion@jonatkins // @name IITC: Ingress intel map total conversion -// @version 0.11.0.@@DATETIMEVERSION@@ +// @version 0.11.1.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ From be957b3435dfc8f19abb12f10ac2928b0d1bc333 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Wed, 24 Apr 2013 13:54:16 +0100 Subject: [PATCH 11/23] change zoom levels for portal level display to match stock intel site - this seems to be enforced by the backend now fix #199 --- code/utils_misc.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/utils_misc.js b/code/utils_misc.js index 4d12fcd9..267a1c06 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -201,8 +201,8 @@ window.renderLimitReached = function(ratio) { window.getMinPortalLevel = function() { var z = map.getZoom(); - if(z >= 16) return 0; - var conv = ['impossible', 8,7,7,6,6,5,5,4,4,3,3,2,2,1,1]; + if(z >= 17) return 0; + var conv = ['impossible', 8,8,8,7,7,6,6,5,4,4,3,3,2,2,1,1]; var minLevelByRenderLimit = portalRenderLimit.getMinLevel(); var result = minLevelByRenderLimit > conv[z] ? minLevelByRenderLimit From 494d388329520455d32711eab9eafda03e5da48d Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Wed, 24 Apr 2013 13:55:16 +0100 Subject: [PATCH 12/23] bump version number in preperation for next release --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index c14497e5..3bebd816 100644 --- a/main.js +++ b/main.js @@ -1,7 +1,7 @@ // ==UserScript== // @id ingress-intel-total-conversion@jonatkins // @name IITC: Ingress intel map total conversion -// @version 0.11.1.@@DATETIMEVERSION@@ +// @version 0.11.2.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ From f370e23a2d4fd776d431d1a4f4488cdc0bf39da1 Mon Sep 17 00:00:00 2001 From: Kevin Date: Wed, 24 Apr 2013 14:59:18 -0700 Subject: [PATCH 13/23] Add number of links and another NaN fix --- plugins/portals-list.user.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/portals-list.user.js b/plugins/portals-list.user.js index 899a1247..4b4bfbd5 100644 --- a/plugins/portals-list.user.js +++ b/plugins/portals-list.user.js @@ -13,7 +13,7 @@ // ==/UserScript== /* whatsnew -* 0.0.11: Add nominal energy column, fix sort bug when opened even amounts of times, nits +* 0.0.11: Add nominal energy column and # links, fix sort bug when opened even amounts of times, nits * 0.0.10: Fixed persistent css problem with alert * 0.0.9 : bugs hunt * 0.0.8 : Aborted to avoid problems with Niantic (export portals informations as csv or kml file) @@ -100,7 +100,7 @@ window.plugin.portalslist.getPortals = function() { }); var APgain= getAttackApGain(d).enemyAp; - var thisPortal = {'portal':d,'name':name,'team':team,'level':level,'guid':guid, 'resonators':resonators,'energyratio' : Math.floor(energy/maxenergy*100), 'shields':shields, 'APgain':APgain, 'EAP' : (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy':maxenergy, 'lat':portal._latlng.lat, 'lng':portal._latlng.lng, 'address': address, 'img' : img}; + var thisPortal = {'portal': d, 'name': name, 'team': team, 'level': level, 'guid': guid, 'resonators': resonators, 'energyratio': maxenergy ? Math.floor(energy/maxenergy*100) : 0, 'shields': shields, 'APgain': APgain, 'EAP': (energy/APgain).toFixed(2), 'energy': energy, 'maxenergy': maxenergy, 'links': d.portalV2.linkedEdges.length, 'lat': portal._latlng.lat, 'lng': portal._latlng.lng, 'address': address, 'img': img}; window.plugin.portalslist.listPortals.push(thisPortal); }); @@ -219,6 +219,7 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { + 'R8' + 'Energy' + '%' + + 'Links' + 'S1' + 'S2' + 'S3' @@ -249,6 +250,7 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { html += '' + prettyEnergy(portal.energy) + '' + '' + portal.energyratio + '%' + + '' + portal.links + '' + '' + portal.shields[0][0] + '' + '' + portal.shields[1][0] + '' + '' + portal.shields[2][0] + '' From 7a41d60d20f492cf3aca423bfe76b85305938566 Mon Sep 17 00:00:00 2001 From: vita10gy Date: Thu, 25 Apr 2013 01:50:16 -0500 Subject: [PATCH 14/23] Scoreboard Fix Links don't always seem to have creators anymore, for some reason. --- plugins/scoreboard.user.js | 48 ++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/plugins/scoreboard.user.js b/plugins/scoreboard.user.js index ed622385..65d2c119 100644 --- a/plugins/scoreboard.user.js +++ b/plugins/scoreboard.user.js @@ -69,7 +69,6 @@ window.plugin.scoreboard.compileStats = function() { var team = getTeam(val.options.data); var player = val.options.data.creator.creatorGuid; - window.plugin.scoreboard.initPlayer(player,team); // Google sends fields long since dead in the data. This makes sure it's still actually up. @@ -109,29 +108,30 @@ window.plugin.scoreboard.compileStats = function() { $.each(window.links, function(qk, link) { somethingInView = true; var team = getTeam(link.options.data); - var player = link.options.data.creator.creatorGuid; - window.plugin.scoreboard.initPlayer(player, team); - scores['team'][team]['count_links']++; - scores['player'][player]['count_links']++; - - var linkLength = window.plugin.scoreboard.portalDistance(link.options.data.edge.destinationPortalLocation,link.options.data.edge.originPortalLocation); - scores['team'][team]['link_length'] += linkLength; - scores['player'][player]['link_length'] += linkLength; - - var largestLink = scores['team'][team]['largest']['link']; - if(largestLink === undefined || largestLink.distance < linkLength) { - largestLink = {}; - largestLink.distance = linkLength; - largestLink.player = player; + if(link.options.data.creator !== undefined) { + var player = link.options.data.creator.creatorGuid; + window.plugin.scoreboard.initPlayer(player, team); + scores['team'][team]['count_links']++; + scores['player'][player]['count_links']++; + + var linkLength = window.plugin.scoreboard.portalDistance(link.options.data.edge.destinationPortalLocation,link.options.data.edge.originPortalLocation); + scores['team'][team]['link_length'] += linkLength; + scores['player'][player]['link_length'] += linkLength; + + var largestLink = scores['team'][team]['largest']['link']; + if(largestLink === undefined || largestLink.distance < linkLength) { + largestLink = {}; + largestLink.distance = linkLength; + largestLink.player = player; + } + scores['team'][team]['largest']['link'] = largestLink; + + //var largestLink = scores['player'][player]['largest']['link']; + //if(largestLink === undefined || largestLink < linkLength) { + // largestLink = linkLength; + //} + //scores['player'][player]['largest']['link'] = largestLink; } - scores['team'][team]['largest']['link'] = largestLink; - - //var largestLink = scores['player'][player]['largest']['link']; - //if(largestLink === undefined || largestLink < linkLength) { - // largestLink = linkLength; - //} - //scores['player'][player]['largest']['link'] = largestLink; - }); $.each(window.portals, function(qk, portal) { somethingInView = true; @@ -204,6 +204,7 @@ window.plugin.scoreboard.fieldInfo = function(field) { + window.digits(field.options.data.entityScore.entityScore) + ' - ' + window.getPlayerName(field.options.data.creator.creatorGuid) + ''; + } else { retVal = 'N/A'; } @@ -224,6 +225,7 @@ window.plugin.scoreboard.fieldInfoArea = function(field) { + window.digits(Math.round(field.options.data.fieldArea)) + ' - ' + window.getPlayerName(field.options.data.creator.creatorGuid) + ''; + } else { retVal = 'N/A'; } From 362b2eb1d992e794e7fb46cf1c543f0c0fa4e0f2 Mon Sep 17 00:00:00 2001 From: vita10gy Date: Thu, 25 Apr 2013 01:51:50 -0500 Subject: [PATCH 15/23] Bump Version --- plugins/scoreboard.user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scoreboard.user.js b/plugins/scoreboard.user.js index 65d2c119..4c53b995 100644 --- a/plugins/scoreboard.user.js +++ b/plugins/scoreboard.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-scoreboard@vita10gy // @name IITC plugin: show a localized scoreboard. -// @version 0.1.6.@@DATETIMEVERSION@@ +// @version 0.1.7.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ From 28dce8a7bb72784c3ce2a0186b8f2db806eebd52 Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Thu, 25 Apr 2013 15:01:01 +0200 Subject: [PATCH 16/23] set databasepath of IITC_WebView...fixes amnesia --- mobile/src/com/cradle/iitc_mobile/IITC_WebView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java index f66bb837..49ca6756 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_WebView.java @@ -22,6 +22,7 @@ public class IITC_WebView extends WebView { settings.setDomStorageEnabled(true); settings.setAllowFileAccess(true); settings.setGeolocationEnabled(true); + settings.setDatabasePath(this.getContext().getApplicationInfo().dataDir + "/databases/"); this.js_interface = new IITC_JSInterface(c); this.addJavascriptInterface(js_interface, "android"); From 488b68df2e2f0be15cb96918c7a00f8c413b40da Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Thu, 25 Apr 2013 21:53:08 +0200 Subject: [PATCH 17/23] simulate map button click on mobile @player search --- plugins/player-tracker.user.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/player-tracker.user.js b/plugins/player-tracker.user.js index 7f20df6c..c1b3f3db 100644 --- a/plugins/player-tracker.user.js +++ b/plugins/player-tracker.user.js @@ -371,7 +371,8 @@ window.plugin.playerTracker.centerMapOnUser = function(nick) { return false; } - map.setView(position, map.getZoom()); + if(window.isSmartphone()) window.smartphone.mapButton.click(); + window.map.setView(position, map.getZoom()); } window.plugin.playerTracker.onNicknameClicked = function(info) { From a208ba90839ac226ae1568080baee6d4d08d303c Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Sat, 27 Apr 2013 00:08:28 +0200 Subject: [PATCH 18/23] send geo intent instead of gmaps intent on maps link click --- code/utils_misc.js | 2 +- mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/code/utils_misc.js b/code/utils_misc.js index 267a1c06..4ded52e1 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -136,7 +136,7 @@ window.showPortalPosLinks = function(lat, lng, name) { portal_name = encodeURIComponent(' (' + name + ')'); } if (typeof android !== 'undefined' && android && android.intentPosLink) { - android.intentPosLink(window.location.protocol + '//maps.google.com/?q='+lat+','+lng); + android.intentPosLink(lat, lng); } else { var qrcode = '
'; var script = ''; diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java b/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java index ba5d3949..e21ecc02 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java @@ -18,11 +18,13 @@ public class IITC_JSInterface { context = c; } - // send intent for gmaps link + // send geo intent for navigation apps like gmaps or waze etc... @JavascriptInterface - public void intentPosLink(String s) { + public void intentPosLink(String lat, String lng) { + // TODO eventually we want back our lat/lng-query? + "?q=" + lat + "," + lng; + String uri = "geo:" + lat + "," + lng; Intent intent = new Intent(android.content.Intent.ACTION_VIEW, - Uri.parse(s)); + Uri.parse(uri)); context.startActivity(intent); } From 28da9e17464218162391b9fb09807dae7556a457 Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Sat, 27 Apr 2013 00:47:49 +0200 Subject: [PATCH 19/23] added query to new portal search intent --- code/utils_misc.js | 2 +- mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/code/utils_misc.js b/code/utils_misc.js index 4ded52e1..53a04c0d 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -136,7 +136,7 @@ window.showPortalPosLinks = function(lat, lng, name) { portal_name = encodeURIComponent(' (' + name + ')'); } if (typeof android !== 'undefined' && android && android.intentPosLink) { - android.intentPosLink(lat, lng); + android.intentPosLink(lat, lng, portal_name); } else { var qrcode = '
'; var script = ''; diff --git a/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java b/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java index e21ecc02..782ffd74 100644 --- a/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java +++ b/mobile/src/com/cradle/iitc_mobile/IITC_JSInterface.java @@ -20,9 +20,8 @@ public class IITC_JSInterface { // send geo intent for navigation apps like gmaps or waze etc... @JavascriptInterface - public void intentPosLink(String lat, String lng) { - // TODO eventually we want back our lat/lng-query? + "?q=" + lat + "," + lng; - String uri = "geo:" + lat + "," + lng; + public void intentPosLink(String lat, String lng, String portal_name) { + String uri = "geo:" + lat + "," + lng + "?q=" + lat + "," + lng + portal_name; Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(uri)); context.startActivity(intent); From 0906114a37badc2c713f76f343f5b19930d970e1 Mon Sep 17 00:00:00 2001 From: Philipp Schaefer Date: Sat, 27 Apr 2013 00:52:48 +0200 Subject: [PATCH 20/23] bump version number --- mobile/AndroidManifest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/AndroidManifest.xml b/mobile/AndroidManifest.xml index 844d7462..472be5e6 100644 --- a/mobile/AndroidManifest.xml +++ b/mobile/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="12" + android:versionName="0.3.1" > Date: Sat, 27 Apr 2013 15:18:27 +0100 Subject: [PATCH 21/23] looks like portals now use type .16, along with .11 and .12 already used --- code/utils_misc.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/utils_misc.js b/code/utils_misc.js index 53a04c0d..bd5c32c1 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -232,6 +232,7 @@ window.getTypeByGuid = function(guid) { // portals end in “.11” or “.12“, links in “.9", fields in “.b” // .11 == portals // .12 == portals + // .16 == portals // .9 == links // .b == fields // .c == player/creator @@ -245,6 +246,7 @@ window.getTypeByGuid = function(guid) { switch(guid.slice(33)) { case '11': case '12': + case '16': return TYPE_PORTAL; case '9': From be430acc7d6355fae89f2fe94d047bcba1c714ff Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Sat, 27 Apr 2013 16:45:42 +0100 Subject: [PATCH 22/23] increase zoom levels for google map layers to 20 add google terrain layer - max zoom possible here is 15 I did try experimenting with higher zoom for the MapQuest tiles. there was some success at 19, but not all tiles would load - reverted for now alternative to merging #212 --- code/boot.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/code/boot.js b/code/boot.js index caaad95f..2982bd34 100644 --- a/code/boot.js +++ b/code/boot.js @@ -119,7 +119,7 @@ window.setupMap = function() { //their usage policy has no limits (except required notification above 4000 tiles/sec - we're perhaps at 50 tiles/sec based on CloudMade stats) var mqSubdomains = [ 'otile1','otile2', 'otile3', 'otile4' ]; var mqTileUrlPrefix = window.location.protocol !== 'https:' ? 'http://{s}.mqcdn.com' : 'https://{s}-s.mqcdn.com'; - var mqMapOpt = {attribution: osmAttribution+', Tiles Courtesy of MapQuest', mazZoom: 18, detectRetena: true, subdomains: mqSubdomains}; + var mqMapOpt = {attribution: osmAttribution+', Tiles Courtesy of MapQuest', maxZoom: 18, detectRetena: true, subdomains: mqSubdomains}; var mqMap = new L.TileLayer(mqTileUrlPrefix+'/tiles/1.0.0/map/{z}/{x}/{y}.jpg',mqMapOpt); //MapQuest satellite coverage outside of the US is rather limited - so not really worth having as we have google as an option //var mqSatOpt = {attribution: 'Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency', mazZoom: 18, detectRetena: true, subdomains: mqSubdomains}; @@ -127,10 +127,11 @@ window.setupMap = function() { var views = [ /*0*/ mqMap, - /*1*/ new L.Google('INGRESS'), - /*2*/ new L.Google('ROADMAP'), + /*1*/ new L.Google('INGRESS',{maxZoom:20}), + /*2*/ new L.Google('ROADMAP',{maxZoom:20}), /*3*/ new L.Google('SATELLITE',{maxZoom:20}), - /*4*/ new L.Google('HYBRID',{maxZoom:20}) + /*4*/ new L.Google('HYBRID',{maxZoom:20}), + /*5*/ new L.Google('TERRAIN',{maxZoom:15}) ]; @@ -161,7 +162,8 @@ window.setupMap = function() { 'Default Ingress Map': views[1], 'Google Roads': views[2], 'Google Satellite': views[3], - 'Google Hybrid': views[4] + 'Google Hybrid': views[4], + 'Google Terrain': views[5] }, addLayers); map.addControl(window.layerChooser); From 4d0ca0683652092706f4dc47ba47c398a8d69d34 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Sat, 27 Apr 2013 16:54:42 +0100 Subject: [PATCH 23/23] the new IITC logo - source .svg and high resolution .png --- assets/IITC.png | Bin 0 -> 52987 bytes assets/IITC.svg | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100755 assets/IITC.png create mode 100755 assets/IITC.svg diff --git a/assets/IITC.png b/assets/IITC.png new file mode 100755 index 0000000000000000000000000000000000000000..d4c6ac5d657d5633f9004e4919ba41e9d57e81d6 GIT binary patch literal 52987 zcmYIvWmH?y(sqKo6nAKgI}|SjX@OFpXbCRC9g4dZDBfbhp)C}5cMUGZ-QC^g3%&Qg z-;b=Um7O!Q_nhaUxMLZ==QRj zUjP7(SI-}yTQsZh6ciZ%a%5@g;4qcE2-{6)5!R{ zLM~;FahC@N3q9>z)jx|3^=gmAvnfA6*|NQy0&#C87Z)_a5v>bDG+)BKw_xhgd zBP5n)>W15U?-Qs>RVzDAC0N58=)jzfh0_XogoM*{XM=RL0PZD~D$Lo0c!?@<%vr$u zza`PcfJH8^eH$Mgw>{5{^Ou~_$s}4-OVq35JMaXh+6B>*7RxC>VA4%yje%9 zG)@I0^dnq~E83@^_Kj}kZqY9GZ#C*#Iy>rQk3p#Yb)Who^xj$9CVh zE8>gH?E3!^?YQ0l$#QoPIqDUv+X7}KMUs=&xU{Dv+@j60}=f=)|m$5W~C7gi9?-Sv;chhs> z_4?N*u42mf-SBgY>&P(&BG@yso7@flvS4|!{E&0Dp{V+-+8A!bXVs@6$K5Seb$-Wx zB^LdBTQlkL7b0~7z1sR?j4gcDZKm#405n%ejTM;F;c8Vnl+&+$3-=95lDk!;5QTB|m98GXmhvppVofiTj5 zNqZFkKhXID+~mEg87Z}nKL>G(BW|C)``z!g>i>VYP#FOX&HAc;w%;et&kNQFKOh#0 zsF92QFJvtw!A#2vIJ3qU%o@g2Wvsb-2gKn|a0A29Dzpy}YalZAY**L(NJ+VPd8WJC zU3ne-@gEpFP?zz6IoX|(F6OeZD8ORrp^vX`Lzh4p{NiWiXu1QeY8Zn6Q$*!;jV9cC zN66bZuKL=!Yel1~|B)~eWZxu8S8?s1RjPF%z^Eo72=LI@KkW3^88u1xhk*hm+hiSb zg09OT{*gF=4&3npnxS^z#v54n2X2kTe}6$lJ`QCYRT&*`rILdi;A*L=h|j+Gp_>vm zHu~#7di>*37!%{>2vBx*OsE{}#d%4g&-*A}F!~Q#gn}3)CCa4rwo?uJ%?n99Nn>EG z?!Zm=`hkzJO`~)F5fahYj%z)i&c$F)rW+5;(ieZ#dM`-R_z!f?U_ZxQ#!upu5vCxh z2ak;U7c!X21~v)geqY1pld4;^JsB*jFlp%ej}Jfvu+}i1`*RRh7snjjDSXkF!YZia z{f!TaK^eGk38(B4*%)N{hw@SJ+O&jGU?cywq+vt89j+HPHzux`D;KD@rLNb%QDgDP zKZ*1>ep6Ne)v($05hPs-`~JBV6ib54zxF6m%8|koa43~ISO4$6(E@yy(eEyUh_^2h z=I0ZI>GhAt6ZOV0u-edX4#wd&)i0P&yEtI=gS)gXCt z_-D5Olw&BzF7S4 zgk3l*3OM?}m0xYGd$NPjQmS3y)!dj%J*fdTrQ%;XLO~zLo&N30h~>!R_#3yy@9gt{ z5=03pae?tU0u}-iOtoKlRfhOecvhMBzm?kTy!RfPPF>>vVaOB^-Sc=E^akC{J2Tu} zD)`6jDC)A9YtL#Solj)gfY#FOwW52&KOaoU>$g`KNBQ~s03H9e^Vi}cYH-hHGd>c3 zSukJtXAHp_kj_@J&z?37XI;)e;1Fup?X=l_B4)WZH@`M&qd=&QpiTh36wUOP8eO{& zL}>5A{huY?GMt%jM=Bk6`6apo1emR*-hZR_%CL!<i=oEQhd6VW zZ3$)t@&X3halQNz-Lw`9|6^vA#f#;dxj6!9KTed!p^-?mx#q>{+%eQ{?sv#$=mUvC z7(ROxS41HD{}>y1e2dUZk+)2N)dusMUviFaaB&%gzf6JDNImkknO=%dhp`TH2Uh))?X|Z@GuKx$404G0L>e?_vg6@i zl>R18E%`a}jv@wiiNB#&0F?rrdRO)Ux;-g=QP+dxf8@U(c}G-#UuNSsBmIJAR={EB zaXe>6YIs*nG8?%`3=e_7q@ERb!qNH${?w_p@L$6aO1#-m?CDZoOw!Fd(6sxW{-sE| zyqUd_q$nm)h_X`VVE1d(kPd$~3A!k0q%6c!lIDT}soB5PO5~%;^sOH24!IF=e$!VW zkGNMs&Tv(A8Vrc;)H~iMj}~M?&q$#kH+YQ_7b0KUgWk+Bf{ihs#k`Se6-stl_x3mz zbhG{0<>8TF3E$i25S4$PfDh5V`SNDT^fmM;QqHDxHV zhVE-h9MGb95aB1$`dxn~S|YOFY#EehUOewT3Po=tF4+yfoJ_u=d-%>b>oK#197FQp9f)`{tAP8~ z!2-BmKA#u&GxXzM1h-1S@y_qvDdh_kASZSeu07PT^ThLL9m(bz>bT43d;dL6@9v(l zMYTb1d-NipiOTfT3^Vh(M>iABS~*1R`7}Y#uq_UFG1|-LAVb8m;z9xDz@?`}?!qcgH^O0Uk+k#NS>;+DJi7R9doD_Od-* z716^2_-oh+%I@%_#19<9K{vA@o)$^2-n$JyOEBMigwGSRgX=?m-p06+h%d7K8d+iQ zlF`9{>JI@Fk(d0ezR|(mM|$Uo2Pd5~62KyNFLSDQ^G~yg7T~%vpS|;;`o1Cf4(!5L zL_>Bc1*be3b{@;$&WxMa^RAvM|IoNVS%p}xBrzMuRQ*eHZi(_gdru}KLb#Sk4$DEsKFb2Se|JCMcWd}7YoQK<}k z_hqt~GE?cbMrt%(uRd|ldLhMhG^xQ0r^#~5iqg-Jw$eOH)in3Jw4RzyqEf(291Vs1 z*p=`VM@lT!z$9sGRhtfb0=DfJQqYIZ{V29doOjWPgp^LFN6y z6e0z3fGv&>%%41S$Yk1YH>@!Mrxx$py~avEmII|F+7)nM#OKTU3i#@)6`5D_pikX^ zuL2*zhXZ#$ALEGL*)h1`L~IhBlHTJdI)Z7jv;wmDK@{;n-ru~4JVh?h8~?%3bQ;L? zK^Mv4+(a>bm|V+DiJ~@li%@PR*L;FSbBd(s2uYF-^0E-SKP~7+m(4Xf;co$)2dlH8 z0SZv~um}TNNenT%#7Pi}1qVMV%UFT~X9uR9_EpS`z{Do!cOK9p2v8G3|07Z4gl0=H z0y$Ezy&M za%VOY(s3wF;>|~9ev?}I%Zm|=>9+HT&&}c!AMq@wWNdD0xD_0O09AVrb826XedcPT zm`c%>%l#i|7HF)ZqI?-os~ z&|6G1+(T+PG{P{AOY5}C8pcL-nu1PN$&K!rc6i{zBoM$z+GwC-X$(M!Qft|G33fAg zn-wAlv0oh<hYOUQLs-!%2e$?BmqX&q4Co?QrW(%zYCrsEKh;Bv{ z(72qd(kS*4qnh^nCe2c8GWYe7_U_(a$9#W;jF1A(sRZO^Y|H#=39*CztZv|a+ub1f zcyS0DA*2IFP?I9IPN6n3Y>NXnF*LS2WnIPfY!mCn4~Y=Bd=vneZ{m64q!7s*aop=- zi*caYiVC$Khd*6MZ_TkQazyr{&HKWAlMj%McqKedJ*q(OkPuLveEnt$_0E?ae>ne4 zb9ly&)BH!4pM(jL0W^s|N>OXJ#ji z4{VF8QNPT1bvq`@_o}h?u^Z7#r*XuV?WAa%UG?Sah!ey@U@QF3V^s0 zjv$QCOnQ7Po`~(mURLzTuhh`$F0E2Tmoo!Mg8Es5eXTJ!M{lE6{B`Im<8ElNMSo7txlnB0@y&v)I9(;r4 zexq_1T9(Pb;JPt0w8BUn)@;f19nn?eluwf;SEWPf?cl`Z7d{x?prB)%uUYfL>iX#K zh)Lwm0t~~l^iNP9YLzBY2K~~Njc>o=5P;yVyLePf{p(~DcOpC|06K6!E_1(tBgbX5 z#wIzEYrr3jlHvT0_SZwVaJ((r^9jmgZ*LrX;Y?rT8G8irM#)jQ%iKvRSGfrkvWb=n04Y*-CLuzDd_{P;c`IZ_EmzMQ^$SR+DV*9^-Q?p2qn$H;QkH=~@ z7SER}?VX+Q#R7X`>A6~KZvH-|;B2XAYxxq{;nuuh#H~Sshg&v(zFZ??O&#hyi^LI& z5!}l9CI|u$)I_XNjgy-%2&W<>I9DD~@r=G1AQ`gNo_95?X zNh*DgSKdH}A-r@pwPR%xqIr^_5Cj7XFGwH>LOH2@{80*m=C{257qdB@LE`n2`J04F zrn%eOT;dE-;{3@4*t?{S1HBV!qEGi;4PCw2x{oQn6ee}5KnGI*^%)Hbw2}8mAagw~ z08$c;Y>#u?6)=VLnrYdnj!-gHBe-rST|TC|O^6;kgFr6?nCbGh=F_km=Qd7?4bMy7 zoj6B%nkt~|i9TCWTw;2J9I5=w5$$WB_A+uBd&|C2jon_IYtDofnUWq7`vS(aP48#( zcRVI{%YJX5_#?Sip3!I7CXzUO&is6C|mU_n>P-TFRlB~WW*tIjxB4NWATfFR<#d( zb8+KRe||_Y8CO0D1_(VOl8(I zp8*Y`@Yh>h5XFx>XG`f=-Cuyg>5FXb*F408*m`*_VZlELUkLo-5qel+P>{d03_ zs{M5mU-JH3a=W?FzP76tipelO^DAzW3`bZc1r*mXu2X#p1Pr{-`uS7&4k?6u^Os3d5UF6M}Ft;3FxdJ^Zu$*3(-n@=LoT{Ulgdv|C9ddFr zwpwf9XaR@(3C*t}p=_qUXF?qz$7ik$!%pm@$#+`cRYOYaW z;bF!rod1bKc^sH9r{#TJX-5-+`&;)=e`-ir-?Il;Gob zRQAwdxx~GmT*Ms$7=svf2Ko#n+tq+aO^ESO{f^^Y-x?YT6)Z3kZsYRj;lg_%s`?ql?;f z$d|a8V*2TTvPiraqb*HsdrgCeY@;TMOSNxiSmT&!`GIcl;AObk1VlF}QoNXKq|fir zwlJO_O8+S&U8Zfv1(ve9t`&U1@A&+`2xeGN2!dv?qd9HEZM1Tm&a^m(fts@Z!d4DgDefv2U7UncPMk{yLNX?o|^E5)X}2oKg$k+8LpY}2Kn znI^GW^Eb3PTl8Me3}ysqtvRZZNt33x69?}I=Q3yzRAM|*4r#1raaPP~uubDPeA>K; z4a=od3iyuF!;fnDOz~3lw4Bq1On&QAiu-bl^&Mr34rMDQ_D1hf_LyOKhrQI31hYwJ zyeOmQD8&ettmPysq~Tg)S%&VC%&IYD*jSoqBa2+t@VrFX%8b?=Hrwtf(xP!`oQBga1DlyA3JZ?KF01LcZT4%#(sn>8U|rB zBlD=ruiyrY3tpB=v+sRV1qh;esV_&OFXYQ`N7P+nH3dUiRthcqU3mas;sHIvPbc`3 zHX%4Mz#Lmi`~FmWAIQ4LS}7N??+aGt;)zEHjDN{()nCe@Sj;KM0%sXtqb<>0W=0Xk zaC!9gwyO~mBC~?6zrqO1b^gHcpcPlY*ddIs6eE_ovk~iS+79Ue0B@O^*3@Q<7u^({ z>-Y5dMH?Q2m1+ zp!rU3aZzzQDJ6VVdxMx;JCcpQ4CjsN50dwdcoX4^iO^uXsqwD&-*yk@a(=4c;qA%K z(1mY*bZo~H3fGYRN;$7%qtp!*=debI$(7KtH(~2je!S@>=1RARJ0S5!ExdHRGSQW{ zO0*Pc5c$6&HYg!z%hSj2ZK7o#=8Ekq#s|u5mB0nF=CJ!#$`>%yQjp&>_@D*qe<$#k zxXqJdKdL#Wa}j5NhCnTY{*4WQQ$65GDG*-v5ii6}n_;3rqe$SLnY;@AY^lBpz(HSP z8P!@9^A>|z4Fj%_ftB-7q+FrOh6Lz2> z6hpH$Y;e0qbV*b4JNnvm1vOn~cJ*m~F@!5S(4Xrg){3cF3>{@VY9mtV{*yXiL+_E* z*;PQb%)46&g^x}w9dzH>N~BKq<*$~1_!rn^xX%rHj9fYS7?aRAZn-9JDAuC~KI54I zug8(zZ;6yn>BVhC$_Aa-%FJET9j78jXb9p8vv2E5!pFjVL@Z!?S|VW#)@wDHm_RiZ zglUv^yklqoVxnra;|nR%^$qqI7ymC9OsoQ0-;j(a8dUJzxDthFF_-fLiiPx$Nozo! zaUIt$Lr$E1A~YhkSs}@r0OIft&SO+hov9C!;)3s$5|oh{x%OrTMzZ8bl+Ji3_jTNh z=_iL2CAPXi86(k^DQ#f^S{=6zIkp)|Iik)C2ZUS+bD1`a7rdHq&)~edTa7E2nMY30 zNza#R>8{FYYPnOQ2&zb;=0(!+l`S(fk`TOSoB@&~_U&o&G?^S38{Tt@mJ zdW%x}HiiZrOP|PXArlkLYu5oic22Kz9LFO6F_se=f?^!|L`trUeL@96sH62+!;{b% zv>kaB@tz`M6QsE0_0)BC|Aj>F=`t|zk_LD3jrZA15u_b=faY%%ofPRh?&rdz$O(Kk z)5U29^U$4{iFu2&gX-!0%FSJyntFDGkV*~ieQK;rtF98d=1r#0RN2w|slCZe<7I<7 z>{oW0R0Ry^lkCKiOCPNAqbzdx(_CFfnzybWbe?vieXUf)Q>oii8c(ja+i~9-qY141 zLINY8LDcQ#0RpIk6nH$D3J<-y)$1)xl_@3gk!e4*^LJScQ;LJKG;Ry$QbMz)k zhe@+%=JsrQvQ}pSxvH)s-?FGIcO} znxu-6C5`3l)QP;HV&qkq(OL}RQ9X+lcd@aYRKA$eg#6^Sv#W0dH4GZUz5DfT4b41j zm>`><%>DGr)4ZM}6v4~^x!q9sJqB`wdJDrw0g26mem%2p!);}DTLk`xeIEr^z9L&t zmwP*!^Pcf(=wRbsZjAcThwR)yLCFG05fRWJe@K~33Z~ZMCL9YZ>@xeBtp+Xl^BzA0 zaQr|LeIiW~c@vXACN4ZMLRW}jU&z;`L`10#)Ce`Ejt|`JV%2laPQPGFm5k$iUto42 z)=5~@>}@bVut+3HH-}I!|967H84G>g@mv0oE}6jauRCj1d*?WZiW0d#H|5;}Vv^=H zh2khq61)Z}H@m-?n@K5#lhtx~QAy*!5CC9}ka0kD$5i)xM9CZr@t1T9%2e$m(pL`a z_U~x#k_!rgnX4!?sYcX9nMhe*=4B5Hzf-9>G<8d`73hY_&|4QJNOr9N#m7ry7>YeN{-*5>rMH`bvET+U>5b#Sm zR=@QoYH95dpmw_hnD1J(x2AsX{ew_`KlBE5q7MLxKLTrzFp_>OkWR**kmuv57CXX$ z$fIzKJRT&UO!CKQF!WPow-44`@m_iJ790?x;ul_QPHGx1>2Kk#zkRx?K5g?5pJs$4 zSOjnW4A2x^J49_~A;RK5fgzP@?HjGksas{WVj@%ZuiNJ}fS|8rEZ(D(+qOrmch@_2 zQ;EMa@CvFe5tx+ZK_wO8uu7I_mEKYIY3_b5yueFSq|S}bmnf*GYJen~#LxKcr(3EL zP`uUO0lyHz1wLiR2a+!dow70`O~PRLdgh{1Z8L=l9mFP^l>qUmqNuDK%ZH1Olzd&o z!dq)|Qmct#1X#{6`zW2=7t*8qbMGZeBD}Tn6KW8{ea4^blQ2HR5af0wtiDRT1pW3n zyx`=lUx?G0K6J+y%1z*HBf69!weW(E@`8Vk8}{OgFk`qkcSm-?sB3XP5E9ZrfiR`0 zA}#{Taees#hTY97cz+O{c7Yzs?9Nv~)Yf7B&uy9x+^i^?W!z&MZ5i%^pK&5Vbcm5x zfE?vEe%?34tuO$a-30|sW3fU0_HlcG&6U4JV6*yrBD5Z{P0Lte1{CMQKnJ`Q2U{)| z9Y_RO_}qbI@cpX(R;L^l&e{hccX{JQ(Ou1T^xt;hh~Ux#_I~VkW@_?rtb?C^DToY& zt)v%w7_?MQk|~xUIOg&q^qg-fW4s68&yqE-y1?+-uD~G$i~*A#IVF9CYtq{mC8*3v ztW4+GL&2j8W+?aWwKh%5$z+X~*v6BW04TjvTyR7$i51z9O5B9^4N7a;E#iHP(zPV8 zFdz(ri8)i7URb4#Y&5FZfD)}IO^imFYL3Sd8y!aKnkD>;nB&K+h}%c%y{)B|uQYR% zutdAtX#r{EPA2F36H%W~?{8n9uKBznxD@T&lY~-gTz_*7;&7*Xp9*m59hIAy{Z_DK z$3Dx(yfW5(yDaaa+8^eWOf4RqT;ROxh7N&S3*g*n$>pL4*(Yl>QRzy%6S|(aSiGEq z-xPuO=QJgRp;!L*gLf|1+^aS>7Ukf>H%Mr#f!r^|!J<+@1qOJ2=nltE^?6HbN&x>s zg5Qc2%h~&aI-^>P25FMGE3&RUtxYcPGNFgxGZ9!~qW!I3r2Vbh9peHwYT^h(e zY5Wj*#}QNabnPHHPaGW*T*^@v!ok#E*-1z2r>oBO77dfeYeK*)GLw82*6Al4;#bkz zLU~s0<%gx*EkilM4O1%$bjYr)e*5i+;Zzn4(&g@LX#JGx-sr-k>>3U}bo$=mww2TR zxJC=P9s300^SRymBa_sA4bxt#wTlHQ!OOGQMBhXF?Rk|$qM2_2eGUSj1&|>Uh-IOZ zSdnK>lBgaFv`3BOD2NL^t9+$Zvqg^8E)GGC`|cc%byX&!EgK>^T$Ch-B_+tqFpy*Zo5mJ+eEfiYDdhnHhRM@#tHPkyPU*w{*9jwfW6`{UW`CbLWmQ>CCVwZCgnyWn= z?5l5GQ`>F$_5it)vbp=3j^mL9q$se547J||~M02m|yg}e$TeqUXglvj@{f$WIN_|Z`$RZWh6zU49YZ9y`qNxO5LQS7wFHT#r2Wd+Tjt3;5mUG`T>N{ZA2={l3G_)8`+?oz(fu;{=MAnF< z=r4qyIN_R;Qw=QzD2*o=xObg`3K6kJ&;kQc`s$dB)9T0zqNI}ZRokK9f!^a`l|Lp5 zF6mCgJL{ZLRzDL?G~gMjA=a#I84uu^6cluGDGWN(oCrtvJ3f7k=8&I3=rNPc*?_m) z@VQsOcDK=qxQO-dEGB5JKew&ix8gl<61KvWhb=8({v-&3`k4W2l(tlqTEf5GbmEgK1zEeKR{29zFqbL{h9BfcKZCu8yqZZF zEN|Kyi{XP045TG|Pg{9^d}x=y_zyiaNFPd0l;(t<>927$cZzgxie5E7NxO(Y&W2oF zNAo^)J)O5iy2~`R8drF|Mw?SRW_v$EtnBn=)*DtW&bHm!ix-$zuFJNh{E6^*5@e+Qk)aN(j=Y=Z{Hc6H}J08^`H zP2KhC6fD26gOW%o7BwsF&O}hBek|8scZ>9w8J=XxA@qnv+$@=eAC0{iHS60ud9u>6 zzqxULcIplEK)jw-{Q^3!;tyg*s222m`l&j;SDNm9 z88W6bIPtVJCDwShIVA?CytQ`4lYSFK?L;ryWnSj9HE@#V1lR;-V;M4@RaBgQW!6jc z=me9tqpGeHQ8qh|Q~~dGprYB{w;aWwE~RcI)v8CW!`*2OG6Fvy+oh1+bFA>+(#UrB zRRKf2@7Oh&^;Wu>ah7=*(55ncEe}zNX@spv>Ijj*v_Xkah0h~52t8{${`ZqDH>J>A zwkaA{;X`~}v{)>Hn5NB_6WemzXaoLaVdqILs83MD)v`LEWQY!88aVCa=V*hJcNTRmW+s z?)ty)_f3txwqdEFO6zb7q51WU(xQ?_UT%k^KmBnpf5W-edu4(*$rvt?0mXiR$pU>+ zFYd4@lG=|;hPxdkBcxqeA&!(|l{7K0^MKv-iGp&hSvFsxDniK+SS81*Wpz$ z>Xm=k!)5_eWhHIfkw@OU2sul|dCGECmVz-KX3w`gsE9*O)*Ai)v^Wim&fLIj(_fJd z?^U19o;dEiC7EezY?fnqgTB3J<;O&u$6|L~#<=F07AAO)gtv?EmutyCfOui^dmolE zr=`Pu{;UyfAR+!n)v)Mj2%PL%xx;Fk|1t&lrgeC(OQzek(MgfqtK7!d2~knDxVn_FuX?rAI=;i>aly=!-bDAo#J@+q8Rd^p{2XMcQqtp~Fl5#;}<9~A~5=fOEO)scXQNTEWIvg`KaSSGi5f>R_DJgkGK894oQy;Ihl(}PTPjzmdarB+djQn3cmg!vBARri;v9OG((YV-}{SEh%IHWD& ztE24YtRJNeRRM?02Q*b@Inue#Sl8nO>2I_5U1bX6$v({Yt$QG!RsS7|PjB(O(QQmr zI)F&l=CPHlzL!tR&q4p~pt^tKBWg?iGq1R+(RT7b{*Hu)^OHI>gKT!{J|fUg{P<-n zc;cH{J5BKgI;N>;908i)hB%QH)gG)r#s>}x9HI{kkEvwDVBfM!h!O!G9r?xlF`}wR zSchwSbd#EOu2KGqEQ7_ET{Oni$(cs+{>iJk17iKVK>dXm6-6^IbvN;7BR*q&2g3W< zdoR-yZIVLymG>AC+p!*6DH0hVKKs8-C6P5ct^q|oaMdOMQb*Tx-$%Iw_<$|xlH0?H zFV6;Nlx*V7>x$R!&7Jqr0!haSBR{uEXJ;-c4t3vKe{ON9rDZRZKK>e1z*$M=KQ%=( zfF}!EnjHH4ER+V;bCQ467%%wj+q97YkVJX~fBA7qyhuU6n%mX3E^h(kU%wZ zxnC_N__0Mk*5c#$8O7+lkC8KrD$0q(1j#Q5VsXa!h;nTA-u=vNz#5h&Ryv5a%SjEg zO=7yLdx+kt{-`!}@}cdkK=sh!#e?4GVoSjRD@k3LM3u0BZy_9^i0-^oz|$(stHWbR z8vm%tCAwk6%j4%9yE5ZuMxu#1j#hf3zWU2{2l9y01(y0i-m9JoZ)AgFlzd2To=0e3 z?Tx7H>#AZ7?uRY|f-2MIX{D|bbkH%pD?Z$q1PoFircWXdMlqMzL^MUCv99UiyqLbc zJoCIK-NIOJ>OL$QGdUf4aLa&C77X#LR@%k|zLVMm6sopyY?={z5gq?+V?i>9eERKG zj0vpB!&a3_B760Sy=jTMRK^;C`!av5eOhpv!0R>N8#mUT9}Il*x{k_Ia|F%qCy)3b z7f14|f)PtWf>@`mipY;}Z|_KYbo?LpdpVsn_^SVam>D_ALP~1-&2$Wag>((|GjLiO zfaRs0kBhiCo*9X3$p$U5oB?crxlCcLQohbuU(19-3(|;r`6F~+=BZztU@tmqjS@11 z)i0*UAYMyG9jztL3wcj)VMUMMqzLj^v%xuNYEQee@5*?dDm;Wgok7fkW{mF-^*vRX zuGzW2^#I#*Y%mm>4M;$xV(1vod%wbRP1Be$M?Wi;$_|+I9eW#Sng$=>C;ik+JP^`; zjDJbNPaBh>%~f5a|29{x8yo$YO5g!D$bWW0p)oLM#&+c$KU`a!VR+Y>(BgI?s_VVp zyuZQeGR=d(>#0WwZ)u-y)`&IB@Nigdwy_HEMfh`l)!U_fy4xHYy4-a0vSjTJIp1v& zW*=bs)$+9WN%7{>%9hxyND#BZ!Ec0e4u3EnpgWk8xRG=^IEpr%Zr3RA4dDP!T#C&+ z`ehi>22N=L0tC2zsMn*0y#{Nw3pgnkP4?G$Xq|4(IKj_Z><9ZSh<%m^Ynt7cOnz9n@8;1^YDa9XTSAcp3n?*?&LIQ078nj#g%z=(pYmRb%TgO zu|C{SaKF2@Mqd$#sZN&}z5T;+4u?}jRmCr_TmUAcm`?-im zMx`Bi-3<>(*#^dOGbgo!!1pI8-VN$U90H}=iC%IA#QXU=c1XRarTz>u_ zUHQLa&CBC};MPRt*G^xsM@J_LxM>TPv5Y?IjJri-z*!R0ajeiyU@0g90rMOBXubQ-3l%EIW_hf!_@0KQEDmcb+ZcWLLw)Ze@_p)u?c3g{rG(n3RdbV0WQWYbT+4%(t~8QFC9dwf2{JKFkB z;A+Sjyr@%kj(8SGtt)1yd7$C5j7gD+oEPjXPv$Z54>gN33ky^vXaaM8soKGy(o=4^ z$E6M0lCuXb@01@IYCGM|(;mI_OO>3{O(lQoh7TEVOqU${vUPGI>Ek}G`t_%(rEzzj zGEBJrF6WW(f^qaG?|yqh%jkS2qW5T|K$ZDTjNHW6v%Qh-{ygXjkL7`~1s&pdpe5^q zqS^rku&c$rdB33Q`9tDgz_J2$!eFqz)IL+TZz#=2tucLBEwn7gul>$ zV3>+=h=6Ms91IXd_VRAkrZ>98st5+x({Mq*D@FZ@!kt9bz$P8uGq^0{_wF_zB>>}* zoCI)}ZRR8_arclz!Hv*&r?qSWpovvhaq(DKhw zA&2V)AStZ0MT>ia} zvY29#M1baQ!I4JUK2r}A@*9Sa^*A8NNsaoz`hAPw`eO)g@(iz&R{(ILvH>T(8YOx} zH}ZcNKc!Qq!{<^!(=&t%ynb}Y6Q+om!o67T)TV{MaE64rw6hA8d-FGxvKqJ`Zq5npjIFtT2Xj&aP1i%Hmw+<{3hQx|6jopRj;g1LlO0{AImm60{ z&G?d46hJ_#&Kz8dB#lI4@0tLYR!3+6--8YjGDPsT|DW)(MJ!zfkpi_7tqe<29@}iJ z5lIDta}~X7G-}V4UG)`C=)C)>adjFCQcz&hPtk`~EdZlGC$cZd`R_y<);33~dKekD z$p`vB+ug#>`$qXg_^|SqRc&Aa!?xS-lqGb7pFRzGxc7Eqsa0+(c#AsX*SS=cg6fUI zN6Yx*rDKlSrJEwTAIKeMJsRHQtTWzh2^=+^tyA|lUQ3c1h2azhNFmlXOcKItGZGp# zxO^8#Ni!gM5d%}=D(isq2`8#TL{}Q9B9+EE?JSv5eiRUb5Ky+Ohhs}f@IgVA)YoCJ z9*4nlCx?2Ah7fOPGVN-=0z`S{x$`^Qsb<7U#2T5L2~uE~W_ha80WG3xQW(wo5Dcf9 zyO^9hX{T%8;B`()f8+#jM!B0&};?fJ%(^+9-!tC0`kO8G$n99dmF zGaYSB`MZA?jcabG)SS*=&LEwKdQ)6qh3A1llSW3bI6gm;F{iT@gx>f$y`dy>z<^nj0W$r)+)Y z6H3HA$AG4aK~FN_gS1iptsod!6W|q1kn-Ecm$<=tzv;RiGgim&zDEBxzTfvQTc7&7 zd*$jJ2i{~g=0pM9J!zpDNIL-d{bhnbl8B9CP%trVByw*07e!+a@iXns65YP_`e+uy znD?}UB2N&pvHZ@#>1Y@m7BtOkuURA~PAbJ~M`aBADMwUTJ`OFnWoAG$`svI0Tz}Qv z4Bk8zg+=G#DH%5(0XWQ1!rl|kyENq*qM>)7n%^Y-25J=jFXT6iKW;GlenXDoypaSq zHKnFtB#eCu25^lbOc$Ta#{{+}m=o0uODIjjT4zv9(&Q#3c%2MS>m+t-F(CrZ5h2{K zsZ33r=9K9poShR53#~}ZF$P>3oabc7^}o_w-&5#6jBGRNKPXkZlL-2KRhrdCWBfFR zr9%{`;e1{k+=h3l+@VNLcAqVM2Y->yk<{)45(f$K+W4#A+=ly?*-jVwJ(aeQm%>P` zl;x@7kPb39%#vxaVue6MS(#;1vAHL{vX5y}NKf}VLSYv?VM=tur~W6f%#sE|gr@#L zd?^GXsOrRl)3fu( zFfcpU50L14mBC*I>-=x2!0-Pu51nnMTZIUc@TT`+k?{S3IR&?WMl-yQ;l!v7-|f6PcX3+eSuyv>QGpVM zqq(JE_J`SN{y1t~s6=tg`D%Eqj>!H6r;kDS6L^brao$%xMnW^4#qFt691Sv2623dZ zs&t*ox4H7?=fXITG<^t1n%L_rTp3kopFU`AeA%xS@Dz11!!Eo^=;MdzmdY9gAJI9H z0$ks|XpieWMU;X`S2_-8V{e)NK&jSfT3G$a*;M)80&~2~B4{H`di>}|0SHX(r-sMS zIf!M0S~{b~5|~roK1Egix2j~S>O!d)pfs6Md@-j63*deQPXiwf3u}&B18XWL=`z20 zlob+_|$LD_9lD9GUk+%Frv79Njgp z;u`J7wJ4EtUJZTE^#{-U?)Ax#3?feLrsg3O1F9f(Ky{KOOTVyQj)i8*u!aSTMp5rin-!gXoiic9?uzv|p>u{NYoz;ia%yT@BEKAJpv zTS|B;w$Yn^>AC~=a06qRby&1!sB(^gI$~;oQKS(P5Z&jqnw7hP2Gnv;7+p9U8FC5t zr0f~f5xK0AIhF1t0tJI0LjrjPF0}nf_ zn_)>sYed=E?+>L!Ss_z=u*_xl0Db*JE6lWS9uAKh*ABZEpz8@<&=4Wq|G;}o?>hJh zg4Xhk?o3#c%_ART#_i=|-|#Kz9Dp{t7Cmn^5}!*nB`x;R+v~q(*)}Y~Y?UPtN(Zs9 zkxPf}vHUqP8i~0Wv}N`I=F{H!S%sDm(U^{SQyqVo_Cz#T{ud@xgRzI}R>9_PTJnuF z%K*KtZpCVr>%K23jkBJ{OSq|it~lsoEc&MnLbZ3w9pge*&f>9evN_^Q#!UV%A3T=I zy>dO1uuTN0m%eBxCbGUnoCCru1*S|{tyaKdi-2XvToiZ0On(FZrMHUosOoJP$Yy~K zRYAlDiv_q55@fYMQS9*HuUr`a#4YQe->!mNpvVj8Wio(^V{l9Qmrdr>P|IAM()8xV z*X^0d346c-=50ivKIv>D#r>0>H{1#|Ef1G-0u@N7H=dpQU+&Mg(g`qpthm4V%;!naS7xuK&``(f6_&Iq$u;fKRb!CA}e0rgin>k49-@+lQ6 z8btFOQn&z=%}|9bfRvvW>Xv3=9_(_Iv1$rYC`=)S`&GoAu&j6#GUVduTtpRWP?#)V zIgG2VUs#Z00zoUIv^bsp>gmdZQflZa$&2J{U4d+q$6wug*4U))Ldb_jc6Y1X5nSQU zBmDaV`Jq)0dCyBZhe|FpO}fG}WKL9tP_o&>r-SN>zxymnc650!xjDTep1AB$iV~}# zrGqxPm#<_39oB?b9$@yoRTjU{7Rnj2`%qEsEEK1(POX zL>&+lG*Zb0!Ew4ASJ~qAJ|gVk@_ivULuao(<;c4x)=9(`cr|3N?sDniU`yt{x%1jV z3ss3aNo|V`gnil`fWjj;|uMln@mQp1(`v- z$pV828mP*2M^VhNGlE^d*}(A;FYjwVC5f4wAA>&Y6G3HP+M{XV$&&ZrH?bfZx3dXf zXW_ZD@9=0#1CAisO6|qOp2hebhFf|j4wvT>F3CVu+fdxDF`EBu)sSZX?opkgS)i2 zLuqk`;98(9?ykYzo#I}!XmEFTcXx`rySvND_n*t$B+p*id#^d?7~@^%L?N@Ogf6I4 zykk`6N>8p{Y_Bqv<~3b}KhZ79KpD<5--X)yK8xv4{xPmCI`?4L5lDW^ zP#FQ_#aeg#gQ7D`81bWl-0fnQxG+!QI*A#8U_tD7ffZz}OUF`>r_O(amM3&Bk>0p22&)Un#bxo zN51BU$RQcGO(4YGSCsm=aocyg5{sB zzas`Ny6EtNhn3F^3pg2>`KCXP;26sNdT!C=DCuc}+Twkx} zg3YhxDz|J(E?`Mv6nfV!A)if#PzDS^6&dSS{UlI(D8J?T&PpMV*kYSRh|V2vY61)l zAz^>9X35u$R3PSPR%|3PkAHt<0;5!RRDHqmH$x44W9?56DZZfu80kJs@#mTUV1CJTwfxhpSr9+zzx@bYjHHQ?Lw0E3hPrG5yEOzShZ0I6ydM4zdD$rQFGddFRIgJ659@Tw;V1W87p4 zXP7mq4s2;OPYPnQJ?P+zWUQ{gdgdU&5V|HT77kU;OIdWit1q4XUh(MQLL^P8uTX znA8;O9HsS|+koUJukV0?k|fMyb{CELyb9`dJ?YRE@5rrAS*fRw*K;AwgP#MK>o_NV zL6SZ+r?Nk;64`>}W+}_x4;gC^JJWWE5*y4a?*er#50XY@nQw0{c!8^ArrKx3>W5AE@a%*7O<@R#exd+G zKsGHdYjJcDtpcU8e#`4ysYF!;v_Vb@OQxo7gcP+6&-3QNCt=Pv$i5YyKKvXsnSsrG z^Ekn*hlA{0Y60u!J3hrUn#>RQo*ThED#?E0jNkIYDctj#NY9uFCAC=|2a`}`V)1?K zBtjI{wtF5As|fNO|Dyg_xOjc=gmlHyr$ORUBUoMcFN9-dC>kSy?v(Z-TK}G{=p-@> zhNmIrPNKqeoxqBz-b6RmRwwJQa$<_&a zCSIR|EZH5Z!Z2n~#2QHnhB4}JSCH1c(PW!3n*tF$q)E7*{dh|7;ePLA54xNyZ5^yQ zKbL(H()$*ZM=XMmX?tYKaO0FP!f>`uS6UqWcFw;ptok=<@`&c*E1nO?V~Vs z=VaHRwOATC79)$nads#CP-2+(j%`y`DFjTEi2{h z^TsK(;0|%(Lx$^K)I5Rxu)5Ni6G0@S(9G=FU6o=Sa%%Uy=#;-oi?-~}a#$xuraFEKBxd`-%SG$xHX~W^yAT{lo2nof_g#hJ?2CT(Q{i8K1}BH;5m(skPY6*lCPx&- zTY~#$k~hS2si%*Tp*r#vAKQ4xItn!m#6wB0J~w^8z*i;WEz)XmR>~cA|CTJF76uh) zOP4ITyoM+ zS#1;1QWcPqFdmAoJDTkwB_bFoXsky*=pE;!U*?f%J(^PWZV+c|qOh*J3mLesFuyr8 zK$@V-@99Q`5aHuXB4z(48)0<>d^OQQ?lQRZk1atw;4jNi3+@R*W1K)fANH@f>Ztr* z2pwMTe>T7!a_V_MD!c3-r~9}Ml76rfe4I;Zy&l9rq@q3cjrnx`6O8>$^VSIeQfHLT z`TofOq{=8Ek*qU1CmpFV|Fu)JWlW0>&WJ@pZ<~?-E%m2RRT8Ujq&e-LDaba_PAXYj zX#U_iANi7#Ql2NCyquzBD=`9s@2bNw}{^Nytm#1g2bb)b-5A~+)CcHZ#Q<^KF}dm>re zukDT51}|XPjP=nEV8y=ky_@KBS;Gye%gUg_!w`))W=9L~3MxxA`%YObAU&H@;d2FZ z0x=Racd!%p82GmjdX6qZouJBnB1rseCr(^roSTxLU6^a{F@#(MlCn$0?JE0P;E8a3tj>V=4KA0Xj-UrP0j)g?u!D5dApbh%cx&N-qMccm#Fz5d=^)f~|F+3+ zMX=;-zeI|6@=6c6wHs^TqNewtHI5gU|5z!H4s zl^);K;W?Z)@u+o-dqyvKV*^ZPE81;1K3E3G!~t`RfneIK4FJtQiDF(<2dVH!sjjI0 z^T4FL_T?3gQys6Vk-GaNVtQZoB?5=%vy#79Cz?wr zop`R5X)TpuK!Pq|0{ z7;zv;)oVflS!;K}f6SD+dOsaI?To59UXopa<1=O7M*hse>O6&-{1et5&5M_z)0mU> zD%nBKi`e=*yVgtszdU`rSmlQ1R4I&RrO=Sr+8*7i#a|cbII2Jl#AnPOk_R1nML}Sep>na)KhX-AE2zv>>{NrQR5{|qF3I#Df?~&20^XokUAJTBea8ttU`77`W?8-~*nbJu z7%@iSm|Jl}?felIpAXW!to145iCatGvNE^tMebwbV(AJVl~H%K$FfWwnt$ehs4Fkq zo2g=5Kqq<^^Q$EyG$;7fl<`&s%2DZf-efTD%=!V5pgRBahN$O_rk#85_vv0sgke9G zrIpcS!3$7Vt7CnS-?tGwD;$WpQ+rBGdSHCbq7!nsNu&F)A56fVYj=qG?&#Ab7+Wd4eF@!q;KFacmQ*xaa17~UXf1Q;&>ts_S@lxp~Of^OS>@8eEg#dex09 zWZAO)Wl{gW8xWL~#4STNDvme$++L3kazi?dN;2U^M=&x;9S$N}_4rK8@GndXSVa$k z(#A~_^M!%iHFhjEP}t+tzx2L;U&~P@6h**vX>4fv|C4ktE-5Wq#zwOI>-E{XlEeTN z%vp2Jv!Y9|yT++1@btoT_@fu%rO|Mgcqm@NPrM{m|&z=F_5kO`ohq(4Frof(HF&JTfCs|RwRK|OIM8a5M;g49la$wv*%AbEl zKz~M!90APLm9N&nk|iRKV2aVzd&U|D{fN~_w6N`zG(Kk?Cp1z-u+9u>ix$T3z0}pC zh>;X30t*E9s(@QL0yJ*^K_g8#*gZliG5hy{)dS^u`$xZi4_gr^?cI`lOcmQm@NWW< zK#2vkF7AJ{>B>iLSR}CI?Nq&x0f9+-G#@f`U&)yO!M>kz$Fhm|^|!17*x-jsc(G6- z;;h1oSh&Ol3 zQ~7D8e$KCX$s{B&rATH|Go@FC>e$T?iD)s|v7C0BKjZ$bzR3DhR~}|Q^uOGMov)X_ z%o8gB$E1d_1CK%7n6fMiAiB;b%HQ>)S zhE*0CkzNuruNcqyzmDtsON=FA_N3o(hd*heTmG^3iAeWcR&5k~>%;Nzjjpnyh0~u& z$%j$y{0X#@GCVSfg+zCaTh2fA)DU$w_cQ z%yA6kg7B|9fu3C7xzYF*g_1nYA{JVuo9a;$hgoJ;LgV52dvmdiUhIWbevCE5r&R)} zM^)(RiX(KSXL)J+0nycDDrFtj@}mCr8G3UAtvKbiQi zrvot1lLY@fi8I0^Y}1g0T)~O|GgZ2T9EC$cvXv`PcAxZpUJ}c z?B_fhM?8<)TC@#ixluO2PDZtR$*p`>X=Xc~a#fR$uj|Ddk@1;cSjq+^bF(ZSQ?*2d z$d}PKQ1sgvuK`OulyF0_A!5pXfZz96^-7sXcOx>%uz+dLfR;eTA-YDv!J`+mv z`Axc|fvtGZo7A}AH{#qj?5MHaxMNWw?{F$5M-u&Tn2-U#(7>2f0;Kz7cw0%_?LB+h z+R(>+kA9ZBud)oBWGf)%Y_?PD6M(faR>&VRF^_jQ)wjS;5s+Hp4SVgOa{EqRrj%Gi zmyl3uM*n12S^BKKW=ZH@EseY+Lh=A)XAv?pHmOWK9+hD zQbx*U*>2F2D9%8r652`rW(no?(DCH;`KRVIlcPr87Q-mj;d9IlthYYnyjT^T*8@L{6d3?Re#U^hkrJGQpzXb zRE^jizQ*TW7}xB?tlI!hl;KH*Q7x<$N(`s%9*P0K7+(A2H0x)rlU{z#Bf4VHxtVaB zQ`)Jt31aDNjwBQpPH}}#$a)gKhiro6JgreG?*N@);)wMgX44)o`7@L8h|~vfOMsd8 zj^@S-)&s(}whTST&9kvR8TN+*m3(hYH}HHP$^-GF+Zw^{*I`Q+0gO>8T-T?8>df?p zPDrz0rpM|{t5gxdbZ5DGh}R#1Aj+)rNd3c5(EHNeQ9YHfZpmn`YJe+#qzcZgm|R=j zokAZ|x8x_P@5_Y=3wi2nHFJcsgpi_Ne`n`5WN0;Bm!LycNwHgWD5P&$^@n@kG5mmR zf<7!{!53Q{EtNb?S!Jri0J3L`0a)(%ze6qMML|MeO5x2V25ujt2!ZF#g~dBS2a**} zNyNY=n>}8w;V<&^`_gQGeBAKYkW(hunh1kY3%;(gVWu*xoAUTVtD`7h>5PH+GGSt5 zj+@wdM7qG@!S*yNR^A7+Lk{tx1?73rd`n%wJWCYI(sRDwhh!sI+`)}7#JV-XnG;At?AT@y>ToW-7}d&j?(B7PD`S^ z;_W|6;i=;AVMJvlH#o!q2p+=_2&(2#LLHq`W*(VsIp^_H6bgk;xrn9E3h6Kr4WSqU z6cLo2bZ`!igb9##>2OMrS@gaT6 z!x2Rrl#V+@1`+uhoAtCH30{SukKmIVg368sp$CRtiJ^-O7P_Mq4_DS*#Z2YAw^3ml zo=L=u@7Ct;`@#GEIGO<@Z7;WHWG?GZgP_i>w7DvbKnln_V;)v_%yjQ0#rG7&aE7#Q zSY|d+5SPtNN>C4?q=^ddqJME{LB7_<`XP<+Mcy*&9b_4Th@Y2GN{9{(BKI{kT4pnu zW`p9vjga8=Vaae#$(9JYN~2v*`PTKL~P5TG0o2I4K=2B`4a$)nY` zztwe!Xl1WwTWt33fLv)SV!n|6>T@a)W=uUQ2$7IOt*smN?)6Hwn!;=-()WU=e_QY8 zy<8SF^{;U-pU&xk#BCb>tS@{Y--Dh@u^p0k$v5j|?-sGy%tfEGnrD__ICS*>nwB`j`9WWI;pl zg7;KEW;ut;}+YEtd9=oOi(1Riys81 z#-OH@1kJt-8{2YL77(66nvx0L*X!>MjOhPCKb(OC2bOwy3Y|7x&lJ>U7_!!)POp*E9v&<%$j<$wu9ZN zZ)U-3j4qXj3qq&tm?DrTokHslwC&`}0^e0}5?U=h(1UN8GmkE&kigP*!IN6Z{(w~p zUvqU3)yyd%uI!5QZmj+kx^DwyKSr&Hj zXYEcdN_G}9PpSC$0c{=SZ6LV~C;P96XZ>B6du>Z=TipHf^gp3(9W;TPps?rT9He2fZrY27+0|M+%GW>YbUWnC; zev+ZhJ!tsJ6WqKg^wrhnU2`5~dmyQ2>6B%em?u8ot5BJf1j^8#a^8^G?xL9udZuS|nL_~TZvYfro@Zz_YhEKX-I>gNVLe@DP)WU$deI1xHPBW{ z#l6rg<`>C3qDhj~AJ-1|W=0;gCI2+WqrEegBCG#fsJXhdODfMPl4D$lT7 zv?ji8w(_&6hVHvojV2_H;OFSFQXOZfn9^5v*bI~D4x}qik?Yd_{`b2@W6+g1LN=pE z$m%49c6@p^r>nT{WUv04Bc3sUN8Cliczi&@v&Ol8z$A011pO+65?JMjKq z`@zeo9Q;06)n>1xj8q;~?YZbx@C-YTVVYYel z);td%;k8*+RAoSWpm}8HafHSo<%&{oNxnYAC6z7tm(pVh?Y2kDCIe!ijxzHP#@4RI z`FBp0G{Y&?_`h!A<@KUb6WK6Ps+E5dvR0+h@A@7?;vSa)7GS7{{Cbf^RQ;PD7!5az z`V4v~7CHAPoc6rjqedZITEXQd>WlEy4F(TS$TJ-D^}K})!U(`{z1RRdcJ)Ma)7lhA zC``^?JZQ5Uc8=~vOEeZc9s4;cp@QKIcLH8jAL+>S{hB{d#OP|&+UAi_`0=ZJW@-{s zx@3mpXTAxY#^`}LxH!K7s>rW$@1)oR&!z>#5ytA@ajm>;Y+tj6sWLTw%93qgwb~}V zSLGCpj@2ghunnteLFM>}s!iwh(Ob4Ad-YHOT*WE}c&(vp&#r}~Mr8>&5|3Jz!H4de82~zFv>p$D+ z$lJiiD}%U!IAbg%Ev7#hp|s_(oQuk7luCxu{GU}V8SRt1urVu(*z!crS8wh3Da|N1 zDT9h}d#3LCMked^BedAItTIS_Gr1+nn62o(O}!}eUzF#^C#u|yzb7@B=^+!sfAs*C zH6AS|u`eajf3g;9EUnRs6m)4Ch^pbQrP+o)R%`>At=rS?k%y0j$Yk5X0g5zLEcGh# zT7xZOyNZ5l8Qpr|-RRPa8mp=hX2-Lc%NC!{S%59(vr(ps(dSxo8X0DOJ;a`C_hzcc zT2ZsW)fs=*kemnz5eJn!9Dtxm0w0lNJqsySFLpfb>JS`OhZQ_!C|5#B_gyLVTN51~ z`?ORtBxtMSDFpidq!Ki4*H+T&p8J%gU^4hr`rC84!#S7ifIO2GO%~|#<3$TYM^QMw zx+O^b);fdM)jxKL?B$YRkWrHCFg}~=%*w|=MVJja)-A?uV0XDB@F;?ug^)lJh~dt~ zR1xvtxd!ijIbzU>HIr-8c>i%}^W$#=nCVB_|HH&PLug$HlEaEX;@dHe+&In;ow4bB zRL3#Kw+0Ab6sq^gZVX^5{l>R;G0IRIpA(E6I(k})y;xhtkKFP-8rcxiQpfvY+rHRJ zuM8Bt+g4I)Ep-g?`Y`W^LEyp0F2F9fT2vEJZ)_LH6`E1Ri8fUFnp39_zH-YCHL0Qx zr>by9PBLIUYq-Dtcb|LT8{$ep8WO}Lg7^r>u zwXKcBe07YeXXIfec&odXzu(8&k$DkCXD=C)FSJC8Dpwa3slI6>ZBtIT#4yJVbf7rj zmMg-m^;6+eY36fv4I!P&~y=pd`B zOtc{?Kq|2a;$mgzSvtwftmb-?M3DJErrYt5yA1M1Ho&a08Ona;OtK6DAIhjH?>k@o;!z2F4 zkI?TjE+6x7RY*OUK&x9acJC2g=Me#I@4UC-z3-xSB2N*l35`!e_BiAF$^6SU=|C|=oaBYN`o`q%X19vlKQC>8_A+lwF#;w zpe6N$U>XCS5F$~=5D7OeZk4gRI8?-l$iM#*ujK9ohyqopjtHt>9Ar$6?#0Bp%)^xY zW#^$YB+o^?Oy&sZxtn>vPjNnt!S``GD+}{o5}{zv#yMe%7Htz`$(8DtU1t+6Aj7<` z^E2c26nNSx^lB7~4nRB$J&nL!X$uG#%x^Y5I)Q)zkO2l3T>7;#3suYDoPfr@ZLoaK>0pG8@$}U~{jb z^f3QNhTh&XW^z{1>3IFHpDe`!?0>+V>tg=|+d0KlmW$&tvx17~hD^-^`3Eat+zUqu zj%jt}I;1L8Jr&ap4Zw}l=`QIHd@d>|>`xSs3@RtN;Ym3HiwRHME*|GCI!+*{xlF_7 zqS=s4&snnyb@}%m0TxX2O7yi?^`$lM=xe`&A1n6IcrU!pjp+)& zCAca;q6GsuR@U71rdydj2#y(v?D>K|WG>Du^(J|eJRkDqoV`^dQ$hg!<&_cJY^6DV z%j>6U#yNd6LZ4WqA1nM2=jQTUEooN;COSbD@MOz6zyyGTbWAYX_k~4FJd)pa*@$#2 z89d9eW~c=hwaDMLI8a7?e}-7FOIkfPQxF!25djjuch>KMB8KT<@3V}vlIjBxbiKaz zno~uIc3DDh$QPLrqfDzLYs}n-m27cY%FnK_EIe#O`_Nv3vU2#Mevky|{-xH$E;6Xu zc2RnoHeMgGmV*i2AI)mIgYMHzDP?HM?~7Wn&9e>K0@U~%f4PvJPst+O0F!W{2yZRw zd%>gu)F}*TYye#fQEC3d6R(FMGAug_hRjnkY$HphCB-KktpCaxxZ|1Dvg(bJ5F~EW@k;swMgZbr}{! zfsQN^o{hodDq;$D6dH+Kn-Mcu-BumyOkCFVJ*^G-nnqOf%a;_Oy6vUWuwFLJ zl$24%xfTwBA1m|_n{c*Wu=gP1rY|PvLlVDA>Tu7D$9dFfVv&g=+b#TlXLgY<(2o@?&sr(5R!JKE1rfb%D z!{n&f=9vV7zH%gEJvorL!>&rOTxo>ShYny@QaOb&WQfVu5B6Wc>&m7`oBbN;R%wFH z3^YuR)PWjEw1TNu)%SqX5M>x4JoGjn8pvHrM_#$0k$LBcTR%bN7R3r+*W&nL8Ev5N zRoz%$w%|avq0TJpSh=^K(VgHlIgS@*!3(z%Vq_SzooQW?_s4~rcw#b2gNhG;Q&Ag_ z3f<%TGFuG#aS1_SYj|+ST}qdXunA}c-WRdi@En{JXjP74`VaS*oP#nI7@~gP#n+B4*x3*D8-(sGZJk-tFCBp`CNpj_s+fOh#x-U@9( zV(XgwYy8l+`m#|qK2z=Az+fX&n4bI{$fWi96MLk}yab}O5U`mI9CQKH3;ihy%+wJ1 zXy0Hh)K?zrPjBV6|9YoR!de!n3Ch#2KkxrR%@fs^ODN35cR@=G6B!=HIIW5||H$pa z)97-;JBs|XH?f1)J5MLHU}bh zR32aS1)SNq?-YHRM%W65<}z6G=+Ifrl9&B8zS!jU;7{2)tq?Bzrg3;I#+#1<^f3dG zNPBXk@0x4p$BNO;Eb!B`S_&f!ydr1ED1{lK@n1rDYp%*_bbh7<_;YJ7{lxd)H29>< zS|!)F;y#RSs7F5P8Vm6$d*(wve{iRzQA?xt#NriVhf&hV3l zNOo=1LwjfjO10!oLG)_^Maej}&z#z=6T6udPG}yHI^Cw}Z|Fu|;V{G<_rSWvs#H3% z_~R!Azq*JDsyq^qzz5Np@iwg-B7_?HWAra|pi(giC-AMD%LRz4!$<6eM>m7b6)eLo z`f(`_U0?PGyhUm&6gm0qy&5*hby6C)63}2(f{)V_#G*j0G=N!eCO;$tl*C#MIo9Na zn2@@mDEOrqBut_#7LA7$Z7oBv8jo0BdnF1up|I_3xx{lb8{2i0zUs-XDqS--inRV~ z-p!ZB?=Mw}4BeA1aj9iA|AV~KFC=~JwjS&fw3_xt_cj#u5VRBslkW>f$IXS<3Tq}p z{b#}g-#s#o0=e@C^tX)6Jho1$b@Kb+99E+#0;}Bf{kydBnKQ!r@tH^un9sk3{m$m^ z?e)ueE2ouZE`?P^2%t@=_YeY^VY?_Oh(DbBVN~m$#!7-g^IysdC;AykzH3ttF?)fb z>tksQ$n@-(!vs>^C9n@!y$vP@{>(}hZ_TRu*0|?{N0C9q7nrwxR`?r}^b{7GVnf&% zm4Hh&K6SHvSb|elfa<(X^FcL153S5J1x%gQq#26^cYv`}HI=pq6@fqkaO2YibuaFD zjZM~xmOc6~{~9TavxpXNZ{7x!?B+mtATb z`I2tn3ECe$YK)qS*rnJNBRq2Q5QW|u*KMY;WAHc=eFjN28HFX1J!IQ+Fe z)&ieTcHc0Ow9aQSS71KvIKfT89-^oW0z(g~3*3An85B~BRA8j@4@1l#$b_Z1>iW-R zhB@K5dgyJuj?RwLS;x6+z&^TKY&2e%!y29?|Gc{9;sh)ppRW@A*4qgSf_g2ebPFW= zvZfx>7Ww5R|Au&0~j>^8UG=RV#IXS3`CL=i@UX(wfo^TJOjJ=J45{)^j$l*z*Ajr z%qf`?GYKV@8-`ebgxV}zoa^F<4WatnH_(l0p2p$`n+MhwX^I9k6Z$!kvaHxRE2I(@@IcM4jv5qm9K_Xy3 zj7rRy@qonCOuphI=~EcY)f$9*WD{eG@_YZ#R0qAG*Qe$0I?GxyNjaS*~;G87l zIKU$D_Ne%!W4)L`tI7#<`KyERe+c6%%e=FZAuIb5XonC12{2I!(^~?Gzx=XvqqNJi z6<1F&HakRSFSo0-D%dwSbBOL*@%EDze?Dm+h(<7QJy55z$bl)NSo$f6KdHIk3{!(N zLdOzJoF;Rix)4Nw!vfpIKJKn;as>`}KR1;kj2;FNf%2&Rl|>#D{` z>gzSGnX*0q1AgB^57qE*Col|28q8R#dY8SwH;B>j*?3uROc0)+M{rl_H;q~1WCw7< z;LikyP2&u)#T)yuVNWoHAh+=D5kYt1ua747!x#*<3K!YH{-m~ z1gFX&$X`-no`n`hW#ld%4Kq2#}45 z$O&p(o2f>sjNN+x_^6Lgy>C5T6E!09Xm}u`z_qEwuD5DqxcOTZN9o*N z+`M1Sq-lA2pu_`GHKEzyaRyWwpvJB9e|Zk@*xO*E6UEpmCe?M{R9UbRr+*{ieK8Y< z7%x_>)5d6GqECtTt#{~MPjhOa#-=a4=%>-Y|AE9_0;}Y=(xH~^Y^T1-O#QM@Gfp$u zwpALckyNEM4mF5E(^U~LA-oG$>0+XLoV{r0KQ9%~eP10w7Yc0FWPtmJdw(5?WQZDLEzjx41D__d0H)Xqhp)=>Pu_al8!Wnz{g}3mZsfKT z7nn$W?O~!aPbWO5UTX*;ME{%@L}s~V;kIaEUi;<#6q@G|A=a3Bpi{#jawk;u5qdc9 zGWnIjJy@s~^_PwhtI~70^FdG7VqR449UV$cw!A9T6ufC>uZzsDs-z>*NB}%IhvX-(I(w2k+k0%<1ruYHKhhf?J-H#K1l+lM zs*1jeBxJLDeg5_ep~1ZlUM2Ueaw_qoCT*4nbcY88+57tq#YgmX6#EN~xCe9p?g$90 z;atPO?h0L9E|hzl2+!4C4*|A{XiYAt1ibl*{xBDvXc!Vi>subRex6wvRgI z<&Ggg7t%gT7rHyq!%wmdPvS&Ht9$He+xZs7DpYa60p)$sd=Pa-ru0oL=G|b~OphdD zSYH1W(P*ebl1b{XNuL$6v(7qfu`3P0wIML=;{z^MU3#{CCPJv+I}5J`yi* z9zt$#0D?Ijrxf*A0UWfw_Kj#y$KIP4vx;_M{(t#j2nsHV-Rq6%(r>59-DIQPRD*WW zzcCT!g255L(boW~#{I{6!yJVR8mkK>=tgL+c$?#V|moB)d6iG=pJBZ?DIl-Pd1x2KKk0vb5{Z0 z`gMR=!S*lOPjrTeF*;eqo@53q&gom>uvM~i9BbH-XauAyk0ar6#2bHwK3;XW9x14h z8z*qz4SnLAf~Uc(ok{&#Xjt)tQR!N|ff^}(4;77Nlt0cC$~4r8_#QZnWU4P(Osx5e zW_14~IgdcK#WDH{eUyRs!k6BUjPr}LZ|djqq)`0EpNc5VS@MC0q0R%e2Q$jvp4iS+ zuLJ^%#A)HYJ`0|&#%}aUNL|(_QYVynJP`{|GwDnY;sXUdm^r!n405BXkfZkL{i!4e4lqey>l z^B(h~+Vz^AS=zzN=iR{L!Pq-A%!*QnipqZQxMWMYaope3;`Ad~xx;k=dKH4!e1f&s z_}#yqPrPQo-KW|Cc;6yG-x7GAbZi^>*~;$37qMb7KsI2OY46XGL|zM)6abhJeV*vf zvTQ>5v55>3S|{?tKkXd{4!k(msSfIOwDd;X4+!I8X+rHvQFXF7H5Se(_db4;>JZUv zk@($&B<@yQ*R-9|?u~d;w?+E0zKIzh8=D2mGxAt+$)#~uC!P4(kM;^-hw(BgN0x6U zrf0VjP5UJ`Bkk-leNV>*2bYsmm>lov3uvX~S`hg^@RbcKlOPxz&n6aR`y<4M{LMD5}(Lg5vqa6B&7!?Op=b-g*xGDPd+%(SoO z>!(j%i4@DmNQV0WLxNp={MP5lohSts@={&95~5u*IVHsbe>7=U!0Ky2>tS7cf^5UA()XfVeaQ*u%2Xi5sz@wW(y6)Mh?&ppyQK1{JeuJhpR2F?t5 zCN&Ehl0oFXeXUv(xD(i;CEEd5{Q%^7)Q&r5F`-VEm)ur^^7sAG%$1=DZLhPxo_%ii z`|}|_+!>4wT2^b0@d!d3Kw_KWSjQMustW_S^vEny(s0MzFco{q+1lyUa#4;!my_Q2 z#fHQ^+uwYgS-A;n8T@9X+1lCW87*t}^6u3J!e*=Ml#z2{z2Y61F6;Nl63@v>AdK)T zsGf0SE7PZH*Fij2PDkq%%jh0DFPWb^8P~0KYCRESZ8qhAs$Yzj}pqY3aXM<-^@G1nDM@d&FjX^uUNj z{pU;37G#XJ4QJlZCKX;YZ-pA;K91RQiXF3huv}mhWT~_;9QPz{at`yzE`)z`Un!%5 z5WT(m16{i72LEFJV%hgJ#ry8x@cys={+*@9W#`kB;*%wc9%YhtpHsEG@)(K&%OUCH zA2rpjJsV~o4HIja|7P#8&(krEbD~UN-VGbPRw!3m+r+7vg?`iV(c^|x`jhRn=V43i{u0rdxY*=QN z@jUbaDV%Wst27Q({6;;Gq7ASZRE=OdE%68@ONg7hD7J;Mnc zK}hO=36jZt2(td9&GQD?NJnfG-?*Z^g{40iv}=fK(=L<}2D7kjkTcG}VxbvuO>GA> zd>%Pic%vzT+ajUpQ!8A-7_vvb`k zLW%k}9bcSMe<1Ro&9^zJ)0}ig_&G`*(siFeZNvaLi}le0Q#{tRKiQ)iN(=VRRVovi2gH|6K%Z-FYKLHJ6j z`p7=jHeG47%ZRmQ!-wpuX=8J?tL2W!cU@xvu?E&t5j3yGd1sCZ(J@u^I-+VqL%h^V zo>@uk8p>6}*w%iRHN<;fXWPu)TTdsi_;J13zhUY;6ni_6_#H5&9aQ@uF11_8+d>>d zULqnQ@`OadKJGeSF$^o%f{rXiRntaABvn%@AQ=#wAHfl-!NxM`#%+Q2h@JMRb4A)E zMoPmaNvWTA^0J|eR5IBd$ru%m5p#VFi}mOF%2~HsAx8;xy1h%L$KFp)uBD%~lDR4p zoP>)i_PWEF^90}vOUh3rKFkNY>0Qyk5~V^SXaq1#vQiR>1l71_MuFA&GFI=~=TFzZ z_AhW#sU?QkC(j_nc$o`+IRBc#Pxvr;LV!jU7JJ{zG5z+xOx`JaJGY*bdOVXa`$3)H z^>k}_6I39oJAT7KMmS-x_NScS7xZaO-2w-mBl$!&MoGvEVPL>bz!4DzuB|cfa(Y!N z-NSMr{%07|5M1)Vk*a|vjSH#>tpj*)u}s17qLdKC@&mplYYG>QQa*rM54mxmGEwZ7 zURpmE>@LI1m^)Ciy>PLMT%L1$!z)mu3Q^g z+|^bzkl~)-Zc*PuI#KYi70&N=9OABYEOAu9Mj1>u+mPt5Y?s@!+D#;psv=q~;@fwG zty>HAHH`K-JA<3q6j_Ux3R?J0f?J-SkXsIA8}J{;?Gd5#>SE!^3khI*_$4S+zBZ+Z z9A2w|*D=(EvMX{Dsa!v?8e2fjd*+G4~NHZj&-nTQGN=^h{QL z-^8UeTvaYIyl~TwVDbm|=%n*LBT5=!wPMT5HrcZYrY z{{DNj7kjgN6GA@EGiT<^%&|H1J@@+9vms0-fDWKRKVq_b@puE9Th}6fcb|OL;H zW>L|nOzc50AWPr(@7XD7%T=_JLb~;!V55zU__BKb4|sz32OTYb1cTBhB?WG~^(m^S zmNSBc0>2aPO1U96+_rT(a_}EIZ8jx<+X}kx!3nUP7WyjF`KH|R_yj*!i&OJtRr7f5 zE~KDPd1Dv-;THC={-a@n7(d|C&cp1tzm7SK&m40^ua-Q%n)ROoa3OK#$)jRci4s%#N^_^(0&=XuR0SWy zfxO4CBh)2dMgR0;sA|mSr9$}UI9z-G`GY#UfRG=*syTQ@G;VLGXVIu1N!fg4UKd8C+$OO7Dy-o`tLG5`1vi-x{$lkGeI$M-VIv#N&z8DpMG(1~zY$b)I zTk8)EfmhJ0%$GQ;ikelj3WCkM(3XOx_9wY2fq{N^<0%y|i9V?Zn2dqVO7%dx_by~$oTOl-RQGXHjM~+7if9c)UzvMDqC+XcMsfR(-0%5|nn1Ks?(kgTey6;lMSxC>jN)pR7Cn=?bn_r4@rAH)sI;B|KR>^&Wx%dzA9u&RdQ0)Xge8b@Zofbv=$P@wwAqaO4 zaRS9#E5*OpC^VimuU;#hB;TR5ifDcKZqI{UD@P)wQ7^syW>aWgz8*+>irlw5`QIH= z!#=5RuLV9{E~R?xsj{i>sf|{yH}BdtswZ1F)?f&)iwI;nZm23~roZ3cXp`?4&&IsE zhFuqG_)eY#6>OFONO=Y&g+DctbS(^1lG`w#{f(Aw0u#`gKEbhKlZoXRL*GfdoY2q z+1RAcxyk%}F6@5mSaq&JEMNsd<~?iGPkcswL(i1)!nNj4(m>yG)1meBLr^72jY(4o zmzMkTJ&B3Wj&%{qHsaw1LDx2^V1(lG4`?Hn|^WC3tQxf z^wxRAf+x8ni+kGiH7OEuAW#yatz5^uTq%A3JRrBMBGJxEgKn6xpd^hyuH0iD?OeLP z{h4`glU`)E{ZsjjZ#5NCv=Dfsba~j#eFt967%z1l*cbu57sQdJ%*sO;cH9x2N0V_Mg4oj#uT>zmvb&dW?C|3fzIuWxyS`rSJCuK zndTxiVX~5-tlML;Owj3?Nm}ILX%4c(xlCBCG(tg*<+nzIUv*6P5;Zzmxsp`RXQ5$2 zN`FwWAO8hGJA2t3U4%j}L** zg^V@&jZsPkFK>#13EnG9;<_j$i`EL_{4Q1k2=&~e8c$iX zK5nbxY*XH33cWY>Ro`f_7WD~*WM*4LY{A;89+V7j&CUWvq1 z@%d_ORLuF~A+~0Z0*V~6=hXA)r3={DDcPmhA7h4*toX++7$>}9aI~^k)m!^mU!O|u zUWax$X(WcQk^>Wx;N1G9L9f%D-LUaJw^}Q4HHL9*BD|(*)cLHgZDmE?=rYlf5??51 z^)~4XdJEUs4)y&X<~9Vn{x_Z7xZRr}6Kd4Eb@%q;4h2&Fz_;{kpTAe~N$VCz!@cmU zpfWXM%7#PR(}*}0LQ4MNbg`QCfTu~4aDv}*3>o`hbEI09wA=O2=3NM*f~3SVk<_=I z2Z~C9PB|h+ijX(8lg{~&oRxYfy6BKepI>-Ox0V34t>A#gnNh1*cq=a?+N9xIrU+NC_o}$>(BfPsX(l&7bE# zt@j@6q0$t|(5oL5K(5w4BITRMd637{*Y1p}DZAhCnmhy${1a>UCaJhs5b{^u#%LuI zEe-(T@uMc3_{hHU=>y#4r{;hpbyx7s(j2Y2RYWsB?`9DR2gr%Yjv4t`a))Zlg1mD= zlnY0yR}h#MM4n_Xw~y~Hpq@w zb?Nw}j7dpn&K40Mowmm74{tJ`*U+q~A0|3P9Wz=8iv`G(_*^^Ljk=sK_KOcI-mmnt zSbqJ%(77u=p+}`YaHJkabG=De+45DP6z!J5uvzRCM#XzFBc89*vRK}tMg=8GDXEF^ zi%08}{xW}D@fARplg6$vf}>GYjtHy3E4YS_r_%lE2Zf8&X;5Xk%vFM{0MuAGrRo9A zrcHM&!N-eBTV9>No>Jpp7&=Vta5%`|W@+)rNM65Cb67|cc$nA0zwr7b z2sNeBo3_PZq9EVUhKJRPNt2^qshXyoM2Or&fl}bJvhB=R_`Y3FY1T$s;vZvbC}QE~ z<5Xgm|9n+jz`W-d(^5~+mYXB&z4K+~`CgVUbJtOA4!pUd0#&=_VYd|J7UnefW1Y*# z-dR)RHHJd4y<}^}WcEKSxZ+Lk?S`>4IeA#_|% zi{qSZ&sd`0sgM6{XPRbS=@5)eIT|i3-GZ|%w%;4PY9!?}aSnuGFz--Cgs|YZ*miD+ z++U(|z=Y>PM?2Jh;1a_!T>D~F4hU;L4y(VBeVf39w*sil<`tK*V11Y7`6^NMY?Wr8 zk(!gN|EWPs9uYw;H$zhKXe?AQsoFUN05~YS|4ir{5tIwEz@VQed{1D!vD)oK78q3< z+nW?SvZ*MiFeI>UJ$>FG3arSD6ca%)3k#XLqX3ANs+&9TbS!Y(xfX(s2`ichh)gw6tK{a(n3SW7{Fl7guH3)a}8%(_T=$ z$3+IET}`UZA$`R+NWv)Hje$7yzKx7MRe#|KHZW%~A}V?9 z^`3D24+4blmAu{H|BN;ITLyvlLP3tuyK)L^(wH+}>Ul9ge`juTThft2_}#wK)(%p_ zpV&Au#+i;j-R2z}n!EBdjO71bFNcAxPS57cPz_$~LJ8|G-4AG#1baw&U)t#_eJ_Mh zi=w7@$Jq9%LYk{Ko@n3iRR99jUP0$JI9*S2a(+skc`NpmPnJK$&lPi;K`)SP`W2c} zLr}`0h>7Fz-tWTC5Olir-)LG(cbojtR_yl|4Ue9ADnn*X-9gs61@H^z9iTUs1|G*r zI>wZ3Cj;*p{5CUURCXNNg|oTP9;*%Q2<3_NM`elQ%7(p&E}PRuic_*y^vmTI(`MU( zaya6{NYTCbnh4-y83~GVI{X^(y_80-^)vbNENs{0_DfTt)^h>v?#z;Ndj|Og`I+}S zR(hDT?*2UEe|t0a8q_sLuj$htZ=LoA44R`;MIH|xGhd#6JW5;gbGaD;P@h}p%~U(T z>)Htf@(6o=Pd;+1R67#l@4X4{5q{Ikl2GO;98-sruFql2IuOffj^Ozrky2IRxR*vY zj<}kzOnUzo4FDRON+s;%-Qw%}LdOcQkO$fmg{v#8!-seye8x zp>y}L_b!yQ)BAjH>26%nDfc(#bvH>&qGwY#4~CNh&%BlghXkRYYaTy0)m1YA1f3m~ zi=8aqJ){5JrR{-Zh{4=$qLJ1&HA?3)Kae!7d|MC%!3P&6f;n3x`MTEKti_~OlT;+w z2%NW3;BS|&C0t0AB?={fkCM_B2MM(%r#M8|n3u4or|ux@laJ5-`3m=62d=&@DxN*K z*D)p4`&jQlziU5OPy7A-CFyswpLXlRT~jl!UDy24CLx(lYCmP~RTWXbVGs0ek(mS7 zTgDB#E>fIE^2Mn$M%0300nb}J`+VEWOZ-9<1*@Bt$j#BTHvr-ZgYz7RZ0stF6~37E z-}f2&i?8Oa_|C_gpng8BAmFYk`8a#=`OKf2ZW5F9ogv9XlJoH9EHZ5P!8yCHMsK;e z=nMR;_LEWOw$wrz4fFs9Ey?P)6jl+lx1golYh+UZDYa96ltRV2S*Sp8&YEhoPl7nH zN|@G7@CHGKon>y$M*V}x3o$YAW|yr#_9fLDLFo=To9#X(0Vow~f-}iI`A>pH*Ob1+ z$u0kjI@rVcS28C3o^fD#*qBfc_zoC|8H>#<H`NBD>= zl&+c-K3&zAV_I`|qj*JA_F`t#>^8@|IJSk+reJ`J)h3*2&XM_c;z77?eK#^-{8`!E zQ%6#?!in$j&FK{!hP%8rOnEQwgRIfO$Am4w@$k%gJg$)WPIRKc!IomsO4D-QY)cme zuVa+_v%x6kcQX*0%dI2&Q`>#HW{8eO;ZklmHRl4RY|H_T96@-OmPZ+QF54>J#j$8D zXf-zn(u8Iu8Ys~jIa=EtAK{DkxLt=-lY>#v$Nr|~F2@ETa+Xi}1$U5SkXUDt@1Dw! z*B7bOk2h1UVh_FlXK{2~VArXO9WXLbB0iS-^R&i=T@7yFs_g8`J|5R=|3+IH4%e6< z?w8k?s5&Y?KH{CX&h5s2@ronLJ0;>N11sz*P21_sz=M z`F(TAT}Jxd2scK*r{U~#&SmeoW%BB6brz0(mD5;cSlt(nouL<3$0tE0_$$QU zioEtceac8GB1Y~vntjwg+064#CZgvGO7bJKZ^tG%#fOJxC8A{qEl;o)Hj>|xtNIK} zr2Ea~XQ4fXF3_u^^ve8}&!7120RQR%R29QfOXa(12DWMw^}Q|6CmNMAoHUG&7UyeJ zLe_v)pAo4Gzr1r@BQLU)BmPna(JN8s01Vka%5g-FTyIoD?_B^ z3(T=R+$V+chx*lE>I$ssx9C@vQMIxWuxoG5JJxze?r=GY-R7E5W;~3F?cu8TEZs~g zIx+gdiVV-!v@d1-c+$DLN?zfMT~7Vmjf;+tYJ5}KZv9?t?=JRy6(jTopCyfX!^uB7 z6-UJ&W>d~I>o_JG%Eci>HHLqUWQ87T{BD!b*v4a}c|TUzvc60$|L19lCTG68q*@N@Ivt#{5!$7Q)D7`?pO4xqp3&dujgKx{rK z8DB2b7<{xxD4(3;F%?NU<~Z&RpE`P}*W;iuX_QyG7M$Kh!(z#6ot8)c?E+34h_K!X z=#p>nhUT3pg$KA|>5`${f-Lg$avC%{;fUcvxbS@nEPZEx>`Sm;UM6e9w0P&YL^pY! zJ+Gm0QZ)NaX$V!}FLG)_p1j8D6Scb8Q8UVHvwK#pikdR#t1C}K1q$f?cdPy`Et?8x z$GQQZi@V;Rw=BGqCI%*;(N;do?gBFhEv6BIh=F$S_?>@uDZf^Qu26=`!%$tBSzERp zbhGxZMfLltzOCBLvowhT7F?Nc#=)Xr%l$~mt@CDwhuDbZ@Qp@dbTj%+kC4p|KXI>m zzx9doVM64jNGMHOISGs(jY@-d(Vb>5RqCP+w-Ho+*PelVjT?aD3fOoLbFll;L&+Ios$IDC@lO=cml*4ue zN<+%Q(OKvr+ha#?#G2oDHR!Xe1+utXUouo6nGGuA!fH~n=bB+zCGT^1!{@^i4;sfn z+uOlr?eAMBs#I^s0Ob(`@Ze#jBy(lUbeE>T`earGTy{wQKRp6R1=;Xa$zvrZpgpd zI%v%o-}$tme0i2$0FB`tPAIuhdO`rD1oobw`qT_rwf;LTuKB#wOrQoeAzN@-^<(`h zy)UlsK7V3>aSM(xLRX$rmkO;#V^oO6G;qQm*<16^3;7M8gYP@RgeTMFbi^{*$IFw9 zLDs3pi(7SH-b#1MGfV+;px0Iny@88;STC_2+*2 zO^_L_S8b@~EZb=m&3qu)xri9%JYUNaz9oVE*l_^F0!Ja-PfRpzKIi*Xf=NqZpy9*` z<*tMFV?)uz*(snRX}dTgT_H$CRv8&hqME_sy3>d`8SE6KQ1S^mEF?s_$OD8NU_8rDfg|m zqJ_Osg@cdg+~?J5zBf?Kx<;!yVWSK(8YfWnZUnIg?Y2@MU+sv?s4FS;HKR1l0h)Hs zQ!9+AoOF~+MPEihPvQ3=R^Dp?2oVuy-T!_Y>O;QnmdXLUI{`#oCC^&SVPQcY8cp3! zTiauaOs5(CvvU~er{k2n zf_a@3u5aMTX){=fq0P~LgUm7@@i&w)YG}bAYNHZaqDI_+WYW!O7fTcNfkU()%*a`bLCp$-hm> zTui7KQJZ|MDAQ+tFZJW@rfq_-4jgDxjrH3_iBObO=$XO0Ko#VM9W}OLkD$in&Zvuk z(Smf}7*&-~gdppd!|Okq(sKOrt!x`}j4T8u==Fu!`D&FsL<_wev%x{s81#Frf>3lF zV4frn$1g+u7?(BdrhDF(P*0t&8Di$raXh``kg-kx6knHV#32{4qOSk-Xpgw)9Va8ao zNQmd8cz992V-@~I=kTjDnLZg>8XF;6g~$ufDzL5$0nTSE|Bp#6^Ilr8i-S~8M@Z<+ zkDCFOibeI9LO3h6KD~X;W`!LJ^>+DW5ToAa&nYfZ^~k#$-Za(=u7V$HjDWqncsGe}{-tL#)KXaF{$gkpn5yL@9g~crNpM*) zDh#?I6j6+N+sF5Bp8SBEvZbpI+3P+xQ~our7>D}HC=T|F3I%eLRxa#<08~U`()nED z1oT$aVBRVUliX$StK}h?ua*<{dW$Y&Vm! z#wXvkK>qr*#iWbv&GdPftr9aKM)W$LMY+OpQ+QGZ3pvqg235*ei|q6F^QRJpFLaq7 zE9rFz?~49Z2RoyL?h)X~3_(8F9*I^fS92~R-i!El8(Ya@O&Ss8KxaZx zXxcu%n#w{wbjCNmLEIqSrOKJ z60jkqpbnBJxiajHr=gwOQy^8;GTK>a{A`9R~|irtUuLGj7pjXky5whXhlZ3O7=osdWU6c(_*!p z#OuTJW2~D?%PUUD37sPR#>Yp%D1`<8HYp2H+c<&8UTAqVyVS?OYkaot^Et`KE2+oP zA8|Zq$pF6jU5bgd3eOrqM$``?mu{rq4z?08n2)?(qZts;DbXjRY*5lEe4$6cVCB&F zl#6tgV%lg`=t6ZOjdtnm%+(mBA^aPONaBK;vktB-c~a$j)rdsrd-p@+W0nmm_1>y~ zeM30zBv*TWertvBxMh#1yIk||;kT$Xb5Ga2lKfE@*Q^$jYI^wtX<@$6p!L?FZ#a}H zaeA!**Njtv!B0ItJCQv-pv64!*{GyZ&;=8q&I|xcZzS4j@QhEq>zZ~wTz~j5RhPqY zF2RS~V&0>*O8rFBUEYntK#Uke5F`&2?IfeyR*KYbHmT|*fl=F>Buxb}JjI#(s*$@~ z5QGrD4N_<%R4E~h`ZJ@up(!~?= zOJaN>5QZHjJq=4k>@6f-gHC#G&xD4?qmH*?V*)*bZ`FarMDIrL-SUk{JniylLVG?P zLchJM`MsSTwq)nd5^q3I)pP1Y)A7 zw;h0!yqd5ik$En5ct*Sn#CS6PpWZu=?{iTD2aqXL|{q>Qw;2d z0vzTn)BjT>3_G?~NOrZpQ8n;G^5DBf(G6k3yIxk4kMCN!k__4%#ztsRdMCclN&bdU zZpT)B=o~K63n$Ce7qUt=prBiA70(RtKAQqYQvH*i`?GY4L$XUY**MZtR!bpw?dDaW z{67v=sevyO)xe8*P5}d|W%rRr}AM$s}D8csB@+ls979HBt4y{@pVc4rL%_dnB#%GgGrO5LaNDGC4Go zc6kt=QIBw^A&FknGaOV&&NX~6_AlSAyVn|M_S*o?c-gA91%m4Q_4x=@c*%n{+b7x^ z+j4I0?8{Aw0}Hy!4$OB&s}FBX^9k=KtJZ$MJNvXkJaSVVlzn+N`6cD4qw(d~i|OQO z^#QRFcV!e@timF5H-@(S9eIEDoMDlTnHL0JT4|Z`I3cEU9`o43%c}PWhQ7- z4>5f%q(q7ctZ33cQt$J{!JrZvV~ojNGh-eT7S|qV!vP1Xvm=OBA_gKU4#f=bX1;PE zD`M!n$?2BrpBhKg-ao~WyP7`9?2YSPcwYFWL9+85?H}Db1^%;Zk@u%+MQockbsK&z zXH%Mw(-oUPHy`194(!CDB z_L1?s{HC%4Ga`mpgX&l0=VmPj+0LN$sE5MDBAt_r<{XoyTi?*Xx;e{)C{FJ%iRGrX z50JLiIH5rfTXSsoaY0IyUME@9#+fCQpH%i=fW$L78mu#8&9XMlYtbQgCC z4&8-5ZHTuyszdXL>k{vUu!_25cR)VvwWXBZPEF=ftuT2BQq*cf!bL!_&WeF)UxE(p zY>fCK(f1>QJmtHR{_Wqg$17~h%pW)LRhLg+iYNdmIdW^(6iMNvwdYvhLMq-`_HOCP8lI-E-3IF%$?{925l|Ik0<=eoJ7PMBYHO zyZ|53LPL;A2iwEAdg>EN7;+P*`%+4ktf|yWK@DFg&z`X&Bnqs5=p9kY8NN zW3Q9ZxVfWey3m+8mE^Im|8O9`uiGT#$~*oi`=*M=(g^m}f!RooP0-1_{^vVSQLh)( z^}FSWFUUWgMuNndrS;5KI>ei5U0cCO*breY$5WjBEDr1iPeN8f(m7hwUKhUtV)y0L zSv8;^QN$-~_iM?-Cz1^(1tE7)B_?lBld9DBeY9HWsSJb;)cg3D6@u&&z&g6*8ZqhR zHU(VQe`@+`qwO{FScobl+p|X?<&QVd$`V^~3du zegzAUnv|sCt%t0O&&mD-X_SC?Hm7Ia3rv9=HN+eX?vTYDo40eyGDXRT_HR1v3rqkA zajb@47HixK<(Cp*KlWq!UYWT8EY4!9UN-YKsQu2?^l`^7BG89y)_ut8)sds@beUS9 z9@f>JTO+6VGxV}_@Y{V1(0>)hQaZB89EdBqgSw z*`DPto5};Z6=Z4WXcHI~DjBM^u|uyAfXp8D)$mL#Q4WWc-xl5N*yda8Ab-5@E>f$m zMV)3JI zQn8Snk3BYP9)wdgSYs`mu#E7b@etzH=zGrseE4SkInHVr1R zf`E7j4Mqd&NNU~YTmAM>Oy&A8J8?c0vy|FcndU0736iNMGeO^Y31_9HNsj77s>uNc zPSX+){ez`MrKoR`e^G)$U%i`qRP1ha8jr(5VPYDW_q#X0s--gh`bJ%uxc^EwH?60= z`!py1wtfU_D1w2=nVP`Zrc@JlzWfYh>F?6-uX>(Tw{OhSVheA2uK~N1Vi#*qmH&R^ zOpjkVgRDl$P59Aht2WW)+&nARU#+@alz?ud>}d&QmV$r^Mz9u+A5_7H>>+O1Z-c-| z=j2=p#*Weg8R4aBY(mDJ-nmVmRv!8|=K=EW>etUL6eNPD@KZ*G=nq89<$3T$`}$6G zN^{lPQzs3fWW|IXzZ0j47zy6>4bE$1U%dWFwQ0bF`_GZ_+^aY%jpViH1@)lW3s?Hy z#4)(O{z%G{zqzj%e}&Lo-OpT{*7mbs8+UH=_b`B9P|)En%-;yhD<~*D%-qs`j1e6K z;)^>*f+NG@j`b%}X|xs?LB@Qq0p_`yNSvF?1OGN<2Yg!PiIpC$7cCdO-&`@9m@RE)^=UVtvlTxE!OpKC3^rHR zs0i0lcyrf6KR^BQ^o`RIN~r^74AxW{?iw z3FrDIXNd-*@qsGF=O%~m&5BUBc!x$AO(>a5Yb z+V+isz^=kz{30|erz5iIuIdm8u>zmANv++wNnZ)d3i`Swiu0wLy1lgIF+N89cU{U1 zdvWa?L`J~BOhD(UuBwYs=}aZ(Q=+K2|CK8pEMg?)y3gEN~;_91&x3s(OxO0 z9^tHaKf++@-SR5&$j@7xZG~D2vEP9!JOH6!Iq_ z*o$uGvxo5A-l0Te+u3IJ8C5nx{vlKKspqmYF>RK_F3v$z;)WR;X2{E&q%2`~levI; zIkCA#ZUGvZ3Fm?#>EG%YzG!#roN-tImLA_0z7XiRBWv-`b(91#da$)|_4-@c-j^i`q+-c34od)Fy11I#dv#^|^0@&M5Fu-R!%fxI z>w)FN>zt*D7t@m%aF$OlgbOC}d7Am$C+xwvHz*isE3&WHObYTPyS|fDdy7+y1REy5 zy5GXm^U>mGJs{hxwH_QFpPWMfy7?;TLmywUY*0GwhOxR#yMCSO7@z4Dv2DqxxdA@y zX89&W-GM~ADB!XFLM#4IMHN7_L}?SQ`_DOuVL^c zFh1$Wr)&vgEv9Y>qKJt1cVE|K-s<7cmL+$ga*Ox)*&EVa^R(FSJGL?ZWEqD8W&8#2MkG9WgwOWk^8gx)vX#YYgLSGhJ1IZPJLonPhueTP471U|lSG+pEkn&m$ z;Slp+Rw%W>;vXW0(6OoW5KRJxhByfw@!5;a7>AKUr@aPANYln{!X^|`mjDf&UN|dR z9m`7`9v$YX)yLT8Du?Br=U@&JPTvKApjb0Mp&l;;OC%5pv3yMH>1tpS9`b=A_ptoY z<75mz>1Ky+miqvW+$AN9#(?4GW*_sMPoY6W^it@Pp#3jlp2mHQ3$71mbNslP4$Xtw zqb?u%hPQQ(ZpV0B(`wyI5?kV@j6VpJPth#q*wtBA9f>O+_ejHb$5`pGr^>(h>b=o0 z#%mOH_iQbUpLsni@KAM$^Zo2DzxE;v_g27SYd2VdIi%ecF}<|Rs++kxA(A{j4%~SU zag=Y2Iqn)Oes}&E*#QLTVq)LpAIrr+NZ@Sk{^NNiF^PJPqj4p}M3gL(?GgyC9IX-~ z${AvY(mq+iiXRjX2KbOCm$bC~^J*SQs~%}&Hr4KMty@76KjC$OG|Wh{Ln7iEIYB1k z>tqhGA{iOJ1RLl-sl1<-E8k}&@h6@5(MVEJXC^u}<*8CJ9fDlhfK88fV?M4@2^w$1 zJ~tKC5|K9^LYfb=vd4zGUgM~B82KTpHP8OZmSxg%cG~9+|I}qW@ky8Dz|Eo$qaet5 zF`X*4e&=sKg&J6%a)yNAlG$>}x%l#XK68ktqB*>je0c>85`B>y#7pfqdBUTY zXEWE)Q;bFnUf+vus9E)Osjv)6&O~r_*x+SChvKBJWj4{(;#$PhU zxAV3F8h5vw@*h1@`-|!CQXisFksV>LoAFQLlB@KBg}J7`;wQ!X-It z4fdJfbEpTV-rsDN*9^WwW_4llXzEn)KO(RXO|o*5Bz?-eT4=5v6TVP4U{l9_ThuPX zcdCfB(z?IOSv;5-&4e&#gj1Uq#ec zl(l~^4u3nGMjV%T-wTQTp;@NLs6^g2fFFx9dk9hSInNl^i}e*#Z1ViJRdlduElf4% z>LK${tbWCIPI>96e`AZ2B;buI8&9m(Fhzo{KyazTrB^)!TTubGVPE1n@bC}YV`C=F z8pnA}4w3aDWl3+uA<^+QQUikP8g>HIg7vBv(}?y>$X!0ZBhwfW!iNsX3#&k0jB?<= z$HSLkCq?Y`GJ*nzh@%+KE9+a;)F}mzGOOai2(Ex?>R={mw3+$IfTJDeF@oa{z?<@4t4 zo{{ROzY(9H@xG*)RJKU7CcBO;@H^3ZXGUfH>}A+%{TJRP#N(F0VP~RZ$_!yOzdX)M zopM2LJnBJ0IU|yHjy-WdoyrV+~^2nLNbh z;}PuPt}^nJfLqcgcXjXMog~A=|DAK}e?)9C@ObdimpHtxC#-o~sp^UwQzCRCIdPYQ8DTbRO7!LT;cdcYN8*+bdpnKIO zL%Y`k+WuaEDDOU+`ezTa6!tirH)0-m5ekcHr9f3oo9%c0KG%(3bxv>}8vhjyH)JhOHupZHiULt_sI(eB0%7ZBQcQc;+i=S-1rknVGkd3vC_zQ-&6o%R@c{wdn z5vIm;PccJxw-I#9LOy{wwO7x=l{<~#qsbANCr_XG)$g|&TG3e$B2^ZA>@Z_UO|X|xoKy3cp@-DP`vM%{T%sqE zFD39#{FeWBjCIBt5fhkXFL43rxW5HuF(Z>b7(|Y!8_%2@m{(^ zeJNNg=caDN98s`mE3h6qng6k|{0V#tupqDaFC11vV z*X zfio!@E%BaC=HVhOzt(M*SwqLf+mp?kbTGUIGEl=_|8jrk_b+qXF7o*_LN}C1Ewl1v zodr>`;n)!K;fNz0u%K+wG`FT)Nc;n_{ni|J z7=M{$rZ4}Y>xo`bGB{nOdxr6rh1#Iy-V{7&cJ2V-Yw%(?!G3WCc}PD_k#QPobbW%4 zT1#>y%LXztIx@Z@ZJh}yb8I+aH#jhbv_(1^51fU5mAxiA0JaEt>j~|1YnJ71w>0Sv zr#emtEC0d}@E=cx`|4X0)*xJRDKD-VAmv-Xrhe@bdL4$$N@%QRTL_5bN3rdYJ%^R~XQ}{<4xQK%MTI^RR z$`c>ATkuP7hxJ*Gn=kiG-ODNBLqf7oc?zG@hxxZf`(fAP*Z3c-b}|Psb;}0TI#dte zy{BSXP+To{l{oyfjuk?Og3tNED()EYb)kGMM;Jhjz=J5am7Bb|uU;v)+(35qzh`Kl zZ-4ArBUc%lkXqEM$XoOEydTD|_(J&8q4c(@>(qw14p?N|0GrP^){`Ixk)U*N>xe4^Nf=P8-|PsCSP%0zC%%IT1CM}eVGWjKo{^E zw-hx`NwHCTlTvOX|M^9>Sv;Wk!V}Sx>yhN<1^Iw#tCSL_DxQ6c7e%ueWiK&y?$6)7 z>beEwK>u%!D)YsuN^RvNi=QYbRtj08>dQ7jNFh7`UbqVp(4A?p?fF_MjhY+dcDg!s zpa0yZF!6zTqY1FEld!^Gf4U56HIeGA$Pcr0&RMLq&fm(7t>gZWEpH8rzl5Q9q;D;P z$h5>o`ANdxWTf*wc(kCA`?5;e`l=@b_mN;%M_m6g=B;Ai;tm(Q&*!k-V=KY|ErM@9 z#1b&HKPA5f#^C(T(yt``xJAx*r^s~*xQ;J1%=g;_J<}S6+6CuOQEfW9vwUZIAR$&?&Ye3>G6IA;*4<-mh1eEL99rt#auKt~buDwGACWU}T zCDE;U&>_VgeZONdL2S4%e*)MLS}4Gp(>GrT2Gbe#63q7@FhCdMDvSl=-^Nk6;c6_Rzcg0I|JbK{wp;$B5nk@=I zFGDrIv>eWM;IPBlE&5*9$86+(1cRRd1dY8OqH!mK94I;wR5_XIhB4fV$C2_Ag9Y2NG^AVyRKbN@9!;B_D*wxDzT&+dGC zx0-MWh!=p+7e#R@<`HmY9oaF^XocvtsQV{i6XW0}RveP*lJG#{El! z^zm9{_kT?wNtUd<#s57kg5_<3<<*n=1Yq@(C$Sw=g}@(xyH9|r1-|_EE6{@{z-WOF z+ULLr@YWNcLEzi}50Cvv;J?=XBk&*5e+2#w`+o%fBl`dGvH#z?`~N=pfBg7=bXWPg ziYw+#Ayb6^{aXB@w2zS1Z6Uf(8ggG-FPVE-b3#x=D`Q+C+O?#_)u*<6Yr?fH-J(%v z44SXz&X(bHH*VxAdfwF9tvB0onWG|Xm2IM@cy<9@-rxtaFJM{d=}pUmB1QF9PdQ+@ z4afC7^OIGS$bGhUn}ej6PesS(W;zrOb+!m-=vFgY@dsaRv;B@%-O3LCcIN4p!o4kA zSl}W^;;pPC;aZE<%SR+^_~bI;5HwqH5QkNT%YS1C5&RzJg$Rn9EgI`+B>&OECh6{7 z#3kL?C-8@tFu~vTI8`(yrLhd}7&?#VNk?aDfLf!1bl7NJjE(|M4A1WVj!jISb4hdp zH$0%(-{m_6q1kpfhRTg)&B4aw3$B0FJ4>3gaRifM$bY&hU~r7=;L)v0&=0o7dznO) zpig93w1z;nXWqV{T|`<7Sh=0L`-BaT>;h#6hT@%GG9>BodS$t8Iakmd@^7xJ)j>qR z`EcSNYr8VLy1B0I@@gH9)Q~QLg)4W_1X5Pffn>9i&<2D+O4#eY^pU#&I%S&+SLcAx znCM*#PX>FcH%g3Kwz$-nij!aQK;JM#>J_>aH{ahKh8?E3{$I6QX;ji#6vxQSOc5=! zMaeB~5fhN8G#!_WQ6x2NF&xyi?1vWWHLpzXwLiFoHJkM)0{J3@4Nqd?!E8c-@X6$?(4q+S~2#;a}JDMNJp{Ia|biy z9Nlm_$%eM!I2(O@u}WD^P<%fM(y ztsxX_vG?VV)6?$|c}k!t(@h@@w5ppkmn%Q~N;C-UQ*^`wK)5RE_h?7zrT^mJ%A4 zXFK5i$P>uya@ayn2h22h!GhAZh=3j#tmqGE>QMNh?=1mDzb<`RVOO9QL)Xdx}oBf*rp7ry!1?|xQmZ-7B?Y3tQ$JSUMxTnGXtf)5o< zt*oHl><$M1sx;eS>ln0EgedotAdT{>Z$1%m9Lgt4@P@-gQY?(a15Dgo5VuT`_V{CC z-j=$h>8zif6)Tp9G|doh)Y!Po*(wt)BqA$nbVk&+u>&1uIq7BPI>??$`$c8)g^SLu z)j?VfXUSvN{_ZqABa7U%_VwvhYHQmVMidgGE+J;eHzU=xa=X!um_Ea_FOdq@S4{c( zku^s@86vA0P4LbSg9sOJW7b+YmFJ#(k$WCZX832k&z7y0k0*G}e&llO6z`VDYC=|0 z#JTZ1DVK=zG6sLmDR@y-Y&*QSKjYa}kNouXx~~^|anbY(<^yhzHos!>Oq82t)2oeY zF+p#}vk)t>j`X_?j|tQbLpDftr;C8Ym)05Cw0F>4`Mb;C@|;x@bkD)I#1PWrBj)Q% ziO24FQ;19O^DdnJ8UtgQ*#jTT;o>s^PMFL$Dwe+P>8AogW`lX6-_SMz-g?rdnx}Tc zWC^x&`bzjO&80I1_XmbutbIM}C&+>?pD!TOS0h-@)z-(myK*;a>)p0Zj`wTf_DsGy zak#io&s+;d!MZipJZ$q%D6JnwPFoB`%+DrkErEF*n@p&(`gI@ZgJ482KTn}M?c877 C#MzPn literal 0 HcmV?d00001 diff --git a/assets/IITC.svg b/assets/IITC.svg new file mode 100755 index 00000000..ca2653f8 --- /dev/null +++ b/assets/IITC.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +